--- id: INT-22 family: RT-INT level: core profiles: [runtime] posture: normative-target added: "1.0" changed: "1.0" source: https://flowdrop.io/spec/rules/rt-int/int-22 specification: FlowDrop Workflow Specification 1.0-draft licence: CC BY 4.0 --- # INT-22 — An interrupt is published as 24 keys, every one always present *RT-INT (Part II) · level: core · profiles: runtime · added in 1.0* One shape, from every endpoint that publishes an interrupt. A consumer reads a key rather than testing whether it is there, because an absent value is present and null. ## The rule > **Normative.** This is the rule. > > 1. Every endpoint that publishes an interrupt publishes the same entry: 24 keys, uniformly camelCase, in this order: `id`, `type`, `status`, `message`, `nodeId`, `workflowId`, `pipelineId`, `sessionId`, `schema`, `options`, `context`, `defaultValue`, `responseData`, `createdAt`, `expiresAt`, `scheduledAt`, `resolvedAt`, `resolvedBy`, `direction`, `jobId`, `targetPipelineId`, `initiatorUid`, `reason`, `linkedInterruptId`. > > 2. `id` is the interrupt's UUID; `type`, `status` and `direction` are the enumerated values (STORE-11); and all four timestamps are ISO-8601 strings or null, never integers. > > 3. Every optional member is present and null rather than omitted. > > 4. An endpoint listing interrupts answers a JSON array, and must still answer an array after access filtering has removed entries. ## What it means Every endpoint that publishes an interrupt publishes the same 24 keys, in the same order, whichever door answered. A consumer that reads this shape once can read it everywhere; a consumer that has to special-case one endpoint's fields is reading a contract that was never actually shared. The clause worth catching is presence, not content: an unset member is published as the key with a `null` value, never left out of the object. A consumer that checks whether a key exists, instead of reading its value, would read an unset member as though the endpoint had a different shape than the one that set it — the two are indistinguishable unless absence is never allowed to mean anything. ## Example ```json title="The interrupt entry's key set, in order" ["id", "type", "status", "message", "nodeId", "workflowId", "pipelineId", "sessionId", "schema", "options", "context", "defaultValue", "responseData", "createdAt", "expiresAt", "scheduledAt", "resolvedAt", "resolvedBy", "direction", "jobId", "targetPipelineId", "initiatorUid", "reason", "linkedInterruptId"] ``` ```json title="One interrupt's unset members" verdict="null" {"schema": null, "options": null, "context": null, "expiresAt": null, "scheduledAt": null, "resolvedAt": null, "resolvedBy": null} ``` Nothing here is omitted; each of these keys sits in its place in the 24-key entry above, carrying `null` rather than being left out. ## Related rules - Names: INT-1, INT-19, PLAY-4, STORE-11 - Referenced by: INT-1, INT-19 --- Rule identifiers are permanent and are never renumbered. This specification carries no implementation status: each implementation publishes its own standing against these rules. Licensed CC BY 4.0.