Vendor-neutral, evidence-grade conformance profiles for AI agents acting on physical-security systems.
Normative CDDL · Threat model · Related work · Offline verifier · RFP language · Reference producer · Report an issue
An AI agent that can view a camera stream or move a PTZ camera leaves a
signed, linked record of what it observed, what it inferred, what it was
authorized to do, what it attempted, whether the command was dispatched, and
what an observer saw happen. Anyone holding that bundle can check it offline,
with no vendor service, account, or network, and get a signed verdict. AAR is
the wire format, the conformance rules, and a free verifier for that record.
It is a stable experimental spec (v0.4.0: bundle wire v0.2 unchanged, verdict v0.4), implemented twice by one
operator, run against real cameras, and not yet adopted by anyone else.
git clone https://github.com/oneshot2001/aar && cd aar
python3 -B -m pyref verify kats/positive/bundle-valid-subset.cbor --at 1735689800Python 3.11+, standard library only. The verifier never reads the wall clock:
you supply the evaluation time. Output is a 20-step report and a signed
verdict; Result: conformant means every requested check passed for the
receipts in scope. Change one byte of the bundle and run it again.
TypeScript harness: bun run harness/verify.ts BUNDLE --at UNIX_SECONDS.
| Proves | Does not prove |
|---|---|
| Every artifact was signed by the key its credential names, and nothing was altered after emission | That a signer told the truth before signing (no compromised-signer immunity) |
| The action the agent attempted is bound to the authorization it cites, and refusals are affirmative evidence | That any inference was correct |
| The epoch's manifest, events, and anchor agree; a producer-declared epoch has not been truncated after the fact | That every action that happened was recorded (completeness is census-conditional, see D-72) |
Outcome claims carry their evidence grade; verified is barred without a named independent observer |
That a device_acknowledged outcome was independently sensed (all live runs so far are device-acknowledged) |
| The verdict bytes are reproducible by a second, clean-room implementation | Custody continuity or legal admissibility (D-71) |
| A relying party can check a bundle under its own root list and sign the verdict with its own key; the verdict binds that policy (D-83, v0.3) | That anything happened outside the instrumented enforcement point: a VMS console, a vendor app, or hands on the device leave no receipt, and the verdict says so (control_path_completeness: not_established, D-84) |
A delegation names the enforcement point that attempted under it, a rotation is signed by the retiring key's issuer, and revocation is judged at each signature's own time: receipts signed before revoked_at keep verifying, nothing signed at or after it passes (D-79..D-81) |
That the status authority's revoked_at instant is accurate (it is that authority's assertion) |
A carried receipt is listed by its own epoch's carried manifest; given epoch manifests the relying party kept from earlier bundles, every carried receipt of a kept epoch is listed there and a competing manifest or event is a fork (retained_manifest_membership: all_receipts_listed when every carried receipt is so listed, D-87) |
That the relying party held those bundles before any compromise, anything about an epoch it never kept, or that a manifest omits nothing; a sequence below the history it supplied is relayed (sequence_below_observed_history), not judged a rollback, because that history is what it observed, not a complete record. History is compared only after every check on the bundle itself: a bundle whose verifier key does not resolve reports key/not-found even if the history shows reuse, and history that contradicts a carried receipt is refused once the bundle passes step 9's coordinate type checks (a bundle that fails earlier is signed with that history bound) |
"Evidence-grade" in this repo means exactly the left column: attribution, post-emission tamper evidence, and anchored completeness over declared contents. Two further limits of the reference toolchain: the reference verdict is signed with a published test key so its bytes are reproducible (not an operational verifier identity), and the demo anchor log is same-operator (it demonstrates mechanics, not independent timestamping).
The v0.2.5 ontology is closed to two camera actions: camera.stream.view
and camera.ptz.preset, on VAPIX and via one VMS control path. Alert
disposition is specified but experimental; access control and data-access
actions (ALPR queries, video export) are not in this wire. That is a scoping
choice, stated so nobody has to discover it.
| Artifact | State |
|---|---|
| Wire | v0.4.0 — bundle wire v0.2 (unchanged since v0.2.5; normative CDDL at spec/aar-core.cddl), verdict v0.4 (v: 6: retained-epoch evidence, in-bundle manifest membership and one history phase after every intrinsic check, D-87; on v0.3's relying-party root ceiling and signing key, D-83, the control-path non-claim, D-84, and step-9 emission-identity precedence, D-86); five rc gates closed, exit bar re-run live against real cameras; delta since rc7 in spec/AUDIT-rc7-to-v0.2.0.md |
| Offline verifier | pyref — clean-room, Python stdlib only, no network, no wall clock |
| Second implementation | TypeScript harness (harness/) — generates the KAT corpus; byte-identical verdicts with pyref on the cross-implementation gate: every corpus row (550 after D-87: 478 plus 38 relying-party rows plus 19 D-86 and 14 D-87 stateful rows plus 1 fix-round row, a leading U+FEFF in a text field) and every fixture-pinned shape agree in both verifiers; shapes no fixture pins are not claimed (the full-corpus test in harness/crossimpl.test.ts runs un-skipped since D-82). The round-8 structural sweep (every member the kit can construct — 74 of 82 map productions, 2,184 effective shapes; the 51 skipped and the 3 kit-rewritten members are listed in the sweep table — mutated to null, list, int, text and bool) agreed in both; the two shapes verified by probe only (test-infrastructure gaps) and the members both verifiers tolerate are listed in the BACKLOG.md step-6 design item. History: parity audit |
| Conformance KATs | byte-pinned positive / negative / class-boundary / terminal-state fixtures in kats/ |
| Threat model | v0.1 — docs/threat-model-v0.1.md (30-finding adversarially challenged, gated) |
| Adapters | VAPIX live leg + one VMS control leg exercised at gate 5 (adapters/) |
| Reference producer | onvif-mcp — governed MCP server for cameras; AAR-vocabulary receipts today, wire conformance in progress |
Two clean-room codebases, one operator. Nobody outside this repo has run an emitter yet; that is the next thing this project needs, and the wire may still change in response to it.
Why the demand side is moving: the FBI Cyber Strategy (September 2026, Objective 4.4) commits the Bureau to "rapidly adopt agentic AI" and to "detect, divert, and deceive threat actors," with governance stated only as "human review and legal controls." An agent acting under legal authority needs a record that binds each consequential action to the person who authorized it and the scope they permitted, checkable by someone who does not trust the operator. That is the record this profile is for.
An emitter sits at the enforcement point between the agent and the device. It
commits an attempt before dispatch, journals durably, and exports bundles.
Start with demo/ep/README.md (the reference enforcement point and its
contract), then adapters/vapix/README.md or adapters/vms/README.md for a
translation leg. Procurement text that pins this version is in
docs/rfp-language-v0.2.md.
AAR provides attribution, post-emission tamper evidence, and tamper evidence over producer-declared epoch contents (completeness is census/reconciliation-conditional). It does not stop a compromised signer lying before emission, prove any inference correct, or establish legal compliance — see the threat model's residual-risk register for the complete honest list.
docs/— governing documents (spec, threat model, wire rubric, RFP model language, related work)spec/— normative CDDL + prose, gate records (v0.2 work product)kats/— byte-pinned known-answer tests + negative fixturesharness/— KAT generator + cross-verification harness (TypeScript)pyref/— free offline verifier (Python 3.11+, stdlib only)adapters/— VAPIX + VMS reference legsdemo/— sanitized end-to-end run evidence
Examiner package (custody profile v0.1): python3 -B -m pyref.examiner_package … packages one producer
bundle with the unchanged verifier's raw outputs, limits first, for a digital-evidence examiner to
re-run under their own key; it is not part of the verifier and adds no wire object. Spec, file formats
and failure behaviour: docs/custody-profile/examiner-package-v0.1.md.
Every tag runs, and must pass, scripts/release-check.sh:
bunx tsc --noEmit -p tsconfig.json # strict types across harness, demo, adapters
bun test harness # KATs, verifier, cross-impl bytes
python3 -B -m pyref.kat --slice all # pyref C1/C2 clean-room KATs
python3 -B -m pyref.schema_kat # CDDL oracle (Ruby cddl gem, pinned in pyref/README.md)
bun test demo/ep/wire-builder.golden.test.ts # demo bundles: pinned digests + two-verifier byte identity
bun test adapters # offline VAPIX + VMS legs through pyrefThe same script runs on every push and pull request (.github/workflows/release-check.yml).
Built with a two-model pipeline (one model plans and gates, another builds and
challenges); the gate records are published in spec/ deliberately, because
scrutiny is the hardening. Wire discipline: deterministic CBOR, closed
schemas, COSE_Sign1 ES256, strict first-failure, externally generated KATs.
The most useful things in spec/DECISIONS.md are the mistakes: D-56, D-60,
and D-73 each record a rule two implementations agreed on until an input the
corpus never covered showed the rule was incomplete.
"Receipt" is the field's term for this object (Notarized Agents, PCAA,
AgentBound; see docs/related-work-addendum-2026-08-28.md). The acronym
collides with "after-action report"; the name stays.
- Code (
pyref/,harness/,kats/,adapters/,demo/): Apache License 2.0 — seeLICENSE. - Specification text (
spec/,docs/prose and CDDL): CC BY 4.0 — seeLICENSE-SPEC.
Verifying receipts is free, forever, offline, with no account and no license from anyone. That property is load-bearing: an evidence format you cannot independently check is not an evidence format.