ADR-0002: Private exchange and execution handover
Generated from
docs/adr/0002-private-exchange-execution-handover.md. Edit the canonical source file, not this page.
Status: Accepted
Date: 1 September 2026
This ADR expands the first protocol profile from capacity discovery into a complete private exchange between heterogeneous transport management systems. It supplements ADR-0001 and does not turn OpenFreytProtocol into a universal transport model.
D015 — Separate discovery from execution transfer
Section titled “D015 — Separate discovery from execution transfer”Capacity discovery, load discovery and match proposals remain independent from transport tendering and execution handover. A match may lead to a tender, but a match is neither an operational assignment nor a legal commitment.
D016 — Transfer a bounded execution package
Section titled “D016 — Transfer a bounded execution package”The protocol transfers a vendor-neutral execution package containing only the stops, time windows, cargo facts, constraints, references, instructions and disclosure-controlled contact details needed to perform an accepted movement. It does not copy a source system’s internal ride, order, shipment, route or planning object.
The source and executing systems retain their own local records. The exchange links those records through the protocol resource identifier and namespaced external references.
D017 — Distinguish agreement from technical handover
Section titled “D017 — Distinguish agreement from technical handover”Commercial acceptance and technical import acknowledgement are separate state transitions. An accepted tender creates an immutable commitment; it is not operationally handed over until the executing system acknowledges that it created or linked the corresponding local record.
D018 — Trust is organizational, technical and bilateral
Section titled “D018 — Trust is organizational, technical and bilateral”An access token alone is not sufficient trust. The private exchange requires:
- a verified organization identity;
- a registered connector or interactive client bound to that organization;
- an active bilateral partner relationship;
- granted API scopes and relationship policy;
- resource-specific visibility and disclosure policy;
- actor authorization for the requested lifecycle transition.
Machine clients use the protocol security profile. Interactive users authenticate through OpenID Connect. Internal TMS session tokens are not portable exchange credentials.
D019 — The exchange is a coordination control plane
Section titled “D019 — The exchange is a coordination control plane”The exchange is authoritative for partner relationships, exchanged resources, decisions, commitments, handover state and the shared audit journal. Connected systems remain authoritative for their local commercial, planning and execution records.
Connectors translate between local models and canonical protocol resources, preserve references, process messages idempotently, quarantine unsafe mappings and reconcile after missed delivery or downtime.
D020 — Profiles keep the canonical contract bounded
Section titled “D020 — Profiles keep the canonical contract bounded”The protocol is organized into composable profiles:
- core identity, relationship, concurrency and error behavior;
- discovery for capacity, demand and matching;
- tendering and immutable commitment;
- execution handover, amendment, cancellation and operational updates;
- security and connector conformance.
An implementation advertises the versions and optional capabilities it supports. Unsupported optional capabilities must fail explicitly rather than being silently ignored.
Amendments (M008)
Section titled “Amendments (M008)”The following decisions were made and shipped during M008 (S01-S05) implementation of the tender/commitment/handover protocol profile. They amend and concretize D015-D020 above.
D021 — Tender revisions form a single linear chain
Section titled “D021 — Tender revisions form a single linear chain”A counterproposal never mutates the current TransportTender’s terms in place. It moves the current tender to countered and the command layer creates a brand-new TransportTender row with revisionOf pointing at the prior revision; the prior revision is marked isImmutableRevision: true. There is no branching revision tree — each tender has at most one direct successor. Confirmed in conformance/src/reference-model/lifecycle/transport-tender.ts (counterpropose event handler) and specification/schemas/transport-tender.schema.json (revisionOf, isImmutableRevision fields).
D022 — Disclosure is phase-gated by resource state, not a separate named role/tier field
Section titled “D022 — Disclosure is phase-gated by resource state, not a separate named role/tier field”Cargo/stop/time-window detail exposed in a TransportTender is scoped to what the current lifecycle phase (draft/issued/countered/accepted) permits, per schema description text, rather than a distinct PUBLIC/COMMITMENT_PARTY/EXECUTION_PARTY enum. A grep of broker/src and conformance/src as of S05 found no such named-tier enum implemented anywhere in the shipped code; only the field-disclosure conformance suite exercises pre-match field withholding, and that suite belongs to the earlier discovery profile (matches, not tenders). The disclosure-tier vocabulary referenced in earlier .gsd/phases/08-tender-commitment-handover-protocol-clos/08-CONTEXT.md planning notes was not implemented as a named enum; this amendment records the actual shipped behavior rather than the originally planned vocabulary.
D023 — Duplicate handover delivery converges via unique-key upsert
Section titled “D023 — Duplicate handover delivery converges via unique-key upsert”HandoverAcknowledgement writes are keyed on (handoverId, acknowledgedByOrganizationId). Repeated acknowledgement submissions for the same handover from the same organization resolve to the existing local record (HTTP 200, existing id) rather than creating a duplicate row. Implemented in broker/src/http/routes/handoverAcknowledgements.ts (natural-key lookup before dispatch) backed by a UNIQUE(handover_id, acknowledged_by_organization_id) database constraint.
D024 — Commercial acceptance and technical handover acknowledgement remain separate finite-state machines
Section titled “D024 — Commercial acceptance and technical handover acknowledgement remain separate finite-state machines”TransportCommitment (commercial, single-shot formed state, no further legal transitions — see conformance/src/reference-model/lifecycle/transport-commitment.ts) and ExecutionHandover/HandoverAcknowledgement (technical, created -> one of acknowledged-imported/acknowledged-linked/acknowledged-rejected/acknowledged-quarantined — see conformance/src/reference-model/lifecycle/execution-handover.ts) are modeled as independent reference-model lifecycle files with no shared state. This confirms and concretizes D017.
D025 — A TransportCommitment freezes its originating tender
Section titled “D025 — A TransportCommitment freezes its originating tender”Once a TransportCommitment is formed from an accepted TransportTender, that tender’s decision-relevant fields are immutable and no further revisions may be issued against it. The tender lifecycle’s legal-transition table (conformance/src/reference-model/lifecycle/transport-tender.ts) permits no outgoing events from the accepted status, so an accepted-then-committed tender cannot re-enter counterpropose/withdraw/expire transitions.