Commit Graph

7 Commits

Author SHA1 Message Date
d09b3e2cdd feat(core-shared): auth-gate mutating feature procedures
Adds a shared requireAuthenticated tRPC middleware (reads the server-
resolved ctx.user from createTrpcContext) and applies it to every
mutating feature procedure — blog.createArticle and media.deleteMedia
were anonymous-callable (audit finding B7). Read-only queries stay
public; features compose <x>ProtectedProcedure from their error-mapped
base procedure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 18:25:46 +02:00
49241845b5 feat(web-next): resolve the session user + live compliance context
The tRPC createContext was () => ({}) — the mounted dsr/consent routers
401'd every call and the dsr singleton stub threw (audit finding A11).
createTrpcContext now accepts an app resolveUser hook; web-next resolves
the session cookie through the auth feature's validateSession (denylist
included) plus a role snapshot, and threads bindProductionDsr/Consent
(or dev-seed) bindings into every request. The dsr router resolves its
binding from ctx.dsrBinding per request instead of a throwing proxy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 18:25:46 +02:00
b66759a1ab fix(auth): derive clientIp server-side, drop it from sign-in input
clientIp was part of the public signInInputSchema, so any client could
spoof its own rate-limit bucket or dodge IP throttling entirely (audit
finding B2). The schema no longer carries it (strict parsing rejects it
with BAD_REQUEST); instead the web-next tRPC fetch adapter derives it in
createTrpcContext from x-forwarded-for (first hop) / x-real-ip — trust
caveat documented — and the router threads ctx.clientIp to the
controller as a second, server-only argument typed outside the input
schema (SignInRequestContext).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 17:28:56 +02:00
aac37fd9af docs(core-shared): correct defineErrorMiddleware jsdoc to match implementation
Code-quality reviewer flagged a stale 'try/catch' phrase in the jsdoc
that didn't match the actual result.ok inspection pattern. Updated
description to accurately describe how tRPC v11 middleware sees errors
(returned result, not thrown exception) and how the middleware
discriminates and rethrows.

Pure docstring change — no behavioral or signature impact.
2026-05-06 11:54:51 +02:00
e25b1f7a1c feat(core-shared): add defineErrorMiddleware factory + export t
Factory takes [[ErrorCtor, TRPC_CODE], ...] tuples and returns a tRPC
middleware that translates matching domain errors to TRPCError. Discrim-
inates by instanceof; preserves original error as cause; unmapped
errors propagate (tRPC then wraps them as INTERNAL_SERVER_ERROR with
the original error as .cause — middleware does not interfere).

core-shared never enumerates feature errors — each feature passes its
own constructors in via integrations/api/procedures.ts (Tasks 3-7).

Also exports the `t` instance from trpc/init.ts so feature procedure
files can do t.procedure.use(...).

Also fixes tsconfig.json: rootDir set to "." and @/* path alias added
so test files using @/ resolve correctly under tsc --noEmit.

Refactor log: §1, §2, §4
Spec: R13–R17
2026-05-06 11:43:45 +02:00
428346a36d feat(core-shared): add tRPC context factory 2026-05-04 20:40:52 +02:00
cd2f3b1fff feat(core-shared): add tRPC init with superjson 2026-05-04 20:40:42 +02:00