internal/postgres
May 15, 2026 · View on GitHub
Mirror notice. Verbatim sync with AGENTS.md. Update both together — divergence = bug.
Postgres adapter: SQLC over pgx, plus the session-pin store impl. Read root CLAUDE.md first.
Layout
repository.go— generic repo for auth + installation domain.converters.go— adapter-boundary mapping betweenpgtype/uuidand the domain types in../auth/../router/sessionpin.- Sibling files implement narrower repos.
Hard rules
- Adapter depends only on the inner ring + may import
internal/sqlc. Adapters never import each other —internal/postgresdoesn't knowinternal/api/adminetc. - Never write raw SQL outside
db/queries/or callpgx.Pooldirectly from anywhere except this package. SQLC is the only data mapper. - Domain types must not leak
pgtype/uuidconcerns.auth.Installation,auth.APIKey,sessionpin.Pinare all converted at the adapter boundary inconverters.go.
Adding a column or query
- Migration first. Add
db/migrations/NNNN_<name>.up.sql+.down.sqlin sequential numbering. Wrap inBEGIN/COMMIT. Down migration must be a precise rollback — noIF EXISTSguards. See../../db/CLAUDE.md. - Add the query to the appropriate
db/queries/<table>.sql. Use named params with type casts (@param::varchar). Usesqlc.embed(t)for JOINs. - Run
make generateto regenerateinternal/sqlc/. Commit the generated code alongside changes. - Update
repository.go(andconverters.goif a new column needs domain mapping).
SQLC conventions
- Always named params (
@param::varchar), never numbered ($1). - Always include type casts so SQLC inference is unambiguous.
- Query names use consistent prefixes:
Insert*,Upsert*,Get*,Update*,Delete*. - Every query gets an explanatory comment (SQLC turns it into godoc on the generated function).
- No-rows single-row queries return an error — check
errors.Is(err, sql.ErrNoRows).
Never edit generated files
internal/sqlc/ is generated. The "DO NOT EDIT" header is load-bearing. Regenerate with make generate.