diff --git a/deploy/README.md b/deploy/README.md index 286eab3..03996b8 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -1,18 +1,26 @@ # tenant-engine production deployment -Manifests recovered from the live objects' -`kubectl.kubernetes.io/last-applied-configuration` on 2026-08-14 so that a -rollback does not depend on a cluster annotation. Applied originally during -TEN-WP-0004; TEN-WP-0005 keeps them in-repo and pins by digest. +**Apply home moving to `rapp-tenant-engine`.** These files remain the source of the absorbed manifests until that package is the operator apply path. + + +The original manifests were recovered from live objects on 2026-08-14. The +repository now carries the reviewed **post-cutover desired state** from +TEN-WP-0009. It is not evidence that PostgreSQL has been provisioned or that +the live SQLite deployment has moved. | File | Deployment | Service DNS | | --- | --- | --- | | `tenant-engine.yaml` | `tenant-engine` | `tenant-engine.tenant-engine.svc.cluster.local:8090` | -The file is a five-document manifest: `Namespace`, `PersistentVolumeClaim`, -`Deployment`, `Service`, and a least-privilege `NetworkPolicy`. Ingress is -restricted to the `user-engine` workload; egress is restricted to -`flex-auth-tenant-engine` on 8080 plus cluster DNS. +`tenant-engine.yaml` declares `Namespace`, rolling `Deployment`, `Service`, +`ServiceAccount`, and least-privilege `NetworkPolicy`. Ingress is restricted +to `user-engine`; egress is restricted to `platform-pg` in `databases`, +`flex-auth-tenant-engine`, and cluster DNS. PostgreSQL and flex-auth caller +credentials are projected as files so clients can re-read them on rotation. + +`tenant-engine-migration.yaml` is the separate schema-migration Job and its +egress policy. The pinned image in both files must contain the PostgreSQL code +and migration before either manifest is applied. ## Rolling out an image @@ -26,14 +34,45 @@ git push origin main # 2. Take the immutable digest from the workflow's "Report immutable digest" # step -- deploy by digest, never by tag -# 3. Edit the image digest in deploy/tenant-engine.yaml, then apply +# 3. Provision the rapp-postgres consumer and credential projections. +# 4. Run the schema migration Job with the migration-role lease. +# 5. Follow the stopped-write transfer below; only then apply the runtime. kubectl apply -f deploy/tenant-engine.yaml kubectl -n tenant-engine rollout status deploy/tenant-engine --timeout=120s ``` -The Deployment uses `Recreate` because the SQLite PVC is `ReadWriteOnce`. -A new pod applies the forward-only lifecycle migration on startup against -the existing database. +The desired Deployment uses `RollingUpdate`; schema migration is never a +runtime startup side effect. Keep replicas at one until recovery and caller +latency evidence justifies otherwise. + +## Stopped-write SQLite transfer + +This is an operator cutover, not an application startup step: + +1. Scale the live SQLite Deployment to zero and verify no pod holds the PVC. +2. Snapshot or copy the SQLite file without modifying it. +3. Apply `deploy/tenant-engine-migration.yaml` with the new immutable image and + wait for success. +4. Run the transfer under the migration-role URL: + + ```bash + tenant-engine-transfer \ + --sqlite /path/to/stopped/tenant-engine.db \ + --url-file /path/to/migration-url \ + --expect-tenant tenant:trial:portalcheck=active:1 \ + --expect-tenant tenant:trial:ten-wp-0005-t05=retired:5 \ + --evidence-output docs/evidence/TEN-WP-0009-cutover.json + ``` + + The target must be empty. The command transfers every table in one + transaction, preserves event sequence values and nullable legacy + timestamps, then compares every row and emits only counts, digests, and the + requested lifecycle/version spot checks. +5. Apply the runtime desired state, require `/health` to report + `store_backend: postgresql`, and execute the TEN-WP-0007 live verification + list. +6. Retain the stopped SQLite PVC, access-restricted, through the recorded soak. + Do not run two writable authorities. ## Detecting pin drift @@ -75,6 +114,13 @@ that cost us a round trip. kubectl -n tenant-engine rollout undo deploy/tenant-engine ``` +Before the first PostgreSQL write, reattaching the stopped SQLite PVC is a +recoverable rollback. After any PostgreSQL write, that file is stale and must +not be made authoritative; rollback means restore or reverse-transfer from +PostgreSQL under a new operator plan. The repository desired manifest does not +carry the PVC, so pre-cutover rollback also requires the retained previous +manifest/revision. + If the ReplicaSet history has been pruned, re-apply the manifest with the last-known-good digest below.