Home Contact
Universal Substratev1.4
/
For agents Markdown

43. Exact HTTP, event, query, federation, and SDK contracts

The API exposes three deliberately different resources: portable canonical records, store admission receipts, and policy-bound projections. A client must be able to tell which one it received from media type, path, schema lock, digest headers and response…

Concept & directionLNK

The API exposes three deliberately different resources: portable canonical records, store admission receipts, and policy-bound projections. A client must be able to tell which one it received from media type, path, schema lock, digest headers and response body. The v1.3 contract below supersedes the illustrative combined envelope in Section 14.2 and the v1.2 endpoint sketches wherever they conflict.

Table
Canonical bytes are not an audience view
GET /records/{recordId}/canonical returns the admitted portable bytes only to a principal authorized for that record class and representation. GET /vehicles/{assetId}/profile returns a rebuildable, redacted projection. Their ETags, digests, caching, deletion behavior and authorization are not interchangeable.

#43.1 Endpoint matrix and consistency contract

Method + pathContractConsistency / authority
POST /v1/records:appendadmit one RecordCore plus detached proofsserializable per stream; expected sequence; idempotent scoped key
POST /v1/records:appendBatchatomic one-stream batch; bounded count/bytesall-or-none under one stream head
GET /v1/records/{id}/canonicalexact admitted representation and record digestauthoritative ledger; strong read after receipt checkpoint
GET /v1/records/{id}/receiptadmission placement, policy decision and chain positionauthoritative ledger; tenant-bound
GET /v1/streams/{id}?afterSequence=ordered canonical record/receipt pairsmonotonic stream sequence; signed continuation cursor
POST /v1/telemetry/sessionsdeclare capture locks and obtain upload capabilitypolicy + quota checkpoint; no segment admitted yet
POST /v1/telemetry/segments:reservereserve bounded object upload and expected digestsshort-lived; one manifest identity
POST /v1/telemetry/segments:commitvalidate bytes + admit SegmentManifestidempotent; duplicate/equivocation explicit
POST /v1/actions:proposestore inert typed proposalno external effect
POST /v1/actions/{id}:confirmconsume exact challenge responseone-time; authenticated principal and terms digest
POST /v1/actions/{id}:dispatchpolicy/mandate recheck + connector operationcompare-and-append; may return UNKNOWN_EFFECT
POST /v1/auctions/{id}/bidsadmit confirmed bid intentlinearizable auction stream
POST /v1/auctions/{id}:closecreate close fence and resultserializable single winner/no-sale receipt
GET /v1/vehicles/{id}/profileaudience and as-of bound projectioncheckpoint-bounded, cacheable by projection ETag
POST /v1/queriestyped bounded query ASTsnapshot checkpoint and policy digest returned
POST /v1/exportsasynchronous signed export manifestcheckpoint-pinned, policy filtered and auditable

Strong consistency is required only where an invariant needs it: stream append, authority epoch, bid admission/close, budget reservation and journal posting. Search, feeds, analytics and public profiles are checkpointed projections and may lag; every response exposes that checkpoint and staleness. A client cannot request strong consistency by hiding a stale projection behind an uncached URL.

#43.2 Append request headers and result

Table
Normative append exchange
POST /v1/records:append HTTP/1.1
Content-Type: application/vnd.rtracer.record+json;version=1.3
Accept: application/vnd.rtracer.ingest-receipt+json;version=1.3
Authorization: DPoP <short-lived-token>
DPoP: <proof bound to method, URL, token and key>
RTracer-Tenant: 5abfa9c8-4ec5-4de9-b786-3b3b1b1d8ed4
RTracer-Stream: 606f60af-fb14-42b4-8677-1ea9a35c2d5b
RTracer-Expected-Sequence: 184
RTracer-Writer-Epoch: 12
Idempotency-Key: 01JAZ...client-random...
Content-Digest: sha-256=:...:

Body = exact RecordCore bytes. Detached proofs are supplied as a bounded
multipart part or by digest-addressed ProofRecord references.

201 Created
Location: /v1/records/019b.../receipt
ETag: "receipt-sha256-..."
RTracer-Record-Digest: sha256:...
RTracer-Receipt-Digest: sha256:...
RTracer-Stream-Sequence: 185
RTracer-Logical-Shard: ledger-03
RTracer-Chain-Epoch: 1
RTracer-Commit-Sequence: 93828011

Retry of same scoped key + same requestDigest returns 200 and original receipt.
Same key + different requestDigest returns 409 RTR-IDEMPOTENCY-EQUIVOCATION.
  • Request digest covers operation family, canonical body digest and semantic headers that affect the operation. Transport attempt count, TCP identity, trace ID and retry timing never enter the canonical event or record digest.
  • A 202 response means admitted asynchronous work, never semantic record acceptance unless it contains a committed IngestReceipt. Upload reservation is not telemetry admission.
  • If the connection fails after dispatch, the client queries the scoped idempotency key before retrying. It never changes the key for the same intended effect merely to escape an unknown result.
  • Proof verification failure, schema failure, policy denial and storage failure use different stable codes. Safe responses never echo secrets, private identifiers, raw policy or existence of unauthorized resources.

#43.3 Projection, ETag, cursor, and typed query semantics

Table
Reproducible view and confidential pagination contract
ProjectionDescriptor {
  projectionKind, projectionVersion, audienceClass, requestingPrincipalId?,
  purpose, validAt, knownAt, sourceCheckpointVector,
  policyBundleDigest, registryCheckpoint, codeDigest,
  locale, unitProfile, privacyTransformRefs[], inputRecordDigestSetDigest
}

projectionDigest = SHA256(domain("PROJECTION", version) ||
  canonicalize({descriptor, renderedSemanticObject}))

CursorBindingV1_4 {
  cursorProfile, queryDigest, requestingPrincipalId?, audienceClass,
  purpose, checkpointVector, projectionDescriptorDigest,
  codeDigest, registryCheckpoint, policyBundleDigest,
  sortPosition, expiresAt, keyEpoch
}

The client receives authenticated encryption of CursorBindingV1_4 or a random
server-side handle. Plaintext private sort tuples and tenant IDs are prohibited.
ProjectionDescriptor {
  projectionKind, projectionVersion, audienceClass, requestingPrincipalId?,
  purpose, validAt, knownAt, sourceCheckpointVector,
  policyBundleDigest, registryCheckpoint, codeDigest,
  locale, unitProfile, privacyTransformRefs[], inputRecordDigestSetDigest
}

projectionDigest = SHA256(
  domain("PROJECTION", version) ||
  canonicalize({descriptor, renderedSemanticObject})
)

Projection ETag = quoted projectionDigest.
Canonical-record ETag = quoted recordDigest.
They are never compared as equivalent validators.

CursorPayload {
  queryDigest, tenantId, principalOrAudienceBinding, purpose,
  checkpointVector, sortTuple, pageSize, policyDigest, expiresAt, nonce
}
cursor = base64url(payload) + "." + signature

A cursor is opaque, short-lived, tamper-evident and bound to the exact query,
policy and principal/audience. It is not a free-form database offset.
Table
Bounded typed query surface
Query {
  from: closed resource family,
  where: allOf|anyOf|not|eq|in|range|exists|relationshipPath,
  validAt, knownAt, projectionPurpose,
  select: allowlisted field paths,
  orderBy: stable indexed keys ending in opaque ID,
  page: {first: 1..500, after?: signedCursor},
  consistency: CHECKPOINTED|AT_LEAST_CHECKPOINT,
  minimumCheckpoint?: vector
}

Limits: depth 16; predicates 100; IN values 1,000; relationship depth 5;
wall time 5 s interactive/60 s export; scanned-row/byte budget per tenant.
No arbitrary expression, regex over unindexed private data, user SQL, mutation,
recursive graph query or model-selected query text is accepted.

#43.4 Problem details and stable machine codes

Table
RFC 9457-compatible failure object
HTTP/1.1 409 Conflict
Content-Type: application/problem+json

{
  "type":"urn:rtracer:problem:stream-sequence-conflict",
  "title":"Stream sequence conflict",
  "status":409,
  "code":"RTR-LEDGER-EXPECTED-SEQUENCE",
  "stage":"admission.commit",
  "correlationId":"019b...",
  "retryable":true,
  "safeContext":{"expected":"184","current":"185"}
}

Fields are closed. detail is optional and localized; clients branch on code.
Validation findings carry JSON Pointer, constraint ID and safe rejected-value
class—not the private value. Retryable never overrides idempotency semantics.
Code familyRepresentative codesDefault HTTP / disposition
RTR-WIRENONCANONICAL, DIGEST-MISMATCH, SCHEMA-LOCK, UNKNOWN-MEMBER400/422; reject
RTR-AUTHNTOKEN-BINDING, AUDIENCE, CREDENTIAL-REVOKED, STEP-UP401; deny/challenge
RTR-AUTHZNO-GRANT, EXPLICIT-DENY, STALE-EPOCH, UNSATISFIED-DUTY403; deny
RTR-LEDGEREXPECTED-SEQUENCE, WRITER-EPOCH, IDEMPOTENCY-EQUIVOCATION409; retry/query/quarantine
RTR-TELEMSEGMENT-EQUIVOCATION, CLOCK, DECOMPRESSION-LIMIT, DESCRIPTOR409/422; quarantine/reject
RTR-COMPPORT-INCOMPATIBLE, SOLVER-NONCONVERGENT, EFFECTIVITY-UNKNOWN422; false/unknown/error
RTR-CONTROLAUTHORITY-EPOCH, FRAME, ENVELOPE, HANDOVER-TIMEOUT409/422; reject/fallback
RTR-MARKETAUCTION-CLOSED, TERMS, BID-INELIGIBLE, CLOSE-CONFLICT409/422; reject/reload
RTR-MONEYMANDATE, JOURNAL-UNBALANCED, UNKNOWN-EFFECT, RECONCILIATION409/422/202; hold/operator
RTR-PRIVACYPURPOSE, NONINTERFERENCE, RETENTION-CONFLICT, RIGHTS403/409; deny/freeze

#43.5 CloudEvents transport profile and topic catalog

Table
At-least-once event envelope
CloudEvent attributes:
  specversion = "1.0"
  id          = eventId (UUIDv7; stable across delivery retries)
  source      = urn:rtracer:service:<serviceId>
  type        = io.rtracer.<domain>.<event>.v1
  subject     = opaque canonical subject route; never VIN/MAC/plate/person
  time        = transaction/recorded time, not necessarily validTime
  datacontenttype = application/vnd.rtracer.event+json;version=1.3
  dataschema  = immutable schema URI containing or resolving to digest
  tenantid, shardid, shardposition, streamid, streamsequence,
  recordid?, recorddigest?, receiptdigest?, correlationid, causationid

data = canonical EventData referencing records/receipts by ID and digest.
transportAttempt, broker partition/offset, delivery time, retry count,
consumer lag and trace propagation are delivery metadata outside EventData.
CloudEvents serialization is a transport envelope, not RecordCore identity.
Topic familyPartition keyConsumer obligation
record.admitted.v1tenantId + logicalShardId + chainEpochone event per receipt; preserve commitSequence order; atomically dedupe, mutate projection, and advance checkpoint
record.invalidated.v1tenantId + affected streamIdinvalidate/rebuild descendants by dependency graph
telemetry.segment-admitted.v1tenantId + captureSessionIdhonor manifest locks and gap/correction events
configuration.compiled.v1tenantId + assetIddiscard older config/context result; retain proof receipt
action.state-changed.v1tenantId + actionIdenforce legal sequence; never infer effect from delivery
auction.state-changed.v1tenantId + auctionIdpreserve stream order; result only from close receipt
journal.posted.v1tenantId + economicEventIdexactly-once projection by batch ID; never repost
publication.changed.v1tenantId + publicationIdapply correction/withdrawal lineage and audience policy

The outbox is authoritative for event production. Broker delivery is at least once. Consumers store event ID plus source checkpoint in the same transaction as their materialized state. Poison messages enter a bounded quarantine lane with alerting; skipping without a recorded gap decision is forbidden.

#43.6 SDK behavioral contract

SDK layerRequired behaviorForbidden convenience
wirestrict builders; exact integers/decimals; canonicalize; digest; local schema/vocabulary locksmap unknown enum to first/default; silently normalize signed data
authDPoP/mTLS support, audience check, key protection, step-up challengelong-lived bearer token in app storage/logs
appendstable idempotency key, expected sequence, receipt verification, unknown-result queryautomatic new key after timeout
querytyped AST, signed cursor, checkpoint/staleness exposure, redaction marker typesraw query string or hiding projection checkpoint
telemetrydescriptor/session lock, bounded chunking, exact bit patterns, resumable digest-verified uploadunit/frame conversion in raw capture batch
actionsproposal/confirmation/dispatch types; legal state parser; reconciliation pollingreport timeout as failure or payment success as title
eventsdedupe, monotonic stream handling, checkpoint atomicity and quarantineassume global order or exactly-once broker
offline edgelocal signed journal, monotonic local sequence, pack lock, conflict-preserving synclast-write-wins over lifecycle/evidence/authority

Generated SDKs are subordinate to semantic fixtures. Each supported language must reproduce canonical golden bytes/digests, exact UUID grammar, unit/dimension vectors, proof verification, HTTP retries, cursor rejection, event deduplication and error-code exhaustiveness. A generator release is not conforming until its language-specific corpus passes byte-for-byte.

#43.7 Offline synchronization, import/export, and federation

Table
Disconnected capture and portable dossier contract
EdgeJournalEntry {
  edgeDeviceId, bootId, localSequence, recordId, canonicalBytes,
  recordDigest, proofRefs[], packLock, capturedAtDevice,
  priorLocalDigest, localDigest, syncState
}

Sync:
  1 authenticate device/workload and authorize exact journal scope
  2 compare server acknowledgement vector and local chain
  3 upload missing bytes/proofs with stable per-record idempotency keys
  4 admit independently; preserve conflicts/equivocation and server receipts
  5 append SyncReceipt mapping local sequence to admission disposition
  6 never rewrite edge history; append corrections/invalidation

ExportManifest pins tenant, subject selectors, purpose, policy decision,
source checkpoint, schema/vocabulary/pack locks, record and artifact digests,
encryption recipients, redactions, retention/recipient duties and signature.
Import verifies bytes first, then maps external IDs as assertions; it never
assumes imported tenant, ownership, grants or registry status are local truth.
  • Public ActivityPub objects remain projections. Remote Actor/Note/Follow/Like IDs never become vehicle, principal, grant, bid, appraisal or lifecycle evidence IDs.
  • Federated inbox content is quarantined untrusted data. It cannot invoke tools, promote memory, reveal private dossiers or enter the physical-control plane.
  • Withdrawal/correction propagates best-effort to federated copies with durable receipts, while the system reports that remote deletion cannot be guaranteed.
  • Government, insurer, workshop and event adapters preserve issuer, native identifier/value, fetch/import time, effective time, source artifact and transformation receipt. They do not flatten external claims into owner-authored facts.