#FLOW Channel Contract/1
Status: prerelease specification candidate for JSON channels.
A named channel contract lets independently authored participants agree on
message meaning, not merely shape. Two {text: string} messages might mean
append a fragment or replace a snapshot. Equal schemas do not establish equal
protocols. Generic channels need no named contract.
#1. Declarations
FLOW.md and Capability Contract/1 method objects may declare a channels
map. Each key is a LocalName; each value is a closed object:
Direct receivers start at sequence one. A broadcast subscription starts at the
next accepted source sequence; a beginning receiver requires that sequence to
be one. suffix accepts a later start but grants neither subscription authority
nor replay. Declarations describe requirements, not grants. A required port must
be connected before invocation; this does not guarantee its peer will succeed.
Channel names are local slots, not globally discoverable addresses.
References obey Package/1's canonical package-local reference rules. Hosts resolve them within the exact calling/receiving package; no URI is fetched.
#2. Descriptor and identity
A self-contained UTF-8 JSON/1 descriptor has exactly these fields:
The complete descriptor is at most 262,144 UTF-8 bytes. Embedded schemas retain Schema/1 graph, keyword and reference limits. Unknown fields reject. Machine schema validation does not replace byte bounds or the schema-graph checks. Examples and executable behavioral checks can live beside the descriptor.
Derive the digest over the complete descriptor, including semantics:
The result is sha256: plus 64 lowercase hexadecimal digits. Authors supply
the package-local reference, never a handwritten digest. Exact compatibility
compares id, version and digest. Descriptor identity is an agreement, not
proof that an implementation obeys it.
#3. Matching and interpretation
A source becomes named only at creation. A later writer, reader or message cannot silently rename it. For a named source, a transferred writer's port must declare that exact contract. Named readers require the same exact source identity. An unnamed source cannot satisfy a named reader even when schemas match.
Named sources may supply generic or schema-only readers. Two nontrivial item
schemas must have equal canonical content; omitted/true is generic. Hosts
do not infer subtyping or execute semantic prose as a validator. Direct late
binding validates the queued prefix before adding a reader constraint, and
later values satisfy the combined constraints. Broadcast readers instead add
per-subscription constraints: a queued prefix is checked before transfer, and
a later invalid value fails only that subscription. A new writer declaration
must be shape-compatible with live bound subscribers, just as a new reader
must match the admitted writer. This is an admission check, not source-wide
receiver validation; disposed, ended or failed subscribers do not veto a later
writer. Writer/source constraints remain source-wide. Invalid mapping rejects
before any right moves or new participant dispatches.
Forwarding an unused receive endpoint preserves its actual source identity. Reading values and copying them into a new generic source does not. A converter or named relay owns its own output meaning and validation.
Hosts enforce identity, item shapes, granted rights, delivery and start position. Applications enforce correlation, ordering across messages, deltas versus snapshots and domain completeness. Sequence one identifies this source's origin, not complete upstream history. A clean channel end cannot establish a successful Agent result, accepted application outcome or durable processing.
The exchange and lifecycle rules are in Run/1. This contract does not grant network access, session mutation or arbitrary transports. Binary payloads require separately specified support.