Merge the T2 readiness and least-privilege staging gate. This does not deploy Cloud Run, mutate Cloud SQL, or change production routing.
9.9 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/sampleorGET /v1/claims/{uuid}with the server-onlyX-Api-Keyvalue. - Done means: the response names
teleo_canonical, the dedicated IAM database principal andkb_observatory_read, reports a read-only transaction and denied write privileges, and live anonymous/write HTTP attempts return401/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-stagingineurope-west6. - Direct VPC egress:
teleo-staging-net/teleo-staging-europe-west6. - Cloud SQL:
teleo-501523:europe-west6:teleo-pgvector-standby, private IP. - Database:
teleo_canonicalonly. - Build identity:
sa-artifact-builder@teleo-501523.iam.gserviceaccount.com; image build/push only. - Staging deploy/canary identity:
sa-observatory-deployer@teleo-501523.iam.gserviceaccount.com; an exact workflow/main-only WIF provider, a five-permission Cloud Run custom role, repository read, exact runtimeactAs, and exact secret access. Never grant deploy permissions to the artifact builder. - 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.
-
Reauthenticate the project operator, then run the first full direct check:
gcloud projects describe teleo-501523 --format=value(projectId) python3 ops/check_gcp_infra_readiness.py -
Review the exact dry-run packet. It enables only required APIs, creates separate staging deploy/runtime identities, creates the dedicated
observatory-read-adapter-mainWIF provider, keeps the artifact builder narrow, scopes Cloud SQL connect/login toteleo-pgvector-standby, and scopes secret access toobservatory-read-api-key-staging:python3 ops/plan_observatory_read_adapter_gcp.py python3 ops/plan_observatory_read_adapter_gcp.py --format shellThe shell output is unexecuted and uses
set -euo pipefail. Apply it only after review with an authenticatedteleo-501523administrator. The deployer custom role contains onlyrun.services.create,run.services.update,run.services.get,run.services.setIamPolicy, andrun.operations.get; it contains no delete permission. Do not addrun.admin,run.developer,cloudsql.admin,secretmanager.admin,compute.admin, Editor, or Owner to either lane identity. -
Add the dedicated runtime service account as a Cloud SQL IAM service-account user on
teleo-pgvector-standby. -
From the existing private GCP VM database-admin path, run
ops/observatory_read_role.sqlagainstteleo_canonicalwithOBSERVATORY_DB_IAM_USER=sa-observatory-read-adapter@teleo-501523.iam. Do not read, copy, or retain the administrator password. -
Create
observatory-read-api-key-staging, add a generated whitespace-free 32-byte-or-longer value through stdin only when no enabled version exists, and grant that secret's accessor role only to the runtime service account and the dedicated staging deploy/canary identity. Deployment pins the exact enabled version; it does not injectlatestinto Cloud Run. -
Dispatch the read-only preflight from merged
main:gh workflow run gcp-observatory-read-adapter.yml \ --repo living-ip/teleo-infrastructure \ --ref main \ -f action=preflight_stagingRequire a passing
observatory-read-adapter-preflightartifact before a boundedaction=deploy_stagingdispatch. The preflight verifies the exact WIF condition, custom-role permission sets, project/resource IAM bindings, Cloud Run service agent, private VPC/subnet relationship, private-only Cloud SQL network and IAM authentication, trimmed IAM database user, exact secret policy/value shape, and the run-unique immutable image. It also rejects any artifact-builder deploy, runtimeactAs, secret, or service binding.
The workflow always builds a run-unique immutable image, deploys at most two Cloud Run
instances, and retains the positive response plus anonymous 401 and
authenticated POST 405 receipts. The retained positive receipt contains
identity/provenance, counts, and proposal/live state only; claim text, source
URLs, excerpts, unknown future provenance fields, and secret values are
removed by an explicit tested allowlist. The live gate binds the response to
the exact project, private instance, database principal, Git revision, Cloud
Run image digest, runtime identity, and pinned secret version. It does not
modify Vercel. The app-level X-Api-Key remains the staging authentication
boundary, so anonymous Cloud Run invocation reaches the adapter and returns
the required 401 instead of a platform-generated status.
Current T2 Receipt And Exact T3 Gate
GitHub Actions run 29389090997 proves the existing living-ip-github WIF
provider can federate as the artifact builder, run the checker, upload its
artifact, and clean up credentials. The checker reported 8 pass, 10
blocked, 0 fail. Eight blocks are missing inventory permissions on the
artifact-builder identity; two are missing restore/replication proof. This is
partial OIDC/T2 evidence, not T3 and not authorization to deploy with that
identity.
The exact external action is for billy@livingip.xyz to reauthenticate gcloud
and ADC, prove gcloud projects describe teleo-501523, run
python3 ops/check_gcp_infra_readiness.py, review and execute the planner's
shell output as a project IAM/API administrator, then apply
ops/observatory_read_role.sql from the existing private database-admin path.
The general readiness identity and artifact-builder identity are not deployer
substitutes. After those actions, dispatch preflight_staging; only a passing
artifact permits deploy_staging. A passing preflight remains T2 setup proof:
the fail-closed live claim and negative receipts are what establish T3.
The IAM basis is the Google Cloud deployment contract for Cloud Run (Cloud Run
access, Artifact Registry repository read, and exact runtime actAs), Secret
Manager resource-level accessor grants, Direct VPC access through the default
Cloud Run service agent, and conditional Cloud SQL client access to one named
instance:
- https://docs.cloud.google.com/run/docs/deploying
- https://docs.cloud.google.com/run/docs/authenticating/public
- https://docs.cloud.google.com/run/docs/configuring/vpc-direct-vpc
- https://docs.cloud.google.com/iam/docs/workload-identity-federation-with-deployment-pipelines
- https://docs.cloud.google.com/secret-manager/docs/manage-access-to-secrets
- https://docs.cloud.google.com/sql/docs/postgres/iam-conditions
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.
- Add server-only Vercel secrets
OBSERVATORY_CANONICAL_API_URLandOBSERVATORY_CANONICAL_API_KEYto a protected preview environment. The URL targets the GCP service; neither setting may useNEXT_PUBLIC_. - 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. - Prove preview Deployment Protection, anonymous denial, source/evidence rendering, proposal/live labels, and no browser key exposure.
- Obtain exact production-repoint authorization naming the reviewed
livingip-webcommit and Vercel project before changing production values.
Unexecuted Rollback Packet
- Revert the authorized
livingip-webconnector commit or disable its server-side feature flag. - Restore the prior production Vercel values and redeploy the last accepted production revision.
- Verify
/claimsagain uses the prior/api/claimscontract. - 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.
- 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.