Themes, not promises: dates are targets and slip when reality intervenes.
- boundary proxy with cap enforcement (
max_usd,max_tokens,max_model_calls,max_wall_seconds) - append-only hash-chained ledger, canonical JSON, RFC 6962 Merkle root
- receipts with embedded price table, usage inclusion proofs, limits disclosure
- offline
docket verify(Python) and an independent Node verifier, both bound to the committed conformance vectors - findings engine: runaway loops, uncached repeats, oversized context, denied calls, deny-write violations, premium-model leakage
- filesystem snapshots and diffs, egress decisions, SDK + raw-HTTP recording
- offline demo with a scripted provider, and a tamper demonstration
- zero runtime dependencies; format specification
docket/receipt/v1 - mutation testing of the cryptographic modules and the ledger (
tools/mutate.py), with every survivor classified as a gap or an equivalent mutant — scores indocs/testing.md
A concept-by-concept answer to the usual checklist (rate limiting, breakers, Kubernetes, Helm,
backpressure, exactly-once, p99, on-call, …) lives in
docs/production-coverage.md: what is implemented and tested, what is
recorded but not enforced, what is a validated artefact that has never been executed here, and what
is deliberately refused with a reason. The short version, as of this commit:
- per-call latency recorded, summarised under a stated rule, and recomputed by both verifiers
-
--port(a fixed loopback port an orchestrator can probe),--upstream NAME=URL(a mock, gateway or self-hosted model, recorded as evidence without its query string), and the boundary's/docket/healthz,/docket/readyz,/docket/metricsdocumented -
DOCKET_AGENT_MODE=backoff: full jitter, capped, honouringRetry-After— the client half of the rate-limit contract - a container recipe, a compose smoke test, a pod topology and a Helm chart, each checked
statically by
tools/deploy_check.py(16 checks) whose own tests break every invariant on purpose — and none of them executed, because no container runtime exists here - an invariant suite: one writer per ledger, 200 events from 8 threads, a replayed call recorded twice, a killed agent, a clock that lies
- load and endurance measured, not estimated:
make load(2,000 calls over 8 threads → 175.93 calls/s, client p50 44 ms) andmake soak(12,002 calls paced over ten minutes, 0 drops, receipt still verifying), with the boundary's memory measured at ≈1.1 KiB per recorded event — and a control run at half the duration showing the same per-event cost, so the growth is the event list rather than a leak. Reports indocs/measurements/2026-10-15-2core/; the harness refuses to call a run evidence when the client's count and the ledger disagree -
policy.denial_code: one reader for "the boundary refused this", shared by the reference agent and the load driver, which fixed a real defect (a provider's ownerror.codewas being read as a Docket refusal) and closed a 502 inRateLimiter(aDecimalrate used to fail inside the request;nansilently disabled the limiter)
-
docket init --from <framework>presets for Claude Code, Codex CLI, Gemini CLI, aider, OpenCode, and a generic HTTP profile. Each writes a policy that names the models that framework calls and prints the command that attaches it.tests/test_presets.pyloads every policy back through the real parser and runs five of them end to end against the scripted provider. - GitHub Action: run an agent step under a policy, upload the receipt as an artifact,
fail the job on a policy violation or an unverifiable receipt. The composite action lives
at
action.yml, withreceipt,exit-code,spend,calls,verifiedandcap-exceededas outputs.tests/test_action.pyexecutes its ownrun:blocks against a real supervised run — including the tampered-receipt and cap-fired paths — andtests/test_action_smoke.pycovers the scripted provider and smoke agent it depends on..github/workflows/action-smoke.ymlruns it in Actions on every push. -
docket watch— tail a live run with a spend meter, safe to leave on a second terminal. It follows a ledger file as a supervisor appends to it, prints each event with a running total costed against the same price table the boundary used, and stops onsession.endor after a quiet window, saying which. Nothing here talks to the boundary or a provider.tests/test_watch.pydrives it against a real supervised run in another thread. - receipt
--redactprofiles for circulating evidence externally (paths, argv, secrets).docket report --redact paths,argv,hosts,secretswrites a redacted receipt and ledger, re-chains the pair so it still verifies, records what it replaced under aredactionblock, and never touches the originals.tests/test_redact.pyasserts every profile on its own leaves a verifying pair, and that the strings a client should not see are absent from both files. - honest coverage: record provider responses the boundary saw without parsing them, so an
unknown provider is recorded rather than reduced to a guess about itself. Every
model.responseevent now carriesresponse_sha256over the exact bytes returned to the agent, and[evidence] record_responsesadditionally keeps a bounded copy of each body, named by that digest, in aresponsessub-directory of the run directory.docket verifyre-hashes every retained body, so one that was edited or deleted after the run fails. The point is the case Docket cannot read: a fourth usage-block shape has its tokens estimated from the response text, and that text used to be discarded, so the estimate could never be checked.tests/test_evidence_retention.pycovers the digest, truncation, the reserved-headroom boundary, a write that fails, the verifier's re-hash, and what--redactdoes with a path it cannot carry. - packaging:
tests/test_packaging.pyexecutes every install path the README names, against the version the tree declares rather than a literal, and skips with a stated reason when that version is not on PyPI yet rather than failing or pretending. Measured on 0.2.0:uv tool install docket-ai(uv 0.13.3),pipx install docket-ai(pipx 1.18.4) into a throwawayPIPX_HOME, and a cleanpython -m venvrunning the whole documented journey (init→run→verify). The pipx test resolves the binary from the directory pipx wrote to, not fromPATH: the previous version calledshutil.which("docket")and found whicheverdockethappened to be installed already, which is how it passed on a clean machine and failed on the release candidate. Still open: a Homebrew formula needs a tap repository and a released bottle, which is separate work and is not claimed here.
How this page is kept honest. Every [x] above is a claim that something exists, and a claim
about code that nothing checks is the same failure mode as a stale test count: it was true when
written and nobody noticed when it stopped being true. tests/test_roadmap.py walks every checked
box on this page and requires it to name a file, a command, or a measurement that exists in the
tree. An unchecked box is a plan; a checked box is a statement of fact, and it is held to one.
- Go verifier (single static binary, no dependencies). Shipped in 0.1.5:
verify-go/builds withgo build, passesgo vet,gofmtandgo test, and is one of the three implementations held to the 132-vector corpus. It was listed here as unshipped while all of that was true, which is the kind of stale row this page now has a guard against. - Rust verifier (crate + CLI) 💰
- TypeScript/browser verifier (verify a receipt by dropping it into a static page, fully client-side) 💰
-
docket verify --explain— for each failing check, the smallest thing you can do next - verifier conformance kit: vectors + a runner any implementation can point at, published with a compatibility table
- a public "verify this receipt" static demo page (no upload; the file never leaves the browser)
- signed receipts by default in CI contexts (
Ed25519, key from env or OS keychain) - transparency-log anchoring: optional append of a receipt digest to a public log (RFC 6962-style, generic — the goal is a trusted timestamp, never a blockchain) 💰
- witness co-signing: a second party countersigns a receipt without seeing contents
- multi-run attestations: "these 200 receipts all verify against this key" for procurement
-
docket diffsemantics for policy changes: what a stricter cap would have done to last week's traffic (retrospective enforcement) 💰
- format frozen with a compatibility promise and a published deprecation policy 💰
- security-fix window for the previous major, stated in months, not vibes 💰
- documented disaster story: what to do when a receipt fails to verify in production
- case studies from regulated-industry adopters (published with their consent)
- A hosted service. There will be no Docket Cloud; the promise is that evidence need not pass through anyone's account.
- A dashboard. Rendering is someone else's product; Docket emits receipts, JSON and Markdown. Dashboards subscribe to the ledger format.
- A sandbox. Containers, gVisor, seccomp and hypervisors are better at enforcement than a user-space tool; Docket records and bounds, and says so.
- Prompt/content recording by default. Evidence that requires storing what people typed will not be the default, whatever it would cost to make it a feature.
- Blockchain anything. A transparency log needs witnesses and hashing, not tokens.