teleo-infrastructure/docs/workstreams/gcp-leoclean/goals.md

107 lines
6.1 KiB
Markdown

# GCP leoclean migration goal
## Objective
Deploy and prove Leo's least-privilege Hermes/leoclean runtime in GCP staging
against canonical Cloud SQL, establish behavioral and database parity, connect
the protected Observatory to canonical/proposal/vector/runtime receipts, then
cut over safely and retire the VPS after soak.
## Architecture baseline
- Hermes with the `leoclean` profile remains Leo's intended runtime.
- Cloud SQL is canonical PostgreSQL authority.
- The protected Observatory is a separate frontend surface.
- The VPS remains untouched until an explicitly approved, parity-proven
cutover and retirement sequence.
## Current state
- Complete: PR #179 least-privilege PostgreSQL authority is merged on main.
- Complete: the revision-bound, structurally no-send runtime from PR #183 is
merged into `main` at `2d88c9765bd9b43641d1efb04a1118c5ce0bce39`.
- Complete: PR #182 head
`3e59845454f5315e955734db7fe598ec4ba4cf70` was merged with merge commit
`94a8160ceeb6821fd113f4c843f024d5de99939a` after all five checks passed.
- Complete: PR #202 remained the exact reviewed three-file QEMU/PID-1
correction at `ffe170007d0e20d77a5208263e5b33fc999139fc` after retargeting
to `main`, then merged with merge commit
`383996a43beebef57cf84a2ced53213e28a41dca` after all five checks passed.
- PR #193 is source material only. It must not be merged wholesale; only the
required identity-binding and OCI-lifecycle corrections belong in the narrow
#182/#183 stack.
- Complete through PR #182 head `3e59845`: the narrow package
correction binds every packaged and synthetic-identity source byte to its
reviewed Git blob; container health binds the packaged/live config plus the
exact sealed no-send tool and plugin surface; and the disposable image smoke
also binds the implicit root bootstrap user, entrypoint, command, healthcheck,
and stop signal. The focused package/runtime/identity/OCI suite passed 204
tests, the repository suite passed 2,338 with 3 skips, and one exact-revision
synthetic `linux/amd64` OCI lifecycle proved UID/GID `65532`, zero runtime
capabilities, no-send health, and complete candidate cleanup on the arm64 Mac
Docker daemon. No GCP or live service was contacted.
- PR #206 at exact head `e42d635523fcb90ecdd504b0f0290df7015991e7`
makes release finalization pull and inspect the exact immutable staging
digest. Its five checks pass, but it must not merge unchanged: PR #209's
final repair at `d2ad4f7c964ff70f01be65ad57290b1346153f95` is the required
corrective layer that prevents finalization from deleting daemon-global
digest references a Docker-config lock cannot exclusively own.
- Published as draft PR #210: one structured, self-hashed build/push receipt
producer. It derives the content-bound candidate tag, manifest digest, and
config binding from validated pre/post-push daemon state; finalization
consumes that receipt instead of caller-supplied digest/config values. The
branch has been rebuilt directly on PR #209's final repair and carries the
same retained-digest rule through both build/push and finalization. No
daemon-global build tag, candidate tag, immutable digest reference, or
receipt pathname is removed automatically. The receipt is published and
consumed only through a private operator-owned directory with a retained
two-link, stable-inode contract; remote candidates are retained. The exact
#210 head belongs in the mutable PR evidence, not recursively inside its own
commit.
- Current exact-head validation: 206 focused package/OCI tests and the full
repository suite at 2,480 passed with 3 expected skips; Ruff, Python compile,
and diff checks pass. Three independent advisory exact-head reviews approved
the receipt deletion/identity boundary. Tests mock Docker and perform no
registry push.
- Current gate: human exact-head review remains pending on #206 and #210. PR
#209 must first correct #206's feature branch; corrected #206 must be
re-reviewed and merged before #210 is retargeted to `main` for its own human
review and merge.
- In progress offline: a separate GCP staging preflight rebuilt on the final
#210 head. It checks exact control-plane and host prerequisites without
reading secrets, logging into PostgreSQL, deploying, or restarting. Its
bounded IAP/SSH path uses a fixed remote command and a maximum five-minute
key lifetime, but no live run is currently authorized.
- Not yet live-proven: staging VM/container engine, IAM/Secret Manager, Cloud
SQL effective identity, restart behavior, or model/database parity.
## Remaining order
1. Merge PR #209 into PR #206's feature branch, rerun exact-head checks, obtain
human review, and merge the corrected PR #206.
2. Update, review, retarget, and merge draft PR #210's structured build/push
receipt producer and receipt-bound release-v3 finalizer.
3. Review and merge the bounded staging preflight; under separate live
authorization, run its control-plane and IAP/SSH observations and verify the
staging repository/tag policy.
4. Under explicit live authorization, build and push one candidate, publish
its receipt, and independently finalize the exact digest.
5. Add the separate fail-closed installer/restart/verification/rollback slice
that consumes the exact inspection-bound release bundle.
6. Provision the scoped Cloud SQL role/secret and deploy the separate staging
service.
7. Prove effective identity, reads, function-only proposal staging, denied
writes/escalation, receipts, restart stability, and rollback.
8. Run behavioral and database parity backtesting.
9. Connect the protected Observatory to canonical claims, proposals, pgvector
projection, and runtime receipts.
10. Cut over, soak, restore-test, revoke VPS credentials, and retire the VPS.
## Current live-action boundary
No merge without explicit human approval, Artifact Registry push,
GCP control-plane or IAP/SSH access, Cloud SQL/Secret Manager mutation,
service deployment/restart, Telegram change, production promotion, canonical
proposal apply, or VPS access is part of the current offline corrective slice.
Any later authorization for the bounded preflight must explicitly accept that
the SSH access path may register a key with a maximum five-minute lifetime.