8000 feat(bep): record a revocation when a live box is destroyed (T20) by minimal-foundry[bot] · Pull Request #2548 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

feat(bep): record a revocation when a live box is destroyed (T20) - #2548

Merged
norrietaylor merged 17 commits into
mainfrom
agent/2277-record-a-revocation-when-a-live-box-is-destroyed
Oct 25, 2026
Merged

norrietaylor merged 17 commits into
mainfrom
agent/2277-record-a-revocation-when-a-live-box-is-destroyed

Conversation

@minimal-foundry
@minimal-foundry minimal-foundry Bot commented Oct 25, 2026 •
Copy link
Copy Markdown
Contributor

T20 — Record a revocation when a live box is destroyed and refuse its values within a minute

slice: S1
kind: task
covers: BEP-043, BEP-067, BEP-071
size: L
est: 380 code, 440 tests
executor: agent
difficulty: needs care
model: strongest
diagnostics: min box audit <box> shows the box's revocation record and each later refusal of its values
observability: one info log line per revocation recorded, naming the box id; one warn line when a destroy completes with the proxy unreachable
layers:
- proxy:
- crates/bep/src/revoke.rs (new): revocations by box id, consulted before any resolution (BEP-071)
- crates/bep/src/control.rs: takes mint and revocation submissions and appends them to the one log
- crates/bep/src/lib.rs: module line
test: cargo nextest run -p bep prop_revocation_covers_exactly_its_box
test: cargo nextest run -p bep revoked_value_never_triggers_renewal
- client:
- crates/minimal/src/mint.rs: submits a mint record per member
- crates/minvmd/src/box_registry.rs: on a live box's destroy submits its revocation and sends forget_box over the control socket, so the proxy attributes the id to no live box (T41, #2483), completing the destroy when the proxy is down
- crates/bep/src/main.rs: drops the box-egress interim from the bep serve startup warning and the wire comment if T14 has not already, since this task is the destroy half of that flip
test: cargo nextest run -p minimal mint_and_destroy_append_audit_records
- e2e:
- scripts/session-e2e.sh: adds two cases
test: ./scripts/session-e2e.sh bep_destroyed_box_values_refused_within_60s
test: ./scripts/session-e2e.sh bep_destroy_with_proxy_down_refuses_by_attachment
produces:
- crates/bep/src/revoke.rs
consumes:
- crates/bep/src/control.rs
- crates/minimal/src/mint.rs
proof: After min session destroy web, a value copied from web is refused within a minute, even if the proxy was down.
depends on:
- blocked by #2271
- blocked by #2273
- blocked by #2276

Proof

After min session destroy web, minvmd sends revoke_box for web's box id to the proxy. The proxy puts the revocation in force at once and appends one revocation record, which min box audit web shows. Later requests that carry web's sealed value are refused before any sign-in is resolved or renewed. With the proxy down, the destroy still completes, minvmd logs one warning, and the withdrawn attachment refuses the value. On this branch, the two bep tests and the minimal test show this in code. The two e2e cases that show it on a live macOS host are written, but they recorded NOT RUN on this Linux box.

Notes from the agent: The e2e cases recorded NOT RUN here because bep_live_gate needs macOS, gvproxy and a GitHub sign-in. The macOS lane still owes that evidence. The decision checks cross_box before revoked, so a value copied into another box is refused as cross_box even with a revocation in force. For that reason the e2e case checks two things: the revocation record in web's audit within 60 s, and the refusal. The revoked marker itself is proved by revoked_value_never_triggers_renewal. Changes in tests.rs: the mint tests and their stub control servers live there, so the new test went there, and the two stub servers got match arms for the new record_mint and revoke_box requests. minvmd: the revocation runs on a thread of its own, so the destroy never waits, and the stop path (withdraw_where) sends none, because the spec says that reaping a stopped box is not a revocation. minvmd also gets a unit test, destroy_revocation_sends_revoke_then_forget (passes). In unit tests the registry has no proxy socket (cfg!(test)). Its builder is with_proxy_control. Outside the layers and not changed: the doc comments in crates/bep/src/redeemer.rs (lines ~107-113 and ~170) still say that nothing writes revocations until T20. They are now out of date. Revocations recorded before a proxy start are not restored: that is T33 (#2290), and the bep serve warning says so…[truncated]

Tests

line exit tail
cargo nextest run -p bep prop_revocation_covers_exactly_its_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-01d1... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 13.46s ──────────── Nextest run ID 0d11ebb9-5281-498c-8de7-67d3ae2fe325 with nexte
cargo nextest run -p bep revoked_value_never_triggers_renewal 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-9889... Finished 'test' profile [unoptimized] target(s) in 0.30s ──────────── Nextest run ID 3e87623a-a4f9-473c-9a30-9ee5561bd979 with nextest profile: default Starting 1 test across 2
cargo nextest run -p minimal mint_and_destroy_append_audit_records 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-6171... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc
./scripts/session-e2e.sh bep_destroyed_box_values_refused_within_60s 0 the 'min' and 'minimald' under /work/build-cache/target/debug report different versions; rebuilding the pair no usable 'min' and 'minimald' pair on PATH or under target/; building the pair this run drives (cargo build --locked -p minimal --bin min -p minimald --bin minimald) built the pair: /work/bu
./scripts/session-e2e.sh bep_destroy_with_proxy_down_refuses_by_attachment 0 ::group::min session destroy with the proxy down: the destroy completes, and the value is refused bep_destroy_with_proxy_down_refuses_by_attachment: NOT RUN (the Box Egress Proxy runs on macOS only) ::endgroup:: session e2e: 1 case(s) NOT RUN: bep_destroy_with_proxy_down_refuses_by_attachment sessio

Verify

min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.97.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

hange's
Applying loadouts: default
Running task runtime-implement-verify in session task-runtime-implement-verify-446e...
    Checking rustls-webpki v0.103.16
    Checking opentelemetry v0.33.1
    Checking args v0.0.1 (/workbench/crates/args)
    Checking ot v0.0.1 (/workbench/crates/ot)
    Checking paths v0.0.1 (/workbench/crates/paths)
   Compiling version v0.8.0 (/workbench/crates/version)
    Checking rustls v0.23.46
    Checking opentelemetry_sdk v0.33.1
    Checking tracing-opentelemetry v0.34.0
    Checking opentelemetry-appender-tracing v0.33.1
    Checking switch v0.0.1 (/workbench/crates/switch)
   Compiling minvmd v0.8.0 (/workbench/crates/minvmd)
    Checking opentelemetry-proto v0.33.0
   Compiling stdlib v0.0.22 (/workbench/crates/stdlib)
    Checking tokio-rustls v0.26.5
    Checking rustls-platform-verifier v0.7.0
    Checking hyper-rustls v0.27.9
    Checking tonic v0.14.6
   Compiling serial_test_derive v4.0.1
    Checking bep v0.0.1 (/workbench/crates/bep)
    Checking reqwest v0.13.5
    Checking tonic-prost v0.14.6
    Checking diagnostics v0.0.1 (/workbench/crates/diagnostics)
    Checking google-cloud-auth v1.17.0
    Checking opentelemetry-http v0.33.1
    Checking serial_test v4.0.1
    Checking opentelemetry-otlp v0.33.0
    Checking google-cloud-gax-internal v0.7.20
    Checking async-dialog v0.0.1 (/workbench/crates/async-dialog)
    Checking wait-timeout v0.2.1
    Checking mlog v0.0.1 (/workbench/crates/mlog)
    Checking rusty-fork v0.3.1
    Checking proptest v1.12.0
    Checking google-cloud-longrunning v1.14.0
    Checking google-cloud-iam-v1 v1.13.0
    Checking google-cloud-lro v1.11.0
    Checking google-cloud-storage v1.20.0
    Checking common v0.0.1 (/workbench/crates/common)
    Checking boxes v0.0.1 (/workbench/crates/boxes)
    Checking sandbox v0.0.1 (/workbench/crates/sandbox)
    Checking minimald-rpc v0.0.1 (/workbench/crates/minimald-rpc)
    Checking mfile v0.0.1 (/workbench/crates/mfile)
    Checking checkouts v0.0.1 (/workbench/crates/checkouts)
    Checking decode v0.0.1 (/workbench/crates/decode)
error: using `chunks_exact` with a constant chunk size
   --> crates/minimald-rpc/src/trace.rs:199:46
    |
199 |     for (byte, pair) in out.iter_mut().zip(s.chunks_exact(2)) {
    |                                              ^^^^^^^^^^^^^^^
    |
help: consider using `as_chunks::<2>()` instead
   --> crates/minimald-rpc/src/trace.rs:199:46
    |
199 |     for (byte, pair) in out.iter_mut().zip(s.chunks_exact(2)) {
    |                                              ^^^^^^^^^^^^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#chunks_exact_to_as_chunks
    = note: `-D clippy::chunks-exact-to-as-chunks` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::chunks_exact_to_as_chunks)]`

error: could not compile `minimald-rpc` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...

Base

The base branch moved while the coder worked and was merged in before the tests ran. These files changed on BOTH sides since the branch point — read them first, because a rewrite from a stale reading can undo a merge without a conflict:

  • crates/bep/src/control.rs
  • crates/minimal/src/mint.rs
  • crates/minimal/src/tests.rs

Out of scope

Layer exception

The task's layers were widened on 2026-10-25 in the plan comment and in #2277: crates/minimal/src/tests.rs (the mint tests and their stub control servers live there), crates/bep/src/redeemer.rs (arch C2 and C3), crates/minvmd/src/cmd/run.rs (the supervisor start path sets the proxy control socket through with_proxy_control, review finding 4369790164), crates/bep/src/proxy.rs (AuditWriter::try_write reports an append failure so a lost revocation record is never silent, review finding 4369863226), and crates/bep/src/lib.rs (the one mod revoke; line; it left the layer list on 2026-10-25 so the task stays within the runtime's ten-file cap). Each is required by the task's own proof and is accepted under the epic owner's layer-exception rule, so the PR is not a draft for them.

These files are outside the task's layers:, so this PR is a draft:

  • crates/minimal/src/tests.rs

Residuals

Closes #2277


Generated by Claude Code

The control socket takes record_mint and revoke_box. Both append to the
proxy's one audit log, and a revocation goes into the set the redeemer
reads, so a revoked box's values are refused before any resolution
(BEP-043, BEP-067, BEP-071). bep serve wires the set and the log.
After the client key registration, the client sends record_mint for
each grant it minted, so the proxy appends a mint record to its audit
log. A failed record is a warning and the mint stands.
When the creator withdraws a live box with a credentialed lane,
minvmd sends revoke_box and then forget_box to the Box Egress Proxy
control socket, on a thread of its own. The destroy does not wait. With
the proxy unreachable it logs one warning, and the withdrawn attachment
refuses the box's values.
Two live proxy cases: with the proxy up, min box audit shows the
destroyed box's revocation record within 60 s, and the copied value is
refused. With the proxy down, the destroy completes, minvmd warns, and
the value is refused after the proxy returns.
…evocation-when-a-live-box-is-destroyed

# Conflicts:
#	crates/bep/src/control.rs
@coderabbitai
coderabbitai Bot commented Oct 25, 2026 •
Copy link
Copy Markdown
Contributor

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 43b4e583-9364-45df-b972-fdb645580193

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@minimal-foundry
minimal-foundry Bot commented Oct 25, 2026 •
Copy link
Copy Markdown
Contributor Author

Reviewed: no findings; approval withheld, 2 threads unresolved at 20f42cf9cf32.

APPROVE withheld: 2 unresolved threads — minimal-arch[bot] scripts/session-e2e.sh:12095, minimal-arch[bot] scripts/session-e2e.sh:12165. Resolving the last thread releases the approval on this head.

Resolve the open threads. Resolving the last one releases the approval on this head; no new review is required.

Clobber: none seen in the changed hunks.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — advisory review

Verdict COMMENT — 3 findings, 3 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread crates/minvmd/src/box_registry.rs Resolved
Comment thread crates/bep/src/main.rs Resolved
Comment thread crates/minvmd/src/box_registry.rs Resolved
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: CONDITIONS · 3 conditions · the full ruling

The revocation path is in the right owner, and it does what Gatehouse §6.10 line 839 requires. minvmd revokes a live box at its destroy, the proxy is the log's one writer, and a revoked value is refused before any renewal. Three items stay open. Run the two e2e legs on the macOS lane (C1), because both print NOT RUN. Correct the interim comments in crates/bep/src/redeemer.rs that say nothing writes a revocation (C2). Make the redeemer use revoke::in_force_for, so the BEP-071 property proves the redemption path (C3).

Ruled at dff3308 against gominimal/arch@109541a48c31 by claude-opus-5-5.

Comment thread scripts/session-e2e.sh Resolved
Comment thread crates/bep/src/revoke.rs Resolved
Comment thread crates/bep/src/main.rs Resolved
The connect-site inventory test failed in CI because the new
mint_and_destroy_append_audit_records test opens a proxy control
socket that the inventory did not list.
@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — advisory review

Verdict COMMENT — 1 finding, 1 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread crates/minvmd/src/box_registry.rs Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 1 of 10 on a failed check suite, pushed as b75eb971d44d.

line exit tail
cargo nextest run -p bep prop_revocation_covers_exactly_its_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-31b5... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 13.50s ──────────── Nextest run ID b8e521f1-7437-490f-9295-85da9b7343fc with nexte
cargo nextest run -p bep revoked_value_never_triggers_renewal 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-2418... Finished 'test' profile [unoptimized] target(s) in 0.26s ──────────── Nextest run ID 4beee9c3-3787-4a3f-bd4c-2866c213ae2c with nextest profile: default Starting 1 test across 2
cargo nextest run -p minimal mint_and_destroy_append_audit_records 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-5838... Compiling ot v0.0.1 (/workbench/crates/ot) Compiling args v0.0.1 (/workbench/crates/args) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc
./scripts/session-e2e.sh bep_destroyed_box_values_refused_within_60s 0 no usable 'min' and 'minimald' pair on PATH or under target/; building the pair this run drives (cargo build --locked -p minimal --bin min -p minimald --bin minimald) built the pair: /work/build-cache/target/debug/min and /work/build-cache/target/debug/minimald ::group::min session destroy: a value
./scripts/session-e2e.sh bep_destroy_with_proxy_down_refuses_by_attachment 0 ::group::min session destroy with the proxy down: the destroy completes, and the value is refused bep_destroy_with_proxy_down_refuses_by_attachment: NOT RUN (the Box Egress Proxy runs on macOS only) ::endgroup:: session e2e: 1 case(s) NOT RUN: bep_destroy_with_proxy_down_refuses_by_attachment sessio

Verify min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.97.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

the sandbox ran rustc (1.98.1), the repository pins 1.97.0 in rust-toolchain.toml; a failure here may be the newer toolchain's, not this change's
Applying loadouts: default
Running task runtime-implement-verify in session task-runtime-implement-verify-22e2...
    Checking args v0.0.1 (/workbench/crates/args)
    Checking ot v0.0.1 (/workbench/crates/ot)
    Checking paths v0.0.1 (/workbench/crates/paths)
   Compiling version v0.8.0 (/workbench/crates/version)
    Checking switch v0.0.1 (/workbench/crates/switch)
   Compiling minvmd v0.8.0 (/workbench/crates/minvmd)
   Compiling stdlib v0.0.22 (/workbench/crates/stdlib)
    Checking bep v0.0.1 (/workbench/crates/bep)
    Checking common v0.0.1 (/workbench/crates/common)
    Checking mlog v0.0.1 (/workbench/crates/mlog)
    Checking diagnostics v0.0.1 (/workbench/crates/diagnostics)
    Checking async-dialog v0.0.1 (/workbench/crates/async-dialog)
    Checking boxes v0.0.1 (/workbench/crates/boxes)
    Checking sandbox v0.0.1 (/workbench/crates/sandbox)
    Checking minimald-rpc v0.0.1 (/workbench/crates/minimald-rpc)
    Checking mfile v0.0.1 (/workbench/crates/mfile)
    Checking checkouts v0.0.1 (/workbench/crates/checkouts)
    Checking decode v0.0.1 (/workbench/crates/decode)
    Checking graph v0.0.1 (/workbench/crates/graph)
error: using `chunks_exact` with a constant chunk size
   --> crates/minimald-rpc/src/trace.rs:199:46
    |
199 |     for (byte, pair) in out.iter_mut().zip(s.chunks_exact(2)) {
    |                                              ^^^^^^^^^^^^^^^
    |
help: consider using `as_chunks::<2>()` instead
   --> crates/minimald-rpc/src/trace.rs:199:46
    |
199 |     for (byte, pair) in out.iter_mut().zip(s.chunks_exact(2)) {
    |                                              ^^^^^^^^^^^^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#chunks_exact_to_as_chunks
    = note: `-D clippy::chunks-exact-to-as-chunks` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::chunks_exact_to_as_chunks)]`

error: could not compile `minimald-rpc` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...

After min session destroy web, the proxy records a revocation for web and refuses a value copied from web within a minute, even when the proxy was down at destroy time. This round makes the tests check pass again, so CI can show that result.

Notes from the agent: The CI tests failure was minimal's tests::every_daemon_connection_is_classified. The new mint_and_destroy_append_audit_records test opens a proxy control socket, and the connect-site inventory did not list it. I added the entry with a comment. Before the fix, one run of cargo nextest run -p bep -p minimal -p minvmd showed this test as the only failure. ci-linux-native-success is the lane aggregator, so it failed only because tests failed. I did not run the two scripts/session-e2e.sh lines because this box has no /dev/kvm.

@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: CONDITIONS · 2 conditions · the full ruling

The code conforms to Gatehouse §6.10 line 839. The creator in minvmd records the revocation at the destroy of a live box. The proxy is the only writer of the log, and a revoked value is refused before any resolution. Two items stay open. The interim notes in crates/bep/src/redeemer.rs still say that nothing writes a revocation until T20, and this PR is T20 (C1). Both BEP-043 e2e legs recorded NOT RUN, so the T0 proof is open. Run them on the macOS lane at this head (C2).

Outside the diff

  • crates/bep/src/redeemer.rs:107: C1 · This interim note is now false. bep serve records revocations through revoke_box (main.rs wire). Rewrite it to name only the T33 restore-on-start (#2290) as the open interim and its flip. Make the same change at lines 223–224 in facts.

Ruled at b75eb97 against gominimal/arch@109541a48c31 by claude-opus-5-5.

Comment thread scripts/session-e2e.sh Resolved
Comment thread scripts/session-e2e.sh Resolved
Copy link
Copy Markdown
Member

/revise

Round 2 of #2548, on the arch ruling at dff3308 and the review findings left open. No round is in flight. T20's layers were widened on 2026-10-25: crates/minimal/src/tests.rs (the mint tests and stub servers live there) and crates/bep/src/redeemer.rs are in the task now, so none of this is out of layers. Arch C1, the two macOS end-to-end cases (bep_destroyed_box_values_refused_within_60s, bep_destroy_with_proxy_down_refuses_by_attachment), needs a live proxy and a GitHub sign-in on the Apple Silicon runner; the epic owner runs that leg by hand under the manual-only stance, so leave thread 4369578234 open and the two cases recorded NOT RUN with that reason.

  1. Arch C2 (thread 4369578241): in crates/bep/src/redeemer.rs, rewrite the interim in the BoxRedeemer::new doc comment (lines 107-113) and the facts-gathering doc comment (lines 223-224): revoke_box on the control socket puts a revocation in force (crate::revoke::record), and the one interim left is the empty set at start until T33 (T33 — Rotate audit segments with the chain carried across and revocations restored #2290) restores it.
  2. Arch C3 (thread 4369578237): in crates/bep/src/redeemer.rs lines 301-305, build revoked as crate::revoke::in_force_for(&set, &box_id) (cloned into a Vec<String>) in place of a clone of the whole set, so redeem::decide reads only the revocations that cover this value and prop_revocation_covers_exactly_its_box proves the filter the redemption path uses; keep Check::Revoked and its order in decide unchanged.
  3. Review findings 4369576612 and 4369576616 (withdraw_client_box and spawn_revocation in crates/minvmd/src/box_registry.rs) and 4369576614 (Revocations in crates/bep/src/main.rs): answer each from the code, fix what is real, and say why where it is not.
  4. Reply on each thread naming the commit and resolve the ones the commit fixes.

One or two commits, Conventional Commits subjects, body lines at most 100 characters.


Generated by Claude Code

Build the revoked set with revoke::in_force_for for the box id the value
names, so decide reads only the revocations that cover it. The doc
comments now say that revoke_box puts a revocation in force, and that
the empty set at start is the one interim left until #2290.
@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — advisory review

Verdict COMMENT — 5 findings, 5 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread crates/minvmd/src/box_registry.rs Resolved
Comment thread crates/minvmd/src/box_registry.rs Resolved
Comment thread crates/bep/src/control.rs Resolved
Comment thread crates/minvmd/src/box_registry.rs Resolved
Comment thread crates/bep/src/control.rs Resolved
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling

The change conforms to Gatehouse §6.10 line 839. The destroy of a live box records one revocation in the proxy's single audit log. The redeemer reads only the revocations for the value's own box id. With the proxy down, the destroy completes and the withdrawn attachment refuses the values. Both BEP-043 e2e cases recorded NOT RUN, and NOT RUN is not a pass. C1 asks the macOS lane to record both cases as passed on this head.

Ruled at 1ff95e4 against gominimal/arch@109541a48c31 by claude-opus-5-5.

Comment thread scripts/session-e2e.sh Resolved
Comment thread scripts/session-e2e.sh Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 2 of 10 on a /revise note, pushed as 1ff95e43185c.

line exit tail
cargo nextest run -p bep prop_revocation_covers_exactly_its_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-9cc2... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 15.69s ──────────── Nextest run ID 683af8d8-9817-4e2c-ac7c-3c355786969c with nexte
cargo nextest run -p bep revoked_value_never_triggers_renewal 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-5cb1... Finished 'test' profile [unoptimized] target(s) in 0.27s ──────────── Nextest run ID 010e8b21-b9d1-4004-84e3-a31bb3cfbe9b with nextest profile: default Starting 1 test across 2
cargo nextest run -p minimal mint_and_destroy_append_audit_records 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-2f4c... Compiling ot v0.0.1 (/workbench/crates/ot) Compiling args v0.0.1 (/workbench/crates/args) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc
./scripts/session-e2e.sh bep_destroyed_box_values_refused_within_60s 0 no usable 'min' and 'minimald' pair on PATH or under target/; building the pair this run drives (cargo build --locked -p minimal --bin min -p minimald --bin minimald) built the pair: /work/build-cache/target/debug/min and /work/build-cache/target/debug/minimald ::group::min session destroy: a value
./scripts/session-e2e.sh bep_destroy_with_proxy_down_refuses_by_attachment 0 ::group::min session destroy with the proxy down: the destroy completes, and the value is refused bep_destroy_with_proxy_down_refuses_by_attachment: NOT RUN (the Box Egress Proxy runs on macOS only) ::endgroup:: session e2e: 1 case(s) NOT RUN: bep_destroy_with_proxy_down_refuses_by_attachment sessio

Verify min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.97.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

cking boxes v0.0.1 (/workbench/crates/boxes)
    Checking json-subscriber v0.3.1
    Checking bcrypt-pbkdf v0.11.0
    Checking ssh-cipher v0.3.0
    Checking ed25519-dalek v3.0.0
    Checking sha3 v0.11.0
    Checking generic-array v0.14.7
    Checking p384 v0.14.0
    Checking p521 v0.14.0
    Checking opentelemetry-appender-tracing v0.33.1
    Checking hash32 v0.3.1
    Checking module-lattice v0.2.3
    Checking kem v0.3.0
    Checking data-encoding v2.11.1
    Checking sponge-cursor v0.1.0
    Checking ml-kem v0.3.2
    Checking heapless v0.9.3
    Checking ssh-key v0.7.0-rc.11
    Checking sha3 v0.12.0
    Checking mlog v0.0.1 (/workbench/crates/mlog)
    Checking generic-array v1.4.4
    Checking russh-cryptovec v0.62.0
    Checking num-bigint v0.5.1
    Checking russh-util v0.52.0
    Checking bitflags v1.3.2
    Checking hex-literal v1.1.0
    Checking managed v0.8.0
    Checking constcat v0.6.1
    Checking tinyvec_macros v0.1.1
    Checking smoltcp v0.14.0
    Checking tinyvec v1.12.0
    Checking minimald-rpc v0.0.1 (/workbench/crates/minimald-rpc)
    Checking russh v0.64.1
    Checking is_executable v1.0.6
    Checking switch v0.0.1 (/workbench/crates/switch)
    Checking clap_complete v4.6.11
    Checking hickory-proto v0.26.3
    Checking sysinfo v0.39.6
   Compiling minvmd v0.8.0 (/workbench/crates/minvmd)
    Checking hashbrown v0.14.5
    Checking serde_bytes v0.11.19
    Checking netlink-packet-core v0.8.1
    Checking dashmap v6.2.1
    Checking konst_macro_rules v0.2.19
   Compiling stdlib v0.0.22 (/workbench/crates/stdlib)
    Checking russh-sftp v2.4.0
    Checking konst v0.2.20
    Checking mfile v0.0.1 (/workbench/crates/mfile)
    Checking netlink-sys v0.8.8
    Checking const_format v0.2.36
    Checking derive_builder v0.20.2
    Checking nix v0.30.1
    Checking netlink-packet-route v0.25.1
    Checking procfs-core v0.18.0
    Checking hash32 v0.2.1
    Checking itertools v0.15.0
    Checking generational-arena v0.2.9
    Checking spin v0.9.9
    Checking strum v0.27.2
    Checking decode v0.0.1 (/workbench/crates/decode)
error: using `chunks_exact` with a constant chunk size
   --> crates/minimald-rpc/src/trace.rs:199:46
    |
199 |     for (byte, pair) in out.iter_mut().zip(s.chunks_exact(2)) {
    |                                              ^^^^^^^^^^^^^^^
    |
help: consider using `as_chunks::<2>()` instead
   --> crates/minimald-rpc/src/trace.rs:199:46
    |
199 |     for (byte, pair) in out.iter_mut().zip(s.chunks_exact(2)) {
    |                                              ^^^^^^^^^^^^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#chunks_exact_to_as_chunks
    = note: `-D clippy::chunks-exact-to-as-chunks` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::chunks_exact_to_as_chunks)]`

error: could not compile `minimald-rpc` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...

Review threads the coder judged:

  • 👎 invalid — crates/minvmd/src/box_registry.rs:4501: Deliberate, per BEP-043: destroying a live box is the one revocation event. withdraw_where serves a box end report, the creation reconcile and the past-bound sweep. Those end or stop a box, and its creation goes dormant and is not destroyed. BEP-043's note says a stopped box's values are refused by
  • 👍 valid — scripts/session-e2e.sh:12090: The finding holds: both macOS cases are still NOT RUN. They need a live proxy and a GitHub sign-in on the Apple Silicon runner, and the epic owner runs that leg by hand. No code change in this round.
  • 👍 valid — crates/bep/src/revoke.rs:98: In 1ff95e4, BoxRedeemer::facts builds revoked with crate::revoke::in_force_for, keyed on the box id the opened value names. Check::Revoked and its order in decide did not change.
  • 👍 valid — crates/bep/src/main.rs:945: In 1ff95e4, the BoxRedeemer::new and facts doc comments now say that revoke_box puts a revocation in force (crate::revoke::record). They say the empty set at start is the one interim left, until T33 (T33 — Rotate audit segments with the chain carried across and revocations restored #2290).
  • 👎 invalid — crates/minvmd/src/box_registry.rs:4500: Deliberate, per the spec. BEP-043's sub-requirement says a destroy the proxy cannot record completes, and the withdrawn attachment refuses the box's values. The design notes reject a client-side queue because it protects nothing the withdrawal does not. Restore from the audit log at start is T33 (Cycle detection #2
  • 👍 valid — scripts/session-e2e.sh:12090: The finding holds: bep_destroyed_box_values_refused_within_60s is NOT RUN on this head. It needs the hand-run macOS leg with a live proxy and a GitHub sign-in. No code change in this round.
  • 👍 valid — scripts/session-e2e.sh:12157: The finding holds: bep_destroy_with_proxy_down_refuses_by_attachment is NOT RUN on this head. It needs the hand-run macOS leg. No code change in this round.

After min session destroy web, minvmd sends revoke_box and forget_box to the proxy. The redeemer refuses a value copied from web as revoked, using the same revoke::in_force_for filter that the property test proves. If the proxy is down, the destroy still completes, and the withdrawn attachment refuses web's values. The two macOS end-to-end cases that show this on a live proxy are NOT RUN on this head.

Notes from the agent: Round 2 changes only crates/bep/src/redeemer.rs (commit 1ff95e4). C3: the revoked set is now built with crate::revoke::in_force_for. The filter key is the box id the value opened under (Unsealed::Opened box_id), not the source's box id. For a host_ip cohort member these two ids are different, and decide compares against the value's id. A value that did not open gets an empty set, because decide refuses it before it reads the set. C2: both doc comments are rewritten as the directive asks. NOT RUN: ./scripts/session-e2e.sh bep_destroyed_box_values_refused_within_60s and ./scripts/session-e2e.sh bep_destroy_with_proxy_down_refuses_by_attachment. Both need a live proxy and a GitHub sign-in on the Apple Silicon runner, and the epic owner runs that leg by hand. Finding 4369576614 (Revocations in crates/bep/src/main.rs) is named in the note but is not in the unresolved-thread list, so its text is not available to me. The wiring in main.rs shares one Revocations set between Control::with_revocations and BoxRedeemer::with_revocations, and I found nothing to change there. The directive asks me to resolve threads. My instructions do not let me do that, so I resolved none.

…evocation-when-a-live-box-is-destroyed

# Conflicts:
#	crates/bep/src/control.rs
#	crates/bep/src/main.rs
Each control request now has its own connection, so forget_box is sent
when revoke_box is refused or times out. The warn line names the step
that failed. bep's handle_line now refuses record_mint and revoke_box,
since it keeps no record, and the minimal stubs answer those two.
@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — advisory review

Verdict COMMENT — 2 findings, 2 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread crates/minvmd/src/box_registry.rs Resolved
Comment thread crates/minvmd/src/box_registry.rs Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

A merge of main before round 3, not counted against the cap (1 of 3), pushed as 97ccc6e8a0ba.

Resolved conflicts in: crates/bep/src/control.rs, crates/bep/src/main.rs

line exit tail
cargo nextest run -p bep prop_revocation_covers_exactly_its_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-a5aa... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 12.13s ──────────── Nextest run ID 4e995663-cdc8-4611-9832-7924ef93fe16 with nexte
cargo nextest run -p bep revoked_value_never_triggers_renewal 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-9a92... Finished 'test' profile [unoptimized] target(s) in 0.26s ──────────── Nextest run ID 9c822f2f-bbb9-4050-84e5-54f57bd9f8a4 with nextest profile: default Starting 1 test across 2
cargo nextest run -p minimal mint_and_destroy_append_audit_records 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-7139... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc
./scripts/session-e2e.sh bep_destroyed_box_values_refused_within_60s 0 no usable 'min' and 'minimald' pair on PATH or under target/; building the pair this run drives (cargo build --locked -p minimal --bin min -p minimald --bin minimald) built the pair: /work/build-cache/target/debug/min and /work/build-cache/target/debug/minimald ::group::min session destroy: a value
./scripts/session-e2e.sh bep_destroy_with_proxy_down_refuses_by_attachment 0 ::group::min session destroy with the proxy down: the destroy completes, and the value is refused bep_destroy_with_proxy_down_refuses_by_attachment: NOT RUN (the Box Egress Proxy runs on macOS only) ::endgroup:: session e2e: 1 case(s) NOT RUN: bep_destroy_with_proxy_down_refuses_by_attachment sessio

Verify min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.97.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

the sandbox ran rustc (1.98.1), the repository pins 1.97.0 in rust-toolchain.toml; a failure here may be the newer toolchain's, not this change's
Applying loadouts: default
Running task runtime-implement-verify in session task-runtime-implement-verify-f719...
    Checking ot v0.0.1 (/workbench/crates/ot)
    Checking args v0.0.1 (/workbench/crates/args)
    Checking paths v0.0.1 (/workbench/crates/paths)
   Compiling version v0.8.0 (/workbench/crates/version)
    Checking switch v0.0.1 (/workbench/crates/switch)
   Compiling minvmd v0.8.0 (/workbench/crates/minvmd)
   Compiling stdlib v0.0.22 (/workbench/crates/stdlib)
    Checking common v0.0.1 (/workbench/crates/common)
    Checking bep v0.0.1 (/workbench/crates/bep)
    Checking diagnostics v0.0.1 (/workbench/crates/diagnostics)
    Checking mlog v0.0.1 (/workbench/crates/mlog)
    Checking boxes v0.0.1 (/workbench/crates/boxes)
    Checking sandbox v0.0.1 (/workbench/crates/sandbox)
    Checking async-dialog v0.0.1 (/workbench/crates/async-dialog)
    Checking minimald-rpc v0.0.1 (/workbench/crates/minimald-rpc)
    Checking mfile v0.0.1 (/workbench/crates/mfile)
    Checking decode v0.0.1 (/workbench/crates/decode)
    Checking checkouts v0.0.1 (/workbench/crates/checkouts)
    Checking graph v0.0.1 (/workbench/crates/graph)
    Checking lcache v0.0.1 (/workbench/crates/lcache)
    Checking rcache v0.0.1 (/workbench/crates/rcache)
error: using `chunks_exact` with a constant chunk size
   --> crates/minimald-rpc/src/trace.rs:199:46
    |
199 |     for (byte, pair) in out.iter_mut().zip(s.chunks_exact(2)) {
    |                                              ^^^^^^^^^^^^^^^
    |
help: consider using `as_chunks::<2>()` instead
   --> crates/minimald-rpc/src/trace.rs:199:46
    |
199 |     for (byte, pair) in out.iter_mut().zip(s.chunks_exact(2)) {
    |                                              ^^^^^^^^^^^^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#chunks_exact_to_as_chunks
    = note: `-D clippy::chunks-exact-to-as-chunks` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::chunks_exact_to_as_chunks)]`

error: could not compile `minimald-rpc` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...

Review threads the coder judged:

  • 👍 valid — PRRT_kwDOPdfcxM6v-eVg: Valid in part. submit_revocation now sends forget_box on its own connection even when revoke_box fails or times out, so the proxy attributes the id to no live box. A test pins this. I did not add the queue: the spec rejects a client queue, because the withdrawn attachment (NET-133) already refuses t (not posted on the thread: not an open thread on the pull request)
  • 👎 invalid — crates/minvmd/src/box_registry.rs:4534: The spec rules on this. BEP-043's sub-requirement completes the destroy and refuses through the withdrawn attachment when the proxy records no revocation. The rationale rejects a client queue because it protects nothing the withdrawal does not. Revocations that survive a proxy restart are T33 (T33 — Rotate audit segments with the chain carried across and revocations restored #2290
  • 👎 invalid — PRRT_kwDOPdfcxM6v-eVk: The in-memory set is the declared interim until T33 (T33 — Rotate audit segments with the chain carried across and revocations restored #2290) restores revocations at start, and the bep serve startup warning says so. AuditWriter::write returns (), so control.rs has no write result to check. Write failures are handled inside the writer. The set changes first on purpose, so no reque (not posted on the thread: not an open thread on the pull request)
  • 👍 valid — crates/minvmd/src/box_registry.rs: spawn_revocation now matches on the outcome of each request. The warn says 'without a revocation' only when revoke_box failed. A forget_box failure after a recorded revocation has its own line. Each line carries the request's error.
  • 👍 valid — PRRT_kwDOPdfcxM6v-eVo: handle_line now refuses record_mint and revoke_box with 'this handler keeps no revocation and writes no record'. The two minimal test stubs answer those two ops themselves. (not posted on the thread: not an open thread on the pull request)
  • 👎 invalid — scripts/session-e2e.sh:12090: No code change answers this. This round ran on a Linux box with no /dev/kvm, so the case is NOT RUN again. The macOS lane must run bep_destroyed_box_values_refused_within_60s against this head and record the result.
  • 👎 invalid — scripts/session-e2e.sh:12157: No code change answers this. This round ran on a Linux box with no /dev/kvm, so the case is NOT RUN again. The macOS lane must run bep_destroy_with_proxy_down_refuses_by_attachment against this head and record the result.

After min session destroy web, minvmd sends revoke_box and then forget_box to the proxy, each on its own connection. A value copied from web is refused through the revocation. If the proxy refuses or misses the revocation, the forget and the withdrawn attachment still refuse it. The e2e proof of the 60-second refusal is not run on this box.

Notes from the agent: Conflict round: control.rs and main.rs conflicted with main's signing-CA rotation (with_rotation, RotationRequest in serve). I kept both sides. Control keeps its Records and also carries the rotation into serve. main.rs calls .control(&control, log).with_rotation(ca). Committed as the merge. bep suite passes (159). Extra checks: cargo nextest run -p minvmd destroy_ (3 passed, includes the new destroy_forgets_the_box_when_the_revocation_is_refused), -p minimal mint (13 passed). NOT RUN: ./scripts/session-e2e.sh bep_destroyed_box_values_refused_within_60s and ./scripts/session-e2e.sh bep_destroy_with_proxy_down_refuses_by_attachment. This Linux box has no /dev/kvm and is not macOS, so it cannot boot the microVM. The macOS or linux-kvm lane still owes that evidence. The spec rejects a client-side revocation queue (spec rationale: 'holding the record in the client would add a queue that protects nothing the withdrawal does not'), so I did not add one.

@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling

The compare conforms to Gatehouse §6.10 line 839. A failed revoke_box no longer stops forget_box, and handle_line refuses the two requests it cannot record. The work that stays open is the e2e evidence. Both e2e cases recorded NOT RUN on Linux, and NOT RUN is not a pass. Run them on the macOS lane at this head, as C1 says. Restore at start stays with #2290.

Ruled at 97ccc6e against gominimal/arch@109541a48c31 by claude-opus-5-5.

Comment thread scripts/session-e2e.sh Resolved
Copy link
Copy Markdown
Member

/revise

Round 3 of #2548, on the two review findings opened at 97ccc6e. No round is in flight. Arch C1, the two macOS end-to-end cases (bep_destroyed_box_values_refused_within_60s, bep_destroy_with_proxy_down_refuses_by_attachment, threads 4369693955 and 4369693958), is the epic owner's run under the manual-only stance; leave those threads open and the two cases recorded NOT RUN with that reason. The disputed finding on the one-shot revocation (4369692369) is accepted under BEP-043 and resolved.

  1. Finding 4369790159 (crates/minvmd/src/box_registry.rs line 2906): the doc comment that describes impl Clone for BoxRegistry ("A clone shares the live rows...") now attaches to the PROXY_CONTROL_SOCKET const. Move the two consts and spawn_revocation's block above that doc comment, or move the doc comment back onto the impl Clone, so each comment documents its own item.
  2. Finding 4369790164 (BoxRegistry::new lines 3097-3101): do not read cfg!(test). Default proxy_control to None in new, and set the home-directory socket where the daemon builds its registry, through with_proxy_control (which has no caller today), so an integration test or any other build of new never sends a revocation to a developer's running proxy; pin with a test that new() sends none and a check that the daemon's start path sets it.
  3. Reply on each thread naming the commit and resolve the ones the commit fixes.

One commit, Conventional Commits subject, body lines at most 100 characters.


Generated by Claude Code

BoxRegistry::new no longer reads cfg!(test). It sets no proxy control socket, so a test's or
any other build's registry never sends a revocation to a developer's running proxy.
The supervisor's start path builds its registry through supervisor_registry, which 
8
sets the
10BC8

home-directory socket with with_proxy_control.

Move the Clone doc comment back onto impl Clone for BoxRegistry, below the new consts and
spawn_revocation.

Tests: new_registry_sends_no_revocation, supervisor_registry_sends_revocations_to_the_home_proxy.
@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approval withheld

Verdict COMMENT — APPROVE withheld: 6 unresolved threads — minimal-arch[bot] scripts/session-e2e.sh:12090, minimal-arch[bot] scripts/session-e2e.sh:12157, minimal-arch[bot] scripts/session-e2e.sh:12090, minimal-foundry[bot] crates/minvmd/src/box_registry.rs:4554, minimal-foundry[bot] crates/minvmd/src/box_registry.rs:2922, …. No findings.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 6 of 10 on a /revise note, pushed as f5e53bf293f0.

line exit tail
cargo nextest run -p bep prop_revocation_covers_exactly_its_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-55e4... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 12.11s ──────────── Nextest run ID 48c383c4-41cb-43cc-ba2d-a0811f5ad7c2 with nexte
cargo nextest run -p bep revoked_value_never_triggers_renewal 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-7cf0... Finished 'test' profile [unoptimized] target(s) in 0.25s ──────────── Nextest run ID 8afc77b8-d5be-4df7-ab97-bbc906312a4a with nextest profile: default Starting 1 test across 2
cargo nextest run -p minimal mint_and_destroy_append_audit_records 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-e0f6... Compiling ot v0.0.1 (/workbench/crates/ot) Compiling args v0.0.1 (/workbench/crates/args) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc
./scripts/session-e2e.sh bep_destroyed_box_values_refused_within_60s 0 no usable 'min' and 'minimald' pair on PATH or under target/; building the pair this run drives (cargo build --locked -p minimal --bin min -p minimald --bin minimald) built the pair: /work/build-cache/target/debug/min and /work/build-cache/target/debug/minimald ::group::min session destroy: a value
./scripts/session-e2e.sh bep_destroy_with_proxy_down_refuses_by_attachment 0 ::group::min session destroy with the proxy down: the destroy completes, and the value is refused bep_destroy_with_proxy_down_refuses_by_attachment: NOT RUN (the Box Egress Proxy runs on macOS only) ::endgroup:: session e2e: 1 case(s) NOT RUN: bep_destroy_with_proxy_down_refuses_by_attachment sessio

Verify min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.97.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

ng libcgroups v0.7.0
    Checking path-absolutize v4.0.1
    Checking route_manager v0.2.13
    Checking args v0.0.1 (/workbench/crates/args)
    Checking tun-rs v2.8.8
    Checking postcard v1.1.3
    Checking serial_test v4.0.1
    Checking common v0.0.1 (/workbench/crates/common)
    Checking close_fds v0.3.2
    Checking caps v0.5.6
    Checking sendfd v0.4.4
    Checking boxes v0.0.1 (/workbench/crates/boxes)
    Checking castaway v0.2.4
    Checking strum v0.28.0
    Checking hakoniwa v1.7.2 (https://github.com/souk4711/hakoniwa.git?rev=0810ffa37620ef5c57de263c8eaa1f4d7633c14a#0810ffa3)
    Checking compact_str v0.9.1
    Checking signal-hook v0.3.18
    Checking unicode-truncate v2.0.1
    Checking kasuari v0.4.12
    Checking sandbox v0.0.1 (/workbench/crates/sandbox)
    Checking pem v4.0.0
    Checking yasna v0.6.0
    Checking lru v0.18.2
    Checking compression-core v0.4.33
    Checking minimald-rpc v0.0.1 (/workbench/crates/minimald-rpc)
    Checking mfile v0.0.1 (/workbench/crates/mfile)
    Checking size v0.5.0
    Checking rcgen v0.14.10
    Checking ratatui-core v0.1.2
    Checking compression-codecs v0.4.45
    Checking decode v0.0.1 (/workbench/crates/decode)
    Checking checkouts v0.0.1 (/workbench/crates/checkouts)
    Checking signal-hook-mio v0.2.5
    Checking derive_more v2.1.1
    Checking tagptr v0.2.0
    Checking graph v0.0.1 (/workbench/crates/graph)
    Checking crossterm v0.29.0
    Checking moka v0.12.16
    Checking lcache v0.0.1 (/workbench/crates/lcache)
    Checking async-compression v0.4.50
    Checking async-tar v0.6.1
    Checking rcache v0.0.1 (/workbench/crates/rcache)
    Checking line-clipping v0.3.8
    Checking object v0.40.0
    Checking ratatui-widgets v0.3.2
    Checking op v0.0.1 (/workbench/crates/op)
    Checking bep v0.0.1 (/workbench/crates/bep)
    Checking ratatui-macros v0.7.2
    Checking orchestrator v0.0.1 (/workbench/crates/orchestrator)
    Checking check v0.0.1 (/workbench/crates/check)
    Checking diagnostics v0.0.1 (/workbench/crates/diagnostics)
    Checking ratatui-crossterm v0.1.2
error: using `chunks_exact` with a constant chunk size
   --> crates/minimald-rpc/src/trace.rs:199:46
    |
199 |     for (byte, pair) in out.iter_mut().zip(s.chunks_exact(2)) {
    |                                              ^^^^^^^^^^^^^^^
    |
help: consider using `as_chunks::<2>()` instead
   --> crates/minimald-rpc/src/trace.rs:199:46
    |
199 |     for (byte, pair) in out.iter_mut().zip(s.chunks_exact(2)) {
    |                                              ^^^^^^^^^^^^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#chunks_exact_to_as_chunks
    = note: `-D clippy::chunks-exact-to-as-chunks` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::chunks_exact_to_as_chunks)]`

error: could not compile `minimald-rpc` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...

Outside the task's layers::

  • crates/bep/src/lib.rs

Converted to a draft: something above needs a person before review.

Review threads the coder judged:

  • 👎 invalid — crates/minvmd/src/box_registry.rs:2922: BEP-043 makes the revocation send one-shot on purpose. The destroy completes, and the withdrawn attachment (NET-133) refuses the box's values in the redemption path in crates/bep/src/redeemer.rs. The spec rationale rejects a queue on the client side. Restore at start is the filed residual T33 (T33 — Rotate audit segments with the chain carried across and revocations restored #2290
  • 👎 invalid — crates/minvmd/src/box_registry.rs:4554: In production only withdraw_expired_detached reaches withdraw_where. A live client row always has a standing creation (register_client_box_as refuses a held name), so the expiry makes the creation dormant, and resume_client_box brings the box back under the same id. A revocation refuses that id for

After min session destroy web, a value copied from web is refused within a minute, even if the proxy was down. This round adds no new behaviour. It pins that a box's expiry leaves it resumable and sends the proxy no revocation.

Notes from the agent: Round 6. Finding 4369995984 is invalid, and the code shows why. In production only withdraw_expired_detached reaches withdraw_where. The public withdraw has callers only in tests. A live client row always has a standing creation, because register_client_box_as refuses a name a live row holds (NameAlreadyHeld). So withdraw_where makes that creation dormant (creation_rowless), and resume_client_box can bring the box back under the same box id. A revocation refuses that id for good (BEP-071). A revocation at expiry will then refuse the values of the resumed box. BEP-043 makes the destroy of a live box the one revocation event, and its rationale says the withdrawn attachment refuses a stopped box's values. Commit f5e53bf adds no revocation. It adds a doc paragraph on withdraw_where and the test expired_credentialed_box_sends_no_revocation_and_stays_resumable, which pins the expiry path. Thread 4369995982 stays as ruled: spawn_revocation's retry behaviour is unchanged, per the directive. The two session-e2e.sh cases are NOT RUN: they are macOS microVM cases, and they are the epic owner's run under the manual-only stance. The C1 and C2 threads stay open for that reason. Clippy on minvmd showed one warning, in minimald-rpc, which is outside this diff.

@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling

The compare conforms to Gatehouse §6.10 line 839. When a detached box expires, its creation becomes dormant and the creator can resume it. So the expiry is not a destroy, and minvmd correctly sends no revocation. BEP-043, BEP-067 and BEP-071 conform in code. Both live e2e legs recorded NOT RUN, so C1 stays open: record PASS for both on the macOS lane, or file an issue for them. Restore at start remains the T33 residual (#2290).

Ruled at f5e53bf against gominimal/arch@109541a48c31 by claude-opus-5-5.

Comment thread scripts/session-e2e.sh Resolved
Comment thread scripts/session-e2e.sh Resolved
@minimal-foundry
minimal-foundry Bot marked this pull request as draft October 25, 2026 07:54
@norrietaylor
norrietaylor marked this pull request as ready for review October 25, 2026 08:03
…evocation-when-a-live-box-is-destroyed

# Conflicts:
#	scripts/session-e2e.sh
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling

This head merges main into the branch. The PR's own changes are the same as at f5e53bf2, and the earlier ruling stands. Revocation on a live destroy, exact-id coverage and the shared audit log conform to Gatehouse §6.10 line 839. The two macOS e2e legs still record NOT RUN, so the 60 s bound (§6.10 line 823) has no live proof. Run both cases on the macOS lane and record them as passed (C1). Restore at start stays a residual for T33 (#2290).

Ruled at 74e011b against gominimal/arch@109541a48c31 by claude-opus-5-5.

Comment thread scripts/session-e2e.sh Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

A merge of main before round 7, not counted against the cap (2 of 3), pushed as 74e011bbb9ab.

Resolved conflicts in: scripts/session-e2e.sh

line exit tail
cargo nextest run -p bep prop_revocation_covers_exactly_its_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-52ac... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 18.25s ──────────── Nextest run ID 7b1b418b-bb17-4f32-ae65-b7ef4b45ccce with nexte
cargo nextest run -p bep revoked_value_never_triggers_renewal 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-3874... Finished 'test' profile [unoptimized] target(s) in 0.36s ──────────── Nextest run ID f60e4956-6b93-4fec-8ca0-672b33bb42f1 with nextest profile: default Starting 1 test across 2
cargo nextest run -p minimal mint_and_destroy_append_audit_records 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-2876... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling paths v0.0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc
./scripts/session-e2e.sh bep_destroyed_box_values_refused_within_60s 0 the 'min' and 'minimald' under /work/build-cache/target/debug report different versions; rebuilding the pair no usable 'min' and 'minimald' pair on PATH or under target/; building the pair this run drives (cargo build --locked -p minimal --bin min -p minimald --bin minimald) built the pair: /work/bu
./scripts/session-e2e.sh bep_destroy_with_proxy_down_refuses_by_attachment 0 ::group::min session destroy with the proxy down: the destroy completes, and the value is refused bep_destroy_with_proxy_down_refuses_by_attachment: NOT RUN (the Box Egress Proxy runs on macOS only) ::endgroup:: session e2e: 1 case(s) NOT RUN: bep_destroy_with_proxy_down_refuses_by_attachment sessio

Verify min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.97.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

.0
    Checking ssh-cipher v0.3.0
    Checking ed25519-dalek v3.0.0
    Checking generic-array v0.14.7
    Checking sha3 v0.11.0
    Checking boxes v0.0.1 (/workbench/crates/boxes)
    Checking p521 v0.14.0
    Checking p384 v0.14.0
    Checking opentelemetry-appender-tracing v0.33.1
    Checking hash32 v0.3.1
    Checking module-lattice v0.2.3
    Checking kem v0.3.0
    Checking sponge-cursor v0.1.0
    Checking data-encoding v2.11.1
    Checking ml-kem v0.3.2
    Checking sha3 v0.12.0
    Checking heapless v0.9.3
    Checking mlog v0.0.1 (/workbench/crates/mlog)
    Checking ssh-key v0.7.0-rc.11
    Checking generic-array v1.4.4
    Checking russh-cryptovec v0.62.0
    Checking num-bigint v0.5.1
    Checking russh-util v0.52.0
    Checking constcat v0.6.1
    Checking hex-literal v1.1.0
    Checking bitflags v1.3.2
    Checking tinyvec_macros v0.1.1
    Checking managed v0.8.0
    Checking russh v0.64.1
    Checking tinyvec v1.12.0
    Checking smoltcp v0.14.0
    Checking minimald-rpc v0.0.1 (/workbench/crates/minimald-rpc)
    Checking is_executable v1.0.6
    Checking switch v0.0.1 (/workbench/crates/switch)
    Checking hickory-proto v0.26.3
    Checking clap_complete v4.6.11
    Checking sysinfo v0.39.6
   Compiling minvmd v0.8.0 (/workbench/crates/minvmd)
    Checking hashbrown v0.14.5
    Checking serde_bytes v0.11.19
    Checking netlink-packet-core v0.8.1
   Compiling stdlib v0.0.22 (/workbench/crates/stdlib)
    Checking dashmap v6.2.1
    Checking konst_macro_rules v0.2.19
    Checking russh-sftp v2.4.0
    Checking konst v0.2.20
    Checking mfile v0.0.1 (/workbench/crates/mfile)
    Checking netlink-sys v0.8.8
    Checking const_format v0.2.36
    Checking derive_builder v0.20.2
    Checking nix v0.30.1
    Checking netlink-packet-route v0.25.1
    Checking procfs-core v0.18.0
    Checking hash32 v0.2.1
    Checking itertools v0.15.0
    Checking spin v0.9.9
    Checking generational-arena v0.2.9
    Checking strum v0.27.2
    Checking heapless v0.7.17
    Checking decode v0.0.1 (/workbench/crates/decode)
    Checking oci-spec v0.10.0
error: using `chunks_exact` with a constant chunk size
   --> crates/minimald-rpc/src/trace.rs:199:46
    |
199 |     for (byte, pair) in out.iter_mut().zip(s.chunks_exact(2)) {
    |                                              ^^^^^^^^^^^^^^^
    |
help: consider using `as_chunks::<2>()` instead
   --> crates/minimald-rpc/src/trace.rs:199:46
    |
199 |     for (byte, pair) in out.iter_mut().zip(s.chunks_exact(2)) {
    |                                              ^^^^^^^^^^^^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#chunks_exact_to_as_chunks
    = note: `-D clippy::chunks-exact-to-as-chunks` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::chunks_exact_to_as_chunks)]`

error: could not compile `minimald-rpc` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...

Outside the task's layers::

  • crates/bep/src/lib.rs

Converted to a draft: something above needs a person before review.

After min session destroy web, the daemon records a revocation for web and the proxy refuses a value copied from web within a minute, even if the proxy was down at destroy. The unit tests pin this. The two e2e cases that show it end to end still need a run on the macOS lane.

Notes from the agent: This round resolved the merge conflict in scripts/session-e2e.sh only. The conflict was in the case dispatch list and in the usage text. Both sides added cases there: this branch added the two bep_destroy cases, and main added bep_dns_steering_fails_closed_end_to_end. The resolution keeps all three. The whole-lane order merged cleanly and also lists all three. The other files in the merge commit come from main. The two e2e cases print NOT RUN on this Linux host and exit 0. That is not a pass. The macOS lane still owes their evidence, as the earlier threads (C1, C2) ask. No verdict on an earlier thread changed this round.

@minimal-foundry
minimal-foundry Bot marked this pull request as draft October 25, 2026 16:36
@norrietaylor
norrietaylor marked this pull request as ready for review October 25, 2026 16:39
@norrietaylor norrietaylor changed the title T20 — Record a revocation when a live box is destroyed and refuse its values within a minute feat(bep): record a revocation when a live box is destroyed (T20) Oct 25, 2026
@norrietaylor norrietaylor left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Babysitter approval at 74e011b: every merge gate passes at this head (arch's conditions are the macOS legs, filed as residual #2564 by the epic owner's decision; zero open threads; every lane aggregator green). Squash title feat(bep): record a revocation when a live box is destroyed (T20) and the squashed message pass commitlint. Queued for squash merge.


Generated by Claude Code

…evocation-when-a-live-box-is-destroyed

# Conflicts:
#	scripts/session-e2e.sh
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling

The PR's own hunks did not change since 74e011bb. The two merges from main keep both sides of the scripts/session-e2e.sh conflict. The ruling on 74e011bb stands. A revocation is recorded only on a live destroy, covers exactly its box id, and is checked before any resolution (Gatehouse §6.10 line 839). The two macOS e2e legs recorded NOT RUN, so C1 keeps them open under #2564 until they pass on the macOS lane.

Ruled at 20f42cf against gominimal/arch@109541a48c31 by claude-opus-5-5.

Comment thread scripts/session-e2e.sh Resolved
Comment thread scripts/session-e2e.sh Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

A merge of main before round 7, not counted against the cap (3 of 3), pushed as 20f42cf9cf32.

Resolved conflicts in: scripts/session-e2e.sh

line exit tail
cargo nextest run -p bep prop_revocation_covers_exactly_its_box 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-2bb3... Compiling bep v0.0.1 (/workbench/crates/bep) Finished 'test' profile [unoptimized] target(s) in 41.86s ──────────── Nextest run ID 62021128-b6c2-4928-a105-0a60b87f7e99 with nexte
cargo nextest run -p bep revoked_value_never_triggers_renewal 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-bfa4... Finished 'test' profile [unoptimized] target(s) in 0.54s ──────────── Nextest run ID c1459863-9015-43f8-9f3d-9921a280f3fe with nextest profile: default Starting 1 test across 2
cargo nextest run -p minimal mint_and_destroy_append_audit_records 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-68f0... Compiling args v0.0.1 (/workbench/crates/args) Compiling ot v0.0.1 (/workbench/crates/ot) Compiling paths v0. 10BC8 0.1 (/workbench/crates/paths) Compiling stdlib v0.0.22 (/workbenc
./scripts/session-e2e.sh bep_destroyed_box_values_refused_within_60s 0 the 'min' and 'minimald' under /work/build-cache/target/debug report different versions; rebuilding the pair no usable 'min' and 'minimald' pair on PATH or under target/; building the pair this run drives (cargo build --locked -p minimal --bin min -p minimald --bin minimald) built the pair: /work/bu
./scripts/session-e2e.sh bep_destroy_with_proxy_down_refuses_by_attachment 0 ::group::min session destroy with the proxy down: the destroy completes, and the value is refused bep_destroy_with_proxy_down_refuses_by_attachment: NOT RUN (the Box Egress Proxy runs on macOS only) ::endgroup:: session e2e: 1 case(s) NOT RUN: bep_destroy_with_proxy_down_refuses_by_attachment sessio

Verify min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.97.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

g v2.11.1
    Checking sponge-cursor v0.1.0
    Checking ml-kem v0.3.2
    Checking heapless v0.9.3
    Checking sha3 v0.12.0
    Checking ssh-key v0.7.0-rc.11
    Checking mlog v0.0.1 (/workbench/crates/mlog)
    Checking generic-array v1.4.4
    Checking russh-cryptovec v0.62.0
    Checking num-bigint v0.5.1
    Checking russh-util v0.52.0
    Checking args v0.0.1 (/workbench/crates/args)
    Checking bitflags v1.3.2
    Checking common v0.0.1 (/workbench/crates/common)
    Checking managed v0.8.0
    Checking hex-literal v1.1.0
    Checking constcat v0.6.1
    Checking boxes v0.0.1 (/workbench/crates/boxes)
    Checking tinyvec_macros v0.1.1
    Checking russh v0.64.1
    Checking tinyvec v1.12.0
    Checking smoltcp v0.14.0
    Checking is_executable v1.0.6
    Checking clap_complete v4.6.11
    Checking hickory-proto v0.26.3
    Checking switch v0.0.1 (/workbench/crates/switch)
    Checking minimald-rpc v0.0.1 (/workbench/crates/minimald-rpc)
    Checking sysinfo v0.39.6
   Compiling minvmd v0.8.0 (/workbench/crates/minvmd)
    Checking hashbrown v0.14.5
    Checking serde_bytes v0.11.19
    Checking netlink-packet-core v0.8.1
   Compiling stdlib v0.0.22 (/workbench/crates/stdlib)
    Checking dashmap v6.2.1
    Checking konst_macro_rules v0.2.19
    Checking russh-sftp v2.4.0
    Checking konst v0.2.20
    Checking mfile v0.0.1 (/workbench/crates/mfile)
    Checking netlink-sys v0.8.8
    Checking const_format v0.2.36
    Checking derive_builder v0.20.2
    Checking nix v0.30.1
    Checking netlink-packet-route v0.25.1
    Checking procfs-core v0.18.0
    Checking hash32 v0.2.1
    Checking itertools v0.15.0
    Checking spin v0.9.9
    Checking generational-arena v0.2.9
    Checking strum v0.27.2
    Checking decode v0.0.1 (/workbench/crates/decode)
    Checking heapless v0.7.17
    Checking oci-spec v0.10.0
    Checking netconfig-rs v0.1.6
    Checking procfs v0.18.0
    Checking pathrs v0.2.5
    Checking checkouts v0.0.1 (/workbench/crates/checkouts)
    Checking nix v0.29.0
    Checking netlink-packet-route v0.31.0
    Checking cobs v0.3.0
error: using `chunks_exact` with a constant chunk size
   --> crates/minimald-rpc/src/trace.rs:199:46
    |
199 |     for (byte, pair) in out.iter_mut().zip(s.chunks_exact(2)) {
    |                                              ^^^^^^^^^^^^^^^
    |
help: consider using `as_chunks::<2>()` instead
   --> crates/minimald-rpc/src/trace.rs:199:46
    |
199 |     for (byte, pair) in out.iter_mut().zip(s.chunks_exact(2)) {
    |                                              ^^^^^^^^^^^^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#chunks_exact_to_as_chunks
    = note: `-D clippy::chunks-exact-to-as-chunks` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::chunks_exact_to_as_chunks)]`

error: could not compile `minimald-rpc` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...

Outside the task's layers::

  • crates/bep/src/lib.rs

Converted to a draft: something above needs a person before review.

After min session destroy web, a value copied from web is refused within a minute, even if the proxy was down. This round changes no behaviour. The branch now merges cleanly with main and keeps both e2e destroy cases.

Notes from the agent: This round resolves the merge conflict with main in scripts/session-e2e.sh. Both sides added new e2e cases at the same place. The resolution keeps this branch's destroy-revocation helpers and its two cases, and then adds main's proof_bep_signing_rotation_keeps_running_box_working in full. Git aligned the two blocks on a few shared seed lines, so each side was rebuilt in full with those lines. The script passes bash -n, and every line from both sides is present. The other files from main (crates/bep/src/lib.rs, store.rs, crates/minimal cli.rs, cmd/mod.rs, cmd/secret.rs) merged without conflict. Those changes come from main and are not work for this task. The two e2e cases report NOT RUN on this Linux box with no /dev/kvm, because the proxy cases run on macOS only. They still owe their evidence on the macOS lane.

@minimal-foundry
minimal-foundry Bot marked this pull request as draft October 25, 2026 18:06
auto-merge was automatically disabled October 25, 2026 18:06

Pull request was converted to draft

@norrietaylor
norrietaylor marked this pull request as ready for review October 25, 2026 18:28
@norrietaylor norrietaylor left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Babysitter approval at 20f42cf: every merge gate passes at this head (arch PASS at 20f42cf, zero open threads, every lane aggregator green). Squash title feat(bep): record a revocation when a live box is destroyed (T20) and the squashed message pass commitlint. Queued for squash merge.


Generated by Claude Code

@norrietaylor
norrietaylor added this pull request to the merge queue Oct 25, 2026
Merged via the queue into main with commit 7529939 Oct 25, 2026
37 checks passed
@norrietaylor
norrietaylor deleted the agent/2277-record-a-revocation-when-a-live-box-is-destroyed branch October 25, 2026 19:39
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.

T20 — Record a revocation when a live box is destroyed and refuse its values within a minute

1 participant

0