preflight: CheckTable/LookupTargetFacts misreport privilege-blocked targets
- Dominant language
- Go
- Stars
- 7
- Forks
- 1
- Avg merge
- 18h 2m
- Merged PRs (30d)
- 74
Description
`CheckTable` and `LookupTargetFacts` resolve the target with `to_regclass`, whose behavior when the connected role lacks schema `USAGE` produces two misleading outcomes instead of an actionable refusal:
- **Qualified name, no `USAGE` on the schema:** `to_regclass` raises `insufficient_privilege` (SQLSTATE 42501), which surfaces as a raw wrapped permission-denied error rather than a typed refusal naming the missing `GRANT`.
- **Unqualified name:** search_path resolution silently skips schemas the role cannot use, so `to_regclass` returns `NULL` and the check reports `ErrTableNotFound` for a table that exists — the operator is told the table is missing when the real problem is a missing `GRANT USAGE`.
The engine-role access check already handles this correctly: `gatherAccessFacts` in `pkg/preflight/privileges.go` catches SQLSTATE 42501 and routes both it and the `NULL`-resolution case through `unresolvedTargetCause`, which separates "does not exist" from "not visible to this role". `CheckTable` and `LookupTargetFacts` in `pkg/preflight/preflight.go` lack the same handling.
**Proposed fix:** mirror the `privileges.go` handling in both functions — catch SQLSTATE 42501 and route through `unresolvedTargetCause` (or an equivalent typed cause), so a privilege-blocked target refuses with the missing grant instead of a raw error or a false not-found. Integration coverage per the test methodology: a role without schema `USAGE`, exercising both the qualified and unqualified paths.
---
*This issue was drafted by Kiran's (@Kiran01bm) coding agent (Amp / Claude Opus 4.5) from a review finding on #60.*
Contributor guide
Research direction
Start in pkg/preflight/preflight.go at CheckTable and LookupTargetFacts, then compare their target-resolution handling with gatherAccessFacts and unresolvedTargetCause in pkg/preflight/privileges.go. Follow the existing integration test methodology with a role lacking schema USAGE, covering qualified and unqualified names. Done means both paths distinguish a missing grant from a nonexistent table and return the typed refusal.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, postgresql
- Domain
- databases, security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100