Facility Service — Event Schemas
Status: populated Owner: TBD Last updated: 2026-04-17 Companion: 04 Event-Driven Architecture · NAMING
1. Subject Naming
All events are published on NATS JetStream stream FACILITY with subjects facility.{aggregate}.{event}.v{N}.
| Attribute | Value |
|---|---|
| Stream | FACILITY |
| Retention class | config (180d hot; snapshot to cold 2y) |
| Partition key | tenantId + aggregate id |
| Envelope | Platform EventEnvelope (F01) |
2. Produced Events
| Event | Aggregate | Retention | Notes |
|---|---|---|---|
facility.hierarchy_node.created.v1 | HierarchyNode | config | |
facility.hierarchy_node.updated.v1 | HierarchyNode | config | |
facility.hierarchy_node.deactivated.v1 | HierarchyNode | config | |
facility.hierarchy_edge.created.v1 | HierarchyEdge | config | |
facility.hierarchy_edge.removed.v1 | HierarchyEdge | config | |
facility.hierarchy_profile.updated.v1 | HierarchyProfile | config | |
facility.location.created.v1 | Location | config | |
facility.location.updated.v1 | Location | config | |
facility.location.deactivated.v1 | Location | config | |
facility.bed.created.v1 | Bed | operational | |
facility.bed.status_changed.v1 | Bed | operational | Hot path — high volume |
facility.resource.created.v1 | Resource | config | |
facility.resource.updated.v1 | Resource | config | |
facility.provider_membership.assigned.v1 | Membership | config | |
facility.provider_membership.revoked.v1 | Membership | config |
3. Schemas
3.1 facility.hierarchy_node.created.v1
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "schemas://facility/hierarchy_node/created/v1",
"type": "object", "additionalProperties": false,
"required": ["nodeId","tenantId","profileId","type","name","status","createdAt"],
"properties": {
"nodeId": { "type": "string", "pattern": "^hnd_[0-9A-HJKMNP-TV-Z]{26}$" },
"tenantId": { "type": "string", "pattern": "^ten_[0-9A-HJKMNP-TV-Z]{26}$" },
"profileId": { "type": "string", "pattern": "^hpf_[0-9A-HJKMNP-TV-Z]{26}$" },
"type": { "type": "string" },
"name": { "type": "string", "maxLength": 200 },
"code": { "type": "string" },
"parentNodeId": { "type": "string" },
"status": { "enum": ["active","inactive"] },
"createdAt": { "type": "string", "format": "date-time" }
}
}
3.2 facility.hierarchy_edge.created.v1
{ "required": ["edgeId","tenantId","parentNodeId","childNodeId","relationshipType","createdAt"],
"properties": {
"edgeId": { "type": "string", "pattern": "^hed_..." },
"parentNodeId": { "type": "string" },
"childNodeId": { "type": "string" },
"relationshipType": { "enum": ["contains","manages","refers-to"] }
} }
3.3 facility.location.created.v1
{ "required": ["locationId","tenantId","hierarchyNodeId","name","serviceType","timezone","locale","createdAt"],
"properties": {
"locationId": { "type": "string", "pattern": "^loc_..." },
"hierarchyNodeId": { "type": "string" },
"name": { "type": "string" },
"serviceType": { "enum": ["OUTPATIENT","INPATIENT","EMERGENCY","ICU","DIAGNOSTIC"] },
"capacity": { "type": "integer", "minimum": 0 },
"timezone": { "type": "string" },
"locale": { "type": "string" }
} }
3.4 facility.bed.status_changed.v1
{ "required": ["bedId","tenantId","locationId","fromStatus","toStatus","changedAt","changedBy"],
"properties": {
"bedId": { "type": "string", "pattern": "^bed_..." },
"locationId": { "type": "string" },
"fromStatus": { "enum": ["AVAILABLE","RESERVED","OCCUPIED","CLEANING","MAINTENANCE","OUT_OF_SERVICE"] },
"toStatus": { "enum": ["AVAILABLE","RESERVED","OCCUPIED","CLEANING","MAINTENANCE","OUT_OF_SERVICE"] },
"patientId": { "type": "string" },
"changedAt": { "type": "string", "format": "date-time" },
"changedBy": { "type": "string" }
} }
3.5 facility.provider_membership.assigned.v1
{ "required": ["membershipId","tenantId","providerId","nodeId","primary","effectiveFrom"],
"properties": {
"membershipId": { "type": "string", "pattern": "^pnm_..." },
"providerId": { "type": "string" },
"nodeId": { "type": "string" },
"primary": { "type": "boolean" },
"effectiveFrom": { "type": "string", "format": "date" },
"effectiveTo": { "type": "string", "format": "date" }
} }
3.6 Example envelope
{
"eventId": "01HN2K...", "eventType": "facility.bed.status_changed.v1",
"eventVersion": 1, "occurredAt": "2026-04-17T09:20:00Z",
"tenantId": "ten_01H...", "traceId": "c2f5...",
"payload": { "bedId": "bed_01H...", "fromStatus":"OCCUPIED", "toStatus":"CLEANING", "changedBy":"usr_01H...", "changedAt":"2026-04-17T09:20:00Z" }
}
4. Consumed Events
| Event | Producer | Handler |
|---|---|---|
tenant.tenant.created.v1 | tenant-service | OnTenantCreatedPolicy — seed profile + root node |
tenant.tenant.archived.v1 | tenant-service | Deactivate nodes under tenant |
provider_directory.practitioner.created.v1 | provider-directory-service | Allow subsequent membership writes |
gdpr.subject_request.received.v1 | platform | Participate — no PII stored, ack-only |
5. Outbox / Inbox
| Concern | Implementation |
|---|---|
| Publication | Transactional outbox table facility.outbox; relay to NATS |
| Consumption | facility.inbox keyed on eventId; idempotent handlers |
| Publication SLO | < 2s p95 from commit → NATS ack |
6. Versioning
- Additive changes → same major version, incremented minor in docs only.
- Breaking changes → new subject version (
v2); dual-publish 30d window.