Close two Phase 1 gate failures found on lin001

agent_ro could still create temporary tables: Postgres grants TEMP on every
database to PUBLIC, and revoking it from the role alone does not remove what
PUBLIC grants. Revoke it from PUBLIC too. postgres is a superuser and keeps
its temp tables, so the seed load is unaffected.

Nothing but the superuser could read schema fixture: 003_roles.sql grants only
on schema public, and the fixture schema is created afterwards. Grant read to
agent_ro and cube_rw. The grants live in 002_fixtures.sql because that file
opens with DROP SCHEMA fixture CASCADE, which would destroy grants held
anywhere else on every fixture reload.

Both re-verified on pg-ai: 11/11 privilege tests and 10/10 fixture access
tests pass, reads work for both roles, writes are rejected for both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Claude 2026-08-20 15:02:51 +10:00
parent 4826255672
commit 12439fa387
2 changed files with 18 additions and 0 deletions

View file

@ -285,6 +285,17 @@ VALUES
(now() - interval '6 days 10 hours', 'PS_STN_ALARM_BITMASK', 'WW-101', 'LEVEL_SIGNAL_FAULT', 1, 'RTN', NULL, NULL, 'LIT-101 signal restored'),
(now() - interval '3 days 5 hours', 'PS_STN_ALARM_BITMASK', 'STN-001', 'SETPOINT_REJECTED', 3, 'ACTIVE', 6500, 'mm', 'Setpoint write rejected - start duty level above the spill weir; previous value retained');
-- =============================================================================
-- Grants. These live HERE and not in 003_roles.sql on purpose: this file starts
-- with DROP SCHEMA fixture CASCADE, which destroys every grant on it. Grants
-- belong with the object they are granted on, so a fixture reload keeps them.
-- Read-only for both roles - nothing writes fixtures except this file.
-- =============================================================================
GRANT USAGE ON SCHEMA fixture TO agent_ro, cube_rw;
GRANT SELECT ON ALL TABLES IN SCHEMA fixture TO agent_ro, cube_rw;
ALTER DEFAULT PRIVILEGES IN SCHEMA fixture GRANT SELECT ON TABLES TO agent_ro, cube_rw;
-- =============================================================================
-- Sanity check after loading. Expect roughly: 30 days of 1-minute samples on
-- three tags, ~300 pump-downs, and alarms concentrated in the wet week.

View file

@ -36,6 +36,13 @@ ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO agent_ro;
-- No sequences, no functions, no temp tables, no schema creation.
REVOKE ALL ON ALL SEQUENCES IN SCHEMA public FROM agent_ro;
-- Revoking TEMPORARY from the role alone is not enough: Postgres grants TEMP on
-- every database to PUBLIC by default, and agent_ro inherits it. Phase 1 gate
-- caught agent_ro creating a temp table. Revoke it from PUBLIC as well.
-- Affects every non-superuser on plant (agent_ro, cube_rw). postgres is a
-- superuser and is unaffected, so the seed load still works. If Cube ever needs
-- temp tables, grant TEMPORARY back to cube_rw explicitly - never to PUBLIC.
REVOKE TEMPORARY ON DATABASE plant FROM PUBLIC;
REVOKE TEMPORARY ON DATABASE plant FROM agent_ro;
REVOKE CREATE ON SCHEMA public FROM agent_ro;