Skip to content

fix(license,mcp,reset): scrub human stderr, gate legacy MCP secrets, clean image-switch volumes (D-0979, D-0737, D-0802) - #984

Open
acamarata wants to merge 4 commits into
mainfrom
dw6-cli-4
Open

acamarata wants to merge 4 commits into
mainfrom
dw6-cli-4

Conversation

@acamarata

Copy link
Copy Markdown
Collaborator

Summary

Fixes three medium-severity technical-debt rows from hq quality/debt.yaml.

D-0979 — license validate/migrate human stderr leaks server text and raw key

  • Route human-mode error diagnostics in license validate and license migrate through licenseScrub so --json runs no longer echo unscrubbed server text on stderr.
  • Move the license key out of the GET query string in fetchMigrationStatus; use req.URL.Query().Set so net/http errors no longer carry ?key=<raw>.

D-0737 — legacy MCP nself_config_set bypasses secret-key gate

  • Refuse config.IsSecretKey keys in the v1.4 legacy nself_config_set handler when !compat.V15(), closing the path that let a token-less loopback client write POSTGRES_PASSWORD without confirmation. V1.5 replaces this tool with the generated gated version (P7-SURF-03).

D-0802 — reset/uninstall/stop --volumes miss image-switch postgres volumes

  • Add docker.VolumeListByLabel to list volumes by label.
  • After compose down --volumes, remove any volumes carrying the org.nself.image-switch label in reset, uninstall --purge, and stop --volumes, so old postgres data volumes left behind by db image switch are actually cleaned up.

Verification

  • go build ./cmd/commands/... ./internal/docker/... — pass
  • go vet ./cmd/commands/... ./internal/docker/... — pass
  • go test ./cmd/commands/ -run 'Reset|Uninstall|Stop|License|Migrate|Scrub|MCP|ConfigSet' -count=1 — pass (64s)

Not addressed

  • D-0698: BLOCKED — requires an ADR-level ruling on promote step order (apply vs migrate vs health); not a local code fix.
  • D-0791: BLOCKED — requires traefik provider migration (model custom domains as routes, add acmeRun.reloader()/servedEnv()); tied to P7-DEPL-25 scope.

@acamarata

Copy link
Copy Markdown
Collaborator Author

Review fixes pushed (9f49dee), branch rebased onto main (S3_SECRET_KEY change from #982 is now in the base).

D-0802 (volumes). The previous cleanup labelled only the new volume, listed every volume with the switch label on the host, and ignored list errors. Replaced by one hook in ComposeDown: after a successful down -v it removes the old volume recorded in .nself/image-switch/state.json plus volumes carrying both the switch label and this project's com.docker.compose.project label. Other projects' volumes are not listed; a volume labelled for a different project is skipped. List and removal errors fail the down, so reset (including its JSON kept_data), stop --volumes and uninstall --purge no longer report the data gone when it is not. This also keeps cmd/commands at its package-size ceiling (the earlier call sites broke TestPackageSizeBudget and the 300-line cap on uninstall.go).

D-0979 (key in URL). The PR text was wrong: the ping_api (web/.../license-migration.ts) reads the key only from the GET query string, so it cannot move without a server change. The key stays in the query, URL-encoded. The real fix is that net/http transport errors quote the full URL, so httptimeout.StripURL now drops it and the key can no longer print. license refresh uses POST /license/validate and prints fixed codes; a new test pins that for an unreachable server.

D-0737. Added the legacy secret-key refusal test (v1.4 refuses, non-secret key still written, v1.5 not affected); the guard is now config.RefuseLegacyMCPSecretSet.

Proof: each new test fails with its fix reverted (secret guard off, StripURL off, unscoped listing / no old volume, hook off) and passes with it. go vet ./..., gofmt, and tests for cmd/commands, repoqa, docker, postgres, config, httptimeout, license and importer all pass.

@acamarata

Copy link
Copy Markdown
Collaborator Author

CI fix pushed (c985000), rebased onto main. The only failing check was contract-check: compat-markers.sh --check reported two unmarked compat.V15() calls. validator.go:181 is fixed on main (#985) and came in with the rebase. secretkeys.go (RefuseLegacyMCPSecretSet, D-0737) is this PR's own call, so it now has its compat.V15(D-0737) marker and a row in the generated Compat-V15 wiki table. compat-markers.sh --check exits 0 now; config tests pass. The 'tar: File exists' lines in the CI log are harmless cache noise.

…clean image-switch volumes (D-0979, D-0737, D-0802)
…ject, keep the key out of errors, test the MCP secret guard (D-0802, D-0979, D-0737)

- D-0802: compose down -v now removes the old data volume a db image switch
  kept plus the project's switch-labelled volumes, found from the switch state
  and the compose project label, so other projects' volumes are never listed.
  List and removal errors fail the down instead of being swallowed. One hook
  in ComposeDown covers reset, stop --volumes and uninstall --purge, so
  cmd/commands does not grow (package-size ratchet).
- D-0979: the ping_api reads the migration key only from the GET query, so it
  stays there URL-encoded; transport errors now drop the request URL so the key
  never prints. license refresh is pinned to its fixed failure codes.
- D-0737: add a legacy secret-key refusal test for nself_config_set.
@acamarata

Copy link
Copy Markdown
Collaborator Author

No review findings were attached, so I looked at the red checks and the base.

  • Rebased onto origin/main (3 commits, no conflicts); force-with-lease push.
  • Vet, Build & Test (windows-2022): TestMigrateSupabaseModes/v1.4 is a timing flake, not this PR. supabase-migration.sql embeds a one-second timestamp and the test compares it byte for byte with a second Generate call. Reproduced with a 1.1s skew (fails before, passes after). The test now normalizes only the -- Generated: line (5cc0495); the other artifacts still compare exactly.
  • Coverage: internal/nginxtopo 93.5% floor 98% is red on main too (86627b8, 9169cbc) and the PR does not touch that package. Left alone; needs its own fix or a floor decision.

This branch has not been deployed

No deployments
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.

1 participant