test: isolate the root package from an exported CARLOS_SERVICE_TOKEN (#229)
R-1: resolveMode reads CARLOS_SERVICE_TOKEN, so in-process root-package tests that call run() or a verb directly inherited a token exported by the shell running go test, and log.Fatal killed the test binary. A TestMain in main_test.go unsets it before m.Run(); tests that want one use t.Setenv. R-2: remove the force-added scratch file .superpowers/sdd/2026-10-05-deploy-credential/final-fix-report.md from the index (kept on disk).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2 files changed,
+16
−32
.superpowers/sdd/2026-10-05-deploy-credential/final-fix-report.md+0 −32main_test.go+16 −0
CI passed — run details
diff --git a/.superpowers/sdd/2026-10-05-deploy-credential/final-fix-report.md b/.superpowers/sdd/2026-10-05-deploy-credential/final-fix-report.md| deleted file mode 100644 |
| index 64cc061fc..000000000 |
| --- a/.superpowers/sdd/2026-10-05-deploy-credential/final-fix-report.md |
| +++ /dev/null |
| @@ -1,32 +0,0 @@ |
| -# Final whole-branch review fixes (#229) |
| - |
| -## F-1 subprocess tests inherit CARLOS_SERVICE_TOKEN |
| -Both `carlosTestEnv` helpers (e2e_test.go, scopedkeys_e2e_test.go) now build the child env by filtering any |
| -`CARLOS_SERVICE_TOKEN=` entry out of `os.Environ()` before appending the test overrides. A token a test passes |
| -in `extra` still wins. No production code changed. |
| -Covering: every subprocess test using carlosTestEnv, notably TestScopedKeysCLI and TestRestartSelectorRefusals |
| -(sets CARLOS_DEPLOYMENT_DIR). |
| -Command: `CARLOS_SERVICE_TOKEN=dummy go test . -run 'TestScopedKeysCLI|TestRestartSelectorRefusals|TestE2E|TestAuth' -count=1` |
| -Output: `ok github.com/carlosframework/platform 30.068s` |
| -Note: the whole root package with the token exported still fails, in TestRunDomainsAttachPrintsAttached, an |
| -in-process run() test (not a subprocess helper) that exits with "CARLOS_SERVICE_TOKEN is set but no console is |
| -named". Not touched, outside this finding. Without the token the whole package passes. |
| - |
| -## F-2 deploy rollback of stable got the legacy refusal |
| -internal/console/apicli.go handleAPIRollback: immediately before the legacy stable block, when the channel is |
| -stable, `deployScopeAllows(p, false, channel, false)` runs and a refusal goes through `writeDeployRefusal`. |
| -It returns nil for every other principal, so people and publish credentials get the legacy 403 unchanged. The |
| -later full check after the pipeline read is unchanged. |
| -Test: TestDeployRollbackOfStableIsD22 (deployscope_test.go): deploy gets 403 with |
| -"deploy credential ci may move canary/<name>, edge only, and stable is not one of them." (no console_url), |
| -stable pointer still absent; person gets the legacy text with console_url. |
| - |
| -## F-3 fast-track regression |
| -TestDeployPromoteCannotFastTrack (deploysign_test.go): promote with `fast_track:true` and `fastTrack:true` as a |
| -deploy credential; both promote (200) and the verified edge pointer payload has FastTrack=false. |
| - |
| -## Runs (TMPDIR=/tmp/claude/fx, GOCACHE from original TMPDIR) |
| -- focused console tests: ok |
| -- `go test ./internal/console/ -count=1`: ok .../internal/console 50.510s |
| -- `go test . -count=1`: ok .../platform 225.343s |
| -- gofmt -l: clean |
diff --git a/main_test.go b/main_test.go| new file mode 100644 |
| index 000000000..b8711d2d9 |
| --- /dev/null |
| +++ b/main_test.go |
| @@ -0,0 +1,16 @@ |
| +package main |
| + |
| +import ( |
| + "os" |
| + "testing" |
| +) |
| + |
| +// TestMain keeps an exported deploy token out of the root package's tests. |
| +// resolveMode reads CARLOS_SERVICE_TOKEN, and a CI shell running `go test` |
| +// may well export one. In-process tests that call run() or a verb directly |
| +// would then inherit it. Tests that want a token set it with t.Setenv, which |
| +// still works after this Unsetenv. |
| +func TestMain(m *testing.M) { |
| + os.Unsetenv("CARLOS_SERVICE_TOKEN") |
| + os.Exit(m.Run()) |
| +} |