Repository navigation
Description
From #424. Expanded with the October 2026 maintainability review; retains the original lazy, memoized initialization proposal.
Problem
Importing src/db/conn.ts starts ready, opens config.database.file with OPEN_CREATE, runs migrations, then initializes connections. Scripts can therefore create/migrate a database before parsing --help or --dry-run. Test overrides prevent bootstrap from reclaiming the exported connections, but do not prevent the configured database being opened/migrated.
The bootstrap catches and logs errors without rethrowing. await ready therefore resolves after an initialization failure and the executable can proceed to listen with unusable connections.
Proposed change
- Replace the eager promise with explicit lazy memoized
ensureReady(): Promise<void>. Importing this module must perform no database I/O. Concurrent initialization calls share one in-flight operation and successful calls reuse it. - Let failures reject; close partially opened administrative/read/write connections in failure paths. Specify whether failure is terminal or retryable and test that policy. Do not silently turn failure into readiness.
- Update
src/index.ts, scheduled entry points, and everyreadyconsumer. Scripts must parse arguments and decide their mode before calling initialization. Recheckcheck-r2-usage.tsandcreateTestStatusData.ts, which previously used connections without awaiting readiness. - Preserve the existing test connection installation seam explicitly; once tests own the connection, no configured-file bootstrap should run or overwrite it. Simplify the race-specific flag only after its responsibilities are replaced.
- Keep transaction queuing/nested-transaction behavior unchanged. Document the new lifecycle and required initialization for executable callers.
Acceptance criteria and tests
- Importing
conn.ts, catalogue modules, or test fixtures creates/migrates no configured database file. - Concurrent
ensureReady()calls migrate/open once and resolve only after usable connections exist. - Migration/open failure rejects readiness and prevents the Portal from listening; partial resources are closed.
- Installing a test database cannot race an eager bootstrap or touch the configured file.
- Script
--helppaths open nothing; dry-run behavior is explicit and causes no incidental migration. - Child-process or injected-opener tests observe real import/init behavior, with isolated temporary paths. Existing transaction and fixture suites pass.
- Search for old
readyimports and initialization omissions; run all three typechecks and lint.
Scope
This fixes initialization ownership, not every global repository dependency. A separate app-factory proposal builds on this. No SQLite replacement, new connection pool, migration rewrite, or automatic production data change is required.
Review baseline
Source review at 78e0f1b2ff157e289c237d533f1406302d95118e. Repository typechecking and the focused specialty-award/level-progress tests passed during the review; these are not reproductions of the new failure scenarios above. Full database and E2E suites were not run.
Activity
jra3 commentedon Oct 13, 2026
The app-construction follow-up is now #539, with a native blocked-by dependency on this issue. #540 consolidates disposable SQLite test setup and explicitly distinguishes that work from fixing eager initialization here.