kastoria-eventnotification
An event notification publisher that follows the DICOMProcessed Changelog and
publishes one Notification Event per study version to a queue. It is a
one-shot image with no listening port: one invocation is one Execution,
which becomes a Run by taking the Run Lease, publishes until it has caught up
with the Changelog, and then exits. A deployment starts it on a schedule.
The events it publishes are described in Ingestion Manifest.
Runtime details
| Property | Value |
|---|---|
| Runtime base image | kastoria-core (final stage), itself node:24-alpine |
| Exposed port | none (CLI, runs to completion) |
| Container user | node (non-root) |
| Entrypoint | node --import ./event-notification/src/instrumentation.js ./event-notification/bin/cli.js |
| Health check | none (not a long-running service) |
| Stop signal | SIGTERM (the Run takes no new work, finishes what is in flight and exits normally) |
Exit codes:
0 when the Lease was taken and the Run ended without a failed publish,
including a Run stopped by SIGTERM. Also 0 when another Execution holds the
Lease (the no-op tick).
Non-zero exits occur when:
- A Run stopped on an event it could not publish. That event is held, and the next Run publishes it again.
- A failure happened before the Lease was reached — configuration, storage
initialization, or building the queue writer (for example, a missing or
invalid
queueWritersection). - A bad input argument is provided.
- A second
SIGTERMis received. - Taking the Lease or reading the Changelog failed.
A failure while closing storage or flushing telemetry after the Run does not change the exit code.
node_modules for npm/npx are stripped from the runtime image.
OCI labels
| Label | Value |
|---|---|
org.opencontainers.image.title |
Event Notification |
org.opencontainers.image.description |
Publishes Notification Events for Kastoria Health |
org.opencontainers.image.licenses |
Proprietary |
org.opencontainers.image.url |
https://github.com/merkalis-io/kastoria-health |
org.opencontainers.image.documentation |
https://github.com/merkalis-io/kastoria-health |
io.kastoria.health-endpoint |
(empty — no health endpoint) |
The org.opencontainers.image.version, org.opencontainers.image.revision,
org.opencontainers.image.created, org.opencontainers.image.source,
io.kastoria.base-image, and io.kastoria.service labels are injected at
build time by the CI/CD pipeline.
Pull and verify
Promoted images are published to the Distribution Registry under the customer namespace:
docker pull acrmerkalisdist0c66.azurecr.io/<customer>/kastoria-eventnotification:<release-tag>
notation verify acrmerkalisdist0c66.azurecr.io/<customer>/kastoria-eventnotification:<release-tag>
See the Distribution Registry guide for authentication and trust setup.
Environment variables
| Variable | Secret | Required | Default | Description |
|---|---|---|---|---|
NODE_ENV |
No | No | production |
Environment; startup fails if unset. |
KASTORIA_CONFIG_JSON[1][2] |
Yes | one of these | — | Storage configuration as an inline JSON string. |
KASTORIA_CONFIG_FILE[1][2] |
No | one of these | — | Path to a storage configuration JSON file. |
EVENT_NOTIFICATION_PUBLISH_CONCURRENCY |
No | No | 16 |
How many Notification Events a Run has in flight at once. |
EVENT_NOTIFICATION_VISIBILITY_DELAY_MS |
No | No | 5000 |
How far short of NOW a Changelog read stops. |
EVENT_NOTIFICATION_BATCH_SIZE |
No | No | 100 |
Entries one bounded Changelog read asks for. |
AZURE_CLIENT_ID[3] |
No | No | — | Client id of the user-assigned managed identity used to reach Azure storage. |
OTEL_ENABLED[4] |
No | No | false |
Set to true to enable OpenTelemetry export. |
OTEL_EXPORTER_OTLP_ENDPOINT[4] |
No | No | — | OTLP collector endpoint, e.g. http://otel-gateway:4317. |
OTEL_DEBUG[4] |
No | No | — | Set to true for verbose OTel diagnostic logging. |
The EVENT_NOTIFICATION_* values must be positive integers; any other value
fails at startup.
The CLI subcommand (publish) is passed at run time.
Deploying to an Azure Container Apps Environment
[1] At least one of KASTORIA_CONFIG_JSON / KASTORIA_CONFIG_FILE is required for storage initialization. If both are set the value of KASTORIA_CONFIG_JSON is used. See Configuration for the document's contents.
[2] The configuration must include a queueWriter section naming the queue to publish to. With the
Azure Storage Queue module the writer authenticates with a
managed identity, so the section carries no credential:
"queueWriter": {
"type": "azure-storage-queue",
"configuration": {
"accountName": "<queue storage account name>",
"managedIdentityClientId": "<queue publisher identity client id>",
"queueName": "kastoria-events",
"messageEncoding": "text"
}
}
messageEncoding is text (the JSON as-is) or base64 (the JSON's UTF-8 bytes, Base64-encoded). The
queue is not created unless createQueueIfMissing is true; a missing queue otherwise fails the Run.
The identity needs the Storage Queue Data Message Sender role on the queue's storage account; the queue
module creates one, umi-<base_name>-queue-publisher, and grants it that role.
[3] AZURE_CLIENT_ID selects the storage identity, not the queue publisher. The container reads the
Changelog from storage and publishes to the queue, so it carries two user-assigned identities: the storage
identity (named by AZURE_CLIENT_ID) and the queue publisher (named by managedIdentityClientId in the
queueWriter section). With the compute module, attach them through user_managed_storage_app and
user_managed_queue_app.
[4] If OTEL_ENABLED is not explicitly set to true, OpenTelemetry metric/trace/logging is disabled.
Job configuration
The image is meant to run as a batch job that is setup to be run on a regular schedele. There is no long-running process to keep alive; the deployment is responsible for starting execution on a cadence. The following launch arguments should be passed into the container
["publish"]
To details on setting up the execution cadence and launch arguments in a deployed environment, see the
jobs configuration documentation for the appropriate Terrform/OpenTofu compute module.
Available versions
v0.10.0v0.9.1— deprecated for security reasons (CVE-2026-101916); usev0.10.0