Dropped @ts-nocheck from admin/payments/monthly-starting-amounts/
subscriptions/authOidc/calendar/export (~113 errors). Mostly mechanical
(catch bindings, params, never[] arrays), but the checker earned its keep:
- types/http.d.ts: added the 4-arg res.download(path, name, options, cb)
overload — the v0.42.0 root-option download fix (admin backup + user-db
export) didn't type-check against the old 3-arg-only signature.
- routes/calendar.cts: deleted dead clampDay() (zero callers; was also a
standing lint warning).
@ts-nocheck server count: 21 -> 14. Server suite 252/252.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All found by the multi-angle /code-review over the branch and verified
against the installed libraries:
- 401 discriminator: the session-expiry redirect keyed off a path prefix
(!/auth/*) and falsely logged users out on /profile/change-password
with a wrong current password. requireAuth's no-session 401 now carries
the distinct AUTH_REQUIRED code — the only signal api.ts dispatches
auth:expired on; wrong-credential 401s keep AUTH_ERROR on any path.
Test updated to pin the code-based contract on both directions.
- OIDC RFC 9207: exchangeAndVerifyTokens rebuilt the callback URL with
only code+state, dropping the iss parameter openid-client v6 validates
when the provider advertises support (authentik does) — every OIDC
login would fail post-upgrade. The full callback query is now forwarded.
- OIDC http issuers: v6 enforces HTTPS on discovery/endpoints (v5
didn't) — breaking internal http:// providers on Docker networks.
OIDC_ALLOW_INSECURE_HTTP=true opts back in (documented in .env.example).
- 2FA downgrade: authService's webauthn fallback caught ANY challenge
error and silently downgraded to password-only login; now only the
stale-flag 'No registered WebAuthn credentials' case falls through,
everything else rethrows.
- Burned-challenge retry: the server consumes the single-use 2FA
challenge before verifying (anti-replay), so after a server rejection
a retry can only ever return 'Challenge expired'. LoginPage now resets
to sign-in on server failure (WebAuthn AND the pre-existing TOTP trap);
a browser-prompt cancel keeps retry (token still live). Also lazy-loads
@simplewebauthn/browser out of the entry bundle, matching ProfilePage.
Server 252/252, client 52/52, OIDC smoke 44/44, probe 33/33, e2e 27.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
utils/logger.cts — console-compatible log.{debug,info,warn,error} with:
- level gating (LOG_LEVEL; debug in dev / info in prod), and
- REDACTION of secrets/PII (sensitive keys + bearer/JWT) so tokens,
passwords, and encrypted values never reach the logs (financial app).
Backend is abstracted (console now, swappable to pino later).
Swept all 317 server-runtime console.* across 35 files → log.* + inserted
the import at correct scope. tests/logger.test.js pins the redaction
contract (4 tests). CODE_STANDARDS updated; raw console.* is now banned in
server code.
Verified: check:server + typecheck:server + lint clean; 240/240 server
tests; client 50/50; build; e2e probe 17/17; boot smoke logs flow through
the logger and graceful shutdown intact.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Every routes/*.js → .cts, with handler signatures typed against the shared
http Req/Res/Next types. Routes carry @ts-nocheck for now — they're thin glue
over the (fully typed) services, so full route-level type-checking is deferred;
the handler-param typing is a head-start. server.js + test requires updated to
the explicit .cts paths.
Behavior-preserving. Verified: check:server 0, typecheck:server 0, suite 226/226,
real boot → /api/health + /api/about 200 (all routes mount).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>