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: 31 slices across 22 dependency waves.
Status as at 2026-08-27¶
This document was last maintained on 2026-08-10 (1efb360a1), before any of the
native-parity PRs merged, so its prose described that workstream as entirely
ahead. It is re-baselined here against current main through #2905
(14755a8b2). Where this roadmap and the
code disagreed, the code won.
Closed since 2026-08-10. All five M005-R17 PRs are merged: A #2735
(a6fcc4987), A2 #2803 (52f031087), B #2806 (0b448ee92), C #2808
(a4d73b297), D #2837 (4b65b43c8), with follow-ups #2838 (b9e753b3c),
#2855 (b558611a3) and #2854 (0eafb3472), plus registration
non-enumeration #2901 (3ea3b800c) and operation-bound step-up #2902
(f8755a2e1), plus deletion-time revocation #2905 (14755a8b2). The final
stacked Identity suite ran 1,789 tests with zero failures
(dotnet test src/services/identity/identity.slnf → 1,112 + 677), and the
fail-closed mapping boundary, the middle-step admission
model and the migration preservation matrix are implemented and covered.
Not closed, and not to be read as closed. Merging the parity stack and its
follow-ups is not the same as passing R17. The acceptance clauses still open on
current main are
enumerated with evidence in
M005-VALIDATION.md; the
load-bearing ones are the missing emailed single-use sign-in link factor, the link-failure 500
(#2835), and auth_time/amr, which no code
issues. The settled email-verification policy is now implemented by #2925.
The provider-derived confirmation service and its external-sign-in call are
removed; provider verification remains metadata only; the admission checkpoint
explains that SyRF performs its own mailbox verification; and migration readiness
measures the linked, unlocked provider route independently of provider/local
confirmation state. Focused endpoint and readiness tests cover the invariant.
An earlier revision of this paragraph also listed the concurrent-unlink
race (#2839). That has been withdrawn, and #2839 was closed as not
reproducible on 2026-08-26: the store persists the removal through a
ConcurrencyStamp compare-and-swap, so the losing racer fails rather than
removing the last sign-in method — the evidence is in M005-VALIDATION's
external-lifecycle exit check, sub-item (a).
S08, the subsequent S08A Redis/Valkey prerequisite for S30/S09, and the serial S30 isolated synthetic rehearsal have not started; the
rehearsal cannot be stood up today. Blockers as at 2026-08-27: the external
test-mailbox resource the
live contract requires has unverified availability — AUTH_SMOKE_MAILBOX_ENDPOINT
and its token are operator-supplied at run time, so their absence from this
repository and from cluster-gitops is the designed state and is not evidence
either way; an operator check is outstanding, not a known gap; the S08 Task 1 render-and-audit of the
reviewed cluster-gitops/ESO staging resources against the Identity chart has not
been performed (slices/S08/S08-PLAN.md:94-103 assigns environment values and
generated credentials to cluster-gitops and External Secrets Operator, and those
resources already exist — so the outstanding work is validating them, not adding
chart templates that would duplicate operator-owned resources). Identity's
read-only ProjectManagement connection is no longer a missing declarative
blocker: cluster-gitops@e25ca2ed declares the least-privilege Atlas user and
the exact generated-Secret contract. Read-only inspection found the Atlas user
Ready and the namespace-local generated Secret present with its expected key;
S08 still must prove the eventual pod mount/use
(IdentityConfigurationStartupTests.cs:366). Separately, current main requires
the ProjectManagementProvisioning BaseUrl/audience and dedicated
syrf-identity-provisioner client/Secret outside Development, but staging
GitOps declares neither that values block nor the ESO-generated Secret. S08
Task 1 must add and render that least-privilege contract without reusing or
broadening syrf-api (IdentityHostOptions.cs:59-67,127-142;
.chart/values.yaml:50-57).
The unexecuted live harness is deliberately not in that list:
slices/S07/S07-PLAN.md:108 requires it to run only after S08 deploys, and
S07's done condition at :110 asks for a checked-in harness rather than live
results, so it cannot be a prerequisite of the environment it needs. The
isolated-topology rollback is sequenced after S08 for the same reason, but
is assigned to S30 as an explicit post-S08 rehearsal/R10 checkpoint, distinct
from S09's later Auth0 provider rollback. The harness asserts all ten flows the
S07 contract requires
(slices/S07/S07-PLAN.md:101-102); its evidence being code-resident rather than
live is the R08 gap, and its operator-invoked design is deliberate and not a gap
at all.
An earlier revision of this paragraph listed "no email sink" as a blocker.
That has been withdrawn: the sink is environment infrastructure, not an
Identity service implementation — the live contract uses an external HTTPS
test-mailbox adapter (slices/S07/S07-PLAN.md:105, implemented at
e2e/tests/auth-migration-live.helpers.ts:88-95,293-317) and S08 asserts SES
synthetic delivery through the existing transport
(slices/S08/S08-PLAN.md:116-124). What is genuinely outstanding is an operator
check that the mailbox resource exists and is reachable, which is the first item above.
Redis is deliberately not in that list. S08 is Identity-only and provisions no session store, so the absent Redis/Valkey path does not gate it. It gates S09, where the BFF session store is first required, and it is a named dependency of the rehearsal's own isolated environment (RH-3). The absence is re-verified rather than assumed — see "Repository / PR Boundaries" below.
Requirements¶
| ID | Requirement | Evidence required |
|---|---|---|
| M005-R01 | Identity/migration code is safe to execute. | Complete: 1,789-test baseline (1,112 + 677, zero failures at 14755a8b2; the former "≥313" baseline predates PRs A–D); real Mongo campaign integration; no vulnerable SharpCompress/Snappier result within identity.slnf, where the shipped Identity projects are clean. The only advisory is test-only SSH.NET 2024.2.0 (High) via Testcontainers 4.3.0; it is reported rather than suppressed, with no repository NuGetAuditSuppress entry. Repo-wide, dotnet list syrf.sln package --vulnerable --include-transitive still reports Snappier 1.0.0 (High) and SharpCompress 0.30.1 (Moderate) in ten non-test projects including SyRF.ProjectManagement.Endpoint, plus Microsoft.OpenApi 2.0.0 (High) in SyRF.Quartz. Tracked as #2907: it does not gate R01 or the Identity image itself, but S08 now changes the deployed Project Management receiver configuration, so the Project Management artifact must pass a focused affected-service audit/remediation before that rollout (see G0 and S08 Task 1). Later affected services are reassessed again before S10–S13. |
| 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; Identity application identifiers only under Pii*; no credentials or sensitive free text in logs; no identifiers/secrets/source paths in argv/GitOps/public 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; four denominators — privileged, active-90-day, all-enabled and Google-only (#2837 added the fourth; it is held to the all-enabled floor rather than a fourth configurable threshold, so ReadinessThresholds still declares three: Models/ReadinessThresholds.cs:16,18-19, rendered [100, 95, 90] at .chart/values.yaml:196; report schema version 4 distinguishes the provider-route definition from schema 3); 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. | Reviewed SyRF chart/package and cluster-gitops Argo/Kubernetes changes; authorised operator-managed exact GCP source/version population; retained Google Auth0 callback; Argo-managed rollout proof; discovery issuer/endpoints and TLS verified through the actual ingress; Auth0 Web/API unchanged. The hostile trusted/untrusted forwarded-header and generated-URL matrix belongs to post-S08 S30/M005-R10, whose harness actually implements it. |
| M005-R10 | Staging proves the isolated rehearsal, teardown, cutover, rollback, and reapply as separate checkpoints. | Post-S08 isolated OpenIddict live matrix and synthetic-resource GitOps teardown; 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. |
| M005-R17 | Native Identity/OpenIddict preserves required Auth0-domain and user-facing behaviour before rehearsal. | The four core PRs A–D plus A2 are merged (five total; SHAs above), as are #2901/#2902/#2905. No email-only linking path exists, registration is non-enumerating, operation-target step-up and deletion-time revocation are enforced, and missing or ambiguous Investigator mappings fail closed (AuthorizationController.cs:108,250,339-349; ApplicationService.cs:111-140; BffAuthController.cs:274-281). Still outstanding: the six code-level acceptance clauses listed in M005-VALIDATION. The live harness execution and eight further full-matrix flows are rehearsal evidence after the S08 Identity dark launch and its audited Project Management receiver prerequisite, not additional R17 code gaps. R17 is therefore partially, not fully, evidenced. |
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.
- Four readiness denominators — privileged, active-90-day, all-enabled and Google-only — come from authoritative named cohorts and separately observed GitOps Jobs, measured against three declared floors (the Google-only cohort reuses the all-enabled floor).
- 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.
- Stable Investigator mapping, confirmation/profile admission, external identity lifecycle and migration preservation are proven before a synthetic rehearsal can exercise the deployed topology.
Mandatory pre-rehearsal parity workstream¶
Auth0 Behaviour → Native Identity/OpenIddict Parity Gate is a prerequisite to S08 rather than an activity to discover during S08. It defines four core SyRF implementation PRs A–D plus the resolved A2 compatibility companion — five total:
- Identity mapping and issuance invariants.
- Identity display compatibility through the native authenticated account-management endpoint and Angular migration (A2, resolved 2026-08-10; no transitional identities claim).
- Confirmation and profile-completion gates.
- External identity create/link/unlink/recovery lifecycle.
- Migration preservation and readiness.
The mapping/invariant contract merges first. A2 implements its resolved native-endpoint decision. Confirmation/profile and external lifecycle can then proceed in parallel; migration parity follows that contract and the approved state schemas. S08 remains serial after A–D and A2 merge and their integration/E2E matrices are green.
As at 2026-08-27 the merge half of that sentence is satisfied and the
matrix half is not. All five PRs merged (see "Status as at 2026-08-27"), but
the integration/E2E matrices are not green in the sense this gate requires: several acceptance clauses of the merged PRs are still open. Separately, the
live harness (e2e/tests/auth-migration-live.spec.ts with
scripts/auth-migration/live-smoke.sh) asserts all ten flows the S07 contract requires (slices/S07/S07-PLAN.md:101-102) but has never been executed against a deployed topology, so its evidence is code-resident rather than live. Its
operator-invoked design is deliberate and is not part of that gap. That execution is not an S08 prerequisite and must not be read as one: slices/S07/S07-PLAN.md:108 says to run it "only after S08 deploy", and S07's own done condition at :110 asks for "a checked-in non-local harness", not live results — so gating S08 on the run would be circular. S08 is serial behind the open in-repo acceptance clauses; the live run belongs to R08 and S30, alongside the eight further application flows and distinct isolated-topology rollback checkpoint in S30's full live matrix (see M005-VALIDATION). Neither is behind the merges.
The later rehearsal uses synthetic users, an isolated database/secrets/clients/
callbacks and an email sink. Auth0 remains live/default and no production
traffic or real-user data enters the rehearsal. None of that isolated
environment exists yet: the external test-mailbox resource's availability is
unverified (the adapter is implemented and required by the harness; its endpoint
and token are supplied by the operator at run time, so neither repository would
carry them in any case), the S08
Task 1 render-and-audit of the reviewed cluster-gitops/ESO resources has not been
performed, and — for the rehearsal's own session dependency under RH-3 — there is
no Redis/Valkey path in cluster-gitops (state refreshed 2026-08-27). Note that
the mail sink is an environment resource, not
missing application code: an earlier revision said "there is no email sink in the
codebase", which located the gap in the wrong place.
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 | Redacted percentages pass — three at the time of S06, four since #2837 added the Google-only cohort. |
| 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 sensitive-field labelling | Identity admin/account/email identifiers use separate Pii* properties and never enter message templates. |
| 6 | S08 | Staging prerequisites + dark launch | GCP setup gate and Argo rollout proof pass. |
| 6.25 | S08A | Staging Redis/Valkey session substrate | Reviewed Kubernetes/GitOps package and isolated/shared staging instances are ready without enabling BFF traffic. |
| 6.5 | S30 | Isolated synthetic rehearsal + teardown | Full restricted live matrix passes; isolated resources are separately removed while Auth0 remains default. |
| 7 | S09 | Staging switch + Auth0 rollback | Starts only after S30 teardown and 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. |
Slice status as at 2026-08-27: S01–S07, S26 and S29 have landed, and the
code-resident half of their exit checks is evidenced item by item in
M005-VALIDATION.md;
their live/manual halves are not. S08 onwards has not started —
cluster-gitops@e25ca2ed declares disabled staging Identity 1.24.0 / SyRF
8053842, but the ApplicationSet selector therefore creates no Argo Application;
read-only inspection found no Identity workload, route or DNS. No production
Identity directory exists, and staging Web/API remain on Auth0.
Dependency Graph¶
S01 ─┬─> S03 ─┬─> S05 ─> S07 ─┐
│ └─> S06 ─────────┼─> S26 ─> S29 ─> S08 ─> S08A ─> S30 ─> S09 ─> S27 ─> S10 ─┬─> S11 ─┐
S02 ─┘ S04 ─> S05 ┘ └─> S12 ─┴─> S13 ─> S14
Native behaviour parity (M005-R17) ─────────────────────────────────────────────> S08
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, S29 and M005-R17 pass. Not passed as at 2026-08-27: R17 is partially evidenced (see the requirements table and M005-VALIDATION). Of the NO-GO conditions listed below, the open R17 acceptance clauses are the ones that still apply.
The Identity artifact's dependency closure is clean, so #2907 does not reopen
M005-R01. The image builds
SyRF.Identity.Endpoint and SyRF.Identity.Migration over SyRF.Identity.Shared
and SyRF.SharedKernel and nothing else (src/services/identity/SyRF.Identity.Endpoint/Dockerfile:17-20,32-38;
the two csproj files reference only those), and all four report no vulnerable
package. That is a narrower claim than "every artifact S08 may roll is clean",
which is no longer true now that S08 Task 1 changes the Project Management
receiver chart/values and therefore rolls that deployment. Repo-wide,
Snappier 1.0.0 (High), SharpCompress 0.30.1 (Moderate) and
Microsoft.OpenApi 2.0.0 (High) ship in ten API, ProjectManagement, Quartz,
S3-notifier and shared-host projects, tracked as #2907 — a real exposure
that leaves the Identity artifact clean but makes the Project Management
portion of #2907 a G0/S08 prerequisite. Before Task 1 changes or syncs that
receiver, a focused audit must prove the exact Project Management image clean
or the shipped Snappier/SharpCompress findings must be remediated; otherwise
S08 remains NO-GO. Later production slices reassess their own affected artifacts
before S10–S13. The only advisory inside
identity.slnf is SSH.NET 2024.2.0 (High) in the two Identity test
projects via Testcontainers; it is not in the image, and R01's "no unexplained
suppression" gate is satisfied because the advisory is reported rather than
suppressed and no repository NuGetAuditSuppress entry exists.
NO-GO for an unexplained vulnerability in the Identity image closure, chart/host mismatch, untrusted forwarding, missing encrypted ring, failed two-token proof, reusable sessions, sensitive output, host-only CSRF, unauthoritative denominators, untagged identifiers or sensitive values interpolated into Identity log message templates, local stop files, non-secret canary data, prose-only status/live tooling, email-only account linking (closed — evidenced in M005-VALIDATION), lossy migration state (closed — evidenced in M005-VALIDATION), or missing/ambiguous Investigator mappings that can reach token issuance (closed — evidenced in M005-VALIDATION). The list stays normative: an annotation records that a condition is currently satisfied, not that it has been removed from the gate.
G1 — Permit production dark launch¶
GO only after S30's isolated live matrix and separate teardown, S09's Auth0 rollback, and S27's independently approved/synced OpenIddict reapply all pass. NO-GO if isolated resources remain, 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 readiness passing on all four denominators — privileged 100%, active-90-day 95%, all-enabled 90%, and the Google-only cohort against that same all-enabled 90% floor (SyRF.Identity.Migration/Commands/ReadinessCommand.cs:347-355,413) — 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.ukand the Auth0 Google callback remain until the final authorised S22 action.
Repository / PR Boundaries¶
- SyRF native parity: the four core M005-R17 PRs plus the resolved A2 native-endpoint companion in the parity matrix merge before S08; mapping invariants first, then parallel confirmation/profile and external lifecycle, then schema-aligned migration parity.
- SyRF readiness: S01–S07/S26, explicitly serialized where campaign/API files overlap.
- Declarative environment delivery: S08/S10 use reviewed SyRF chart/package changes plus cluster-gitops Argo/Helm/Kustomize/ExternalSecret/operator patterns. S08 changes no Web/API provider and has no Redis dependency. S08A is the executable owner for the missing staging Redis/Valkey path: it adds a pinned, rendered Kubernetes/Helm/operator package through the established SyRF + cluster-gitops ownership boundary, proves separate ordinary-staging and isolated-rehearsal instances/credentials/network policy, and keeps every BFF consumer disabled. S30 depends on S08A before using the isolated instance; S09 depends on it before using the ordinary staging instance. No Terraform or manual cloud configuration is introduced. Re-verified 2026-08-27 at
cluster-gitops@e25ca2ed: a case-insensitive search forredisorvalkeyacross application YAML returns no workload/operator path, so S08A, S30 and S09 stay NO-GO until that reviewed path lands. An earlier revision of this bullet added that the SyRF chart was "also still missing" an ExternalSecret template and an isolated-environment values profile. That is withdrawn:slices/S08/S08-PLAN.md:94-103assigns environment values and generated credentials to cluster-gitops and External Secrets Operator, cert-manager the Issuer/Certificates and Atlas the database user, and those resources already exist underplugins/local/extra-secrets-staging/alongsidesyrf/environments/staging/identity/. Adding chart templates for them would duplicate operator-owned resources. - Secret setup: S08/S08A/S30/S10 restricted exact source/version manifests and authorised population gates.
- GitOps auth: S08/S08A/S30/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.