Skip to content

test(attestation): write-v2 receiver controls end to end (aegis-2idcev) - #823

Merged
scbrown merged 1 commit into
mainfrom
malcolm/2idcev-receiver-controls
Oct 25, 2026
Merged

scbrown merged 1 commit into
mainfrom
malcolm/2idcev-receiver-controls

Conversation

@scbrown

@scbrown scbrown commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #820 (base malcolm/2idcev-verified-write). It changes tests only; no product code changes.

Why

An external signed-write client (an sd subprocess over HTTP) reaches quipu through the signed-write middleware. So the receiving service that must re-verify is that middleware, and an in-process dispatch would have no caller.

The existing write-v2 unit test stops at the pre-check and settles directly. The integration tests cover v2 audience refusal, but only before any settlement. Replay, concurrency and nonce durability are covered on v1 only.

What

New src/server/write_attest_v2_tests.rs, a child of the existing test module. Each test drives the full stack: pre-check, the real graph_create under the writer lock, then durable finalization.

test property
a_settled_v2_write_replays_nowhere_and_binds_its_path Once settled, the same bytes are replay at this store. A second store that trusts the same session refuses them as invalid (audience) and is not mutated. A signature for /knot sent to /graph/create is badsig.
concurrent_copies_of_one_v2_write_admit_exactly_one 16 racing copies: 1 created, 15 replay.
a_v2_write_that_fails_inside_the_lock_still_spends_its_nonce Handler error after the lock: nothing written, nonce spent, retry is replay.
the_lock_time_spend_alone_survives_a_failed_handler Durability layer 1 on its own: the handler is called directly, with no middleware finalization.
a_v2_write_refused_before_the_lock_is_finalized_by_the_middleware Durability layer 2 on its own: the body is rejected before any lock, and finalization alone spends the nonce.
a_v2_write_revoked_while_queued_is_refused_end_to_end Revoked between the pre-check and the lock: 401 revoked, nothing created, nothing spent.

Sabotage

Each sabotaged file was restored from a saved copy, and its sha256 was checked after the run.

sabotage red
lock-time nonce consume skipped (settle_on) concurrent v2, lock-time-alone, and the existing v1 concurrent test
finalization skipped on non-2xx (handle) refused-before-lock
audience taken from the envelope (check_signed_request) settled-replays-nowhere (the other-store arm), and the existing v2 unit test
revocation not re-checked at settlement revoked-end-to-end, and 2 existing tests
lock-time consume AND finalization both skipped additionally fails-inside-the-lock

The fails-inside-the-lock test stays green when either durability layer is removed alone. That is by design, since there are two independent layers, and the two single-layer tests cover each one.

Not sabotaged: the path-binding arm. A verifier that ignores the path also breaks the positive case, so no sabotage isolates that arm. Path binding stays covered by the canonical-message construction.

Gates

  • server unit suite 247 passed / 0 failed, under the HOME-escape guard (clean);
  • cargo clippy --all-targets -D warnings -A missing-docs rc 0 for full and shacl,owl;
  • fmt, file size and the repository pendant scripts pass.
  • The library suite is untouched by this diff; hosted CI is the authoritative full run.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BzgSY2LpdGhBhb7D1nHbiF

The DREAM adapter reaches quipu as an sd subprocess over HTTP, so the
canonical receiving service is the signed-write middleware, not an
in-process dispatch. The only v2 test stopped at the pre-check and settled
directly. These drive the full stack (pre-check, real graph_create under
the writer lock, durable finalization):

- a settled write replays nowhere: same store is replay; another store
  that trusts the session refuses on audience and is not mutated; a
  signature for another route is badsig;
- sixteen concurrent copies create exactly one;
- a handler failing inside the lock still spends its nonce, and each of
  the two durability layers is controlled on its own (lock-time spend
  with no finalization; finalization with no lock taken);
- a binding revoked while queued is a 401 with nothing created or spent.

Sabotage, each red: lock-time consume skipped; finalization skipped on
non-2xx; audience taken from the envelope; revocation not re-checked.

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-receiver-controls branch from ec8dca1 to 7cb6c37 Compare October 25, 2026 02:15
@scbrown
scbrown merged commit d6c403c into main Oct 25, 2026
24 checks passed
@scbrown
scbrown deleted the malcolm/2idcev-receiver-controls branch October 25, 2026 02:47
@scbrown
scbrown restored the malcolm/2idcev-receiver-controls branch October 25, 2026 02:48
@scbrown

scbrown commented Oct 25, 2026

Copy link
Copy Markdown
Collaborator Author

SOURCE APPROVE at 7cb6c37. Original full two-path source audit at ec8dca1 and shared middleware/fixture call-chain read retained. The six new controls exercise replay/audience/path, concurrency, failed-handler and finalization durability, and queued revocation. The direct-handler case deliberately isolates the shared lock-settlement layer; wire cases go through v2 middleware. Exact-head hosted controls are green; no local Cargo/runtime reproduction is claimed by this reviewer.

SAME qualification: both proposal blobs/modes are unchanged, and replaying the original whole binary patch reconstructs the entire refreshed tree. Automatic refresh reuse combined with diff-bound was refused; that refusal is retained. Fresh ordinary SAME review bound content943c accepted. Normal diff-bound preflight/execute merged d6c403c, predicted and actual integration tree1584 match; the whole inverse restores07f. Exact-main watch remains pending; no runtime acceptance.

The repository auto-deleted the source ref despite no delete flag. It was restored to the exact reviewed7cb head to preserve the stacked proposal. #824 remains open and was automatically retargeted to main; it still needs its own current CI and review.

@scbrown scbrown mentioned this pull request Oct 25, 2026
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