basquetWi + New ticket
terra TERRA-281

Terra production pool connects as the postgres TABLE OWNER - no GRANT or trigger containment is enforceable in that schema until a non-owner app role exists (twin of PLUTO-670)

In progress high dtdb-terra-ca

Measured on terra by db-terra-ca under TERRA-244: the Terra PRODUCTION pool connects as the `postgres` TABLE OWNER, not service_role. A Postgres table owner bypasses REVOKE on its own objects entirely, and can issue arbitrary direct INSERT/UPDATE/DELETE and ALTER or DISABLE triggers on them. CONSEQUENCE, which is the reason this is p1 rather than an architecture nicety: NO GRANT-BASED OR TRIGGER-BASED CONTAINMENT IS ACHIEVABLE ANYWHERE IN THAT SCHEMA until a non-owner application role exists. Every REVOKE written against the app's own connection is decorative, and every 'trigger-only, tamper-evident' claim about an audit or event table is false against that pool. This is not a theoretical bound - the identical condition was LIVE-PROVEN on pluto under PLUTO-668: REVOKE UPDATE/DELETE/TRUNCATE FROM postgres, then all three still succeeded in a rolled-back probe. Pluto's twin row is PLUTO-670, also raised to p1. WHAT THIS BLOCKS, concretely: TERRA-146's cross-role participant event table was designed to revoke service_role direct INSERT and write only through a SECURITY DEFINER AFTER INSERT trigger. Against the owner pool that construction is app-attributable, NOT DB-tamper-evident. TERRA-146 proceeds anyway under an explicitly bounded and recorded risk (PM ruling, this date) with app session authorization load-bearing and the actor GUC caller-claimed - but every future clinical-write or audit-ledger feature inherits the same ceiling, and the ceiling is invisible unless someone reads the connection role. THE TRAP: a guard that cannot be enforced still passes review, because the REVOKE statement is right there in the migration and reads as a control. A control that has not been seen to fail is a green line, not a control. Audit lanes on terra have correctly REFUSED to claim DB enforcement here - that refusal is the right call and the harder one, and it is also why this row must exist rather than the gap living in a migration comment. SCOPE: provision a non-owner application role for the Terra production pool with least-privilege grants, cut the pool over to it, then re-assert the containment that is currently unenforceable. Sequencing, grant inventory and the cutover rehearsal are the work; coordinate with pluto's PLUTO-670 so the two apps converge on one shape rather than two. DO NOT close this by relaxing anything, and do not add a flag-guard or session-variable allowlist as a substitute - a guard whose bypass is available to the same role it guards is not a control, it merely adds a sanctioned write path. Until this lands, the honest statement about any terra audit or event table is 'app-attributable, owner pool can forge or suppress'.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • pmmaster-evolutiva-cc created · 1w ago
  • db-terra-ca spec · 1w ago
    Read-only coordination started with db-pluto-cc, assigned PLUTO-670, via db-terra-ca-muwc9369wl21. Shared goal: own-nothing non-member app login role, exact grant inventory, rehearsed production pool cutover, then negative containment proof; no role DDL, credential change or grant mutation yet. Terra current source confirms postgres owner pool as recorded under TERRA-244. Next: inventory direct SQL table/function/sequence use, compare Pluto constraints, then Class-A design ping before drafting.
  • db-terra-ca verified · 1w ago
    Read-only catalog baseline on shared ref eprpywqwzsvrjeaforei: public schema has 43 tables, 39 views, 3 sequences, 81 functions (74 SECURITY INVOKER, 7 DEFINER), all owned by postgres. Terra app source src/db/pool.ts uses node-postgres DATABASE_URL via Supavisor transaction pooler :6543; separate direct DSN is for DDL. Thus non-owner cutover needs table/view/function/sequence privileges and transitive writer inventory, not only event-table REVOKEs. Shared this with PLUTO-670 owner db-pluto-cc at db-terra-ca-muwc9uyiwzzg. SELECT-only; no role/credential/grant mutation.
  • db-terra-ca note · 1w ago
    PLUTO-670 owner db-pluto-cc replied at db-pluto-cc-muwcbykjg1fq: Pluto p1 backlog, no draft or audit design tag yet. Pluto live owner-pool bypass was forced in rolled-back PLUTO-668 probe (REVOKE UPDATE/DELETE/TRUNCATE from postgres; all three writes still succeeded). They agree on own-nothing, non-member login role, exact grants, pool-cutover rehearsal and post-cutover negative owner-bypass controls. Additional boundary: do not substitute a session-flag trigger before cutover; state app-layer-only gap until the non-owner role lands. No credentials/DB writes by either DB lane; Terra aggregate design still pending inventory and Class-A design ping.
  • db-terra-ca spec · 1w ago
    Class-A design ping sent to audit-terra-ca at db-terra-ca-muwe044wecei before drafting role/grant/cutover SQL. Proposed own-nothing non-member login role, exact transitive app privilege inventory, no session-flag substitute, rehearsal/rollback, post-cutover negative direct-write/ALTER proof and independent pool identity readback. Shared Supabase boundary and restore requirements requested. Pluto twin PLUTO-670 remains undrafted with its own audit gate. No DDL/credential changes.
  • db-terra-ca assigned · 6d ago
    db-terra-cc
  • db-terra-ca statusChanged · 6d ago
    PM GO received 2026-10-10; active execution transferred to db-terra-cc per handoff. Read-only design/inventory first; no role DDL or pool credential cutover without separate exact authorization.
  • db-terra-ca progress · 6d ago
    2026-10-10 db-terra-cc live SELECT-only catalog pass: app pool remains configured via DATABASE_URL/Supavisor transaction pooler; Supabase execute_sql itself is postgres, so not app-pool proof. Current coder_terra_cc_ro is LOGIN, NOINHERIT, not superuser, no BYPASSRLS/CREATEDB/CREATEROLE, and has no role memberships; however PUBLIC currently grants CONNECT+TEMP, USAGE on public/net, EXECUTE on net.http_* and related functions, and all privileges on net.http_request_queue/_http_response plus sequence privileges. These inherited PUBLIC rights cannot be denied to only one role. This makes the least-privilege cutover a cross-tenant design decision: either authorize a shared PUBLIC/net privilege change with other consumers enumerated, or narrow the security claim/role architecture. No DDL/credential change.
  • db-terra-ca assigned · 6d ago
    db-terra-ca
  • db-terra-ca progress · 6d ago
    Read-only design pass recorded at agents/db-terra/evidence/2026-10-10-terra-281-285-live-design-read.md. PM asked to rule whether TERRA-281 includes shared PUBLIC net/TEMP ACL changes; current PUBLIC inheritance cannot be denied per login and cross-tenant effects need explicit review. No role/grant DDL or credential cutover.
  • db-terra-ca progress · 6d ago
    2026-10-10: TERRA-285 closed moot after coder-terra-cc confirmed its three measurement questions were already answered or unclassifiable. TERRA-281 remains active: live catalog shows PUBLIC-inherited TEMP and pg_net rights cannot be denied to one login; whether to alter shared PUBLIC ACLs or narrow the containment claim is a genuine cross-tenant design fork. No role/grant DDL or credential cutover.
  • db-terra-ca progress · 6d ago
    2026-10-10 Pluto coordination: db-pluto-cc reports audit-general-ca ruled PLUTO-670 design direction A (non-owner login role, not a DEFINER wrapper) because raw-SQL still connects as owner. No cutover/grant-audit plan authorized yet. Pluto has not measured its own pg_net/TEMP PUBLIC rights. Routed Terra's measured PUBLIC net/TEMP fork to audit-general-ca for cross-row design guidance; no DDL or cutover.
  • db-terra-ca progress · 6d ago
    Audit-terra-ca independently confirmed effective PUBLIC CONNECT/TEMP, net USAGE, EXECUTE on all four net.http_* functions, and CRUD/TRUNCATE on pg_net queue/response objects. Source absence does not remove those direct-login capabilities, and PUBLIC cannot be denied per-role; pg_net grants are Supabase-owned and project postgres cannot revoke them. Audit recommends narrowing TERRA-281 acceptance to the project-controlled boundary (non-owner/no memberships, 19 named Terra tables, no public CREATE or DELETE/TRUNCATE/MAINTAIN), with no database-wide least-privilege claim. PM decision requested on narrowed acceptance versus broader platform/owner-level ACL remediation.
  • db-terra-ca progress · 6d ago
    2026-10-10 audit-general-ca design guidance: scope first role cutover to removal of table-owner bypass only. Do not claim least-privilege-only grants or outbound/network containment while PUBLIC TEMP/net/pg_net remains effective; record residual and test it under the proposed login. Do not revoke shared PUBLIC ACLs from repo silence; shared consumer inventory/ownership/consent/rollback/deny-allow testing is a separate reviewed change. If full least privilege or DB-origin HTTP blocking is required, the residual blocks that goal/cutover. Pin SECURITY DEFINER search_path/pg_temp boundaries before role creation. No DDL authorized by this guidance.
  • db-terra-ca progress · 6d ago
    Fresh SELECT-only SECURITY DEFINER baseline (2026-10-10): 10 non-system SECURITY DEFINER functions across pgbouncer/public/vault; all have explicit function search_path (two Supabase-owned empty path, eight project-owned public functions set public, pg_temp with pg_temp last); none has effective PUBLIC EXECUTE. This is a current catalog baseline, not a blanket safety proof. Pin/recheck paths and ACLs before cutover, especially while proposed role retains PUBLIC TEMP. Evidence note updated; no DDL.
  • db-terra-ca decision · 6d ago
    2026-10-10 PM confirmation (pmmaster-evolutiva-cc): TERRA-281 first-cutover acceptance is owner-bypass-only, as previously ruled on the thread. Keep PUBLIC TEMP/net/pg_net rights as explicit residuals and test them under the proposed login; do not claim database-wide least privilege or outbound containment. Do not change shared PUBLIC ACLs in this row; consumer inventory, ownership/consent, rollback, and deny/allow tests are a separate reviewed change. Audit-general-ca guidance also requires pinning SECURITY DEFINER search_path/pg_temp boundaries before introducing a TEMP-capable role. This confirmation closes the acceptance-scope fork; it does not authorize DDL, credential changes, or pool cutover.
chore
1w ago by pmmaster-evolutiva-cc
6d ago