ThatAIguyA world of ideas

THE CONSCIOUSNESS ATLAS
Read. Experiment. Follow the evidence.

ConsciousnessLearn · Explore · Joseph Anady

Janady13/missionmatch / docs/RUNBOOK_OPERATIONS.md

Source identity, revision, and recovered contents.

GitHub sourceSource text recovered

Source identity

FieldRecorded value
Source typeGitHub source
Original recordJanady13/missionmatch / docs/RUNBOOK_OPERATIONS.md
DateNot specified in source
RepositoryJanady13/missionmatch
Revisionbdacd9d0b4d5998d25fc74bf4007f4c3ec538c7a
Branchdeploy-and-ops
Path or archive memberdocs/RUNBOOK_OPERATIONS.md
Original SHA-25608d8081a5ff6791e616d01bdea4093de18ce5898f5af8df50e7a93eea7c8995c
Git blob SHAa3ae79e2716db713b4fca62eb556d8f55fe92550
Reading-copy SHA-25608d8081a5ff6791e616d01bdea4093de18ce5898f5af8df50e7a93eea7c8995c

Original source ↗

Recovered source transcript

# Operations runbooks Day two operations for missionMATCH under the database per tenant model. Each section is a checklist with a verification and a rollback. New client onboarding is `docs/RUNBOOK_ONBOARDING.md`; the one time move of the existing shared database into per tenant is `docs/MIGRATE_TO_PER_TENANT.md`. ## 1. Provisioning and deploy Stand up or update the platform. 1. Infrastructure: `terraform -chdir=infra/terraform apply -var-file=environments/aws-govcloud.tfvars` (operator, real credentials). See `infra/terraform/README.md`. 2. Schema: run goose against the control plane database (creates the pgvector extension, the missionmatch_app, missionmatch_migrator, and missionmatch_compliance roles, the schema, RLS). For the tenant fleet, `make migrate-all-tenants-check` then `make migrate-all-tenants`. 3. Identity genesis: `provision-org` for the first org and owner. 4. Build and publish the images: `docker build -f infra/docker/Dockerfile.mm-api ...` and the gateway (the in build FIPS gate must pass), push to the registry. 5. Deploy with the pod securityContext in `infra/docker/README.md` (non root 65532, read only rootfs, `/tmp` tmpfs, drop ALL capabilities) and the env: `MM_TENANCY=per_tenant`, `MM_CLOUD`, the three control plane DSNs, `MM_SECRETS_BACKEND` (a government cloud store in production), the pool bounds, and the auth secrets. Verify: `GET /healthz` is ok, `GET /readyz` is ready (the control plane pool answers), and `GET /healthz/fips` reports `fips_enabled: true`. Rollback: redeploy the previous image tag; infrastructure changes roll back with the prior Terraform state. ## 2. Scaling The API is stateless (sessions are opaque and server side in the control plane), so any pod serves any request. 1. API throughput: increase the replica count. No sticky sessions are needed. 2. Per tenant connection budget (the load bearing limit): `MM_TENANT_MAX_POOLS` times `MM_TENANT_POOL_MAX_CONNS`, plus the control plane and compliance pools, must stay under the database `max_connections`. As the tenant fleet grows, watch the `/metrics` pool gauges and the database connection count; the bounded LRU pool registry evicts idle tenants, so the live pool count is bounded, not the tenant count. Tune the two bounds (lower MaxConns per pool before raising MaxPools). 3. Database: scale the instance class vertically, or add read replicas for read heavy reporting. The control plane is small (identity and the directory); each tenant database scales on its own. Verify: the pool gauges stay below the connection ceiling under load, and p95 latency holds. Rollback: lower the replica count or the pool bounds; a pooler in front of any database MUST be in TRANSACTION mode, never statement mode, or the per request org GUC isolation breaks. ## 3. Failover 1. Database: managed Postgres is multi AZ, so a node failure fails over automatically to the standby on the same endpoint. The pgx pool reconnects; the per tenant pool manager Pings before serving and returns a typed 503 (never a hang) on a still unreachable tenant, then reopens on recovery. 2. Control plane: it is a single point for identity and routing, so it must be multi AZ like the tenant databases. While it is down, login and routing fail, but each tenant database is independent and its data is intact; recovery is automatic on control plane failover. 3. API: a rolling deploy with the readiness probe gates traffic away from a starting or unhealthy pod. Verify: after a forced failover, `GET /readyz` returns to ready and a tenant request serves its own data. Rollback: failover is automatic; if a node is unhealthy, replace it from the standby. ## 4. Backup and recovery (per database) Every database (the control plane and each tenant) is covered by the managed automated backups (the Terraform `backup_retention_period`) plus on demand logical backups. 1. On demand backup: `scripts/backup-tenant.sh -dsn "<migrator DSN to the tenant DB>" -out FILE` (a custom format archive of the whole database, public and eeo and the vectors; the tenant stays online). Pin the client to PostgreSQL 16 (set `PGBIN`). 2. Recovery: take the tenant offline in the directory first (`UPDATE tenant_directory SET status='offline' WHERE organization_id=...`, so the router refuses it with a typed error), then `scripts/restore-tenant.sh -admin-dsn "<superuser>" -migrator-dsn "<migrator>" -source <db> -target <db> -dump FILE`. This is the procedure proven on M4 staging (BUILD_REPORT B4): it mirrors provision-tenant's prep, restores, and verifies row count equality across public and eeo, a vector sample, and the isolation invariants. On a green verify, set the status back to `active`. Verify: the restore script's own verify must pass (row counts match, vectors present, invariants hold). Rollback: if a restore is bad, leave the tenant offline and restore from an earlier backup; never flip a tenant active on a failed verify. ## 5. Secret rotation All secrets rotate without a flag day because the load bearing ones are versioned. 1. Per tenant database credential: rotate the value in the secret store under the tenant's reference. The secrets port caches with a short TTL (`MM_SECRET_CACHE_TTL_SECONDS`) and force refreshes on an authentication failure, so the app picks up the new credential within the TTL or on the next failed connect and retries with backoff. Keep a separate higher privilege identity for rotation. Verify: a request to that tenant still serves after the old credential is invalidated. Rollback: restore the prior secret value. 2. The credential pepper (`MM_CREDENTIAL_PEPPER`): set the new pepper, increment `MM_CREDENTIAL_PEPPER_VERSION`, and keep the prior key in `MM_CREDENTIAL_PEPPER_PREVIOUS`. Old hashes verify under the previous version and are rehashed to the new one on the next login. Verify: existing users can still log in; new credentials carry the new version. Rollback: revert the version and the keys. 3. The TOTP KEK (`MM_TOTP_KEK`, 32 byte AES 256): set the new key, increment `MM_TOTP_KEK_VERSION`, keep the prior key in `MM_TOTP_KEK_PREVIOUS` so existing TOTP secrets still decrypt. Verify: enrolled users pass a TOTP check. Rollback: revert. 4. The CSRF key (`MM_CSRF_KEY`) and the recovery lookup key (`MM_RECOVERY_LOOKUP_KEY`): rotate the value. A CSRF key rotation invalidates in flight CSRF tokens (clients fetch a fresh one on the next unsafe request), so rotate at a low traffic window. Verify: a login and an unsafe request succeed after rotation. Rollback: restore the prior key. Never log a resolved DSN, password, or secret value; the secrets port logs only the reference and the tenant id. All keys load from the server side environment file or the cloud secret store, never the repo or the browser bundle.

Search equations, builds, manuscript text, and recovered sources.