Reference
Events
Events are written through a transactional outbox in the same commit as the clinical change they describe. One event contract is active today, and it is relayed locally — never transmitted.
#The outbox pattern
An event row is inserted inside the same transaction as the aggregate it describes, so the event and the fact can never disagree. The stored payload is byte-authoritative: the exact serialized bytes are persisted alongside a content hash and a structured copy, and the relay validates all three before acting.
A background relay claims rows with row-level skip-locking under a short lease, so concurrent workers cannot double-process a row. Rows that fail structural validation, or that exhaust their attempt budget, are quarantined terminally rather than retried forever. Outbox deletion is rejected at the database level.
#Active event contract
Emitted when a synthetic draft is committed. It is the only event type the relay accepts; anything else is quarantined by design rather than published.
{
"eventId": "evt_...",
"eventType": "prescription.draft-created.v1",
"occurredAt": "2026-08-04T12:00:00.000000Z",
"tenantId": "tnt_...",
"environment": "SANDBOX",
"aggregateId": "rx_...",
"aggregateVersion": 0,
"correlationId": "..."
}
The schema is JSON Schema Draft 2020-12, source-controlled, compiled in CI, and validated against a checked example. A production data-transfer object equality test keeps the emitted shape and the published example aligned.
CI does not yet capture bytes from a running producer and validate them against the checked JSON Schema. The equality test and the runtime envelope verifier are useful but distinct controls. Direct emitted-byte schema validation remains an explicit hardening gate.
#What "published" means here
The relay copies the event into a table in the same database. PUBLISHED means "copied to a local table" — never network submission, delivery, pharmacy acknowledgment, or any external effect. There is no broker, no webhook transport, and no prescription-network adapter. Simulated
#Planned event surface
The outbox is the designed emission seam for customer-facing webhooks. None of the following exists yet — each is Not implemented:
| Planned event | Fires when |
|---|---|
prescription.validation.completed | A validation run finishes, whatever its outcome. |
prescription.ready_for_review | A draft reaches the review state. |
prescription.review.started | A reviewer establishes a bound session. |
prescription.simulation.approved | A simulated approval is recorded. Never a legal signature. |
prescription.simulation.transmission_queued | A simulated transmission is queued through the transport port. |
prescription.simulation.transmission_failed | A simulated transport failure occurs. |
prescription.cancelled · prescription.expired | Lifecycle termination. |
renewal.requested · refill.requested | Simulated inbound clinical transactions. |
#Delivery design once webhooks exist
Planned delivery will carry versioned envelopes, stable event identifiers, tenant and correlation identifiers, causation identifiers, sequence numbers, and payload schema versions, with signed requests, key rotation, exponential retry, dead-letter handling, replay, endpoint disabling, and delivery logs with redacted previews.
Webhook delivery to a customer endpoint will remain categorically distinct from prescription-network delivery. A delivered webhook says the platform emitted an event; it never says a pharmacy received a prescription.