Commit Graph

11 Commits

Author SHA1 Message Date
marcuspaico
a08544db7d feat(labs): unit conversion, analyte registry, marker normalization 2026-08-17 15:23:34 -07:00
marcuspaico
bd4817cb77 feat(db): lab_drafts, lab_draws, biomarkers tables
Refs PAI-91.
2026-08-17 15:17:37 -07:00
marcuspaico
0b0f81b7bb fix(auth): global login rate limit — XFF was spoofable and Map unbounded
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.
2026-08-17 14:34:08 -07:00
marcuspaico
0ac233945c fix: 404 unknown API routes, add .dockerignore
- Add catch-all 404 handler for unknown /api/* routes after API mounts
- Unauthed requests to unknown API paths now return 401, authed return 404
- Add .dockerignore to prevent leaking data/ (DB, secret.key), .git/, node_modules/
- Add test in auth.test.ts verifying unknown /api/nope returns 401 unauthed, 404 authed

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 14:27:15 -07:00
marcuspaico
24bc8917f1 feat(deploy): serve SPA from server, Dockerfile, compose, deploy docs
- 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>
2026-08-17 14:23:29 -07:00
marcuspaico
f33d395b71 feat(settings): LLM config API with AES-GCM sealed key, masked reads
- Add GET/PUT /api/settings for encrypted LLM configuration
- SettingsResponse with masked key display
- SettingsUpdate validation with optional fields
- Defaults: llmBaseUrl "https://openrouter.ai/api/v1", llmModel "anthropic/claude-sonnet-4.5"
- Encrypted storage with AES-256-GCM for llm_key
- getSetting() export for future route groups
- Comprehensive test coverage: defaults, updates, masking, encryption at rest, validation

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 14:14:53 -07:00
marcuspaico
0b8e897e31 feat(auth): setup/login/logout, argon2id, sessions, login rate limit 2026-08-17 14:11:00 -07:00
marcuspaico
3c796da649 feat(crypto): boot-generated key + AES-256-GCM sealed values 2026-08-17 14:07:50 -07:00
marcuspaico
0f96d5e3b8 feat(db): drizzle schema (settings, sessions) + boot migrations 2026-08-17 14:04:56 -07:00
marcuspaico
caa9af2f40 fix: typecheck without emit, placeholder test, drop build artifacts
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.
2026-08-17 14:02:12 -07:00
marcuspaico
fe9be9597c chore: monorepo scaffold, CI, MIT license
Bun workspaces (server/web/shared), typecheck+test gates, Gitea CI.
Refs PAI-90.
2026-08-17 13:55:39 -07:00