Skip to content

fix(acq): bind GitHub token at create by prompting before provision - #386

Merged
mogul merged 4 commits into
mainfrom
fix/acq-github-token-injection
Aug 26, 2026
Merged

fix(acq): bind GitHub token at create by prompting before provision#386
mogul merged 4 commits into
mainfrom
fix/acq-github-token-injection

Conversation

@mogul

@mogul mogul commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Context

On the MSB backend, secrets are bound at create time (--secret ENV@HOST) — the same constraint the USAi API key already respects (ensure_key_present runs before acq_backend_provision). But the GitHub-token prompt (advise_github_scope) ran after acq_backend_provision, so a token stored during that prompt would never bind to the just-created sandbox.

This makes the GitHub token behave like the USAi key: the prompt to set/scope it now happens before the sandbox is created.

Changes

acq (dispatch):

  • create verb: moved advise_github_scope to run before acq_backend_provision, right after the ensure_key_present USAi gate.
  • run verb, fresh-create branch: added advise_github_scope before acq_backend_provision (it previously only ran post-provision).
  • run verb, re-attach branch: kept an advisory call — a re-attach can't rebind at create, so there it drives the live re-feed path (msb modify / sbx proxy).

The prompt now runs pre-create for all backends and stays warn-and-continue (declining never aborts the create — the GitHub token is optional, consistent with ADR-0013, unlike the USAi gate which fails closed).

Docs:

  • docs/adr/0013-per-sandbox-github-token-downscoping.md — documents the pre-create ordering and rationale.
  • docs/howto/msb.md — notes that both the USAi key and a GitHub token must be in place before create, and that acq run/acq create handle this ordering.

Verification

  • bash -n acq and bash -n scripts/test-acq: clean
  • ./scripts/test-acq: 1142 passed, 0 failed (+3 new msb assertions covering "advisory runs before msb create" and "declined advisory still provisions")
  • shellcheck --severity=warning on acq, acq.backends/common.sh, scripts/test-acq: clean (one file per invocation, per the repo's shellcheck guidance)

Security impact

No change to attack surface. The GitHub token is still read from the TTY (never argv), stored sandbox-scoped, and the real value never enters the guest. Reordering only affects when the prompt fires relative to sandbox creation.

Rollback

Revert the single commit on this branch; the prior post-provision ordering is restored.

@mogul
mogul requested a review from a team as a code owner August 24, 2026 22:27
@mogul
mogul marked this pull request as draft August 24, 2026 22:42
@mogul

mogul commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

Leaving this in the draft state until #370 lands, whereupon we'll need to port the tests to BATS.

@mogul
mogul force-pushed the fix/acq-github-token-injection branch 3 times, most recently from 9be912e to 1773b76 Compare August 25, 2026 19:40
@mogul
mogul marked this pull request as ready for review August 25, 2026 20:31
On msb, secrets bind at create time (--secret ENV@HOST), so the GitHub
token must be stored before the sandbox is created — the same constraint
the USAi key gate already respects. Move advise_github_scope ahead of
acq_backend_provision on the fresh-create path of both create and run.
Warn-and-continue: declining never aborts (the token is optional).
Re-attach keeps a post-heal advisory that drives the live re-feed path.

Co-authored-by: OpenCode [claude_4_8_opus] <bret.mogilefsky@gsa.gov>
@mogul
mogul force-pushed the fix/acq-github-token-injection branch from 19ff091 to b2d9a54 Compare August 25, 2026 21:01

@wz-gsa wz-gsa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Adversarial review — LGTM

Structural correctness verified. `advise_github_scope` is called and returns as its own statement BEFORE `acq_backend_provision "$local_name" "$@"` is invoked (both at the fresh-`create` site and the fresh-create branch of `run`) — so the token write the prompt performs completes before the function that reads secrets to build `--secret` flags is even called. This isn't just "the call moved earlier in the file", it's the right causal ordering. The re-attach branch correctly gets a DIFFERENT treatment (an advisory that drives the live re-feed path, since a re-attach can't re-bind at create) — that distinction is exactly right and easy to get wrong.

Warn-not-block confirmed. Read `advise_github_scope`: on decline it `echo`s a continuation note and `return 0` — no exit code that could abort `create`. Matches ADR-0013 and is the correct contrast with the USAi gate (which fails closed).

Non-interactive path is safe. `[ ! -t 0 ]` short-circuits to advise-and-continue without blocking on a `read` — correct for CI/piped callers.

Non-blocking observations

  1. Stale verification claim in the description: it cites `scripts/test-acq: 1142 passed`, but that runner doesn't exist on this branch (`git show origin/main:scripts/test-acq` — 0 bytes) — it was retired by the bats migration. The actual new coverage is correctly in `test/bats/30-dispatch-routing.bats`; just flagging the prose is stale (likely copied from before the local checkout picked up the migration).

  2. The new test asserts co-occurrence, not sequencing. `create(msb): github advisory runs before provision…` checks `assert_output --partial 'no repo-scoped GitHub token'` AND `assert_regex "$CALLS" 'msb create'` — both true, but that doesn't prove the advisory ran first. I checked: `$CALLS` is a strictly append-only log (one `printf … >>"$CALLS"` per stub invocation), so line order is invocation order — a genuinely-available, cheap strengthening would be asserting the advisory's line number precedes `msb create`'s in `$CALLS` (or having the stub log a sentinel and checking relative position). Not blocking since the source-level ordering is structurally sound and independently verifiable by reading the diff, but a regression that silently moved the call back wouldn't be caught by this test today.

Approve — small, well-scoped, matches the USAi-gate pattern it's modeled on.

AI-assisted (OpenCode).

@mogul
mogul enabled auto-merge (squash) August 26, 2026 22:46
@mogul
mogul merged commit c066206 into main Aug 26, 2026
3 of 5 checks passed
@mogul
mogul deleted the fix/acq-github-token-injection branch August 26, 2026 22:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants