PgBeam
PgBeam Docs
Policies

Recommend a least-privilege policy from recorded traffic

POST
/v1/projects/{project_id}/agents/{agent_id}/policy-recommendation

Derives the tightest policy that would still pass every statement this agent credential has legitimately run, using its recorded audit history over a lookback window (default 30 days). The candidate's table allowlist is the union of relations actually referenced, its statement-kind allow set is the observed set, it downgrades to read-only when no writes were seen, and its max_rows ceiling comes from an observed high-percentile row count. The candidate is proven safe by replaying it through the data plane's own policy engine against the same history: a good recommendation has replay.summary.newly_blocked == 0. This endpoint is advisory only. It reads the audit log, never connects to the upstream database, and never creates, updates, or mutates any policy or credential; the operator loads the candidate into the editor and saves it themselves.

Authorization

AuthorizationBearer <token>

JWT issued by Better Auth. Verified via JWKS.

In: header

Path Parameters

project_id*string

Unique project identifier (prefixed, e.g. prj_xxx).

Match^[a-zA-Z0-9_.-]+$
agent_id*string

Unique agent credential identifier (prefixed, e.g. agt_xxx).

Match^[a-zA-Z0-9_.-]+$

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Optional parameters for a least-privilege policy recommendation. Every field is optional; an empty body analyzes the last 30 days of the credential's audit history.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/projects/string/agents/string/policy-recommendation" \  -H "Content-Type: application/json" \  -d '{}'
{  "sufficient_history": true,  "message": "string",  "candidate": {    "name": "string",    "access_mode": "read_only",    "statement_rules": {      "allow": [        "string"      ],      "deny": [        "string"      ]    },    "table_allowlist": [      "string"    ],    "table_denylist": [      "string"    ],    "masking_rules": [      {        "table": "users",        "column": "email",        "kind": "redact"      }    ],    "budget_queries_per_hour": 0,    "budget_queries_per_day": 0,    "max_rows": 0,    "statement_timeout_ms": 0,    "row_filters": [      {        "table": "orders",        "predicate": "tenant_id = current_setting('pgbeam.tenant')"      }    ],    "write_mode": "normal",    "approval_mode": "off",    "approval_auto_max_rows": 0,    "approval_timeout_seconds": 300,    "migration_safety": "off",    "egress_bytes_per_day": 0,    "max_affected_rows": 0  },  "replay": {    "summary": {      "entries_scanned": 0,      "distinct_queries": 0,      "evaluated": 0,      "would_allow": 0,      "would_block": 0,      "would_mask": 0,      "would_row_filter": 0,      "newly_blocked": 0,      "newly_allowed": 0,      "skipped_unparseable": 0,      "truncated": true    },    "items": [      {        "query_hash": "string",        "sql": "string",        "statement_kind": "string",        "occurrences": 0,        "first_seen": "2019-08-24T14:15:22Z",        "last_seen": "2019-08-24T14:15:22Z",        "recorded_event": "string",        "recorded_rule": "string",        "change": "newly_blocked",        "result": {          "verdict": "allow",          "rule": "ok",          "reason": "string",          "hint": "string",          "masked_columns": [            {              "column": "email",              "kind": "redact"            }          ],          "row_filter_predicate": "tenant_id = current_setting('pgbeam.tenant')",          "rewritten_sql": "string",          "notes": [            "string"          ]        }      }    ]  },  "observed_queries": 0,  "observed_entries": 0,  "window_start": "2019-08-24T14:15:22Z",  "window_end": "2019-08-24T14:15:22Z",  "notes": [    "string"  ]}
{  "error": {    "code": "string",    "message": "string"  }}
{  "error": {    "code": "string",    "message": "string"  }}
{  "error": {    "code": "string",    "message": "string"  }}
{  "error": {    "code": "string",    "message": "string"  }}
{  "error": {    "code": "string",    "message": "string"  }}