Commit Graph

6 Commits

Author SHA1 Message Date
50eda34e8e The app is now wired to GlitchTip with the Sentry SDKs
Some checks failed
Production — tag build, push, deploy / build-and-push (push) Successful in 1h13m36s
Production — tag build, push, deploy / deploy (push) Failing after 1m1s
2026-08-31 07:34:07 +03:30
dc10d8dbe3 docs: cut the comments that were not earning their place
I wrote 731 comment lines on this branch against 4,530 lines of code — 14%,
where the rest of the repo runs at 1.8%. CLAUDE.md asks for code that reads
like its surroundings, and this did not.

Removed by genre rather than by taste:

- restating the code, e.g. "JS getUTCDay() numbering: Sunday = 0" above the
  map that literally shows it, and a docblock on startOfWeek explaining that
  it returns the start of the week;
- narrating history — "this used to rebuild the whole map", "left the bar
  recording forever" — which the commit message and git blame already carry;
- saying the same thing in several places: the "cannot record is not a
  denied microphone" reason appeared three times in one file, and the
  "aborting stops a per-minute metered call" reason across three files. Each
  now lives once, where the behaviour it explains lives;
- defending decisions nobody would question, like why toLatinDigits is its
  own module;
- over-explaining defensive branches, three separate comments to distinguish
  null from missing-kind from unrecognised-kind.

What stays is what the code cannot say: the patient-right convention in
toFdi, whose failure mode is a valid code for the wrong tooth; the
"this"-vs-"next" week anchoring; StrictMode re-arming mountedRef; Safari
accepting no mimeType hint; and the invariants whose violation already cost
a bug — the body parser's middleware ordering and the dispatch panel's
auto-fill rules.

Comments only. The diff contains no non-comment line.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 23:14:15 +03:30
afb30691cf fix(backend): restore the large-body limit on the voice route
POST /voice/extract returned 500 for any real recording. The threshold was
exactly 100 kb — Express's body-parser default — which is about 20 seconds of
audio, so the endpoint was unusable at its own 2-minute cap.

The scoped parser was registered as a path-mounted json() stacked in front of a
default one, which relied on two implicit behaviours: Express stripping the
mount path, and body-parser skipping a request another parser had already
handled. That coupling broke when the surrounding middleware order shifted, and
it broke silently — the parser was still registered, just no longer the one that
ran. Bisected by dumping the Express layer stack and confirming the raw error was
`entity.too.large` with `limit: 102400`.

Replaced with a single middleware that picks a parser by path. No mount-path
stripping, no dependence on parser ordering. Extracted to common/body-parsers.ts
so it is covered by a unit test rather than only reachable through main.ts, which
createTestingModule never executes.

The test is mutation-checked: forcing the default parser fails 2 of its 5 cases.
It also pins that the larger limit does not leak app-wide, and that a merely
similar path (/api/voice/extract/extra) does not get it.

Verified against the compiled server: 300 kb now reaches /api/voice/extract,
/api/auth/login still rejects it, and ordinary requests are unaffected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 23:05:30 +03:30
db9d7d280a feat(backend): voice extraction endpoint
POST /voice/extract behind JwtAuthGuard + ClinicOrgGuard, plus
GET /voice/availability so the frontend can decide whether to render the
microphone — it cannot learn that from NEXT_PUBLIC_*, which are baked in at
build time.

Audio is held in memory for the request only: never written to disk, never a
Prisma row. The transcript goes back to the client and is not persisted. What
is logged is structured and patient-free — clip length, which fields resolved,
unresolved count, vendor cost, outcome — with log lines as the interim sink
until this repo has metrics infrastructure.

On extraction failure the transcript still travels back in the error details,
so the words the clinician already paid for can be salvaged into a note.

v1 ships ungated beyond a configured locale profile; the Plan.features design
is deferred, not dropped.

From review of this commit, four of which were load-bearing:

- Express's 100 kb default body limit rejected any recording past ~20 seconds,
  making the endpoint unusable at its own 2-minute cap. Body parsers are now
  registered explicitly with a 10 MB limit scoped to the voice route only.
  Verified empirically: 600 KB reaches /api/voice/extract, while /api/auth/login
  still 413s.
- ThrottlerGuard keys on req.ip, so behind nginx the whole deployment would
  share one bucket and an abuser rotating IPs would bypass it. VoiceThrottlerGuard
  keys on the user id instead — with no plan gate, this is the only control on
  metered vendor spend.
- ThrottlerException had no 429 fallback and surfaced as INTERNAL_ERROR; the
  guard now throws VOICE_RATE_LIMITED directly.
- durationMs was optional, so omitting it bypassed VOICE_MAX_RECORDING_MS
  entirely. It is required.
- VOICE_UNSUPPORTED_FORMAT was dead code — the DTO's @IsIn already rejects
  unknown containers — so it is gone rather than left unreachable.

ThrottlerModule is deliberately not bound as a global APP_GUARD: a global
ThrottlerGuard rate-limits every route against every named throttler, which
would have capped the whole API at the voice limit.

All seven remaining VOICE_* codes have errors.* keys in en, fa and nl.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 23:05:30 +03:30
fab5111aa8 improvement: error handeling structure changed and unified all across the app. user no longer sees inappropriate messages. 2026-07-12 18:27:38 +03:30
26bd35ae3c Initial commit: Full project structure
- Backend: NestJS with Docker
- Frontend: Next.js with Docker
- Nginx configuration for reverse proxy
- PostgreSQL setup
- Docker compose for orchestration
- Development environment configuration
2026-04-23 15:33:11 +03:30