[E00-S03-T02] pg/Kysely imports isolated to database-postgres #391
No Reviewers
Labels
Clear labels
agent/analyst-drafted
agent/analyst-drafted
needs/human-decision
needs/human-decision
needs/security-review
needs/security-review
tier/t0
tier/t1
tier/t2
tier/t3
kind
bug
kind
bug
kind
epic
kind
epic
kind
initiative
EPPP programme initiative
kind
story
kind
story
kind
task
EPPP engineering card/task decomposed from a story
kind
toil
kind
toil
loop
1
loop
1
loop
2
loop
2
loop
3
loop
3
risk
agent-full
risk
agent-full
risk
human-gated
risk
human-gated
risk
human-only
risk
human-only
size
l
size
l
size
m
size
m
size
s
size
s
status
blocked
status
blocked
status
done
Workflow: Done
status
in-progress
status
in-progress
status
proposed
status
proposed
status
ready
status
ready
status
review
status
review
stream
checkout
stream
checkout
stream
onboarding
stream
onboarding
stream
platform
stream
platform
trivial — implementer only, auto-merge
standard — implementer + reviewer + tester
complex — security if triggered, human merge
critical — full chain + security, human merge
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: Fabrika/PersonalBlog#391
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What changed
Implements [E00-S03-T02] pg/Kysely imports isolated to database-postgres (#177): the PostgreSQL driver (
pg) and Kysely now live only in the newdatabase-postgrespackage, and the isolation is locked in by a static scan with mutation probes and enforced in CI.packages/database-postgres— new driver-owner package (@personal-blog/database-postgres): the single workspace package allowed to import the PostgreSQL driver. It declares the architecture doc's golden tuple (Technology-Stack §5.2 / §7) as exact dependencies —pg@8.22.0andkysely@0.29.4(@types/pg@8.21.0for types — no8.22.xof@types/pgis published, so8.21.0, the closest matching release for the preceding pg minor, is pinned) — and itssrc/index.tsimports and re-exports the driver pieces (Pool,Kysely,PostgresDialect), so the isolation is real — the driver is reachable only from this boundary — not a placeholder. Rollback: remove the package and revertpnpm-lock.yaml.pnpm-lock.yaml— importer + resolved driver tree:packages/database-postgresimporter plus the lockedpg/kysely/@types/pgdependency graph (generated by pnpm 11.23.0;pnpm install --frozen-lockfilepasses). The resolved transitive pg tree (pg-connection-string 2.14.0, pg-pool 3.14.0, pg-protocol 1.16.0, pg-types 2.2.0, pgpass 1.0.5, pg-cloudflare 1.4.0) is unchanged between the old and new driver pins.tests/database-postgres-imports.test.mjs— new suite locking in both acceptance criteria: a string/comment-aware static scan of every workspace package source proves that everypg/kyselyimport specifier (static import/export-from, dynamic import, require — incl. subpaths likepg/…,kysely/…) resolves to a file insidepackages/database-postgres; the owner manifest pins the driver and no other package declares it. Mutation probes prove non-vacuousness: injectingimport { Pool } from 'pg';intoapps/server/src/index.tsin a temp copy of the committed tree fails the scan, naming the file and the driver; a clean copy passes (probe sanity). Unit probes cover the specifier matcher and comment stripping.workspace-layout,workspace-config,strict-tsconfigandtypescript-pinnow includepackages/database-postgres(layout ↔ lockfile parity, strict-base compile, pinned-TS resolution)..gitea/workflows/ci.yml— newdatabase-postgres-importsjob runsnode --test tests/database-postgres-imports.test.mjson every PR, so the isolation criterion gates merges. (Note: this touches the CI workflow — pipeline tripwire, additive job, same action majors, nosecrets:context, no untrusted interpolation; matches the merged precedent #390.)docs/development/non-container.md— workspace package table and build expectations updated for the new package.Review fix (finding #1 — golden-tuple pin alignment)
The previous head pinned
pg@8.23.0/kysely@0.29.5/@types/pg@8.23.1; the architecture doc's golden tuple (Technology-Stack §5.2 runtime stack and §7 golden compatibility tuple) pinspg@8.22.0and Kysely@0.29.4. This head correctspackages/database-postgres/package.json, regeneratespnpm-lock.yaml(pnpm 11.23.0), and updates the exact-pin assertions intests/database-postgres-imports.test.mjsto the documented versions.@types/pghas no published8.22.x;8.21.0(types for the immediately preceding pg minor) is the closest matching release.Explicitly out of scope per the brief, not touched: PostgreSQL 18.6 container (E00-S03-T01), migration ledger (E00-S03-T03), advisory lock (E00-S03-T04).
Criterion → test table
pg/Kysely imports are isolated todatabase-postgrestests/database-postgres-imports.test.mjs— "packages/database-postgres exists, is the driver owner, and its source imports the driver" (manifest pinspg@8.22.0/kysely@0.29.4/@types/pg@8.21.0exactly;src/index.tsimports both); "pg/Kysely imports are isolated to database-postgres in the real workspace" (scan of every workspace package source finds driver imports only underpackages/database-postgres, and the owner really imports both drivers — non-vacuous); "comment stripping ignores commented-out driver imports (unit probe)"tests/database-postgres-imports.test.mjs— "no other package declares the database driver in its manifest" (only the owner's manifest listspg/kysely); "the isolation scan catches a driver import injected into another package (mutation probe)" (injectimport { Pool } from 'pg';intoapps/server/src/index.tsin a temp tree copy → scan fails naming the file and driver); "a copy of the committed tree without misplaced driver imports passes the scan (probe sanity)"; "the specifier matcher flags pg/kysely imports and ignores other packages (unit probe)"tests/database-postgres-imports.test.mjs— "the isolation criterion is enforced in CI" (asserts the root test glob covers the suite and.gitea/workflows/ci.ymlruns it);.gitea/workflows/ci.yml—database-postgres-importsjob runsnode --test tests/database-postgres-imports.test.mjson every PRTest plan executed
node --test tests/database-postgres-imports.test.mjs→ pass.node --test "tests/**/*.test.mjs", Node 24.19.0 + pnpm 11.23.0, frozen install) → pass, zero failures.pnpm install --frozen-lockfileon the corrected lockfile → passes ("Lockfile is up to date");pnpm build/pnpm typecheckover the 4-package workspace → exit 0.Risks / notes
pg/kysely/@types/pgare pinned to exact versions matching the documented golden tuple (repo policy, same astypescript@6.0.3); the lockfile carries the full resolved driver tree so--frozen-lockfilestays reproducible.pgoptional dependencypg-cloudflareinstalls on standard linux/x64 CI runners (no platform gate); the frozen-install "exact tree" assertion counts it in both lockfile and virtual store.Pool,Kysely,PostgresDialect) are the surface later stories (migration ledger T03, advisory lock T04) build the adapter on; until then nothing else in the workspace imports the driver.Refs #177