Skip to content

M005: Cutover + Decommission (Phase 5)

Outcome: SyRF users authenticate through BFF cookies backed by OpenIddict; cross-process reset tokens, sessions, rollback, and campaign controls are proven; Auth0 has no live runtime consumer only after 28 days of fallback evidence; and every final external action is authorised and classified.

Plan: 30 slices across 21 dependency waves.

Requirements

ID Requirement Evidence required
M005-R01 Identity/migration code is safe to execute. ≥313-test baseline; real Mongo campaign integration; no vulnerable SharpCompress/Snappier result.
M005-R02 Every Identity setting consumed by the host is supplied by one tested chart-to-host contract. Exact Mongo, Google, SES, OpenIddict, issuer, UI and DataProtection mapping; SYRF__ provider; rendered-chart startup; regenerated schema/blocks/checksums are idempotent.
M005-R03 Identity has a stable external issuer and dependency-aware health. Trusted forwarded-header tests; issuer/discovery assertions; S02 live/basic readiness; S03 encrypted-ring readiness contribution; liveness remains process-only.
M005-R04 Password-reset tokens survive process, replica, and restart boundaries. Shared encrypted Mongo ring used identically by CLI/Endpoint; two tokens generated before redemption; token A redeems before restart and token B through another process/replica after restart; backup proof.
M005-R05 BFF rollout and rollback fail closed. Explicit provider; provider+issuer+generation namespace; BFF-disabled selector ignores cookies; custom Auth0 domain; distinct switch, rollback, and reapply generations/checkpoints.
M005-R06 BFF/campaign security and telemetry are production-safe. Exact effective scheme+host+port CSRF; bounded telemetry; no identifiers/secrets/source paths in argv/logs/diffs/evidence; exact 24-hour queries; worktree/preflight/status/redaction scripts.
M005-R07 Migration/campaign tooling is authoritative, secret-safe, and controllable. Activity/privilege/enabled/Google/locked inputs; three denominators; shared production input resolver; secret-mounted canary; durable canary approval/stop/resume/idempotency tests and Jobs.
M005-R08 A checked-in live staging harness covers the real deployed topology. Password, Google, reset, /me, admin/account, API, SignalR, cross-replica Redis and old-cookie checks; local E2E is regression only.
M005-R09 Staging Identity is dark-launched without altering browser/API auth. Terraform/GitOps changes; authorised exact GCP source/version population; retained Google Auth0 callback; Argo-managed rollout proof; Auth0 Web/API unchanged.
M005-R10 Staging proves cutover, rollback, and reapply as separate checkpoints. OpenIddict live matrix; S09 Auth0 rollback completes/syncs; S27 separately authorised OpenIddict reapply completes/syncs; old cookies fail and recovery is measured.
M005-R11 Production Identity is dark-launched without changing user authentication. Authorised exact production GCP version population; Synced/Healthy Identity; two-token Argo-rollout proof; backup/restore; Web/admin remain Auth0.
M005-R12 Production first moves to BFF cookies backed by Auth0 and establishes a 24-hour baseline. Auth0-log baseline queries exist before rollout; the 24-hour BFF window is itself the authoritative 5xx/callback-p95 baseline; Redis on every replica; explicit provider=auth0; exact authorised Auth0 confidential-client source → enabled syrf-auth0-bff-production version → ExternalSecret mapping; ≥99% login success for exactly 24 hours; fresh rollback generation.
M005-R13 Production migration/campaign reach explicit readiness while Auth0 is live. Distinct GitOps import/verify/rerun and campaign-control Jobs; status inspection; zero rerun writes/sends; reconciliation; 100% privileged, ≥95% active-90-day, ≥90% all-enabled.
M005-R14 Production OpenIddict cutover is atomic and reversible. BFF provider/authority/client/generation and IdentityService change together; smoke/thresholds pass or fresh-generation GitOps rollback completes.
M005-R15 Runtime, charts, promotion, and secrets are cleaned only after four reviews spanning ≥28 days. Kill switch through G4; bounded Angular/API/core/event/seed/chart plans; generated two-pass proof; S19 rollback and S28 reapply; production promotion; separate GitOps secret cleanup; BSON Auth0Id preserved.
M005-R16 #2466 is the audit trail and final external actions are authorised/manual. Redacted evidence; final encrypted export; per-GCP-version retain/disable/destroy classification; Google Auth0 callback removal while Identity callbacks remain; authorised #2442 tenant action; no mutation automation.

Goal-Backward Truths

  • Two tokens created before a restart remain usable through different Identity processes/replicas on opposite sides of an Argo-managed rollout.
  • Users can sign in with password or Google, refresh, call protected APIs, use SignalR, manage accounts, and sign out through BFF.
  • Provider switch, rollback, and reapply never accept a cookie from another issuer/provider/generation.
  • Operators can stop and resume a campaign durably without pod-local files, duplicate delivery, or user/run/canary identifiers in GitOps/argv/evidence.
  • Three readiness percentages come from authoritative named cohorts and separately observed GitOps Jobs.
  • Auth0 remains an actionable kill switch for four full weeks; post-G4 cleanup remains bounded and staged.
  • Final export, GCP versions, Google callback, and tenant state each have an authorised, verifiable classification.

Waves and Slices

Wave Slice Purpose Gate at exit
1 S01 Campaign runtime/dependency baseline Real-store send and clean package audit.
1 S02 Identity chart/host, issuer, forwarding, basic readiness Rendered chart starts host; no pre-S03 ring dependency.
1 S04 BFF provider/session rollback contract Explicit provider/generation and old-cookie tests.
2 S03 Shared encrypted DataProtection + ring readiness Two pre-redemption tokens cross process/restart.
3 S05 CSRF, log hygiene, bounded telemetry Runs after S04 provider and shared campaign foundations.
3 S06 Authoritative readiness denominators Three redacted percentages pass.
4 S07 Worktree/preflight/query/status/live harness Normal/bare worktrees and safe evidence pass.
5 S26 Secret-safe durable campaign operations Canary/stop/resume Jobs are deployable.
5 S29 Identity endpoint log redaction Identity admin/account/email logs carry no email or stable user identifier.
6 S08 Staging prerequisites + dark launch GCP setup gate and Argo rollout proof pass.
7 S09 Staging switch + Auth0 rollback Ends healthy on separately synced Auth0 rollback.
8 S27 Separate staging OpenIddict reapply Ends healthy on fresh-generation OpenIddict.
9 S10 Production prerequisites + dark launch GCP setup, durability, backup, and dark invariants pass.
10 S11 Production BFF→Auth0 Exact 24-hour BFF/Auth0 baseline passes.
10 S12 Production import/campaign/readiness Jobs Every operation/sync/status and threshold passes.
11 S13 Production OpenIddict cutover Atomic switch passes or Auth0 rollback completes.
12 S14 Four-review observation Four reviews span ≥28 days with kill switch intact.
13 S15 Angular provider/package cleanup 12-file BFF-only provider boundary passes.
13 S16 API Auth0/JWT cleanup API has one BFF/OpenIddict runtime.
13 S17 Core/ApplicationService BSON-safe rename Seven-file legacy BSON boundary passes.
13.5 S23A Web Auth0 state/effects cleanup Seven-file auth state/effects/interface boundary passes.
14 S23 Angular cookie/config/account cleanup 15-file Web flow boundary passes and the Auth0 SPA SDK is removed.
14 S24 Event/handler/API rename Eight-path API propagation passes.
14 S25 Seed/provenance cleanup Five-file seed/allowlist boundary passes.
15 S18 Chart/generated cleanup NSwag location and two-pass generation pass.
16 S19 Staging cleanup promotion + rollback Ends healthy on separately synced prior release.
17 S28 Separate staging cleanup reapply Ends healthy on cleanup release.
18 S20 Production cleanup promotion Intentionally unflagged runtime is healthy.
19 S21 Separate GitOps secret cleanup Zero-consumer refs/secrets removed and external decisions frozen.
20 S22 Final export/external cleanup/tenant shutdown GCP, Google, and Auth0 states match authorised classifications.

Dependency Graph

S01 ─┬─> S03 ─┬─> S05 ─> S07 ─┐
     │        └─> S06 ─────────┼─> S26 ─> S29 ─> S08 ─> S09 ─> S27 ─> S10 ─┬─> S11 ─┐
S02 ─┘              S04 ─> S05 ┘                                             └─> S12 ─┴─> S13 ─> S14

S14 ─┬─> S15 ─> S23A ─> S23 ───────┐
     ├─> S16 ───────────┬─> S24 ───┼─> S18 ─> S19 ─> S28 ─> S20 ─> S21 ─> S22
     └─> S17 ───────────┴─> S25 ───┘

Go / No-Go Gates

G0 — Permit staging dark launch

GO only after S01–S07, S26 and S29 pass. NO-GO for dependency vulnerabilities, chart/host mismatch, untrusted forwarding, missing encrypted ring, failed two-token proof, reusable sessions, sensitive output, host-only CSRF, unauthoritative denominators, identifier-bearing Identity endpoint logs, local stop files, non-secret canary data, or prose-only status/live tooling.

G1 — Permit production dark launch

GO only after S09's Auth0 rollback and S27's independently approved/synced OpenIddict reapply both pass. NO-GO if Git revisions/generations/checkpoints are combined, old cookies authenticate, OAuth setup removes Auth0, or ring/readiness differs by replica.

G2 — Permit production BFF-via-Auth0

GO only with production Redis, explicit Auth0 provider, new generation, confidential client, exact pre-created queries, fresh-generation inverse, and a restricted approval proving the Auth0 application secret was transferred into the exact enabled syrf-auth0-bff-production version whose clientSecret property is mapped by extra-secrets-production. NO-GO for memory sessions, custom-domain misclassification, missing secret-version/source-transfer approval, missing ExternalSecret mapping, or any secret value/version identifier in GitOps.

G3 — Permit OpenIddict cutover

GO only after exact 24-hour BFF/Auth0 success, distinct successful import/verify/rerun Jobs, zero unexplained mismatch, completed durable campaign sequence/reconciliation, disposed hard bounces/unknowns, and 100/95/90 readiness, and a verified post-migration backup restore of the completed S12 state.

G4 — Permit runtime cleanup

GO only after four timestamped reviews spanning ≥28 days from S13 KEEP with required thresholds, zero Auth0 traffic, no Sev-½, and no unexplained mismatch. Through G4, all Auth0 code/packages/config/secrets/tenant and GitOps flags remain deployable. S15–S18/S23–S25 are unmergeable on NO-GO.

G5 — Permit GitOps secret cleanup

GO only after S19's independently completed rollback, S28's independently completed reapply, and S20 production proof. Runtime rollback then uses release reversion; GitOps secret cleanup is a separate PR.

G6 — Permit external cleanup and tenant shutdown

GO only after G5, final encrypted export, complete restricted external classification, support sign-off, and authorised GCP/Google/Auth0 administrators. Automation may verify but may not mutate secret versions, callbacks, tenant applications/connections, or billing.

Rollback Contract

  • Every active, inverse, and reapply GitOps change has a distinct PR/revision, approval, Argo sync, and fresh session generation.
  • S09 completes Auth0 rollback before S27 may reapply OpenIddict; S19 completes prior-release rollback before S28 may reapply cleanup. No single command chains either direction.
  • BffAuth.Provider, normalized authority, client reference, and generation change together; old namespaces are never reused.
  • With BFF disabled, stale cookies cannot divert the selector from JWT/API-key behavior.
  • Campaign delivery is not reversed. OpenIddict reset does not change Auth0; rollback guidance uses original Auth0 password/reset/support.
  • signin.syrf.org.uk and the Auth0 Google callback remain until the final authorised S22 action.

Repository / PR Boundaries

  • SyRF readiness: S01–S07/S26, explicitly serialized where campaign/API files overlap.
  • Infrastructure: S08/S10 Terraform worktrees; 0/2 detailed-exitcode wrapper; containers/IAM only.
  • Secret setup: S08/S10 restricted exact source/version manifests and authorised population gates.
  • GitOps auth: S08/S09/S27/S10/S11/S12/S13; Kubernetes mutation only through commits and Argo.
  • SyRF cleanup: bounded S15–S18/S23–S25, unmergeable before G4. S17, S24 and S25 merge together as one buildable unit because DevAuthController.cs, DatabaseSeeder.cs/SeedDataConstants.cs/InvestigatorBuilder.cs and DatabaseSeederTests.cs consume the renamed member.
  • GitOps promotion: S19 rollback, S28 reapply, S20 production, S21 secrets.
  • External manual: S22 export classification, GCP version actions, Google callback removal, Auth0 disable/cancel.

Every executor supplies an explicit physical */.worktrees/<name>, */pr/<name>, or */agents/<name> root. The checked-in guard also requires linked git metadata beneath <git-common-dir>/worktrees/*, covering normal .git and bare .bare layouts while rejecting /main.

Tracker

2466 supersedes the stale completed-phase assumption and bundles #2441–#2443. #2442 remains the manual tenant-shutdown record. Public evidence is aggregate/redacted; restricted exact secret/version/export/callback classification remains outside git and issue attachments.