Skip to content

feat(attestation): one canonical signed-request check and an opaque VerifiedWrite (aegis-2idcev) - #820

Merged
scbrown merged 2 commits into
mainfrom
malcolm/2idcev-verified-write
Oct 25, 2026
Merged

scbrown merged 2 commits into
mainfrom
malcolm/2idcev-verified-write

Conversation

@scbrown

@scbrown scbrown commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

Slice 1 of the receiver packet designed on aegis-2idcev (2026-10-14).

The canonical verifier was reachable only inside the HTTP middleware's
private verify, mixed with axum parsing, the route allowlist, identity
installation and finalization. It is now quipu::verified_write:

  • check_signed_request: the one check of a signed request's exact bytes:
    size bound, body hash computed from the bytes, the receiving store's own
    id as the v2 audience (never the envelope's claim), every binding check,
    and whether the nonce is already spent. The HTTP middleware calls it, so
    there is one verifier; HTTP behaviour is unchanged (its tests pass
    byte-unchanged).
  • verify_signed_write: additionally requires a store-audience-bound
    write-v2 envelope (no v1 downgrade) and an audited write route, and
    returns VerifiedWrite: private fields, read-only views, no public
    constructor, Clone, deserializer or conversion from Identity or
    PendingAttestation. It spends nothing and authorizes no effect; the
    writer-barrier dispatch is slice 2.

ATTESTED_PATHS and the body limit move to the library unchanged. No new
route or caller.

Tests: v2 positive with exact bytes, audience and unspent nonce; the same
signature over a different body, method, path or content type; signed for
another store (audience mismatch) and with the claim relabelled (badsig);
v1 refused by verify_signed_write but accepted by the core for HTTP; an
unaudited route; an oversize body; a spent nonce; another key; an empty
signature; an unregistered session; revocation. Five sabotages (v1
downgrade, route, size, audience from the envelope, spent read) each turn
a core test red. The HTTP write_attest tests stay green under the audience
and spent-read sabotages: they are v1-only, a pre-existing gap now covered
by the shared core's tests.

Gates (head 8b0e7a5, base d68a89a)

  • full default lib 2853/0 under the HOME-escape guard (clean; command exit 0); integration tests and bins pass; server --features full 241/0 (write_attest tests byte-unchanged)
  • clippy -D warnings -A missing-docs rc 0 for full and shacl,owl; wasm32 check PASS (module native-only)
  • fmt, file-size ratchet, witness re-hash of src/lib.rs, and all three Repository pendant source-control scripts (rdflib 7.6.0) PASS

Not in this PR: dispatch_verified_write (writer barrier, nonce settlement under the same lock, async identity isolation) is slice 2. Default-off; no runtime change.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BzgSY2LpdGhBhb7D1nHbiF

scbrown added a commit that referenced this pull request Oct 24, 2026
…cev)

The receiver's existing tests are v1-only, so a regression in the v2
audience or in settlement under the writer lock could not turn any of them
red (found while sabotaging #820's shared core). This drives the real
middleware verify and the writer-lock settle with quipu-write-v2:

- signed for this store: admitted;
- signed for another store: refused, audience mismatch;
- signed for another store with the claim relabelled to this one: badsig;
- valid at the pre-check, revoked while queued: refused at settlement as
  revoked, with the nonce left unspent.

Sabotages that now turn it red: the audience taken from the envelope, and
settlement that skips the revocation re-check (the queued-revocation
control the receiver design requires).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BzgSY2LpdGhBhb7D1nHbiF
scbrown and others added 2 commits October 24, 2026 17:32
…erifiedWrite (aegis-2idcev)

Slice 1 of the receiver packet designed on aegis-2idcev (2026-10-14).

The canonical verifier was reachable only inside the HTTP middleware's
private verify, mixed with axum parsing, the route allowlist, identity
installation and finalization. It is now quipu::verified_write:

- check_signed_request: the one check of a signed request's exact bytes:
  size bound, body hash computed from the bytes, the receiving store's own
  id as the v2 audience (never the envelope's claim), every binding check,
  and whether the nonce is already spent. The HTTP middleware calls it, so
  there is one verifier; HTTP behaviour is unchanged (its tests pass
  byte-unchanged).
- verify_signed_write: additionally requires a store-audience-bound
  write-v2 envelope (no v1 downgrade) and an audited write route, and
  returns VerifiedWrite: private fields, read-only views, no public
  constructor, Clone, deserializer or conversion from Identity or
  PendingAttestation. It spends nothing and authorizes no effect; the
  writer-barrier dispatch is slice 2.

ATTESTED_PATHS and the body limit move to the library unchanged. No new
route or caller.

Tests: v2 positive with exact bytes, audience and unspent nonce; the same
signature over a different body, method, path or content type; signed for
another store (audience mismatch) and with the claim relabelled (badsig);
v1 refused by verify_signed_write but accepted by the core for HTTP; an
unaudited route; an oversize body; a spent nonce; another key; an empty
signature; an unregistered session; revocation. Five sabotages (v1
downgrade, route, size, audience from the envelope, spent read) each turn
a core test red. The HTTP write_attest tests stay green under the audience
and spent-read sabotages: they are v1-only, a pre-existing gap now covered
by the shared core's tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BzgSY2LpdGhBhb7D1nHbiF
…cev)

The receiver's existing tests are v1-only, so a regression in the v2
audience or in settlement under the writer lock could not turn any of them
red (found while sabotaging #820's shared core). This drives the real
middleware verify and the writer-lock settle with quipu-write-v2:

- signed for this store: admitted;
- signed for another store: refused, audience mismatch;
- signed for another store with the claim relabelled to this one: badsig;
- valid at the pre-check, revoked while queued: refused at settlement as
  revoked, with the nonce left unspent.

Sabotages that now turn it red: the audience taken from the envelope, and
settlement that skips the revocation re-check (the queued-revocation
control the receiver design requires).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BzgSY2LpdGhBhb7D1nHbiF
@scbrown
scbrown force-pushed the malcolm/2idcev-verified-write branch from 324d957 to 1eef9dc Compare October 24, 2026 21:33
@scbrown

scbrown commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator Author

Head 1eef9dc (rebased onto main bb9254c; range-diff shows both commits =).

Added a_v2_signed_write_is_bound_to_this_store_and_settles_under_the_lock. It closes the v1-only gap in the HTTP receiver tests found by this PR's sabotages. Through the real verify and the writer-lock settle:

  • v2 signed for this store is admitted;
  • signed for another store is refused as an audience mismatch;
  • a relabelled audience claim fails as badsig;
  • a session revoked while queued is refused at settlement, with the nonce unspent.

Sabotages: taking the audience from the envelope, and settlement skipping the revocation re-check, now turn it red.

Gates: server 242/0 (pre-rebase); after the rebase, write_attest 7/7, verified_write 6/6, clippy full rc 0, file size and witnesses clean. Re-classified; fresh CI is owed.

@scbrown

scbrown commented Oct 25, 2026

Copy link
Copy Markdown
Collaborator Author

Non-author Ian — SOURCE APPROVE at 1eef9dc6b38544251d6fdc166d3ec0cfa2009577, base bb9254c249fccc64ca3f2168a870f00c4f8430f5. Reviewed all six changed paths after current complete-green/native admission. No blocking findings.

Native T2 INPUT 9591d9090ee88945219432baf2e16bd0af634a209722212f8c54260d0f4ad0e7; accepted CONTENT cc880dcfd23b55ee817e25d97dfec3a739756a5f44e3e326c383043a8ca83b46, reviewer ian.

Checked the extracted canonical verifier against the prior HTTP implementation: exact-byte hashing, receiving-store audience, binding validation and spent-nonce read remain shared; the HTTP adapter retains its route/identity/settlement barriers. VerifiedWrite has private owned fields and immutable views, no public constructor/Clone/deserializer, and no effect-dispatch caller in this slice. The repository witness matches src/lib.rs.

Validation: all six supplied core tests plus one independent valid-input ownership/no-write/no-spend control PASS. HOME guard inner 0, outer 0, clean. Exact-head CI job 120994068469 independently confirms the new HTTP v2 receiver/settlement control and existing HTTP controls passed; all five workflow parents are successful. Temporary reviewer test inclusion was restored exactly; checkout clean. No deployed-service or new dispatch-barrier acceptance claimed.

Landing constraint: do not use --delete-branch. #823 is stacked on this branch. Its author must retarget it to main after #820 lands, obtain full fresh CI and re-classify before its separate review. This approval does not cover #823 or waive operator holds/the normal merge helper.

@scbrown
scbrown merged commit 9fc5294 into main Oct 25, 2026
26 checks passed
@scbrown
scbrown deleted the malcolm/2idcev-verified-write branch October 25, 2026 01:20
@scbrown
scbrown restored the malcolm/2idcev-verified-write branch October 25, 2026 01:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant