TanStack Start
permdock/tanstack-start is request middleware that adds context.permdock for server routes and server functions, a protect middleware, and the decision endpoint for permdock/react.
Purpose
permdock/tanstack-start is the server half for TanStack Start apps on React; permdock/react is the client half. middleware() and protect are TanStack Start request middleware, so the instance and the loaded row arrive as typed context in server routes and server functions.
API
import { createPermDock } from "permdock/tanstack-start";
import { policy } from "./policy";
export const { middleware, protect, permdockHandler } = createPermDock(policy, {
subject: (request) => userFromSession(request),
});import { createStart } from "@tanstack/react-start";
export const startInstance = createStart(() => ({
requestMiddleware: [middleware()],
}));export const Route = createFileRoute("/api/posts/$id")({
server: {
middleware: [protect(permissions.post.update, postFromPath)],
handlers: {
PATCH: ({ context }) => Response.json(update(context.permdockData)),
},
},
});export const Route = createFileRoute("/api/permdock")({
server: { handlers: permdockHandler() },
});| Export | Role |
|---|---|
middleware() | Request middleware for requestMiddleware in createStart, a server route's server.middleware or a server function's .middleware([...]). Adds context.permdock. A bad Web Bot Auth signature answers 401. |
protect(target, data?, options?) | Request middleware. data receives the Request. A grant adds context.permdock and context.permdockData; a refusal ends the request with the Problem Details response. |
getPermDock(request) | The instance for a server function: getPermDock(getRequest()) with getRequest from @tanstack/react-start/server. |
getSnapshot(request, query?) | The snapshot a route loader returns through a server function for permdock/react. |
connection(request, options?) | A kernel Connection for a stream. |
permdockHandler() | GET (snapshot) and POST (AuthZEN-shaped evaluations) for server.handlers. |
openapi | The kernel's OpenAPI hook contract. |
There is no withPermDock: the middleware chain types context, so a handler after middleware() or protect reads context.permdock without a wrapper.
Request lifecycle
permdock/tanstack-start follows the shared adapter contract. What differs on TanStack Start:
subject,tenant,contextandprotect'sdatareceive the FetchRequest. Route params are not part of it; parse them fromrequest.url, as the example'spostFromPathdoes.- A loader that returns
nullorundefinedanswers404. - An
asserterror that propagates back throughnext()becomes the same Problem Details response as aprotectrefusal. - Route
beforeLoadandloaderrun on the client as well, so they are not a guard; guard server routes and server functions.
Why
TanStack Start request middleware receives the Fetch Request and passes typed context to the next step with next({ context }). The adapter returns that middleware type, so context.permdock and context.permdockData are inferred in server routes and server functions with no module augmentation and no wrapper. The entry targets @tanstack/react-start; Solid Start for TanStack would need its own peer and is not supported.
Example app
apps/examples/tanstack-start: src/lib/permissions.ts, src/lib/policy.ts and src/lib/permdock.ts, middleware() in src/start.ts, protect on PATCH /api/posts/$id (granted) and POST /api/posts/$id/publish (denied for member), and the decision endpoint at src/routes/api/permdock.ts. src/routeTree.gen.ts is generated by pnpm dev.
Related standards
- Problem Details.
- AuthZEN for the decision endpoint.
- Web Bot Auth.
Last updated on
SolidStart
permdock/solid-start is an h3 middleware for SolidStart 2's createMiddleware, a protect wrapper for API routes, and the decision endpoint for permdock/solid.
Server kernel
permdock/server is the Fetch-first kernel every HTTP and RPC adapter wraps; it resolves the subject from a Request, scopes one PermDock per request, runs protect, emits Problem Details and exposes the OpenAPI hook contract.