8000 feat(min): sign in to GitHub under the published App, kept in the host keychain by minimal-foundry[bot] · Pull Request #2364 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

feat(min): sign in to GitHub under the published App, kept in the host keychain - #2364

Merged
norrietaylor merged 12 commits into
mainfrom
agent/2263-sign-in-to-github-with-min-auth-and-keep-the-sig
Oct 20, 2026
Merged

norrietaylor merged 12 commits into
mainfrom
agent/2263-sign-in-to-github-with-min-auth-and-keep-the-sig

Conversation

@minimal-foundry
Copy link
Copy Markdown
Contributor

T12 — Sign in to GitHub with min auth and keep the sign-in in one keychain item

slice: S0
kind: task
covers: BEP-001, BEP-002, BEP-004
size: L
est: 410 code, 480 tests
executor: agent
difficulty: needs care
model: strongest
diagnostics: min auth status prints "Signed in to GitHub as . The token expires at ." or, with expired token and live refresh material, "Signed in to GitHub as . The token renews at the proxy on the next request that uses it.", never a token, pinned by auth_status_reports_expiry_without_token
observability: one info log line per sign-in naming the account, the flow and whether the instance is new
layers:
- cli:
- crates/minimal/src/cli.rs: min auth login [--device], min auth status
- crates/minimal/src/cmd/mod.rs: dispatch and module line
- crates/minimal/src/cmd/auth.rs (new): device and PKCE browser flows under the App (client id Iv23liv6KetAFJp4Eb5K, callback http://127.0.0.1/callback, any port), browser by default; the secret is option_env!("MINIMAL_GITHUB_APP_CLIENT_SECRET"), and a build without it takes the device flow; status from the item's metadata
- crates/minimal/Cargo.toml: the bep crate
- Cargo.lock: the new dependency edge
test: cargo nextest run -p minimal auth_login_completes_device_flow_and_reports_account
test: cargo nextest run -p minimal auth_login_completes_browser_pkce_flow
test: cargo nextest run -p minimal auth_login_without_built_in_secret_takes_device_flow
test: cargo nextest run -p minimal auth_status_reports_expiry_without_token
test: cargo nextest run -p minimal auth_status_reports_renewal_of_expired_sign_in
- item:
- crates/bep/src/signin.rs (new): the one sign-in keychain item and its instance identifier (BEP-002)
- crates/bep/src/lib.rs: module line
test: cargo nextest run -p minimal auth_login_stores_material_in_keychain_only
test: cargo nextest run -p minimal a_sign_in_with_no_held_item_is_a_new_instance
test: cargo nextest run -p minimal re_login_to_the_same_account_keeps_the_instance
produces:
- crates/bep/src/signin.rs
consumes: none
proof: min auth login completes the device flow and names the account, and min auth status shows the expiry and no token.
depends on:
- blocked by #2258

Proof

min auth login --device prints a code to enter at github.com. After the code is entered, it prints Signed in to GitHub as <account>. and keeps the token and refresh token in one host keychain item. In a build with no embedded client secret, the bare min auth login takes the same device flow. min auth status prints Signed in to GitHub as <account>. The token expires at <time>. and prints no token. The tests show this against a local stand-in for GitHub.

Notes from the agent: The tests use a local fake GitHub server and an in-memory keychain (bep::signin::MemoryKeychain). No test ran against real GitHub or a real host keychain. The host keychain backend calls /usr/bin/security on macOS. On other hosts it calls secret-tool (Secret Service), because the spec leaves the Linux store open. The macOS backend did not run on this Linux box. It needs a check on a Mac: the write through security -i, and the parse of the icmt comment attribute that holds the metadata. bep has no Cargo.toml change: the backends use std::process only. minimal depends on bep through bep = { path = "../bep" }, because the root Cargo.toml (not in layers) has no workspace entry for bep. The PKCE verifier and the state use bep::signin::new_instance_id, and the base64url encoder is local, so minimal has no new crates. The hidden min login verb in cmd/admin.rs is unchanged. docs/reference/cli-min.md does not yet document min auth (not in layers). The status line for an expired token copies the wording from the task's diagnostics line, which uses the word "proxy". The status time is printed in UTC. auth_login_stores_material_in_keychain_only proves the material goes to the keychain item and not to the metadata. The code writes no file, but the test does not scan the project directory for the token. just clippy-strict and just ci were not run.

Tests

line exit tail
cargo nextest run -p minimal auth_login_completes_device_flow_and_reports_account 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-6594... 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
cargo nextest run -p minimal auth_login_completes_browser_pkce_flow 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-ab80... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minimal-clie
cargo nextest run -p minimal auth_login_without_built_in_secret_takes_device_flow 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-26fa... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_status_reports_expiry_without_token 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-ce56... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_status_reports_renewal_of_expired_sign_in 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-bde7... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_login_stores_material_in_keychain_only 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-4749... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal a_sign_in_with_no_held_item_is_a_new_instance 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-36b3... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal re_login_to_the_same_account_keeps_the_instance 0 Applying loadouts: default Running task runtime-implement-test-7 in session task-runtime-implement-test-7-d091... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.

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-1f0b...
    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 stdlib v0.0.22 (/workbench/crates/stdlib)
   Compiling version v0.8.0 (/workbench/crates/version)
    Checking switch v0.0.1 (/workbench/crates/switch)
   Compiling minvmd v0.8.0 (/workbench/crates/minvmd)
    Checking diagnostics v0.0.1 (/workbench/crates/diagnostics)
    Checking common v0.0.1 (/workbench/crates/common)
    Checking mlog v0.0.1 (/workbench/crates/mlog)
    Checking bep v0.0.1 (/workbench/crates/bep)
    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 mfile v0.0.1 (/workbench/crates/mfile)
    Checking minimald-rpc v0.0.1 (/workbench/crates/minimald-rpc)
    Checking decode v0.0.1 (/workbench/crates/decode)
    Checking checkouts v0.0.1 (/workbench/crates/checkouts)
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...

Closes #2263

One host keychain item holds the sign-in's token and refresh material,
with its metadata (account, instance identifier, flow, expiries) kept
apart so status reads no secret. A sign-in with no held item or to a
different account gets a new instance identifier; the same account keeps
it (BEP-002).
min auth login runs the browser PKCE flow under the Minimal GitHub App
when the build embeds the client secret, and the device flow under
--device or without it, then stores the sign-in in the keychain item.
min auth status reports the account and the token expiry, and never the
token (BEP-001, BEP-004).
@coderabbitai
coderabbitai Bot commented Oct 19, 2026 •
Copy link
Copy Markdown
Contributor

Important

Review skipped

Bot user detected.

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

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 38d297fd-4c93-4932-9a64-d0bacea5816a

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 19, 2026 •
Copy link
Copy Markdown
Contributor Author

Reviewed: 1 finding, none blocking at b7145f68cda4.

Address the comments on the diff.

Clobber: none seen. The only change to existing lines is a reorder of boxes in crates/minimal/Cargo.toml.

@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 sign-in flows, the keychain item and min auth status follow Gatehouse §6.10. Two paths break the rule that a same-account login keeps the instance identifier (line 839). store_sign_in reads a keychain refusal as no held item and mints a new instance. The Secret Service backend deletes the item before it stores the new one. Both fail open and revoke every running box's references. Fix them with C1 and C2. Add the App-installation notice at first sign-in with C3.

Ruled at 9b5e516 against gominimal/arch@3dab1097cda1 by claude-opus-5-5.

Comment thread crates/bep/src/signin.rs Resolved
Comment thread crates/bep/src/signin.rs Resolved
Comment thread crates/minimal/src/cmd/auth.rs Resolved
@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 — 7 findings, 7 inline.

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

Comment thread crates/minimal/src/cmd/auth.rs Resolved
Comment thread crates/minimal/src/cmd/auth.rs Resolved
Comment thread crates/bep/src/signin.rs Resolved
Comment thread crates/bep/src/signin.rs Resolved
Comment thread crates/bep/src/signin.rs Resolved
Comment thread crates/bep/src/signin.rs Resolved
Comment thread crates/minimal/src/cmd/auth.rs Resolved
A keychain refusal no longer reads as no item held, so it mints no new
instance. On Linux the metadata moves to the label and the one attribute
is service, so secret-tool store replaces the item in place without a
clear first. The search output is zeroized after the label is parsed.

min auth login now says on stderr, at a new sign-in, that the token
reaches only where the App is installed. The browser callback reads each
connection in its own task under a 10 second limit.
@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 — 6 findings, 6 inline.

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

Comment thread crates/minimal/src/cmd/auth.rs Resolved
Comment thread crates/minimal/src/cmd/auth.rs Resolved
Comment thread crates/minimal/src/cmd/auth.rs Resolved
Comment thread crates/bep/src/signin.rs Resolved
Comment thread crates/bep/src/signin.rs Resolved
Comment thread crates/minimal/Cargo.toml 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 · the full ruling

The change conforms to Gatehouse §6.10, the un-enrolled bullet at line 839. This head fixes the defects of the earlier ruling. A refused keychain read now stops the sign-in before the write. The Linux store replaces the item in place. The install note prints at first sign-in. A same-account login keeps the instance identifier, and a login that finds no item gets a new one. Nobody checked the macOS backend on a Mac. Run one min auth login on a Mac before release.

Ruled at 94e52e8 against gominimal/arch@3dab1097cda1 by claude-opus-5-5.

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 1 of 10 on the runtime's review findings, pushed as 94e52e8d855e.

line exit tail
cargo nextest run -p minimal auth_login_completes_device_flow_and_reports_account 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-56b8... 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
cargo nextest run -p minimal auth_login_completes_browser_pkce_flow 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-a133... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_login_without_built_in_secret_takes_device_flow 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-2470... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_status_reports_expiry_without_token 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-51cc... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_status_reports_renewal_of_expired_sign_in 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-58b6... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_login_stores_material_in_keychain_only 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-5ffc... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal a_sign_in_with_no_held_item_is_a_new_instance 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-3d4d... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal re_login_to_the_same_account_keeps_the_instance 0 Applying loadouts: default Running task runtime-implement-test-7 in session task-runtime-implement-test-7-84a3... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.

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-e4eb...
    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 stdlib v0.0.22 (/workbench/crates/stdlib)
   Compiling version v0.8.0 (/workbench/crates/version)
    Checking switch v0.0.1 (/workbench/crates/switch)
   Compiling minvmd v0.8.0 (/workbench/crates/minvmd)
    Checking diagnostics v0.0.1 (/workbench/crates/diagnostics)
    Checking bep v0.0.1 (/workbench/crates/bep)
    Checking mlog v0.0.1 (/workbench/crates/mlog)
    Checking common v0.0.1 (/workbench/crates/common)
    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 mfile v0.0.1 (/workbench/crates/mfile)
    Checking minimald-rpc v0.0.1 (/workbench/crates/minimald-rpc)
    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)
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 — crates/bep/src/signin.rs: store_sign_in now treats only SignInError::Corrupt as no item held. Any other read error is returned before the write. Pinned by re_login_with_a_refused_keychain_read_writes_nothing.
  • 👍 valid — crates/bep/src/signin.rs: Removed the clear. The Linux item now has service as its one attribute and carries the metadata in its label, so secret-tool store replaces the item in place.
  • 👍 valid — crates/minimal/src/cmd/auth.rs:141: When stored.new_instance is true, run_login writes INSTALL_NOTE to err. The note says the token reaches only the accounts and organizations where the App is installed. Asserted in the new-instance and re-login tests.
  • 👎 invalid — crates/minimal/src/cmd/auth.rs:747: This is a recorded decision. The spec calls the embedded secret a public client secret of the published App (BEP-001 note, BEP-069 renewal, Gatehouse §6.10). A build without it takes the device flow. The release variable lives in the release pipeline under .github/, which is outside this task's laye
  • 👍 valid — crates/minimal/src/cmd/auth.rs:470: await_callback now reads each connection in its own spawned task under a 10 s REQUEST_READ_TIMEOUT. The browser test holds a silent connection open and still completes.
  • 👍 valid — PRRT_kwDOPdfcxM6uG4gL: Linux write no longer clears first. The store replaces the item that matches on service, so a failed store leaves the old item and its instance in place. (not posted on the thread: not an open thread on the pull request)
  • 👍 valid — PRRT_kwDOPdfcxM6uG4gS: Same fix as C1: only Corrupt maps to a new instance, and other read errors are returned before the write. (not posted on the thread: not an open thread on the pull request)
  • 👍 valid — PRRT_kwDOPdfcxM6uG4gW: secret-tool has no metadata-only read. metadata() now keeps only the label line and zeroizes the captured stdout right after it parses the label. (not posted on the thread: not an open thread on the pull request)
  • 👍 valid — crates/bep/src/signin.rs: Same fix: only the label = line is kept, and the captured search output, secret line included, is zeroized before metadata() returns.
  • 👍 valid — crates/minimal/src/cmd/auth.rs: Each callback connection now has a 10 s read limit and its own task, so a silent local connection no longer stalls the sign-in.

min auth login completes the device flow and prints "Signed in to GitHub as ." A first sign-in also says on stderr that the token reaches only where the Minimal GitHub App is installed. min auth status prints the account and the token expiry, and never prints a token. A refused keychain read or a failed store no longer replaces the held sign-in with a new instance.

Notes from the agent: Revise round 1. The Linux keychain path (secret-tool) is not on this box. So the new label-based metadata and the in-place replace are checked by clippy only, and not against a real Secret Service. This round touched no files outside the layers. The thread on the embedded client secret is judged invalid: the spec records the embedded public client secret as a deliberate decision (BEP-001 and BEP-069 notes, Gatehouse §6.10). The release step that sets MINIMAL_GITHUB_APP_CLIENT_SECRET lives in the release pipeline under .github/, which is outside this task and a protected path. Until it is set, a build takes the device flow.

Copy link
Copy Markdown
Member

/revise The native lane is red on 94e52e8: ci-linux-native-success fails because the tests job fails one test, minimal cmd::auth::tests::base64url_matches_rfc_7636_example (job 118316072685). minimal-arch rules PASS on this head (check run 118317799425), so this round is only the test.

The encoder is right and the test's constant is wrong. In crates/minimal/src/cmd/auth.rs line 965 the verifier reads dBjftJeZ4CVP-mJ92K27uhbUJU1p1r_wW1gFWFOEjXk. RFC 7636 appendix B spells it dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk (mB92, not mJ92). SHA-256 of the RFC spelling, base64url without padding, is E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM, the value the test expects; SHA-256 of the current spelling is ngF5GsXcbwljx6u133FFr3Xht9xooA_DuaX_3QwODtc, which is the failure. Fix the one character and change nothing else.


Generated by Claude Code

The verifier constant read mJ92 where RFC 7636 appendix B reads mB92.
The encoder is unchanged.
@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 · the full ruling

The change since the last PASS corrects one test vector. The PKCE test now uses the code_verifier from RFC 7636 Appendix B, and that verifier hashes to the asserted challenge. The encoder and the assertion did not change. The ruling on 94e52e8 stands for the remainder of the change under §6.10 line 839.

Ruled at e029b5b against gominimal/arch@3dab1097cda1 by claude-opus-5-5.

@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: 13 unresolved threads — minimal-arch[bot] crates/bep/src/signin.rs, minimal-arch[bot] crates/bep/src/signin.rs, minimal-arch[bot] crates/minimal/src/cmd/auth.rs:141, minimal-foundry[bot] crates/minimal/src/cmd/auth.rs:747, minimal-foundry[bot] crates/minimal/src/cmd/auth.rs:470, …. No findings.

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

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

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

line exit tail
cargo nextest run -p minimal auth_login_completes_device_flow_and_reports_account 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-d9cd... 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
cargo nextest run -p minimal auth_login_completes_browser_pkce_flow 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-da62... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_login_without_built_in_secret_takes_device_flow 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-2574... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_status_reports_expiry_without_token 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-eda6... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_status_reports_renewal_of_expired_sign_in 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-b134... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_login_stores_material_in_keychain_only 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-cba2... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal a_sign_in_with_no_held_item_is_a_new_instance 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-0c73... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minimal-clie
cargo nextest run -p minimal re_login_to_the_same_account_keeps_the_instance 0 Applying loadouts: default Running task runtime-implement-test-7 in session task-runtime-implement-test-7-bb94... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.

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.

king p521 v0.14.0
    Checking p384 v0.14.0
    Checking unicode-truncate v2.0.1
    Checking opentelemetry-appender-tracing v0.33.0
    Checking kasuari v0.4.12
    Checking hash32 v0.3.1
    Checking module-lattice v0.2.3
    Checking lru v0.18.2
    Checking kem v0.3.0
    Checking sponge-cursor v0.1.0
    Checking size v0.5.0
    Checking data-encoding v2.11.1
    Checking compression-core v0.4.33
    Checking op v0.0.1 (/workbench/crates/op)
    Checking sha3 v0.12.0
    Checking ml-kem v0.3.2
    Checking ratatui-core v0.1.2
    Checking heapless v0.9.3
    Checking compression-codecs v0.4.45
    Checking mlog v0.0.1 (/workbench/crates/mlog)
    Checking ssh-key v0.7.0-rc.11
    Checking signal-hook-mio v0.2.5
    Checking generic-array v1.4.4
    Checking derive_more v2.1.1
    Checking russh-cryptovec v0.62.0
    Checking num-bigint v0.5.1
    Checking russh-util v0.52.0
    Checking hex-literal v1.1.0
    Checking managed v0.8.0
    Checking tagptr v0.2.0
    Checking bitflags v1.3.2
    Checking constcat v0.6.1
    Checking tinyvec_macros v0.1.1
    Checking moka v0.12.16
    Checking smoltcp v0.14.0
    Checking tinyvec v1.12.0
    Checking russh v0.63.3
    Checking minimald-rpc v0.0.1 (/workbench/crates/minimald-rpc)
    Checking crossterm v0.29.0
    Checking async-compression v0.4.50
    Checking async-tar v0.6.1
    Checking line-clipping v0.3.8
    Checking object v0.40.0
    Checking is_executable v1.0.6
    Checking ratatui-widgets v0.3.2
    Checking clap_complete v4.6.11
    Checking check v0.0.1 (/workbench/crates/check)
    Checking switch v0.0.1 (/workbench/crates/switch)
    Checking hickory-proto v0.26.3
    Checking orchestrator v0.0.1 (/workbench/crates/orchestrator)
    Checking sysinfo v0.39.6
   Compiling minvmd v0.8.0 (/workbench/crates/minvmd)
    Checking ratatui-macros v0.7.2
    Checking diagnostics v0.0.1 (/workbench/crates/diagnostics)
    Checking ratatui-crossterm v0.1.2
    Checking fuzzy-matcher v0.3.7
    Checking mctx v0.0.1 (/workbench/crates/mctx)
    Checking hashbrown v0.14.5
    Checking inquire v0.9.4
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 — crates/minimal/src/cmd/auth.rs:320: Holds: post_form(...).await? in the device_flow poll loop ends the sign-in on one failed request. Not changed this round, because the revise note limits this round to the RFC 7636 test constant.
  • 👎 invalid — crates/minimal/src/cmd/auth.rs:26: The task fixes the secret as option_env!("MINIMAL_GITHUB_APP_CLIENT_SECRET"). A GitHub App code exchange needs a client secret even with PKCE, so a shipped browser flow carries it. A build without the variable takes the device flow. This is the same finding as the earlier thread on BUILT_IN_SECRET.
  • 👍 valid — crates/minimal/src/cmd/auth.rs:452: Holds: await_callback answers "Signed in to GitHub" before the token exchange and keychain write run. Not changed this round, because the revise note limits this round to the RFC 7636 test constant.
  • 👍 valid — crates/bep/src/signin.rs:238: Holds: SignInError::Corrupt gives no next step, and encode_secret uses Corrupt("material") for a bad token. Not changed this round, because the revise note limits this round to the RFC 7636 test constant.
  • 👍 valid — crates/bep/src/signin.rs:580: Holds: secret() copies out.stdout into a plain String and does not zeroize the buffer. Not changed this round, because the revise note limits this round to the RFC 7636 test constant.
  • 👎 invalid — crates/minimal/Cargo.toml:72: The change needs a bep line in the root Cargo.toml [workspace.dependencies]. The root Cargo.toml is outside this task's layers, so crates/minimal/Cargo.toml keeps the path dependency.

min auth login completes the device flow and names the account, and min auth status shows the expiry and no token. The RFC 7636 base64url test now passes, so the native lane has no failing test from this branch.

Notes from the agent: The revise note said to fix the one character in the RFC 7636 verifier and change nothing else. I changed only that character (mJ92 to mB92) on line 965 of crates/minimal/src/cmd/auth.rs. Four review threads hold against the code: the device poll aborts on a transient error, the callback page says signed in too early, the keychain errors give no next step, and the secret-tool stdout is not zeroized. I did not fix them this round because the note limits the round to the test. Each one is a small follow-up inside this task's layers. The Cargo.toml thread needs a change to the root Cargo.toml, which is outside the layers.

Copy link
Copy Markdown
Member

/revise Round 2 fixed the test. This round takes the four runtime findings that still hold on e029b5b (the earlier revise note scoped them out by mistake; they are in scope now). Arch rules PASS on this head, so change nothing else.

  1. Device poll retries transient failures (thread on device_flow, auth.rs line 320). A network error, a timeout or a 5xx from post_form inside the poll loop must not end the sign-in while the code is live. Retry on the next interval until deadline; a 4xx with an OAuth error field keeps today's handling. Pin it with a fake GitHub that fails one poll with a connection reset and one with a 502 before it returns the token.

  2. Callback page text (thread on await_callback, auth.rs line 452). The page answers "Signed in to GitHub" before the token exchange and the keychain write have run. Use neutral text, such as "Return to the terminal to finish signing in.", and keep the terminal as the only place that says the sign-in succeeded.

  3. Error text names the next step (thread on SignInError, signin.rs line 238). Corrupt says to run min auth login to replace the item. encode_secret's rejection of a token with unexpected characters is not Corrupt: give it its own variant (or Account-style text) that says GitHub returned a token in an unexpected form and nothing was saved, since the held item is intact. A missing keychain tool names the tool (secret-tool or /usr/bin/security) and what to install.

  4. Zeroize every copy of the material (thread on secret, signin.rs line 580). Both host::secret implementations copy out.stdout into a plain String and leave the buffer; zeroize out.stdout after decoding and build Material without an extra lingering copy. The same applies to the text String in post_form for the token endpoint, which holds the raw token JSON: zeroize it after parsing.

Then reply on each of the four threads with the commit, as before. The two threads on BUILT_IN_SECRET are a recorded decision under review by the epic owner; leave them.


Generated by Claude Code

@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 review of e029b5b (T12: min auth login and min auth status, the sign-in item in bep::signin). Read as a COMMENT review so it starts no coder round.

What I checked. The item is one keychain entry with the material and the metadata as separate parts; status reads only the metadata. store_sign_in keeps the instance identifier on a same-account login, mints one on a first login or an account switch, and returns before any write on a refused read. The macOS backend writes through security -i on stdin so the secret never reaches a command line, and reads the metadata back after the write. The Secret Service backend stores on the single service attribute with no prior clear and zeroizes the captured search output. The browser flow carries PKCE S256 with a 64-hex verifier, checks the state, serves each callback connection in its own task under a 10 s read limit, and exchanges the code with the client secret. The device flow honours slow_down and the code's expiry. Tokens are validated to the character set every keychain command carries unquoted. The tests cover both flows against a fake GitHub, the keychain-only storage, the instance rules, the refused-read case, the status texts and the RFC 7636 vector. No blocking finding from me.

Findings, none blocking. The four runtime findings that still hold (device poll retries, callback page text, error next steps, zeroizing the remaining copies) are in the round-3 revise. One more of the same class is folded into that revise: post_form keeps the raw token JSON in a String that is not zeroized.

For the epic owner. The two open threads on BUILT_IN_SECRET (HIGH and MEDIUM, embedded App client secret in the shipped binary) are disputed by the coder as a recorded decision, and minimal-arch's PASS ruling on this head names "the embedded public secret as a recorded decision". A security thread stays open until the owner rules. Nothing else holds the PR once round 3 lands and the arch re-passes.


Generated by Claude Code

A damaged item now says to run min auth login to replace it. A token in
an unexpected form gets its own error that says nothing was saved. A
missing secret-tool or /usr/bin/security names the tool and what to
install. Both keychain reads build Material from the captured output
and zeroize it, and the macOS write zeroizes its command line.
A network error, a timeout or a 5xx on a device-flow poll no longer
ends the sign-in while the code is live. The poll retries on the next
interval. The callback page no longer says the sign-in succeeded before
the exchange and the keychain write run. Token endpoint replies are
zeroized after they parse.
@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 · the full ruling

This push conforms to Gatehouse §6.10 line 839. It does not change the earlier PASS. The device poll retries only until the code expires, so the sign-in still fails closed. A token that the item cannot store is refused before the write, so the held sign-in stays the same. The wipes of token copies in memory go further than the design requires, and the design does not forbid them. No conditions.

Ruled at 54c42fb against gominimal/arch@3dab1097cda1 by claude-opus-5-5.

@minimal-foundry minimal-foundry Bot left a comment
< 8 div clas 10BC8 s="timeline-comment-actions flex-shrink-0 d-flex flex-items-center">
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/bep/src/signin.rs Resolved
Comment thread crates/bep/src/signin.rs Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 3 of 10 on a /revise note, pushed as 54c42fb05786.

line exit tail
cargo nextest run -p minimal auth_login_completes_device_flow_and_reports_account 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-1114... 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
cargo nextest run -p minimal auth_login_completes_browser_pkce_flow 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-1c9c... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_login_without_built_in_secret_takes_device_flow 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-d3ba... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_status_reports_expiry_without_token 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-6df6... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling mlog v0.0.1 (/workbench/crates/mlog) Compiling minimal-clie
cargo nextest run -p minimal auth_status_reports_renewal_of_expired_sign_in 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-03ff... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_login_stores_material_in_keychain_only 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-9b3b... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal a_sign_in_with_no_held_item_is_a_new_instance 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-d4b8... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal re_login_to_the_same_account_keeps_the_instance 0 Applying loadouts: default Running task runtime-implement-test-7 in session task-runtime-implement-test-7-8c7d... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.

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-acb7...
    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 stdlib v0.0.22 (/workbench/crates/stdlib)
   Compiling version v0.8.0 (/workbench/crates/version)
    Checking switch v0.0.1 (/workbench/crates/switch)
   Compiling minvmd v0.8.0 (/workbench/crates/minvmd)
    Checking diagnostics v0.0.1 (/workbench/crates/diagnostics)
    Checking common v0.0.1 (/workbench/crates/common)
    Checking bep v0.0.1 (/workbench/crates/bep)
    Checking mlog v0.0.1 (/workbench/crates/mlog)
    Checking async-dialog v0.0.1 (/workbench/crates/async-dialog)
    Checking wait-timeout v0.2.1
    Checking boxes v0.0.1 (/workbench/crates/boxes)
    Checking sandbox v0.0.1 (/workbench/crates/sandbox)
    Checking bit-vec v0.8.0
    Checking quick-error v1.2.3
    Checking mfile v0.0.1 (/workbench/crates/mfile)
    Checking minimald-rpc v0.0.1 (/workbench/crates/minimald-rpc)
    Checking rusty-fork v0.3.1
    Checking bit-set v0.8.0
    Checking checkouts v0.0.1 (/workbench/crates/checkouts)
    Checking decode v0.0.1 (/workbench/crates/decode)
    Checking rand_xorshift v0.4.0
    Checking unarray v0.1.4
    Checking graph v0.0.1 (/workbench/crates/graph)
    Checking proptest v1.11.0
    Checking lcache v0.0.1 (/workbench/crates/lcache)
    Checking rcache v0.0.1 (/workbench/crates/rcache)
    Checking op v0.0.1 (/workbench/crates/op)
    Checking orchestrator v0.0.1 (/workbench/crates/orchestrator)
    Checking check v0.0.1 (/workbench/crates/check)
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...

min auth login completes the device flow and names the account, also when one poll gets a connection reset and one gets a 502. min auth status shows the expiry and no token. The browser tab says only to return to the terminal, and the terminal is the one place that says the sign-in succeeded.

Notes from the agent: Round 3 addresses the four findings in the /revise note. (1) Device poll retries: commit 54c42fb (thread PRRT_kwDOPdfcxM6uHH43). A network error, a timeout or a 5xx on a poll is retried on the next interval until the deadline. A 4xx whose body carries an OAuth error now goes through the same match as a 200 with one. Any other 4xx still stops the sign-in. The new test auth_login_device_poll_retries_transient_failures pins it with a fake GitHub that resets the first poll (zero linger) and answers the second with a 502. (2) Callback page: commit 54c42fb (thread PRRT_kwDOPdfcxM6uHH5E). The page now reads "Return to the terminal to finish signing in." (3) Error text: commit 4afac86 (thread PRRT_kwDOPdfcxM6uHH5J). Corrupt says to run min auth login to replace the item. The new SignInError::Token says GitHub returned a token in an unexpected form, that nothing was saved, and that any sign-in held before is unchanged. The new SignInError::MissingTool names secret-tool (libsecret-tools on Debian and Ubuntu, libsecret on Fedora and Arch) or /usr/bin/security (part of macOS). The new test auth_login_with_an_odd_token_keeps_the_held_item pins the Token case. (4) Zeroize: commit 4afac86 and commit 54c42fb (thread PRRT_kwDOPdfcxM6uHH5N). host::secret is now host::material. It decodes Material from a borrowed view of out.stdout and then zeroizes the buffer on every path. The macOS write also zeroizes its security -i command line, which holds the secret. post_form and the poll zeroize the reply text after they parse it. Outside the note: crates/minimal/Cargo.toml gets zeroize.workspace = true, and Cargo.lock gets that one dependency…[truncated]

Copy link
Copy Markdown
Member

/revise Round 3 is verified. minimal-arch rules PASS on 54c42fb. This round takes the two runtime findings raised on that head and nothing else.

  1. valid_account refuses Enterprise Managed User logins (thread on signin.rs line 166). GitHub logins on github.com can carry an underscore (handle_shortcode for EMU accounts). Allow _ in valid_account and in the metadata round trip, keep the 64-character limit, and add the case to the account test. Check Metadata::encode/decode still split cleanly: _ is not a separator there, so no change is expected beyond the predicate.

  2. min auth status must not read the token on Linux (thread on signin.rs line 607). secret-tool search prints the secret with the attributes, so every status call pulls the token pair into this process before you zeroize it, which breaks the BEP-004 claim in the module doc. Keep the metadata in an item that holds no token: store the metadata as a second item under its own service name (for example dev.minimal.github-sign-in.meta) whose secret is the encoded metadata, write both items in host::write, and read the metadata with secret-tool lookup on the meta service so no token leaves the keyring on status. Keep the read-back check after the write. On macOS the -j comment read already carries no secret, so leave that backend as it is. Say in the module doc which backend holds the metadata where, and update the test that asserts the metadata holds no token so it covers the two-item layout through MemoryKeychain.

Reply on both threads with the commit. The two BUILT_IN_SECRET threads are reopened and wait for the epic owner; leave them.


Generated by Claude Code

valid_account now accepts `_`, so an Enterprise Managed User login
(handle_shortcode) signs in and its metadata decodes.

On the Secret Service, the metadata moves to a second item under
dev.minimal.github-sign-in.meta whose secret is the encoded metadata.
min auth status reads it with secret-tool lookup, so no token enters
the process. The macOS backend is unchanged.
@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 · 1 condition · the full ruling

The Linux layout now keeps the instance identifier only in the META_SERVICE item. The token item holds no identifier. host::write stores the token item first and the metadata item second. If the second store fails on a different-account login, the old instance names the new account's token. Section 6.10 line 839 says the keychain item carries the per-instance identifier and a new account is a new instance that no outstanding reference names. Make the change in C1. Then the change conforms.

Ruled at 4dc1dfd against gominimal/arch@3dab1097cda1 by claude-opus-5-5.

Comment thread crates/bep/src/signin.rs Resolved
Comment thread crates/bep/src/signin.rs Resolved
@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/bep/src/signin.rs Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 4 of 10 on a /revise note, pushed as 4dc1dfda073d.

line exit tail
cargo nextest run -p minimal auth_login_completes_device_flow_and_reports_account 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-4c9a... 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
cargo nextest run -p minimal auth_login_completes_browser_pkce_flow 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-4505... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_login_without_built_in_secret_takes_device_flow 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-1238... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_status_reports_expiry_without_token 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-d033... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_status_reports_renewal_of_expired_sign_in 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-371e... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_login_stores_material_in_keychain_only 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-089c... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal a_sign_in_with_no_held_item_is_a_new_instance 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-9e22... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal re_login_to_the_same_account_keeps_the_instance 0 Applying loadouts: default Running task runtime-implement-test-7 in session task-runtime-implement-test-7-a674... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.

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-c5de...
    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 stdlib v0.0.22 (/workbench/crates/stdlib)
   Compiling version v0.8.0 (/workbench/crates/version)
    Checking switch v0.0.1 (/workbench/crates/switch)
   Compiling minvmd v0.8.0 (/workbench/crates/minvmd)
    Checking diagnostics v0.0.1 (/workbench/crates/diagnostics)
    Checking bep v0.0.1 (/workbench/crates/bep)
    Checking mlog v0.0.1 (/workbench/crates/mlog)
    Checking async-dialog v0.0.1 (/workbench/crates/async-dialog)
    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 mfile v0.0.1 (/workbench/crates/mfile)
    Checking minimald-rpc v0.0.1 (/workbench/crates/minimald-rpc)
    Checking checkouts v0.0.1 (/workbench/crates/checkouts)
    Checking decode v0.0.1 (/workbench/crates/decode)
    Checking graph v0.0.1 (/workbench/crates/graph)
    Checking lcache v0.0.1 (/workbench/crates/lcache)
    Checking rcache v0.0.1 (/workbench/crates/rcache)
    Checking op v0.0.1 (/workbench/crates/op)
    Checking check v0.0.1 (/workbench/crates/check)
    Checking orchestrator v0.0.1 (/workbench/crates/orchestrator)
    Checking mctx v0.0.1 (/workbench/crates/mctx)
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 — PRRT_kwDOPdfcxM6uG4gF: No change this round. The embedded secret is the published App's public client secret, which the spec records (BEP-001). A build without MINIMAL_GITHUB_APP_CLIENT_SECRET takes the device flow. The thread waits for the epic owner's ruling, as the round note says. (not posted on the thread: not an open thread on the pull request)
  • 👎 invalid — PRRT_kwDOPdfcxM6uHH4-: No change this round. This is the same finding as the other BUILT_IN_SECRET thread. The task fixes the secret as option_env!("MINIMAL_GITHUB_APP_CLIENT_SECRET"), and a build without it takes the device flow. The thread waits for the epic owner's ruling. (not posted on the thread: not an open thread on the pull request)
  • 👍 valid — crates/bep/src/signin.rs:184: 4dc1dfd: valid_account accepts _ with the 64-character limit. The device-flow account test signs in octo_emu and decodes its metadata back.
  • 👍 valid — PRRT_kwDOPdfcxM6uJWY_: 4dc1dfd: on Linux the metadata is a second item under dev.minimal.github-sign-in.meta, read with secret-tool lookup, so status reads no token. The module doc names where each backend keeps it. The test checks the two-item layout through MemoryKeychain. (not posted on the thread: not an open thread on the pull request)

min auth login completes the device flow and names the account, also for an Enterprise Managed User login such as octo_emu. min auth status shows the expiry and no token. On Linux it now reads only the metadata item, so no token enters the process.

Notes from the agent: Round 4 addresses the two runtime findings in commit 4dc1dfd. (1) valid_account accepts _ and keeps the 64-character limit. Metadata::encode/decode split on spaces and =, so they need no change. The EMU case is in auth_login_completes_device_flow_and_reports_account, because no separate account test existed. (2) On the Secret Service, host::write stores the token item under dev.minimal.github-sign-in and then a second item under dev.minimal.github-sign-in.meta (META_SERVICE) whose secret is the encoded metadata. host::metadata uses secret-tool lookup service dev.minimal.github-sign-in.meta. The read-back check in HostKeychain::write is unchanged. The macOS backend is unchanged. The module doc says which backend keeps the metadata where. MemoryKeychain now models the two-item layout and has an item(service) accessor. auth_login_stores_material_in_keychain_only asserts that the META_SERVICE item holds no token. If the token store succeeds and the metadata store fails, the old metadata stays, and the read-back 10BC8 reports the failed write. The Linux host path is not exercised by a test on this box, because it needs a running Secret Service. Other runs: cargo nextest run -p minimal cmd::auth (12 passed) and cargo test -p bep (11 passed, 1 ignored). The two BUILT_IN_SECRET threads wait for the epic owner, so they get no change this round.

Copy link
Copy Markdown
Member

/revise minimal-arch ruled CONDITIONS on 4dc1dfd (check run 118386649812): one condition, and the runtime raised the same point on host::write. Take it this round and nothing else; arch PASS is otherwise in hand.

C1, crates/bep/src/signin.rs: the token item carries the instance identifier. (1) encode_secret takes the Metadata too and writes v1 <instance> <token> <refresh token>. (2) decode_secret parses that form, checks the instance with valid_instance, and returns it in a new Material::instance: String field; Debug stays redacted and Drop zeroizes the tokens as before. (3) HostKeychain::write and MemoryKeychain::write pass metadata to encode_secret. (4) Update the module doc: the token item under SERVICE carries the instance identifier, and the META_SERVICE item is a token-free copy for min auth status. Then the item a reference resolves names its own instance, so a torn Linux write (token stored, metadata store failed) cannot put a new account's token under an instance that an outstanding reference binds. (5) In crates/minimal/src/cmd/auth.rs a_sign_in_with_no_held_item_is_a_new_instance, sign in as a second account over a held item, then assert that keychain.material() returns the new instance, that the SERVICE item holds no old instance, and that the material's instance equals keychain.metadata()'s.

Reply on the two arch threads (signin.rs lines 433 and 671) and the runtime's write thread with the commit. The two BUILT_IN_SECRET threads are the epic owner's; leave them open.


Generated by Claude Code

The token item now stores v1 <instance> <token> <refresh token>, and a
read returns the instance in Material::instance. A torn Linux write can
no longer put a new account's token under an instance that an
outstanding reference binds.
@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 · the full ruling

The compare since 4dc1dfd has one PR commit. It puts the instance identifier into the token item, so the item that holds the material names its own instance. Section 6.10 line 839 says the keychain item carries a per-instance identifier and references bind it. A torn Linux write can no longer put a new account's token under an old instance. The rest of the change keeps its earlier status. The change conforms.

Ruled at 0d3334d against gominimal/arch@3dab1097cda1 by claude-opus-5-5.

@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/minimal/src/cmd/auth.rs Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 5 of 10 on a /revise note, pushed as 0d3334d505fa.

line exit tail
cargo nextest run -p minimal auth_login_completes_device_flow_and_reports_account 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-ff90... 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
cargo nextest run -p minimal auth_login_completes_browser_pkce_flow 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-04a4... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_login_without_built_in_secret_takes_device_flow 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-7c14... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_status_reports_expiry_without_token 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-cfae... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_status_reports_renewal_of_expired_sign_in 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-6d8e... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_login_stores_material_in_keychain_only 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-2ed0... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal a_sign_in_with_no_held_item_is_a_new_instance 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-f010... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal re_login_to_the_same_account_keeps_the_instance 0 Applying loadouts: default Running task runtime-implement-test-7 in session task-runtime-implement-test-7-7739... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.

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-3eb7...
    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 stdlib v0.0.22 (/workbench/crates/stdlib)
   Compiling version v0.8.0 (/workbench/crates/version)
    Checking switch v0.0.1 (/workbench/crates/switch)
    Checking bep v0.0.1 (/workbench/crates/bep)
   Compiling minvmd v0.8.0 (/workbench/crates/minvmd)
    Checking diagnostics v0.0.1 (/workbench/crates/diagnostics)
    Checking common v0.0.1 (/workbench/crates/common)
    Checking mlog v0.0.1 (/workbench/crates/mlog)
    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 mfile v0.0.1 (/workbench/crates/mfile)
    Checking minimald-rpc v0.0.1 (/workbench/crates/minimald-rpc)
    Checking checkouts v0.0.1 (/workbench/crates/checkouts)
    Checking decode v0.0.1 (/workbench/crates/decode)
    Checking graph v0.0.1 (/workbench/crates/graph)
    Checking lcache v0.0.1 (/workbench/crates/lcache)
    Checking rcache v0.0.1 (/workbench/crates/rcache)
    Checking op v0.0.1 (/workbench/crates/op)
    Checking check v0.0.1 (/workbench/crates/check)
    Checking orchestrator v0.0.1 (/workbench/crates/orchestrator)
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 — PRRT_kwDOPdfcxM6uG4gF: No change this round. The embedded App client secret is a recorded decision (BEP-001 note, Gatehouse 6.10), and a build without the variable takes the device flow. The epic owner decides whether it stands. (not posted on the thread: not an open thread on the pull request)
  • 👎 invalid — PRRT_kwDOPdfcxM6uHH4-: No change this round. This is the same finding as the other BUILT_IN_SECRET thread. The task fixes option_env!("MINIMAL_GITHUB_APP_CLIENT_SECRET"), and the epic owner decides whether that stands. (not posted on the thread: not an open thread on the pull request)
  • 👍 valid — crates/bep/src/signin.rs: In 0d3334d, encode_secret takes the Metadata and writes v1 <instance> <token> <refresh token>. decode_secret checks the instance and returns it in Material::instance.
  • 👍 valid — crates/bep/src/signin.rs:695: In 0d3334d, the token item carries its own instance, so a torn write cannot put the new token under the old instance. a_sign_in_with_no_held_item_is_a_new_instance asserts this after a second-account sign-in.
  • 👍 valid — PRRT_kwDOPdfcxM6uKABq: In 0d3334d, the secret that host::write stores first names the new instance. If the metadata store then fails, the old instance in the metadata does not match the token item, and no reference bound to the old instance resolves the new token. (not posted on the thread: not an open thread on the pull request)

min auth login completes the device flow and names the account, and min auth status shows the expiry and no token. The token item in the host keychain now also names its own instance identifier, so after a sign-in to a second account the token item and the metadata agree on the new instance.

Notes from the agent: This round addresses only C1, as the directive asks. encode_secret takes the Metadata and writes v1 <instance> <token> <refresh token>. decode_secret checks the instance with valid_instance and returns it in the new Material::instance field. Debug stays redacted, and Drop zeroizes the two tokens as before. A write ignores Material::instance and stores the metadata's instance, so callers that build a Material before store_sign_in picks the instance set it to an empty string. The secret format changed, so an item written by an earlier build of this branch reads as damaged, and the error tells the person to run min auth login. No released build wrote the old format. Commit 0d3334d. After the tests passed, I changed one code comment in host::write, and the only check I ran after that was cargo fmt --check. I did not run just clippy-strict.

@norrietaylor norrietaylor changed the title T12 — Sign in to GitHub with min auth and keep the sign-in in one keychain item feat(min): sign in to GitHub under the published App and keep the sign-in in the host keychain Oct 20, 2026
@norrietaylor norrietaylor changed the title feat(min): sign in to GitHub under the published App and keep the sign-in in the host keychain feat(min): sign in to GitHub under the published App, kept in the host keychain Oct 20, 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.

Approving for merge: T12 after the person's secret ruling and the arch PASS on 0d3334d. Gate passes on 0d3334d (arch PASS, review approved, lanes green, squash subject lint-clean).


Generated by Claude Code

@norrietaylor
norrietaylor added this pull request to the merge queue Oct 20, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 20, 2026
Copy link
Copy Markdown
Member

/revise Base merge only. The merge queue built 0d3334d on top of main (767c59f, T13) as a9f01f6 and every Linux lane failed before compiling (run 39364695161, clippy job): error: duplicate key --> crates/minimal/Cargo.toml:76:1 | bep = { path = "../bep" }. T13 added the same bep = { path = "../bep" } dependency to crates/minimal/Cargo.toml (line 74 on main, after boxes.workspace = true), and this branch adds it at line 72 with its min auth comment. Git merges the two cleanly, so the manifest ends up with the key twice and cargo refuses the workspace. The queue dropped the entry. Do this, in order:

  1. Merge origin/main (767c59f) into the branch. In crates/minimal/Cargo.toml keep exactly one bep = { path = "../bep" } line (keep this branch's placement and its comment, drop the duplicate main carries); regenerate Cargo.lock with cargo, never by hand.
  2. Run just fix and just test on the merged tree and fix only what the merge breaks (a second definition, a moved import, a doubled pub mod). The branch's own changes are already reviewed and arch PASS at 0d3334d: change nothing in auth.rs, signin.rs or the tests beyond merge fallout.
  3. Reply on no threads. The next head goes back through the gate and the queue.

Generated by Claude Code

The merge with main carried bep twice in the manifest, and cargo
refused the workspace. Keep one line and fold both uses into its comment.
@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 · the full ruling

The compare since 0d3334d5 merges main twice and removes a duplicate bep line from crates/minimal/Cargo.toml. The sign-in code (signin.rs, auth.rs, cli.rs) has no change. Gatehouse §6.10 line 839 still governs it, and the PASS on 0d3334d5 stands. The change conforms. There are no conditions.

Ruled at b7145f6 against gominimal/arch@3dab1097cda1 by claude-opus-5-5.

@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/minimal/src/cmd/auth.rs Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

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

line exit tail
cargo nextest run -p minimal auth_login_completes_device_flow_and_reports_account 0 Applying loadouts: default Running task runtime-implement-test-0 in session task-runtime-implement-test-0-2865... 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
cargo nextest run -p minimal auth_login_completes_browser_pkce_flow 0 Applying loadouts: default Running task runtime-implement-test-1 in session task-runtime-implement-test-1-222f... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_login_without_built_in_secret_takes_device_flow 0 Applying loadouts: default Running task runtime-implement-test-2 in session task-runtime-implement-test-2-612d... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_status_reports_expiry_without_token 0 Applying loadouts: default Running task runtime-implement-test-3 in session task-runtime-implement-test-3-2e58... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_status_reports_renewal_of_expired_sign_in 0 Applying loadouts: default Running task runtime-implement-test-4 in session task-runtime-implement-test-4-0630... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal auth_login_stores_material_in_keychain_only 0 Applying loadouts: default Running task runtime-implement-test-5 in session task-runtime-implement-test-5-5675... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal a_sign_in_with_no_held_item_is_a_new_instance 0 Applying loadouts: default Running task runtime-implement-test-6 in session task-runtime-implement-test-6-0ebe... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.
cargo nextest run -p minimal re_login_to_the_same_account_keeps_the_instance 0 Applying loadouts: default Running task runtime-implement-test-7 in session task-runtime-implement-test-7-3e4e... Compiling stdlib v0.0.22 (/workbench/crates/stdlib) Compiling version v0.8.0 (/workbench/crates/version) Compiling decode v0.0.1 (/workbench/crates/decode) Compiling mlog v0.

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.

st-types v0.14.4
    Checking google-cloud-gax v1.15.0
    Checking opentelemetry_sdk v0.33.0
    Checking hyper-util v0.1.20
    Checking tracing-opentelemetry v0.34.0
    Checking hyper-rustls v0.27.9
    Checking hyper-timeout v0.5.2
    Checking logos v0.16.1
    Checking tonic v0.14.6
    Checking topiary-tree-sitter-facade v0.7.3 (https://github.com/tweag/topiary.git?rev=838c74ab4058f82bc3c6a12380f22c10f22ac814#838c74ab)
    Checking reqwest v0.13.5
    Checking nickel-lang-parser v0.4.0
    Checking topiary-core v0.7.3
    Checking tonic-prost v0.14.6
    Checking google-cloud-auth v1.17.0
    Checking tree-sitter-nickel v0.5.0
    Checking ot v0.0.1 (/workbench/crates/ot)
    Checking paths v0.0.1 (/workbench/crates/paths)
   Compiling stdlib v0.0.22 (/workbench/crates/stdlib)
   Compiling version v0.8.0 (/workbench/crates/version)
    Checking google-cloud-gax-internal v0.7.20
    Checking opentelemetry-http v0.33.0
    Checking google-cloud-longrunning v1.14.0
    Checking google-cloud-iam-v1 v1.13.0
    Checking google-cloud-lro v1.11.0
    Checking opentelemetry-proto v0.33.0
    Checking opentelemetry-appender-tracing v0.33.0
    Checking google-cloud-storage v1.20.0
    Checking opentelemetry-otlp v0.33.0
    Checking async-tar v0.6.1
    Checking mlog v0.0.1 (/workbench/crates/mlog)
    Checking switch v0.0.1 (/workbench/crates/switch)
    Checking bep v0.0.1 (/workbench/crates/bep)
   Compiling minvmd v0.8.0 (/workbench/crates/minvmd)
    Checking diagnostics v0.0.1 (/workbench/crates/diagnos
10BC8
tics)
    Checking async-dialog v0.0.1 (/workbench/crates/async-dialog)
    Checking nickel-lang-core v0.19.0
    Checking args v0.0.1 (/workbench/crates/args)
    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 mfile v0.0.1 (/workbench/crates/mfile)
    Checking minimald-rpc v0.0.1 (/workbench/crates/minimald-rpc)
    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...

min auth login completes the device flow and names the account, and min auth status shows the expiry and no token. The branch now builds on top of main, because crates/minimal/Cargo.toml carries the bep dependency once.

Notes from the agent: Base merge round. The merge commit c367d6a with origin/main (767c59f) was already on the branch. It left bep = { path = "../bep" } twice in crates/minimal/Cargo.toml. I kept the line in this branch's place and dropped the duplicate from main. I folded main's comment (activation checks a grant box's egress against the GitHub host set) into this branch's comment. Cargo.lock needed no change: cargo metadata left it unchanged, because the lock already has one bep edge. auth.rs, signin.rs and the tests are unchanged. just fix applied one clippy fix to crates/minimald/src/net/switch.rs (chunks_exact to as_chunks). That code comes from main and is not merge fallout, so I reverted the fix. The other remaining lints are in minimald and minimald-rpc code from main (result_unit_err, chunks_exact), and I did not change them. In just test, the sandbox test caps_root_integration boxes_lack_cap_net_raw failed (socket family filter: errno 1, expected 97). Neither this branch nor the merge touches crates/sandbox, so this box's environment is the cause. No threads to answer.

@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.

Own review carried to b7145f6. This head is round 6 on the base-merge directive: two merges of main (767c59f then abbdb31) and one commit, 178726c, that drops the duplicate bep = { path = "../bep" } line from crates/minimal/Cargo.toml (one line remains, at 74, with the min auth comment). The branch's own diff against main is the same 7 files as at 0d3334d. minimal-arch ruled PASS on this head. The runtime review's one finding (LOW, the embedded App secret) is the point the epic owner already ruled on; resolved with that ruling. Approval follows once the KVM and macOS lanes are green.


Generated by Claude Code

@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.

Approving for merge: T12 on the round-6 base-merge head b7145f6 (arch PASS 118448851499, duplicate bep dependency dropped). Gate passes on b7145f6 (arch PASS, review concluded with no open threads, lanes green, squash subject lint-clean).


Generated by Claude Code

@norrietaylor
norrietaylor added this pull request to the merge queue Oct 20, 2026
Merged via the queue into main with commit 5919d28 Oct 20, 2026
37 checks passed
@norrietaylor
norrietaylor deleted the agent/2263-sign-in-to-github-with-min-auth-and-keep-the-sig branch October 20, 2026 06:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet
42E9

Development

Successfully merging this pull request may close these issues.

T12 — Sign in to GitHub with min auth and keep the sign-in in one keychain item

1 participant

0