CrateStack Transport Architecture
Status
Proposed target architecture. This document is the canonical transport design reference to use before changing routing, client runtime, or generated contracts. Current implementation is narrower than this design:- generated Axum routers currently enforce a single configured codec per router
- CBOR is the only first-party checked-in server codec crate today
- JSON support currently exists inline in
cratestack-client-rustrather than as a dedicated codec crate - COSE remains an unimplemented envelope seam
application/cbor-seqis not implemented yet
Purpose
CrateStack needs a transport model that stays correct as the project grows from today’s CBOR-first bootstrap slice to a broader multi-client, multi-service, and optional signed-envelope platform. This document fixes the architecture vocabulary first so implementation work does not blur distinct concerns.Core Model
CrateStack transport is composed from three separate layers:- codec
- framing
- envelope
Definitions
Codec
A codec converts a typed value graph into bytes and back. Examples:- JSON
- CBOR
- value serialization and deserialization
- codec-specific content rules
- typed error reporting for encode and decode failures
- request authentication
- response negotiation policy
- body streaming semantics
- signing or encryption
Framing
Framing defines how one or more encoded values are arranged inside a single HTTP body. Examples:- single value
- sequence
- define whether a body contains one payload or many
- define how multiple payloads are delimited or concatenated
- constrain which endpoints can legally use the framing mode
- typed value serialization rules
- cryptographic protection
Envelope
An envelope wraps already-encoded and already-framed bytes. Examples:- none
- COSE Sign1 in a future implementation
- sealing and opening transport bytes
- binding transport bytes to signatures or future cryptographic metadata
- optionally using auth context or host-provided signing material
- primary typed serialization format
- list versus sequence semantics
Design Rules
Rule 1: COSE is an envelope, not a codec
COSE must not be modeled as a peer alternative to CBOR or JSON. Correct model:- choose codec
- choose framing
- optionally apply COSE
- choose one of JSON, CBOR, COSE
Rule 2: application/cbor-seq is not just another codec label
application/cbor and application/cbor-seq share a CBOR value model, but they do not have the same body semantics.
application/cbormeans one CBOR data item per bodyapplication/cbor-seqmeans multiple top-level CBOR data items in sequence
cbor-seq belongs at the framing layer, even if media-type handling ends up representing it as a distinct transport option in code.
Rule 3: Transport capability is route-specific
Not every generated route should support every transport shape. Examples:GET /products/{id}is naturally a single-value responsePOST /productsis naturally a single-value request and response- an export, feed, or watch procedure may support sequence responses
Rule 4: Request and response negotiation are related but separate
For HTTP:- request decoding is driven by
Content-Type - response encoding is driven by
Accept
Rule 5: Error bodies follow the negotiated response transport
Once the server has successfully selected a response transport, both success and error bodies should use it. Before response transport selection is possible, the server may fall back to a plain text or minimal host-defined error response only for truly pre-negotiation failures.Media-Type Direction
Implemented today
application/cboron generated server routes when a router is built withCborCodec
Planned first-class media types
application/jsonapplication/cbor
Planned framing-aware media types
application/cbor-seq
Planned future envelope-aware media types
This repo has not yet committed to final envelope media types for COSE-wrapped payloads. That decision must happen explicitly rather than being implied by implementation. Questions to settle before COSE implementation:- whether the outer response type is a generic COSE media type or a CrateStack-specific profile
- how the inner codec and framing are declared or discoverable
- whether some routes require envelopes while others merely allow them
Recommended Runtime Shape
The currentCoolCodec and CoolEnvelope split is still directionally correct, but it is not sufficient on its own for content negotiation and sequence framing.
The long-term runtime should represent three concepts:
- codec registry
- framing policy
- envelope policy
- keep
CoolCodecfor typed encoding - add a framing abstraction for single versus sequence bodies
- keep
CoolEnvelopefor post-framing wrapping - add a transport selector or registry that resolves request and response behavior from HTTP headers plus route capability metadata
Route Capability Model
Generated routes should eventually declare transport capabilities instead of inheriting one implicit codec for every path. A route capability model should answer:- which request media types are accepted
- which response media types are supported
- whether sequence responses are allowed
- whether an envelope is optional, forbidden, or required
| Route shape | Request transport | Response transport |
|---|---|---|
GET /products/{id} | none | JSON, CBOR |
POST /products | JSON, CBOR | JSON, CBOR |
GET /products | none | JSON, CBOR, maybe CBOR sequence |
POST /$procs/exportProducts | JSON, CBOR | CBOR sequence |
cbor-seq Guidance
application/cbor-seq should be introduced as a selective transport mode rather than a blanket replacement for list responses.
Good early fits:
- export procedures
- event feeds
- watch or tail style responses
- large result streams where incremental processing matters
- standard CRUD create or update requests
- simple detail fetches
- small procedure responses that already fit the single-value model cleanly
- implement negotiated JSON and CBOR single-value transport first
- add route capability metadata
- add response-side
cbor-seqfor explicitly sequence-oriented endpoints - consider request-side
cbor-seqonly after a concrete use case exists
Client Architecture Direction
Clients should mirror the same transport split. Client responsibilities:- choose a request transport explicitly when a request body exists
- advertise one or more acceptable response transports
- decode responses based on actual response
Content-Type - expose explicit sequence APIs instead of forcing sequence responses through single-value decode helpers
- default request transport: CBOR for internal first-party clients
- default accepted response transports: CBOR first, JSON second
- optional route- or request-level override when interoperability needs differ
Current Repo Mapping
This document is intentionally ahead of the current checked-in implementation. Current repo reality:- generated Axum routes currently validate
AcceptandContent-Typeagainst one configured codec cratestack-codec-cboris the only dedicated checked-in codec crate- JSON codec support exists inline in
cratestack-client-rust cratestack-client-rustandcratestack-client-flutteralready expose runtime codec configuration for CBOR and JSON, but each client instance still operates as a single-codec transport client- COSE envelope configuration exists as a reserved runtime option, but the runtime rejects it because implementation is missing
Implementation Phasing
Recommended order:- document the transport model and HTTP contract first
- add a dedicated JSON codec crate
- add negotiated JSON and CBOR request and response handling for generated routes
- update Rust client decoding to respect actual response
Content-Type - expose response preference ordering in client runtime config
- add route capability metadata for transport support
- add selective
application/cbor-seqsupport for sequence-oriented routes - add COSE envelope support only after codec and framing boundaries are proven in code
Non-Goals For The First Transport Expansion
- supporting every route under every media type from day one
- implementing COSE and multi-codec negotiation in the same patch set
- treating sequence framing as required for all list endpoints
- hiding transport differences behind vague automatic magic that clients cannot reason about
Canonical Companion Document
./http-transport-contract.md should be read alongside this document. This architecture file explains the model and boundaries. The HTTP contract file explains concrete request, response, and negotiation behavior.