Skip to content

Grant pg_read_all_stats to the Claude read-only DB user#5122

Open
habdelra wants to merge 1 commit into
mainfrom
grant-claude-readonly-pg-read-all-stats
Open

Grant pg_read_all_stats to the Claude read-only DB user#5122
habdelra wants to merge 1 commit into
mainfrom
grant-claude-readonly-pg-read-all-stats

Conversation

@habdelra
Copy link
Copy Markdown
Contributor

@habdelra habdelra commented Jun 5, 2026

What

Adds a Postgres migration that grants the built-in pg_read_all_stats role to the dedicated read-only DB user that Claude uses for triage.

-- up
GRANT pg_read_all_stats TO "<claude-readonly-user>";
-- down
REVOKE pg_read_all_stats FROM "<claude-readonly-user>";

The grant target is read from CLAUDE_DB_USER — the same source the existing claude-readonly migration used to create the role — so the GRANT always lands on the role that actually exists in the deployed environment. The user name is validated against a conservative Postgres-identifier regex before it's interpolated into the raw GRANT / REVOKE (mirroring the existing migration), so it can't become a SQL-injection vector.

Why

The read-only DB user is a member of readonly_role and can already query application tables. But for pg_stat_activity it can only see its own session in full — for every other backend the query and state columns render as <insufficient privilege>. That masking hid the SQL a worker backend was actually running while a from-scratch indexing job hung in its invalidation-discovery phase, so we couldn't tell what was stuck.

pg_read_all_stats is exactly the fix: it's a read-only statistics-visibility role. It lifts the masking on pg_stat_activity and the other system statistics views without conferring any data-write or table-read privilege beyond what the user already has. With it, stuck/slow queries can be attributed to a specific backend and statement during an indexing incident.

Scope / safety

  • Gated to staging and production only, where the read-only role exists. The migration no-ops in dev (the role isn't provisioned there), matching the existing claude-readonly migration's env gate.
  • GRANT is idempotent, so a re-run is a no-op.
  • No write or table-read escalation — pg_read_all_stats only widens visibility into the statistics views.
  • The migration runs automatically on deploy via the pg-migration task; it has not been run against any deployed database from this PR.

Schema snapshot

pnpm make-schema was run. Because this is a GRANT to a built-in role and adds no table DDL, the generated schema snapshot content is byte-identical — the only change is the snapshot file being renamed to track the new latest-migration timestamp (the repo keeps one snapshot named after the most recent migration).

🤖 Generated with Claude Code

Lets the read-only DB role see the query and state columns of every other
backend in pg_stat_activity (and the other system statistics views) instead
of <insufficient privilege>, so stuck/slow queries can be diagnosed during
indexing incidents.

pg_read_all_stats is a read-only stats-visibility grant only; it confers no
data-write or table-read privilege. The migration is gated to staging and
production, where the role exists, and no-ops elsewhere.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 5, 2026

Preview deployments

Host Test Results

    1 files      1 suites   1h 53m 23s ⏱️
2 936 tests 2 921 ✅ 15 💤 0 ❌
2 955 runs  2 940 ✅ 15 💤 0 ❌

Results for commit fd9a40c.

Realm Server Test Results

    1 files      1 suites   12m 33s ⏱️
1 559 tests 1 558 ✅ 1 💤 0 ❌
1 650 runs  1 649 ✅ 1 💤 0 ❌

Results for commit fd9a40c.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an operationally-scoped Postgres migration to grant the built-in pg_read_all_stats role to the dedicated Claude triage read-only DB user (gated to staging/production), enabling full visibility into pg_stat_activity during incident debugging without expanding data access beyond existing read-only permissions.

Changes:

  • Add a new Postgres migration that GRANTs/REVOKEs pg_read_all_stats for the role named by CLAUDE_DB_USER, with conservative identifier validation and env gating.
  • Update the generated host schema snapshot to the latest migration timestamp (DDL unchanged).

Reviewed changes

Copilot reviewed 1 out of 2 changed files in this pull request and generated no comments.

File Description
packages/postgres/migrations/1780620712404_grant-claude-readonly-pg-read-all-stats.js New migration granting pg_read_all_stats to the Claude read-only DB role in staging/production, with username validation.
packages/host/config/schema/1780620712404_schema.sql Regenerated/renamed schema snapshot to reflect latest migration timestamp (no schema DDL changes).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@habdelra habdelra requested a review from a team June 5, 2026 01:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants