symfonic.memory.backends.postgres_staged_roles¶
postgres_staged_roles ¶
Opt-in PostgreSQL authority boundary between a staged turn writer and its publisher.
The claim fence trigger honours a transaction setting that any session may set, so by itself it is a trusted-host contract. This installer makes PostgreSQL the authority for one named, non-owner writer role:
memory_nodes: the writer may INSERT a row, and UPDATE a row, only while that row is pending and carries a selected claim, before and after the statement. It cannot release a row, cannot overwrite a published row and cannot DELETE, so DELETE+INSERT of a published row is refused as well.memory_operation_receipts: the writer may INSERT and UPDATEwritereceipts only. A FLUSH receipt, and so ACTIVE, is out of its reach.memory_invocation_staged_proofs(CORE-339): the writer and PUBLIC have no access; the publisher is granted SELECT and INSERT. A COMMITTED FLUSH receipt the writer forges while the boundary is down has no proof, so it never reads as ACTIVE after the boundary returns.memory_erase_jobs(CORE-199 S1), when present: SELECT only for both roles, so both pass the native erase fence and neither can write a job (D6); neither may hold anything onmemory_erase_receipts.- edges and vectors are read-only for the writer; it holds no TRUNCATE, REFERENCES or TRIGGER privilege, and the installer refuses a writer that could run DDL or assume another role.
Every other role, the publisher included, keeps unrestricted row access, so the
publisher is the only named role that can activate; any further role an
operator grants these tables can as well. ensure_schema never calls this
module: a default or staged journal without it behaves exactly as before.
Not covered: the writer can still set the claim setting and so change the
claim, id or scope of a pending claimed row (it stays pending and claimed);
it writes its own journal rows, and can spend an operation id as a write
receipt to block a FLUSH. None of these releases a row or commits a FLUSH
receipt. Views, SECURITY DEFINER functions or policies an operator adds over
these tables are outside the attestation, except foreign policies, which it
refuses.
Policy bodies are attested against a baseline the installer records, in the
same transaction, as each policy's comment: a server-side fingerprint of its
command, mode, roles and deparsed USING and WITH CHECK. Only the table owner
can alter a policy or its comment, so the writer can read the baseline but not
edit it. ALTER POLICY keeps the old comment and so mismatches; a dropped
and recreated policy has none. Both refuse, as does a deparse change after a
server upgrade, until install records the baseline again. The owner itself,
and any superuser, is trusted: it bypasses row security in any case.
install
async
¶
Install and attest the boundary in one transaction; run as the table owner.
Requires the staged journal schema (and so the claim fence) to exist. The roles must already exist; creating roles is a deployment decision.
Source code in src/symfonic/memory/backends/postgres_staged_roles.py
require_boundary
async
¶
Attest the installed boundary exactly; any drift refuses.
Source code in src/symfonic/memory/backends/postgres_staged_roles.py
statements ¶
The grants and policies, in order; names are validated, never quoted.
Source code in src/symfonic/memory/backends/postgres_staged_roles.py
uninstall
async
¶
Drop the policies and row security; table grants are left to the operator.