Tenant-scoped Drizzle query helper #3
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Type
Feature
Lineage
Hard depends on
forgejo_admin/westside-admin#1(Drizzle setup — needsdb.tsto wrap andschema.tsto type-check against). Hard depends onforgejo_admin/westside-admin#6(scaffolding).Repo
forgejo_admin/westside-adminUser Story
story-westside-admin-admin-row-crud. Implements the tenant scoping safety constraint.Context
Nearly every basketball-api table has a
tenant_idcolumn. ForgettingWHERE tenant_id = ?in even one query is a data-leak bug. The fix is to make tenant scoping a property of the query helper, not a discipline applied per call site.For v1, Westside is the only tenant. tenant_id is sourced from a single constant (
TENANT_ID = 1), NOT from the JWT. The constant lives in one well-marked file as the swap point for future multi-tenant.The unscoped
dbfromsrc/lib/server/db.tsis NOT exported from$lib/server. Only the scoped helper is. A lint or grep-based CI check enforces this.File Targets
Create:
src/lib/server/tenant.ts— exportsTENANT_ID = 1with a top-of-file comment marking the future multi-tenant swap pointsrc/lib/server/scopedDb.ts— exportsscopedDbwrapper. Providesselect(table),update(table),insert(table)builders that auto-injectWHERE tenant_id = TENANT_IDfor tenant-scoped tables. Tables without tenant_id (alembic_version, player_teams) accessed via separatesystemDbbuilder.Modify:
src/lib/server/db.ts— keep unscopeddbbut mark with@internalJSDoc; onlyscopedDb.tsshould import itpackage.json— add lint script that fails on anyimport { db } from '$lib/server/db'outsidescopedDb.tsDo NOT modify:
src/routes/(no consumers yet)Acceptance Criteria
scopedDb.select(players)generates SQL withWHERE tenant_id = 1automaticallyscopedDb.update(players).set({...}).where(eq(players.id, 5))generatesWHERE id = 5 AND tenant_id = 1tenant_idcolumn) from system tables — using a system table via scopedDb is a TypeScript errorscopedDb.tsimports unscopeddbtenant.tshas a multi-line block comment explaining the swap procedure when a second tenant existsTest Expectations
expectTypeOfor similar)Constraints
where/and/orChecklist
Related
project-westside-adminarch-dataflow-westside-admin#6(scaffolding),#1(Drizzle setup)Scope Review: NEEDS_REFINEMENT
Review note:
review-1091-2026-04-25Strong ticket — scope, ACs, file targets, and constraints are crisp. Two minor items before todo:
[SCOPE]arch:scopeddb-helperlabel has no backing arch note. Project page listsarch-domain-westside-admin,arch-dataflow-westside-admin,arch-deployment-westside-admin. The issue's Related section already points toarch-dataflow-westside-admin. Recommend relabeling board item #1091 toarch:dataflow-westside-admin(Ava's call).[BODY]Pin Lineage to explicit issue numbers: "Depends on #1 (Drizzle setup) which depends on #6 (scaffolding)."No decomposition needed. File targets cannot be live-verified (repo is empty pre-#6/#1) but paths are well-formed and consistent with the dependency chain.
Scope Re-Review: NEEDS_REFINEMENT
Review note:
review-1091-2026-04-25-v2(re-review ofreview-1091-2026-04-25)Resolved since v1:
[BODY]Lineage now pins explicit issue numbers (#1, #6) — clean.[SCOPE]Arch label changed toarch:scoped-db, matching sibling #1089 (Drizzle setup). Helper layer is consistent.Still outstanding:
[SCOPE]No backingarch-scoped-dbnote exists in pal-e-docs. The arch label points nowhere; the issue's Related section points atarch-dataflow-westside-admin. Recommend creatingarch-scoped-db-westside-admin(or similar) as a sub-component note documenting the helper API surface, tenant-vs-system table split, and lint-enforced single entry point — backs both #1089 and this ticket.Ticket scope, ACs, file targets, and constraints are otherwise READY. Flips to APPROVED once the arch note lands or Ava waives the requirement.
Scope Review: APPROVED
Review note:
review-1091-2026-04-25-v3v2 NEEDS_REFINEMENT resolved. New arch note
arch-scoped-db-westside-adminexists and maps thearch:scoped-dblabel to real components (scopedDb+systemDb), nested underarch-dataflow-westside-admin. Traceability triangle is complete — story note, arch note, and Forgejo issue all verified.Ready to advance backlog → todo.
Optional (non-gating): Related section could also list
arch-scoped-db-westside-adminalongsidearch-dataflow-westside-admin. Not required — the parent-arch link is sufficient.build/index.htmldoesn't exist for adapter-node #12