ExecutionOutcome — Append-Only Corrections Model
Generated from
specification/state-machines/execution-outcome.md. Edit the canonical source file, not this page.
RFC 2119 normative language applies throughout.
ExecutionOutcomefollows an append-only corrections model. A submitted outcome is never mutated in place. Corrections are expressed as new records that supersede prior ones. This document describes the submission chain, correction types, preconditions, postconditions, and invariants.
1. Nature of the Record
Section titled “1. Nature of the Record”An ExecutionOutcome records whether and how an accepted exchange was executed, without copying participants’ complete operational records. The record is logically associated with one ExecutionReference.
The outcome history forms an ordered chain:
Outcome-1 (initial submission) └─ Outcome-2 (correction, supersedes Outcome-1) └─ Outcome-3 (further correction, supersedes Outcome-2)At any moment, the head of the chain (the record with no supersededByOutcomeId) is the current authoritative outcome.
2. Outcome Status Values
Section titled “2. Outcome Status Values”Although there is no single lifecycle automaton, each ExecutionOutcome record carries a status reflecting the execution reality it reports:
status Value |
Meaning |
|---|---|
planned |
Execution accepted but not yet started. |
inProgress |
Execution underway; partial confirmation available. |
completed |
Execution concluded successfully. |
cancelled |
Execution was called off after ExecutionReference was created. |
disputed |
One or more parties dispute the reported outcome; arbitration pending. |
These values describe the execution event being reported, not the record’s own lifecycle. A completed outcome record can still be superseded by a correction if the reported data was erroneous.
3. Submission Chain Operations
Section titled “3. Submission Chain Operations”3.1 Initial Submission (POST /execution-outcomes)
Section titled “3.1 Initial Submission (POST /execution-outcomes)”Creates the first ExecutionOutcome for a given ExecutionReference.
Preconditions:
- Authorization: Actor belongs to one of the
participatingOrganizationIdsof the linkedExecutionReference. - Scope required:
outcomes:write - Reference state: The linked
ExecutionReferenceMUST be inlinkedorcreatedstate (not yetcompletedorcancelled). - Version check:
executionReferenceIdand its currentresourceVersionMUST be included. - Deduplication key:
deduplicationKey(a stable caller-supplied key) MUST be provided. A duplicate submission with the samededuplicationKeyreturns the original record (200 OK). - Policy check:
status, planned and actual time ranges (where available), and participant confirmations MUST be present. Sensitive fields (exact addresses, customer identity, price) MUST NOT be included.
Postconditions:
- New
ExecutionOutcomerecord created;submittedAtrecorded;resourceVersion= 1;supersedes= null. ExecutionReferencestatus transitions tolinkedif it wascreated, or remainslinked.- If
statusiscompletedorcancelled,ExecutionReferenceMAY transition tocompletedorcancelledrespectively (broker policy determines exact trigger). - Event
pcx.execution-outcome.recorded.v1emitted.
3.2 Correction (POST /execution-outcomes/{id}/corrections)
Section titled “3.2 Correction (POST /execution-outcomes/{id}/corrections)”Creates a new ExecutionOutcome that supersedes the identified prior record.
Preconditions:
- Authorization: Actor belongs to one of the
participatingOrganizationIdsof the linkedExecutionReference. - Scope required:
outcomes:write - Prior record state: The
{id}in the path MUST identify the current head of the correction chain (i.e. the record with nosupersededByOutcomeId). Correcting a non-head record MUST return409 Conflictwithidempotency-conflict. - Version check:
observedOutcomeVersionMUST match theresourceVersionof the record being superseded. A mismatch MUST return409 Conflictwithstale-resource-version. - Correction reason:
correctionReasonMUST be provided.correctionReasonCodeSHOULD be provided from the correction vocabulary. - Deduplication key: A new
deduplicationKeyMUST be supplied for this correction record.
Postconditions:
- New
ExecutionOutcomerecord created;submittedAtrecorded;supersedes={id};resourceVersion= 1 on the new record. - Prior record’s
supersededByOutcomeIdset to the new record’sid(immutable pointer added); prior record is otherwise unchanged. - If
statusof the new record iscompletedorcancelled, appropriateExecutionReferencetransitions may be triggered. - Event
pcx.execution-outcome.corrected.v1emitted, referencing both the old and new record IDs.
4. Correction Chain Fields
Section titled “4. Correction Chain Fields”Per-Record Fields
Section titled “Per-Record Fields”| Field | Type | Required | Description |
|---|---|---|---|
id |
string (UUID) | yes | Stable immutable identifier for this outcome record. |
executionReferenceId |
string | yes | Reference to the parent ExecutionReference. |
status |
enum (see §2) | yes | Execution status being reported. |
submittedAt |
RFC 3339 timestamp | yes | When this record was recorded (server-assigned). |
submittedBy |
actor reference | yes | The actor submitting this record. |
deduplicationKey |
string | yes | Caller-supplied stable key for idempotent submission. |
plannedTimeRange |
time range | no | Planned start and end times. |
actualTimeRange |
time range | no | Actual start and end times; required if status is completed. |
participantConfirmations |
array | no | Per-organization confirmation records. |
externalExecutionRefs |
array | no | External system references (namespaced). |
operationalDeviations |
array | no | Documented deviations or exceptions. |
capacityUtilizationObservations |
object | no | Optional observed utilization data. |
routeObservations |
object | no | Optional route deviation or mileage data. |
schemaVersion |
string | yes | Protocol schema version used for this record. |
supersedes |
string (UUID) | no | ID of the prior record this one corrects; null for initial submissions. |
supersededByOutcomeId |
string (UUID) | no | ID of the next record in the chain; null if this is the head. Set by the server; never provided by the client. |
correctionReason |
string | conditional | Required when supersedes is set. |
correctionReasonCode |
string | conditional | Structured reason code; SHOULD be provided when supersedes is set. |
observedOutcomeVersion |
integer | conditional | Required when supersedes is set; MUST match resourceVersion of superseded record. |
5. Concurrency Rules
Section titled “5. Concurrency Rules”- Concurrent corrections on the same head: Two concurrent
POST /execution-outcomes/{id}/correctionsagainst the same head record MUST be serialized. The first writer creates a new head and setssupersededByOutcomeIdon the old head. The second writer’sobservedOutcomeVersionwill no longer match; it MUST return409 Conflictwithstale-resource-version. The caller MUST re-read the current head and retry if the correction is still needed. - Concurrent initial submissions with the same
deduplicationKey: Only one record is created; subsequent requests with the same key return the original (200 OK). - Concurrent initial submissions with different
deduplicationKeyvalues: Both are accepted; however, a(executionReferenceId, status=completed)record SHOULD be treated as idempotent by the broker — only the firstcompletedoutcome triggersExecutionReferencecompletion. - Dispute and correction racing: A
disputedoutcome may be corrected; the correction supersedes the disputed record and MUST include acorrectionReasonexplaining the resolution.
6. Invariants
Section titled “6. Invariants”- Append-only chain: No
ExecutionOutcomerecord MUST be mutated or deleted after recording. ThesupersededByOutcomeIdpointer MAY be set by the server when a correction arrives, but all other fields are immutable. - Single head invariant: At most one record per
executionReferenceIdMUST havesupersededByOutcomeId= null at any time. Two concurrent corrections to the same head violate this invariant and MUST be prevented by thestale-resource-versioncheck. - Correction chain integrity: The chain formed by
supersedespointers MUST be acyclic and MUST eventually terminate at a record withsupersedes= null (the initial submission). - Deduplication key uniqueness:
deduplicationKeyMUST be unique perexecutionReferenceId. The server MUST reject a new record whosededuplicationKeymatches an existing record unless the request is an exact replay (same payload, returns200 OK). - Schema version recording:
schemaVersionMUST be stored on every record so historical records remain interpretable after protocol version advances. - Data minimisation:
ExecutionOutcomerecords MUST NOT contain customer identity, exact addresses, price, or complete goods details unless policy explicitly permits disclosure. Adapter-specific fields MUST be in theextensionsnamespace. - Audit retention: All records in the correction chain MUST be retained for the period defined in the
retentionPolicyRefof the linkedPartnerRelationship. - Outcome-reference consistency: A
completedExecutionReferenceMUST have a headExecutionOutcomewithstatusofcompletedorcancelled. The broker MUST NOT mark the referencecompletedbased on a superseded outcome record.