one directory per feature: schema.ts and queries.ts together
src/databases/officer_db/src/<feature>/{schema.ts,queries.ts}, replacing the
parallel schema/ and queries/ trees. 24 feature directories, 46 files moved with
git mv so history follows.
The parallel trees had drifted, which is what the restructure is really fixing:
four features were named differently on each side — app-store/sidecar-installs,
email/email-accounts, server/server-config
operations had a schema and NO query file: its task_logs is reached directly
from src/servers/api/task-logger.ts, bypassing this package's own boundary
integrations had queries and NO schema, because it spans two features'
tables — server_integrations and user_integrations
Both lopsided cases survive as directories holding one file, which states the
problem instead of hiding it across two trees.
Nothing outside the package changed how it imports. `officerdb`, `officerdb/types`
and `officerdb/db` resolve exactly as before; index.ts absorbed the path changes.
Added `"./*": "./src/*"` so the new layout is reachable — `officerdb/soulseek/schema`
— which one script needed, because soulseek is a plugin and therefore commented
out of the aggregator.
schema/index.ts became src/schema.ts, keeping the core/plugin split from earlier
tonight. drizzle.config.ts and the package's "./schema" export follow it.
Verified rather than assumed: all 52 files in the package parse, every relative
import resolves against the new layout (checked by walking each specifier to a
real file, since parsing does not check paths), and everything in the tree
importing officerdb still parses. Not typechecked — empty node_modules, frozen
installs.
One rewrite bug worth recording: the rule mapping a query module's sibling import
also matched the './schema' this pass had just written, turning it into
'../schema/queries' in 22 files. Caught by the resolver check, not by parsing —
both spellings parse fine.
Also corrects every path reference the move invalidated: src/databases/CLAUDE.md's
layout diagram, the root CLAUDE.md data section, three docs, and seven sidecar
comments naming queries/<x>.ts.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -327,4 +327,4 @@ service verbs exist (`listApiKeys`, `revokeApiKey`) if that changes.
|
||||
bearer string into a caller. All four doors call it: `userMiddleware`, `originScopeMiddleware`, the
|
||||
WebSocket upgrade in `server.tsx`, and the vault socket.
|
||||
- `src/servers/api/api-keys/router.ts` — the three endpoints.
|
||||
- `src/databases/officer_db/src/schema/api-keys.ts` — the table, and why it stores what it stores.
|
||||
- `src/databases/officer_db/src/api-keys/schema.ts` — the table, and why it stores what it stores.
|
||||
|
||||
@@ -5,7 +5,7 @@ does and does not protect against.
|
||||
|
||||
Authoritative for the crypto design. The code is `src/servers/sidecar/wallet/keys.ts` (sealing,
|
||||
derivation, unlock sessions), `src/databases/officer_db/src/crypto.ts` (storage encryption) and
|
||||
`src/databases/officer_db/src/queries/wallet.ts` (where the two meet).
|
||||
`src/databases/officer_db/src/wallet/queries.ts` (where the two meet).
|
||||
|
||||
## The requirement
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ and the rename sequence leaves `workspaces` with no zombie.
|
||||
- [x] **`ws-terminals-{id}: null` on a live dashboard is a 500.** Same file, `:61-66` — the
|
||||
`ws-layout-*` branch has a `value === null` → `deleteDashboard` case (`:42`); the terminals
|
||||
branches do not. A null falls to the UPDATE branch and sets a `NOT NULL` column
|
||||
(`databases/officer_db/src/queries/dashboards.ts:70`) → 23502.
|
||||
(`databases/officer_db/src/dashboards/queries.ts:70`) → 23502.
|
||||
**Resolved.** A null on either terminals branch is now a no-op: it means "forget this key", and it
|
||||
only ever arrives paired with `ws-layout-{id}: null` on a rename, by which point the row is gone.
|
||||
|
||||
@@ -202,7 +202,7 @@ these.
|
||||
> which uuid ids would not.
|
||||
|
||||
- [ ] **`dashboards.id` is a global primary key but ids are `slugify(name)`.**
|
||||
`databases/officer_db/src/schema/dashboards.ts` declares `id: text('id').primaryKey()`. Live:
|
||||
`databases/officer_db/src/dashboards/schema.ts` declares `id: text('id').primaryKey()`. Live:
|
||||
`"dashboards_pkey" PRIMARY KEY, btree (id)` plus a redundant
|
||||
`"uq_dashboards_user_id" UNIQUE, btree (user_id, id)` — evidence per-user ids were intended and
|
||||
half-built. Ids come from `DashboardPreview.tsx:300` (`slugify(trimmed) || generateSlug()`) and the
|
||||
@@ -213,7 +213,7 @@ these.
|
||||
(see `databases/CLAUDE.md` → "Composite keys") — harmless churn, but read the plan.
|
||||
|
||||
- [x] **`upsertDashboard`'s UPDATE has no `userId` predicate.**
|
||||
`databases/officer_db/src/queries/dashboards.ts:73` —
|
||||
`databases/officer_db/src/dashboards/queries.ts:73` —
|
||||
`db.update(dashboards).set(set).where(eq(dashboards.id, id))`. The `existing` lookup above it _is_
|
||||
scoped, so it cannot reach another user's row today, but it is a non-transactional read-then-write.
|
||||
**It becomes a live cross-user overwrite the moment the PK above is made composite.**
|
||||
|
||||
Reference in New Issue
Block a user