Skip to main content

Crate car_bundle

Crate car_bundle 

Source
Expand description

Manifest format, canonicalization, and ed25519 signing for CAR contributed-agent bundles (Parslee-ai/car#182).

§Scope

This crate owns the on-disk shape and crypto primitives shared between the supervisor (loads + verifies installed agents), the CLI (publishes + signs new agents), and the registry (serves signed manifests). It is no-runtime — pure data, pure functions, no async, no I/O outside read_to_string for tests. The supervisor and CLI hold the I/O.

§Phase status

  • Phase 1 (car-registry): the manifest format landed inline at car_registry::manifest. The supervisor dual-reads legacy agents.json and the new ~/.car/agents/<id>/manifest.toml layout. Signature verification was stubbed out.
  • Phase 2 (this crate): types extracted here; ed25519 sign/verify added; manifest-level canonicalization landed. The supervisor wires verification with warn-but-not-reject semantics so existing setups keep working while operators sign their agents.
  • Phase 3+: full-bundle canonicalization (multi-file: identity.md, skills.jsonl, policies.json, …) per docs/agent-bundle-spec.md §canonicalization. Today’s canonical_manifest_bytes covers only the single manifest.toml file — sufficient for external_process bundles which carry no auxiliary data files.

Structs§

AgentIdentity
[agent] block.
AgentManifest
manifest.toml top-level structure. One file per installed agent at ~/.car/agents/<id>/manifest.toml.
CapabilityDeclarations
ExternalProcessTransport
LifecyclePolicy
PublisherInfo
[publisher] block. The signature field is the base64- encoded ed25519 signature over the canonicalized manifest (i.e., the manifest with publisher.signature cleared). key_id is the ed25519 public key, base64-encoded (32 bytes raw → 44 char base64).
RuntimeRequirements

Enums§

BundleError
RestartPolicy
Restart policy mirrors the supervisor’s surface. Re-declared here (rather than re-exported from car-registry) so this crate stays standalone — car-registry depends on car-bundle, not the other way around.
TransportSpec

Functions§

canonical_manifest_bytes
Produce canonical bytes of a manifest for signing / verification.
manifest_digest_hex
SHA-256 hex digest of the canonical manifest bytes. Useful for content-addressed lookups (registry caching, etc.) without requiring signature verification.
sha256_hex
SHA-256 hex digest of an arbitrary byte slice. Used by car install to verify binaries fetched via transport.binary_url against the manifest’s transport.sha256 (Parslee-ai/car#182 phase 5).
sign_manifest
Sign a manifest in place: writes the public key id into publisher.key_id, then serializes canonical bytes (which clear the signature but include the key_id), signs them with key, and writes the base64 signature into publisher.signature. Replaces any existing signature.
verify_detached
Verify a detached ed25519 signature over raw bytes against a base64-encoded 32-byte public key and base64-encoded 64-byte signature. Used to authenticate documents that aren’t manifests (e.g. the refreshable model catalog in car-inference): the source signs the exact file bytes, so no canonicalization is needed.
verify_sha256
Verify a byte slice matches a hex-encoded SHA-256 digest. Comparison is constant-time-ish (case-insensitive hex equality), and returns an error rather than a bool so the failure message can name the expected + actual digests.
verify_signature
Verify a manifest’s signature against the embedded publisher.key_id. Returns Ok(()) on success, Err(...) on any failure (missing publisher, malformed key, mismatched signature). A manifest with no publisher block is treated as unsigned and rejected — callers that want to accept unsigned manifests should not call this function.