Chio/Docs

Bindings API

The Bindings API is the low-level invariants contract shared across every chio SDK. It defines the functions each binding must implement, the data shapes that cross the language boundary, and the cross-language conformance suite that keeps the four SDKs in byte-for-byte agreement.

Not a transport layer

The bindings contract is deliberately narrow. It covers canonical JSON, hashing, signing, and verification of the protocol artifacts. It does not cover transport, authentication, session state, orchestration, or any runtime concern. Those layers live in the per-language SDKs.

Scope

The upstream crate chio-binding-helpers fixes this contract in Rust. Every other SDK (TypeScript, Python, Go) mirrors the same API shape, the same input and output rules, and the same stable error codes.

The Contract Owns

  • Canonical JSON helpers (RFC 8785).
  • SHA-256 hashing helpers for both bytes and UTF-8 strings.
  • Ed25519 signing and verification helpers.
  • Receipt parsing and verification helpers.
  • Capability parsing and verification helpers.
  • Signed manifest parsing and verification helpers.
  • Delegation-chain validity as part of capability verification (walked via chio-core).
  • Stable, bindings-oriented error codes.

The Contract Does Not Own

  • Session state machines.
  • Remote HTTP or stream transports.
  • Auth discovery, OAuth, token exchange, token providers.
  • Task orchestration or nested callback routers.
  • Trust-control service clients.
  • Kernel execution runtime.

Public Surface

Each binding must expose the functions below under its language-native naming convention. The snake_case names used here are the canonical reference names from chio-binding-helpers.

Canonical JSON

  • canonicalize_json_str(json: string) -> string

RFC 8785 JSON Canonicalization Scheme. Object keys are sorted lexicographically by UTF-16 code unit. Numbers are emitted in ECMAScript Number.prototype.toStringform. No insignificant whitespace. Output is deterministic for any input that parses to the same JSON value.

Hashing

  • sha256_hex_bytes(bytes) -> string
  • sha256_hex_utf8(text: string) -> string

SHA-256 over the input, hex-encoded lowercase. The UTF-8 form hashes the bytes of the UTF-8 encoding of the string without a BOM.

Ed25519 Signing

  • is_valid_public_key_hex(hex): 64 lowercase hex characters.
  • is_valid_signature_hex(hex): 128 lowercase hex characters.
  • public_key_hex_matches(a, b): constant-time equality.
  • sign_utf8_message_ed25519(message, seed_hex) -> Utf8MessageSignature
  • verify_utf8_message_ed25519(message, signature, public_key_hex) -> bool
  • sign_json_str_ed25519(json, seed_hex) -> CanonicalJsonSignature
  • verify_json_str_signature_ed25519(json, signature, public_key_hex) -> bool

JSON signing canonicalizes the input before signing. Signing an already-canonical JSON string and signing its non-canonical equivalent must produce the same signature.

Receipts

  • parse_receipt_json(json) -> ChioReceipt
  • receipt_body_canonical_json(receipt) -> string
  • verify_receipt(receipt) -> ReceiptVerification
  • verify_receipt_json(json) -> ReceiptVerification

A receipt verifies when its canonical-body Ed25519 signature checks against the kernel key and the parameter hash in the receipt matches SHA-256 of the canonical action arguments.

Capabilities

  • parse_capability_json(json) -> CapabilityToken
  • capability_body_canonical_json(cap) -> string
  • verify_capability(cap, now: u64, max_delegation_depth: Option<u32>) -> CapabilityVerification
  • verify_capability_json(json, now: u64, max_delegation_depth: Option<u32>) -> CapabilityVerification

verify_capability takes the parsed token, the current Unix timestamp in seconds, and an optional maximum delegation depth. The returned CapabilityVerification carries signature_valid, delegation_chain_valid, time_valid, and a time_status of valid, not_yet_valid, or expired. The delegation-chain walk checks each parent-to-child signature and enforces attenuation between consecutive scopes up to max_delegation_depth.

rust
use std::time::{SystemTime, UNIX_EPOCH};

use chio_binding_helpers::{parse_capability_json, verify_capability};

let cap = parse_capability_json(&json)?;
let now = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
let max_delegation_depth = Some(8_u32);

let verification = verify_capability(&cap, now, max_delegation_depth)?;
assert!(verification.signature_valid);
assert!(verification.delegation_chain_valid);
assert!(verification.time_valid);

Signed Manifests

  • parse_signed_manifest_json(json) -> SignedManifest
  • signed_manifest_body_canonical_json(manifest) -> string
  • verify_signed_manifest(manifest) -> ManifestVerification
  • verify_signed_manifest_json(json) -> ManifestVerification

Delegation-chain and Merkle helpers are planned

Standalone exports such as verify_delegation_chain, check_attenuation, and merkle_proof_verify are not part of the current chio-binding-helpers surface. Today, delegation-chain validity is returned as a field of CapabilityVerification; direct chain and attenuation inspection lives in chio-core. Merkle inclusion-proof verification for receipt stores will land once the wire shape stabilises.

Input and Output Rules

Prefer:

  • JSON-string input for structured payloads.
  • UTF-8 string input for signed text helpers.
  • Byte-slice input only where byte identity is the point.
  • Explicit verification result structs (not raw booleans) when policy or receipt detail matters.

Avoid:

  • Exposing deep internal Rust types across the binding boundary.
  • Opaque handles unless they are genuinely reusable compiled objects.
  • Async APIs in the invariants layer.
  • Ownership-sensitive runtime state.

Stable Error Taxonomy

SDKs surface errors through a typed class that carries one of the snake_case error codes below. Depend on the code value, not on the Rust enum spelling or any message text.

CodeMeaning
invalid_public_keyPublic key hex is malformed or wrong length.
invalid_hexGeneric hex-decode failure.
invalid_signatureSignature hex is malformed or wrong length.
jsonJSON parse failure.
canonical_jsonRFC 8785 canonicalization refused the input.
capability_expiredCapability is past expires_at.
capability_not_yet_validCapability is before issued_at.
capability_revokedCapability appears in a revocation list.
delegation_chain_brokenA link in the delegation chain fails signature check.
attenuation_violationChild scope exceeds parent scope.
scope_mismatchRequested action not within the capability scope.
signature_verification_failedEd25519 verification returned false.
delegation_depth_exceededChain depth exceeds the per-binding limit.
invalid_hash_lengthA hash field is not 32 bytes.
merkle_proof_failedMerkle inclusion proof did not reproduce the root.
empty_treeMerkle operation requested on an empty tree.
invalid_proof_indexMerkle proof index is out of range.
empty_manifestSigned manifest has no tools.
duplicate_tool_nameSigned manifest contains two tools with the same name.
unsupported_schemaSchema identifier is unknown to this binding.
manifest_verification_failedManifest body signature failed to verify.

Cross-Language Conformance

The conformance harness lives in the chio monorepo. It ships a corpus of input vectors and expected outputs for every function above, plus a runner per language that compares the binding's output to the Rust reference byte for byte.

bash
$ cargo test -p chio-conformance          # Rust reference
$ cd packages/sdk/chio-ts && npm test      # TypeScript
$ cd packages/sdk/chio-py && pytest        # Python
$ cd packages/sdk/chio-go && go test ./...  # Go

The suite covers:

  • Canonical JSON for Unicode edge cases, nested objects, floats, and integer boundaries.
  • SHA-256 vectors across byte and UTF-8 inputs including non-BMP characters.
  • Ed25519 sign and verify with seeds from the RFC 8032 test vectors plus protocol-specific cases.
  • Receipt verification against signatures produced by the Rust kernel.
  • Capability verification and delegation chains of depth 0, 1, 3, and the depth limit.
  • Signed manifest verification over the spec fixtures.

Canonical JSON is non-negotiable

The single most common source of cross-language verification failures is non-conformant canonical JSON. Every binding must implement RFC 8785 to the letter: key sorting, no whitespace, ECMAScript number formatting, and exact handling of -0, infinities, and lone surrogates. If your binding is failing, start there.

Change Rules

The contract is frozen under the rules below. They exist so SDK work can proceed without the bindings layer turning into a second runtime.

  • New public entrypoints require an owning use case, a unit test, or both.
  • Changes that widen scope into transport or runtime behavior are rejected by default.
  • Error code removals or renames are breaking changes and require a major bump.
  • SDKs should consume helpers through this facade rather than reaching into chio-core or chio-manifest directly.

Versioning

The Bindings API follows semantic versioning. The current major version is 1. Patch releases add tests and fix bugs without changing the public surface. Minor releases add new helpers or new error codes without removing or renaming existing ones. Major releases are rare and are coordinated with an upgrade guide that walks every SDK through the change.

Deferred Work

A handful of directions are intentionally deferred until the package-backed remote-edge parity path is proven. They will only be picked up once the pure-TypeScript and pure-Python parity path is shipping cleanly in production.

  • chio-bindings-ffi: C ABI bindings for embedding in non-Rust hosts.
  • chio-bindings-wasm: WASM module with JS glue.
  • chio-native: Native-library companion to the pure-language SDKs.
  • Go CGO bridge work.
  • Policy compilation helpers beyond plain verification.

Per-Language SDK References

Bindings API · Chio Docs