pg_policy
pg_policy : Agentic policy language for PostgreSQL with guardrails, guidance, and session-aware controls
Overview
| ID | Extension | Package | Version | Category | License | Language |
|---|---|---|---|---|---|---|
| 7440 | pg_policy
|
pg_policy
|
0.1.0 |
SEC
|
PostgreSQL
|
SQL
|
| Attribute | Has Binary | Has Library | Need Load | Has DDL | Relocatable | Trusted |
|---|---|---|---|---|---|---|
----d--
|
No
|
No
|
No
|
Yes
|
no
|
no
|
| Relationships | |
|---|---|
| Schemas | policy |
| See Also | pg_command_fw
pgextwlist
set_user
noset
block_copy_command
supautils
anon
pgaudit
|
PIGSTY patches the reserved upstream schema pg_policy to policy and quotes the reserved check function, so the packaged API is policy.check() rather than pg_policy.check(); pure SQL and PL/pgSQL, no preload.
Packages
| Type | Repo | Version | PG Major Compatibility | Package Pattern | Dependencies |
|---|---|---|---|---|---|
| EXT | PIGSTY
|
0.1.0 |
18
17
16
15
14
|
pg_policy |
- |
| RPM | PIGSTY
|
0.1.0 |
18
17
16
15
14
|
pg_policy_$v |
- |
| DEB | PIGSTY
|
0.1.0 |
18
17
16
15
14
|
postgresql-$v-pg-policy |
- |
| Linux / PG | PG18 | PG17 | PG16 | PG15 | PG14 |
|---|---|---|---|---|---|
el8.x86_64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
el8.aarch64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
el9.x86_64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
el9.aarch64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
el10.x86_64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
el10.aarch64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
d12.x86_64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
d12.aarch64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
d13.x86_64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
d13.aarch64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
u22.x86_64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
u22.aarch64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
u24.x86_64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
u24.aarch64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
u26.x86_64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
u26.aarch64
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
PIGSTY 0.1.0
|
Source
pig build pkg pg_policy; # build rpm/debInstall
Make sure PGDG and PIGSTY repo available:
pig repo add pgsql -u # add both repo and update cacheInstall this extension with pig:
pig install pg_policy; # install via package name, for the active PG version
pig install pg_policy -v 18; # install for PG 18
pig install pg_policy -v 17; # install for PG 17
pig install pg_policy -v 16; # install for PG 16
pig install pg_policy -v 15; # install for PG 15
pig install pg_policy -v 14; # install for PG 14Create this extension with:
CREATE EXTENSION pg_policy;Usage
Sources:
- pg_policy 0.1.0 on PGXN
- pg_policy 0.1.0 README
- Agent Policy Language reference
- pg_policy 0.1.0 security policy
- pg_policy 0.1.0 control file
- pg_policy 0.1.0 extension SQL
- Pigsty pg_policy package page
pg_policy 0.1.0 is an experimental SQL and PL/pgSQL policy evaluator for agent and tool actions. It stores Agent Policy Language rules, evaluates context and session history, records every decision, and returns obligations for a gateway to enforce. It complements PostgreSQL roles and row-level security; it does not intercept SQL or tool calls by itself.
Pigsty Schema Compatibility
Upstream 0.1.0 declares the reserved schema name pg_policy and defines an unquoted function named check. Pigsty packages patch the installed schema to policy, quote the reserved function name as policy."check"(), and fix function search paths. The upstream examples therefore cannot be copied verbatim into a Pigsty installation.
CREATE EXTENSION pg_policy;
SELECT policy.set_setting('enforcement_mode', 'log_only');The extension is not relocatable, requires PostgreSQL 14 or later, and does not require shared_preload_libraries or a PostgreSQL restart. Current Pigsty packages cover PostgreSQL 14–18.
Define and Evaluate a Guardrail
SELECT policy.upsert_policy('block_ddl', $apl$
forbid
principal agent "research_bot"
action tool "execute_sql"
when { context.statement_type in ["DROP", "TRUNCATE", "ALTER", "CREATE"] }
reason "Research agents may not run DDL"
$apl$);
SELECT policy.set_setting('enforcement_mode', 'enforce');
SELECT policy.evaluate(
'agent', 'research_bot',
'tool', 'execute_sql',
'*', '*',
'{"statement_type":"DROP"}'::jsonb,
NULL
);
SELECT policy."check"(
'research_bot',
'execute_sql',
'{"statement_type":"DROP"}'::jsonb
);policy.evaluate(...) returns JSON containing decision, allowed, matched_policies, obligations, reasons, and mode. The convenience wrapper policy."check"() returns only a boolean. policy.enforce() requests exception-on-deny behavior when the mode is enforce.
APL Surface
An APL document begins with one effect: permit, forbid, or guide. It can match principal, action, and resource types and identifiers. In 0.1.0, context conditions support only ==, in [...], and and. A temporal clause can count matching session events inside an interval when evaluation receives a session identifier.
forbid overrides matching permit rules. guide allows the action and can return advice, prefer_tool, or max_rows obligations. The caller—not the extension—must interpret and apply those obligations.
Sessions, Temporal Limits, and Audit
SELECT policy.open_session(
'sess-1',
'agent',
'research_bot'
);
SELECT policy.upsert_policy('export_budget', $apl$
forbid
principal agent "research_bot"
action tool "export_csv"
when temporal {
count(action == "export_csv") within interval '1 hour' >= 3
}
reason "Export budget exceeded"
$apl$);
SELECT policy.evaluate(
'agent', 'research_bot',
'tool', 'export_csv',
'*', '*',
'{}'::jsonb,
'sess-1'
);policy.open_session() creates or updates a session. Evaluations with a session identifier append an event and can satisfy temporal predicates. Every evaluation writes policy.decision_log; other important relations are policy.policies, policy.sessions, policy.events, and policy.settings.
Enforcement and Security Boundaries
- The default
enforcement_modeislog_onlyand the default decision ispermit. A matched deny becomes an allow with ashadow_denyobligation. - In
guidemode, a matched deny becomes an allow withwould_deny. Onlyenforcepreserves a deny and allowspolicy.enforce()to raise an error. - A gateway must call the evaluator before the protected action and hard-fail on deny. Calling
policy.evaluate(...)after executing a tool is only auditing. - Keep PostgreSQL
GRANTandREVOKE, row-level security, network controls, and least-privilege credentials as the authoritative data-plane controls. Superusers and roles withBYPASSRLScan bypass row-level controls. - The 0.1 line is explicitly an experimental MVP, not a hardened production security boundary. Shadow-test policies, restrict who can change
policy.settingsorpolicy.policies, and monitorpolicy.decision_logbefore switching toenforce.