Skip to content

feat: add status page migration SDK methods#3

Merged
debidong merged 1 commit intomainfrom
feat/statuspage-migration
Apr 20, 2026
Merged

feat: add status page migration SDK methods#3
debidong merged 1 commit intomainfrom
feat/statuspage-migration

Conversation

@debidong
Copy link
Copy Markdown
Collaborator

Summary

Adds four asynchronous status page migration endpoints plus the body-log redaction required to ship them safely.

New public API (statuspage.go)

Method HTTP Endpoint
StartStatusPageMigration POST /status-page/migrate-structure
StartStatusPageEmailSubscriberMigration POST /status-page/migrate-email-subscribers
GetStatusPageMigrationStatus GET /status-page/migration/status
CancelStatusPageMigration POST /status-page/migration/cancel

New exported types: StartStatusPageMigrationInput, StartStatusPageEmailSubscriberMigrationInput, StartStatusPageMigrationOutput (shared by both start methods), StatusPageMigrationProgress, StatusPageMigrationJob.

Both Start* methods return a job ID that can be polled with GetStatusPageMigrationStatus and cancelled with CancelStatusPageMigration.

Body-log redaction hardening (client.go)

These migration endpoints are the first SDK calls that put a third-party credential (source-provider api_key) inside a JSON request body. The existing URL-only sanitization was insufficient — secrets would have been written into request/response logs and propagated through the returned error values. This change:

  • sanitizeBody now recurses into nested maps and arrays.
  • Keys are matched after normalization (case + punctuation insensitive), so API_KEY, Api-Key, apiKey all match.
  • Sensitive-key set expanded to ~23 credential aliases: api_key, apikey, xapikey, accesskey, password, passwd, pwd, token, access_token, refresh_token, id_token, session_token, auth_token, oauth_token, bearer_token, authorization, auth, secret, client_secret, secret_key, private_key, signing_key, credential, credentials.
  • Redaction is applied at all four leak sites: makeRequest request log, parseResponse response log + returned error, handleAPIError log + returned error.

Non-JSON bodies still pass through unchanged (documented via TestReturnedAPIErrorsPreserveNonJSONBody). Redacting plaintext bodies is deferred as optional hardening.

Why one commit not two

The redaction hardening was prompted by this feature (first endpoint to carry a third-party secret in the body). Splitting would produce an unrunnable-as-standalone security commit. Kept as one feature commit to preserve tight coupling.

Test plan

  • go test -race -count=1 ./... green (1.9s)
  • gofmt -l . clean
  • goimports -l . clean
  • go vet ./... clean
  • New-code coverage: sanitizeBody 91.7%, sanitizeJSONValue 100%, parseResponse 88.9%, handleAPIError 91.7%, StartStatusPageMigration 100%, StartStatusPageEmailSubscriberMigration 100%, startStatusPageMigration 86.7%, GetStatusPageMigrationStatus 84.2%, CancelStatusPageMigration 86.7%
  • Wire format cross-checked against fc-statuspage (paths and JSON fields match)
  • Two rounds of independent code review (go-reviewer agent + Codex): one HIGH (api_key logging leak) and two MEDIUMs (nil-input panic, fmt.Errorferrors.New) resolved; Codex expanded redaction scope beyond the original fix

Compatibility

Additive only. No existing public API changed. Intended for a minor bump (v0.6.0 → v0.7.0).

Downstream consumer

This unblocks flashduty-cli#1, which currently ships a CLI-local HTTP transport for these endpoints. Once this release is tagged, the CLI will bump its go.mod, extend its flashdutyClient interface, and port status_page_migrate.go to use the SDK + RunContext pattern.

Add four async status page migration endpoints plus hardened body-log
redaction required to ship them safely.

New public API (statuspage.go):
- StartStatusPageMigration — POST /status-page/migrate-structure
- StartStatusPageEmailSubscriberMigration — POST /status-page/migrate-email-subscribers
- GetStatusPageMigrationStatus — GET /status-page/migration/status
- CancelStatusPageMigration — POST /status-page/migration/cancel

New exported types: StartStatusPageMigrationInput,
StartStatusPageEmailSubscriberMigrationInput,
StartStatusPageMigrationOutput (shared by both start methods),
StatusPageMigrationProgress, StatusPageMigrationJob.

Body-log redaction (client.go):
- sanitizeBody now recurses into nested maps and arrays, normalizes
  keys (case + punctuation insensitive), and covers ~23 credential
  aliases (api_key, authorization, bearertoken, refresh_token,
  client_secret, private_key, etc).
- Applied to request log (makeRequest), response log (parseResponse),
  handleAPIError log, and to the error strings returned from
  parseResponse and handleAPIError — so echoed credentials cannot
  leak either through logs or through the Go error chain.

These migration endpoints are the first SDK calls that put a
third-party credential (source provider api_key) in a JSON request
body, so the existing URL-only sanitization was insufficient.

Tests: httptest-backed coverage per method + per redaction site.
go test -race -count=1 ./... green. New-code coverage:
sanitizeBody 91.7%, sanitizeJSONValue 100%, parseResponse 88.9%,
handleAPIError 91.7%, all migration methods ≥84%.

Additive, backward-compatible. Intended for v0.7.0.
@debidong debidong merged commit d2b32ab into main Apr 20, 2026
@debidong debidong deleted the feat/statuspage-migration branch April 20, 2026 06:35
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