Reference

Protocol

The sovereign-protocol wire types: small schemas, fail-closed parsing, canonical bytes. Consumers must not invent fields.

The constants

Every stone that touches the wire agrees on these values first. If two sides disagree here, nothing else on this page matters.

Constant
Value
COMMS_CONTRACT_VERSION
irin.comms.v0.1
CloudEvents specversion
1.0
datacontenttype
application/json
ENVELOPE_SCHEMA_VERSION
1
kinds
Escalation | Directive
CE type ids
irin.escalation.v0.1 | irin.directive.v0.1

The envelope family

Everything on the wire wears an envelope. Parse the wrapper first, then the CloudEvents spine, then the payload. In that order, always.

Type
Shape and rules
EnvelopeWrapper
{"v":1,"envelope":...}. Parse the wrapper first: the outer v is the envelope schema version, the inner value is the actual envelope.
CommsEnvelope / CommsData
The CloudEvents 1.0 spine: id (random 32-hex), source (urn:irin:sentinel:{name}), type, time (RFC3339 with Z), datacontenttype, and data carrying {contract, kind, tenant, ttl_seconds, budget_hint, reply_to, payload}. The builder requires sentinel_name, tenant, ttl_seconds, budget_hint, and reply_to. Deserialization fails closed on a bad specversion, datacontenttype, or type.
SentinelState
{tenant, sentinel, observed_at, payload}, where observed_at is a unix epoch in milliseconds and payload is arbitrary JSON.

Escalation and Directive

Two kinds ride the envelope. One asks for judgment, one carries an order. Neither may pretend to be the other.

Kind
Shape and rules
Escalation
{state, reason, urgency} with urgency in low | medium | high. Identity-altitude escalations must set payload.escalation_target = "sovereign_only". Facts, not opinions.
Directive
{job, scope, stop_condition, return_expectation}. No persistence, no looping, no scheduling. Identity and recall writes route through Librarian approval.

Why the fences care about words

An Escalation reports what a watcher saw. A Directive says what an actor may do. The moment a watcher starts issuing orders, or an actor starts narrating reality, the separation of powers collapses. The wire types make that confusion structurally awkward.

JCS canonical JSON

The Gateway signs JCS bytes (RFC 8785), not pretty JSON. Two documents that read the same must serialize to the same bytes, or the signature means nothing.

Rule
Behavior
Fail-closed errors
Serde, NonFinite, DuplicateKeys. NaN, Infinity, and duplicate keys never sign.
Key sort
UTF-16 code-unit order.
Floats
ES6 / ryu shortest-round-trip formatting, with exponential cutover at n > 21 and n <= -6.
Unicode
No Unicode normalization. The bytes in are the bytes out.
Verification
The canonical bytes are the exact Ed25519 preimage. Anyone can verify externally with any conformant RFC 8785 library.

The fence corpora

One corpus, two fences. The council-rs emitter and the gateway receiver test against the same accept/reject cases, so a directive that leaves one stone is exactly what the next stone accepts.

Fence fact
Detail
directive_fence_cases.json
Embedded at compile time. One accept/reject corpus shared by the council-rs emitter fence and the gateway receiver fence. The build fails on a corrupt or empty corpus.
ALLOWED_ACTIONS
The verbs read, report, notify, review, escalate. The fence rejects delete, write, *, and whitespace-padded variants.
Closed keysets
Top-level and scope keysets are closed. Unknown keys do not pass.
Act scope pin
Act pins scope.tenant.
Proposal schema
irin.directive.proposal.v1, with authority recommend and verdicts Act / Dismiss.

Provenance and validation types

Provenance records where an answer came from. It is a receipt, not a halo: captured correlation, never attestation.

Type
What it carries
GatewayProvenance
routed_model, provider, fallback, request-id. Header-captured correlation, not attestation.
WorkerProvenanceGuard
Pairs with WorkerProvenanceStatus: opaque_handle_only | verified_exact | unavailable. An explicit fabrication guard.
ProviderProvenance
Constructors: api, api_web, cli_readonly, cli_tools, gateway.
ProviderResponse
text, model, tokens, latency, cost, and gateway attempts.
SeatResponse
The per-seat response type in deliberation.
ProblemDetails
RFC 9457 problem payloads for errors.

Reserved, and honestly unfinished

CapabilityToken exists as a reserved type. The v0.1 fences reject it. The full story lives on the Librarian page.

Deliberate v0.1 gaps

  • Transport binding, payload schemas, and Worker return shape are not specified yet.
  • Librarian commit policy, Sentinel registry mechanics, and failure/retry semantics are not specified yet.
  • The contract is frozen: additive payload fields need no version bump.
  • Tooling: check_protocol_version_drift.py pins consumers to the package version; verify_provenance_harness.py is a stub.