Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / db/migrations/0065_revert_audit_logs_rls.sql |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | db/migrations/0065_revert_audit_logs_rls.sql |
| Original SHA-256 | 60e3dfc5df72340d8969b47f9bf36a59ed9f1beed672a183189fc3f95f937799 |
| Git blob SHA | 93c5ba88daabcf00074f88682acff6a501472bca |
| Reading-copy SHA-256 | 60e3dfc5df72340d8969b47f9bf36a59ed9f1beed672a183189fc3f95f937799 |
Every recorded occurrence
These 2 records contain identical original source bytes. Their paths and revisions remain part of the archive.
| Original record | Branch or archive | Revision / identifier | Original location |
|---|---|---|---|
| Janady13/missionmatch / db/migrations/0065_revert_audit_logs_rls.sql | feature/opportunity-to-outcome | 720d47fae476b0d38477ae4401697d372b1ea2bc | Open original |
| Janady13/missionmatch / db/migrations/0065_revert_audit_logs_rls.sql | feature/aioe-upgrade | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 | Open original |
Recovered source transcript
Download complete source text ↓32 lines · 2.1 KB
-- +goose Up
-- Reverts the audit_logs row level security added in 0064. It broke authentication.
--
-- What went wrong: Postgres applies a SELECT policy to RETURNING. The audit insert uses RETURNING, and a
-- platform event such as a login is written with organization_id NULL, before any tenant is known. The
-- policy compared organization_id to the request GUC, and NULL = anything is NULL rather than true, so
-- the row was inserted and then filtered out of its own RETURNING clause. The scan found no row and the
-- login path panicked on the nil dereference. Every login on the platform returned 500.
--
-- The finding that prompted it is real: audit_logs is tenant scoped, the app role holds SELECT, and it is
-- the largest cross tenant surface in the schema protected only by the convention that every query
-- remembers an organization predicate. But it cannot be closed with a naive policy, because this table
-- deliberately holds two different KINDS of row:
--
-- * tenant events, with an organization_id, which must be readable only by that tenant, and
-- * platform events, with organization_id NULL (a failed login, a lockout, a session rejection), which
-- belong to no tenant and must remain writable and readable before any tenant context exists.
--
-- A correct policy has to express both, and it has to be written against a read path that does not depend
-- on RETURNING seeing rows the policy hides. That is a considered change with its own verification, not a
-- line in a batch migration, so the table returns to its previous posture and the finding stays open and
-- documented rather than half fixed in a way that takes the product down.
DROP POLICY IF EXISTS audit_logs_tenant_read ON audit_logs;
DROP POLICY IF EXISTS audit_logs_insert_any ON audit_logs;
ALTER TABLE audit_logs NO FORCE ROW LEVEL SECURITY;
ALTER TABLE audit_logs DISABLE ROW LEVEL SECURITY;
-- +goose Down
-- Deliberately empty. Re enabling the policy is what broke login; a down migration must not restore a
-- known outage. The forward fix, when it is written, gets its own migration.
SELECT 1;