Three strictness flags that the codebase already satisfies (0 errors each):
- noFallthroughCasesInSwitch on src + e2e — a missing `break` is now a type error.
- noUnusedLocals + noUnusedParameters on the e2e project, so it matches src and node
and dead spec scaffolding can't accumulate (it was the one project without them).
- allowJs + checkJs on the node project, pulling tailwind.config.js and
postcss.config.js under the type checker (the last hole in C-4.5) — a real type
error in either is now caught (verified: `content: 123` fails; Config stays
permissive on plugin keys by design).
noUncheckedIndexedAccess is NOT here — it has 98 call-site fixes and lands as its own
reviewable sub-sprint (S3b).
Review round 1 fallout, all of it verified against real builds:
- .dockerignore: `node_modules/` is anchored at the context root and has no
implicit `**/` (unlike gitignore), so it never matched frontend/node_modules.
`COPY frontend/ ./` was overlaying the Windows host's node_modules on top of
what `npm ci` had installed — the image carried @esbuild/win32-x64 and 31 .cmd
shims, and the new typecheck ran a tsc resolved from that merged tree. Build
context transfer drops 3.05 GB -> 19 kB. Also excludes e2e/.auth (a live
Playwright session), the report/result dirs and logs.
- build no longer type-checks the e2e project: a type error in a spec must not
make the app unbuildable for a self-hoster. The gate still checks it via
`npm run typecheck` (now three named lanes).
- tsconfig.json references tsconfig.node.json, so editors check vite.config.ts /
vitest.config.ts under the same config the gate uses instead of an inferred one.
- vitest include accepts .test.tsx: an uncollected test file does not fail, it
silently never runs.
`npm run build` now runs `typecheck` first, so the Docker image is built through the
same gate as local dev — until now the image was a bare `vite build`, and esbuild
strips types without checking them.
typecheck covers three projects: src, the Node-side build configs (new
tsconfig.node.json — vite.config.ts/vitest.config.ts were type-checked by nothing),
and e2e. knip moves from `npx knip@latest` to a pinned devDependency so the gate
stops depending on the network and on whichever version shipped that morning.