The safety contract

What every pgdba session promises before a single query runs.

Every connection pgdba makes — checks, doctor probes, migration preflight — runs under the same contract, applied before any analysis query:

  1. Read-only transaction (default_transaction_read_only=on) — the server rejects writes even if pgdba had a bug; nothing depends on pgdba being correct.
  2. Statement timeout (default 30s) — a pathological query cannot wedge the session; the run degrades gracefully instead.
  3. Connect timeout (default 10s) — a hung host cannot stall the run.
  4. Version gate — PG 13–17 verified from server_version_num; anything else refuses with a clear error rather than guessing.
  5. Managed-host detection (RDS and friends) — privilege-sensitive checks adapt or skip instead of erroring.

Why writes are opt-in, always

Advice-only is the default for every command that can write: --apply executes remediation you approve per action; migration writes only after preflight passes and you confirm; restore rehearsal is fenced away from production targets. The tool’s job is to make the safe path the default path — and to record, in an audit log, every action that did run.

On pooled targets (PgBouncer and friends), session SETs do not survive, so the contract is re-applied per statement with transaction-scoped SET LOCAL when pooled = true marks the profile.

Proving a run never wrote

pgdba check --journal appends one line per run to pgdba-audit.jsonl (state dir, else the current directory): run id, date, redacted target, executed check ids, statement count and classes, the safety values, and a writes count from classifying every captured statement (writes: INSERT/UPDATE/DELETE/MERGE/TRUNCATE/COPY/DDL/GRANT/REVOKE/ COMMENT/CALL/DO; anything unlisted counts as a write). The journal holds ids and counts only — never query text or secrets — keeps the newest 100 lines, and never changes the run’s exit code. pgdba audit show prints the trail; a run that applied actions records its applied count alongside, so applied runs are never misread as zero-write runs.

pgdba self-scan turns the lens on the tool itself: it scans every generated artifact (reports, journals, history, captured logs) for DSN/password residue and — with --dsn — runs a scratch check in a temp directory plus a read-only probe (a temp-table write the server must refuse; nothing user-visible persists). Exit 0 clean, 1 on residue or a failed probe, 3 on config/connect errors.