Chio/Docs
LOGIN · JOIN

HTTP Transport

Look up the sidecar endpoints, request and verdict fields, receipt signing and verification, and the errors middleware must handle.

Reference chio@5f63e6e

On this page

Middleware posts each incoming API request to the sidecar at /chio/evaluate, receives a verdict and a signed HttpReceipt, and forwards the request upstream only on allow.

The chio api protect reverse proxy evaluates with the same types in process and forwards the request itself. Choose the integration boundary first; the endpoints, fields, verdicts, and receipt rules below apply to both. The keywords MUST, SHOULD, and MAY are normative per RFC 2119.

Endpoint synopsis

Sidecar routestext
POST /chio/evaluate   body: ChioHttpRequest   ->  200  EvaluateResponse { verdict, receipt, evidence, execution_nonce? }
POST /chio/verify     body: HttpReceipt       ->  200  VerifyReceiptResponse
GET  /chio/live                               ->  200  HealthResponse { status, version, receipt_backend, revocation_backend }
GET  /chio/health                             ->  200 | 503  HealthResponse

chio-api-protect mounts the routes under /chio, with the request and response types chio-http-core defines.

Decision ownership

HTTP evaluationChoose an outcome.

πrouteκcapabilitygguardsτapproval

The sidecar decides, then middleware forwards

Middleware builds a ChioHttpRequest and posts it to /chio/evaluate. The sidecar resolves the route, authorizes through the kernel, and records the signed HttpReceipt before it answers 200 with verdict, receipt, and evidence. Only an explicit allow lets middleware forward the request upstream. POST /chio/evaluate.

The middleware integration: the sidecar records the decision before the upstream request is sent, and middleware owns the forwarding step. The sidecar’s checks are drawn as one row. Receipt verification through POST /chio/verify and the health routes are left out.

A Chio kernel runs as a local process and exposes an HTTP API on localhost. Framework middleware or an SDK intercepts an incoming HTTP request, constructs a ChioHttpRequest, sends it to the sidecar, and enforces the returned verdict. The sidecar records the decision before the upstream request is sent; middleware owns the forwarding step and handles refusal, approval requirements, nonce preflight, and transport failure before it.

Sidecar evaluation protocol

The sidecar serves four routes on a localhost listener. The two POST routes each take one JSON body.

Transport

The sidecar MUST listen on 127.0.0.1:9090 by default; that is the default of the --listen flag of chio api protect. Implementations MAY override the sidecar URL via:

  • An explicit configuration value (sidecarUrl in SDK config, or equivalent)
  • The CHIO_SIDECAR_URL environment variable

If both are set, the explicit configuration value takes precedence. If neither is set, the default http://127.0.0.1:9090 MUST be used. All request and response bodies MUST use Content-Type: application/json.

Endpoints

EndpointMethodPurpose
/chio/evaluate
POST
Evaluate an HTTP request against policy and sign a receipt
/chio/verify
POST
Verify a receipt: signature, content-addressed id, and authority semantics
/chio/live
GET
Process liveness; answers 200 while the process runs
/chio/health
GET
Dependency-aware readiness and the storage backends in effect

The sidecar also mounts the approval routes under /approvals and the SDK helper routes under /v1, behind the sidecar-control token where its router requires it. Those routes sit outside the evaluation protocol.

POST /chio/evaluate

Evaluates an HTTP request against the loaded policy and returns a signed receipt. The sidecar reads at most 10 MiB of request body, decodes it as a ChioHttpRequest, and records the receipt before answering with an EvaluateResponse:

FieldTypeRequiredDescription
verdict
Verdict
MUST
The evaluation verdict
receipt
HttpReceipt
MUST
Signed receipt that records the evaluation
evidence
GuardEvidence[]
MUST
Guard evidence collected during evaluation. Always serialized; a decoder treats an absent field as [].
execution_nonce
SignedExecutionNonce or absent
MAY
Present only when the kernel issues one

The kernel issues execution_nonce on an allow verdict when it is configured with an execution nonce. The client MUST re-present it as ToolCallRequest.execution_nonce before the governed action executes. In strict mode the preflight response carries incomplete plus this field, and the caller retries with the nonce. The field is absent on deny and cancel, on deployments without a nonce config, and on advisory routes.

Implementations MUST return 200 for both allow and deny verdicts. The HTTP status code reports the health of the evaluation, and the policy outcome is encoded in the verdict field. The status codes:

  • 200 OK. Evaluation completed, for every verdict, including a deny for a revoked capability. The verdict field carries the outcome.
  • 400 Bad Request, "error": "chio_bad_request". The body could not be read or does not decode as a ChioHttpRequest.
  • 409 Conflict, "error": "chio_approval_required". The route is approval-gated and the decision is pending; the body carries kernel_receipt_id and, when the sidecar holds an approval handle, approval_id and resume_path.
  • 500 Internal Server Error, "error": "chio_evaluation_failed" for any other evaluation error, or "error": "chio_receipt_persistence_failed" when the receipt could not be recorded.

POST /chio/verify

Verifies the signature, content-addressed id, and authority semantics of a previously issued HttpReceipt. The sidecar reads at most 1 MiB of body and answers 400 chio_bad_request when the body does not decode as an HttpReceipt.

The response, VerifyReceiptResponse, reports each conclusion in its own field; it has no single valid field.

FieldTypeDescription
signature_valid
boolean
HttpReceipt::verify_signature: the authority semantics hold, the recomputed id matches, and the signature verifies against kernel_key
signer_trusted
boolean
Whether kernel_key equals the public key of the sidecar's own signer
receipt_id_valid
boolean
Whether id matches the recomputed content-addressed id
parameter_hash_valid
boolean
Whether content_hash is a well-formed 64-character lowercase hex digest
receipt_kind
string
The receipt's receipt_kind as a string
boundary_class
string
The receipt's boundary_class as a string
trust_level
string
The receipt's trust_level as a string
result
string
Verdict result: allow, deny, cancelled, or incomplete
authorized
boolean
ok and the verdict is allow; describes the recorded decision
signer_key_hex
string
Hex encoding of kernel_key
ok
boolean
Roll-up of the four checks and the authority semantics

ok requires a valid signature, a trusted signer, a valid id, a valid parameter hash, and the semantics mediated_decision, prevent, no observation_outcome, and mediated. authorized neither authorizes a new request nor establishes freshness. Verification reruns no current policy and says nothing about whether an upstream request occurred.

No field reads timestamp. A receipt with a valid signature but a timestamp outside the caller's accepted window still reports signature_valid: true; temporal validity is the caller's responsibility.

GET /chio/live and GET /chio/health

Both routes answer with a HealthResponse. Liveness is process-only: it reports healthy and empty backend fields while the process runs, so a dependency fault never restarts a container that is serving. Readiness consults the proxy state.

FieldTypeRequiredDescription
status
string
MUST
One of "healthy", "degraded", or "unhealthy"
version
string
MUST
The chio-api-protect package version
receipt_backend
string
MUST
Receipt log backend: durable or ephemeral. Empty on /chio/live.
revocation_backend
string
MUST
Revocation state backend: durable, remote, or ephemeral. Empty on /chio/live.

Both backends belong to the embedded kernel, and a decoder treats an absent receipt_backend as empty. On /chio/health the sidecar answers 200 OK when healthy and 503 Service Unavailable when degraded or unhealthy. It reports unhealthy when its durable receipt store is unreachable, because every mediated call would then be denied fail closed.

Timeout and failure behavior

SDKs MUST implement a configurable timeout for sidecar calls. The default timeout SHOULD be 5000 milliseconds; the TypeScript @chio-protocol/node-http package defaults timeoutMs to 5000.

When the sidecar is unreachable or times out, SDKs MUST default to fail-closed behavior (deny the request). SDKs MAY expose a configuration option to override this to fail-open, but fail-closed MUST be the default.

ChioHttpRequest

The protocol-agnostic HTTP request that Chio evaluates, and the shared input type for every HTTP adapter: reverse proxy, framework middleware, and sidecar alike. The specification defines these fields.

FieldTypeRequiredDefaultDescription
request_id
string
MUST
Unique request identifier. UUIDv7 recommended; the proxy mints one with Uuid::now_v7.
method
HttpMethod
MUST
HTTP method of the request
route_pattern
string
MUST
Matched route pattern (e.g., "/pets/{petId}")
path
string
MUST
Request path as received (e.g., "/pets/42")
query
map<string, string>
MAY
{}
Query parameters. Omitted from the wire when empty.
headers
map<string, string>
MAY
{}
Selected headers. Adapters MUST NOT include raw auth credential headers.
caller
CallerIdentity
MUST
Extracted caller identity
body_hash
string or null
MAY
null
SHA-256 hex hash of the request body. null for bodyless requests (GET, HEAD, OPTIONS).
body_length
integer
MAY
0
Content-Length of the request body in bytes
session_id
string or null
MAY
null
Session ID this request belongs to
capability_id
string or null
MAY
null
Capability token ID presented with this request
timestamp
integer
MUST
Unix timestamp (seconds) when the request was received

The sidecar re-matches path against its own route table and ignores the client's route_pattern.

Sidecar-only fields

The crate carries further optional fields that the schema file does not list. Each is omitted from the wire when absent.

FieldTypeDescription
tool_server
string or null
Tool server identity for a synthetic sidecar evaluation of a governed action
tool_name
string or null
Tool name for a synthetic sidecar evaluation
arguments
object or null
Structured arguments for a synthetic sidecar evaluation
model_metadata
ModelMetadata or null
Model identity and safety tier for model-constrained grants
governed_intent, approval_token, approval_tokens, threshold_approval_proposal, supplemental_authorization
any or null
Extra authority inputs outside the HTTP grant
execution_nonce
SignedExecutionNonce or null
The signed nonce presented to complete a strict nonce preflight

The HTTP authority enforces none of the five authorization extensions. A request that carries one is denied at the authority boundary instead of being silently ignored.

Content hash computation

The content hash that binds a request to its receipt is the SHA-256 hex digest of the canonical JSON (RFC 8785) of this binding object, which ChioHttpRequest::content_hash serializes from the RequestContentBinding struct:

RequestContentBindingjson
{
  "body_hash": "<body_hash or null>",
  "method": "<HTTP method>",
  "path": "<actual path>",
  "query": { "<query key>": "<query value>" },
  "route_pattern": "<route pattern>"
}

CallerIdentity

The identity of the caller as extracted from the HTTP request.

FieldTypeRequiredDefaultDescription
subject
string
MUST
Stable identifier for the caller
auth_method
AuthMethod
MUST
How the caller authenticated
verified
boolean
MAY
false
Whether this identity has been cryptographically verified. The proxy sets false for every identity it extracts.
tenant
string or null
MAY
null
Tenant or organization the caller belongs to
agent_id
string or null
MAY
null
Agent identifier when the caller is an AI agent

The caller_identity_hash in receipts is the SHA-256 hex digest of the canonical JSON representation of the full CallerIdentity object (CallerIdentity::identity_hash). The same identity MUST always produce the same hash.

AuthMethod

A tagged union representing how the caller authenticated. The discriminator field is method, and variant names use snake_case.

VariantTag valueFieldsDescription
Bearer
"bearer"
token_hash: string
Bearer token (JWT or opaque). token_hash is the SHA-256 hex hash of the raw token.
ApiKey
"api_key"
key_name, key_hash
API key. key_name is the header or query parameter name; key_hash is the SHA-256 hex hash of the key value.
Cookie
"cookie"
cookie_name, cookie_hash
Session cookie. cookie_hash is the SHA-256 hex hash of the cookie value.
MtlsCertificate
"mtls_certificate"
subject_dn, fingerprint
mTLS client certificate. fingerprint is the SHA-256 fingerprint of the certificate.
Anonymous
"anonymous"
(none)
No authentication was presented. CallerIdentity::anonymous() sets subject to "anonymous".

Implementations MUST NOT store or transmit raw tokens. The specification's Bearer example, with a shortened hash, and the Anonymous example:

Bearer AuthMethodjson
{
  "method": "bearer",
  "token_hash": "a1b2c3d4e5f6..."
}
Anonymous AuthMethodjson
{
  "method": "anonymous"
}

SessionContext

Per-session context carried through the Chio HTTP guard pipeline. A session groups related requests from the same caller over a bounded time window.

FieldTypeRequiredDefaultDescription
session_id
string
MUST
Unique session identifier
caller
CallerIdentity
MUST
Authenticated caller for this session
created_at
integer
MUST
Unix timestamp (seconds) when the session was created
expires_at
integer or null
MAY
null
Unix timestamp (seconds) when the session expires; is_expired() compares it with the current time
request_count
integer
MAY
0
Number of requests evaluated in this session
bytes_read
integer
MAY
0
Cumulative bytes read by this session
bytes_written
integer
MAY
0
Cumulative bytes written by this session
delegation_depth
integer
MAY
0
Current delegation depth. 0 means direct caller.
metadata
object or null
MAY
null
Extensibility metadata

Verdict

Internally tagged with "verdict" as the tag key and snake_case variant names.

VariantTag valueFieldsDescription
Allow
"allow"
(none)
Request is allowed. Proceed to upstream.
Deny
"deny"
reason, guard, http_status, details
Request is denied. http_status defaults to 403. details is a boxed DenyDetails block, omitted from the wire when empty.
Cancel
"cancel"
reason
Evaluation was cancelled (e.g., timeout, circuit breaker).
Incomplete
"incomplete"
reason
Evaluation reached no terminal state. A strict nonce preflight answers with this variant and an execution_nonce.

When the verdict is cancel or incomplete, middleware MUST treat the request as denied. Only an explicit allow verdict permits forwarding to the upstream API. The reverse proxy answers an incomplete verdict with 428 Precondition Required and the EvaluateResponse as the body.

When deserializing a deny verdict without an explicit http_status field, implementations MUST default to 403; the crate does this through a serde default. The specification's examples:

Allow verdictjson
{ "verdict": "allow" }
Deny verdictjson
{
  "verdict": "deny",
  "reason": "side-effect route requires a capability token",
  "guard": "CapabilityGuard",
  "http_status": 403
}

The HTTP authority emits that deny for a deny-by-default route with no capability presented. An invalid capability yields a deny from the same guard, with the validation failure as reason.

DenyDetails

A deny verdict carries an optional boxed DenyDetails block so a sidecar can tell an SDK what scope was required and what scope was granted. Every field is optional; the whole details key is omitted from the wire when all fields are empty.

FieldTypeDescription
tool_name
string or null
Tool that was denied
tool_server
string or null
Tool server that hosts the denied tool
requested_action
string or null
Short summary of the attempted action
required_scope
string or null
Scope the kernel requires, as a canonical ToolGrant(...) string
granted_scope
string or null
Scope the presented capability had. Null when none was presented.
reason_code
string or null
Stable machine-readable code, e.g. scope.missing
receipt_id
string or null
Receipt id that records this denial, for audit correlation
hint
string or null
Next-steps sentence for the developer
docs_url
string or null
Link to the docs page that explains this deny code

HttpMethod

Serialized as uppercase strings. HttpMethod::is_safe names the Safe column and requires_capability is its negation.

ValueSafeRequires capability
"GET"
Yes
No
"HEAD"
Yes
No
"OPTIONS"
Yes
No
"POST"
No
Yes
"PUT"
No
Yes
"PATCH"
No
Yes
"DELETE"
No
Yes

Unsafe methods (POST, PUT, PATCH, DELETE) require an explicit capability grant. Default policy semantics gives the verdict each method receives without one.

GuardEvidence

The same GuardEvidence type the core receipt carries. The HTTP authority emits entries named DefaultPolicyGuard for a session-scoped allow and CapabilityGuard for a capability decision.

FieldTypeRequiredDescription
guard_name
string
MUST
Name of the guard
verdict
boolean
MUST
Whether the guard passed (true) or denied (false)
details
string or null
MAY
Human-readable details about the guard's decision; omitted when absent

HttpReceipt

The kernel's signed record that it evaluated one HTTP request. The receipt binds the request identity, route, method, verdict, semantic classification, and guard evidence under a kernel signature (Ed25519 by default; P-256 and P-384 also supported). The Required column reads the serde attributes: a field with a skip rule is omitted from the wire at its default.

FieldTypeRequiredDefaultSignedDescription
id
string
MUST
Yes
Content-addressed receipt id
request_id
string
MUST
Yes
Unique request ID this receipt covers
route_pattern
string
MUST
Yes
Matched route pattern
method
HttpMethod
MUST
Yes
HTTP method of the evaluated request
caller_identity_hash
string
MUST
Yes
SHA-256 hex hash of the caller identity
session_id
string or null
MAY
null
Yes
Session ID the request belonged to
verdict
Verdict
MUST
Yes
The kernel's verdict
receipt_kind
ReceiptKind
MUST
Yes
Signed semantic class. Signing rejects any value other than mediated_decision.
boundary_class
BoundaryClass
MUST
Yes
Signed runtime boundary. Signing rejects any value other than prevent.
observation_outcome
ObservationOutcome or null
MUST NOT
null
Yes
Absent on mediated HTTP receipts; signing rejects a present value.
tool_origin
ToolOrigin
MUST
Yes
Where the protected effect executes relative to Chio
redaction_mode
RedactionMode
MUST
Yes
Redaction applied to signed details: none, summary, or redacted. The HTTP authority writes none.
actor_chain
ActorRef[]
MAY
[]
Yes
Signed actor attribution for the HTTP decision. Omitted from the wire when empty.
evidence
GuardEvidence[]
MAY
[]
Yes
Per-guard evidence collected during evaluation. Omitted from the wire when empty.
response_status
integer
MUST
Yes
HTTP status Chio associated with the outcome at signing time
timestamp
integer
MUST
Yes
Unix timestamp (seconds) when the receipt was created
content_hash
string
MUST
Yes
SHA-256 hex hash binding the request content to this receipt
policy_hash
string
MUST
Yes
SHA-256 hex hash of the policy that was applied
trust_level
TrustLevel
MUST
Yes
Strength of kernel mediation. Signing rejects any value other than mediated.
capability_id
string or null
MAY
null
Yes
Capability ID that was exercised, if any
metadata
object or null
MAY
null
Yes
Extensibility metadata
kernel_key
PublicKey (hex)
MUST
Yes
Kernel's algorithm-aware public key
signature
Signature (hex)
MUST
No
Algorithm-aware signature over canonical JSON of the body fields

Field contracts that need more than a cell:

  • id is the SHA-256 hex of the canonical JSON of the receipt body with id removed (compute_http_receipt_id). HttpReceipt::sign computes and assigns it, overwriting any caller-supplied value.
  • tool_origin is caller_executed, host_executed_provider_reported, or host_executed_unmediated. The HTTP authority writes caller_executed.
  • response_status on a deny receipt is the error status Chio emits. On an allow receipt signed before an upstream response exists, it is evaluation-time metadata.
  • metadata: the reverse proxy writes chio_http_status_scope (decision or final) and, on a finalized receipt, chio_decision_receipt_id.
  • kernel_key is the same chio_core_types::crypto::PublicKey as the core receipt; kernel_key and signature formats are under Cryptographic representations.

Exported evidence packages embed HTTP door receipts as chio_http_receipt_v1, and evidence verification checks each embedded HttpReceipt.

Signing

HttpReceipt::sign(body, keypair) produces a signed receipt in this order:

  1. Construct an HttpReceiptBody containing every field in the table except signature.
  2. Compute the content-addressed id (compute_http_receipt_id) and overwrite the body's id with it.
  3. Validate the authority semantics: mediated_decision, prevent, no observation_outcome, mediated. Any other shape is an error.
  4. Serialize the body to canonical JSON (RFC 8785) and sign the canonical bytes with the kernel's private key (Ed25519 by default; P-256 or P-384 when configured).
  5. Attach the resulting signature to the receipt.

Verification

HttpReceipt::verify_signature returns false at the first failing step:

  1. Extract the body (all fields except signature) and validate the authority semantics.
  2. Recompute the content-addressed id and compare it with id.
  3. Serialize the body to canonical JSON (RFC 8785) and verify the signature against the canonical bytes using the kernel_key embedded in the receipt.

Implementations SHOULD verify the receipt signature before treating receipt content as authoritative.

Cryptographic representations

kernel_key and signature reuse the algorithm-aware chio_core_types::crypto types of the core ChioReceipt, so they accept three algorithms:

  • kernel_key: bare 64-character lowercase hex for Ed25519, p256:<130-hex> (uncompressed SEC1), or p384:<194-hex>.
  • signature: bare 128-character lowercase hex for Ed25519, or a p256: or p384: prefixed DER hex form. Verification dispatches on the prefix.

HttpReceipt to ChioReceipt mapping

An HttpReceipt maps into the core ChioReceipt type for unified storage and querying, through to_chio_receipt_with_keypair(keypair). It builds the ChioReceiptBody, recomputes content_hash over that canonical body, and re-signs through ChioReceipt::sign(...) with the supplied kernel keypair. The HTTP signature is never copied.

Field mapping

HttpReceipt fieldChioReceipt fieldTransformation
id
id and signing nonce metadata
Passed into the core body; a new core ID is derived
timestamp
timestamp
Copied directly
capability_id
capability_id
Unwrapped; defaults to the empty string if null
(constant)
tool_server
Set to "http"
method + route_pattern
tool_name
Formatted as "{method} {route_pattern}"
method, route_pattern, request_id
action.parameters
JSON object { method, route, request_id }
(derived)
action.parameter_hash
Canonical hash of action.parameters
verdict
decision
Converted through Verdict::to_decision()
receipt_kind, boundary_class, observation_outcome, tool_origin, redaction_mode, actor_chain
(same fields)
Copied directly
content_hash
content_hash
Recomputed as SHA-256 of the canonical JSON of the ChioReceiptBody
policy_hash
policy_hash
Copied directly
evidence
evidence
Copied directly
metadata
metadata
Copied directly
trust_level
trust_level
Copied directly
(constant)
tenant_id
Set to null
(constant)
bbs_projection_version
Set to null
kernel_key
kernel_key
Copied directly
(re-signed)
signature
Freshly produced by ChioReceipt::sign(...) with the supplied keypair

Core signing retains the HTTP id under metadata.chio_receipt_signing_nonce and derives a new content-addressed core ID. The action.parameter_hash comes from ToolCallAction::from_parameters, so a durable store that recomputes the hash accepts the converted receipt; the HTTP content_hash stays bound through its own field.

Verdict to Decision mapping

Verdict variantDecision variantFields dropped
allow
allow
none
deny { reason, guard, http_status, details }
deny { reason, guard }
http_status, details
cancel { reason }
cancelled { reason }
none
incomplete { reason }
incomplete { reason }
none

The reverse mapping, Verdict::from(Decision), restores a deny with http_status 403 and empty details.

Conversion re-signs or fails closed

to_chio_receipt() takes no keypair and unconditionally returns an error: "cannot convert HttpReceipt into signed ChioReceipt without the kernel keypair". A copied HTTP signature would fail verification over the ChioReceiptBody, so the conversion refuses instead of emitting it.

Use to_chio_receipt_with_keypair(keypair) for conversion. The resulting ChioReceipt carries a signature and an action.parameter_hash that verify, so a durable receipt store accepts it.

Default policy semantics

The HTTP sidecar protocol defines default policy behavior based on HTTP method safety:

  • Safe methods (GET, HEAD, OPTIONS): treated as side-effect-free, so they receive a session-scoped allow, recorded as a passing DefaultPolicyGuard evidence entry.
  • Unsafe methods (POST, PUT, PATCH, DELETE): deny by default. These methods require a capability token presented in the X-Chio-Capability request header, the chio_capability query parameter, or capability_id in the ChioHttpRequest.

A door that admits federated grants refuses safe methods by default as well. When a route is not matched in the loaded policy, the evaluator MUST fall back to method-based default policy, and the reverse proxy records the raw path as route_pattern.

Error handling

Two code sets: the codes SDKs raise to callers, and the codes the sidecar writes in its own error bodies.

Sidecar error codes

SDKs MUST use the following error codes when communicating sidecar failures to callers:

  • chio_access_denied: the request was denied by policy.
  • chio_sidecar_unreachable: the sidecar process is unreachable.
  • chio_evaluation_failed: the sidecar returned a non-200 status.
  • chio_invalid_receipt: receipt verification failed.
  • chio_timeout: the sidecar did not respond within the timeout.

The TypeScript @chio-protocol/node-http package exports these five and one more, chio_sidecar_unavailable, as ChioErrorCode; it classifies a verify response of 408, 404, 429, or 5xx under that code. The sidecar itself answers with these codes in its own JSON error bodies:

CodeStatusWhen
chio_bad_request
400
The body could not be read or decoded; a duplicate query key; a blank or malformed x-chio-execution-nonce header
chio_access_denied
403 (or the verdict's http_status)
The proxy denied a forwarded request; the body carries message, receipt_id, and suggestion
chio_approval_required
409
Evaluation returned a pending approval
chio_evaluation_failed
500
Any other evaluation error
chio_receipt_sign_failed
500
The revocation receipt could not be hashed or signed
chio_receipt_persistence_failed
500
The receipt could not be recorded

Structured error response

When middleware denies a request, the response body SHOULD be a structured JSON object. The reverse proxy's 403 body carries all four fields and repeats the receipt id in an X-Chio-Receipt-Id header.

FieldTypeRequiredDescription
error
string
MUST
Error code from the sidecar error codes
message
string
MUST
Human-readable error message; the proxy uses the verdict's reason
receipt_id
string or null
MAY
Receipt ID for the denied evaluation
suggestion
string or null
MAY
Actionable suggestion for the caller

Schemas and conformance

Versioned HTTP sidecar schemas live under spec/schemas/chio-http/v1/, the machine-readable contract for the HTTP sidecar types. Implementations MUST serialize all HTTP sidecar types in a form accepted by those schemas. Schema validation SHOULD be exercised against live Rust serialization and never against handwritten examples alone.

The directory holds 15 schema files; the schema registry lists 0 of them. Each file, with the title it declares:

  • caller-identity.schema.json: Chio CallerIdentity
  • chio-http-request.schema.json: Chio HTTP Request
  • error-envelope.schema.json: Chio HTTP Error Envelope
  • evaluate-request.schema.json: Chio Evaluate Request
  • evaluate-response.schema.json: Chio Evaluate Response
  • finding-hosted-domain-event.schema.json: Chio Hosted Finding Domain Event Envelope
  • finding-hosted-error.schema.json: Chio Hosted Finding Error
  • finding-hosted-mutation-response.schema.json: Chio Hosted Finding Mutation Response
  • finding-hosted-request-context.schema.json: Chio Hosted Finding Authenticated Request Context
  • finding-hosted-tenant-binding.schema.json: Chio Hosted Finding Tenant Binding
  • http-receipt.schema.json: Chio HTTP Receipt
  • session-init.schema.json: Chio HTTP Session Init
  • session-resume.schema.json: Chio HTTP Session Resume
  • stream-frame.schema.json: Chio HTTP Stream Frame
  • verdict.schema.json: Chio HTTP Verdict

evaluate-request.schema.json is a reference to chio-http-request.schema.json. The session, stream, error-envelope, and hosted-finding schemas describe the chio-http session edge and the hosted finding API, outside the sidecar evaluation protocol.

15 files in chio-http · 0 registered · registry 1.0.0
FileTitleRegistry IDVersion
chio-http/v1/caller-identity.schema.jsonChio CallerIdentityunregisteredv1
chio-http/v1/chio-http-request.schema.jsonChio HTTP Requestunregisteredv1
chio-http/v1/error-envelope.schema.jsonChio HTTP Error Envelopeunregisteredv1
chio-http/v1/evaluate-request.schema.jsonChio Evaluate Requestunregisteredv1
chio-http/v1/evaluate-response.schema.jsonChio Evaluate Responseunregisteredv1
chio-http/v1/finding-hosted-domain-event.schema.jsonChio Hosted Finding Domain Event Envelopeunregisteredv1
chio-http/v1/finding-hosted-error.schema.jsonChio Hosted Finding Errorunregisteredv1
chio-http/v1/finding-hosted-mutation-response.schema.jsonChio Hosted Finding Mutation Responseunregisteredv1
chio-http/v1/finding-hosted-request-context.schema.jsonChio Hosted Finding Authenticated Request Contextunregisteredv1
chio-http/v1/finding-hosted-tenant-binding.schema.jsonChio Hosted Finding Tenant Bindingunregisteredv1
chio-http/v1/http-receipt.schema.jsonChio HTTP Receiptunregisteredv1
chio-http/v1/session-init.schema.jsonChio HTTP Session Initunregisteredv1
chio-http/v1/session-resume.schema.jsonChio HTTP Session Resumeunregisteredv1
chio-http/v1/stream-frame.schema.jsonChio HTTP Stream Frameunregisteredv1
chio-http/v1/verdict.schema.jsonChio HTTP Verdictunregisteredv1
The schema registry rows for the chio-http family. The file list above names every schema in the directory.
Specification and implementation sources

The lookup reflects spec/HTTP-SUBSTRATE.md in the chio repository. Status: normative. Version 1.0.

Where that document and the code differ, the lookup follows the crate crates/platform/chio-http-core (evaluation.rs, verdict.rs, receipt.rs) and the sidecar in crates/products/chio-api-protect/src/proxy, which are the normative source for wire behavior. The router is crates/products/chio-api-protect/src/proxy/router.rs and the evaluation sequence is crates/products/chio-api-protect/src/proxy/sidecar.rs.

Next: put the proxy in front of an API