Access Control

March 20, 2026 · View on GitHub

Who Can Do What

ActionRequired privilege
Install extensionSuperuser
Manage sync (add/remove tables, create/drop groups, start/stop workers)Superuser
Monitor sync (status(), groups(), tables(), worker_status(), metrics())Any user
Read config (get_config(), get_group_config())Any user
Change config (set_config(), set_group_config())Superuser
Query target DuckLake tablesSource table owner (auto-granted), or manually granted roles

Target Table Permissions

Local sync: add_table() automatically grants SELECT on the target DuckLake table to the owner of the source table. No INSERT/UPDATE/DELETE — the target is write-only via the CDC pipeline.

public.orders (owned by app_user)
  → add_table('public.orders')
  → public.orders_ducklake (SELECT granted to app_user)

Remote sync: No automatic grants. The source owner is on a different server. Grant access manually:

GRANT SELECT ON public.orders_ducklake TO analyst_role;

Additional grants: Use standard PostgreSQL GRANT to give more roles access:

GRANT SELECT ON public.orders_ducklake TO analyst_role;

-- Or for all future tables in a schema:
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO analyst_role;

Monitoring Access

Monitoring functions use SECURITY DEFINER so any user can call them without needing direct access to internal tables. Passwords in connection strings are redacted in output.

Internal metadata tables (sync_groups, table_mappings, global_config) are not directly accessible — use the monitoring functions instead.

Remote Sync Credentials

The remote conninfo user needs:

-- On the remote PostgreSQL instance:
CREATE ROLE replicator LOGIN REPLICATION PASSWORD '...';
GRANT SELECT ON public.orders TO replicator;

Connection strings are stored in duckpipe.sync_groups.conninfo. This table is only accessible to superusers — non-superusers cannot read it directly. The groups() monitoring function redacts passwords before returning conninfo to callers.