You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Design a real grain-authenticity (signing) story for Areev — and decide how far to take it — before anyone (human or AI assistant) tries to "finish" the dormant COSE scaffolding that already sits in areev-core.
This came up because an AI pair-programming session, working through a security review, was about to implement this and stopped after finding an explicit guardrail in the repo. Filing it as a real ticket so the decision gets made deliberately instead of by whoever next stumbles into the scaffolding.
Current state (verified against code)
crates/areev-core/CLAUDE.md says, verbatim:
The signing feature is referenced in code (serialize_grain_signed, crate::crypto::signing, coset) but there is no crypto module, dep, or feature declaration — dormant scaffolding for a future areev-crypto. Don't try to build it.
That's accurate:
crates/areev-core/src/format/serialize.rs (~lines 113-138) has serialize_grain_signed, #[cfg(feature = "signing")], with a detailed doc comment: it sets an is_signed flag (bit 0 of byte 1), recomputes the content hash over the blob with that flag set, then COSE-Sign1-wraps it with org_context bound into the AAD "to prevent cross-org replay attacks." This is a carefully designed shape, not a stub.
crates/areev-core/src/format/deserialize.rs (~lines 13-38) has unwrap_if_cose, which detects a COSE Sign1 envelope by its leading CBOR byte (0x84) and unwraps it — but explicitly does not verify the signature (doc comment: "no signature verification — use crypto::signing::verify_grain separately if verification is required").
Both reference crate::crypto::signing::* and the coset crate. Neither exists. There is no crypto module in areev-core, and coset is not a dependency anywhere in the workspace.
crates/areev-core/Cargo.toml (~lines 15-21) declares signing = [] as an empty feature, with the comment: "Dormant capability gates: the code carries #[cfg(feature = ...)] hooks for these but they are not wired up yet... enabling them is future work."
Net effect: turning the signing feature on today would fail to compile (the code paths reference things that don't exist). This is intentional scaffolding for a future crate, not a working feature with a flag someone forgot to flip.
Why it's not a quick finish (the three real blockers)
No trust model.docs/areev-governed-agents-proposal.md (~lines 674-678) ties real verification to a "host-configured author key" registry that doesn't exist yet: "When COSE signing lands (named dependency), the registry upgrades to signature verification against host-configured author keys." Without deciding who signs, how a host declares which authors/keys are trusted, and how rotation/revocation works, a signature check has nothing meaningful to check against.
The spec isn't finalized. Areev is positioned as the reference implementation of OMS. docs/cal-all-you-need-proposal.md (~lines 158-166) calls COSE signing "OMS §9 ... the high-assurance upgrade path, not v1" — i.e. the external spec hasn't settled the signing semantics. Areev's canonical serialization is deliberately frozen for exactly this class of risk (CLAUDE.md invariant deps: bump logos from 0.14.4 to 0.16.1 #2: changing it "silently changes every content address and breaks OMS conformance"). Building envelope details ahead of the spec risks the same failure mode later.
New dependency, core crate.coset would be the first crypto-format dependency in areev-core, the crate everything else in the workspace depends on — against the stated "dependency-light by policy... think twice before adding a dependency" stance (CLAUDE.md invariant deps: bump pyo3 from 0.29.0 to 0.29.2 #6).
A secondary, real-but-not-primary consideration: Areev gates releases on hard latency numbers (voice_loop's 50ms-cadence gate; a ~200µs recall gate referenced in docs/postgres-backend-proposal.md). Ed25519 (or similar) sign/verify at write- and import-time isn't free at scale on a bulk bundle import and would need to be benchmarked against crates/areev-store/examples/bench.rs before being made mandatory-by-default. This is not documented anywhere as the reason the feature was deferred — no rationale survives in git history (the repo's history is a single squashed "Initial commit: Areev 1.0.0," so the original design conversation isn't recoverable) — but it's a real cost worth planning for regardless of why the deferral happened.
What this closes
docs/security-model.md's "Known limitations in transit" section: "⚠️ Integrity, not authenticity. Content addressing detects corruption and tampering, but does not verify who authored a grain... Only sync with peers you trust." Real signing is what upgrades that from "detect tampering" to "verify provenance," and is the prerequisite docs/areev-governed-agents-proposal.md §7 names for the host code-approval registry to become signature-backed instead of hash-allowlist-only.
Options discussed (decide which to pursue)
Design now, build later (recommended starting point). Write an ARCHITECTURE.md §10 decision entry plus a concrete, scoped implementation plan: key management model (who signs, host-configured trusted-author config shape, rotation/revocation), the coset dependency addition, where verification wires into import/sync, and an explicit note on how this interacts with OMS §9 (build to the current draft with a documented migration path, or wait). No crypto code lands in this pass.
Build a minimal real version now. Stand up an actual areev-crypto module + coset dependency + real sign/verify, scoped narrowly (e.g. local areev verify / bundle import only, not the full trusted-author registry). Real capability sooner, but more surface area in one pass, and ahead of the OMS spec settling.
Skip full signing; close the gap a lighter way. Leave the COSE scaffolding untouched as documented future work, and instead strengthen what already exists — areev verify's hash-chain checking, areev audit export's tamper-evidence — as a stop-gap authenticity signal that's explicit about being weaker than real signatures, with no new dependency.
Acceptance criteria
A decision is recorded (ARCHITECTURE.md §10 entry at minimum) on which option to pursue and why.
If design-now: a scoped implementation plan exists that a future PR can execute directly, including the key-management shape and the OMS §9 relationship.
crates/areev-core/CLAUDE.md's "don't try to build it" gotcha is updated once a direction is chosen, so it stops being a trap for the next person (human or AI) who reads it.
Context
Surfaced during a conversational security/enterprise-readiness review. Related: #83
Summary
Design a real grain-authenticity (signing) story for Areev — and decide how far to take it — before anyone (human or AI assistant) tries to "finish" the dormant COSE scaffolding that already sits in
areev-core.This came up because an AI pair-programming session, working through a security review, was about to implement this and stopped after finding an explicit guardrail in the repo. Filing it as a real ticket so the decision gets made deliberately instead of by whoever next stumbles into the scaffolding.
Current state (verified against code)
crates/areev-core/CLAUDE.mdsays, verbatim:That's accurate:
crates/areev-core/src/format/serialize.rs(~lines 113-138) hasserialize_grain_signed,#[cfg(feature = "signing")], with a detailed doc comment: it sets anis_signedflag (bit 0 of byte 1), recomputes the content hash over the blob with that flag set, then COSE-Sign1-wraps it withorg_contextbound into the AAD "to prevent cross-org replay attacks." This is a carefully designed shape, not a stub.crates/areev-core/src/format/deserialize.rs(~lines 13-38) hasunwrap_if_cose, which detects a COSE Sign1 envelope by its leading CBOR byte (0x84) and unwraps it — but explicitly does not verify the signature (doc comment: "no signature verification — usecrypto::signing::verify_grainseparately if verification is required").crate::crypto::signing::*and thecosetcrate. Neither exists. There is nocryptomodule inareev-core, andcosetis not a dependency anywhere in the workspace.crates/areev-core/Cargo.toml(~lines 15-21) declaressigning = []as an empty feature, with the comment: "Dormant capability gates: the code carries#[cfg(feature = ...)]hooks for these but they are not wired up yet... enabling them is future work."signingfeature on today would fail to compile (the code paths reference things that don't exist). This is intentional scaffolding for a future crate, not a working feature with a flag someone forgot to flip.Why it's not a quick finish (the three real blockers)
docs/areev-governed-agents-proposal.md(~lines 674-678) ties real verification to a "host-configured author key" registry that doesn't exist yet: "When COSE signing lands (named dependency), the registry upgrades to signature verification against host-configured author keys." Without deciding who signs, how a host declares which authors/keys are trusted, and how rotation/revocation works, a signature check has nothing meaningful to check against.docs/cal-all-you-need-proposal.md(~lines 158-166) calls COSE signing "OMS §9 ... the high-assurance upgrade path, not v1" — i.e. the external spec hasn't settled the signing semantics. Areev's canonical serialization is deliberately frozen for exactly this class of risk (CLAUDE.mdinvariant deps: bump logos from 0.14.4 to 0.16.1 #2: changing it "silently changes every content address and breaks OMS conformance"). Building envelope details ahead of the spec risks the same failure mode later.cosetwould be the first crypto-format dependency inareev-core, the crate everything else in the workspace depends on — against the stated "dependency-light by policy... think twice before adding a dependency" stance (CLAUDE.mdinvariant deps: bump pyo3 from 0.29.0 to 0.29.2 #6).A secondary, real-but-not-primary consideration: Areev gates releases on hard latency numbers (
voice_loop's 50ms-cadence gate; a ~200µs recall gate referenced indocs/postgres-backend-proposal.md). Ed25519 (or similar) sign/verify at write- and import-time isn't free at scale on a bulk bundle import and would need to be benchmarked againstcrates/areev-store/examples/bench.rsbefore being made mandatory-by-default. This is not documented anywhere as the reason the feature was deferred — no rationale survives in git history (the repo's history is a single squashed "Initial commit: Areev 1.0.0," so the original design conversation isn't recoverable) — but it's a real cost worth planning for regardless of why the deferral happened.What this closes
docs/security-model.md's "Known limitations in transit" section: "docs/areev-governed-agents-proposal.md§7 names for the host code-approval registry to become signature-backed instead of hash-allowlist-only.Options discussed (decide which to pursue)
ARCHITECTURE.md§10 decision entry plus a concrete, scoped implementation plan: key management model (who signs, host-configured trusted-author config shape, rotation/revocation), thecosetdependency addition, where verification wires into import/sync, and an explicit note on how this interacts with OMS §9 (build to the current draft with a documented migration path, or wait). No crypto code lands in this pass.areev-cryptomodule +cosetdependency + real sign/verify, scoped narrowly (e.g. localareev verify/ bundle import only, not the full trusted-author registry). Real capability sooner, but more surface area in one pass, and ahead of the OMS spec settling.areev verify's hash-chain checking,areev audit export's tamper-evidence — as a stop-gap authenticity signal that's explicit about being weaker than real signatures, with no new dependency.Acceptance criteria
crates/areev-core/CLAUDE.md's "don't try to build it" gotcha is updated once a direction is chosen, so it stops being a trap for the next person (human or AI) who reads it.Context
Surfaced during a conversational security/enterprise-readiness review. Related: #83