Skip to content

symfonic.memory.backends.postgres_staged_release

postgres_staged_release

Private PostgreSQL staged-release authority: the database owns the release.

Three roles, none of them chosen by this module. The schema owner runs :func:install_staged_release_schema as an explicit migration, never from request dispatch. Only the exact runtime login may stage and seal, through owner functions; it holds no privilege on any table, so it can neither read nor tamper with staged rows, and it cannot disable a trigger it does not own. Only the exact publisher login may call release_v1, which publishes a sealed manifest if and only if the caller names its exact (record, digest) set, in one transaction. Every key is (tenant_id, manifest_id[, record_id]): one tenant's manifest id never claims or collides with another's.

Authority is exact logins plus SECURITY DEFINER functions with a pinned search_path. No session GUC is consulted: any role can set one.

Limits, stated so they are not mistaken for guarantees: the port is opt-in and wired to nothing, including CORE-339's staging. It does not protect the runtime-owned memory_nodes/memory_pending_claims path, does not provision roles or credentials, and proves nothing about host final commit (CORE-341). The shared runtime names its tenant itself; tenant-derived authority needs per-tenant logins (postgres_staged_tenant_logins). Nothing here grants a direct read of published. A DBA or superuser retains power over all of these objects.

StagedReleaseRoles dataclass

StagedReleaseRoles(schema: str, runtime: str, publisher: str)

Where the port lives and which pre-provisioned roles it grants to.

install_staged_release_schema async

install_staged_release_schema(owner_conn: Any, roles: StagedReleaseRoles) -> None

Explicit schema-owner migration; refuses to reuse an existing schema.

Source code in src/symfonic/memory/backends/postgres_staged_release.py
async def install_staged_release_schema(owner_conn: Any, roles: StagedReleaseRoles) -> None:
    """Explicit schema-owner migration; refuses to reuse an existing schema."""
    rt, pub = roles.runtime, roles.publisher
    if await owner_conn.fetchval(_INSTALLER_CHECK, rt, pub) is not True:
        raise MemoryContractError(
            "staged release owner must be separate from runtime and publisher")
    ddl = _DDL.format(s=roles.schema, rt=rt, pub=pub, pin=_PINNED)
    async with owner_conn.transaction():
        await owner_conn.execute(
            "SELECT pg_advisory_xact_lock(hashtext('symfonic_staged_release'), "
            "hashtext($1))", roles.schema,
        )
        await owner_conn.execute(ddl)
        safe = await owner_conn.fetchval(
            _POST_DDL_CHECK, roles.schema, rt, pub,
            sorted([f"release_v1:{pub}", f"seal_v1:{rt}", f"stage_v1:{rt}"]),
            sorted([f"{pub}:USAGE", f"{rt}:USAGE"]),
        )
        if safe is not True:  # raising here rolls the whole schema back
            raise MemoryContractError("staged release install left unsafe effective access")

no_privileged_reach

no_privileged_reach(who: str, ns: str) -> str

SQL predicate: no role who reaches (itself, inherited, or by SET ROLE) carries a cluster attribute (REPLICATION creates WAL slots), is predefined (pg_read_all_data/pg_write_all_data bypass grants), or holds any effective privilege on a relation in namespace ns.

Source code in src/symfonic/memory/backends/postgres_staged_release.py
def no_privileged_reach(who: str, ns: str) -> str:
    """SQL predicate: no role ``who`` reaches (itself, inherited, or by SET ROLE)
    carries a cluster attribute (REPLICATION creates WAL slots), is predefined
    (``pg_read_all_data``/``pg_write_all_data`` bypass grants), or holds any
    effective privilege on a relation in namespace ``ns``."""
    return f"""NOT EXISTS (SELECT 1 FROM pg_roles a WHERE pg_has_role({who}, a.oid, 'MEMBER')
  AND (a.rolsuper OR a.rolreplication OR a.rolbypassrls OR a.rolcreaterole
       OR a.rolcreatedb OR starts_with(a.rolname::text, 'pg_') OR EXISTS (
    SELECT 1 FROM pg_class c, unnest(ARRAY['SELECT', 'INSERT', 'UPDATE', 'DELETE',
                                          'TRUNCATE', 'REFERENCES', 'TRIGGER']) p
     WHERE c.relnamespace = {ns} AND c.relkind IN ('r', 'p', 'v', 'm')
       AND has_table_privilege(a.oid, c.oid, p))))"""

require_runtime_authority async

require_runtime_authority(conn: Any, roles: StagedReleaseRoles) -> None

Refuse before staging unless conn is exactly the restricted runtime.

Source code in src/symfonic/memory/backends/postgres_staged_release.py
async def require_runtime_authority(conn: Any, roles: StagedReleaseRoles) -> None:
    """Refuse before staging unless ``conn`` is exactly the restricted runtime."""
    # Without USAGE, resolving schema objects errors instead of refusing.
    usable = await conn.fetchval(
        "SELECT has_schema_privilege(current_user, to_regnamespace($1::text), 'USAGE')",
        '"' + roles.schema + '"',
    )
    safe = usable is True and await conn.fetchval(
        _RUNTIME_CHECK, roles.schema, roles.runtime, roles.publisher, _PINNED,
        sorted(V1_DEFINERS), sorted(V1_DEFINERS + V2_DEFINERS), _TRIGGERS,
    )
    if safe is not True:
        raise MemoryContractError("staged release requires the restricted runtime role")