Implement Content-Security-Policy headers and strict content-type handling
for non-API responses, with x-content-type-options applied to all routes.
Adds security-headers test suite to verify header presence.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bun-sqlite's Database.transaction is synchronous, but async callbacks return
a pending Promise at the first await, causing immediate COMMIT before the
entire callback completes. This allowed partial inserts with no rollback.
Fixed by:
- Remove async from transaction callback
- Add .run() to each insert/update to execute synchronously
- Add regression test proving atomicity: transaction that throws mid-loop
rolls back all changes (both tables empty after failure)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Add ConfirmDraftBody schema to shared types
- Implement GET /api/labs/drafts/:id (retrieves draft with extracted data)
- Implement POST /api/labs/drafts/:id/confirm (normalizes markers, inserts lab draw + biomarkers in transaction, marks draft confirmed)
- Implement POST /api/labs/drafts/:id/discard (marks draft discarded)
- Add comprehensive test suite with 3 new tests
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Anonymous HTTPS clone fails while the repo is private; token works either
way, and the internal gitea:3000 host skips the reverse proxy.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The login rate limiter keyed on the client-controlled x-forwarded-for
header, letting an attacker rotate XFF for unlimited password guesses
while also growing the failures Map unboundedly (memory DoS). Since
this is a single-password instance, replace with one global
{count, resetAt} tracker per app instance: check the 15-min window and
reject at >=10 failures before verifying the password, increment on
failure, reset on success.
- Add serveStatic middleware to server/src/app.ts to serve web/dist
- Include SPA fallback route for client-side routing deep links
- Create Dockerfile with multi-stage build (Node deps + build, slim runtime)
- Add docker-compose.yml for single-command deployment
- Add docs/deploy.md with deployment instructions and Caddy reverse proxy example
- Add bun run build:web step to CI pipeline after typecheck
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Projects are non-composite with noEmit, so build mode (-b) re-builds every run.
Use -p for proper project checking: bunx tsc -p server && bunx tsc -p shared && bunx tsc -p web
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Removes composite project references in favor of simpler -p checking.
Adds noEmit to tsconfig so tsc is typecheck-only.
Adds smoke test to unblock CI test gate.
Ignores tsbuildinfo artifacts from git.