1. Before the shadow period
- SCF has named the community operator and the handover start date (plan section 2.1).
- The new operator has its own GitHub owner (user or organisation), cloud project, DNS account, probe account, alert receiver, and age identities for at least two people.
- The new operator’s people have read ../architecture.md, ../deploy/, ../runbooks/, ../sla.md, ../support.md and this directory.
- The new operator’s age public keys are recipients of staging only
(
infra/secrets/recipients/staging.txt,sync-recipients.sh).
2. Independent rebuild (shadow period)
- A new environment built from the repository alone in the new operator’s accounts, following ../deploy/overview.md; every gap in the docs found on the way is fixed in the repository. Evidence: the issue or pull request per gap.
- It runs the same release as production (
SA_IMAGE_TAG). -
make tofu-check,make ansible-lint, the secondsite.ymlrun reportschanged=0. - The end-to-end checks of ../deploy/verification.md pass.
- The runbooks that need no production access were run on it: edge node loss, database failover, point-in-time restore, Umami upgrade.
- Its backups run:
pgbackrest infolists a full backup, and the backup alerts are quiet. - Its probe and status page measure it; one monthly SLO report exists.
3. Domain
- The registrar account that holds
<input I4>is known, and so is its transfer lock state (many registrars refuse a transfer within 60 days of a registration or a previous transfer, and the ICANN 60-day lock after a registrant change applies unless it was waived). - The new DNS zone exists in the new account (
make <env>-apply,infra/tofu/modules/dns) andcutover-transfer.yml -e cutover_stage=precheckpasses against its nameservers. - The auth code is issued, the transfer is approved by both sides, and the registrar shows the new owner.
- The delegation points at the new nameservers and
cutover-transfer.yml -e cutover_stage=verifypasses: public resolvers answer with the new nodes, every pinned tracker release is served byte for byte with a valid certificate, console, web dashboards and OTLP answer. - An example page that still carries a snippet from before the cutover delivers a pageview in
Chromium, Firefox and WebKit (the
@cutovercheck oftests/handover, pointed at the real names, or by hand with the browsers’ network tools). - Not used: the redirect path. If the domain cannot be transferred, every tenant was told to
replace its snippet and OTLP endpoint before
cutover-redirect.ymlran (redirect-research.md).
4. Data
- Ingestion was drained and the source stopped (rebuild.md section 2).
- The export ran by the pgBackRest path (or the pg_dump path for another provider), and the
directory’s
SHA256SUMSwas checked on import. -
make migrate-importpassed: schema versions equal, row-level security coverage check,jobs run reconcile. -
platformctl umami rotate-adminandjobs run umami-rotate --forceran on the new leader. -
make verify-migrationprintedresult: source and target are equal. Evidence: its output. - Two tenants confirmed they see their history in the new console and web dashboards.
- The dump directories were deleted after verification.
5. Secrets and credentials
- The original operator’s age keys are removed from every
infra/secrets/recipients/<env>.txt,sync-recipients.shran, and the change is merged. - Every value they could read is rotated:
infra/secrets/rotate-secrets.py, thenrotate-all.ymlwithrotate_previous_age_identitywhen that identity is available. Its last play passed, which proves every previous PostgreSQL, NATS, NATS route, Umami admin, Umami user, Patroni REST and Grafana credential is refused and every new one accepted. - Owner inputs replaced at their providers and the old ones revoked there: GitHub OAuth client
secrets (I2;
rotate-all.ymlasks GitHub), Cloudflare token (I6), Azure role assignments (I5), Discord webhooks (I8), the OpenTofu state passphrase and the provider tokens intofu.enc.env. -
secrets.previous.enc.yamldeleted afterrotate-all.ymlpassed. - Operator API keys the original operator created are revoked (../runbooks/operator-key-revocation.md).
- The original operator’s SSH keys are removed from the
opsuser of every server (input I15, the inventory’s admin keys), and their source addresses from the admin CIDRs (I13).
6. Repository and packages
- The repository is transferred to the new owner on GitHub; issues, pull requests, releases and the old URL redirect are checked after the move.
- Set up again under the new owner, because a transfer does not move them: Actions secrets
and variables, environments and their protection rules, branch protection, Dependabot
settings and alerts, the container registry path (images under
ghcr.io/<owner>/...), the npm trusted publisher (input I9) bound to the new repository. - The npm scope is transferred and one tracker release is published from the new repository (../runbooks/tracker-release.md).
- Release images are built and signed from the new repository;
deploy.ymlverifies the new signing identity.
7. Accounts and access
- Cloud, DNS, probe and registrar accounts of the original operator hold nothing the new environment needs, and the original operator has no access to the new ones.
- GitHub OAuth apps of every environment belong to the new owner (input I2), with the callback URLs of the new environment and wildcard redirect matching off.
-
OPERATOR_GITHUB_IDS(input I3) lists exactly the people SCF names; the control plane was restarted after the change (../operators/overview.md). - Alerts reach the new operator’s receiver (I8); a test alert was delivered before the old receiver was removed.
8. Tenants
- Every project was told the cutover date, the new processor and that nothing changes in its snippet or exporter (plan section 2.3, step 1), with the notice period the legal review set (input I10).
- The public issue tracker and ../support.md name the new operator.
9. Done
- SCF confirms the new operator runs the system on its own, and the closing issue on the repository links the evidence above (plan section 7).
- The old environment’s teardown date is announced; its backups expire with their retention.