Repository navigation
feat(minimal): mint sealed GitHub sign-in references and register the box with the proxy - #2490
Conversation
The identity carries root_not_after, the root key's creation time plus the fixed default validity (OQ3, gominimal/arch#85). A start or a key replacement keeps the end while the root key stays the same. A mint reads it as the expiry of each sign-in reference (BEP-005). The bep serve startup warning no longer says that no creator registers a box's declared egress: min now sends register_box at create.
A box spec with a GitHub grant is refused when no GitHub sign-in is held (BEP-003). The refusal carries the defined error github_sign_in_required, exits 3 as a refused box spec, and tells the person to run min auth login. Nothing here asks for a sign-in.
A box with GitHub grants is refused at creation when no sign-in is held, with no prompt. After the create, min mints one sign-in reference for each grant under a client key it registers with the proxy, seals it to the proxy's published key with the root's validity end as its expiry, and registers the box's declared egress and address stance. The sealed value is not yet delivered into the box (BEP-007).
The case starts two grant boxes headless on macOS with a sign-in held and the proxy running. Elsewhere it records NOT RUN.
A shared CARGO_TARGET_DIR can hold a 'min' with no 'minimald' beside it. The fallback took that dir, skipped the build, and failed the daemon gate. Accept a dir only when both halves of the pair are in it.
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
There was a problem hiding this comment.
Babysitter review of T14 at f744a67 (round 0, draft). Not an approval yet.
Verified line by line against spec 24: a box with a GitHub grant and no held sign-in is refused at creation with the defined error and the fixed text, after a metadata-only read that asks for nothing (BEP-003); each grant's member is a sign-in reference signed under a per-creation client key that the mint registers with the proxy before any handle is sealed, with the module's authorities as its upstream set, no injection form, no token in any part, and the root's validity end as its expiry, carried in the published identity from one start to the next while the root key is unchanged (BEP-005, OQ3); the Box Host it binds is the sealing key's fingerprint, the same name bep serve redeems under; and register_box follows the mint with the declared egress and the box's stance. All five commits lint.
One design point for the arch ruling before any round: register_box is sent only for a box with a GitHub grant. A box steered at the proxy with no grant is then never registered, so every request from it is refused outside_declared_egress and the BEP-030 passthrough never works for it. Either registration follows steering, with the mint staying grant-only, or T40 (#2334) carries it when it points the box at the proxy. I will carry whichever the ruling says.
Low, for the same round or none: on a mint failure after the create, the box row is withdrawn, and it needs saying whether the created box is destroyed or left; main.rs drops the whole "no creator registers" warning sentence although nothing sends forget_box until #2277, which the warning should still say; and the e2e case records NOT RUN on every lane without a person's sign-in, the macOS runner included, so the PR body should say the unit tests carry the proof in CI.
Generated by Claude Code
The connection inventory matches ControlClient::connect, so the mint path and its tests count as connections. They reach the Box Egress Proxy, not the daemon, so they carry no version gate.
|
Round 1 of 10 on a failed check suite, pushed as
Verify Outside the task's
Converted to a draft: something above needs a person before review. A grant box is created with no prompt. Each grant's sealed value is minted under the client's key with the root's expiry, and the proxy holds the box's declared egress. The tests check this, and the minimal crate's connection inventory test now passes again. Notes from the agent: The CI 'tests' job failed on minimal tests::every_daemon_connection_is_classified. Its scanner matches any |
|
Revise round 1 ran against |
|
/revise Carry the one failure left on shellcheck reports SC2031 (HOME was modified in a subshell) at lines 11515 and 11516, the two Generated by Claude Code |
|
Round 2 of 10 on a /revise note, pushed as
Verify Outside the task's
Converted to a draft: something above needs a person before review. A grant box is created with no prompt, each grant's sealed value is minted under the client's key with the root's expiry, and the proxy holds the box's declared egress. This round only makes scripts/session-e2e.sh pass shellcheck, so the e2e case that shows this no longer fails the Linux lint lane. Notes from the agent: Revise round 2: proof_bep_second_box_needs_no_sign_in now computes bep_control="$HOME/.minimal/bep/control.sock" once, under a '# shellcheck disable=SC2031' line and a one-line reason, and uses $bep_control in both places. The cargo test lines were not re-run because no Rust file changed this round. The e2e case is NOT RUN on this Linux box, as the script itself reports, so its evidence still comes from the macOS lane. |
|
/revise Carry the The body of Generated by Claude Code |
|
Round 3 of 10 on a /revise note: the coder changed nothing. I did not do the revise note on purpose. The note asks for an amend of commit e71670c and a force-push. My instructions forbid both: never rewrite commits already on the branch, and never force-push. I also hold no push credential. A new commit cannot fix this failure, because commitlint checks each commit on the branch, and e71670c stays in the history. The body of e71670c is one line of 156 characters, over the body-max-line-length limit of 100. The other commits pass; the footer-leading-blank result on the bafb2c7-era feat(bep) commit is a warning only. A person with push rights can fix it with these steps: git rebase -i e71670c~1, reword e71670c, and keep the subject 'fix(e2e): read the proxy control socket path once in the BEP proof'. Wrap the body at 72 columns, for example: 'shellcheck reports SC2031 on $HOME at top level, because earlier' / 'proofs export HOME in subshells. Compute the path once under a' / 'disable line, as mnl() does.' Then run npx commitlint…[truncated] |
shellcheck reports SC2031 on $HOME at top level, because earlier proofs export HOME in subshells. Compute the path once under a disable line, as mnl() does.
e71670c to
3c15cca
Compare
|
Reworded Generated by Claude Code |
|
Reviewed: 1 finding, none blocking at Address the comments on the diff. Clobber: not checked in depth. If that was not intentional, restore the earlier change. |
There was a problem hiding this comment.
arch-review: CONDITIONS · 7 conditions · the full ruling
The member shape, the key registration order and the placement conform to Gatehouse §6.10 lines 839 and 842. The refusal path does not conform to §6.2 line 580. The sign-in error must print only when a node-local proxy exists, and a grant box with no proxy or no box id must be refused with gatehouse_unenrolled_node. C1 and C2 fix this. C3, C4 and C5 make three interims honest: the dropped forget_box warning, the per-creation client key and the undelivered sealed value. C6 puts the root validity in one constant. C7 records an observed macOS run of the BEP-003 e2e case.
Ruled at 3c15cca against gominimal/arch@109541a48c31 by claude-opus-5-5.
An identity that an older bep published names the root key with no end. Counting ten years from the restart can outlive the real root, so the end stays unset and the refusal names bep --replace-key root.
A failed box registration left the client key registered with the proxy, and no box used it. The key now goes last, before any handle leaves the process.
There was a problem hiding this comment.
arch-review: CONDITIONS · 4 conditions · the full ruling
Two fix commits conform. The client key now registers last, and an upgraded identity with an unknown root age fails closed. Two deviations stay open. Gatehouse §6.2 line 580 keeps gatehouse_unenrolled_node as the refusal where no node-local proxy exists. This change refuses with github_sign_in_required on every host, and it lets a grant box with no box id start with nothing behind its grant (C1). with_root_validity still gives a root key of unknown age a fresh ten-year end when the identity file is absent (C2). C3 and C4 make the dropped sealed values and the NOT RUN e2e leg honest.
Ruled at deda556 against gominimal/arch@109541a48c31 by claude-opus-5-5.
|
Round 4 of 10 on the runtime's review findings, pushed as
Verify Outside the task's
Converted to a draft: something above needs a person before review. Review threads the coder judged:
A grant box is created with no prompt. Each grant's sealed value is minted under the client's key, with the root's expiry. The proxy holds the box's declared egress. This round, an identity with no known root start gets no invented expiry, and a failed box registration leaves no client key registered with the proxy. Notes from the agent: Revise round 4. publish.rs: when the previous identity names the same root key with no root_not_after, the end now stays unset. A mint refuses that identity with NoRootValidity. The text of that refusal changed from 'Start |
A reply that fails after the proxy stored the box left it registered. The mint now forgets the box over a new connection. The inventory of connection sites drops the stale mint.rs::drop entry and adds the test.
The interrupt handler exits with no destructor, so the forget does not run. The box's destroy forgets it (#2277).
The store already holds the new root key, and a later bep start gives it no validity end. Only a new replacement fixes it.
|
Round 9 of 10 on a /revise note, pushed as
Verify Outside the task's
Converted to a draft: something above needs a person before review. Review threads the coder judged:
A grant box is created with no prompt. Each grant's sealed value is minted under the client's key with the root's expiry, and the proxy holds the box's declared egress. A registration whose reply fails no longer leaves the box at the proxy. Notes from the agent: Round 9. (1) mint_and_register now forgets the box when register_box fails with any error other than NotRunning. The forget goes over a new connection, because the old one can still carry the late reply. ControlClient keeps its socket path for this. The new test a_failed_box_reply_forgets_the_box_again uses a socket that stores the box and closes with no reply. (2) cmd/mod.rs (arm_activation_interrupt) is outside the layers, so the three comments (mint.rs ProxyRegistration doc, mint.rs drop, create.rs) now say a Ctrl-C leaves the box at the proxy until its destroy forgets it (#2277). (3) bep replace_key: on a clock error for the root, the message now says to set the system clock and run |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 2 conditions · the full ruling
The compare closes the failed-reply gap. A register_box reply that fails now forgets the box over a new connection, and the new test proves it. Gatehouse §6.2 line 580 and §6.10 line 839 govern the change, and the refusals, the mint and its placement conform. Two items stay open, and their issues are filed. C1: the live e2e leg is NOT RUN until T18 starts bep serve. C2: the sealed value is dropped until T42 delivers it.
Ruled at 174d8d0 against gominimal/arch@109541a48c31 by claude-opus-5-5.
A failed register_client_key reply, such as a read timeout, can leave the late reply on the control connection. A forget_box on that same connection then reads the stale reply as its own answer. Send the forget over a new connection, as the register_box failure path does.
|
The runtime will not revise this pull request again on its own: round 11 would exceed the cap of 10; 0 base merges were not counted (the last trigger was the runtime's review findings). A person decides now. Remove |
There was a problem hiding this comment.
arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling
The compare conforms. The forget after a refused client key now goes over a new connection, so a late reply cannot read as its answer. The test proves the new connection. BEP-003 and BEP-005 conform to §6.2 line 580 and §6.10 line 839. C1 stays open because the e2e leg bep_second_box_needs_no_sign_in records NOT RUN on every lane. Record it as PASS on the macOS lane after #2275 starts the proxy.
Ruled at 3b907a8 against gominimal/arch@109541a48c31 by claude-opus-5-5.
|
Round 10 of 10 on the runtime's review findings, pushed as
Verify Outside the task's
Converted to a draft: something above needs a person before review. Review threads the coder judged:
A person can create a grant box with no prompt. The box carries one sealed sign-in reference for each grant, minted under the client's key and expiring with the root. The proxy holds the box's declared egress. When the proxy refuses the client key, it forgets the box over a new connection, so a late reply cannot hide a failed forget. Notes from the agent: This round fixes the one open thread. mint_and_register now sends the forget_box cleanup over a new connection after both register_box and register_client_key fail. Both paths share the helper forget_on_a_new_connection. The test server serve_refusing_keys now accepts each connection on its own thread, as the real control socket does. It also records each connect, so a_refused_client_key_forgets_the_box_again proves that the forget uses a second connection. I did not run ./scripts/session-e2e.sh bep_second_box_needs_no_sign_in because this box has no /dev/kvm and no microVM host. The script records that leg as NOT RUN off macOS. cargo clippy -p minimal --all-targets shows no new warnings. The warnings it prints come from minimald and minimald-rpc and were there before this change. |
There was a problem hiding this comment.
Babysitter review of T14 at 3b907a8, against the plan block on #2273 and the rounds since my review at f744a67.
Plan coverage. Every layer line is in the diff: publish.rs carries root_not_after from a known root creation time (with_root_validity(previous, root_made_at)); mint.rs mints one sealed sign-in reference per grant under a per-creation client key, registers the box and then the key over the control socket, and forgets the box over a fresh connection when either registration fails; create.rs refuses a grant box with gatehouse_unenrolled_node (exit 5) where no proxy identity or control socket exists and with github_sign_in_required where one does, mints on a blocking thread after the create settles the box id, destroys the new session and withdraws its row when the mint fails, and keeps the proxy registration only once the session is active; boxes/core/bep.rs defines the error; bep/src/main.rs drops the box-egress interim sentence; session-e2e.sh adds bep_second_box_needs_no_sign_in, NOT RUN until #2275. The five test lines of the plan ran green in every round table and in CI.
Rounds verified. Rounds 1 to 10 were read commit by commit (each message commitlint clean, one reworded under the standing rule): SC2031 precedent, the daemon-connection inventory (twice: the connect_with_timeout rename moved a site), ProxyRegistration with keep() after the interrupt guard drops, the forget on a blocking thread with a 2 s timeout, the pre-epoch clock refusals in min and bep, the best_effort_destroy on a failed mint, the corrected Ctrl-C comments, the root-replacement message, and the fresh-connection forgets. Each matched its finding.
Arch. PASS_WITH_CONDITIONS at 3b907a8 with C1 only; C1 (live leg) is filed on #2275 and C2 from 174d8d0 (delivery) on #2488, both as layer lines on the owning tasks. The review MEDIUM at this head (expired-root guard) is filed on #2288 under the revise cap.
Layer exception. crates/minimal/Cargo.toml (three workspace dependencies) and crates/bep/src/ca.rs (one constant, an arch condition) under the recorded rule.
Size. +1977/-23 against an estimate of 720: 2.8x, under the 3x cap.
Verdict: ready to merge once the lanes at this head finish and the epic owner lifts the revise-cap needs-human.
Generated by Claude Code
There was a problem hiding this comment.
Approved at 3b907a8 by the babysitter under the epic owner's merge-on-green delegation for #1501. All twelve gates pass at this head: own review, arch pass (C1 filed on #2275, C2 on #2488), review concluded, no open threads, every bot resolution re-verified, five lane aggregators green, not a draft, no round in flight, needs-human removed by the epic owner at 16:15Z, and Closes #2273. The squash message is Conventional Commits compliant (feat(minimal): mint sealed GitHub sign-in references and register the box with the proxy
D8B2
code>).
Generated by Claude Code
T14 — Mint a sealed sign-in reference for each GitHub grant and register the box with the proxy
slice: S0
kind: task
covers: BEP-003, BEP-005
size: L
est: 360 code, 360 tests
executor: agent
difficulty: needs care
model: strongest
diagnostics: creating a grant box with no sign-in held exits with code
github_sign_in_requiredand prints "This box declares a GitHub grant, and no GitHub sign-in is held on this machine. Runmin auth login, then create the box again." on stderr, pinned by creation_without_sign_in_fails_with_defined_errorobservability: one info log line per mint naming the box id, the module and the member's expiry, never the handle or the sealed value; one debug line per
register_boxnaming the box id and the count of its declared authoritieslayers:
- publish:
- crates/bep/src/publish.rs: the published identity carries the root's validity end (
root_not_after), the root key's creation time plus the fixed default validity in one constant (OQ3), until gominimal/arch#85 rules otherwisetest: cargo nextest run -p bep published_identity_carries_the_root_validity_end
- mint:
- crates/minimal/src/mint.rs (new): the BEP-005 sign-in reference under the client's key, registered over the control socket, sealed from the published identity, with the member's expiry read from the identity's
root_not_after- crates/minimal/src/lib.rs: module line
- crates/minimal/src/tests.rs: the mint and registration tests
- crates/minimal/src/cmd/boxes/create.rs: refuses creation with no sign-in held and never prompts; mints and seals per grant; sends
register_boxover the proxy's control socket with the box id, its declared egress and itsown_iporhost_ipstance (T41)- crates/bep/src/main.rs: drops the "no creator registers a box's declared egress" sentence from the
bep servestartup warning and the matching interim comment inwire, since this task is the create half of that flip (the destroy half is T20)test: cargo nextest run -p minimal local_member_is_a_sign_in_reference_expiring_with_the_root
test: cargo nextest run -p minimal grant_box_registers_its_declared_egress_with_the_proxy
- refuse:
- crates/boxes/src/core/bep.rs: the defined error
github_sign_in_requiredtest: cargo nextest run -p boxes creation_without_sign_in_fails_with_defined_error
- e2e:
- scripts/session-e2e.sh: adds the case
test: ./scripts/session-e2e.sh bep_second_box_needs_no_sign_in
produces:
- crates/minimal/src/mint.rs
consumes:
- crates/bep/src/signin.rs
- crates/bep/src/handle.rs
- crates/bep/src/publish.rs
- crates/bep/src/control.rs
- crates/boxes/src/core/bep.rs
proof: A grant box is created with no prompt, each grant's sealed value is minted under the client's key with the root's expiry, and the proxy holds the box's declared egress.
depends on:
- blocked by T2
- blocked by T7
- blocked by T10
- blocked by T12
- blocked by T13
- blocked by T41
- assumes OQ3
Proof
A box that declares a GitHub grant is refused at creation with the defined github_sign_in_required text when no sign-in is held, and it never prompts. With a sign-in held, min mints one sealed sign-in reference for each grant after the create. The reference is signed under a client key that min registers with the proxy, it carries no token, and its expiry is the root's validity end from ~/.minimal/bep/identity.json. min then sends register_box with the box id, the declared egress and the own_ip or host_ip stance. The minimal tests open the sealed value with the proxy key, verify the handle against the registered key, and read the box's egress and stance back from the proxy's registry. The live two-box e2e case is written but not observed (see notes).
Notes from the agent: Out-of-scope files: crates/minimal/Cargo.toml adds base64, getrandom and p256 (workspace deps) for the client key and the handle, and Cargo.lock follows. The e2e test line exited 1 in the script's preflight because this box has no minimald on PATH. The case itself runs only on macOS, because bep serve is macOS-only, and it records NOT RUN elsewhere or when no sign-in or no control socket is present. It is also in the whole-lane order. So the macOS lane owes the live evidence. Design points: (1) The key store keeps no creation time, so bep start and key replacement stamp root_not_after = now + ROOT_VALIDITY_SECS (10 years, OQ3), and keep the previous value while the root kid is unchanged. ca.rs keeps its own ROOT_VALIDITY with the same value; it is not linked because ca.rs is outside the layers. (2) The client key is made for each creation and held in memory, because no keychain-held client key exists yet. (3) A mint or proxy failure ends the creation and withdraws the box row. A creation with no box id (native host or older daemon) or a network mode with no stance skips the mint with a debug log. Nothing in the repo starts bep serve, so a grant box on a host that gets a box id now fail…[truncated]
Tests
cargo nextest run -p bep published_identity_carries_the_root_validity_endcargo nextest run -p minimal local_member_is_a_sign_in_reference_expiring_with_the_rootcargo nextest run -p minimal grant_box_registers_its_declared_egress_with_the_proxycargo nextest run -p boxes creation_without_sign_in_fails_with_defined_error./scripts/session-e2e.sh bep_second_box_needs_no_sign_inVerify
min task run agent-verifyexited 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.Layer exception
Accepted by the epic owner on 2026-10-19 under the rule recorded for #2361, #2363 and #2365 (required one-line changes outside the planned layers), applied by the babysitter on 2026-10-22:
crates/minimal/Cargo.toml: thebase64,getrandomandp256workspace dependencies thatmint.rsneeds for the handle-signing key, the handle id and the key's encoding on the proxy's control socket.crates/bep/src/ca.rs:ROOT_VALIDITYis derived frompublish::ROOT_VALIDITY_SECS, so one constant gives the root's validity and each member's expiry (BEP-005, OQ3), per arch-review condition at deda556 (thread 4344725159).Residuals
Filed by the babysitter from the arch and review rulings on this PR; each may stay open at merge.
bep_second_box_needs_no_sign_inrecords NOT RUN on every lane until T18 T18 — Run the proxy beside gvproxy so git and gh reach GitHub from a box #2275 startsbep serve; T18's e2e layer carries the leg to record as a pass on the macOS lane (comment 6336808325 on T18 — Run the proxy beside gvproxy so git and gh reach GitHub from a box #2275).drop(minted)in theMintGrantsstep leaves a grant's variable empty until T42 T42 — Deliver each sealed value into its grant's environment variable in the box #2488 delivers eachMinted.sealed; T42's carry layer names thecreate.rsline (comment 6338545816 on T42 — Deliver each sealed value into its grant's environment variable in the box #2488).root_not_afteris later than now before it becomes the member expiry; the guard is on T27 T27 — Mint store handles and keep the client's key registered across proxy restarts #2288's mint layer.Out of scope
These files are outside the task's
layers:, so this PR is a draft:crates/minimal/Cargo.tomlCloses #2273
Generated by Claude Code