Skip to content
Enterprise capability — not included in Chronacta.

NATS → Chronacta ingress

Commercial-only component. chronacta-ingress is not included in the free chronacta-server artifact and requires an entitlement with nats_ingress_enabled: true.

Use separate subjects:

  • agents.events.persist — events selected for Chronacta; chronacta-ingress is the only production consumer.
  • agents.events.telemetry — ping/heartbeat and operational messages; handled by a separate NATS-only consumer.
  • chronacta.events — optional downstream subject, published after Chronacta append.

Developer credentials must be denied subscribe access to agents.events.persist and allowed only on chronacta.events.>.

{
"version": 1,
"message_id": "01J...",
"agent_id": "agent-42",
"event_type": "ProcessStarted",
"stream_id": "agent-42",
"data": {"pid": 123},
"metadata": {"hostname": "pc-42"}
}

The ingress allowlist is default-deny. Only configured event types on the configured persist subject are stored. Do not put ping/heartbeat on the persist subject: skipped messages are sent to the configured DLQ, while telemetry remains available to its own consumer.

For selected messages: fetch → validate → append with idempotency key nats:<message_id> → optional downstream publish → ACK NATS. If Chronacta is unavailable, the source message is not acknowledged. Delivery is at-least-once; consumers must deduplicate by message_id/event_id.

Invalid or non-allowlisted messages require dlq_subject; otherwise they are NAKed and retried. This prevents a developer consumer from taking messages before persistence and prevents silent loss.

The raw subject must have one ingress consumer. Do not rely on consumer creation order: independent consumers each receive a copy. Enforce the boundary with subject separation and NATS account permissions.

# conceptual NATS permissions
user ingress {
subscribe = ["agents.events.persist"]
publish = ["agents.events.persist.dlq", "chronacta.events"]
}
user developer {
subscribe = ["chronacta.events.>"]
# no subscribe permission for agents.events.persist
}

The telemetry consumer uses agents.events.telemetry and is independent of ingress. If an existing developer consumer uses a wildcard, stop it or change its ACL/filter before switching agents to the persist subject.

Terminal window
# commercial entitlement file
cat > entitlements.json <<'JSON'
{"entitlements":{"nats_ingress_enabled":true}}
JSON
CHRONACTA_INGRESS_NATS_URL=nats://127.0.0.1:4222 \
CHRONACTA_ENTITLEMENTS_CONFIG=./entitlements.json \
./bin/chronacta-ingress -stream AGENTS -consumer chronacta-ingress \
-filter-subject agents.events.persist

Build separately with make ingress; it is intentionally excluded from make build for the Community artifact.

Set CHRONACTA_INGRESS_METRICS_ADDR=:9091 or pass -metrics-addr :9091. The process exposes /health, /status, and Prometheus-compatible counters at /metrics.

A deployment must grant the ingress NATS user consume/ack access to agents.events.persist and publish access to the DLQ/downstream subjects. Developer users must have no subscribe permission for the raw persist subject.

Roll out in this order: create subjects and ACLs; create and validate the ingress durable consumer; start the licensed gateway; publish a test ProcessStarted; verify the Chronacta stream and /metrics; then enable developer consumers on chronacta.events.>.

For rollback, stop publishers to the persist subject or route them to the previous adapter. Do not grant developers raw-subject access as a shortcut. Messages remain in JetStream when Chronacta is unavailable; resume the gateway to catch up. Use the DLQ/replay procedure for rejected messages.

Before production sizing, run a soak test with 10,000 simulated agents and record target events/sec, message size, reconnect burst, backlog recovery time, NATS lag, Chronacta append latency, WAL/disk throughput, memory, and downstream duplicate rate. This repository does not claim that this profile has been executed.