\set ON_ERROR_STOP on \getenv runtime_password TELEO_LEOCLEAN_DB_PASSWORD -- One-time GCP staging provisioning for Leo's Cloud SQL identity. The password -- is supplied only through the process environment and is never stored here. -- -- The login can read the canonical allowlist and can stage a pending proposal -- through one narrowly-scoped SECURITY DEFINER function. It cannot inherit or -- SET ROLE into another principal, forge the proposer identity, write directly -- to canonical/staging tables, or inspect the legacy teleo_restore audit schema. select 'create role leoclean_kb_runtime login nosuperuser nocreatedb nocreaterole noinherit noreplication nobypassrls connection limit 8' where not exists (select 1 from pg_catalog.pg_roles where rolname = 'leoclean_kb_runtime') \gexec select 'create role leoclean_kb_stage_owner nologin nosuperuser nocreatedb nocreaterole noinherit noreplication nobypassrls connection limit -1' where not exists (select 1 from pg_catalog.pg_roles where rolname = 'leoclean_kb_stage_owner') \gexec select format('alter role leoclean_kb_runtime password %L', :'runtime_password') \gexec alter role leoclean_kb_runtime with login nosuperuser nocreatedb nocreaterole noinherit noreplication nobypassrls connection limit 8; alter role leoclean_kb_stage_owner with nologin nosuperuser nocreatedb nocreaterole noinherit noreplication nobypassrls connection limit -1 password null; alter role leoclean_kb_runtime reset all; alter role leoclean_kb_stage_owner reset all; -- NOINHERIT does not prevent SET ROLE. Remove every membership edge in either -- direction so neither scoped principal can reach, or be reached through, a -- broader role left behind by an earlier deployment. select format('revoke %I from %I', granted_role.rolname, member_role.rolname) from pg_catalog.pg_auth_members membership join pg_catalog.pg_roles granted_role on granted_role.oid = membership.roleid join pg_catalog.pg_roles member_role on member_role.oid = membership.member where granted_role.rolname in ('leoclean_kb_runtime', 'leoclean_kb_stage_owner') or member_role.rolname in ('leoclean_kb_runtime', 'leoclean_kb_stage_owner') \gexec revoke all privileges on database teleo_canonical from leoclean_kb_runtime; revoke all privileges on database teleo_canonical from leoclean_kb_stage_owner; revoke all privileges on database teleo_kb from leoclean_kb_runtime; revoke all privileges on database teleo_kb from leoclean_kb_stage_owner; grant connect on database teleo_canonical to leoclean_kb_runtime; -- PostgreSQL normally grants TEMP to PUBLIC. A role-specific REVOKE cannot -- override that inherited grant, while REVOKE TEMP FROM PUBLIC would be a -- database-wide change that could break kb_apply/review or operator workflows. -- Leave PUBLIC TEMP policy unchanged here and surface it in the final receipt. -- TEMP cannot shadow this SECURITY DEFINER boundary: pg_catalog is first, -- pg_temp is explicitly last, and every relation reference is schema-qualified. -- Database CREATE, direct TEMP grants, and all unexpected direct database ACLs -- are rejected below. A database-wide TEMP removal requires a separate role-use -- inventory and explicit grants to every workload that still needs it. alter role leoclean_kb_runtime in database teleo_canonical reset all; alter role leoclean_kb_stage_owner in database teleo_canonical reset all; alter role leoclean_kb_runtime in database teleo_kb reset all; alter role leoclean_kb_stage_owner in database teleo_kb reset all; alter role leoclean_kb_runtime in database teleo_canonical set search_path = pg_catalog, public, kb_stage; alter role leoclean_kb_runtime in database teleo_canonical set statement_timeout = '15s'; alter role leoclean_kb_runtime in database teleo_canonical set lock_timeout = '2s'; \connect teleo_canonical begin; -- The deploy principal needs temporary ownership authority to replace an -- existing function on idempotent reruns. This membership is transaction-local -- and is revoked before verification/commit. select format('grant leoclean_kb_stage_owner to %I', current_user) where current_user <> 'leoclean_kb_stage_owner' \gexec revoke all on schema public, kb_stage from leoclean_kb_runtime, leoclean_kb_stage_owner; revoke all privileges on all tables in schema public, kb_stage from leoclean_kb_runtime, leoclean_kb_stage_owner; revoke all privileges on all sequences in schema public, kb_stage from leoclean_kb_runtime, leoclean_kb_stage_owner; revoke all privileges on all functions in schema public, kb_stage from leoclean_kb_runtime, leoclean_kb_stage_owner; revoke all privileges on all procedures in schema public, kb_stage from leoclean_kb_runtime, leoclean_kb_stage_owner; -- Table-level REVOKE does not clear column ACLs. Clear every column ACL for both -- principals before rebuilding the exact allowlist below. select format( 'revoke all privileges (%s) on table %I.%I from %I', pg_catalog.string_agg(pg_catalog.quote_ident(attribute.attname), ', ' order by attribute.attnum), namespace.nspname, relation.relname, target.rolname ) from pg_catalog.pg_class relation join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace join pg_catalog.pg_attribute attribute on attribute.attrelid = relation.oid cross join ( values ('leoclean_kb_runtime'), ('leoclean_kb_stage_owner') ) as target(rolname) where namespace.nspname in ('public', 'kb_stage') and relation.relkind in ('r', 'p', 'v', 'm', 'f') and attribute.attnum > 0 and not attribute.attisdropped group by namespace.nspname, relation.relname, target.rolname \gexec grant usage on schema public, kb_stage to leoclean_kb_runtime; grant select on public.agents, public.claims, public.claim_evidence, public.claim_edges, public.sources, public.personas, public.strategies, public.beliefs, public.blindspots, public.agent_roles, public.peer_models, public.behavioral_rules, public.contributor_rules, public.reasoning_tools, public.governance_gates, kb_stage.kb_proposals to leoclean_kb_runtime; -- The function owner is a dedicated NOLOGIN role. Grant only the columns the -- function reads/inserts. CREATE is temporary and is revoked immediately after -- ownership is assigned. grant usage, create on schema kb_stage to leoclean_kb_stage_owner; grant usage on schema public to leoclean_kb_stage_owner; grant select (id, handle) on public.agents to leoclean_kb_stage_owner; grant select on kb_stage.kb_proposals to leoclean_kb_stage_owner; grant insert ( proposal_type, status, proposed_by_handle, proposed_by_agent_id, channel, source_ref, rationale, payload ) on kb_stage.kb_proposals to leoclean_kb_stage_owner; -- Remove the prior caller-supplied-identity overload before installing the -- session-bound form. A runtime caller can only stage as canonical agent Leo. drop function if exists kb_stage.stage_leoclean_proposal(text, text, text, text, text, jsonb); create or replace function kb_stage.stage_leoclean_proposal( p_proposal_type text, p_channel text, p_source_ref text, p_rationale text, p_payload jsonb ) returns jsonb language plpgsql security definer set search_path = pg_catalog, pg_temp as $function$ declare staged kb_stage.kb_proposals%rowtype; proposer_id uuid; begin if session_user <> 'leoclean_kb_runtime' then raise exception 'stage_leoclean_proposal is restricted to leoclean_kb_runtime' using errcode = '42501'; end if; if p_proposal_type not in ('revise_claim', 'revise_strategy', 'add_edge') then raise exception 'unsupported Leo proposal type: %', p_proposal_type using errcode = '22023'; end if; if nullif(btrim(p_source_ref), '') is null then raise exception 'source_ref is required' using errcode = '22023'; end if; if nullif(btrim(p_rationale), '') is null then raise exception 'rationale is required' using errcode = '22023'; end if; if p_payload is null or jsonb_typeof(p_payload) <> 'object' then raise exception 'proposal payload must be a JSON object' using errcode = '22023'; end if; select agent.id into proposer_id from public.agents as agent where agent.handle = 'leo'; if proposer_id is null then raise exception 'canonical Leo agent row is required' using errcode = '23503'; end if; insert into kb_stage.kb_proposals ( proposal_type, status, proposed_by_handle, proposed_by_agent_id, channel, source_ref, rationale, payload ) values ( p_proposal_type, 'pending_review', 'leo', proposer_id, coalesce(nullif(p_channel, ''), 'telegram'), p_source_ref, p_rationale, p_payload ) returning * into staged; return to_jsonb(staged); end $function$; alter function kb_stage.stage_leoclean_proposal(text, text, text, text, jsonb) owner to leoclean_kb_stage_owner; revoke create on schema kb_stage from leoclean_kb_stage_owner; -- Normalize explicit ACL entries left by CREATE OR REPLACE or an earlier grant. revoke all on function kb_stage.stage_leoclean_proposal(text, text, text, text, jsonb) from public; select format( 'revoke all on function kb_stage.stage_leoclean_proposal(text, text, text, text, jsonb) from %I', grantee.rolname ) from pg_catalog.pg_proc function_row cross join lateral pg_catalog.aclexplode( coalesce( function_row.proacl, pg_catalog.acldefault('f', function_row.proowner) ) ) as acl join pg_catalog.pg_roles grantee on grantee.oid = acl.grantee where function_row.oid = 'kb_stage.stage_leoclean_proposal(text,text,text,text,jsonb)'::pg_catalog.regprocedure and grantee.rolname <> 'leoclean_kb_stage_owner' \gexec grant execute on function kb_stage.stage_leoclean_proposal(text, text, text, text, jsonb) to leoclean_kb_runtime; select format('revoke leoclean_kb_stage_owner from %I', current_user) where current_user <> 'leoclean_kb_stage_owner' \gexec do $verification$ declare unexpected text; runtime_oid oid := 'leoclean_kb_runtime'::pg_catalog.regrole::oid; owner_oid oid := 'leoclean_kb_stage_owner'::pg_catalog.regrole::oid; stage_function oid := 'kb_stage.stage_leoclean_proposal(text,text,text,text,jsonb)'::pg_catalog.regprocedure::oid; begin if exists ( select 1 from pg_catalog.pg_roles role_row where role_row.rolname = 'leoclean_kb_runtime' and (not role_row.rolcanlogin or role_row.rolsuper or role_row.rolcreatedb or role_row.rolcreaterole or role_row.rolinherit or role_row.rolreplication or role_row.rolbypassrls or role_row.rolconnlimit <> 8) ) then raise exception 'leoclean_kb_runtime has unsafe role attributes'; end if; if exists ( select 1 from pg_catalog.pg_roles role_row where role_row.rolname = 'leoclean_kb_stage_owner' and (role_row.rolcanlogin or role_row.rolsuper or role_row.rolcreatedb or role_row.rolcreaterole or role_row.rolinherit or role_row.rolreplication or role_row.rolbypassrls or role_row.rolconnlimit <> -1) ) then raise exception 'leoclean_kb_stage_owner has unsafe role attributes'; end if; select pg_catalog.string_agg( pg_catalog.format('%I->%I', granted_role.rolname, member_role.rolname), ', ' order by granted_role.rolname, member_role.rolname ) into unexpected from pg_catalog.pg_auth_members membership join pg_catalog.pg_roles granted_role on granted_role.oid = membership.roleid join pg_catalog.pg_roles member_role on member_role.oid = membership.member where membership.roleid in (runtime_oid, owner_oid) or membership.member in (runtime_oid, owner_oid); if unexpected is not null then raise exception 'scoped Leo roles retain role memberships: %', unexpected; end if; select pg_catalog.string_agg( pg_catalog.format( '%I:%s:%s:grantable=%s', database_row.datname, grantee.rolname, acl.privilege_type, acl.is_grantable ), ', ' order by database_row.datname, grantee.rolname, acl.privilege_type ) into unexpected from pg_catalog.pg_database database_row cross join lateral pg_catalog.aclexplode( coalesce( database_row.datacl, pg_catalog.acldefault('d', database_row.datdba) ) ) as acl join pg_catalog.pg_roles grantee on grantee.oid = acl.grantee where database_row.datname in ('teleo_canonical', 'teleo_kb') and grantee.rolname in ('leoclean_kb_runtime', 'leoclean_kb_stage_owner') and not ( database_row.datname = 'teleo_canonical' and grantee.rolname = 'leoclean_kb_runtime' and acl.privilege_type = 'CONNECT' and not acl.is_grantable ); if unexpected is not null then raise exception 'scoped Leo roles retain unexpected direct database ACLs: %', unexpected; end if; if has_database_privilege('leoclean_kb_runtime', 'teleo_canonical', 'CREATE') or has_database_privilege('leoclean_kb_runtime', 'teleo_kb', 'CREATE') or has_database_privilege('leoclean_kb_stage_owner', 'teleo_canonical', 'CREATE') or has_database_privilege('leoclean_kb_stage_owner', 'teleo_kb', 'CREATE') then raise exception 'a scoped Leo role unexpectedly has database CREATE'; end if; select pg_catalog.string_agg( pg_catalog.format('%s:%s:%s', dependency.classid::pg_catalog.regclass, dependency.objid, dependency.objsubid), ', ' ) into unexpected from pg_catalog.pg_shdepend dependency where dependency.refclassid = 'pg_catalog.pg_authid'::pg_catalog.regclass and dependency.refobjid = runtime_oid and dependency.deptype = 'o'; if unexpected is not null then raise exception 'leoclean_kb_runtime unexpectedly owns database objects: %', unexpected; end if; select pg_catalog.string_agg( pg_catalog.format('%s:%s:%s', dependency.classid::pg_catalog.regclass, dependency.objid, dependency.objsubid), ', ' ) into unexpected from pg_catalog.pg_shdepend dependency where dependency.refclassid = 'pg_catalog.pg_authid'::pg_catalog.regclass and dependency.refobjid = owner_oid and dependency.deptype = 'o' and not ( dependency.dbid = (select database_row.oid from pg_catalog.pg_database database_row where database_row.datname = current_database()) and dependency.classid = 'pg_catalog.pg_proc'::pg_catalog.regclass and dependency.objid = stage_function and dependency.objsubid = 0 ); if unexpected is not null then raise exception 'leoclean_kb_stage_owner owns unexpected database objects: %', unexpected; end if; if has_schema_privilege('leoclean_kb_runtime', 'public', 'CREATE') or has_schema_privilege('leoclean_kb_runtime', 'kb_stage', 'CREATE') or has_schema_privilege('leoclean_kb_stage_owner', 'public', 'CREATE') or has_schema_privilege('leoclean_kb_stage_owner', 'kb_stage', 'CREATE') then raise exception 'a scoped Leo role unexpectedly has schema CREATE'; end if; select pg_catalog.string_agg( pg_catalog.format('%I.%I:%s', namespace.nspname, relation.relname, privilege.name), ', ' order by namespace.nspname, relation.relname, privilege.name ) into unexpected from pg_catalog.pg_class relation join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace cross join (values ('INSERT'), ('UPDATE'), ('DELETE'), ('TRUNCATE'), ('REFERENCES'), ('TRIGGER')) privilege(name) where namespace.nspname in ('public', 'kb_stage') and relation.relkind in ('r', 'p', 'v', 'm', 'f') and has_table_privilege('leoclean_kb_runtime', relation.oid, privilege.name); if unexpected is not null then raise exception 'leoclean_kb_runtime unexpectedly has table-level DML: %', unexpected; end if; select pg_catalog.string_agg( pg_catalog.format('%I.%I.%I:%s', namespace.nspname, relation.relname, attribute.attname, privilege.name), ', ' order by namespace.nspname, relation.relname, attribute.attnum, privilege.name ) into unexpected from pg_catalog.pg_class relation join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace join pg_catalog.pg_attribute attribute on attribute.attrelid = relation.oid cross join (values ('INSERT'), ('UPDATE'), ('REFERENCES')) privilege(name) where namespace.nspname in ('public', 'kb_stage') and relation.relkind in ('r', 'p', 'v', 'm', 'f') and attribute.attnum > 0 and not attribute.attisdropped and has_column_privilege('leoclean_kb_runtime', relation.oid, attribute.attnum, privilege.name); if unexpected is not null then raise exception 'leoclean_kb_runtime unexpectedly has column-level DML: %', unexpected; end if; select pg_catalog.string_agg( pg_catalog.format('%I.%I', namespace.nspname, relation.relname), ', ' order by namespace.nspname, relation.relname ) into unexpected from pg_catalog.pg_class relation join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace where namespace.nspname in ('public', 'kb_stage') and relation.relkind in ('r', 'p', 'v', 'm', 'f') and has_table_privilege('leoclean_kb_runtime', relation.oid, 'SELECT') and (namespace.nspname, relation.relname) not in ( ('public', 'agents'), ('public', 'claims'), ('public', 'claim_evidence'), ('public', 'claim_edges'), ('public', 'sources'), ('public', 'personas'), ('public', 'strategies'), ('public', 'beliefs'), ('public', 'blindspots'), ('public', 'agent_roles'), ('public', 'peer_models'), ('public', 'behavioral_rules'), ('public', 'contributor_rules'), ('public', 'reasoning_tools'), ('public', 'governance_gates'), ('kb_stage', 'kb_proposals') ); if unexpected is not null then raise exception 'leoclean_kb_runtime can SELECT outside its table allowlist: %', unexpected; end if; select pg_catalog.string_agg( pg_catalog.format('%I.%I.%I', namespace.nspname, relation.relname, attribute.attname), ', ' order by namespace.nspname, relation.relname, attribute.attnum ) into unexpected from pg_catalog.pg_class relation join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace join pg_catalog.pg_attribute attribute on attribute.attrelid = relation.oid where namespace.nspname in ('public', 'kb_stage') and relation.relkind in ('r', 'p', 'v', 'm', 'f') and attribute.attnum > 0 and not attribute.attisdropped and has_column_privilege('leoclean_kb_runtime', relation.oid, attribute.attnum, 'SELECT') and (namespace.nspname, relation.relname) not in ( ('public', 'agents'), ('public', 'claims'), ('public', 'claim_evidence'), ('public', 'claim_edges'), ('public', 'sources'), ('public', 'personas'), ('public', 'strategies'), ('public', 'beliefs'), ('public', 'blindspots'), ('public', 'agent_roles'), ('public', 'peer_models'), ('public', 'behavioral_rules'), ('public', 'contributor_rules'), ('public', 'reasoning_tools'), ('public', 'governance_gates'), ('kb_stage', 'kb_proposals') ); if unexpected is not null then raise exception 'leoclean_kb_runtime has column SELECT outside its allowlist: %', unexpected; end if; if has_table_privilege('leoclean_kb_stage_owner', 'public.agents', 'SELECT') or not has_column_privilege('leoclean_kb_stage_owner', 'public.agents', 'id', 'SELECT') or not has_column_privilege('leoclean_kb_stage_owner', 'public.agents', 'handle', 'SELECT') or not has_table_privilege('leoclean_kb_stage_owner', 'kb_stage.kb_proposals', 'SELECT') or has_table_privilege('leoclean_kb_stage_owner', 'kb_stage.kb_proposals', 'INSERT') then raise exception 'leoclean_kb_stage_owner does not have the exact read/insert grant shape'; end if; select pg_catalog.string_agg( pg_catalog.format('%I.%I.%I', namespace.nspname, relation.relname, attribute.attname), ', ' order by namespace.nspname, relation.relname, attribute.attnum ) into unexpected from pg_catalog.pg_class relation join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace join pg_catalog.pg_attribute attribute on attribute.attrelid = relation.oid where namespace.nspname in ('public', 'kb_stage') and relation.relkind in ('r', 'p', 'v', 'm', 'f') and attribute.attnum > 0 and not attribute.attisdropped and has_column_privilege('leoclean_kb_stage_owner', relation.oid, attribute.attnum, 'INSERT') and not ( namespace.nspname = 'kb_stage' and relation.relname = 'kb_proposals' and attribute.attname in ( 'proposal_type', 'status', 'proposed_by_handle', 'proposed_by_agent_id', 'channel', 'source_ref', 'rationale', 'payload' ) ); if unexpected is not null then raise exception 'leoclean_kb_stage_owner can INSERT unexpected columns: %', unexpected; end if; select pg_catalog.string_agg( pg_catalog.format('%I.%I:%s', namespace.nspname, relation.relname, privilege.name), ', ' order by namespace.nspname, relation.relname, privilege.name ) into unexpected from pg_catalog.pg_class relation join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace cross join (values ('INSERT'), ('UPDATE'), ('DELETE'), ('TRUNCATE'), ('REFERENCES'), ('TRIGGER')) privilege(name) where namespace.nspname in ('public', 'kb_stage') and relation.relkind in ('r', 'p', 'v', 'm', 'f') and has_table_privilege('leoclean_kb_stage_owner', relation.oid, privilege.name); if unexpected is not null then raise exception 'leoclean_kb_stage_owner unexpectedly has table-level DML: %', unexpected; end if; select pg_catalog.string_agg( pg_catalog.format('%I.%I.%I:%s', namespace.nspname, relation.relname, attribute.attname, privilege.name), ', ' order by namespace.nspname, relation.relname, attribute.attnum, privilege.name ) into unexpected from pg_catalog.pg_class relation join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace join pg_catalog.pg_attribute attribute on attribute.attrelid = relation.oid cross join (values ('UPDATE'), ('REFERENCES')) privilege(name) where namespace.nspname in ('public', 'kb_stage') and relation.relkind in ('r', 'p', 'v', 'm', 'f') and attribute.attnum > 0 and not attribute.attisdropped and has_column_privilege('leoclean_kb_stage_owner', relation.oid, attribute.attnum, privilege.name); if unexpected is not null then raise exception 'leoclean_kb_stage_owner unexpectedly has column-level DML: %', unexpected; end if; select pg_catalog.string_agg( pg_catalog.format('%I.%I.%I', namespace.nspname, relation.relname, attribute.attname), ', ' order by namespace.nspname, relation.relname, attribute.attnum ) into unexpected from pg_catalog.pg_class relation join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace join pg_catalog.pg_attribute attribute on attribute.attrelid = relation.oid where namespace.nspname in ('public', 'kb_stage') and relation.relkind in ('r', 'p', 'v', 'm', 'f') and attribute.attnum > 0 and not attribute.attisdropped and has_column_privilege('leoclean_kb_stage_owner', relation.oid, attribute.attnum, 'SELECT') and not ( (namespace.nspname = 'kb_stage' and relation.relname = 'kb_proposals') or ( namespace.nspname = 'public' and relation.relname = 'agents' and attribute.attname in ('id', 'handle') ) ); if unexpected is not null then raise exception 'leoclean_kb_stage_owner can SELECT unexpected columns: %', unexpected; end if; select pg_catalog.string_agg( pg_catalog.format('%I.%I:%s:%s', namespace.nspname, relation.relname, scoped_role.name, privilege.name), ', ' order by namespace.nspname, relation.relname, scoped_role.name, privilege.name ) into unexpected from pg_catalog.pg_class relation join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace cross join (values ('leoclean_kb_runtime'), ('leoclean_kb_stage_owner')) scoped_role(name) cross join (values ('USAGE'), ('SELECT'), ('UPDATE')) privilege(name) where namespace.nspname in ('public', 'kb_stage') and relation.relkind = 'S' and has_sequence_privilege(scoped_role.name, relation.oid, privilege.name); if unexpected is not null then raise exception 'a scoped Leo role unexpectedly has sequence privileges: %', unexpected; end if; if exists ( select 1 from pg_catalog.pg_attribute attribute where attribute.attrelid = 'kb_stage.kb_proposals'::pg_catalog.regclass and attribute.attname in ( 'proposal_type', 'status', 'proposed_by_handle', 'proposed_by_agent_id', 'channel', 'source_ref', 'rationale', 'payload' ) and not has_column_privilege( 'leoclean_kb_stage_owner', attribute.attrelid, attribute.attnum, 'INSERT' ) ) then raise exception 'leoclean_kb_stage_owner is missing a required INSERT column grant'; end if; select pg_catalog.string_agg( pg_catalog.format('%I.%I(%s)', namespace.nspname, function_row.proname, pg_catalog.pg_get_function_identity_arguments(function_row.oid)), ', ' ) into unexpected from pg_catalog.pg_proc function_row join pg_catalog.pg_namespace namespace on namespace.oid = function_row.pronamespace where namespace.nspname in ('public', 'kb_stage') and function_row.prosecdef and function_row.oid <> stage_function and has_function_privilege('leoclean_kb_runtime', function_row.oid, 'EXECUTE'); if unexpected is not null then raise exception 'leoclean_kb_runtime can execute unexpected SECURITY DEFINER functions: %', unexpected; end if; if not exists ( select 1 from pg_catalog.pg_proc function_row where function_row.oid = stage_function and function_row.prosecdef and function_row.proowner = owner_oid and function_row.proconfig = array['search_path=pg_catalog, pg_temp']::text[] ) then raise exception 'stage_leoclean_proposal owner/security/search_path contract is invalid'; end if; select pg_catalog.string_agg( pg_catalog.format( 'grantee=%s privilege=%s grantable=%s', acl.grantee, acl.privilege_type, acl.is_grantable ), ', ' ) into unexpected from pg_catalog.pg_proc function_row cross join lateral pg_catalog.aclexplode( coalesce( function_row.proacl, pg_catalog.acldefault('f', function_row.proowner) ) ) as acl where function_row.oid = stage_function and not ( acl.grantee in (runtime_oid, owner_oid) and acl.privilege_type = 'EXECUTE' and (acl.grantee = owner_oid or not acl.is_grantable) ); if unexpected is not null then raise exception 'stage_leoclean_proposal has unexpected ACL entries: %', unexpected; end if; if not has_function_privilege( 'leoclean_kb_runtime', 'kb_stage.stage_leoclean_proposal(text,text,text,text,jsonb)', 'EXECUTE' ) then raise exception 'leoclean_kb_runtime cannot execute stage_leoclean_proposal'; end if; end $verification$; commit; -- The legacy restore database is not an audit fallback for the scoped runtime. -- Strip direct ACLs from both scoped roles and fail if PUBLIC/group grants still -- make any teleo_restore relation reachable. \connect teleo_kb begin; select format('revoke all on schema %I from leoclean_kb_runtime, leoclean_kb_stage_owner', namespace.nspname) from pg_catalog.pg_namespace namespace where namespace.nspname = 'teleo_restore' \gexec select format('revoke all privileges on all tables in schema %I from leoclean_kb_runtime, leoclean_kb_stage_owner', namespace.nspname) from pg_catalog.pg_namespace namespace where namespace.nspname = 'teleo_restore' \gexec select format('revoke all privileges on all sequences in schema %I from leoclean_kb_runtime, leoclean_kb_stage_owner', namespace.nspname) from pg_catalog.pg_namespace namespace where namespace.nspname = 'teleo_restore' \gexec select format('revoke all privileges on all functions in schema %I from leoclean_kb_runtime, leoclean_kb_stage_owner', namespace.nspname) from pg_catalog.pg_namespace namespace where namespace.nspname = 'teleo_restore' \gexec select format('revoke all privileges on all procedures in schema %I from leoclean_kb_runtime, leoclean_kb_stage_owner', namespace.nspname) from pg_catalog.pg_namespace namespace where namespace.nspname = 'teleo_restore' \gexec select format( 'revoke all privileges (%s) on table %I.%I from %I', pg_catalog.string_agg(pg_catalog.quote_ident(attribute.attname), ', ' order by attribute.attnum), namespace.nspname, relation.relname, target.rolname ) from pg_catalog.pg_class relation join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace join pg_catalog.pg_attribute attribute on attribute.attrelid = relation.oid cross join ( values ('leoclean_kb_runtime'), ('leoclean_kb_stage_owner') ) as target(rolname) where namespace.nspname = 'teleo_restore' and relation.relkind in ('r', 'p', 'v', 'm', 'f') and attribute.attnum > 0 and not attribute.attisdropped group by namespace.nspname, relation.relname, target.rolname \gexec do $audit_verification$ declare unexpected text; scoped_role text; begin foreach scoped_role in array array['leoclean_kb_runtime', 'leoclean_kb_stage_owner'] loop if to_regnamespace('teleo_restore') is not null and (has_schema_privilege(scoped_role, 'teleo_restore', 'USAGE') or has_schema_privilege(scoped_role, 'teleo_restore', 'CREATE')) then raise exception '% unexpectedly has teleo_restore schema access', scoped_role; end if; select pg_catalog.string_agg( pg_catalog.format('%I.%I:%s', namespace.nspname, relation.relname, privilege.name), ', ' order by relation.relname, privilege.name ) into unexpected from pg_catalog.pg_class relation join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace cross join ( values ('SELECT'), ('INSERT'), ('UPDATE'), ('DELETE'), ('TRUNCATE'), ('REFERENCES'), ('TRIGGER') ) privilege(name) where namespace.nspname = 'teleo_restore' and relation.relkind in ('r', 'p', 'v', 'm', 'f') and has_table_privilege(scoped_role, relation.oid, privilege.name); if unexpected is not null then raise exception '% unexpectedly has teleo_restore table access: %', scoped_role, unexpected; end if; select pg_catalog.string_agg( pg_catalog.format('%I.%I.%I:%s', namespace.nspname, relation.relname, attribute.attname, privilege.name), ', ' order by relation.relname, attribute.attnum, privilege.name ) into unexpected from pg_catalog.pg_class relation join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace join pg_catalog.pg_attribute attribute on attribute.attrelid = relation.oid cross join (values ('SELECT'), ('INSERT'), ('UPDATE'), ('REFERENCES')) privilege(name) where namespace.nspname = 'teleo_restore' and relation.relkind in ('r', 'p', 'v', 'm', 'f') and attribute.attnum > 0 and not attribute.attisdropped and has_column_privilege(scoped_role, relation.oid, attribute.attnum, privilege.name); if unexpected is not null then raise exception '% unexpectedly has teleo_restore column access: %', scoped_role, unexpected; end if; select pg_catalog.string_agg( pg_catalog.format('%I.%I:%s', namespace.nspname, relation.relname, privilege.name), ', ' order by relation.relname, privilege.name ) into unexpected from pg_catalog.pg_class relation join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace cross join (values ('USAGE'), ('SELECT'), ('UPDATE')) privilege(name) where namespace.nspname = 'teleo_restore' and relation.relkind = 'S' and has_sequence_privilege(scoped_role, relation.oid, privilege.name); if unexpected is not null then raise exception '% unexpectedly has teleo_restore sequence access: %', scoped_role, unexpected; end if; end loop; end $audit_verification$; commit; \connect teleo_canonical select jsonb_build_object( 'role', rolname, 'superuser', rolsuper, 'create_db', rolcreatedb, 'create_role', rolcreaterole, 'inherit', rolinherit, 'replication', rolreplication, 'bypass_rls', rolbypassrls, 'has_role_memberships', exists ( select 1 from pg_catalog.pg_auth_members membership where membership.roleid = pg_catalog.pg_roles.oid or membership.member = pg_catalog.pg_roles.oid ), 'can_select_claims', has_table_privilege(rolname, 'public.claims', 'SELECT'), 'can_select_proposals', has_table_privilege(rolname, 'kb_stage.kb_proposals', 'SELECT'), 'can_insert_proposals_directly', has_table_privilege(rolname, 'kb_stage.kb_proposals', 'INSERT'), 'can_create_database_objects', has_database_privilege(rolname, 'teleo_canonical', 'CREATE'), 'can_create_temp_objects', has_database_privilege(rolname, 'teleo_canonical', 'TEMP'), 'can_stage_proposal', has_function_privilege( rolname, 'kb_stage.stage_leoclean_proposal(text,text,text,text,jsonb)', 'EXECUTE' ) )::text from pg_catalog.pg_roles where rolname = 'leoclean_kb_runtime';