From b8187039a783d3c37cfdf1bc26a5d3d4e2a3790c Mon Sep 17 00:00:00 2001 From: tianzhou Date: Wed, 24 Jun 2026 20:53:06 -0700 Subject: [PATCH 1/4] docs(config): colocate [[agents]] with users/groups in example config Move the Agents section to sit alongside the other principals (Users, Groups) before IAM Rules, so the file reads define-principals then grant-access. Relocate the pure-agent's [[iam]] example into the IAM section and document the agent: member prefix there. Co-Authored-By: Claude Opus 4.8 (1M context) --- pgconsole.example.toml | 67 +++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/pgconsole.example.toml b/pgconsole.example.toml index 9aa40c6..1b1ab12 100644 --- a/pgconsole.example.toml +++ b/pgconsole.example.toml @@ -188,33 +188,6 @@ labels = ["staging"] # name = "Database Administrators" # members = ["admin"] -# ============================================================================= -# IAM Rules (optional - requires auth to be enabled) -# ============================================================================= -# Controls what users can do on each connection -# Permissions: read (SELECT), write (INSERT/UPDATE/DELETE), ddl (CREATE/ALTER/DROP), -# admin (full access), explain (EXPLAIN), execute (CALL), export (CSV export) -# Use "*" to grant all permissions at once -# Members: "user:username", "group:groupid", or "*" for all users -# Connection: specific connection id or "*" for all connections -# Multiple matching rules are unioned (user gets all permissions from all matching rules) -# Default deny: no matching rule = no access (connection hidden from user) -# -# [[iam]] -# connection = "*" -# permissions = ["read"] -# members = ["*"] -# -# [[iam]] -# connection = "local" -# permissions = ["*"] -# members = ["user:admin", "group:dba"] -# -# [[iam]] -# connection = "staging" -# permissions = ["read", "write"] -# members = ["group:dev-team"] - # ============================================================================= # Agents (optional) - non-human principals for the MCP server # ============================================================================= @@ -233,17 +206,12 @@ labels = ["staging"] # Fields: id (required), token (required), name (optional, defaults to id), # on_behalf_of (user email), permissions (delegated only), connections (delegated only) # -# # Pure agent - authorize it with an [[iam]] rule using member "agent:" +# # Pure agent - authorize it with an [[iam]] rule using member "agent:" (see below) # [[agents]] # id = "ci-bot" # name = "CI Pipeline" # token = "generate-a-long-random-secret" # openssl rand -hex 32 # -# [[iam]] -# connection = "staging" -# permissions = ["read", "ddl"] -# members = ["agent:ci-bot"] -# # # Delegated agent - acts as alice, capped to read-only on the local connection # [[agents]] # id = "alice-assistant" @@ -252,3 +220,36 @@ labels = ["staging"] # on_behalf_of = "alice@example.com" # must match a [[users]] email # permissions = ["read"] # cap: intersected with alice's IAM grant # connections = ["local"] # cap: connection IDs the agent may touch + +# ============================================================================= +# IAM Rules (optional - requires auth to be enabled) +# ============================================================================= +# Controls what users can do on each connection +# Permissions: read (SELECT), write (INSERT/UPDATE/DELETE), ddl (CREATE/ALTER/DROP), +# admin (full access), explain (EXPLAIN), execute (CALL), export (CSV export) +# Use "*" to grant all permissions at once +# Members: "user:username", "group:groupid", "agent:agentid", or "*" for all users +# Connection: specific connection id or "*" for all connections +# Multiple matching rules are unioned (user gets all permissions from all matching rules) +# Default deny: no matching rule = no access (connection hidden from user) +# +# [[iam]] +# connection = "*" +# permissions = ["read"] +# members = ["*"] +# +# [[iam]] +# connection = "local" +# permissions = ["*"] +# members = ["user:admin", "group:dba"] +# +# [[iam]] +# connection = "staging" +# permissions = ["read", "write"] +# members = ["group:dev-team"] +# +# # Authorize a pure agent (see the Agents section above) +# [[iam]] +# connection = "staging" +# permissions = ["read", "ddl"] +# members = ["agent:ci-bot"] From 92022ce90c90942dec4a71008437226072437b6c Mon Sep 17 00:00:00 2001 From: tianzhou Date: Wed, 24 Jun 2026 21:50:35 -0700 Subject: [PATCH 2/4] docs(config): correct IAM member examples to use emails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address PR review: user:/group: members are matched against the user's email, so bare usernames never match. Use full emails (user:admin@example.com, group members admin@example.com / developer@example.com) and clarify that "*" applies to users only — pure agents match only explicit "agent:" rules. Co-Authored-By: Claude Opus 4.8 (1M context) --- pgconsole.example.toml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pgconsole.example.toml b/pgconsole.example.toml index 1b1ab12..ba46020 100644 --- a/pgconsole.example.toml +++ b/pgconsole.example.toml @@ -181,12 +181,12 @@ labels = ["staging"] # [[groups]] # id = "dev-team" # name = "Development Team" -# members = ["developer", "alice@example.com"] +# members = ["developer@example.com", "alice@example.com"] # # [[groups]] # id = "dba" # name = "Database Administrators" -# members = ["admin"] +# members = ["admin@example.com"] # ============================================================================= # Agents (optional) - non-human principals for the MCP server @@ -228,7 +228,8 @@ labels = ["staging"] # Permissions: read (SELECT), write (INSERT/UPDATE/DELETE), ddl (CREATE/ALTER/DROP), # admin (full access), explain (EXPLAIN), execute (CALL), export (CSV export) # Use "*" to grant all permissions at once -# Members: "user:username", "group:groupid", "agent:agentid", or "*" for all users +# Members: "user:", "group:", "agent:", or "*" (all users; agents +# match only explicit "agent:" rules, never "*"/"user:"/"group:") # Connection: specific connection id or "*" for all connections # Multiple matching rules are unioned (user gets all permissions from all matching rules) # Default deny: no matching rule = no access (connection hidden from user) @@ -241,7 +242,7 @@ labels = ["staging"] # [[iam]] # connection = "local" # permissions = ["*"] -# members = ["user:admin", "group:dba"] +# members = ["user:admin@example.com", "group:dba"] # # [[iam]] # connection = "staging" From d7cd29577e2d749183d6ba2617e19ced0c4e9992 Mon Sep 17 00:00:00 2001 From: tianzhou Date: Wed, 24 Jun 2026 21:56:42 -0700 Subject: [PATCH 3/4] docs(config): scope agent IAM caveat to pure agents Address PR review: delegated agents (on_behalf_of) inherit their user's IAM grant and so do match "*"/"user:"/"group:" rules via that user. Only pure agents are limited to explicit "agent:" rules. Co-Authored-By: Claude Opus 4.8 (1M context) --- pgconsole.example.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pgconsole.example.toml b/pgconsole.example.toml index ba46020..8b19b5b 100644 --- a/pgconsole.example.toml +++ b/pgconsole.example.toml @@ -228,8 +228,9 @@ labels = ["staging"] # Permissions: read (SELECT), write (INSERT/UPDATE/DELETE), ddl (CREATE/ALTER/DROP), # admin (full access), explain (EXPLAIN), execute (CALL), export (CSV export) # Use "*" to grant all permissions at once -# Members: "user:", "group:", "agent:", or "*" (all users; agents -# match only explicit "agent:" rules, never "*"/"user:"/"group:") +# Members: "user:", "group:", "agent:", or "*" (all users; a pure +# agent matches only explicit "agent:" rules, never "*"/"user:"/"group:", +# while a delegated agent inherits its user's matches) # Connection: specific connection id or "*" for all connections # Multiple matching rules are unioned (user gets all permissions from all matching rules) # Default deny: no matching rule = no access (connection hidden from user) From 1e325348c8b92a462df0ed5746bd901774cca6c3 Mon Sep 17 00:00:00 2001 From: tianzhou Date: Thu, 25 Jun 2026 01:08:49 -0700 Subject: [PATCH 4/4] docs(config): clarify "*" applies to human users only Address PR review: label "*" as all human users to avoid implying it matches agents (pure agents must be granted explicitly via agent:). Co-Authored-By: Claude Opus 4.8 (1M context) --- pgconsole.example.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pgconsole.example.toml b/pgconsole.example.toml index 8b19b5b..0fc70a4 100644 --- a/pgconsole.example.toml +++ b/pgconsole.example.toml @@ -228,7 +228,7 @@ labels = ["staging"] # Permissions: read (SELECT), write (INSERT/UPDATE/DELETE), ddl (CREATE/ALTER/DROP), # admin (full access), explain (EXPLAIN), execute (CALL), export (CSV export) # Use "*" to grant all permissions at once -# Members: "user:", "group:", "agent:", or "*" (all users; a pure +# Members: "user:", "group:", "agent:", or "*" (all human users; a pure # agent matches only explicit "agent:" rules, never "*"/"user:"/"group:", # while a delegated agent inherits its user's matches) # Connection: specific connection id or "*" for all connections