8000 Merge remote-tracking branch 'origin/main' into agent/2277-record-a-revocation-when-a-live-box-is-destroyed · gominimal/minimal@dff3308 · GitHub
[go: up one dir, main page]

Skip to content

Merge remote-tracking branch 'origin/main' into agent/2277-record-a-r…

Minimal Arch / arch-review failed Oct 25, 2026

CONDITIONS

Governs: Gatehouse §6.10 line 839 (v1.24, Identity, attribution, and revocation). 3FC1 A box revocation is written when a live box is destroyed, and this is the mode's one revocation event. It names an id that never returns and covers exactly that creation's values. The records live in the helper's hash-chained log, are restored at start, and are consulted at step 2 before any resolution. The same line requires that the host-side creator withdraws a box's attachment at its end. Also §6.10 line 836 and architecture.md line 501, which say the local log holds the destroyed box's standing revocation record. The checkout (109541a4) has no arch-map.md, so I started from §6.10, as the earlier BEP rulings did. No findings.json and no since.diff were staged. This is the first ruling on this PR. pr.diff equals git diff 17ce321a dff33084.

Ruling: the shape conforms. minvmd, outside the VM, sends revoke_box then forget_box from withdraw_client_box. That is the creator's destroy path, and the attachment is retired first under the row lock. The stop and detach-expiry path (withdraw_where) sends none. The proxy is the log's only writer, and the control socket shares the decisions' Arc<Mutex<AuditLog>>. A revocation is in force before its record is written, and decide refuses it before the keychain is read. Three conditions remain. C1: both e2e legs are NOT RUN, and BEP-043 has no other proof (rubric rule 4). C2: redeemer.rs still states the interim this PR flips (rule 2). C3: the BEP-071 property proves revoke::covers and in_force_for, which the redeemer never calls (rule 3).

Observations, not conditions:

  • The creator's rollbacks in crates/minimal/src/cmd/boxes/create.rs (an abandoned activation, a skewed daemon, a failed upload) also call withdraw_box_row. So with this PR they send a revocation and, with the proxy down, log the "the destroy completed" warning. I read an abandoned creation's row as the remove of a live box, so this is not a deviation. The warning text is wrong for that path.
  • AuditWriter::write returns no result. If the append fails, the revocation is in force in memory and revoke_box still replies ok, but T33 cannot restore it. The proxy logs an error, and the withdrawn attachment refuses the values anyway (the BEP-043 sub-requirement).
  • min box audit shows a revocation record with decision: refuse and resource/permission module_unmapped, and a mint record with admit and an empty upstream. The design gives the field set for admit/refuse events only, so it is silent on these values.
  • The e2e refusal case checks cross_box, not revoked. Attribution refuses first, as the PR notes. BEP-043's two clauses (the record, then the refusal) are still both checked.

Not checked: I did not build or run anything. I did not check a destroy whose DestroySession takes more than DETACH_GRACE (45 s, for a slow on_destroy hook). In that case the drainer can withdraw the row first, and the creator's withdrawal then finds a dormant creation and sends no revocation. The attachment still refuses, but no record is written. The ledger keeps only 400 characters of each precedent, so I cite them for the governing line, not for their conditions.

Conditions

  • C1: 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 on the macOS lane (just e2e on the Apple Silicon runner, live proxy and GitHub sign-in). Record each as PASS in the PR's Tests table. Today both print NOT RUN, and BEP-043 has no other verify line.
  • C2: crates/bep/src/redeemer.rs: rewrite the interim in the BoxRedeemer::new doc comment (lines 107-113) and in the facts-gathering doc comment (lines 223-224). Today both say that nothing in bep serve writes a revocation until T20 (#2277). Make them say that revoke_box on the control socket puts a revocation in force (crate::revoke::record). Make them say that the one interim left is the empty set at start until T33 (#2290) restores it, which matches the bep serve warning in crates/bep/src/main.rs line 945. This file is outside the task's layers. Edit it in this PR, because this PR is the flip those comments name.
  • C3: 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. Then 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.

Ruled at dff3308 against gominimal/arch@109541a48c31 by claude-opus-5-5; arch_rulings 266, job 672605cf-440c-476e-8fa7-55280747843a.

0