# 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`.
