Production is live on Cloud Run — with evidence boundaries still explicit.
This update folds in the 2026-06-27 production deployment: backend, CMS, and web are live on GCP Cloud Run run.app with Cloud SQL PG17, Upstash Valkey TLS, Secret Manager, and declarative Terraform IaC. The missed shared-table RLS step has also been completed on the live Cloud SQL database and wired into the backend. This is a production-runtime status addendum with no new screenshots; custom-domain browser proof, live public-domain /mcp cross-tenant proof, and UAT remain open.
GCP Cloud Run production deployment — live runtime, RLS wired (no new screenshots)
The owner-selected production topology is now the lower-ops managed path in ADR-DEPLOY-003: Cloud Run (backend + cms + web), Cloud SQL PG17 via Auth-Proxy unix socket, Upstash Valkey TLS, Google Secret Manager, and Cloud Run domain mappings for api/www/admin. This addendum updates executive readiness status; it does not claim fresh production visual approval.
Live shared-table RLS provisioned after deploy
Declarative production state
What is still not proven
Resilience & fail-closed hardening — chaos axis fully closed (no new screenshots)
A run of backend/test-tier prod-readiness lanes shipped as PRs against dev (#107/#108/#110/#111/#112/#113), reducing the codebase's mock-heavy / false-green / stub character with executable chaos & fail-closed coverage — and fixing one real wire-up bug found en route. These are shipped fixes (cited to PRs + spec evidence); no operator screens changed, so the visuals on this page still stand.
Inbound webhook-flood dedup under race (REQ-RCC-006)
AI-generation transaction/connection leak fixed
Quota / GraphRAG / storage fail-closed paths locked
Recommendation ranking & MCP-pool LRU locked
Payments / Donations / E-commerce — shipped & browser-proven (PR #86)
A generic, site-scoped, decoupled payment / donation / e-commerce module shipped as PR #86 against dev (payment-plugin). Donation is one purpose preset of a generic Payment* core. This is a shipped, browser-proven capability (cited to PR + spec + Playwright evidence), with a new donor-form screenshot.
Public donor PaymentForm (DB-driven, real backend)

CMS Donation & Payment + Products & Services admin
One module, many use-cases
Public createPaymentCheckout(purpose) + a provider-registry (add a driver = one blank import) + a single PAYMENT_MODULE_ENABLED mount switch (ADR rejecting a runtime .so). Per-site BYOK secrets (write-only, masked-on-read), per-site routed sessions (VIP DB / non-VIP D2 RLS), order/line-item + product/service/variation/category catalog, and digital entitlements auto-granted on paid.
Claim boundary
Proof tier: unit / property (gopter + fast-check) / mutation / enttest + web vitest + cms mocked-GraphQL component + tsc + governed browser-full-integration (both tiers). Not live external provider/OAuth/settlement, real charge/invoice, DNS/TLS/deploy, UAT, or production. Authority: .agents/specs/payment-plugin/review.md, PR #86.
Production-readiness hardening (no new screenshots)
A backend/config-tier hardening lane shipped as PR #71 against dev, promoted from a repo-wide mock/stub/false-green audit (prod-readiness-wireup-hardening). These are shipped fixes (cited to PR + spec evidence), not roadmap; no new screenshots were captured, so the visuals on this page still stand.
Per-tenant DB connections fail closed in production
Tenant database connections could previously fall back to default credentials and non-TLS in production. They now reject default user/password and require TLS when ENV=production — closing a fail-open path that the central platform-DB validation did not cover. 6 unit tests + 2 hand-killed mutants.
AI provider keys are server-only
The CMS no longer sources provider keys from NEXT_PUBLIC_*_API_KEY (which would inline secrets into the browser bundle); generation routes through the backend BYOK path, and the admin endpoint fallback fails closed on Vercel-style production markers.
Real Postgres-outage health proof
An empty placeholder test was replaced with a real-dependency chaos test: the production health checker against a downed Postgres returns HTTP 503 (unhealthy), bounded — the most central dependency now has executable fail-closed evidence instead of mock-only coverage.
Docs reconciled to real maturity
Module guides that under-stated implemented OAuth (Google/Facebook/Microsoft/Cognito + SAML + LDAP), storage (S3/GCS/Azure/R2/local), and real GraphQL data-binding were corrected — so the genuine remaining gaps stand out instead of being hidden behind stale "TODO" notes.
Platform proven to degrade gracefully (PRs #72–#74)
A new resilience cluster proves the platform stays bounded and never hangs under fault injection: connection-pool exhaustion stays within its limit and recovers; a transient tenant-DB outage isn't cached and routing self-heals; a hung AI provider fails with a bounded typed error. Runtime-backed on governed PostgreSQL + hand-killed mutants.
Sanitizer + fail-closed guards locked (PRs #75–#77)
The user-input→tenant-ID/cms_<slug> database-name sanitizer and the production credential/TLS guards gained property-based (gopter/fast-check) + call-site-wiring tests, so a future refactor can't silently weaken the only sanitizer before a DB name or re-open an insecure connection path.
Registries streamlined, history preserved (PRs #78–#80)
The spec-governance artifacts were token-lean'd while keeping full traceability: ISSUE_LOG.md 270→65, NEXT_STEPS.md 5654→63, RTM.md 2789→382, SPECS.md chars −59% — the complete catalogs/indexes stay in the active files; full history moved verbatim to *_ARCHIVE.md. Open items reconciled to 4, all owner/infra/docs-gated.
Shipped since this review (two backend lanes — no new screenshots)
After the 2026-06-16 capture below, two backend/API-tier lanes shipped as PRs against dev. Both are shipped capabilities (cited to PRs + spec evidence), not roadmap; no new screenshots were captured, so the visuals on this page still stand.
Spawn now provisions the VIP database
A spawned VIP site is no longer a dangling control-plane record: SpawnSite now creates the physical cms_<slug> database and migrates the schema into it (the create-side gap that previously forced hand-creating cms_showcase). Non-VIP/D2 stays record-only by design; fail-closed with site-record rollback. Proven by unit + property + 8 hand-killed mutants + a governed-PostgreSQL integration test.
Messaging & Social draft/template editing API
The two previously-stubbed GraphQL operations are now implemented: updatePostDraft (edit a draft pre-publish; a published post is immutable) and upsertSkillTemplate (create / version-bump), both gated on site.social.manage. Includes a gqlgen codegen-hygiene refactor so schema regen stays safe.
Executive Summary
CMS Platform is a multi-tenant, DB/config-driven CMS with a Go backend, Next.js CMS admin, public web, plugin architecture, AI/SEO surfaces, and governed spec/test evidence. The 2026-06-16 pass refreshed the stakeholder artifacts after the non-VIP tenancy model converged on D2 (shared-table RLS) per ADR-RLS-002, the deprecated schema-tier code was removed, and host-preflight/operator tooling shipped — with the full local stack up on real data/API and fresh evidence.
One platform, two isolation tiers — both demoable
VIP ⇒ database-per-tenant; non-VIP ⇒ shared-table RLS (the "D2" model). Four seeded sites now make both tiers visible: three DATABASE/VIP sites plus tenant-demo on the SCHEMA/non-VIP tier, each rendering identically to the end user.
D2 read path runtime-backed end-to-end
The non-VIP read path is proven on a governed PG15 from primitives → provider → real public MCP read tools → literal HTTP transport, as a genuine non-superuser role, plus a transaction-pool safety proof. A host-capability db-doctor + a one-command provisioning flow make host selection reproducible.
Custom-domain and UAT remain bounded
Cloud Run runtime is live and Cloud SQL RLS is wired; custom-domain browser proof, public-domain /mcp proof, worker, AGE/GraphRAG, multi-region, and UAT are still not claimed.
What's New Since The Last Review (2026-06-16)
Since the 2026-06-15 PR #9 review. Items below are backed by spec-local review.md / tasks.md / ADR evidence cited in the Source Manifest.
D2 is the canonical non-VIP model (ADR-RLS-002)
Owner-approved: non-VIP tenancy is shared-table Row-Level Security keyed on the site, enforced by a non-superuser app role. The deprecated schema-per-tenant/search_path code (provider, router, middleware, per-schema rollout) was removed; one model, one rollout (rls-rollout-shared).
Non-VIP SCHEMA tier now exercised by seed
A fourth seeded site tenant-demo (tenancyTier:schema) renders as a public site at /site/tenant-demo and appears in the DR admin "Sites & DR" table with the SCHEMA badge and a Set VIP action (vs Remove VIP for DATABASE sites) — closing the prior "seed only exercises VIP tier" gap.
Host-capability preflight — migrate db-doctor
A read-mostly probe for any candidate Postgres: can it create a non-superuser app role and have FORCE RLS actually confine it, and does it have pgvector + Apache AGE for runtime GraphRAG (advisory)? Turns host selection from a guess into a reproducible check; runtime-backed on a governed PG15.
Turnkey operator flow + pooling safety
A one-command idempotent provision→seed→rollout→verify script (with --dry-run + a documented env contract), a post-deploy /mcp cross-tenant UAT smoke, and a proof that D2 is safe behind a transaction-mode PgBouncer (SET LOCAL is tx-scoped) + default-OFF PgBouncer Helm values.
Core Features And Evidence
Each card shows Evidence Source, Coverage Tier, and claim boundary directly in the artifact.
tenant-demo — SCHEMA tier public site

CMS DR admin — Sites & DR (now 4 sites)

CMS dashboard

Platform public homepage

Showcase site homepage

NAELT volunteer flow

Platform contact flow

CMS page builder

Host preflight — migrate db-doctor
$ migrate db-doctor ✅ privileged-role-can-create-app-role ✅ app-role-is-non-superuser ✅ app-role-non-bypassrls ✅ force-rls-confines-app-role ⚠️ tls NOT using TLS — set sslmode=require ⚠️ extension:age NOT available — GraphRAG cannot run here ⚠️ extension:vector NOT available — GraphRAG cannot run here ✅ HOST OK for the D2 shared-table-RLS read path.
FAQ
Questions leadership and operators should ask before treating Cloud Run runtime as full launch approval.
Does this prove production readiness?
It proves Cloud Run runtime is live and Cloud SQL shared-table RLS is wired, but it does not prove custom-domain browser behavior, public-domain /mcp cross-tenant isolation, worker runtime, AGE/GraphRAG, multi-region, or UAT sign-off.
What business data is visible?
Backend GraphQL returned 4 seeded sites — platform, naelt, showcase (DATABASE/VIP) and tenant-demo (SCHEMA/non-VIP). The DR admin table renders all four backend-backed; the non-VIP site renders publicly at /site/tenant-demo.
What is the main visual risk?
The non-VIP tier is now exercised, but all four sites set domain none, so the pending-custom-domain Verify affordance and the per-tenant /settings/dr panel are still not seed-exercised; backup/spawn render disabled (unbuilt). CMS captures are hybrid auth with a Next dev "1 Issue" overlay badge.
Is the D2 read path actually wired?
Yes — runtime-backed end-to-end on a governed PG15: primitives → provider → real public MCP read tools → literal HTTP transport, as a non-superuser role, default-off via SCHEMA_TIER_APP_USER. What is NOT done is confirming /mcp over the public custom domain after certificates finish provisioning.
How is auth evidence bounded?
CMS captures used the real CMS runtime plus CMS auth API cookie bootstrap. That is hybrid evidence and must not be described as full browser-login.
What changed since the previous review?
The non-VIP model converged on D2 (ADR-RLS-002) and the deprecated schema-tier code was removed; a non-VIP seed site now exercises the SCHEMA tier visually; and a host-preflight db-doctor + turnkey operator flow + PgBouncer transaction-pool safety shipped.
Runtime Evidence & UX Flow (this pass)
Full local stack up on real data/API, capped to the evidence actually gathered (2026-06-16).
Seed 4 sites (platform, naelt, showcase = DATABASE/VIP; tenant-demo = SCHEMA/non-VIP)
-> Stack up: backend GraphQL :28080 (HTTP 200, 4 seeded sites), CMS :23000,
web :23001, postgres :5432, valkey :6379
-> Public routes 200: /site/platform, /site/platform/contact, /site/naelt,
/site/showcase, /site/tenant-demo, /site/naelt/volunteer/register
-> DR admin /platform/sites renders backend-backed: 4 sites, 1 SCHEMA/non-VIP row
-> Host preflight: `migrate db-doctor` PASS on governed PG15 (non-super + FORCE-RLS
confined; pgvector/AGE advisory-absent); `provision_...py --dry-run` plan printed
-> Fixed scripts/ops.py db seed (broken single-file go run after migrate pkg split)
-> 9 fresh screenshots + 2 CLI transcripts captured under docs/{manual,review}/assets/
-> Production final gate remains blocked until DNS/TLS + deploy + UAT + hosted DB existGap Analysis
Resolved items are real improvements since the prior review; open gaps remain bounded and should not be marketed as complete.
Resolved this pass
- Non-VIP / SCHEMA tier now visually exercised — seeded
tenant-demoon the SCHEMA tier, so the DR admin SCHEMA badge + Set-VIP distinction render with real data and the non-VIP public site loads (closes the top visual gap from 2026-06-15; ISSUE_LOGDR-DEMO-SEED-COVERAGE-001, partial). - Live D2 read path moved from "SQL-only / pending" to runtime-backed end-to-end (provider → real read tools → HTTP transport, non-superuser role) and wired into
/mcp(default-off). - Host-preflight + operator tooling shipped —
db-doctor(incl. pgvector/AGE detection),--dry-run+ env contract, post-deploy UAT smoke, PgBouncer transaction-pool safety + Helm. - Model simplified — D2 is the single canonical non-VIP model (ADR-RLS-002); deprecated schema-tier code removed.
- Seed command fixed —
scripts/ops.py db seedcorrected togo run ./cmd/migrate(the single-file invocation broke after the migrate package split).
Amazon-style PR note
CMS Platform now demonstrates both tenancy tiers end-to-end: a VIP database-per-tenant site and a non-VIP shared-table-RLS site render identically, while a host-capability preflight and a one-command provisioning flow make standing the non-VIP path up on a new Postgres a reproducible, verifiable operation. The next milestone is not more local proof; it is production-domain closure — certificate-complete browser proof, public-domain /mcp cross-tenant proof, UAT, and later worker/AGE/GraphRAG/multi-region decisions.
Pending-domain & tenant DR panel
All four seeded sites set domain none, so the pending-custom-domain Verify affordance and the per-tenant /settings/dr panel are still not visually exercised; backup/spawn ops render disabled (unbuilt).
Hybrid CMS auth captures
CMS captures (dashboard, page builder, DR admin) use auth-cookie bootstrap — hybrid evidence, not full browser-login. A Next dev "1 Issue" overlay badge appears.
No DR admin browser e2e
No full backend-backed CMS browser e2e exists yet for the DR admin UI; the table is shown via backend-backed capture, not an automated browser suite.
Public-domain D2/MCP proof
The live Cloud SQL RLS layer is provisioned and wired, but the public custom-domain /mcp cross-tenant proof still waits for the API certificate and at least two non-VIP tenants.
Worker / AGE / GraphRAG / multi-region
The Cloud Run HTTP services are live; continuous worker runtime, AGE-backed runtime GraphRAG, and multi-region/HA expansion remain deferred decisions.
Custom-domain browser proof + UAT
Cloud Run runtime and DNS mappings exist, but Google-managed certificates were still provisioning during this pass; custom-domain browser proof and UAT are not claimed.
Roadmap / Next Steps
1. Custom-domain browser proof + public MCP
After certificates finish, verify www, admin, and api end-to-end, then run the /mcp cross-tenant UAT smoke against the public API URL.
2. Deferred runtime surfaces
Decide and implement worker runtime, AGE/GraphRAG, multi-region/HA, and any remaining production backup/restore drills.
3. UAT sign-off
Run the launch/UAT matrix against production values and keep proof-tier labels separate from local predecessor screenshots.
Source Manifest
Used sources for this 2026-06-27 pass are explicit. No docs/*FEATURE*.md exists in this repo, so the spec/report/IaC chain below is the fallback authority. RTM.md is rollup only, not readiness authority.
| Source | How it was used |
|---|---|
.agents/specs/{SPECS,NEXT_STEPS,ISSUE_LOG,RTM}.md (2026-06-27 rollup) | Spec registry, rolling queue, issue-first launch notes, and traceability rollup (Cloud Run deployment, live Cloud SQL RLS follow-up, and prior D2 evidence) |
.agents/specs/production-deployment-topology/{review.md,adr/ADR-DEPLOY-003-gcp-cloudrun-cloudsql-cloudflare.md} + infra/terraform/envs/gcp-cloudrun/ | Production deployment authority: Cloud Run runtime live on run.app, Cloud SQL/Upstash connectivity, Terraform IaC, and live shared-table RLS provisioning/wiring claim boundary. |
.agents/specs/schema-per-tenant-routing-rls/{tasks.md (Slice 8), review.md, adr/ADR-RLS-002-NON-VIP-CANONICAL-D2.md} | The D2 canonical model + host-preflight / dry-run / UAT-smoke / transaction-pool-safety deliverables and their claim caps |
.agents/specs/tenant-lifecycle-dr-admin/{design-cms-ui.md,requirements.md,tasks.md} | DR admin UI scope (no review.md in this spec dir; cites the design/requirements/tasks chain) |
backend/seeds/{platform,naelt,showcase,tenant-demo}-*.json | Canonical seed/demo/sample data for the 4 seeded sites (the new tenant-demo carries tenancyTier:schema) |
| Live runtime probes (2026-06-27 deployment pass) | Backend GraphQL 200 in prd on Cloud Run with Cloud SQL socket + Upstash TLS connected; cms/web healthy on run.app; live Cloud SQL shared-table RLS provisioned and verified. Existing 2026-06-16 local route screenshots remain predecessor visual evidence. |
docs/review/assets/*-review-2026-06-16.png + *-cli-2026-06-16.txt | 9 predecessor 2026-06-16 local screenshots + 2 CLI transcripts embedded in this artifact; no new screenshots in the 2026-06-27 deployment addendum |
docs/{REVIEW_GENERATION_GUIDE,PROJECT_REVIEW_GUIDE}.md | Review workflow, capture rules, and project-specific review priorities (2026-06-27 note added) |
docs/*FEATURE*.md | No matching files exist in this repo; fell back to the spec/report chain above |