teleo-infrastructure/docs/observatory-read-adapter-gcp-staging.md
twentyOne2x 92da54d804
Some checks are pending
CI / lint-and-test (push) Waiting to run
Add authenticated GCP Observatory read adapter (#154)
2026-07-15 03:43:05 +02:00

5.2 KiB

GCP Observatory Read Adapter

Definition of Working

  • Working target: an authenticated GCP staging API returns one canonical claim with source/evidence provenance and a separately labeled proposal ledger.
  • Operator path: GET /v1/claims/sample or GET /v1/claims/{uuid} with the server-only X-Api-Key value.
  • Done means: the response names teleo_canonical, the dedicated IAM database principal and kb_observatory_read, reports a read-only transaction and denied write privileges, and live anonymous/write HTTP attempts return 401/405.
  • Not done: the VPS teleo-pg, a public Cloud SQL address, a browser-visible key, a mock-only receipt, or a production Vercel repoint.
  • Required tier: T3_live_readonly.

Existing Connector Boundary

The current living-ip/livingip-web main branch reads claims through src/lib/api.ts. It selects NEXT_PUBLIC_API_URL and otherwise falls back to http://77.42.65.182:8081, then calls the legacy /api/claims routes. That is the VPS-local/public Observatory path. It is not safe to replace that public environment variable with this protected API: the response shape differs and the adapter key must never enter a NEXT_PUBLIC_ variable or browser bundle.

The existing Teleo route GET /api/kb/claims is the compatibility reference for route-scoped authentication, but its default database/container settings still describe the VPS-local process. This service is a separate GCP runtime; it does not change Argus or PR #148's Leo runtime files.

Runtime Contract

  • Cloud Run service: observatory-read-adapter-staging in europe-west6.
  • Direct VPC egress: teleo-staging-net / teleo-staging-europe-west6.
  • Cloud SQL: teleo-501523:europe-west6:teleo-pgvector-standby, private IP.
  • Database: teleo_canonical only.
  • Runtime identity: sa-observatory-read-adapter@teleo-501523.iam.gserviceaccount.com.
  • IAM database user: sa-observatory-read-adapter@teleo-501523.iam.
  • Database authorization role: kb_observatory_read (NOLOGIN).
  • API authentication: route-scoped key from Secret Manager secret observatory-read-api-key-staging; the value is not in Git or deploy logs.
  • No mutation routes exist. Authenticated unsupported methods return 405.

The Cloud SQL Python Connector uses Application Default Credentials from the Cloud Run service identity, automatic IAM database authentication, and private IP. Every request starts a read-only transaction and refuses the response if the database, IAM principal, authorization membership, required reads, or effective write-denial checks drift.

One-Time Staging Bootstrap

These are staging mutations. Run them only with an authenticated GCP operator; they do not route production traffic.

  1. Create the dedicated runtime service account and grant only roles/cloudsql.client and roles/cloudsql.instanceUser in project teleo-501523.
  2. Add the service account as a Cloud SQL IAM service-account user on teleo-pgvector-standby.
  3. From the existing private GCP VM database-admin path, run ops/observatory_read_role.sql against teleo_canonical with OBSERVATORY_DB_IAM_USER=sa-observatory-read-adapter@teleo-501523.iam. Do not read, copy, or retain the administrator password.
  4. Create observatory-read-api-key-staging, add a generated 32-byte-or-longer value through stdin, and grant that secret's accessor role only to the runtime service account and the bounded staging canary identity.
  5. Dispatch .github/workflows/gcp-observatory-read-adapter.yml with action=deploy_staging from the exact reviewed branch revision.

The workflow builds an immutable image, deploys at most two Cloud Run instances, and retains the positive response plus anonymous 401 and authenticated POST 405 receipts. It does not modify Vercel.

Unexecuted Cutover Packet

Production cutover requires a separate exact authorization and a living-ip/livingip-web change. Do not execute these steps from this lane.

  1. Add server-only Vercel secrets OBSERVATORY_CANONICAL_API_URL and OBSERVATORY_CANONICAL_API_KEY to a protected preview environment. The URL targets the GCP service; neither setting may use NEXT_PUBLIC_.
  2. Add a Next.js server route or server action that calls the GCP API, validates livingip.observatory-canonical-claim.v1, and maps it to the Observatory UI. The browser calls only the same-origin Next.js route.
  3. Prove preview Deployment Protection, anonymous denial, source/evidence rendering, proposal/live labels, and no browser key exposure.
  4. Obtain exact production-repoint authorization naming the reviewed livingip-web commit and Vercel project before changing production values.

Unexecuted Rollback Packet

  1. Revert the authorized livingip-web connector commit or disable its server-side feature flag.
  2. Restore the prior production Vercel values and redeploy the last accepted production revision.
  3. Verify /claims again uses the prior /api/claims contract.
  4. Leave the private Cloud SQL instance and adapter role intact while receipts are reviewed; scale the staging Cloud Run service to zero if isolation is required.
  5. Delete the staging service/role/secret only under a separate cleanup decision. Rollback never adds a Cloud SQL public IP and never redirects the adapter to VPS teleo-pg.