Address review: PGRST205 degrade, per-user rate limit, header hardening
Five should-fixes and six nits from the independent review of #81. PGRST205 was a real defect. A missing TABLE on Supabase is PostgREST's PGRST205 (404, answered from its schema cache), never Postgres's 42P01 - verified empirically against PostgREST 14.16 in a local container (no credentials involved): missing table -> PGRST205, missing column in a filter -> 42703, missing column in a write payload -> PGRST204. The 42P01-only degrade would have thrown in production, and would have failed account deletion / SAR export outright on an unmigrated database. The code table now lives in a dependency-free leaf module lib/postgrestCodes.ts. - /clio-matters gets its own limiter keyed on res.locals.userId (IP only as the pre-auth fallback), inside the router because an app-level limiter runs before auth. The pilot firm NATs one office IP, so the shared IP-keyed research bucket would have let a few solicitors take /companies and /legislation down for everyone. New vars RATE_LIMIT_CLIO_MATTERS_MAX / _WINDOW_MINUTES, documented in .env.example and CLAUDE.md. Auth moves to router level so no future route can omit it. - headersFor drops any caller header colliding case-insensitively with a fixed one: object spread is case-sensitive and new Headers() then joins case-differing duplicates into "Bearer attacker, Bearer real". - linkWorkspace gains the matter-side pre-check; link candidates are ordered by created_at with the caller's own preferred; the workspace side of the conflict gets its own 409 copy. - Nits: cross-user cache isolation test, etag input guard, created_by predicate on the unlink delete, uuid guard on getLinkForProject, lifecycle fixtures corrected, amountsHidden renamed amountsUnavailable (a null price can mean a rate-less entry, so only quantityRedacted may drive "Hidden by your Clio permissions" copy). The first attempt imported the predicate from the feature seam into userDataCleanup, forming an import cycle through lib/access.ts that broke an unrelated tombstone test in routes/tabular.test.ts; hence the leaf module. Lifecycle paths must never import a feature seam. Verified: tsc clean; full vitest 871 passed / 49 files (baseline 757); prettier clean on all new and newly-touched files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| Repository | Sloth-ninja/JessicaOSS |
|---|---|
| Author | sloth-ninja <ezanahaddis@gmail.com> |
| Authored | |
| Parents | 7945ad49 |
| Stats | 17 files changed , +742 , -146 |
| Part of | Practice Management: Clio-backed Matters and workspace links |
Capture this commit into my fork
Download a Markdown prompt that tells Claude how to port this
exact commit into your working tree. Run it via
claude -p < capture-commit-20288bac.md
from inside the repo you want the change in.