Review: Tenant-scoped Drizzle query helper (v3)

review-1091-2026-04-25-v3 Review

review approved

Verdict: APPROVED

Re-review v3 of review-1091-2026-04-25-v2. v2 verdict was NEEDS_REFINEMENT with one outstanding [SCOPE] recommendation: missing backing arch note for arch:scoped-db. That recommendation is now resolved.

Changes Since v2 Review

  • [x] [SCOPE] RESOLVED — arch-scoped-db-westside-admin note created (note id 1639, note_type architecture, project westside-admin, tagged architecture,active). Verified directly via get_note(slug="arch-scoped-db-westside-admin"). The note describes scopedDb as a sub-component nested inside arch-dataflow-westside-admin, which matches v2's recommended option (a).
  • [x] Components table maps arch:scoped-db to two real components: scopedDb (tenant-scoped query builder, lives in src/lib/server/scopedDb.ts) and systemDb (unscoped builder for system tables). Plus internal db and tenant.ts rows. The label is no longer phantom.
  • [x] Implementation Tickets section in the arch note explicitly lists forgejo_admin/westside-admin#1 (board #1089) and forgejo_admin/westside-admin#3 (board #1091) — both helper-layer tickets share this arch note as agreed in v2.
  • [x] Issue body unchanged from v2 (caller confirmed). Related section points to arch-dataflow-westside-admin; that's still correct since the new arch-scoped-db-westside-admin nests under it. Optional polish: the issue could also reference the new sub-component note, but this is cosmetic — both arch notes are reachable from the project page and from each other.

Template Completeness

  • [x] Type — Feature
  • [x] Lineage — explicit issue numbers (#1, #6)
  • [x] Repo — forgejo_admin/westside-admin
  • [x] User Story — story-westside-admin-admin-row-crud
  • [x] Context — clear motivation, swap-point design, lint enforcement rationale
  • [x] File Targets — Create + Modify + Do NOT modify lists present
  • [x] Acceptance Criteria — 6 ACs, behavioral + type-system + lint + comment
  • [x] Test Expectations — unit + integration described
  • [x] Constraints — no JWT-derived tenant_id (v1), Drizzle typed builders only
  • [x] Checklist — PR / ACs / lint verification
  • [x] Related — project page + arch note + DEPENDS ON line

Traceability

  • [x] story:admin-row-crud label — present
  • [x] story note verified — story-westside-admin-admin-row-crud in project-westside-admin user-stories section (verified in v2, unchanged)
  • [x] arch:scoped-db label — present
  • [x] arch note verified — arch-scoped-db-westside-admin exists in pal-e-docs (note_type architecture, components table maps the label to scopedDb/systemDb)
  • [x] type:feature label — present
  • [x] Forgejo issue — https://forgejo.tail5b443a.ts.net/forgejo_admin/westside-admin/issues/3 — open

File Targets

Repo state unchanged from v2 — forgejo_admin/westside-admin still contains only README.md on main. All file targets sit downstream of #6 (scaffolding) and #1 (Drizzle setup). Paths are well-formed and match the helper-layer design. Dev agent must re-verify after #6 + #1 land.
  • [~] src/lib/server/tenant.ts (Create) — plausible after #1
  • [~] src/lib/server/scopedDb.ts (Create) — well-formed
  • [~] src/lib/server/db.ts (Modify) — created by #1
  • [~] package.json (Modify) — exists after #6

Repo Placement

OK. All file targets in westside-admin. No multi-repo fan-out.

Dependencies

  • Hard blocker: #1 (board #1089, backlog) — creates db.ts and schema.ts.
  • Hard blocker: #6 (board #1087, backlog) — creates SvelteKit shell.
  • Downstream: #1090 (hooks-server), #1092 (page-server tables), #1093 (page-server rows, currently in todo) all consume scopedDb. Board ordering note for Ava: #1093 in todo while its dependency #1091 sits in backlog — not this ticket's blocker but worth flagging.
  • Documented? Yes — Lineage pins both upstream issues by number.

Acceptance Criteria

All 6 ACs agent-verifiable (unchanged from v2):
  • AC1–AC2: SQL output assertions via snapshot test
  • AC3: TypeScript type error on system-table misuse via expectTypeOf or tsc --noEmit
  • AC4: CI lint check fails on direct db import — verifiable on fixture
  • AC5: 6+ unit tests — quantitative
  • AC6: swap-procedure comment in tenant.ts — verifiable via grep
Integration test (URL/form-body tenant_id mutation still produces correct WHERE clause) remains the strongest data-leak guarantee.

Blast Radius

  • First Drizzle consumer in the cluster — pattern set here informs future adoption
  • Downstream rebases on #1090, #1092, #1093 if API shape is wrong; agent should sanity-check Drizzle's actual builder API before locking signatures
  • Grep-based lint is brittle to renames/re-exports; acceptable for v1
  • TENANT_ID = 1 in TS file works for v1; swap-point comment is the discipline

Decomposition Assessment

4 file targets (2 create + 2 modify), 6 ACs, ~6 unit tests + 1 integration test. Estimated agent work 30–60 min one-pass. No decomposition needed. Within 5-minute-rule envelope.

Recommendation

No action needed. APPROVED — ready to advance backlog → todo.
Optional cosmetic polish (not gating): the issue's Related section could also list arch-scoped-db-westside-admin alongside arch-dataflow-westside-admin, but the parent-arch link is sufficient since the new note nests under it.