@nifrajs/cli 1.13.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +17 -2
  2. package/dist/check.d.ts +17 -6
  3. package/dist/check.d.ts.map +1 -1
  4. package/dist/check.js +256 -15
  5. package/dist/check.js.map +1 -1
  6. package/dist/cli.d.ts +2 -3
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +58 -71
  9. package/dist/cli.js.map +1 -1
  10. package/dist/doctor.d.ts.map +1 -1
  11. package/dist/doctor.js +108 -48
  12. package/dist/doctor.js.map +1 -1
  13. package/dist/mcp-http.js +1 -1
  14. package/dist/mcp-http.js.map +1 -1
  15. package/dist/mcp.d.ts +2 -0
  16. package/dist/mcp.d.ts.map +1 -1
  17. package/dist/mcp.js +42 -0
  18. package/dist/mcp.js.map +1 -1
  19. package/dist/recipes/2.0.0.d.ts +9 -0
  20. package/dist/recipes/2.0.0.d.ts.map +1 -0
  21. package/dist/recipes/2.0.0.js +25 -0
  22. package/dist/recipes/2.0.0.js.map +1 -0
  23. package/dist/recipes/index.d.ts +7 -0
  24. package/dist/recipes/index.d.ts.map +1 -1
  25. package/dist/recipes/index.js +2 -0
  26. package/dist/recipes/index.js.map +1 -1
  27. package/dist/sync-manifest.d.ts +33 -0
  28. package/dist/sync-manifest.d.ts.map +1 -0
  29. package/dist/sync-manifest.js +97 -0
  30. package/dist/sync-manifest.js.map +1 -0
  31. package/dist/upgrade.d.ts +23 -2
  32. package/dist/upgrade.d.ts.map +1 -1
  33. package/dist/upgrade.js +144 -13
  34. package/dist/upgrade.js.map +1 -1
  35. package/docs/examples.json +69 -21
  36. package/docs/llms-full.txt +1065 -104
  37. package/docs/types.json +880 -175
  38. package/package.json +9 -9
  39. package/src/check.ts +251 -18
  40. package/src/cli.ts +57 -73
  41. package/src/doctor.ts +133 -49
  42. package/src/mcp-http.ts +1 -1
  43. package/src/mcp.ts +52 -0
  44. package/src/recipes/2.0.0.ts +26 -0
  45. package/src/recipes/index.ts +10 -0
  46. package/src/sync-manifest.ts +111 -0
  47. package/src/upgrade.ts +163 -11
package/docs/types.json CHANGED
@@ -63,7 +63,7 @@
63
63
  "kind": "interface",
64
64
  "package": "@nifrajs/core",
65
65
  "signature": "export interface AdmissionController {\n admit(req: Request): AdmissionDecision | Promise<AdmissionDecision>;\n}",
66
- "doc": "/**\n * A capacity-admission gate. Decides, per request, whether the instance has capacity to run it now —\n * bounding *concurrency*, which rate limits (frequency) and deadlines (duration) do not. Provide an\n * implementation (see `@nifrajs/middleware`'s `createAdmissionController`) as {@link ServerOptions.admission}.\n *\n * Enabling it trades the fused native-route lane for native matching + this gate (the gate cannot be a\n * per-request `onRequest` hook without disabling native routes entirely); when unset, the request path\n * is untouched.\n */"
66
+ "doc": "/**\n * A capacity-admission gate. Decides, per request, whether the instance has capacity to run it now -\n * bounding *concurrency*, which rate limits (frequency) and deadlines (duration) do not. Provide an\n * implementation (see `@nifrajs/middleware`'s `createAdmissionController`) as {@link ServerOptions.admission}.\n *\n * Enabling it trades the fused native-route lane for native matching + this gate (the gate cannot be a\n * per-request `onRequest` hook without disabling native routes entirely); when unset, the request path\n * is untouched.\n */"
67
67
  },
68
68
  {
69
69
  "name": "AdmissionControllerHandle",
@@ -168,20 +168,6 @@
168
168
  "package": "create-nifra",
169
169
  "signature": "export interface AgentsMdOptions {\n readonly template: TemplateName;\n readonly framework: Framework;\n readonly name: string;\n /** Drizzle preset, when scaffolded with `--db` — adds a Database section. */\n readonly db?: DbChoice;\n /** Auth preset, when scaffolded with `--auth` — adds an Authentication section. */\n readonly auth?: AuthChoice;\n}"
170
170
  },
171
- {
172
- "name": "AgentSpan",
173
- "kind": "type",
174
- "package": "@nifrajs/agent-telemetry",
175
- "signature": "export type AgentSpan = NifraSpan;",
176
- "doc": "/** A tool-call span. Kept as an alias for package-specific naming without duplicating OTel types. */"
177
- },
178
- {
179
- "name": "AgentSpanExporter",
180
- "kind": "type",
181
- "package": "@nifrajs/agent-telemetry",
182
- "signature": "export type AgentSpanExporter = SpanExporter;",
183
- "doc": "/** Exporter seam shared with `@nifrajs/otel`. */"
184
- },
185
171
  {
186
172
  "name": "agentTelemetry",
187
173
  "kind": "function",
@@ -193,7 +179,7 @@
193
179
  "name": "AgentTelemetryOptions",
194
180
  "kind": "interface",
195
181
  "package": "@nifrajs/agent-telemetry",
196
- "signature": "export interface AgentTelemetryOptions {\n /** Exporter that receives completed tool-call spans. */\n readonly exporter: AgentSpanExporter;\n /** Path prefix for nifra tool routes (default `\"/_nifra/tool/\"`). */\n readonly toolPathPrefix?: string | undefined;\n /** Path for the MCP endpoint (default `\"/mcp\"`). */\n readonly mcpPath?: string | undefined;\n}"
182
+ "signature": "export interface AgentTelemetryOptions {\n /** Exporter that receives completed tool-call spans. */\n readonly exporter: ObservationAdapter;\n /** Path prefix for nifra tool routes (default `\"/_nifra/tool/\"`). */\n readonly toolPathPrefix?: string | undefined;\n /** Path for the MCP endpoint (default `\"/mcp\"`). */\n readonly mcpPath?: string | undefined;\n}"
197
183
  },
198
184
  {
199
185
  "name": "aggregateSizeReport",
@@ -262,11 +248,17 @@
262
248
  "signature": "export declare function apiRoutesSection(routes: readonly ReflectedRoute[]): string;",
263
249
  "doc": "/** Markdown section listing the backend's API routes with their request + response field shapes. */"
264
250
  },
251
+ {
252
+ "name": "appendCookiesToResponse",
253
+ "kind": "function",
254
+ "package": "@nifrajs/core",
255
+ "signature": "export declare function appendCookiesToResponse(response: Response, set: CtxSet): Response;"
256
+ },
265
257
  {
266
258
  "name": "appendTrailingSlash",
267
259
  "kind": "function",
268
260
  "package": "@nifrajs/middleware",
269
- "signature": "export declare function appendTrailingSlash(options?: TrailingSlashOptions): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").AnyServer>;",
261
+ "signature": "export declare function appendTrailingSlash(options?: TrailingSlashOptions): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").AnyServer>;",
270
262
  "doc": "/**\n * Append a trailing slash to non-root paths. By default it skips file-looking paths such as\n * `/app.css`, which keeps static assets and extensionful API routes stable.\n */"
271
263
  },
272
264
  {
@@ -408,13 +400,13 @@
408
400
  "name": "AssuranceFindingCode",
409
401
  "kind": "type",
410
402
  "package": "@nifrajs/core",
411
- "signature": "export type AssuranceFindingCode = \"no-routes\" | \"unclassified-route\" | \"missing-evidence\" | \"forbidden-evidence\";"
403
+ "signature": "export type AssuranceFindingCode = \"no-routes\" | \"unclassified-route\" | \"missing-evidence\" | \"forbidden-evidence\" | \"classified-no-evidence\";"
412
404
  },
413
405
  {
414
406
  "name": "AssurancePolicy",
415
407
  "kind": "interface",
416
408
  "package": "@nifrajs/core",
417
- "signature": "export interface AssurancePolicy {\n /** First matching rule owns a route. Put exceptions before broad defaults. */\n readonly rules: readonly AssuranceRule[];\n /** Default `error`: an unclassified route fails closed. */\n readonly unmatched?: \"error\" | \"ignore\";\n /** Default false: reject an empty reflected source so a wrong import cannot pass CI silently. */\n readonly allowEmpty?: boolean;\n}"
409
+ "signature": "export interface AssurancePolicy {\n /** First matching rule owns a route. Put exceptions before broad defaults. */\n readonly rules: readonly AssuranceRule[];\n /** Default `error`: an unclassified route fails closed. */\n readonly unmatched?: \"error\" | \"ignore\";\n /** Default false: reject an empty reflected source so a wrong import cannot pass CI silently. */\n readonly allowEmpty?: boolean;\n /**\n * Default false. When true, a route matched by a **pure-classification** rule (no `require`, no `forbid`)\n * that carries NO enforcement evidence is reported (`classified-no-evidence`). This surfaces the gap the\n * feedback flagged: a classification-only policy silently degrades \"proof\" to a \"label\". Opt-in, because\n * a genuinely public route legitimately carries no evidence; enable it once your guards emit evidence\n * (inline `schema.assurance` or a `withRouteAssurance` middleware) to keep classification honest.\n */\n readonly flagClassifiedWithoutEvidence?: boolean;\n}"
418
410
  },
419
411
  {
420
412
  "name": "AssuranceReport",
@@ -491,6 +483,20 @@
491
483
  "package": "create-nifra",
492
484
  "signature": "export type AuthChoice = (typeof AUTH_CHOICES)[number];"
493
485
  },
486
+ {
487
+ "name": "authed",
488
+ "kind": "function",
489
+ "package": "@nifrajs/better-auth",
490
+ "signature": "export declare function authed<A extends BetterAuthLike, const RequireTenant extends boolean = false>(auth: A, options?: AuthedOptions<SessionUserOf<A>> & {\n readonly requireTenant?: RequireTenant;\n}): <S extends AnyServer>(app: S) => WithPrincipal<S, PrincipalFor<SessionUserOf<A>, RequireTenant>>;",
491
+ "doc": "/**\n * A nifra plugin that derives a fail-closed {@link Principal} onto every downstream handler as\n * `c.principal`. After `server().use(authed(auth))`, `c.principal.user` / `c.principal.userId` are typed\n * and **non-null** - a handler CANNOT run without an authenticated caller, so the guard can't be\n * forgotten. Works in both modes:\n *\n * ```ts\n * // inline\n * const app = server().use(authed(auth)).get(\"/me\", (c) => ({ id: c.principal.userId }))\n * // contract-first (the pre-applied derive threads `principal` into the contract's handlers)\n * const api = implement(contract, handlers, server().use(authed(auth, { requireTenant: true })))\n * ```\n *\n * With `{ requireTenant: true }`, `c.principal.tenantId` is typed `string` (a missing tenant is a `403`).\n *\n * DESIGN NOTE: this is an **unnamed** plugin by necessity. A named plugin (for idempotent dedupe) carries\n * a `& { pluginName }` intersection that defeats the generic inference of `use`'s context-threading\n * overload and collapses the server - and its typed client - to `any` (see `@nifrajs/core` plugin docs).\n * Threading a NON-NULL principal is the whole point, so `authed` stays unnamed and generic. Applying it\n * twice simply derives twice (the second resolve overwrites with the same value); scope it once per app.\n */"
492
+ },
493
+ {
494
+ "name": "AuthedOptions",
495
+ "kind": "interface",
496
+ "package": "@nifrajs/better-auth",
497
+ "signature": "export interface AuthedOptions<User> {\n /** Require a resolvable tenant. When set and no tenant resolves, fail closed with `403`. */\n readonly requireTenant?: boolean;\n /** Browser redirect target (`302`) for a missing session, instead of the default `401` JSON. Same-origin. */\n readonly redirectTo?: string;\n /** Resolve the tenant id from the user. Default: `user.tenantId ?? user.orgId` (string-valued only). */\n readonly tenantOf?: (user: User) => string | undefined;\n}",
498
+ "doc": "/**\n * Options for {@link requirePrincipal} / {@link authed}.\n */"
499
+ },
494
500
  {
495
501
  "name": "AuthPlugin",
496
502
  "kind": "type",
@@ -646,7 +652,7 @@
646
652
  "name": "betterAuth",
647
653
  "kind": "function",
648
654
  "package": "@nifrajs/better-auth",
649
- "signature": "export declare function betterAuth(auth: BetterAuthLike, options?: BetterAuthOptions): import(\"@nifrajs/core\").IdentityPlugin;",
655
+ "signature": "export declare function betterAuth(auth: BetterAuthLike, options?: BetterAuthOptions): import(\"@nifrajs/core/server\").IdentityPlugin;",
650
656
  "doc": "/**\n * Mount a better-auth instance into a nifra app: registers its handler at `${basePath}/*`\n * (default `/api/auth/*`) for `GET` + `POST`, so every better-auth endpoint — sign-in/up/out, OAuth\n * callbacks, session, 2FA, magic links, … — is served by your nifra server.\n *\n * ```ts\n * import { betterAuth, requireSession } from \"@nifrajs/better-auth\"\n * import { auth } from \"./auth\" // your configured better-auth instance\n *\n * const app = server().use(betterAuth(auth)) // wires /api/auth/*\n * .get(\"/me\", async (c) => (await requireSession(auth, c.req)).user)\n * ```\n *\n * Idempotent (named `\"better-auth\"` — applying twice mounts once). Read the session with\n * {@link getSession} / {@link requireSession}, which infer your better-auth types.\n */"
651
657
  },
652
658
  {
@@ -875,7 +881,7 @@
875
881
  "name": "cacheControl",
876
882
  "kind": "function",
877
883
  "package": "@nifrajs/middleware",
878
- "signature": "export declare function cacheControl(value: string | ((request: Request) => string | undefined), options?: CacheControlOptions): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").AnyServer>;",
884
+ "signature": "export declare function cacheControl(value: string | ((request: Request) => string | undefined), options?: CacheControlOptions): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").AnyServer>;",
879
885
  "doc": "/**\n * Set a `Cache-Control` header on matching responses. `value` is either a fixed directive string or a\n * function of the request (return `undefined` to leave a response untouched — e.g. cache by path).\n * Defaults to `GET`/`HEAD` + 2xx, and never clobbers a `Cache-Control` the handler set itself.\n *\n * ```ts\n * app.use(cacheControl(\"public, max-age=3600, stale-while-revalidate=60\"))\n * // or per-path:\n * app.use(cacheControl((req) =>\n * new URL(req.url).pathname.startsWith(\"/assets/\") ? \"public, max-age=31536000, immutable\" : undefined,\n * ))\n * ```\n */"
880
886
  },
881
887
  {
@@ -1369,14 +1375,14 @@
1369
1375
  "name": "CheckDiagnostic",
1370
1376
  "kind": "interface",
1371
1377
  "package": "@nifrajs/cli",
1372
- "signature": "export interface CheckDiagnostic {\n readonly rule: \"typecheck\" | \"typed-client\" | \"untyped-client\" | \"server-only-import\" | \"response-route\" | \"undeclared-dependency\" | \"duplicate-install\" | \"server-manifest-drift\" | \"manifest-drift\" | \"capability-assurance\" | \"capability-config\";\n /** `error` fails the gate (a real contract break); `warning` is advisory — surfaced to the agent but\n * does NOT fail `nifra check`, for patterns that are sometimes intentional (a route returning a raw\n * `Response`, which silently drops the typed client to `data: never` but is valid for files/redirects). */\n readonly severity: \"error\" | \"warning\";\n readonly file?: string;\n readonly line?: number;\n readonly message: string;\n /** The canonical, rule-level fix — clean of the per-occurrence snippet, so an agent can apply it\n * directly. Set for the lint rules (they have one correct fix); omitted for `typecheck` (the fix is\n * specific to each type error). */\n readonly fix?: string;\n /** A richer, agent-oriented fix hint. Diffs are only emitted when the edit is mechanical and local;\n * ambiguous cases give concrete steps instead of pretending the checker can safely rewrite code. */\n readonly suggestion?: CheckSuggestion;\n /**\n * The import chain that pulls server-only code into the browser bundle, as display labels\n * `[routeFile, …as-written specifiers…, sink]`. Set only on `server-only-import`.\n *\n * #4.4: this is now the FULL **transitive** chain — a bounded import-resolution walk (`Bun.resolveSync`\n * from each file's dir, BFS the local module graph) follows `route → ../data → ../db → node:crypto`,\n * matching the build leak-guard's depth (`detectNodeBuiltinsInClient` in `@nifrajs/web/build`). A\n * length-2 chain (`[routeFile, specifier]`) means the route imports the sink directly. When a hop can't\n * be resolved precisely (a bare pkg, a tsconfig path alias), the walk degrades to the honest direct\n * edge rather than fabricating a deeper path — never a lie.\n */\n readonly chain?: readonly string[];\n}",
1378
+ "signature": "export interface CheckDiagnostic {\n readonly rule: \"typecheck\" | \"typed-client\" | \"untyped-client\" | \"server-only-import\" | \"response-route\" | \"undeclared-dependency\" | \"duplicate-install\" | \"server-manifest-drift\" | \"manifest-drift\" | \"capability-assurance\" | \"capability-config\" | \"check-config\";\n /** `error` fails the gate (a real contract break); `warning` is advisory — surfaced to the agent but\n * does NOT fail `nifra check`, for patterns that are sometimes intentional (a route returning a raw\n * `Response`, which silently drops the typed client to `data: never` but is valid for files/redirects). */\n readonly severity: \"error\" | \"warning\";\n readonly file?: string;\n readonly line?: number;\n readonly message: string;\n /** The canonical, rule-level fix — clean of the per-occurrence snippet, so an agent can apply it\n * directly. Set for the lint rules (they have one correct fix); omitted for `typecheck` (the fix is\n * specific to each type error). */\n readonly fix?: string;\n /** A richer, agent-oriented fix hint. Diffs are only emitted when the edit is mechanical and local;\n * ambiguous cases give concrete steps instead of pretending the checker can safely rewrite code. */\n readonly suggestion?: CheckSuggestion;\n /**\n * The import chain that pulls server-only code into the browser bundle, as display labels\n * `[routeFile, …as-written specifiers…, sink]`. Set only on `server-only-import`.\n *\n * #4.4: this is now the FULL **transitive** chain — a bounded import-resolution walk (`Bun.resolveSync`\n * from each file's dir, BFS the local module graph) follows `route → ../data → ../db → node:crypto`,\n * matching the build leak-guard's depth (`detectNodeBuiltinsInClient` in `@nifrajs/web/build`). A\n * length-2 chain (`[routeFile, specifier]`) means the route imports the sink directly. When a hop can't\n * be resolved precisely (a bare pkg, a tsconfig path alias), the walk degrades to the honest direct\n * edge rather than fabricating a deeper path — never a lie.\n */\n readonly chain?: readonly string[];\n}",
1373
1379
  "doc": "/** A single machine-readable check failure — the unit an agent (or CI) acts on. */"
1374
1380
  },
1375
1381
  {
1376
1382
  "name": "CheckResult",
1377
1383
  "kind": "interface",
1378
1384
  "package": "@nifrajs/cli",
1379
- "signature": "export interface CheckResult {\n readonly ok: boolean;\n readonly typecheck: \"pass\" | \"fail\" | \"skipped\";\n readonly diagnostics: readonly CheckDiagnostic[];\n /** Set only when the caller passed `maxDiagnostics` and there were more — `diagnostics` then holds the\n * first `shown` of `total`. It caps the serialized size so the `nifra_check` MCP tool can't emit a\n * message large enough to break the stdio transport; fix the shown diagnostics and re-run for the rest. */\n readonly truncated?: {\n readonly shown: number;\n readonly total: number;\n };\n}",
1385
+ "signature": "export interface CheckResult {\n readonly ok: boolean;\n readonly typecheck: \"pass\" | \"fail\" | \"skipped\";\n readonly diagnostics: readonly CheckDiagnostic[];\n /** Intentional non-typed mount prefixes declared in `nifra.check.json` (e.g. `/auth` for a mounted\n * better-auth). Echoed here so `--json` / the MCP tool / the report can show what the typed-client scan\n * deliberately skipped - a suppressed prefix stays auditable instead of silently hiding real drift. */\n readonly externalMounts?: readonly string[];\n /** Set only when the caller passed `maxDiagnostics` and there were more — `diagnostics` then holds the\n * first `shown` of `total`. It caps the serialized size so the `nifra_check` MCP tool can't emit a\n * message large enough to break the stdio transport; fix the shown diagnostics and re-run for the rest. */\n readonly truncated?: {\n readonly shown: number;\n readonly total: number;\n };\n}",
1380
1386
  "doc": "/** The structured result of a full check — what `--json` prints and the `nifra_check` MCP tool returns. */"
1381
1387
  },
1382
1388
  {
@@ -1439,11 +1445,25 @@
1439
1445
  "signature": "export declare function clientCall(method: string, path: string, schema: unknown): string;",
1440
1446
  "doc": "/**\n * The typed-client call form for a route — the exact `client<typeof app>` proxy chain an agent should\n * write, derived from the same convention `@nifrajs/client` implements (so it never has to read the\n * client tests to learn it): a static segment is a property (`.users`), a path param/wildcard is a call\n * that appends the value (`({ id })`), the root path is `.index`, and the HTTP verb is the terminal call.\n * Body verbs (POST/PUT/PATCH) take the body first then call-options; other verbs take call-options first —\n * so the `{ query }` argument lands in the right slot for each.\n */"
1441
1447
  },
1448
+ {
1449
+ "name": "ClientIpTrust",
1450
+ "kind": "type",
1451
+ "package": "@nifrajs/core",
1452
+ "signature": "export type ClientIpTrust = {\n readonly trustedHops: number;\n} | {\n readonly header: string;\n};",
1453
+ "doc": "/**\n * How much of the forwarding chain to trust when deriving `c.clientIp`. Omit for the safe default\n * (socket peer only, no header believed).\n *\n * - `{ trustedHops: n }` - trust `n` reverse-proxy hops in front of the app. The caller is taken from\n * `X-Forwarded-For` counted from the right past the `n` trusted hops (the socket peer is hop 0). Use\n * this when the app sits behind `n` proxies **you operate**. Fewer entries than trusted hops means\n * the header is too short to trust, so `c.clientIp` is `undefined` (fail closed).\n * - `{ header: name }` - trust a single named header's first value (e.g. a CDN that overwrites it at\n * the edge). Only declare this when the app is reachable **exclusively** through that edge; a\n * directly-reachable app lets any client forge the header.\n */"
1454
+ },
1442
1455
  {
1443
1456
  "name": "ClientOptions",
1444
1457
  "kind": "interface",
1445
1458
  "package": "@nifrajs/client",
1446
- "signature": "export interface ClientOptions {\n /** Headers sent on every request (a per-call `headers` option is merged on top). */\n readonly headers?: Record<string, string>;\n /** Override the `fetch` implementation (tests, an in-process bridge, a custom agent, etc.). */\n readonly fetch?: FetchFn;\n}"
1459
+ "signature": "export interface ClientOptions {\n /** Headers sent on every request (a per-call `headers` option is merged on top). */\n readonly headers?: Record<string, string>;\n /** Override the `fetch` implementation (tests, an in-process bridge, a custom agent, etc.). */\n readonly fetch?: FetchFn;\n /**\n * Runs before each request (including each retry). Return a header map to MERGE onto the outgoing\n * request — the place to inject a fresh auth token. `await`ed, so async token refresh works.\n */\n readonly onRequest?: (request: {\n readonly url: string;\n readonly method: string;\n readonly headers: Record<string, string>;\n readonly body: unknown;\n }) => MaybePromise<Record<string, string> | undefined>;\n /** Runs after a response arrives (once per call, on the final response). Observe-only. */\n readonly onResponse?: (response: {\n readonly url: string;\n readonly method: string;\n readonly response: Response;\n }) => MaybePromise<void>;\n /** Abort a call that takes longer than this many ms. Surfaces as `{ ok: false, status: 0 }` with a\n * `timeout` error, never a throw. Combined with a per-call `signal`. */\n readonly timeoutMs?: number;\n /** Enable safe automatic retries. See {@link ClientRetryOptions}. */\n readonly retry?: ClientRetryOptions;\n}"
1460
+ },
1461
+ {
1462
+ "name": "ClientRetryOptions",
1463
+ "kind": "interface",
1464
+ "package": "@nifrajs/client",
1465
+ "signature": "export interface ClientRetryOptions {\n /** Max RETRIES after the first attempt. Default 2. */\n readonly attempts?: number;\n /** Response statuses to retry. Default `[502, 503, 504]`. 4xx/429 are never added by default. */\n readonly on?: readonly number[];\n /** Methods eligible for retry. Default the idempotent set `GET/HEAD/OPTIONS/PUT/DELETE`. */\n readonly methods?: readonly string[];\n /** Delay (ms) before retry `n` (1-based). Default exponential backoff with jitter, capped at 3s. */\n readonly backoff?: (attempt: number) => number;\n}",
1466
+ "doc": "/** Safe retry policy. Off unless `retry` is set; retries ONLY idempotent methods and transient 5xx —\n * never a 4xx/429 and never a non-idempotent method, so a retry can't double a side effect. */"
1447
1467
  },
1448
1468
  {
1449
1469
  "name": "ClientRouter",
@@ -1491,6 +1511,13 @@
1491
1511
  "package": "@nifrajs/web",
1492
1512
  "signature": "export interface CloudflarePagesRoutesOptions {\n /** Prerendered request paths (e.g. `prerenderRoutes(...).prerendered.map(p => p.path)`, or the\n * build's `prerendered.json`). Each is excluded from the worker — plus its static `_data.json`. */\n readonly prerendered: readonly string[];\n /** Extra globs to keep OFF the worker (CDN-served). Default `[\"/assets/*\"]` (the hashed bundle). */\n readonly staticGlobs?: readonly string[];\n}"
1493
1513
  },
1514
+ {
1515
+ "name": "codePositionMask",
1516
+ "kind": "function",
1517
+ "package": "@nifrajs/cli",
1518
+ "signature": "export declare function codePositionMask(src: string): string;",
1519
+ "doc": "/** Blank comments and every quoted/template literal while preserving offsets. Unlike\n * {@link stripComments}, this is a code-position mask: scanners use it to find a call expression in\n * executable code, then inspect the original source for the call's literal argument. That prevents\n * documentation strings such as `const example = 'client(\"/\")'` from becoming diagnostics. */"
1520
+ },
1494
1521
  {
1495
1522
  "name": "collectAssuranceReport",
1496
1523
  "kind": "function",
@@ -1626,7 +1653,7 @@
1626
1653
  "kind": "function",
1627
1654
  "package": "@nifrajs/web-react",
1628
1655
  "signature": "export declare function compose(chain: readonly unknown[], props: RenderProps): ReactNode;",
1629
- "doc": "/**\n * Fold a layout chain (outermost layout → page) into a single React tree: the page\n * (innermost) receives `props` (the loader data); each layout wraps the child via its\n * `children`. Shared by the server adapter (renderToString) and the client (hydrateRoot).\n *\n * The whole tree is wrapped in a {@link RouterContext} provider carrying the matched `params` + the\n * current `path` (both threaded through `RenderProps` identically on SSR and client), so the routing\n * hooks (`useParams`/`useLocation`/`useSearchParams`) read the same value on both sides — no hydration\n * mismatch. A render with no routing fields (a non-router adapter usage) provides the empty default.\n */"
1656
+ "doc": "/**\n * Fold a layout chain (outermost layout → page) into a single React tree: the page\n * (innermost) receives `props` (the loader data); each layout wraps the child via its\n * `children`. Shared by the server adapter (renderToString) and the client (hydrateRoot).\n *\n * The whole tree is wrapped in a {@link RouterContext} provider carrying the matched `params`, the\n * current `path`, and the client `pending` flag (all threaded through `RenderProps` identically on SSR\n * and client), so the routing hooks (`useParams`/`useLocation`/`useNavigation`) read the same value on\n * both sides - no hydration mismatch (`pending` is `false` on SSR and on the initial client render).\n * A render with no routing fields (a non-router adapter usage) provides the empty default.\n */"
1630
1657
  },
1631
1658
  {
1632
1659
  "name": "compose",
@@ -1653,7 +1680,7 @@
1653
1680
  "name": "compression",
1654
1681
  "kind": "function",
1655
1682
  "package": "@nifrajs/middleware",
1656
- "signature": "export declare function compression(options?: CompressionOptions): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").AnyServer>;",
1683
+ "signature": "export declare function compression(options?: CompressionOptions): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").AnyServer>;",
1657
1684
  "doc": "/**\n * Transparently **gzip** responses when the client sends `Accept-Encoding: gzip` and the body is a\n * compressible type larger than `threshold`. Uses the Web-standard `CompressionStream` (streaming, no\n * full-body buffering), so it runs on every nifra runtime including the edge. gzip is the one encoding\n * `CompressionStream` guarantees everywhere; brotli isn't part of the standard, so it's not offered.\n *\n * The body is **peeked** up to `threshold` bytes to enforce the size floor: a response that ends below\n * the threshold is sent uncompressed (gzip's ~20-byte overhead would enlarge it), and only larger\n * bodies are compressed — the buffered prefix is replayed and the remainder streamed. (Runtimes rarely\n * set `Content-Length` on a constructed `Response`, so the header alone can't gate this.)\n *\n * Skips: clients that don't accept gzip, already-encoded responses, bodyless responses (204/304/HEAD),\n * `Range` responses (206 / `Content-Range`), `Cache-Control: no-transform`, and non-compressible types.\n * Adds `Vary: Accept-Encoding`.\n *\n * ```ts\n * app.use(compression())\n * ```\n */"
1658
1685
  },
1659
1686
  {
@@ -1694,14 +1721,14 @@
1694
1721
  "name": "consoleAgentExporter",
1695
1722
  "kind": "function",
1696
1723
  "package": "@nifrajs/agent-telemetry",
1697
- "signature": "export declare function consoleAgentExporter(log?: (line: string) => void): AgentSpanExporter;",
1724
+ "signature": "export declare function consoleAgentExporter(log?: (line: string) => void): ObservationAdapter;",
1698
1725
  "doc": "/**\n * Pretty-prints agent tool call traces to the terminal.\n *\n * Output format:\n * ```\n * [agent] tool:get_weather 12ms ok (input: 45B, output: 128B)\n * ```\n */"
1699
1726
  },
1700
1727
  {
1701
1728
  "name": "consoleSpanExporter",
1702
1729
  "kind": "function",
1703
1730
  "package": "@nifrajs/otel",
1704
- "signature": "export declare function consoleSpanExporter(log?: (line: string) => void): SpanExporter;",
1731
+ "signature": "export declare function consoleSpanExporter(log?: (line: string) => void): ObservationAdapter;",
1705
1732
  "doc": "/** A no-frills exporter that logs each completed span as one structured line. Useful in dev or as a\n * starting point before wiring a real backend. */"
1706
1733
  },
1707
1734
  {
@@ -1767,9 +1794,21 @@
1767
1794
  "name": "Context",
1768
1795
  "kind": "interface",
1769
1796
  "package": "@nifrajs/core",
1770
- "signature": "export interface Context<Path extends string = string, S extends RouteSchema = RouteSchema> {\n readonly req: Request;\n /**\n * Alias of {@link req} — the same `Request`. Page loaders/actions receive their request as `request`;\n * this alias lets route handlers and loaders share one name, so `c.request` and `ctx.req` both work\n * everywhere (no more `c.req` vs `ctx.request` mismatch).\n */\n readonly request: Request;\n readonly params: Params<Path>;\n readonly query: QueryOf<S>;\n readonly body: BodyOf<S>;\n /** The request's cookies, parsed from the `Cookie` header (values URL-decoded). Parsed lazily on\n * first access + cached. Signed cookies arrive as `value.signature` — verify with `unsignValue`. */\n readonly cookies: Readonly<Record<string, string>>;\n readonly set: ResponseControls;\n /**\n * Aborts when the server's `requestTimeoutMs` elapses (and never, when no timeout\n * is configured). Pass it to cancellation-aware work — DB drivers, `fetch` — so a\n * timed-out request stops doing work instead of running on after the 503.\n */\n readonly signal: AbortSignal;\n /**\n * Absolute request deadline plus monotonic remaining time. It shares {@link signal}; the server\n * clamps an inbound deadline to local policy when `acceptInboundDeadlines` is enabled.\n */\n readonly budget: RequestBudget;\n /**\n * Platform bindings from `app.fetch(request, { env })` — Workers `env` (KV/D1/secrets), etc.\n * `undefined` off-edge (Bun/Node/Deno). Declare the shape with `server<Env>()` to read it typed\n * (`c.env: Env`); otherwise `unknown`. Validate at the trust boundary before use either way.\n */\n readonly env: unknown;\n /**\n * Schedule background work. On edge runtimes it extends the response lifetime (Workers\n * `ctx.waitUntil`); off-edge it runs the promise fire-and-forget (a rejection is swallowed,\n * never an unhandled rejection).\n */\n readonly waitUntil: (promise: Promise<unknown>) => void;\n /**\n * Read the raw request body as bytes, **capped** at `maxBytes` (default: the server's\n * `maxBodyBytes`). For routes with **no body schema** — raw bodies, file uploads,\n * BYO-validation — where the automatic schema cap doesn't apply. An over-cap body (by\n * `Content-Length` or while streaming) throws a flat `413`; a malformed `Content-Length`\n * throws `400`. Consumes the body stream (call once). Pass a larger `maxBytes` for an\n * upload route, a smaller one to tighten a specific endpoint.\n */\n readonly boundedBody: (maxBytes?: number) => Promise<Uint8Array>;\n /**\n * `boundedBody` + `JSON.parse` (UTF-8). Same cap + `413`/`400` semantics; additionally\n * throws a flat `400` on invalid JSON. Use for a schema-less JSON endpoint that still\n * wants the body bounded.\n */\n readonly boundedJson: <T = unknown>(maxBytes?: number) => Promise<T>;\n /**\n * Build a JSON `Response`. Pass a status number or a full `ResponseInit` as the second arg. `return` it\n * from a handler, or `throw` it from `derive`/`beforeHandle` to short-circuit — both work:\n * `throw c.json({ error: \"unauthorized\" }, 401)`. A terser alternative to\n * `new Response(JSON.stringify(...), { status, headers: { \"content-type\": \"application/json\" } })`.\n */\n readonly json: (body: unknown, init?: ResponseInit | number) => Response;\n /** Build a `text/plain; charset=utf-8` `Response`. Like {@link json}, pass a status or `ResponseInit`. */\n readonly text: (body: string, init?: ResponseInit | number) => Response;\n}",
1797
+ "signature": "export interface Context<Path extends string = string, S extends RouteSchema = RouteSchema> {\n readonly req: Request;\n /**\n * Alias of {@link req} — the same `Request`. Page loaders/actions receive their request as `request`;\n * this alias lets route handlers and loaders share one name, so `c.request` and `ctx.req` both work\n * everywhere (no more `c.req` vs `ctx.request` mismatch).\n */\n readonly request: Request;\n readonly params: ParamsOf<S, Path>;\n readonly query: QueryOf<S>;\n readonly body: BodyOf<S>;\n /** The request's cookies, parsed from the `Cookie` header (values URL-decoded). Parsed lazily on\n * first access + cached. Signed cookies arrive as `value.signature` — verify with `unsignValue`. */\n readonly cookies: Readonly<Record<string, string>>;\n readonly set: ResponseControls;\n /**\n * Aborts when the server's `requestTimeoutMs` elapses (and never, when no timeout\n * is configured). Pass it to cancellation-aware work — DB drivers, `fetch` — so a\n * timed-out request stops doing work instead of running on after the 503.\n */\n readonly signal: AbortSignal;\n /**\n * Absolute request deadline plus monotonic remaining time. It shares {@link signal}; the server\n * clamps an inbound deadline to local policy when `acceptInboundDeadlines` is enabled.\n */\n readonly budget: RequestBudget;\n /**\n * Platform bindings from `app.fetch(request, { env })` — Workers `env` (KV/D1/secrets), etc.\n * `undefined` off-edge (Bun/Node/Deno). Declare the shape with `server<Env>()` to read it typed\n * (`c.env: Env`); otherwise `unknown`. Validate at the trust boundary before use either way.\n */\n readonly env: unknown;\n /**\n * The caller's IP. By default the raw socket peer the serving adapter observed (`listen()`,\n * `@nifrajs/node`, `@nifrajs/deno`) — the one address a client cannot forge — or `undefined` when the\n * runtime exposes no socket (Workers) and no trust is declared. Behind a proxy/CDN, set the\n * `clientIp` server option (`{ trustedHops }` or `{ header }`) to derive the real caller from the\n * forwarding chain as far as you trust it; unset, no forwarded header is ever believed. Safe to key\n * rate limits and audit logs on.\n */\n readonly clientIp: string | undefined;\n /**\n * Schedule background work. On edge runtimes it extends the response lifetime (Workers\n * `ctx.waitUntil`); off-edge it runs the promise fire-and-forget (a rejection is swallowed,\n * never an unhandled rejection).\n */\n readonly waitUntil: (promise: Promise<unknown>) => void;\n /**\n * Read the raw request body as bytes, **capped** at `maxBytes` (default: the server's\n * `maxBodyBytes`). For routes with **no body schema** — raw bodies, file uploads,\n * BYO-validation — where the automatic schema cap doesn't apply. An over-cap body (by\n * `Content-Length` or while streaming) throws a flat `413`; a malformed `Content-Length`\n * throws `400`. Consumes the body stream (call once). Pass a larger `maxBytes` for an\n * upload route, a smaller one to tighten a specific endpoint.\n */\n readonly boundedBody: (maxBytes?: number) => Promise<Uint8Array>;\n /**\n * `boundedBody` + `JSON.parse` (UTF-8). Same cap + `413`/`400` semantics; additionally\n * throws a flat `400` on invalid JSON. Use for a schema-less JSON endpoint that still\n * wants the body bounded.\n */\n readonly boundedJson: <T = unknown>(maxBytes?: number) => Promise<T>;\n /**\n * Build a JSON `Response`. Pass a status number or a full `ResponseInit` as the second arg. `return` it\n * from a handler, or `throw` it from `derive`/`beforeHandle` to short-circuit — both work:\n * `throw c.json({ error: \"unauthorized\" }, 401)`. A terser alternative to\n * `new Response(JSON.stringify(...), { status, headers: { \"content-type\": \"application/json\" } })`.\n */\n readonly json: (body: unknown, init?: ResponseInit | number) => Response;\n /** Build a `text/plain; charset=utf-8` `Response`. Like {@link json}, pass a status or `ResponseInit`. */\n readonly text: (body: string, init?: ResponseInit | number) => Response;\n}",
1771
1798
  "doc": "/**\n * Handler context. `params` are inferred from the path; `body` and `query` are\n * the validated outputs of their schemas when declared (else `undefined` /\n * raw `URLSearchParams`).\n */"
1772
1799
  },
1800
+ {
1801
+ "name": "CONTEXT_SEARCH",
1802
+ "kind": "const",
1803
+ "package": "@nifrajs/core",
1804
+ "signature": "export declare const CONTEXT_SEARCH: unique symbol;"
1805
+ },
1806
+ {
1807
+ "name": "CONTEXT_SET",
1808
+ "kind": "const",
1809
+ "package": "@nifrajs/core",
1810
+ "signature": "export declare const CONTEXT_SET: unique symbol;"
1811
+ },
1773
1812
  {
1774
1813
  "name": "ContextFilter",
1775
1814
  "kind": "interface",
@@ -1909,6 +1948,13 @@
1909
1948
  "package": "@nifrajs/cli",
1910
1949
  "signature": "export declare function countBodyHits(lowerBody: string, group: SearchTermGroup, maxHits: number): number;"
1911
1950
  },
1951
+ {
1952
+ "name": "Counter",
1953
+ "kind": "class",
1954
+ "package": "@nifrajs/otel",
1955
+ "signature": "export declare class Counter {\n readonly name: string;\n readonly help: string;\n private readonly series;\n constructor(name: string, help: string);\n inc(labels?: Labels, by?: number): void;\n render(): string;\n}",
1956
+ "doc": "/** A monotonically increasing counter (requests, errors). */"
1957
+ },
1912
1958
  {
1913
1959
  "name": "createAdmissionController",
1914
1960
  "kind": "function",
@@ -1963,6 +2009,13 @@
1963
2009
  "signature": "export declare function createDevServer(options: DevServerOptions): Promise<DevServer>;",
1964
2010
  "doc": "/** Start the dev server: build → serve → watch → rebuild + reload on change. */"
1965
2011
  },
2012
+ {
2013
+ "name": "createEffectLedgerRuntime",
2014
+ "kind": "function",
2015
+ "package": "@nifrajs/core",
2016
+ "signature": "export declare function createEffectLedgerRuntime(options: EffectLedgerOptions): EffectLedgerRuntime;",
2017
+ "doc": "/**\n * Build an effect-ledger runtime from the app-wide options. `sink` receives the sealed, token-only\n * ledger when a capability-declaring route settles with recorded entries; `maxEntries` bounds a single\n * request's ledger; `chain` opts into the per-entry hash chain.\n */"
2018
+ },
1966
2019
  {
1967
2020
  "name": "createEventLoopLagSampler",
1968
2021
  "kind": "function",
@@ -1998,6 +2051,13 @@
1998
2051
  "signature": "export declare function createFormatter(locale: string, messages: Messages): Formatter;",
1999
2052
  "doc": "/**\n * Build (or reuse) a {@link Formatter} bound to a locale + its message catalog. Cheap to call per\n * request/render — instances are cached per `(messages, locale)`, and parsed ASTs + `Intl.*` are\n * memoized inside each. The catalog is the app's (import a JSON file); this only negotiates (see\n * `negotiateLocale`) and formats.\n */"
2000
2053
  },
2054
+ {
2055
+ "name": "createIdempotencyRuntime",
2056
+ "kind": "function",
2057
+ "package": "@nifrajs/core",
2058
+ "signature": "export declare function createIdempotencyRuntime(options?: IdempotencyPluginOptions): IdempotencyRuntime;",
2059
+ "doc": "/**\n * Build an idempotency runtime. `store` is the app-wide default backing routes that declare\n * `schema.idempotency` without their own `store`; when omitted, a shared in-process\n * {@link MemoryIdempotencyStore} is created lazily on first idempotent route.\n */"
2060
+ },
2001
2061
  {
2002
2062
  "name": "createImageHandler",
2003
2063
  "kind": "function",
@@ -2051,6 +2111,13 @@
2051
2111
  "signature": "export declare function createMemoryLedgerSink(options?: MemoryLedgerSinkOptions): MemoryLedgerSink;",
2052
2112
  "doc": "/** Bounded in-memory sink for tests and local development. Token-only, like every sink. */"
2053
2113
  },
2114
+ {
2115
+ "name": "createMetricsRegistry",
2116
+ "kind": "function",
2117
+ "package": "@nifrajs/otel",
2118
+ "signature": "export declare function createMetricsRegistry(): MetricsRegistry;",
2119
+ "doc": "/** Create a standalone registry to register custom app metrics on, shared into `metrics({ registry })`. */"
2120
+ },
2054
2121
  {
2055
2122
  "name": "createMockServer",
2056
2123
  "kind": "function",
@@ -2132,13 +2199,6 @@
2132
2199
  "signature": "export declare function createScheduler(options?: SchedulerOptions): Scheduler;",
2133
2200
  "doc": "/** Create an in-process cron scheduler. */"
2134
2201
  },
2135
- {
2136
- "name": "createSeededRandom",
2137
- "kind": "function",
2138
- "package": "@nifrajs/core",
2139
- "signature": "export declare function createSeededRandom(seed: number): () => number;",
2140
- "doc": "/** Deterministic PRNG (mulberry32). Ambient randomness would make failures unreproducible. */"
2141
- },
2142
2202
  {
2143
2203
  "name": "createSessions",
2144
2204
  "kind": "function",
@@ -2177,7 +2237,7 @@
2177
2237
  "name": "CreateWebAppOptions",
2178
2238
  "kind": "interface",
2179
2239
  "package": "@nifrajs/web",
2180
- "signature": "export interface CreateWebAppOptions {\n readonly adapter: RenderAdapter;\n readonly manifest: Manifest;\n /** URL of the built client entry (module script) injected into every page. */\n readonly clientEntry: string;\n /** Default document title for all pages. */\n readonly title?: string;\n /** Injected into each loader's `ctx.api` — typically an `inProcessClient(app)` (typed\n * per-route via `@nifrajs/client`'s `createRoutes`). Opaque to the core.\n *\n * **Auto-mount.** Every `inProcessClient(backend)` exposes the symbol-keyed platform-aware backend\n * mount interface from `@nifrajs/core/mount`; `createWebApp` also serves that backend over HTTP at\n * {@link apiPrefix} (default `/api`): a request whose pathname starts with the prefix is dispatched\n * before page routing with the same `env`/`waitUntil` platform context, and the backend's `Response`\n * is returned untouched. Legacy custom `.fetch(url, init)` bridges remain mountable but cannot\n * receive platform context. The mount runs in `nifra dev` too. Pass `apiPrefix: \"\"` to disable it. */\n readonly api?: unknown;\n /** HTTP path prefix the {@link api} backend is auto-mounted at (default `\"/api\"`). A request whose\n * pathname is exactly the prefix or starts with `prefix + \"/\"` is dispatched to the backend before\n * page routing; the backend therefore defines its routes at the **full** path (`server().post(\"/api/\n * sync\", …)`), matching the in-process `inProcessClient` call sites. Set to `\"\"` to disable the\n * auto-mount entirely (the app serves pages only and `api` stays a loader-only `ctx.api`). Mounting\n * is also a no-op when `api` has neither the symbol mount nor a legacy callable `.fetch`. */\n readonly apiPrefix?: string;\n /** Secret for **draft / preview mode** (see `enableDraft`). When set, a request carrying a valid\n * signed `__nifra_draft` cookie gets `ctx.draft === true` in loaders/actions (else always `false`).\n * Pair with `withISR({ draftSecret })` so editors bypass the cache. Omit to disable draft mode. */\n readonly draftSecret?: string;\n /** Per-route chunk URLs (`buildClient`'s `BuildManifest.routes`) — `routeId → [layout chunks…, own\n * chunk]`. When present, each page `modulepreload`s its matched route's chunks alongside the entry,\n * so the route code downloads in parallel (no entry→route-chunk waterfall). Omit ⇒ entry-only. */\n readonly routePreload?: Readonly<Record<string, readonly string[]>>;\n /** The app's bundled stylesheet URLs (`buildClient`'s `BuildManifest.css`) — the aggregate, injected\n * as `<link rel=\"stylesheet\">` in a page's `<head>`. Used as the fallback for any route absent from\n * {@link routeStyles}. Omit ⇒ no links (dev, where Vite injects CSS, or a CSS-free app). */\n readonly styles?: readonly string[];\n /** Per-route stylesheet URLs (`buildClient`'s `BuildManifest.routeStyles`) — `routeId → [chain CSS]`.\n * When a matched route has an entry here, only those (its layout chain + own CSS) are linked instead\n * of the aggregate `styles`, so a page ships only the CSS it uses. An empty array ⇒ no `<link>` (the\n * page imports no CSS). Routes absent here fall back to `styles`. Omit ⇒ always use `styles`. */\n readonly routeStyles?: Readonly<Record<string, readonly string[]>>;\n /** SSG: the prerendered-path set (e.g. from `enumeratePrerenderedPaths` or the build's\n * `prerendered.json`). Injected as `window.__NIFRA_PRERENDERED__` on every page so a client soft-nav\n * into a prerendered route fetches its static `_data.json` instead of hitting the worker. */\n readonly prerenderedPaths?: readonly string[];\n /** SSG: per dynamic route pattern, its `getStaticPaths` `fallback` (from `enumerateStaticRoutes` or\n * the build's `prerendered.json`). A route mapped to `\"404\"` rejects any path NOT in\n * `prerenderedPaths` with the 404 page — the unlisted path simply doesn't exist. `\"ssr\"` (the\n * default for unmapped routes) renders unlisted paths on-demand. */\n readonly staticFallbacks?: Readonly<Record<string, \"ssr\" | \"404\">>;\n /** Observe every loader/action failure — for error-reporting plugins (Sentry-style). Called for\n * real throws (not control-flow `Response`s like `redirect`), **before** the nearest `_error`\n * boundary renders / a soft-nav 500 / a rethrow — so it sees errors that the boundary would\n * otherwise hide. Observation only; its own throws are swallowed so a faulty reporter can't break\n * rendering. (`beforeLoader` is intentionally omitted — the core HTTP hooks already cover\n * pre-request work.) */\n readonly onLoaderError?: (error: unknown, ctx: {\n readonly request: Request;\n readonly params: Readonly<Record<string, string>>;\n readonly route: string;\n }) => void;\n}"
2240
+ "signature": "export interface CreateWebAppOptions {\n readonly adapter: RenderAdapter;\n readonly manifest: Manifest;\n /** URL of the built client entry (module script) injected into every page. */\n readonly clientEntry: string;\n /** Default document title for all pages. */\n readonly title?: string;\n /** Injected into each loader's `ctx.api` — typically an `inProcessClient(app)` (typed\n * per-route via `@nifrajs/client`'s `createRoutes`). Opaque to the core.\n *\n * **Auto-mount.** Every `inProcessClient(backend)` exposes the symbol-keyed platform-aware backend\n * mount interface from `@nifrajs/core/mount`; `createWebApp` also serves that backend over HTTP at\n * {@link apiPrefix} (default `/api`): a request whose pathname starts with the prefix is dispatched\n * before page routing with the same `env`/`waitUntil` platform context, and the backend's `Response`\n * is returned untouched. The mount runs in `nifra dev` too. Pass `apiPrefix: \"\"` to disable it. */\n readonly api?: unknown;\n /** HTTP path prefix the {@link api} backend is auto-mounted at (default `\"/api\"`). A request whose\n * pathname is exactly the prefix or starts with `prefix + \"/\"` is dispatched to the backend before\n * page routing; the backend therefore defines its routes at the **full** path (`server().post(\"/api/\n * sync\", …)`), matching the in-process `inProcessClient` call sites. Set to `\"\"` to disable the\n * auto-mount entirely (the app serves pages only and `api` stays a loader-only `ctx.api`). Mounting\n * is also a no-op when `api` does not expose the symbol mount. */\n readonly apiPrefix?: string;\n /** Secret for **draft / preview mode** (see `enableDraft`). When set, a request carrying a valid\n * signed `__nifra_draft` cookie gets `ctx.draft === true` in loaders/actions (else always `false`).\n * Pair with `withISR({ draftSecret })` so editors bypass the cache. Omit to disable draft mode. */\n readonly draftSecret?: string;\n /** Per-route chunk URLs (`buildClient`'s `BuildManifest.routes`) — `routeId → [layout chunks…, own\n * chunk]`. When present, each page `modulepreload`s its matched route's chunks alongside the entry,\n * so the route code downloads in parallel (no entry→route-chunk waterfall). Omit ⇒ entry-only. */\n readonly routePreload?: Readonly<Record<string, readonly string[]>>;\n /** The app's bundled stylesheet URLs (`buildClient`'s `BuildManifest.css`) — the aggregate, injected\n * as `<link rel=\"stylesheet\">` in a page's `<head>`. Used as the fallback for any route absent from\n * {@link routeStyles}. Omit ⇒ no links (dev, where Vite injects CSS, or a CSS-free app). */\n readonly styles?: readonly string[];\n /** Per-route stylesheet URLs (`buildClient`'s `BuildManifest.routeStyles`) — `routeId → [chain CSS]`.\n * When a matched route has an entry here, only those (its layout chain + own CSS) are linked instead\n * of the aggregate `styles`, so a page ships only the CSS it uses. An empty array ⇒ no `<link>` (the\n * page imports no CSS). Routes absent here fall back to `styles`. Omit ⇒ always use `styles`. */\n readonly routeStyles?: Readonly<Record<string, readonly string[]>>;\n /** SSG: the prerendered-path set (e.g. `enumerateStaticRoutes(routes).paths` or the build's\n * `prerendered.json`). Injected as `window.__NIFRA_PRERENDERED__` on every page so a client soft-nav\n * into a prerendered route fetches its static `_data.json` instead of hitting the worker. */\n readonly prerenderedPaths?: readonly string[];\n /** SSG: per dynamic route pattern, its `getStaticPaths` `fallback` (from `enumerateStaticRoutes` or\n * the build's `prerendered.json`). A route mapped to `\"404\"` rejects any path NOT in\n * `prerenderedPaths` with the 404 page — the unlisted path simply doesn't exist. `\"ssr\"` (the\n * default for unmapped routes) renders unlisted paths on-demand. */\n readonly staticFallbacks?: Readonly<Record<string, \"ssr\" | \"404\">>;\n /** Observe every loader/action failure — for error-reporting plugins (Sentry-style). Called for\n * real throws (not control-flow `Response`s like `redirect`), **before** the nearest `_error`\n * boundary renders / a soft-nav 500 / a rethrow — so it sees errors that the boundary would\n * otherwise hide. Observation only; its own throws are swallowed so a faulty reporter can't break\n * rendering. (`beforeLoader` is intentionally omitted — the core HTTP hooks already cover\n * pre-request work.) */\n readonly onLoaderError?: (error: unknown, ctx: {\n readonly request: Request;\n readonly params: Readonly<Record<string, string>>;\n readonly route: string;\n }) => void;\n}"
2181
2241
  },
2182
2242
  {
2183
2243
  "name": "CronError",
@@ -2239,6 +2299,13 @@
2239
2299
  "signature": "export declare function cssModulesBunPlugin(generate: \"dom\" | \"ssr\"): BunPlugin;",
2240
2300
  "doc": "/**\n * The CSS Modules Bun plugin. `\"dom\"` → the `.module.css` import becomes the class map AND emits the\n * scoped stylesheet as a virtual `?nifra-css-module` module that `Bun.build`'s CSS bundler folds into\n * the app stylesheet. `\"ssr\"` → the class map only (no CSS; the scoped names match the client build).\n * Tolerates a trailing `?query` on the path (dev servers append one to bust Bun's import cache).\n */"
2241
2301
  },
2302
+ {
2303
+ "name": "CtxSet",
2304
+ "kind": "type",
2305
+ "package": "@nifrajs/core",
2306
+ "signature": "export type CtxSet = ResponseControls & {\n _headers?: Record<string, string>;\n /** Accumulated `Set-Cookie` values — a list, since a `Record` would collapse multiple cookies. */\n _cookies?: string[];\n};",
2307
+ "doc": "/** `ctx.set` carrying the lazy backings (`_headers`, `_cookies`) so `toResponse` can skip allocating\n * anything when no handler touched `c.set.*`. Server-internal. */"
2308
+ },
2242
2309
  {
2243
2310
  "name": "CURSOR_MCP_JSON_PATH",
2244
2311
  "kind": "const",
@@ -2510,19 +2577,19 @@
2510
2577
  "kind": "function",
2511
2578
  "package": "@nifrajs/core",
2512
2579
  "signature": "export declare function defineIdentityPlugin(name: string, apply: <S extends AnyServer>(app: S) => S): IdentityPlugin;",
2513
- "doc": "/**\n * Define a type-**identity** plugin: it registers routes/hooks as a side effect but returns the app with\n * its `Registry` + `Context` UNCHANGED. Use this (not {@link definePlugin}) for any plugin that doesn't\n * add context types — e.g. one mounting an auth handler. It threads the caller's *concrete* server type\n * through `use`, so routes declared after `app.use(plugin)` keep their types.\n *\n * Why a dedicated helper: `definePlugin((app) => app)` infers `app: Server<any, any>`, so `use` returns\n * `Server<any, any>` and the whole typed client collapses to `any`. The explicit generic return type here\n * (which a plain `Object.assign` can't preserve) is what keeps `use` returning the precise server type.\n *\n * ```ts\n * export const audit = defineIdentityPlugin(\"audit\", (app) => app.onResponse(logResponse))\n * const api = server().get(\"/a\", h).use(audit).get(\"/b\", h) // /a AND /b stay typed\n * ```\n */"
2580
+ "doc": "/**\n * Define a type-**identity** plugin: it registers routes/hooks as a side effect but returns the app with\n * its `Registry` + `Context` UNCHANGED. Use this (not {@link definePlugin}) for any plugin that doesn't\n * add context types - e.g. one mounting an auth handler. It threads the caller's *concrete* server type\n * through `use`, so routes declared after `app.use(plugin)` keep their types.\n *\n * Why a dedicated helper: `definePlugin((app) => app)` infers `app: Server<any, any>`, so `use` returns\n * `Server<any, any>` and the whole typed client collapses to `any`. The explicit generic return type here\n * (which a plain `Object.assign` can't preserve) is what keeps `use` returning the precise server type.\n *\n * ```ts\n * export const audit = defineIdentityPlugin(\"audit\", (app) => app.onResponse(logResponse))\n * const api = server().get(\"/a\", h).use(audit).get(\"/b\", h) // /a AND /b stay typed\n * ```\n */"
2514
2581
  },
2515
2582
  {
2516
2583
  "name": "defineMcpTool",
2517
2584
  "kind": "function",
2518
2585
  "package": "@nifrajs/mcp",
2519
- "signature": "export declare function defineMcpTool(opts: DefineMcpToolOptions): McpTool;"
2586
+ "signature": "export declare function defineMcpTool<S extends StandardSchemaV1 = UntypedArgs>(opts: DefineMcpToolOptions<S>): McpTool;"
2520
2587
  },
2521
2588
  {
2522
2589
  "name": "DefineMcpToolOptions",
2523
2590
  "kind": "interface",
2524
2591
  "package": "@nifrajs/mcp",
2525
- "signature": "export interface DefineMcpToolOptions {\n readonly name: string;\n readonly description: string;\n /** JSON Schema for the arguments. Defaults to an empty object schema. */\n readonly inputSchema?: Record<string, unknown>;\n /** Link a widget so the tool's result renders as interactive UI in MCP Apps hosts (iframe). */\n readonly widget?: McpWidget;\n /** Render-intent for generative hosts that build their own themed UI from `structuredContent`. Lands\n * in `_meta.ui.intent`. Independent of `widget` — a tool can offer both (widget for MCP Apps hosts,\n * intent for generative builders). */\n readonly intent?: McpUiIntent;\n readonly handler: (args: Record<string, unknown>, context: McpToolContext) => McpToolHandlerResult | Promise<McpToolHandlerResult>;\n}"
2592
+ "signature": "export interface DefineMcpToolOptions<S extends StandardSchemaV1 = UntypedArgs> {\n readonly name: string;\n readonly description: string;\n /**\n * A Standard Schema for the arguments (nifra's `t`, zod, valibot, arktype, …). It validates every\n * call before the handler runs - invalid arguments return an in-band `isError` result naming each\n * issue, so the calling agent can correct and retry - and it types the handler's `args`. Schemas\n * that carry a JSON Schema (nifra's `t` does) also become the advertised `inputSchema` for free.\n */\n readonly input?: S;\n /**\n * JSON Schema for the wire descriptor (`tools/list`). Defaults to `input`'s own JSON Schema when\n * it exposes one, else an empty object schema. Pass explicitly when `input` comes from a vendor\n * whose schemas carry no JSON Schema, so the agent still sees real parameter docs.\n */\n readonly inputSchema?: Record<string, unknown>;\n /** Link a widget so the tool's result renders as interactive UI in MCP Apps hosts (iframe). */\n readonly widget?: McpWidget;\n /** Render-intent for generative hosts that build their own themed UI from `structuredContent`. Lands\n * in `_meta.ui.intent`. Independent of `widget` — a tool can offer both (widget for MCP Apps hosts,\n * intent for generative builders). */\n readonly intent?: McpUiIntent;\n readonly handler: (args: InferOutput<S>, context: McpToolContext) => McpToolHandlerResult | Promise<McpToolHandlerResult>;\n}"
2526
2593
  },
2527
2594
  {
2528
2595
  "name": "defineMcpWidget",
@@ -2541,14 +2608,14 @@
2541
2608
  "kind": "function",
2542
2609
  "package": "@nifrajs/core",
2543
2610
  "signature": "export declare function definePlugin<In extends AnyServer, Out extends AnyServer>(name: string, apply: (app: In) => Out): NifraPlugin<In, Out>;",
2544
- "doc": "/**\n * Name + ergonomics for a plugin that **adds typed context** (`derive`/`decorate`). `app.use(myPlugin)`\n * applies it once; a second `use` of the same name is skipped (idempotent), so plugins can depend on each\n * other without double-registering hooks.\n *\n * ```ts\n * export const requestId = definePlugin(\"requestId\", (app) => app.derive(() => ({ requestId: uuid() })))\n * app.use(requestId) // downstream handlers see c.requestId\n * ```\n *\n * FOOTGUN: only use this for a plugin that adds context. For a plugin that **mounts routes/hooks but adds\n * NO context** (an auth router, an audit logger), use {@link defineRouterPlugin} ({@link defineIdentityPlugin}).\n * `definePlugin((app) => app.get(...))` infers `app: Server<any, any>`, so `.use()` returns `Server<any, any>`\n * and your whole typed client silently collapses to `any` — no type error, no runtime error.\n */"
2611
+ "doc": "/**\n * Name + ergonomics for a plugin that **adds typed context** (`derive`/`decorate`). `app.use(myPlugin)`\n * applies it once; a second `use` of the same name is skipped (idempotent), so plugins can depend on each\n * other without double-registering hooks.\n *\n * ```ts\n * export const requestId = definePlugin(\"requestId\", (app) => app.derive(() => ({ requestId: uuid() })))\n * app.use(requestId) // downstream handlers see c.requestId\n * ```\n *\n * FOOTGUN: only use this for a plugin that adds context. For a plugin that **mounts routes/hooks but adds\n * NO context** (an auth router, an audit logger), use {@link defineRouterPlugin} ({@link defineIdentityPlugin}).\n * `definePlugin((app) => app.get(...))` infers `app: Server<any, any>`, so `.use()` returns `Server<any, any>`\n * and your whole typed client silently collapses to `any` - no type error, no runtime error.\n */"
2545
2612
  },
2546
2613
  {
2547
2614
  "name": "defineRouterPlugin",
2548
2615
  "kind": "const",
2549
2616
  "package": "@nifrajs/core",
2550
2617
  "signature": "export declare const defineRouterPlugin: typeof defineIdentityPlugin;",
2551
- "doc": "/**\n * Alias of {@link defineIdentityPlugin} with a name that says what it's FOR: a plugin that **mounts\n * routes/hooks but adds no context type** (an auth router, an audit logger). Use this — not\n * {@link definePlugin} — for any such plugin, or the typed client silently collapses to `any`. The\n * \"identity\" in {@link defineIdentityPlugin} refers to the type-identity it preserves; `defineRouterPlugin`\n * is the same thing under a clearer name.\n *\n * Mount routes as a **side effect**, then return the app unchanged (registering via `.get`/`.post` would\n * change the type away from the identity `S`; the mounted routes run but aren't in the caller's typed\n * registry — that's the trade that keeps everything else typed):\n *\n * ```ts\n * export const scim = defineRouterPlugin(\"scim\", (app) => {\n * app.get(\"/scim/v2/Users\", listUsers) // side effect: mounted at runtime\n * return app // return S unchanged → routes added after .use(scim) stay typed\n * })\n * const api = server().get(\"/a\", h).use(scim).get(\"/b\", h) // /a AND /b stay typed\n * ```\n */"
2618
+ "doc": "/**\n * Alias of {@link defineIdentityPlugin} with a name that says what it's FOR: a plugin that **mounts\n * routes/hooks but adds no context type** (an auth router, an audit logger). Use this - not\n * {@link definePlugin} - for any such plugin, or the typed client silently collapses to `any`. The\n * \"identity\" in {@link defineIdentityPlugin} refers to the type-identity it preserves; `defineRouterPlugin`\n * is the same thing under a clearer name.\n *\n * Mount routes as a **side effect**, then return the app unchanged (registering via `.get`/`.post` would\n * change the type away from the identity `S`; the mounted routes run but aren't in the caller's typed\n * registry - that's the trade that keeps everything else typed):\n *\n * ```ts\n * export const scim = defineRouterPlugin(\"scim\", (app) => {\n * app.get(\"/scim/v2/Users\", listUsers) // side effect: mounted at runtime\n * return app // return S unchanged → routes added after .use(scim) stay typed\n * })\n * const api = server().get(\"/a\", h).use(scim).get(\"/b\", h) // /a AND /b stay typed\n * ```\n */"
2552
2619
  },
2553
2620
  {
2554
2621
  "name": "DehydratedState",
@@ -2557,6 +2624,19 @@
2557
2624
  "signature": "export interface DehydratedState {\n readonly queries: ReadonlyArray<{\n readonly key: unknown;\n readonly data: unknown;\n readonly updatedAt: number;\n }>;\n}",
2558
2625
  "doc": "/** A serializable snapshot of the cache's successful queries — the SSR→client bridge payload. */"
2559
2626
  },
2627
+ {
2628
+ "name": "DependencyMove",
2629
+ "kind": "interface",
2630
+ "package": "@nifrajs/cli",
2631
+ "signature": "export interface DependencyMove {\n readonly from: string;\n readonly to: string;\n readonly toVersion: string;\n}",
2632
+ "doc": "/** Move a removed package dependency to its replacement, preserving the consumer's range style. */"
2633
+ },
2634
+ {
2635
+ "name": "DependencyMoveChange",
2636
+ "kind": "interface",
2637
+ "package": "@nifrajs/cli",
2638
+ "signature": "export interface DependencyMoveChange {\n readonly file: string;\n readonly field: string;\n readonly from: string;\n readonly to: string;\n readonly fromVersion: string;\n readonly toVersion: string;\n readonly action: \"renamed\" | \"removed\";\n}"
2639
+ },
2560
2640
  {
2561
2641
  "name": "describeProject",
2562
2642
  "kind": "function",
@@ -2629,7 +2709,7 @@
2629
2709
  "name": "devtools",
2630
2710
  "kind": "function",
2631
2711
  "package": "@nifrajs/devtools",
2632
- "signature": "export declare function devtools(options?: DevToolsOptions | undefined): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").AnyServer>;",
2712
+ "signature": "export declare function devtools(options?: DevToolsOptions | undefined): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").AnyServer>;",
2633
2713
  "doc": "/**\n * DevTools plugin. Its observation adapter projects the single request span into a\n * `DevToolsEvent`; its middleware only owns the secured SSE transport.\n * When configuring `tracing()` yourself, register it before this plugin so DevTools attaches to\n * that request owner.\n */"
2634
2714
  },
2635
2715
  {
@@ -2833,6 +2913,13 @@
2833
2913
  "signature": "export interface EffectEntryInput {\n /** Capability token (`db.write`, `payments.charge`). Must be a valid capability id. */\n readonly capability: string;\n /** Default `\"intent\"`. Record `committed`/`failed`/`compensated` only after the outcome is known. */\n readonly phase?: EffectPhase;\n /** Adapter/resource token (`repo:orders`, `provider:payments`). A token — never a value or a row. */\n readonly target?: string;\n /** Dimensionless counters; see {@link EffectCost}. At most {@link MAX_COST_AXES} axes. */\n readonly cost?: EffectCost;\n /** Optional keyed-HMAC digest of the effect payload (see {@link computeEffectDigest}); hex, 64 chars. */\n readonly digest?: string;\n /** Outcome error as a bounded token code — never a message, never a stack. */\n readonly error?: {\n readonly code: string;\n };\n}",
2834
2914
  "doc": "/** Caller-supplied fields for one entry. Everything else (`seq`, `at`) is assigned by the ledger. */"
2835
2915
  },
2916
+ {
2917
+ "name": "effectLedger",
2918
+ "kind": "function",
2919
+ "package": "@nifrajs/core",
2920
+ "signature": "export declare function effectLedger(options: EffectLedgerOptions): IdentityPlugin;",
2921
+ "doc": "/**\n * Enable the per-request effect ledger. Each route that declares `schema.capabilities` gets a bounded,\n * token-only ledger; `useCapability(c, id, …)` appends one entry per effect, and the sink receives the\n * sealed ledger when the response settles (only when it recorded entries). Token-only by construction -\n * capability ids, phases, counters, digests; never payloads, values, or the concrete URL (the route\n * pattern is recorded). Without this plugin, capability-declaring routes simply carry no ledger.\n */"
2922
+ },
2836
2923
  {
2837
2924
  "name": "effectLedgerOf",
2838
2925
  "kind": "function",
@@ -2854,6 +2941,13 @@
2854
2941
  "signature": "export declare class EffectLedgerOverflowError extends Error {\n readonly maxEntries: number;\n constructor(maxEntries: number);\n}",
2855
2942
  "doc": "/** Thrown by `append` when the per-request entry bound is exceeded. Fails the request closed. */"
2856
2943
  },
2944
+ {
2945
+ "name": "EffectLedgerRuntime",
2946
+ "kind": "interface",
2947
+ "package": "@nifrajs/core",
2948
+ "signature": "export interface EffectLedgerRuntime {\n /** Resolve a capability-declaring route into its ledger wiring, or `undefined` when it declares none. */\n resolve(capabilities: readonly string[], method: string, path: string): ResolvedEffectLedger | undefined;\n /** Create the per-request ledger for a ledgered route. */\n create(resolved: ResolvedEffectLedger): RequestLedger;\n /** Attach a ledger to the request context so `useCapability` can append to it. */\n attach(context: object, ledger: RequestLedger): void;\n /** Seal the ledger and deliver it to the sink (empty ledgers are not delivered). */\n settle<T>(ledger: RequestLedger, resolved: ResolvedEffectLedger, value: T, onSinkError: (fields: {\n method: string;\n path: string;\n name: string;\n }) => void): Promise<T>;\n}",
2949
+ "doc": "/** The injected effect-ledger implementation the kernel calls through when the plugin is installed. */"
2950
+ },
2857
2951
  {
2858
2952
  "name": "EffectLedgerSealedError",
2859
2953
  "kind": "class",
@@ -2874,6 +2968,12 @@
2874
2968
  "package": "@nifrajs/core",
2875
2969
  "signature": "export declare const EMPTY_PARAMS: Record<string, string>;"
2876
2970
  },
2971
+ {
2972
+ "name": "EMPTY_RESPONSE_CONTROLS",
2973
+ "kind": "const",
2974
+ "package": "@nifrajs/core",
2975
+ "signature": "export declare const EMPTY_RESPONSE_CONTROLS: CtxSet;"
2976
+ },
2877
2977
  {
2878
2978
  "name": "EmptyRegistry",
2879
2979
  "kind": "type",
@@ -2920,13 +3020,6 @@
2920
3020
  "signature": "export declare function ensureDefaultFormats(): void;",
2921
3021
  "doc": "/**\n * Install the standard string formats into TypeBox's global `FormatRegistry`, once.\n *\n * This is driven from the validate path (see `./adapter.ts`) rather than run as a bare\n * top-level import side effect *on purpose*: a production bundler (`Bun.build`, esbuild)\n * tree-shakes a module that is only imported for its effect, and Bun.build does **not**\n * honor the `sideEffects` package.json field — so the old top-level registration loop was\n * dropped from prod server bundles, making every `t.string({ format })` reject with\n * \"Unknown format\" while unbundled `nifra dev` worked. Calling this from code the validator\n * actually reaches keeps the registration in the bundle.\n *\n * Idempotent and cheap to call on every validate (a single boolean check after the first\n * run). The `Has` guard means a format a consumer registered first via {@link registerFormat}\n * is left untouched.\n */"
2922
3022
  },
2923
- {
2924
- "name": "enumeratePrerenderedPaths",
2925
- "kind": "function",
2926
- "package": "@nifrajs/web",
2927
- "signature": "export declare function enumeratePrerenderedPaths(routes: readonly RouteEntry[]): Promise<string[]>;",
2928
- "doc": "/** The prerendered-path subset of {@link enumerateStaticRoutes} — kept for callers that only need the\n * paths (e.g. injecting `window.__NIFRA_PRERENDERED__`). */"
2929
- },
2930
3023
  {
2931
3024
  "name": "enumerateStaticRoutes",
2932
3025
  "kind": "function",
@@ -3004,11 +3097,18 @@
3004
3097
  "signature": "export declare function errorBoundary(fallback: unknown): unknown;",
3005
3098
  "doc": "/**\n * Build an error-boundary chain element bound to `fallback` (a route's `_error` component). nifra's\n * client codegen inserts it before the page in the matched chain; a render error in the subtree is\n * captured (`onErrorCaptured`) and renders `fallback` with `{ data: { name, message } }` instead of\n * crashing. DOM-transparent (renders the default slot directly), so it never disturbs hydration.\n */"
3006
3099
  },
3100
+ {
3101
+ "name": "ErrorStatus",
3102
+ "kind": "type",
3103
+ "package": "@nifrajs/client",
3104
+ "signature": "export type ErrorStatus = 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511;",
3105
+ "doc": "/**\n * The failure statuses a call can carry (the IANA registry's 3xx/4xx/5xx set). Finite on purpose:\n * the undeclared-status fallback arm of {@link Result} is `Exclude<ErrorStatus, declared>` - with a\n * bare `number` there instead, `status === 404` could not narrow `data` to the declared 404 body,\n * because 404 would still inhabit the fallback arm.\n */"
3106
+ },
3007
3107
  {
3008
3108
  "name": "etag",
3009
3109
  "kind": "function",
3010
3110
  "package": "@nifrajs/middleware",
3011
- "signature": "export declare function etag(options?: ETagOptions): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").AnyServer>;",
3111
+ "signature": "export declare function etag(options?: ETagOptions): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").AnyServer>;",
3012
3112
  "doc": "/**\n * A {@link definePlugin} plugin that adds a content-hash `ETag` to `GET` `200` responses and returns\n * **`304 Not Modified`** when the client's `If-None-Match` matches — saving bandwidth on unchanged\n * responses. It reads and rebuilds small bodies only; larger responses pass through unchanged.\n * Idempotent.\n */"
3013
3113
  },
3014
3114
  {
@@ -3179,6 +3279,13 @@
3179
3279
  "package": "@nifrajs/testing",
3180
3280
  "signature": "export interface FailureScenarioReport {\n readonly name: string;\n readonly ok: boolean;\n readonly replay: FailureReplay;\n readonly evidence: readonly FailureEvidence[];\n /** Sanitized failure identity. Messages and stacks are deliberately excluded. */\n readonly error?: {\n readonly name: string;\n readonly kind?: FailureInjectedError[\"kind\"];\n };\n}"
3181
3281
  },
3282
+ {
3283
+ "name": "fallbackWaitUntil",
3284
+ "kind": "const",
3285
+ "package": "@nifrajs/core",
3286
+ "signature": "export declare const fallbackWaitUntil: (promise: Promise<unknown>) => void;",
3287
+ "doc": "/** Off-edge `waitUntil`: run the background work fire-and-forget, never leaking an unhandled\n * rejection. Edge runtimes pass their own (Workers `ctx.waitUntil`) via the platform arg. */"
3288
+ },
3182
3289
  {
3183
3290
  "name": "FEATURE_IDS",
3184
3291
  "kind": "const",
@@ -3248,13 +3355,6 @@
3248
3355
  "signature": "export type FetcherStore = Readable<FetcherState> & {\n /** Load a route path's loader data into this fetcher (concurrent; doesn't touch the active view). */\n readonly load: (path: string) => Promise<void>;\n /** Submit an action into this fetcher (concurrent); honors `X-Nifra-Revalidate`. */\n readonly submit: (action: string, body: NonNullable<RequestInit[\"body\"]>) => Promise<void>;\n};",
3249
3356
  "doc": "/** A fetcher store: a `Readable<FetcherState>` (read via `$`) plus imperative `load`/`submit`. */"
3250
3357
  },
3251
- {
3252
- "name": "FetchFinding",
3253
- "kind": "type",
3254
- "package": "@nifrajs/cli",
3255
- "signature": "export type FetchFinding = SourceFinding;",
3256
- "doc": "/** @deprecated kept for back-compat with existing tests; prefer {@link SourceFinding}. */"
3257
- },
3258
3358
  {
3259
3359
  "name": "FetchFn",
3260
3360
  "kind": "type",
@@ -3266,7 +3366,7 @@
3266
3366
  "name": "FetchHandler",
3267
3367
  "kind": "interface",
3268
3368
  "package": "@nifrajs/node",
3269
- "signature": "export interface FetchHandler {\n fetch(request: Request): Response | Promise<Response>;\n /** Nifra apps also expose this WS-upgrade seam; present → this adapter serves `app.ws()` routes via\n * the optional `ws` package (lazy-imported on the first upgrade). Absent (a plain `{ fetch }`\n * handler) → HTTP only, and an upgrade request gets a 404. */\n resolveWebSocketUpgrade?(request: Request): WsUpgradeOutcome | Promise<WsUpgradeOutcome>;\n}",
3369
+ "signature": "export interface FetchHandler {\n fetch(request: Request, platform?: NodePlatform): Response | Promise<Response>;\n /** Nifra apps also expose this WS-upgrade seam; present → this adapter serves `app.ws()` routes via\n * the optional `ws` package (lazy-imported on the first upgrade). Absent (a plain `{ fetch }`\n * handler) → HTTP only, and an upgrade request gets a 404. */\n resolveWebSocketUpgrade?(request: Request): WsUpgradeOutcome | Promise<WsUpgradeOutcome>;\n}",
3270
3370
  "doc": "/** Anything exposing a Web `fetch` handler — a nifra `app`, for instance. */"
3271
3371
  },
3272
3372
  {
@@ -3322,7 +3422,7 @@
3322
3422
  "kind": "function",
3323
3423
  "package": "@nifrajs/web",
3324
3424
  "signature": "export declare function fillRoutePattern(pattern: string, params: Record<string, string>): {\n path: string;\n missing: string[];\n};",
3325
- "doc": "/**\n * Substitute a route pattern's `:param` segments with concrete values: `/users/:id` + `{id:\"7\"}` →\n * `/users/7`. Returns the filled path plus any params that had no value (a `getStaticPaths` bug) so\n * the caller can skip rather than emit a path with a literal `:name`. Shared by the SSG driver and\n * {@link enumeratePrerenderedPaths}.\n */"
3425
+ "doc": "/**\n * Substitute a route pattern's `:param` segments with concrete values: `/users/:id` + `{id:\"7\"}` →\n * `/users/7`. Returns the filled path plus any params that had no value (a `getStaticPaths` bug) so\n * the caller can skip rather than emit a path with a literal `:name`. Shared by the SSG driver and\n * {@link enumerateStaticRoutes}.\n */"
3326
3426
  },
3327
3427
  {
3328
3428
  "name": "fixedBackoff",
@@ -3335,7 +3435,7 @@
3335
3435
  "name": "Flags",
3336
3436
  "kind": "interface",
3337
3437
  "package": "@nifrajs/cli",
3338
- "signature": "export interface Flags {\n readonly port: number;\n readonly out: string;\n readonly poll: boolean;\n /** `nifra build --target <t>`: emit a full deploy dir for a target (bun/node/deno/cf-pages/vercel/\n * static) instead of just the client bundle. Undefined ⇒ the legacy client-only build. */\n readonly target?: string;\n /** `nifra build --report`: print a per-chunk size + gzip table after the build. */\n readonly report: boolean;\n}"
3438
+ "signature": "export interface Flags {\n readonly port: number;\n readonly out: string;\n readonly poll: boolean;\n /** `nifra build --target <t>`: emit a full deploy dir for this target. Defaults to `bun`. */\n readonly target: string;\n /** `nifra build --report`: print a per-chunk size + gzip table after the build. */\n readonly report: boolean;\n}"
3339
3439
  },
3340
3440
  {
3341
3441
  "name": "FontAsset",
@@ -3409,6 +3509,13 @@
3409
3509
  "signature": "export declare function formatDiff(diff: RoutesDiff): string;",
3410
3510
  "doc": "/** Render a diff for terminals: breaking first, then info, then compatible. */"
3411
3511
  },
3512
+ {
3513
+ "name": "formatIssues",
3514
+ "kind": "function",
3515
+ "package": "@nifrajs/mcp",
3516
+ "signature": "export declare function formatIssues(issues: ReadonlyArray<StandardIssue>): string;",
3517
+ "doc": "/** Render issues as one agent-readable line per problem: `location: message`. */"
3518
+ },
3412
3519
  {
3413
3520
  "name": "formatManifestDiff",
3414
3521
  "kind": "function",
@@ -3495,6 +3602,27 @@
3495
3602
  "signature": "export declare function fromTypeBox<T extends TSchema>(schema: T, options?: {\n readonly coerce?: boolean;\n}): NifraSchema<T>;",
3496
3603
  "doc": "/**\n * Wrap a TypeBox schema as a `NifraSchema`.\n *\n * **Validation is fast where it can be, and works everywhere.** The first `validate`\n * builds a compiled `TypeCompiler` validator (codegen via `new Function`) and memoizes\n * it — composing schemas (`t.object({ a: t.string() })`) never compiles the inner\n * pieces; only a schema actually used to validate a request pays the one-time codegen\n * cost. On Bun and Node this is the only path and it is untouched.\n *\n * Edge runtimes (Cloudflare Workers, Vercel Edge, Deno Deploy) **forbid dynamic code\n * generation**, so that first compile throws there. We catch it once per schema and\n * fall back to TypeBox's eval-free `Value` checker — same semantics (and same global\n * `FormatRegistry`, so `t.string({ format })` behaves identically), no `new Function`.\n * The branch is decided once and memoized, so the hot path is a single check either way.\n *\n * Exposed (not just used internally by `t`) so a TypeBox schema authored directly can\n * be adapted without leaving the Standard Schema world.\n *\n * `options.coerce` runs TypeBox's `Value.Convert` (string→number/integer/boolean, per the schema)\n * BEFORE validating. Query values always arrive as strings (`?limit=20` → `\"20\"`), so a query schema\n * with a numeric field can't validate without this — it's how `t.pageQuery` yields a real `number`.\n * Leave it OFF (the default) for body/JSON schemas: a JSON number is already a number, and coercing\n * would silently accept `\"20\"` where the contract said `20`.\n */"
3497
3604
  },
3605
+ {
3606
+ "name": "fusedRespond",
3607
+ "kind": "function",
3608
+ "package": "@nifrajs/core",
3609
+ "signature": "export declare function fusedRespond(result: unknown, ctx: RawContext): Response;",
3610
+ "doc": "/** Fused-lane respond with a context: read `c.set` once; untouched (the common case) -> the fast\n * JSON respond; touched -> the generic `toResponse` with those controls (statuses, headers, cookies). */"
3611
+ },
3612
+ {
3613
+ "name": "fusedRespondNoSet",
3614
+ "kind": "function",
3615
+ "package": "@nifrajs/core",
3616
+ "signature": "export declare function fusedRespondNoSet(result: unknown): Response;",
3617
+ "doc": "/** Fused-lane respond when `c.set` is untouched. Bun 1.3's native `Response.json` now beats the\n * older hand-inlined stringify + Response construction on this lane while preserving the exact\n * body/content-type contract; keep the generic fallback for non-JSON values. */"
3618
+ },
3619
+ {
3620
+ "name": "Gauge",
3621
+ "kind": "class",
3622
+ "package": "@nifrajs/otel",
3623
+ "signature": "export declare class Gauge {\n readonly name: string;\n readonly help: string;\n private readonly series;\n constructor(name: string, help: string);\n private at;\n inc(labels?: Labels, by?: number): void;\n dec(labels?: Labels, by?: number): void;\n set(labels: Labels, value: number): void;\n render(): string;\n}",
3624
+ "doc": "/** A value that can go up and down (in-flight requests, queue depth). */"
3625
+ },
3498
3626
  {
3499
3627
  "name": "generateClientEntry",
3500
3628
  "kind": "function",
@@ -3582,6 +3710,12 @@
3582
3710
  "signature": "export declare function getContext<C extends Context = Context>(): C;",
3583
3711
  "doc": "/** Return the current request context, or throw when no context-storage wrapper is active. */"
3584
3712
  },
3713
+ {
3714
+ "name": "getNeverAbortSignal",
3715
+ "kind": "const",
3716
+ "package": "@nifrajs/core",
3717
+ "signature": "export declare const getNeverAbortSignal: () => AbortSignal;"
3718
+ },
3585
3719
  {
3586
3720
  "name": "getRecipe",
3587
3721
  "kind": "function",
@@ -3603,10 +3737,10 @@
3603
3737
  "doc": "/** A dynamic route's build-time param enumeration (the SSG equivalent of \"which pages exist\"). */"
3604
3738
  },
3605
3739
  {
3606
- "name": "getWsRuntime",
3607
- "kind": "function",
3740
+ "name": "getUnboundedRequestBudget",
3741
+ "kind": "const",
3608
3742
  "package": "@nifrajs/core",
3609
- "signature": "export declare function getWsRuntime(): WsRuntime | undefined;"
3743
+ "signature": "export declare const getUnboundedRequestBudget: () => RequestBudget;"
3610
3744
  },
3611
3745
  {
3612
3746
  "name": "githubDeployWorkflow",
@@ -3657,6 +3791,13 @@
3657
3791
  "signature": "export declare function handleRpc(message: JsonRpcRequest, tools: readonly McpTool[], serverInfo: {\n name: string;\n version: string;\n}, features?: McpServerFeatures, options?: McpProtocolOptions): Promise<JsonRpcResponse | null>;",
3658
3792
  "doc": "/**\n * Dispatch one JSON-RPC message against the given tools. Returns the response, or `null` for a\n * notification (no reply). Tool errors are reported in-band (`isError`) so the agent can react to them.\n */"
3659
3793
  },
3794
+ {
3795
+ "name": "HandlerResult",
3796
+ "kind": "type",
3797
+ "package": "@nifrajs/core",
3798
+ "signature": "export type HandlerResult = Response | unknown;",
3799
+ "doc": "/** A handler returns a `Response` (used as-is) or any value (serialized to JSON). */"
3800
+ },
3660
3801
  {
3661
3802
  "name": "HandlersFor",
3662
3803
  "kind": "type",
@@ -3678,11 +3819,17 @@
3678
3819
  "signature": "export declare function hashQueryKey(key: unknown): string;",
3679
3820
  "doc": "/**\n * Hash a query key to a stable cache string. Object keys are sorted (so `{a,b}` ≡ `{b,a}`); arrays\n * keep order. Keys must be serializable — a function/symbol in the key throws (it can't be a stable\n * identity). Mirrors TanStack Query's structural hashing.\n */"
3680
3821
  },
3822
+ {
3823
+ "name": "headerOf",
3824
+ "kind": "function",
3825
+ "package": "@nifrajs/core",
3826
+ "signature": "export declare function headerOf(source: RequestSource, name: string): string | null;"
3827
+ },
3681
3828
  {
3682
3829
  "name": "healthcheck",
3683
3830
  "kind": "function",
3684
3831
  "package": "@nifrajs/middleware",
3685
- "signature": "export declare function healthcheck(options?: HealthcheckOptions): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").AnyServer>;",
3832
+ "signature": "export declare function healthcheck(options?: HealthcheckOptions): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").AnyServer>;",
3686
3833
  "doc": "/**\n * Register **liveness** (`/health`) and **readiness** (`/ready`) endpoints. Liveness is a flat `200`\n * (the process is serving). Readiness runs each `check` and returns `200 { status: \"ok\", checks }`\n * when all pass, or `503 { status: \"error\", checks }` when any fail (a thrown check counts as failed).\n * Both are `Cache-Control: no-store`.\n *\n * Apply it **before** auth guards so the endpoints stay public (`beforeHandle` is order-scoped):\n *\n * ```ts\n * app.use(healthcheck({ checks: { db: () => db.ping() } })).use(bearer({ verify }))\n * ```\n */"
3687
3834
  },
3688
3835
  {
@@ -3691,6 +3838,13 @@
3691
3838
  "package": "@nifrajs/middleware",
3692
3839
  "signature": "export interface HealthcheckOptions {\n /** Liveness path — always `200` while the process is up. Default `\"/health\"`. */\n readonly path?: string;\n /** Readiness path — runs `checks`; `200` if all pass, `503` otherwise. Default `\"/ready\"`. */\n readyPath?: string;\n /** Readiness checks (DB ping, cache reachable, …). Each returns a boolean or throws; a throw counts\n * as failing. `/ready` reports each by name and is `200` only when all pass. */\n readonly checks?: Readonly<Record<string, () => MaybePromise<boolean>>>;\n}"
3693
3840
  },
3841
+ {
3842
+ "name": "Histogram",
3843
+ "kind": "class",
3844
+ "package": "@nifrajs/otel",
3845
+ "signature": "export declare class Histogram {\n readonly name: string;\n readonly help: string;\n private readonly series;\n private readonly buckets;\n constructor(name: string, help: string, buckets: readonly number[]);\n observe(value: number, labels?: Labels): void;\n render(): string;\n}",
3846
+ "doc": "/** Latency-style distribution over fixed buckets (seconds). Renders Prometheus cumulative buckets. */"
3847
+ },
3694
3848
  {
3695
3849
  "name": "hmacSha256",
3696
3850
  "kind": "function",
@@ -3827,6 +3981,12 @@
3827
3981
  "signature": "export interface I18nProviderProps {\n /** The active locale (e.g. `\"en\"`, `\"fr-CA\"`). */\n locale: string\n /** The ICU message catalog for `locale`. */\n messages: Messages\n /** The subtree that reads the formatter via `useT()`. */\n children?: Snippet\n}",
3828
3982
  "doc": "/** Hand-written types for `I18nProvider.svelte` (consumers resolve these via the `./i18n` re-export). */"
3829
3983
  },
3984
+ {
3985
+ "name": "idempotency",
3986
+ "kind": "function",
3987
+ "package": "@nifrajs/core",
3988
+ "signature": "export declare function idempotency(options?: IdempotencyPluginOptions): IdentityPlugin;"
3989
+ },
3830
3990
  {
3831
3991
  "name": "idempotency",
3832
3992
  "kind": "function",
@@ -3878,12 +4038,26 @@
3878
4038
  "signature": "export interface IdempotencyEntryKey {\n readonly namespace: string;\n readonly key: string;\n}",
3879
4039
  "doc": "/** Namespaces isolate the same client key across tenants/subjects without putting identity in a header. */"
3880
4040
  },
4041
+ {
4042
+ "name": "IdempotencyHost",
4043
+ "kind": "interface",
4044
+ "package": "@nifrajs/core",
4045
+ "signature": "export interface IdempotencyHost {\n readonly maxBodyBytes: number;\n runLanes(buffered: Request, platform: Platform | undefined, entry: unknown, params: Record<string, string>, search: string | undefined): Promise<Response>;\n}",
4046
+ "doc": "/**\n * What the dedupe lane needs from the server to run a fresh key: the app-wide body cap and a way to\n * run the buffered request through the route's normal lanes to a concrete `Response`.\n */"
4047
+ },
3881
4048
  {
3882
4049
  "name": "IdempotencyOptions",
3883
4050
  "kind": "interface",
3884
4051
  "package": "@nifrajs/middleware",
3885
4052
  "signature": "export interface IdempotencyOptions {\n /** Where claims + cached responses live. `MemoryIdempotencyStore` for dev; a shared store in production. */\n readonly store: IdempotencyStore;\n /** Header carrying the key. Default `\"idempotency-key\"`. */\n readonly header?: string;\n /** Methods the guard applies to. Default `[\"POST\", \"PUT\", \"PATCH\", \"DELETE\"]` (unsafe methods). */\n readonly methods?: readonly string[];\n /** How long a completed response is replayable, in ms. Default 24h. */\n readonly ttlMs?: number;\n /** How long the in-flight lock survives a crashed handler, in ms. Default 60s. */\n readonly lockTtlMs?: number;\n /** Max response bytes to cache. A larger response is returned but **not** stored. Default 1 MiB. */\n readonly maxBytes?: number;\n /** Whether a response should be cached for replay. Default: status `< 500` (don't replay transient 5xx). */\n readonly shouldCache?: (response: Response) => boolean;\n /**\n * Derive the store key from the request. Default: the `header` value **scoped by method + path**, so the\n * same key on a different endpoint can't collide. Return a **principal-scoped** key (e.g.\n * `` `${userId}:${req.headers.get(\"idempotency-key\")}` ``) so one user can't replay another's stored\n * response on a shared key. Return `null`/`\"\"` to skip dedupe for this request.\n */\n readonly key?: (req: Request, header: string) => string | null;\n}"
3886
4053
  },
4054
+ {
4055
+ "name": "IdempotencyPluginOptions",
4056
+ "kind": "interface",
4057
+ "package": "@nifrajs/core",
4058
+ "signature": "export interface IdempotencyPluginOptions {\n readonly store?: IdempotencyStore | undefined;\n}",
4059
+ "doc": "/**\n * Enable request idempotency. Routes that declare `schema.idempotency` get the dedupe lane: a repeat\n * `Idempotency-Key` replays the stored response instead of re-running the handler. Without this plugin,\n * declaring `schema.idempotency` is a registration error (the safety gate can never be silently\n * dropped). `store` is the app-wide default backing routes that do not pin their own; omit it for a\n * shared in-process store (development/tests only - inject a durable store in production).\n */"
4060
+ },
3887
4061
  {
3888
4062
  "name": "IdempotencyRecord",
3889
4063
  "kind": "interface",
@@ -3897,6 +4071,13 @@
3897
4071
  "package": "@nifrajs/core",
3898
4072
  "signature": "export declare class IdempotencyResponseTooLargeError extends Error {\n readonly maxBytes: number;\n constructor(maxBytes: number);\n}"
3899
4073
  },
4074
+ {
4075
+ "name": "IdempotencyRuntime",
4076
+ "kind": "interface",
4077
+ "package": "@nifrajs/core",
4078
+ "signature": "export interface IdempotencyRuntime {\n /** Resolve a route's declared idempotency into a pinned store + defaults, or `undefined` when off. */\n resolve(schema: RouteSchema | undefined, authenticated: boolean, maxBodyBytes: number): ResolvedIdempotency | undefined;\n /** The dedupe lane: read the key, fingerprint the request, consult the store, run/replay/reject. */\n run<T>(config: ResolvedIdempotency, req: Request, platform: Platform | undefined, entry: unknown, params: Record<string, string>, search: string | undefined, wrapResponse: (response: Response) => T, host: IdempotencyHost): Promise<T>;\n}",
4079
+ "doc": "/** The injected idempotency implementation the kernel calls through when the plugin is installed. */"
4080
+ },
3900
4081
  {
3901
4082
  "name": "IdempotencyScope",
3902
4083
  "kind": "type",
@@ -4127,6 +4308,13 @@
4127
4308
  "signature": "export type InferOutput<S extends StandardSchemaV1> = NonNullable<S[\"~standard\"][\"types\"]>[\"output\"];",
4128
4309
  "doc": "/** Extract a Standard Schema's validated output type. */"
4129
4310
  },
4311
+ {
4312
+ "name": "InferOutput",
4313
+ "kind": "type",
4314
+ "package": "@nifrajs/mcp",
4315
+ "signature": "export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema[\"~standard\"][\"types\"]>[\"output\"];",
4316
+ "doc": "/** The validated (post-transform) type of a Standard Schema. */"
4317
+ },
4130
4318
  {
4131
4319
  "name": "InfiniteData",
4132
4320
  "kind": "interface",
@@ -4178,8 +4366,8 @@
4178
4366
  "name": "inProcessClient",
4179
4367
  "kind": "function",
4180
4368
  "package": "@nifrajs/client",
4181
- "signature": "export declare function inProcessClient<App extends {\n fetch(request: Request): Response | Promise<Response>;\n}>(app: App, options?: Omit<ClientOptions, \"fetch\">): InProcessClient<App>;",
4182
- "doc": "/**\n * A {@link client} whose `fetch` calls a nifra app's own `fetch` in-process — no network, full\n * lifecycle (validation, middleware, contracts). For SSR loaders. Typed from `App` exactly like\n * the network client. The `(url, init) → Request` bridge is required because the client calls\n * `fetch(url, init)` while `app.fetch` takes a `Request`.\n *\n * The returned proxy also implements the explicit symbol-keyed {@link BackendMount} interface, so\n * `createWebApp({ api: inProcessClient(backend) })` can auto-mount the backend while forwarding the\n * outer runtime's `env` and `waitUntil`. The released `.fetch(url, init)` bridge remains available as\n * a compatibility surface for custom integrations, but the platform-aware mount never relies on it.\n */"
4369
+ "signature": "export declare function inProcessClient<App extends {\n fetch(request: Request): Response | Promise<Response>;\n}>(app: App, options?: InProcessClientOptions): InProcessClient<App>;",
4370
+ "doc": "/**\n * A {@link client} whose `fetch` calls a nifra app's own `fetch` in-process — no network, full\n * lifecycle (validation, middleware, contracts). For SSR loaders. Typed from `App` exactly like\n * the network client. The `(url, init) → Request` bridge is required because the client calls\n * `fetch(url, init)` while `app.fetch` takes a `Request`.\n *\n * The returned proxy also implements the explicit symbol-keyed {@link BackendMount} interface, so\n * `createWebApp({ api: inProcessClient(backend) })` can auto-mount the backend while forwarding the\n * outer runtime's `env` and `waitUntil`.\n */"
4183
4371
  },
4184
4372
  {
4185
4373
  "name": "InProcessClient",
@@ -4188,6 +4376,54 @@
4188
4376
  "signature": "export type InProcessClient<App> = Treaty<App> & BackendMount;",
4189
4377
  "doc": "/** Typed route client plus the explicit platform-aware backend mount capability. */"
4190
4378
  },
4379
+ {
4380
+ "name": "InProcessClientOptions",
4381
+ "kind": "interface",
4382
+ "package": "@nifrajs/client",
4383
+ "signature": "export interface InProcessClientOptions extends Omit<ClientOptions, \"fetch\"> {\n /**\n * Assert every JSON response against the route's declared contract — `schema.response` for 2xx,\n * `schema.errors[status]` for declared failures — and THROW on mismatch, so a handler whose real\n * output drifts from its schema fails the test instead of passing silently. Statuses with no\n * declared schema, non-JSON bodies, and 204/205/HEAD pass through unchecked. Test-focused: the\n * check parses a clone of each JSON body, a cost that belongs in tests, not production hot paths.\n */\n readonly validateResponses?: boolean;\n}"
4384
+ },
4385
+ {
4386
+ "name": "INSTALL_EFFECT_LEDGER",
4387
+ "kind": "const",
4388
+ "package": "@nifrajs/core",
4389
+ "signature": "export declare const INSTALL_EFFECT_LEDGER: unique symbol;",
4390
+ "doc": "/** @internal Install the effect-ledger runtime on a server (called by the `effectLedger()` plugin). */"
4391
+ },
4392
+ {
4393
+ "name": "INSTALL_IDEMPOTENCY",
4394
+ "kind": "const",
4395
+ "package": "@nifrajs/core",
4396
+ "signature": "export declare const INSTALL_IDEMPOTENCY: unique symbol;",
4397
+ "doc": "/** @internal Install the idempotency runtime on a server (called by the `idempotency()` plugin). */"
4398
+ },
4399
+ {
4400
+ "name": "INSTALL_MCP",
4401
+ "kind": "const",
4402
+ "package": "@nifrajs/core",
4403
+ "signature": "export declare const INSTALL_MCP: unique symbol;",
4404
+ "doc": "/** @internal Install the MCP runtime on a server (called by the `mcp()` plugin). */"
4405
+ },
4406
+ {
4407
+ "name": "INSTALL_NODE_DIRECT",
4408
+ "kind": "const",
4409
+ "package": "@nifrajs/core",
4410
+ "signature": "export declare const INSTALL_NODE_DIRECT: unique symbol;",
4411
+ "doc": "/** @internal Install the Node-direct renderer on a server (called by the `nodeDirect()` plugin). */"
4412
+ },
4413
+ {
4414
+ "name": "INSTALL_SSE",
4415
+ "kind": "const",
4416
+ "package": "@nifrajs/core",
4417
+ "signature": "export declare const INSTALL_SSE: unique symbol;",
4418
+ "doc": "/** @internal Install the SSE streaming runtime on a server (called by the `sse()` plugin). */"
4419
+ },
4420
+ {
4421
+ "name": "INSTALL_WS",
4422
+ "kind": "const",
4423
+ "package": "@nifrajs/core",
4424
+ "signature": "export declare const INSTALL_WS: unique symbol;",
4425
+ "doc": "/** @internal Install the WebSocket runtime on a server (called by the `websocket()` plugin). */"
4426
+ },
4191
4427
  {
4192
4428
  "name": "installForms",
4193
4429
  "kind": "function",
@@ -4211,26 +4447,8 @@
4211
4447
  "name": "InvariantExecutor",
4212
4448
  "kind": "type",
4213
4449
  "package": "@nifrajs/core",
4214
- "signature": "export type InvariantExecutor = (request: Request) => Response | Promise<Response>;"
4215
- },
4216
- {
4217
- "name": "InvariantFinding",
4218
- "kind": "interface",
4219
- "package": "@nifrajs/core",
4220
- "signature": "export interface InvariantFinding {\n readonly code: InvariantFindingCode;\n readonly method: string;\n readonly path: string;\n /** The case's deterministic seed — rerun with it to reproduce the exact request. */\n readonly seed?: number;\n readonly message: string;\n}"
4221
- },
4222
- {
4223
- "name": "InvariantFindingCode",
4224
- "kind": "type",
4225
- "package": "@nifrajs/core",
4226
- "signature": "export type InvariantFindingCode = \"classification-understated\" | \"server-error-on-valid-input\" | \"response-schema-violation\" | \"validation-bypass\" | \"server-error-on-invalid-input\";",
4227
- "doc": "/**\n * Contract-generated invariant tests: the declared contract *is* the test suite.\n *\n * `runContractInvariants(app)` reads each route's reflected contract (schemas, classification) and\n * verifies, with deterministic seeded fuzzing, the properties the contract already promises:\n *\n * 1. **Classification consistency** (static) — a route whose response fields are tagged more\n * sensitive than its declared route-level classification is understating what it emits.\n * 2. **Valid input never crashes** (dynamic) — schema-generated valid requests must not produce 5xx.\n * 3. **Response conformance** (dynamic) — a 2xx response body must validate against the declared\n * response schema; an undeclared response shape is exactly where sensitive data leaks.\n * 4. **Validation fails closed** (dynamic) — schema-violating bodies must be rejected (4xx), never\n * accepted (2xx) and never crash (5xx).\n *\n * Everything is deterministic: a seeded PRNG (no ambient randomness, no wall clock), so a failing\n * case reproduces from its seed. Routes whose inputs cannot be generated from their JSON Schema are\n * reported in `skipped` — never silently dropped.\n */"
4228
- },
4229
- {
4230
- "name": "InvariantReport",
4231
- "kind": "interface",
4232
- "package": "@nifrajs/core",
4233
- "signature": "export interface InvariantReport {\n readonly ok: boolean;\n /** Routes exercised dynamically. */\n readonly tested: readonly {\n readonly method: string;\n readonly path: string;\n }[];\n /** Routes that could not be exercised, with the reason — reported, never silently dropped. */\n readonly skipped: readonly SkippedRoute[];\n readonly findings: readonly InvariantFinding[];\n}"
4450
+ "signature": "export type InvariantExecutor = (request: Request) => Response | Promise<Response>;",
4451
+ "doc": "/** Isolated request executor used by adversarial contract verification. */"
4234
4452
  },
4235
4453
  {
4236
4454
  "name": "IpMatcher",
@@ -4381,6 +4599,12 @@
4381
4599
  "signature": "export interface ISRApp {\n fetch(req: Request, platform?: ISRPlatform): Response | Promise<Response>;\n}",
4382
4600
  "doc": "/** The app `withISR` wraps — anything with a `fetch(req, platform?)` (a `createWebApp` result). */"
4383
4601
  },
4602
+ {
4603
+ "name": "isResponseResult",
4604
+ "kind": "function",
4605
+ "package": "@nifrajs/core",
4606
+ "signature": "export declare function isResponseResult(value: unknown): value is ResponseResult;"
4607
+ },
4384
4608
  {
4385
4609
  "name": "ISROptions",
4386
4610
  "kind": "interface",
@@ -4401,6 +4625,13 @@
4401
4625
  "signature": "export declare const issue: (message: string) => {\n readonly issues: ReadonlyArray<StandardIssue>;\n};",
4402
4626
  "doc": "/** A single issue. Messages NEVER include the variable's value — it may be a secret. */"
4403
4627
  },
4628
+ {
4629
+ "name": "isUrlEncodedForm",
4630
+ "kind": "function",
4631
+ "package": "@nifrajs/core",
4632
+ "signature": "export declare function isUrlEncodedForm(contentType: string): boolean;",
4633
+ "doc": "/** `application/x-www-form-urlencoded`, with or without a charset suffix. */"
4634
+ },
4404
4635
  {
4405
4636
  "name": "JobContext",
4406
4637
  "kind": "interface",
@@ -4469,6 +4700,13 @@
4469
4700
  "signature": "export declare function joinCausality(parents: readonly CausalityContext[], nodeKind: CausalityKind, id: string, options?: ContinueCausalityOptions): CausalityStep;",
4470
4701
  "doc": "/** Join several immediate parents. Cross-execution joins fail closed. */"
4471
4702
  },
4703
+ {
4704
+ "name": "jsonError",
4705
+ "kind": "function",
4706
+ "package": "@nifrajs/core",
4707
+ "signature": "export declare function jsonError(status: number, error: string, headers?: Record<string, string>): Response;",
4708
+ "doc": "/** A uniform JSON error envelope: `{ ok: false, error }` at the given status. */"
4709
+ },
4472
4710
  {
4473
4711
  "name": "jsonError",
4474
4712
  "kind": "function",
@@ -4521,6 +4759,13 @@
4521
4759
  "signature": "export type JsonSchema = boolean | Readonly<Record<string, unknown>>;",
4522
4760
  "doc": "/** JSON Schema permits either a schema object or the boolean schemas `true` and `false`. */"
4523
4761
  },
4762
+ {
4763
+ "name": "jsonSchemaOf",
4764
+ "kind": "function",
4765
+ "package": "@nifrajs/mcp",
4766
+ "signature": "export declare function jsonSchemaOf(schema: StandardSchemaV1): Record<string, unknown> | undefined;",
4767
+ "doc": "/**\n * The wire JSON Schema of a Standard Schema, when it carries one. nifra's `t` schemas ARE\n * JSON Schema (exposed as `.jsonSchema`), so tools authored with `t` advertise a full\n * `inputSchema` for free. Schemas from other vendors return `undefined` - pass an explicit\n * `inputSchema` alongside `input` for those.\n */"
4768
+ },
4524
4769
  {
4525
4770
  "name": "jwk",
4526
4771
  "kind": "function",
@@ -4631,7 +4876,7 @@
4631
4876
  "name": "language",
4632
4877
  "kind": "function",
4633
4878
  "package": "@nifrajs/middleware",
4634
- "signature": "export declare function language<const L extends readonly string[]>(options: LanguageOptions<L>): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").Server<any, any>>;",
4879
+ "signature": "export declare function language<const L extends readonly string[]>(options: LanguageOptions<L>): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").Server<any, any>>;",
4635
4880
  "doc": "/**\n * Derives `c.language` from `Accept-Language` and emits `Content-Language` by default.\n */"
4636
4881
  },
4637
4882
  {
@@ -4839,7 +5084,7 @@
4839
5084
  "name": "logger",
4840
5085
  "kind": "function",
4841
5086
  "package": "@nifrajs/middleware",
4842
- "signature": "export declare function logger(options?: LoggerOptions): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").AnyServer>;",
5087
+ "signature": "export declare function logger(options?: LoggerOptions): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").AnyServer>;",
4843
5088
  "doc": "/**\n * A {@link definePlugin} plugin that logs one structured line per request — method, path, status,\n * and duration — via `onRequest`/`onResponse` (so it covers 404s and errors too). The start time is\n * paired to the request through a `WeakMap` (no per-request allocation leak). Idempotent.\n */"
4844
5089
  },
4845
5090
  {
@@ -4937,12 +5182,25 @@
4937
5182
  "signature": "export declare function maxClassification(values: Iterable<DataClassification>): DataClassification;",
4938
5183
  "doc": "/** The most sensitive classification among the inputs; `\"public\"` when none are given. */"
4939
5184
  },
5185
+ {
5186
+ "name": "MaybePromise",
5187
+ "kind": "type",
5188
+ "package": "@nifrajs/core",
5189
+ "signature": "export type MaybePromise<T> = T | Promise<T>;"
5190
+ },
4940
5191
  {
4941
5192
  "name": "MaybePromise",
4942
5193
  "kind": "type",
4943
5194
  "package": "@nifrajs/middleware",
4944
5195
  "signature": "export type MaybePromise<T> = T | Promise<T>;"
4945
5196
  },
5197
+ {
5198
+ "name": "mcp",
5199
+ "kind": "function",
5200
+ "package": "@nifrajs/core",
5201
+ "signature": "export declare function mcp(): IdentityPlugin;",
5202
+ "doc": "/**\n * Enable MCP declarations on a server: `.use(mcp())` turns on `.tool()`, `.resource()`, and\n * `.prompt()`. Applying it twice is a no-op (named plugin dedupe).\n */"
5203
+ },
4946
5204
  {
4947
5205
  "name": "MCP_CLI_VERSION",
4948
5206
  "kind": "const",
@@ -5035,7 +5293,7 @@
5035
5293
  "kind": "interface",
5036
5294
  "package": "@nifrajs/core",
5037
5295
  "signature": "export interface McpPromptDescriptor {\n readonly name: string;\n readonly description: string;\n readonly arguments?: readonly PromptArgument[];\n readonly handler: (args: Record<string, string>) => MaybePromise<readonly PromptMessage[]>;\n}",
5038
- "doc": "/** An app-declared MCP prompt — a reusable prompt template an agent can fetch through `nifra mcp`. */"
5296
+ "doc": "/** An app-declared MCP prompt - a reusable prompt template an agent can fetch through `nifra mcp`. */"
5039
5297
  },
5040
5298
  {
5041
5299
  "name": "McpPromptMessage",
@@ -5066,7 +5324,13 @@
5066
5324
  "kind": "interface",
5067
5325
  "package": "@nifrajs/core",
5068
5326
  "signature": "export interface McpResourceDescriptor {\n readonly uri: string;\n readonly name: string;\n readonly description?: string;\n readonly mimeType?: string;\n readonly read: () => MaybePromise<string | {\n readonly text: string;\n readonly mimeType?: string;\n }>;\n}",
5069
- "doc": "/** An app-declared MCP resource — read-only data an agent can fetch through `nifra mcp`. */"
5327
+ "doc": "/** An app-declared MCP resource - read-only data an agent can fetch through `nifra mcp`. */"
5328
+ },
5329
+ {
5330
+ "name": "McpRuntime",
5331
+ "kind": "interface",
5332
+ "package": "@nifrajs/core",
5333
+ "signature": "export interface McpRuntime {\n tool(name: string, config: McpToolConfig, handler: (input: unknown, context: Context) => unknown): McpToolPlan;\n resource(uri: string, config: {\n readonly name: string;\n readonly description?: string;\n readonly mimeType?: string;\n }, read: McpResourceDescriptor[\"read\"]): McpResourceDescriptor;\n prompt(name: string, config: {\n readonly description: string;\n readonly arguments?: readonly PromptArgument[];\n }, handler: McpPromptDescriptor[\"handler\"]): McpPromptDescriptor;\n}"
5070
5334
  },
5071
5335
  {
5072
5336
  "name": "McpServer",
@@ -5100,6 +5364,12 @@
5100
5364
  "signature": "export interface McpToolAnnotations {\n readonly title?: string;\n readonly readOnlyHint?: boolean;\n readonly destructiveHint?: boolean;\n readonly idempotentHint?: boolean;\n readonly openWorldHint?: boolean;\n}",
5101
5365
  "doc": "/** MCP tool safety hints (`readOnlyHint`/`destructiveHint`/…) surfaced in `tools/list`, per the MCP spec. */"
5102
5366
  },
5367
+ {
5368
+ "name": "McpToolConfig",
5369
+ "kind": "interface",
5370
+ "package": "@nifrajs/core",
5371
+ "signature": "export interface McpToolConfig {\n readonly description: string;\n readonly input: StandardSchemaV1;\n readonly output?: StandardSchemaV1;\n readonly annotations?: ToolAnnotations;\n}"
5372
+ },
5103
5373
  {
5104
5374
  "name": "McpToolContext",
5105
5375
  "kind": "interface",
@@ -5113,6 +5383,12 @@
5113
5383
  "signature": "export type McpToolHandlerResult = string | {\n /** Model-facing text (becomes a single text content block when `content` is omitted). */\n readonly text?: string;\n /** Explicit content blocks (overrides `text`). */\n readonly content?: readonly McpContentBlock[];\n /** Structured data for the linked widget — NOT added to the model's context. */\n readonly structuredContent?: Record<string, unknown>;\n readonly _meta?: Record<string, unknown>;\n readonly isError?: boolean;\n};",
5114
5384
  "doc": "/** The ergonomic result an MCP-tool handler may return (coerced to the protocol's {@link McpToolResult}). */"
5115
5385
  },
5386
+ {
5387
+ "name": "McpToolPlan",
5388
+ "kind": "interface",
5389
+ "package": "@nifrajs/core",
5390
+ "signature": "export interface McpToolPlan {\n readonly path: string;\n readonly schema: RouteSchema;\n readonly run: (context: Context) => unknown;\n readonly descriptor: NonNullable<RouteDescriptor[\"tool\"]>;\n}"
5391
+ },
5116
5392
  {
5117
5393
  "name": "McpToolResult",
5118
5394
  "kind": "interface",
@@ -5279,7 +5555,7 @@
5279
5555
  "name": "MetaArgs",
5280
5556
  "kind": "interface",
5281
5557
  "package": "@nifrajs/web",
5282
- "signature": "export interface MetaArgs<Data = unknown> {\n readonly data: Data;\n readonly params: Record<string, string>;\n /**\n * The site origin — scheme + host (+ port), e.g. `\"https://news.example.com\"`, **with no trailing\n * slash**. The single piece of server/env knowledge `meta()` otherwise can't see: it runs in BOTH\n * SSR and client navigation, so it has no `request`/`process.env`. The framework resolves it from the\n * request URL during SSR and from `location.origin` on client nav — and they match, so an absolute\n * `og:url`/`canonical`/`og:image` built from it never drifts between the server-rendered `<head>` and\n * a soft-nav. Use it for absolute URLs (`origin + \"/posts/\" + slug`) instead of threading `siteUrl`\n * through loader data. Empty string (`\"\"`) when the origin is unknown (e.g. a hand-built test render\n * with no request URL) — back-compat-safe: a `meta()` that ignores `origin` is unchanged.\n */\n readonly origin: string;\n}",
5558
+ "signature": "export interface MetaArgs<Data = unknown> {\n readonly data: Data;\n readonly params: Record<string, string>;\n /**\n * The site origin — scheme + host (+ port), e.g. `\"https://news.example.com\"`, **with no trailing\n * slash**. The single piece of server/env knowledge `meta()` otherwise can't see: it runs in BOTH\n * SSR and client navigation, so it has no `request`/`process.env`. The framework resolves it from the\n * request URL during SSR and from `location.origin` on client nav — and they match, so an absolute\n * `og:url`/`canonical`/`og:image` built from it never drifts between the server-rendered `<head>` and\n * a soft-nav. Use it for absolute URLs (`origin + \"/posts/\" + slug`) instead of threading `siteUrl`\n * through loader data. Empty string (`\"\"`) when the origin is unknown (e.g. a hand-built test render\n * with no request URL). A `meta()` that ignores `origin` is unchanged.\n */\n readonly origin: string;\n}",
5283
5559
  "doc": "/**\n * Args for a route's `meta` function: the loader's `data` + the route `params` + the request `origin`.\n * `meta()` runs in BOTH SSR and client navigation, so it has **no `request`/`process.env`/server access** —\n * `origin` is the only server-resolved fact it gets (so you needn't thread `siteUrl` through loader data\n * for absolute `og:url`/`canonical`/`og:image` URLs). See {@link origin}.\n */"
5284
5560
  },
5285
5561
  {
@@ -5299,14 +5575,14 @@
5299
5575
  "name": "methodOverride",
5300
5576
  "kind": "function",
5301
5577
  "package": "@nifrajs/middleware",
5302
- "signature": "export declare function methodOverride(options?: MethodOverrideOptions): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").AnyServer>;",
5578
+ "signature": "export declare function methodOverride(options?: MethodOverrideOptions): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").AnyServer>;",
5303
5579
  "doc": "/**\n * HTTP method override for clients that can only send `POST`. The middleware rewrites the request\n * before routing, so handlers, validation, and response hooks all see the overridden method.\n *\n * Header override is enabled by default; query override is opt-in. Form-body override is deliberately\n * not implemented because reading the body before routing would consume or buffer it for every write.\n */"
5304
5580
  },
5305
5581
  {
5306
5582
  "name": "MethodOverrideOptions",
5307
5583
  "kind": "interface",
5308
5584
  "package": "@nifrajs/middleware",
5309
- "signature": "export interface MethodOverrideOptions {\n /**\n * Header carrying the desired method. Default `\"x-http-method-override\"`.\n * Set `false` to disable header-based override.\n */\n readonly header?: string | false;\n /**\n * Query parameter carrying the desired method. Disabled by default because query-tunneled writes are\n * easier to trigger accidentally from links/forms. Use only with CSRF protection on browser routes.\n */\n readonly query?: string | false;\n /** Original request methods allowed to tunnel. Default `[\"POST\"]`. */\n readonly methods?: readonly string[];\n /** Target methods accepted from the override source. Default `[\"PUT\", \"PATCH\", \"DELETE\"]`. */\n readonly allowed?: readonly Method[];\n /** Invalid override values reject with `400` by default. Use `\"ignore\"` for legacy clients. */\n readonly onInvalid?: \"reject\" | \"ignore\";\n}"
5585
+ "signature": "export interface MethodOverrideOptions {\n /**\n * Header carrying the desired method. Default `\"x-http-method-override\"`.\n * Set `false` to disable header-based override.\n */\n readonly header?: string | false;\n /**\n * Query parameter carrying the desired method. Disabled by default because query-tunneled writes are\n * easier to trigger accidentally from links/forms. Use only with CSRF protection on browser routes.\n */\n readonly query?: string | false;\n /** Original request methods allowed to tunnel. Default `[\"POST\"]`. */\n readonly methods?: readonly string[];\n /** Target methods accepted from the override source. Default `[\"PUT\", \"PATCH\", \"DELETE\"]`. */\n readonly allowed?: readonly Method[];\n}"
5310
5586
  },
5311
5587
  {
5312
5588
  "name": "METHODS",
@@ -5315,12 +5591,32 @@
5315
5591
  "signature": "export declare const METHODS: readonly [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"HEAD\", \"OPTIONS\"];",
5316
5592
  "doc": "/** HTTP methods the router accepts. */"
5317
5593
  },
5594
+ {
5595
+ "name": "metrics",
5596
+ "kind": "function",
5597
+ "package": "@nifrajs/otel",
5598
+ "signature": "export declare function metrics(options?: MetricsOptions): NifraPlugin;",
5599
+ "doc": "/**\n * Enable RED metrics + a `/metrics` Prometheus endpoint. Records `nifra_http_requests_total`,\n * `nifra_http_request_duration_seconds`, and `nifra_http_requests_in_flight`, labeled by method,\n * matched route template, and status. Apply once (named-plugin dedupe).\n */"
5600
+ },
5601
+ {
5602
+ "name": "MetricsOptions",
5603
+ "kind": "interface",
5604
+ "package": "@nifrajs/otel",
5605
+ "signature": "export interface MetricsOptions {\n /** Where to expose the Prometheus text. Default `/metrics`. This route is excluded from the metrics. */\n readonly path?: string;\n /** Reuse a registry (so custom app metrics render alongside the RED series). Default: a fresh one. */\n readonly registry?: MetricsRegistry;\n /** Histogram buckets in SECONDS for request duration. Default OpenTelemetry latency buckets. */\n readonly buckets?: readonly number[];\n}"
5606
+ },
5607
+ {
5608
+ "name": "MetricsRegistry",
5609
+ "kind": "class",
5610
+ "package": "@nifrajs/otel",
5611
+ "signature": "export declare class MetricsRegistry {\n private readonly counters;\n private readonly gauges;\n private readonly histograms;\n counter(name: string, help?: string): Counter;\n gauge(name: string, help?: string): Gauge;\n histogram(name: string, buckets: readonly number[], help?: string): Histogram;\n /** The Prometheus text exposition of every registered series. */\n render(): string;\n}",
5612
+ "doc": "/** A collection of metrics that renders one Prometheus exposition document. */"
5613
+ },
5318
5614
  {
5319
5615
  "name": "Middleware",
5320
5616
  "kind": "interface",
5321
5617
  "package": "@nifrajs/core",
5322
5618
  "signature": "export interface Middleware {\n readonly name?: string;\n readonly onRequest?: (req: Request, platform?: Platform) => MaybePromise<OnRequestResult>;\n readonly around?: <T>(context: Context, next: () => MaybePromise<T>) => MaybePromise<T>;\n readonly beforeHandle?: (context: Context) => MaybePromise<unknown>;\n readonly afterHandle?: (result: unknown, context: Context) => MaybePromise<unknown>;\n readonly onResponse?: (response: Response, req: Request) => MaybePromise<Response>;\n readonly onResponseFinalized?: (outcome: ResponseFinalization, req: Request) => MaybePromise<void>;\n readonly onError?: (error: unknown, context: Context) => MaybePromise<unknown>;\n}",
5323
- "doc": "/**\n * A bundle of lifecycle hooks applied together via {@link Server.use} — the unit\n * `@nifrajs/middleware` ships (cors, security headers, rate-limit). Every hook is\n * optional and wired to its lifecycle point. Middleware is context-agnostic (sees\n * the base `Context`); `use` does no context-type merging — the full type-merging\n * plugin system is deferred, and `.use` is reserved as its future entry point.\n */"
5619
+ "doc": "/**\n * A bundle of lifecycle hooks applied together via {@link Server.use} - the unit\n * `@nifrajs/middleware` ships (cors, security headers, rate-limit). Every hook is\n * optional and wired to its lifecycle point. Middleware is context-agnostic (sees\n * the base `Context`); `use` does no context-type merging - the full type-merging\n * plugin system is deferred, and `.use` is reserved as its future entry point.\n */"
5324
5620
  },
5325
5621
  {
5326
5622
  "name": "MIN_DIGEST_KEY_BYTES",
@@ -5432,6 +5728,13 @@
5432
5728
  "signature": "export interface MovableStorageAdapter extends StorageAdapter {\n copy(sourceKey: string, destinationKey: string): Promise<void>;\n move(sourceKey: string, destinationKey: string): Promise<void>;\n}",
5433
5729
  "doc": "/** Optional server-side copy/move capability. */"
5434
5730
  },
5731
+ {
5732
+ "name": "moveDependenciesText",
5733
+ "kind": "function",
5734
+ "package": "@nifrajs/cli",
5735
+ "signature": "export declare function moveDependenciesText(text: string, moves: readonly {\n from: string;\n to: string;\n toVersion: string;\n}[]): {\n text: string;\n changes: Array<Omit<DependencyMoveChange, \"file\">>;\n};",
5736
+ "doc": "/** Move removed package dependencies without reserializing or reordering package.json. */"
5737
+ },
5435
5738
  {
5436
5739
  "name": "MutationCallbacks",
5437
5740
  "kind": "interface",
@@ -5495,6 +5798,13 @@
5495
5798
  "signature": "export interface NavigateProps {\n readonly to: string;\n readonly replace?: boolean;\n}",
5496
5799
  "doc": "/** {@link Navigate} props: the destination `to` and whether to `replace` the history entry. */"
5497
5800
  },
5801
+ {
5802
+ "name": "Navigation",
5803
+ "kind": "interface",
5804
+ "package": "@nifrajs/web-react",
5805
+ "signature": "export interface Navigation {\n /** True while a client navigation (or revalidation) is in flight. The current route stays mounted\n * until the new one is ready, so this drives a loading indicator, not a route swap. */\n readonly pending: boolean;\n /** `\"loading\"` while a navigation is in flight, else `\"idle\"`. */\n readonly state: \"idle\" | \"loading\";\n /** The `pathname + search` being navigated TO while `pending`; `undefined` when idle or during a\n * same-route revalidation. Mirrors Remix's `useNavigation().location`. */\n readonly location: string | undefined;\n}",
5806
+ "doc": "/** The current navigation state, mirroring the Remix `useNavigation()` shape for familiarity. */"
5807
+ },
5498
5808
  {
5499
5809
  "name": "NavLink",
5500
5810
  "kind": "const",
@@ -5513,7 +5823,7 @@
5513
5823
  "name": "NavLinkRenderProps",
5514
5824
  "kind": "interface",
5515
5825
  "package": "@nifrajs/web-react",
5516
- "signature": "export interface NavLinkRenderProps {\n /** True when the current location matches this link's `to` (prefix match, or exact when `end`). */\n readonly isActive: boolean;\n /** Reserved for a future pending-navigation signal; currently always `false`. */\n readonly isPending: boolean;\n}",
5826
+ "signature": "export interface NavLinkRenderProps {\n /** True when the current location matches this link's `to` (prefix match, or exact when `end`). */\n readonly isActive: boolean;\n /** True while a client navigation to THIS link's target is in flight (matched like `isActive`).\n * `false` on SSR and when idle. Use it to show a per-link spinner during the transition. */\n readonly isPending: boolean;\n}",
5517
5827
  "doc": "/** The state a {@link NavLink}'s function-form `className`/`style`/`children` receive. */"
5518
5828
  },
5519
5829
  {
@@ -5637,7 +5947,7 @@
5637
5947
  "kind": "type",
5638
5948
  "package": "@nifrajs/core",
5639
5949
  "signature": "export type NifraPlugin<In extends AnyServer = AnyServer, Out extends AnyServer = In> = ((app: In) => Out) & {\n readonly pluginName?: string;\n};",
5640
- "doc": "/**\n * A nifra **plugin**: a function that augments an app — calling `use`/`derive`/`decorate` and/or\n * registering routes — and returns it. Because `derive`/`decorate` are type-threaded, an **inline**\n * `app.use((a) => a.derive(...).decorate(...))` carries the added context to handlers defined after\n * it (the `use` overload is generic over the concrete `this`). Wrap with {@link definePlugin} to\n * attach a name for idempotent dedupe (applying the same named plugin twice — e.g. transitively — is\n * a no-op).\n */"
5950
+ "doc": "/**\n * A nifra **plugin**: a function that augments an app - calling `use`/`derive`/`decorate` and/or\n * registering routes - and returns it. Because `derive`/`decorate` are type-threaded, an **inline**\n * `app.use((a) => a.derive(...).decorate(...))` carries the added context to handlers defined after\n * it (the `use` overload is generic over the concrete `this`). Wrap with {@link definePlugin} to\n * attach a name for idempotent dedupe (applying the same named plugin twice - e.g. transitively - is\n * a no-op).\n */"
5641
5951
  },
5642
5952
  {
5643
5953
  "name": "NifraSchema",
@@ -5668,7 +5978,14 @@
5668
5978
  "doc": "/** The portable socket handed to WS lifecycle callbacks. Each adapter wraps its native socket. */"
5669
5979
  },
5670
5980
  {
5671
- "name": "noBackoff",
5981
+ "name": "NO_SOCKET",
5982
+ "kind": "const",
5983
+ "package": "@nifrajs/client",
5984
+ "signature": "export declare const NO_SOCKET: unique symbol;",
5985
+ "doc": "/** Internal handshake between `inProcessClient` and the proxy: in-process apps have no socket. */"
5986
+ },
5987
+ {
5988
+ "name": "noBackoff",
5672
5989
  "kind": "const",
5673
5990
  "package": "@nifrajs/jobs",
5674
5991
  "signature": "export declare const noBackoff: Backoff;",
@@ -5681,12 +5998,31 @@
5681
5998
  "signature": "export interface NodeBuiltinFinding {\n readonly builtin: string;\n readonly chunk: string;\n /** The shortest import path from a user entry to the builtin, as a list of display labels:\n * `[entryFile, ...as-written specifiers along the way, builtin]`, e.g.\n * `[\"routes/article/[slug].tsx\", \"../data.ts\", \"../db/client.ts\", \"postgres\", \"node:tls\"]`. The\n * entry is its graph key (the route file); each hop is the import's *as-written* specifier; the tail\n * is the builtin. Empty only if the builtin module isn't reachable from any traced input (it always\n * is when flagged). */\n readonly chain: readonly string[];\n}",
5682
5999
  "doc": "/** One `node:`-builtin-in-the-client finding: the offending builtin, the emitted chunk it landed in,\n * and the shortest USER-module import chain that pulled it there (entry → … → builtin). */"
5683
6000
  },
6001
+ {
6002
+ "name": "nodeDirect",
6003
+ "kind": "function",
6004
+ "package": "@nifrajs/core",
6005
+ "signature": "export declare function nodeDirect(): IdentityPlugin;",
6006
+ "doc": "/** Enable `app.resolveNode()` for direct callers. Applying it twice is a no-op (named plugin dedupe). */"
6007
+ },
6008
+ {
6009
+ "name": "nodeOutcomeFromResponse",
6010
+ "kind": "function",
6011
+ "package": "@nifrajs/core",
6012
+ "signature": "export declare function nodeOutcomeFromResponse(response: Response): NodeServeOutcome;"
6013
+ },
6014
+ {
6015
+ "name": "NodeOutcomeRuntime",
6016
+ "kind": "interface",
6017
+ "package": "@nifrajs/core",
6018
+ "signature": "export interface NodeOutcomeRuntime {\n toOutcome(result: unknown, set: CtxSet): NodeServeOutcome;\n fromResponse(response: Response): NodeServeOutcome;\n timeout(): NodeServeOutcome;\n}"
6019
+ },
5684
6020
  {
5685
6021
  "name": "NodeServeOutcome",
5686
6022
  "kind": "type",
5687
6023
  "package": "@nifrajs/core",
5688
6024
  "signature": "export type NodeServeOutcome = {\n readonly kind: \"response\";\n readonly response: Response;\n} | {\n readonly kind: \"json\";\n readonly status: number;\n /** `c.set.headers` backing, or `undefined` when the handler never set a header. */\n readonly headers: Readonly<Record<string, string>> | undefined;\n /** Queued `Set-Cookie` lines, or `undefined`; the adapter emits one header line each. */\n readonly cookies: readonly string[] | undefined;\n /** The JSON body already stringified, or `null` for an empty (204) response. */\n readonly body: string | null;\n} | {\n readonly kind: \"body\";\n readonly status: number;\n readonly headers: Readonly<Record<string, string | readonly string[]>> | undefined;\n readonly body: string | Uint8Array;\n};",
5689
- "doc": "/**\n * What {@link Server.resolveNode} returns: either a plain-data render the `@nifrajs/node` adapter writes\n * to the socket directly (`kind: \"json\"` — status + headers + cookies + a pre-stringified body, **no**\n * undici `Response` built or drained), a marked buffered response body (`kind: \"body\"` — e.g.\n * @nifrajs/web's non-deferred SSR HTML), or a `Response` (`kind: \"response\"`) for everything else\n * (redirects, 404/405/errors, unmarked or streaming bodies). Internal to the nifra↔node bridge.\n */"
6025
+ "doc": "/**\n * What {@link Server.resolveNode} returns: either a plain-data render the `@nifrajs/node` adapter writes\n * to the socket directly (`kind: \"json\"` - status + headers + cookies + a pre-stringified body, **no**\n * undici `Response` built or drained), a marked buffered response body (`kind: \"body\"` - e.g.\n * @nifrajs/web's non-deferred SSR HTML), or a `Response` (`kind: \"response\"`) for everything else\n * (redirects, 404/405/errors, unmarked or streaming bodies). Internal to the nifra<->node bridge.\n */"
5690
6026
  },
5691
6027
  {
5692
6028
  "name": "NodeServer",
@@ -5768,7 +6104,7 @@
5768
6104
  "name": "openapi",
5769
6105
  "kind": "function",
5770
6106
  "package": "@nifrajs/middleware",
5771
- "signature": "export declare function openapi(options?: OpenApiOptions): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").AnyServer>;",
6107
+ "signature": "export declare function openapi(options?: OpenApiOptions): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").AnyServer>;",
5772
6108
  "doc": "/**\n * Serve an OpenAPI 3.1 document (a structural subset — see {@link buildOpenApiDocument}) at\n * `options.path` (default `/openapi.json`), generated from the app's registered routes. Generation is\n * **lazy + memoized**: it reads `app.routes()` on the first request, by which point every route is\n * registered — so the plugin's own position in the chain doesn't matter.\n *\n * Pass `ui: true` (or `ui: { path, title, cdn }`) to also serve a Scalar API-reference page (default\n * `/reference`) that renders the spec. The page loads Scalar from a CDN; pin/self-host via `ui.cdn`,\n * and remember to allow that origin if you ship a `script-src` Content-Security-Policy.\n *\n * ```ts\n * app.use(openapi({ info: { title: \"My API\", version: \"1.0.0\" }, ui: true }))\n * ```\n */"
5773
6109
  },
5774
6110
  {
@@ -5847,11 +6183,17 @@
5847
6183
  "signature": "export interface OpenGraphInput {\n readonly title?: string;\n readonly description?: string;\n /** Absolute URL of the share image (`og:image`). */\n readonly image?: string;\n /** Canonical URL of the page (`og:url`). */\n readonly url?: string;\n /** Object type (`og:type`) — `\"website\"`, `\"article\"`, … Default `\"website\"`. */\n readonly type?: string;\n}",
5848
6184
  "doc": "/** Inputs for {@link openGraph} — the common Open Graph properties. All optional; only the provided\n * ones become tags. `type` defaults to `\"website\"`. */"
5849
6185
  },
6186
+ {
6187
+ "name": "openWebSocket",
6188
+ "kind": "function",
6189
+ "package": "@nifrajs/client",
6190
+ "signature": "export declare function openWebSocket(base: string, path: string, callOptions: WsRuntimeOptions | undefined, noSocket: boolean): WsHandle<unknown, unknown>;"
6191
+ },
5850
6192
  {
5851
6193
  "name": "OperationDef",
5852
6194
  "kind": "interface",
5853
6195
  "package": "@nifrajs/core",
5854
- "signature": "export interface OperationDef {\n readonly method: Method;\n readonly path: string;\n readonly body?: StandardSchemaV1;\n readonly query?: StandardSchemaV1;\n readonly response?: StandardSchemaV1;\n /** Declared effect tokens, carried into route reflection and capability assurance. */\n readonly capabilities?: readonly string[];\n /** Dedupe retries of this operation on an `Idempotency-Key` header (see {@link RouteSchema.idempotency}). */\n readonly idempotency?: IdempotencyConfig;\n /** Highest data-sensitivity the response carries (see {@link RouteSchema.classification}). */\n readonly classification?: DataClassification;\n /** Short summary (OpenAPI `summary`). */\n readonly summary?: string;\n /** Longer description (OpenAPI `description`, CommonMark). */\n readonly description?: string;\n /** Grouping tags (OpenAPI `tags`). */\n readonly tags?: readonly string[];\n /** Mark the operation deprecated. */\n readonly deprecated?: boolean;\n /** Security requirements (names ref `securitySchemes`); `[]` = explicitly public. Omit ⇒ inherit the document default. */\n readonly security?: ReadonlyArray<Readonly<Record<string, readonly string[]>>>;\n /** Request body content type. Default `application/json`. */\n readonly requestContentType?: string;\n /** Content type of the success (`200`) response. Default `application/json`. */\n readonly responseContentType?: string;\n /** Additional responses by status code, e.g. `{ \"404\": { description: \"Not found\" } }`. */\n readonly responses?: Readonly<Record<string, ResponseDef>>;\n}",
6196
+ "signature": "export interface OperationDef {\n readonly method: Method;\n readonly path: string;\n /** Optional path-params schema (validated + coercible at the boundary; see {@link RouteSchema.params}). */\n readonly params?: StandardSchemaV1;\n readonly body?: StandardSchemaV1;\n readonly query?: StandardSchemaV1;\n readonly response?: StandardSchemaV1;\n /** Declared effect tokens, carried into route reflection and capability assurance. */\n readonly capabilities?: readonly string[];\n /** Dedupe retries of this operation on an `Idempotency-Key` header (see {@link RouteSchema.idempotency}). */\n readonly idempotency?: IdempotencyConfig;\n /** Highest data-sensitivity the response carries (see {@link RouteSchema.classification}). */\n readonly classification?: DataClassification;\n /** Inline route-assurance evidence this operation carries (see {@link RouteSchema.assurance}). */\n readonly assurance?: readonly string[];\n /** Mark this operation a dynamic route family (see {@link RouteSchema.family}). */\n readonly family?: boolean;\n /** Short summary (OpenAPI `summary`). */\n readonly summary?: string;\n /** Longer description (OpenAPI `description`, CommonMark). */\n readonly description?: string;\n /** Grouping tags (OpenAPI `tags`). */\n readonly tags?: readonly string[];\n /** Mark the operation deprecated. */\n readonly deprecated?: boolean;\n /** Security requirements (names ref `securitySchemes`); `[]` = explicitly public. Omit ⇒ inherit the document default. */\n readonly security?: ReadonlyArray<Readonly<Record<string, readonly string[]>>>;\n /** Request body content type. Default `application/json`. */\n readonly requestContentType?: string;\n /** Content type of the success (`200`) response. Default `application/json`. */\n readonly responseContentType?: string;\n /** Additional responses by status code, e.g. `{ \"404\": { description: \"Not found\" } }`. */\n readonly responses?: Readonly<Record<string, ResponseDef>>;\n}",
5855
6197
  "doc": "/**\n * One operation in a contract. Input schemas are any Standard Schema; `response` is optional.\n *\n * The fields below `response` are **optional OpenAPI metadata** — they don't affect runtime\n * validation or the inferred handler types, they enrich the document `toOpenAPI` emits. A contract is\n * the natural home for them: it's the versionable description of the API, decoupled from the impl.\n */"
5856
6198
  },
5857
6199
  {
@@ -5861,6 +6203,24 @@
5861
6203
  "signature": "export type Orm = \"drizzle\" | \"prisma\" | \"kysely\";",
5862
6204
  "doc": "/** ORM family of a preset — drives the auth adapter, the AGENTS DB rules, and the `c.db` query idiom. */"
5863
6205
  },
6206
+ {
6207
+ "name": "otlpExporter",
6208
+ "kind": "function",
6209
+ "package": "@nifrajs/otel",
6210
+ "signature": "export declare function otlpExporter(options: OtlpExporterOptions): OtlpExporter;"
6211
+ },
6212
+ {
6213
+ "name": "OtlpExporter",
6214
+ "kind": "interface",
6215
+ "package": "@nifrajs/otel",
6216
+ "signature": "export interface OtlpExporter extends ObservationAdapter {\n /** Send everything queued now. Await it in a graceful shutdown so no span is lost. */\n flush(): Promise<void>;\n /** Stop the periodic timer and flush a final time. Call on server stop. */\n shutdown(): Promise<void>;\n}"
6217
+ },
6218
+ {
6219
+ "name": "OtlpExporterOptions",
6220
+ "kind": "interface",
6221
+ "package": "@nifrajs/otel",
6222
+ "signature": "export interface OtlpExporterOptions {\n /** The collector's traces endpoint, e.g. `http://localhost:4318/v1/traces`. */\n readonly url: string;\n /** Extra headers on every export (auth tokens, tenant ids). */\n readonly headers?: Record<string, string>;\n /** `service.name` resource attribute. Default `\"nifra\"`. */\n readonly serviceName?: string;\n /** Batching knobs. */\n readonly batch?: {\n /** Flush once this many spans are queued. Must be a positive safe integer. Default 512. */\n readonly maxBatch?: number;\n /** Hard cap on the queue; oldest spans are dropped past it. Positive safe integer; default 2048. */\n readonly maxQueue?: number;\n /** Periodic flush interval (ms). Must be a positive safe integer. Default 5000. */\n readonly flushIntervalMs?: number;\n };\n /** Called when an export POST fails or spans are dropped. Fail-open: never throws into a request. */\n readonly onError?: (error: unknown) => void;\n /** Override `fetch` (tests, a proxy agent). Defaults to the global. */\n readonly fetch?: (input: string, init: RequestInit) => Promise<{\n ok: boolean;\n status: number;\n }>;\n}"
6223
+ },
5864
6224
  {
5865
6225
  "name": "OutputFormat",
5866
6226
  "kind": "type",
@@ -6024,6 +6384,20 @@
6024
6384
  "signature": "export declare function parseManifestRouteFiles(source: string, routesPrefix?: string): string[];",
6025
6385
  "doc": "/**\n * Extract the route-relative file list the committed server-manifest imports, normalized to the same\n * `routes/`-relative keys `discoverRoutes` produces (e.g. `docs/index.tsx`). `routesPrefix` is the\n * specifier prefix the manifest used for the routes dir (default `./routes/`, what `buildServer`'s\n * default `resolve` emits). Only import specifiers under that prefix are route files; the\n * `@nifrajs/web` import (and any other bare specifier) is ignored. Pure — operates on source text.\n */"
6026
6386
  },
6387
+ {
6388
+ "name": "parseManifestRouteStyles",
6389
+ "kind": "function",
6390
+ "package": "@nifrajs/web",
6391
+ "signature": "export declare function parseManifestRouteStyles(source: string): Record<string, string[]>;",
6392
+ "doc": "/** The baked per-route `routeStyles` map in a committed server-manifest (empty if absent/unparseable). Pure. */"
6393
+ },
6394
+ {
6395
+ "name": "parseManifestStyles",
6396
+ "kind": "function",
6397
+ "package": "@nifrajs/web",
6398
+ "signature": "export declare function parseManifestStyles(source: string): string[];",
6399
+ "doc": "/** The baked top-level `styles` array in a committed server-manifest (empty if absent/unparseable). Pure. */"
6400
+ },
6027
6401
  {
6028
6402
  "name": "parseNdjsonData",
6029
6403
  "kind": "function",
@@ -6110,7 +6484,7 @@
6110
6484
  "name": "Platform",
6111
6485
  "kind": "interface",
6112
6486
  "package": "@nifrajs/core",
6113
- "signature": "export interface Platform<Env = unknown> {\n /** Platform bindings (KV/D1/secrets on Workers). Typed as `Env` when the app declares them via\n * `server<Env>()`; otherwise `unknown` — validate before use. */\n readonly env?: Env;\n /** Extend the response's lifetime for background work (Workers `ctx.waitUntil`). */\n readonly waitUntil?: (promise: Promise<unknown>) => void;\n}",
6487
+ "signature": "export interface Platform<Env = unknown> {\n /** Platform bindings (KV/D1/secrets on Workers). Typed as `Env` when the app declares them via\n * `server<Env>()`; otherwise `unknown` — validate before use. */\n readonly env?: Env;\n /** Extend the response's lifetime for background work (Workers `ctx.waitUntil`). */\n readonly waitUntil?: (promise: Promise<unknown>) => void;\n /** The raw socket peer address the serving adapter observed, if any (`listen()`, `@nifrajs/node`,\n * `@nifrajs/deno` set it). The server applies the app's `clientIp` trust declaration to this before\n * exposing {@link Context.clientIp}; read `c.clientIp`, not this. */\n readonly clientIp?: string | undefined;\n}",
6114
6488
  "doc": "/**\n * Runtime platform inputs, passed as `app.fetch(request, platform)`. Edge adapters (e.g.\n * Cloudflare Workers) supply `env` (bindings) + `waitUntil`; Bun/Node/Deno omit them. Optional +\n * runtime-neutral, so `app.fetch` stays a Web-standard handler.\n */"
6115
6489
  },
6116
6490
  {
@@ -6161,6 +6535,33 @@
6161
6535
  "package": "@nifrajs/cli",
6162
6536
  "signature": "export interface PortResult {\n readonly resolved: ResolvedTarget | undefined;\n readonly detected: readonly DetectedFeature[];\n readonly json: PortJson;\n}"
6163
6537
  },
6538
+ {
6539
+ "name": "postcssBunPlugin",
6540
+ "kind": "function",
6541
+ "package": "@nifrajs/web",
6542
+ "signature": "export declare function postcssBunPlugin(generate: \"dom\" | \"ssr\", options?: PostcssPluginOptions): BunPlugin;",
6543
+ "doc": "/**\n * The PostCSS Bun plugin. `\"dom\"` → bundles the processed CSS (and, for `*.module.*`, exports the\n * scoped class map); `\"ssr\"` → the class map only for `*.module.*`, an empty module for plain CSS.\n * Tolerates a trailing `?query` (dev servers append one to bust Bun's import cache).\n */"
6544
+ },
6545
+ {
6546
+ "name": "PostcssConfigLoader",
6547
+ "kind": "type",
6548
+ "package": "@nifrajs/web",
6549
+ "signature": "export type PostcssConfigLoader = (ctx?: Record<string, unknown>, path?: string) => Promise<{\n readonly plugins?: readonly unknown[];\n readonly options?: Record<string, unknown>;\n}>;",
6550
+ "doc": "/** The subset of `postcss-load-config` this plugin uses when no explicit `plugins` are given. */"
6551
+ },
6552
+ {
6553
+ "name": "PostcssPluginOptions",
6554
+ "kind": "interface",
6555
+ "package": "@nifrajs/web",
6556
+ "signature": "export interface PostcssPluginOptions {\n /** Inject the `postcss` function (default: the optional peer, loaded lazily). Pass a stub in tests. */\n readonly postcss?: PostcssProcessor;\n /** PostCSS plugins to run. When omitted, the project's `postcss.config.js` is loaded instead. */\n readonly plugins?: readonly unknown[];\n /** Directory (or file) to load `postcss.config.js` from, when `plugins` is omitted. Default: cwd. */\n readonly config?: string;\n /** Inject the config loader (default: the `postcss-load-config` optional peer). */\n readonly loadConfig?: PostcssConfigLoader;\n}"
6557
+ },
6558
+ {
6559
+ "name": "PostcssProcessor",
6560
+ "kind": "type",
6561
+ "package": "@nifrajs/web",
6562
+ "signature": "export type PostcssProcessor = (plugins?: readonly unknown[]) => {\n process(css: string, options: {\n readonly from?: string;\n readonly to?: string;\n }): PromiseLike<{\n readonly css: string;\n }>;\n};",
6563
+ "doc": "/** The subset of the `postcss` API this plugin uses (structural, so no hard dependency on its types). */"
6564
+ },
6164
6565
  {
6165
6566
  "name": "poweredBy",
6166
6567
  "kind": "function",
@@ -6293,7 +6694,7 @@
6293
6694
  "name": "prettyJson",
6294
6695
  "kind": "function",
6295
6696
  "package": "@nifrajs/middleware",
6296
- "signature": "export declare function prettyJson(options?: PrettyJsonOptions): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").AnyServer>;",
6697
+ "signature": "export declare function prettyJson(options?: PrettyJsonOptions): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").AnyServer>;",
6297
6698
  "doc": "/**\n * Pretty-print JSON responses for debugging and developer-facing APIs. It only touches JSON content,\n * skips encoded responses, caps inspection size, and leaves invalid JSON untouched.\n */"
6298
6699
  },
6299
6700
  {
@@ -6302,6 +6703,20 @@
6302
6703
  "package": "@nifrajs/middleware",
6303
6704
  "signature": "export interface PrettyJsonOptions {\n /** JSON indentation spaces. Default `2`. */\n readonly spaces?: number;\n /** Maximum response bytes to inspect. Default `1_000_000`; larger responses pass through. */\n readonly maxBytes?: number;\n /** Append a final newline. Default `true`. */\n readonly newline?: boolean;\n /** Optional query toggle. When set, pretty printing runs only when the parameter is present. */\n readonly query?: string | false;\n /** Only pretty-print matching requests. Default `true`. */\n readonly enabled?: boolean | ((request: Request) => boolean);\n}"
6304
6705
  },
6706
+ {
6707
+ "name": "Principal",
6708
+ "kind": "interface",
6709
+ "package": "@nifrajs/better-auth",
6710
+ "signature": "export interface Principal<User> {\n /** The full better-auth user record, typed from the concrete auth instance. */\n readonly user: User;\n /** The user's id (`user.id`). */\n readonly userId: string;\n /** The session's id (`session.id`). */\n readonly sessionId: string;\n /** The resolved tenant/org id, if any. Non-optional `string` under `{ requireTenant: true }`. */\n readonly tenantId?: string;\n}",
6711
+ "doc": "/**\n * The authenticated caller of a request, mapped from a better-auth session. Built by\n * {@link requirePrincipal} / {@link authed} and threaded onto the handler context as `c.principal`.\n *\n * `tenantId` is optional here (`string | undefined`); with `{ requireTenant: true }` it is narrowed to a\n * non-optional `string` (see {@link authed}), so a tenant-scoped handler never has to null-check it.\n * nifra owns the session -> principal wiring ONLY; binding the principal to a DB/RLS scope stays in\n * userland (nifra is storage-agnostic and adds no DB code).\n */"
6712
+ },
6713
+ {
6714
+ "name": "PrincipalFor",
6715
+ "kind": "type",
6716
+ "package": "@nifrajs/better-auth",
6717
+ "signature": "export type PrincipalFor<User, RequireTenant extends boolean> = RequireTenant extends true ? Principal<User> & {\n readonly tenantId: string;\n} : Principal<User>;",
6718
+ "doc": "/**\n * The principal type for a given `requireTenant` flag: `tenantId` narrows to a required `string` when\n * `requireTenant` is `true`, otherwise stays optional (`string | undefined`). The flag is captured as a\n * literal `const` type parameter at the call sites so `{ requireTenant: true }` selects the narrowed branch.\n */"
6719
+ },
6305
6720
  {
6306
6721
  "name": "projectFeatures",
6307
6722
  "kind": "function",
@@ -6488,7 +6903,7 @@
6488
6903
  "kind": "type",
6489
6904
  "package": "@nifrajs/core",
6490
6905
  "signature": "export type QueryValue = string | string[];",
6491
- "doc": "/** A query value: a single occurrence is a string; a repeated key promotes to a string[] so an\n * array query schema (`t.array(t.string())`) can validate `?tag=a&tag=b` — last-wins silently\n * dropped values before (audit 2026-06). Single-occurrence keys stay plain strings, so existing\n * `t.string()` schemas are untouched; a repeated key against a string schema now FAILS validation\n * (an explicit 400 beats silently picking one). */"
6906
+ "doc": "/** A query value: a single occurrence is a string; a repeated key promotes to a string[] so an\n * array query schema (`t.array(t.string())`) can validate `?tag=a&tag=b` - last-wins silently\n * dropped values before (audit 2026-06). Single-occurrence keys stay plain strings, so existing\n * `t.string()` schemas are untouched; a repeated key against a string schema now FAILS validation\n * (an explicit 400 beats silently picking one). */"
6492
6907
  },
6493
6908
  {
6494
6909
  "name": "Queue",
@@ -6568,6 +6983,13 @@
6568
6983
  "signature": "export declare function raw(trusted: string): RawHtml;",
6569
6984
  "doc": "/**\n * Mark a string as trusted, pre-escaped markup — it is emitted verbatim. The deliberate escape\n * hatch (CMS-sanitized HTML, pre-rendered markdown): every call site is greppable, exactly like\n * React's dangerouslySetInnerHTML, without the JSX.\n */"
6570
6985
  },
6986
+ {
6987
+ "name": "RawContext",
6988
+ "kind": "interface",
6989
+ "package": "@nifrajs/core",
6990
+ "signature": "export interface RawContext {\n readonly req: Request;\n readonly request: Request;\n readonly json: (body: unknown, init?: ResponseInit | number) => Response;\n readonly text: (body: string, init?: ResponseInit | number) => Response;\n params: Record<string, string>;\n query: unknown;\n readonly cookies: Readonly<Record<string, string>>;\n body: unknown;\n readonly set: ResponseControls;\n readonly [CONTEXT_SET]: () => CtxSet | undefined;\n readonly [CONTEXT_SEARCH]: string;\n readonly signal: AbortSignal;\n readonly budget: RequestBudget;\n readonly env: unknown;\n readonly clientIp: string | undefined;\n readonly waitUntil: (promise: Promise<unknown>) => void;\n readonly boundedBody: (maxBytes?: number) => Promise<Uint8Array>;\n readonly boundedJson: <T = unknown>(maxBytes?: number) => Promise<T>;\n}",
6991
+ "doc": "/** Internal, path-erased runtime context. The typed `Context<Path, S>` is a structural view of this. */"
6992
+ },
6571
6993
  {
6572
6994
  "name": "RawHtml",
6573
6995
  "kind": "class",
@@ -6622,6 +7044,20 @@
6622
7044
  "signature": "export declare function readBoundedBytes(req: BodySource, maxBytes: number): Promise<{\n ok: true;\n bytes: Uint8Array;\n} | {\n ok: false;\n status: 400 | 413;\n}>;",
6623
7045
  "doc": "/**\n * Read a request body as **bytes**, capped at `maxBytes`. Rejects a `Content-Length` over the cap\n * before buffering (`413`) and a malformed `Content-Length` (`400`); a chunked / length-less body\n * falls through to the streaming byte-cap guard. Fast path: a non-chunked request with a\n * `Content-Length` within the cap is read via native `arrayBuffer()` (framing-bounded by the runtime's\n * HTTP server), skipping the manual stream loop.\n */"
6624
7046
  },
7047
+ {
7048
+ "name": "readBoundedForm",
7049
+ "kind": "function",
7050
+ "package": "@nifrajs/core",
7051
+ "signature": "export declare function readBoundedForm(req: RequestSource, maxBytes: number): Promise<Record<string, QueryValue> | Response>;",
7052
+ "doc": "/**\n * Read an HTML-form body (urlencoded) into the plain object a body schema validates - same byte\n * cap as the JSON path (a lying/absent Content-Length can't force an oversized buffer), same\n * repeated-key -> `string[]` promotion as query parsing, same `__proto__` guard.\n */"
7053
+ },
7054
+ {
7055
+ "name": "readBoundedJsonSource",
7056
+ "kind": "function",
7057
+ "package": "@nifrajs/core",
7058
+ "signature": "export declare function readBoundedJsonSource(req: RequestSource, maxBytes: number): Promise<unknown | Response>;",
7059
+ "doc": "/**\n * Read a JSON body with the same byte cap used by schema validation and `c.boundedJson`.\n * Non-chunked, framed requests with an in-cap `Content-Length` use the runtime-native `req.json()`;\n * chunked or length-less requests fall back to the streaming byte-cap guard.\n */"
7060
+ },
6625
7061
  {
6626
7062
  "name": "readCausalityHeaders",
6627
7063
  "kind": "function",
@@ -6681,8 +7117,8 @@
6681
7117
  "name": "redirect",
6682
7118
  "kind": "function",
6683
7119
  "package": "@nifrajs/web",
6684
- "signature": "export declare function redirect(location: string, statusOrOptions?: number | RedirectOptions): Response;",
6685
- "doc": "/**\n * Build a redirect `Response` — return it from a route `action` for the Post/Redirect/Get\n * pattern (POST mutates, 303 sends the browser to a fresh GET, so a reload doesn't re-submit).\n * Defaults to 303 (See Other); pass `307`/`308` (or `{ status }`) to preserve the method.\n *\n * **Secure by default:** `location` must be a same-origin path (begins with `/`, not `//`). An\n * off-origin/absolute destination throws unless you pass `{ external: true }` — this closes the\n * open-redirect footgun of `return redirect(formData.get(\"next\"))` on the no-JS (native-form) path,\n * which returns the action's `Response` verbatim.\n *\n * @param statusOrOptions a status number (back-compat) or `{ status?, external? }`.\n */"
7120
+ "signature": "export declare function redirect(location: string, options?: RedirectOptions): Response;",
7121
+ "doc": "/**\n * Build a redirect `Response` — return it from a route `action` for the Post/Redirect/Get\n * pattern (POST mutates, 303 sends the browser to a fresh GET, so a reload doesn't re-submit).\n * Defaults to 303 (See Other); pass `{ status: 307 }` or `{ status: 308 }` to preserve the method.\n *\n * **Secure by default:** `location` must be a same-origin path (begins with `/`, not `//`). An\n * off-origin/absolute destination throws unless you pass `{ external: true }` — this closes the\n * open-redirect footgun of `return redirect(formData.get(\"next\"))` on the no-JS (native-form) path,\n * which returns the action's `Response` verbatim.\n *\n * @param options redirect status and whether an off-origin destination is intentional.\n */"
6686
7122
  },
6687
7123
  {
6688
7124
  "name": "REDIRECT_HEADER",
@@ -6709,13 +7145,13 @@
6709
7145
  "name": "ReflectedRoute",
6710
7146
  "kind": "interface",
6711
7147
  "package": "@nifrajs/core",
6712
- "signature": "export interface ReflectedRoute {\n readonly method: string;\n readonly path: string;\n readonly schema?: ReflectedRouteSchema;\n readonly assurance?: readonly AssuranceEvidence[];\n readonly capabilities?: readonly string[];\n /** Field-level response classification plus the highest sensitivity present. */\n readonly classification?: ResponseClassification;\n readonly tool?: {\n readonly name: string;\n readonly description: string;\n readonly annotations?: ToolAnnotations;\n };\n}"
7148
+ "signature": "export interface ReflectedRoute {\n readonly method: string;\n readonly path: string;\n readonly schema?: ReflectedRouteSchema;\n readonly assurance?: readonly AssuranceEvidence[];\n readonly capabilities?: readonly string[];\n /** Set when the route is a declared dynamic route family (a runtime-resolved template like\n * `/api/:slug/:resource`) - so the assurance gate treats it as one classified family, not a single route. */\n readonly family?: boolean;\n /** Field-level response classification plus the highest sensitivity present. */\n readonly classification?: ResponseClassification;\n readonly tool?: {\n readonly name: string;\n readonly description: string;\n readonly annotations?: ToolAnnotations;\n };\n}"
6713
7149
  },
6714
7150
  {
6715
7151
  "name": "ReflectedRouteSchema",
6716
7152
  "kind": "interface",
6717
7153
  "package": "@nifrajs/core",
6718
- "signature": "export interface ReflectedRouteSchema {\n readonly body?: SchemaReflection;\n readonly query?: SchemaReflection;\n readonly response?: SchemaReflection;\n readonly errors?: Readonly<Record<string, SchemaReflection>>;\n /** The SSE event-payload schema of a typed streaming route (`app.sse()`). */\n readonly sse?: SchemaReflection;\n}"
7154
+ "signature": "export interface ReflectedRouteSchema {\n readonly body?: SchemaReflection;\n readonly query?: SchemaReflection;\n /** Path-params schema — constraints (uuid format, integer min/max) declared via `params: t.object(…)`. */\n readonly params?: SchemaReflection;\n readonly response?: SchemaReflection;\n readonly errors?: Readonly<Record<string, SchemaReflection>>;\n /** The SSE event-payload schema of a typed streaming route (`app.sse()`). */\n readonly sse?: SchemaReflection;\n}"
6719
7155
  },
6720
7156
  {
6721
7157
  "name": "ReflectedSchemaField",
@@ -6871,7 +7307,7 @@
6871
7307
  "name": "RenderProps",
6872
7308
  "kind": "interface",
6873
7309
  "package": "@nifrajs/web",
6874
- "signature": "export interface RenderProps {\n readonly data: unknown;\n readonly actionData?: unknown;\n /** True while a client navigation or submit is in flight (client-only; absent/false on SSR). */\n readonly pending?: boolean;\n /** The in-flight client submit, for optimistic UI (client-only; absent on SSR + when idle). */\n readonly submission?: Submission;\n /** The matched route's decoded path params (`/users/:id` → `{ id: \"7\" }`). Threaded identically on\n * SSR (from the request match) and on client navigation (from router state) so an adapter's\n * `useParams` reads the same value on both, with no hydration mismatch. Absent ⇒ no params (`{}`). */\n readonly params?: Readonly<Record<string, string>>;\n /** The current URL's `pathname + search` (no hash — the hash never reaches the server). Threaded on\n * SSR and client alike so an adapter's `useLocation`/`useSearchParams` hydrate consistently. Absent\n * on adapters/callers that don't supply it (treated as `\"\"`). */\n readonly path?: string;\n}",
7310
+ "signature": "export interface RenderProps {\n readonly data: unknown;\n readonly actionData?: unknown;\n /** True while a client navigation or submit is in flight (client-only; absent/false on SSR). */\n readonly pending?: boolean;\n /** The path a client navigation is transitioning TO while `pending` (client-only; absent on SSR and\n * when idle). Lets an adapter tell a `NavLink` whether its own target is the one loading. */\n readonly pendingPath?: string;\n /** The in-flight client submit, for optimistic UI (client-only; absent on SSR + when idle). */\n readonly submission?: Submission;\n /** The matched route's decoded path params (`/users/:id` → `{ id: \"7\" }`). Threaded identically on\n * SSR (from the request match) and on client navigation (from router state) so an adapter's\n * `useParams` reads the same value on both, with no hydration mismatch. Absent ⇒ no params (`{}`). */\n readonly params?: Readonly<Record<string, string>>;\n /** The current URL's `pathname + search` (no hash — the hash never reaches the server). Threaded on\n * SSR and client alike so an adapter's `useLocation`/`useSearchParams` hydrate consistently. Absent\n * on adapters/callers that don't supply it (treated as `\"\"`). */\n readonly path?: string;\n}",
6875
7311
  "doc": "/** The data handed to a route component. Opaque to the core. `actionData` is the return of a\n * route `action` after a POST (absent on plain GETs). `pending` + `submission` are client-only\n * (absent on SSR): they drive **optimistic UI** — render from `submission.formData` while `pending`. */"
6876
7312
  },
6877
7313
  {
@@ -6936,11 +7372,17 @@
6936
7372
  "signature": "export interface RequestBudget {\n /** Absolute Unix epoch deadline for wire propagation. */\n readonly deadline: number;\n /** The request cancellation signal. Nifra drives this when its effective deadline elapses. */\n readonly signal: AbortSignal;\n /** Non-negative milliseconds remaining, measured with the monotonic clock. */\n remaining(): number;\n /** A view that finishes `reserveMs` before this budget, preserving time for response cleanup. */\n child(reserveMs: number): RequestBudget;\n}",
6937
7373
  "doc": "/** A time budget shared by one request and every downstream hop it initiates. */"
6938
7374
  },
7375
+ {
7376
+ "name": "RequestContext",
7377
+ "kind": "class",
7378
+ "package": "@nifrajs/core",
7379
+ "signature": "export declare class RequestContext implements RawContext {\n params: Record<string, string>;\n body: unknown;\n private searchValue;\n private signalValue;\n private budgetValue;\n private platformValue;\n private setValue;\n private queryValue;\n private queryReady;\n private cookiesValue;\n private readonly source;\n private readonly maxBodyBytes;\n constructor(source: RequestSource, params: Record<string, string>, maxBodyBytes: number);\n constructor(source: RequestSource, params: Record<string, string>, search: string | undefined, signal: AbortSignal, budget: RequestBudget, platform: Platform | undefined, maxBodyBytes: number);\n static native(source: RequestSource, params: Record<string, string>, maxBodyBytes: number): RequestContext;\n [CONTEXT_SET](): CtxSet | undefined;\n get [CONTEXT_SEARCH](): string;\n get set(): CtxSet;\n get signal(): AbortSignal;\n get budget(): RequestBudget;\n get env(): unknown;\n get clientIp(): string | undefined;\n get waitUntil(): (promise: Promise<unknown>) => void;\n get req(): Request;\n get request(): Request;\n json(body: unknown, init?: ResponseInit | number): Response;\n text(body: string, init?: ResponseInit | number): Response;\n get query(): unknown;\n set query(v: unknown);\n get cookies(): Readonly<Record<string, string>>;\n boundedBody(maxBytes?: number): Promise<Uint8Array>;\n boundedJson<T = unknown>(maxBytes?: number): Promise<T>;\n}"
7380
+ },
6939
7381
  {
6940
7382
  "name": "requestId",
6941
7383
  "kind": "function",
6942
7384
  "package": "@nifrajs/middleware",
6943
- "signature": "export declare function requestId(options?: RequestIdOptions): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").Server<any, any>>;",
7385
+ "signature": "export declare function requestId(options?: RequestIdOptions): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").Server<any, any>>;",
6944
7386
  "doc": "/**\n * A {@link definePlugin} plugin that gives every request a stable id: it reuses an inbound\n * `x-request-id` (or generates one), exposes it on the handler context as **`c.requestId`** (typed,\n * threaded by `derive`), and echoes it on the response header. Idempotent — applying it twice is a\n * no-op.\n *\n * ```ts\n * app.use(requestId()) // c.requestId available downstream; X-Request-Id on responses\n * ```\n */"
6945
7387
  },
6946
7388
  {
@@ -6963,6 +7405,13 @@
6963
7405
  "signature": "export interface RequestLogFields {\n readonly method: string;\n readonly path: string;\n readonly status: number;\n /** Wall-clock duration in ms (0 if the start couldn't be paired). */\n readonly ms: number;\n}",
6964
7406
  "doc": "/** Structured fields logged per request. */"
6965
7407
  },
7408
+ {
7409
+ "name": "requestOf",
7410
+ "kind": "function",
7411
+ "package": "@nifrajs/core",
7412
+ "signature": "export declare function requestOf(source: RequestSource): Request;",
7413
+ "doc": "/** The concrete `Request` for a source - itself when a real `Request` was passed (the Web path), or the\n * lazily-built one (the Node adapter). A real `Request` IS a `RequestSource`, so no wrapper is allocated\n * on the Web hot path. */"
7414
+ },
6966
7415
  {
6967
7416
  "name": "RequestProtocol",
6968
7417
  "kind": "type",
@@ -6996,6 +7445,13 @@
6996
7445
  "signature": "export declare function requirePeer<T>(specifier: string, hint: {\n readonly feature: string;\n readonly install: string;\n}): Promise<T>;",
6997
7446
  "doc": "/**\n * Load an optional peer compiler at build time, throwing a consistent, actionable install-hint error if\n * it's absent — the `@vue/compiler-sfc` peer pattern, centralized. Build-time only, so the dynamic\n * `import` (which keeps the peer out of the package's hard dependencies) is correct here.\n */"
6998
7447
  },
7448
+ {
7449
+ "name": "requirePrincipal",
7450
+ "kind": "function",
7451
+ "package": "@nifrajs/better-auth",
7452
+ "signature": "export declare function requirePrincipal<A extends BetterAuthLike, const RequireTenant extends boolean = false>(auth: A, request: Request, options?: AuthedOptions<SessionUserOf<A>> & {\n readonly requireTenant?: RequireTenant;\n}): Promise<PrincipalFor<SessionUserOf<A>, RequireTenant>>;",
7453
+ "doc": "/**\n * Resolve the better-auth session and map it to a {@link Principal}, or **throw a `Response`** so the\n * handler never runs unauthenticated:\n *\n * - No/invalid session -> `302` to `options.redirectTo` when set, else `401` JSON (`requireSession`).\n * - `requireTenant: true` and no tenant resolves -> `403` JSON (`{ ok: false, error: \"forbidden\" }`).\n *\n * nifra returns a thrown `Response` as-is (short-circuit), so this is the fail-closed guard used inline\n * or by {@link authed}. `tenantId` is a non-optional `string` in the return type when `requireTenant`.\n *\n * ```ts\n * const principal = await requirePrincipal(auth, c.req, { requireTenant: true })\n * // principal.userId / principal.tenantId are typed `string`, no null-check\n * ```\n */"
7454
+ },
6999
7455
  {
7000
7456
  "name": "requireSecretBytes",
7001
7457
  "kind": "function",
@@ -7043,6 +7499,27 @@
7043
7499
  "package": "@nifrajs/image",
7044
7500
  "signature": "export interface ResizeOutput {\n readonly bytes: Uint8Array;\n readonly contentType: string;\n readonly format: OutputFormat;\n}"
7045
7501
  },
7502
+ {
7503
+ "name": "resolveClientIp",
7504
+ "kind": "function",
7505
+ "package": "@nifrajs/core",
7506
+ "signature": "export declare function resolveClientIp(peer: string | undefined, req: Request, trust: ClientIpTrust | undefined): string | undefined;",
7507
+ "doc": "/**\n * Resolve the caller IP from the raw socket `peer` (adapter-observed), the request's forwarding\n * headers, and the app's `trust` declaration. Pure and synchronous.\n */"
7508
+ },
7509
+ {
7510
+ "name": "ResolvedEffectLedger",
7511
+ "kind": "interface",
7512
+ "package": "@nifrajs/core",
7513
+ "signature": "export interface ResolvedEffectLedger {\n readonly sink: EffectLedgerOptions[\"sink\"];\n readonly maxEntries: number;\n readonly chain: boolean;\n /** The registered route pattern - what the sealed ledger names (never the concrete URL). */\n readonly method: string;\n readonly path: string;\n /** The route's declared capability tokens, surfaced on the sealed ledger. */\n readonly declared: readonly string[];\n}",
7514
+ "doc": "/** Registration-resolved effect-ledger wiring for one capability-declaring route. */"
7515
+ },
7516
+ {
7517
+ "name": "ResolvedIdempotency",
7518
+ "kind": "interface",
7519
+ "package": "@nifrajs/core",
7520
+ "signature": "export interface ResolvedIdempotency {\n readonly store: IdempotencyStore;\n readonly ttlMs: number;\n readonly headerName: string;\n readonly namespace: NonNullable<RouteSchema[\"idempotency\"]>[\"namespace\"];\n readonly maxResponseBytes: number;\n}",
7521
+ "doc": "/** Registration-resolved idempotency for a route: the config with its store + defaults pinned. */"
7522
+ },
7046
7523
  {
7047
7524
  "name": "ResolvedImage",
7048
7525
  "kind": "interface",
@@ -7111,6 +7588,12 @@
7111
7588
  "signature": "export declare function respondMcpHttp(request: Request, tools: McpTool[], serverInfo: {\n name: string;\n version: string;\n}, options?: McpHttpOptions): Promise<Response>;",
7112
7589
  "doc": "/**\n * Handle one MCP request over HTTP against the given `tools`/`features`. POST a JSON-RPC body → JSON-RPC\n * response; GET → a plain-text health page; OPTIONS → CORS preflight. Never throws — a bad body becomes a\n * JSON-RPC parse error. The dispatch is the shared, transport-agnostic {@link handleRpc}.\n */"
7113
7590
  },
7591
+ {
7592
+ "name": "RESPONSE_RESULT",
7593
+ "kind": "const",
7594
+ "package": "@nifrajs/core",
7595
+ "signature": "export declare const RESPONSE_RESULT: unique symbol;"
7596
+ },
7114
7597
  {
7115
7598
  "name": "responseCache",
7116
7599
  "kind": "const",
@@ -7130,6 +7613,13 @@
7130
7613
  "signature": "export interface ResponseClassification {\n readonly fields: Readonly<Record<string, DataClassification>>;\n readonly max: DataClassification;\n}",
7131
7614
  "doc": "/** Field paths use JSON Pointer segments; array items use a `*` segment. */"
7132
7615
  },
7616
+ {
7617
+ "name": "ResponseContractViolation",
7618
+ "kind": "class",
7619
+ "package": "@nifrajs/client",
7620
+ "signature": "export declare class ResponseContractViolation extends Error {\n constructor(message: string);\n}",
7621
+ "doc": "/**\n * A response body that broke its route's declared contract. Thrown THROUGH the \"never throws\"\n * client on purpose: this is a test assertion about the server's honesty, not a call outcome the\n * caller should branch on - swallowing it into a `Result` would let the drift pass the test.\n */"
7622
+ },
7133
7623
  {
7134
7624
  "name": "ResponseControls",
7135
7625
  "kind": "interface",
@@ -7158,12 +7648,25 @@
7158
7648
  "signature": "export declare function responseFromStored(stored: StoredResponse, options?: {\n readonly maxBytes?: number;\n}): Response;",
7159
7649
  "doc": "/** Rebuild a live response from storage, stamping the replay marker header. */"
7160
7650
  },
7651
+ {
7652
+ "name": "ResponseResult",
7653
+ "kind": "interface",
7654
+ "package": "@nifrajs/core",
7655
+ "signature": "export interface ResponseResult {\n readonly [RESPONSE_RESULT]: true;\n toResponse(): Response;\n toNodeBody?(): {\n readonly status: number;\n readonly headers: Readonly<Record<string, string | readonly string[]>> | undefined;\n readonly body: string | Uint8Array;\n };\n}"
7656
+ },
7161
7657
  {
7162
7658
  "name": "Result",
7163
7659
  "kind": "type",
7164
7660
  "package": "@nifrajs/client",
7165
- "signature": "export type Result<Data, ErrData = unknown> = {\n readonly ok: true;\n readonly status: number;\n readonly data: Data;\n readonly error: null;\n} | {\n readonly ok: false;\n readonly status: number;\n readonly data: ErrData;\n readonly error: ApiError;\n};",
7166
- "doc": "/**\n * The outcome of a client call. The client never throws — inspect `ok` to branch.\n * `data` is the parsed response body, **typed by `ok`**: on success it's the route's\n * response type; on failure it's the parsed error body, typed from the route's\n * `errors` contract (`unknown` when the route declares none, `null` on a transport\n * error with no response body). `error` is always the server's normalized\n * `{ error, issues? }` summary on failure (or a transport error), `null` on success.\n */"
7661
+ "signature": "export type Result<Data, Errors = unknown> = {\n readonly ok: true;\n readonly status: number;\n readonly data: Data;\n readonly error: null;\n} | ([Errors] extends [Record<number, unknown>] ? DeclaredFailures<Errors> | {\n readonly ok: false;\n readonly status: Exclude<ErrorStatus, Extract<keyof Errors, number>> | 0;\n readonly data: unknown;\n readonly error: ApiError;\n} : {\n readonly ok: false;\n readonly status: number;\n readonly data: Errors;\n readonly error: ApiError;\n});",
7662
+ "doc": "/**\n * The outcome of a client call. The client never throws - inspect `ok` to branch.\n *\n * On success, `data` is the route's response type. On failure the union is DISCRIMINATED BY\n * `status` when the route declares an `errors` record: `status === 404` narrows `data` to the\n * declared 404 body; every undeclared status (plus `0` for a transport error with no response)\n * falls into a fallback arm whose `data` is `unknown`. A route with no `errors` contract keeps a\n * single failure arm with `data: Errors` (`unknown`). `error` is always the server's normalized\n * `{ error, issues? }` summary on failure, `null` on success.\n */"
7663
+ },
7664
+ {
7665
+ "name": "resyncServerManifestSource",
7666
+ "kind": "function",
7667
+ "package": "@nifrajs/web",
7668
+ "signature": "export declare function resyncServerManifestSource(source: string, manifest: Parameters<typeof generateServerManifest>[0], routesPrefix: string): string;",
7669
+ "doc": "/**\n * Re-emit a committed server-manifest from a freshly-discovered route tree, PRESERVING its baked\n * client-asset references (`clientEntry` / `styles` / `routeStyles`) and its eager-vs-lazy shape. This is\n * what makes `nifra sync-manifest` a route-table refresh (renamed / added / removed routes) that does NOT\n * need a full build. It deliberately does NOT rebuild the client bundle: a brand-new HYDRATING route still\n * needs a full build so its client chunk exists - this only re-syncs the server manifest's route table.\n * Pure: `source` + the discovered `manifest` in, new source out.\n */"
7167
7670
  },
7168
7671
  {
7169
7672
  "name": "RetryPolicy",
@@ -7282,8 +7785,8 @@
7282
7785
  "name": "RouteDescriptor",
7283
7786
  "kind": "interface",
7284
7787
  "package": "@nifrajs/core",
7285
- "signature": "export interface RouteDescriptor {\n readonly method: Method;\n readonly path: string;\n readonly schema: RouteSchema | undefined;\n /** Effective enforcement evidence, populated only during reflection/introspection. */\n readonly assurance?: readonly AssuranceEvidence[];\n /** Normalized declared effect tokens, populated only when the route declares any. */\n readonly capabilities?: readonly string[];\n readonly tool?: {\n readonly name: string;\n readonly description: string;\n readonly annotations?: ToolAnnotations;\n };\n}",
7286
- "doc": "/**\n * A registered route's public descriptor — method, path, and input schemas. The\n * router trie discards the original patterns, so this flat list is what lets tools\n * (e.g. `toOpenAPI`) enumerate routes after registration.\n */"
7788
+ "signature": "export interface RouteDescriptor {\n readonly method: Method;\n readonly path: string;\n readonly schema: RouteSchema | undefined;\n /** Effective enforcement evidence, populated only during reflection/introspection. */\n readonly assurance?: readonly AssuranceEvidence[];\n /** Normalized declared effect tokens, populated only when the route declares any. */\n readonly capabilities?: readonly string[];\n /** Set when the route is a declared dynamic route family (`schema.family`). */\n readonly family?: boolean;\n readonly tool?: {\n readonly name: string;\n readonly description: string;\n readonly annotations?: ToolAnnotations;\n };\n}",
7789
+ "doc": "/**\n * A registered route's public descriptor - method, path, and input schemas. The\n * router trie discards the original patterns, so this flat list is what lets tools\n * (e.g. `toOpenAPI`) enumerate routes after registration.\n */"
7287
7790
  },
7288
7791
  {
7289
7792
  "name": "RouteEntry",
@@ -7303,7 +7806,7 @@
7303
7806
  "name": "RouteInfo",
7304
7807
  "kind": "interface",
7305
7808
  "package": "@nifrajs/core",
7306
- "signature": "export interface RouteInfo {\n readonly params: object;\n readonly query: unknown;\n readonly body: unknown;\n readonly output: unknown;\n /** Union of the route's declared error-response body types (from `schema.errors`); `unknown` when the\n * route declares none. Surfaced by the typed client as the failure `errorData`. */\n readonly errors?: unknown;\n /** The SSE event payload type (from `schema.sse`, declared via `app.sse()`); `never` for ordinary\n * routes. The typed client keys `.subscribe()` availability and its event type off this. */\n readonly sse?: unknown;\n}",
7809
+ "signature": "export interface RouteInfo {\n readonly params: object;\n readonly query: unknown;\n readonly body: unknown;\n readonly output: unknown;\n /** The route's declared error bodies as a status-keyed record (from `schema.errors`, e.g.\n * `{ 404: NotFound }`); `unknown` when the route declares none. The typed client turns this into\n * a status-discriminated failure union. */\n readonly errors?: unknown;\n /** The SSE event payload type (from `schema.sse`, declared via `app.sse()`); `never` for ordinary\n * routes. The typed client keys `.subscribe()` availability and its event type off this. */\n readonly sse?: unknown;\n /** The WebSocket message contract (from `app.ws()`'s `messageSchema`/`sendSchema`): `in` is what the\n * client may send, `out` what the server pushes. Present only on WS entries (method key `\"WS\"`);\n * the typed client keys `.ws()` availability and its frame types off this. */\n readonly ws?: unknown;\n}",
7307
7810
  "doc": "/**\n * One route's input/output shape as the **client** will consume it. `query`/`body`\n * are `never` when the route declares no schema for them, so the client can detect\n * \"this route takes no body\" via `[body] extends [never]`. `output` is the\n * handler's raw return type (the client applies `Jsonify` when reading it).\n */"
7308
7811
  },
7309
7812
  {
@@ -7313,6 +7816,13 @@
7313
7816
  "signature": "export type RouteInfoFor<Path extends string, S extends RouteSchema, Output> = {\n readonly params: Params<Path>;\n readonly query: RegistryQuery<S>;\n readonly body: RegistryBody<S>;\n readonly output: RegistryOutput<S, Output>;\n readonly errors: RegistryErrors<S>;\n readonly sse: RegistrySse<S>;\n};",
7314
7817
  "doc": "/** Build a {@link RouteInfo} from a route's path, schema, and handler output type. */"
7315
7818
  },
7819
+ {
7820
+ "name": "RouteIntrospectable",
7821
+ "kind": "interface",
7822
+ "package": "@nifrajs/client",
7823
+ "signature": "export interface RouteIntrospectable {\n routes(): ReadonlyArray<RouteDescriptorLike>;\n}",
7824
+ "doc": "/** What `validateResponses` needs from the app beyond `fetch`: the route table. */"
7825
+ },
7316
7826
  {
7317
7827
  "name": "RouteJson",
7318
7828
  "kind": "interface",
@@ -7406,7 +7916,7 @@
7406
7916
  "name": "RouterContextValue",
7407
7917
  "kind": "interface",
7408
7918
  "package": "@nifrajs/web-react",
7409
- "signature": "export interface RouterContextValue {\n /** The matched route's decoded path params (`/users/:id` → `{ id: \"7\" }`). */\n readonly params: Readonly<Record<string, string>>;\n /** The current URL's `pathname + search` (no hash — the router never carries one). */\n readonly path: string;\n}",
7919
+ "signature": "export interface RouterContextValue {\n /** The matched route's decoded path params (`/users/:id` → `{ id: \"7\" }`). */\n readonly params: Readonly<Record<string, string>>;\n /** The current URL's `pathname + search` (no hash — the router never carries one). */\n readonly path: string;\n /** True while a client navigation (or revalidation) is in flight — the current route stays mounted\n * until the new one is ready. Always `false` on SSR (loaders block before render). Drives loading UI\n * via {@link useNavigation}. */\n readonly pending: boolean;\n /** The `pathname + search` a navigation is transitioning TO while `pending` (`undefined` when idle or\n * during a same-route revalidation). Powers {@link NavLink}'s per-link `isPending`. */\n readonly pendingPath?: string | undefined;\n}",
7410
7920
  "doc": "/** The current route the routing hooks read. Provided by `compose` on SSR + client mount alike. */"
7411
7921
  },
7412
7922
  {
@@ -7420,14 +7930,14 @@
7420
7930
  "name": "RouterState",
7421
7931
  "kind": "interface",
7422
7932
  "package": "@nifrajs/web",
7423
- "signature": "export interface RouterState {\n readonly routeId: string;\n readonly params: Record<string, string>;\n /** The current URL path (used to revalidate the active loader after an action). */\n readonly path: string;\n readonly data: unknown;\n /** An action's data return after a client-side submit (cleared on navigation). */\n readonly actionData?: unknown;\n /** True while a navigation or submit is in flight (drives loading UI). */\n readonly pending: boolean;\n /** The in-flight submit (set during a `submit`, cleared when it settles) — for optimistic UI. */\n readonly submission?: Submission;\n}",
7933
+ "signature": "export interface RouterState {\n readonly routeId: string;\n readonly params: Record<string, string>;\n /** The current URL path (used to revalidate the active loader after an action). */\n readonly path: string;\n readonly data: unknown;\n /** An action's data return after a client-side submit (cleared on navigation). */\n readonly actionData?: unknown;\n /** True while a navigation or submit is in flight (drives loading UI). */\n readonly pending: boolean;\n /** The path a navigation is transitioning TO while `pending` (cleared when it settles). Lets a\n * `NavLink` know whether its own `to` is the one loading; `undefined` when idle. */\n readonly pendingPath?: string | undefined;\n /** The in-flight submit (set during a `submit`, cleared when it settles) — for optimistic UI. */\n readonly submission?: Submission;\n}",
7424
7934
  "doc": "/** The router's observable state. A new object is published on every transition. */"
7425
7935
  },
7426
7936
  {
7427
7937
  "name": "RouteSchema",
7428
7938
  "kind": "interface",
7429
7939
  "package": "@nifrajs/core",
7430
- "signature": "export interface RouteSchema {\n /** Declared effect tokens. Reflected for assurance; never read by validation or serialization. */\n readonly capabilities?: readonly string[];\n /**\n * Dedupe retries of this (mutating) route on an `Idempotency-Key` header. The first request runs and\n * its response is stored; a retry with the same key replays that response without re-running the\n * handler, and a key reused with a different body is rejected (409). A missing key on an\n * idempotency-required route fails closed (400). Off the hot path — routes without it are unchanged.\n */\n readonly idempotency?: IdempotencyConfig;\n /**\n * Highest data-sensitivity this route's response body carries (`public` | `pii` | `secret`). A\n * declarative, compile-time + introspection fact — never validated at runtime. Reflected for tooling,\n * recorded in the capability lockfile (so a route that starts returning PII is a reviewable change),\n * and read by downstream policy (e.g. a partner-API surface refusing to expose `pii`/`secret`).\n */\n readonly classification?: DataClassification;\n readonly body?: StandardSchemaV1;\n readonly query?: StandardSchemaV1;\n /** Optional **response contract**. When declared: the handler's return is type-checked against it\n * (the implementation can't drift from the contract), the typed client sees THIS as the response type\n * (the contract — not the handler's incidental return), and it's emitted into OpenAPI/JSON-Schema so\n * tooling and coding agents can read the exact shape. It is **not** validated at runtime (zero\n * hot-path cost) — purely a compile-time + introspection contract. */\n readonly response?: StandardSchemaV1;\n /**\n * Optional **error-response contract**: a map of HTTP status code → the Standard Schema of that error's\n * body. Declares a route's failure modes so they flow into OpenAPI (as non-2xx `responses`), the\n * `/llms.txt` context, and other introspection — the whole contract, not just the happy path, is legible\n * to tooling and coding agents. Like `response`, it is **not** validated at runtime (zero hot-path cost);\n * it's a compile-time + introspection contract. Example: `{ 404: NotFound, 409: Conflict }`. */\n readonly errors?: Readonly<Record<number, StandardSchemaV1>>;\n /**\n * Optional **SSE event contract**: the Standard Schema of each event's `data` payload on a\n * streaming route (declared via `app.sse()`). Marks the route as a typed event stream — the\n * typed client grows a `.subscribe()` for it, and the schema flows into reflection. Like\n * `response`, it is **not** validated at runtime (zero hot-path cost); the server-side\n * `stream.send()` is compile-time-checked against it instead.\n */\n readonly sse?: StandardSchemaV1;\n /**\n * Hook fired when the request fails `body`/`query` validation, before the handler runs. `kind` says\n * which input failed (`\"body\"` | `\"query\"`). Its return value selects one of three outcomes (may be async):\n * - a **`Response`** → returned as-is, short-circuiting the route (custom error envelope, redirect, …).\n * - **any other value** → treated as a repaired payload and **re-validated once** against the same\n * schema. If it now passes, the handler runs with it; if it still fails, the original `422` stands.\n * Re-validation means a bad return can't bypass the schema — the trust boundary holds.\n * - **`undefined`** → give up; the original validation `422` is returned unchanged.\n * A route hook **overrides** the app-wide default set via `server({ onValidationError })`; return\n * `undefined` to fall through to the plain `422` even when an app default exists. Typical uses: a custom\n * error envelope, coercing the input, or prompting an LLM to repair the payload (re-validated, so it can't\n * bypass the schema).\n */\n readonly onValidationError?: (issues: ReadonlyArray<StandardIssue>, ctx: Context, kind: \"body\" | \"query\") => Response | unknown | Promise<Response | unknown>;\n}",
7940
+ "signature": "export interface RouteSchema {\n /** Declared effect tokens. Reflected for assurance; never read by validation or serialization. */\n readonly capabilities?: readonly string[];\n /**\n * Dedupe retries of this (mutating) route on an `Idempotency-Key` header. The first request runs and\n * its response is stored; a retry with the same key replays that response without re-running the\n * handler, and a key reused with a different body is rejected (409). A missing key on an\n * idempotency-required route fails closed (400). Off the hot path — routes without it are unchanged.\n */\n readonly idempotency?: IdempotencyConfig;\n /**\n * Highest data-sensitivity this route's response body carries (`public` | `pii` | `secret`). A\n * declarative, compile-time + introspection fact — never validated at runtime. Reflected for tooling,\n * recorded in the capability lockfile (so a route that starts returning PII is a reviewable change),\n * and read by downstream policy (e.g. a partner-API surface refusing to expose `pii`/`secret`).\n */\n readonly classification?: DataClassification;\n /**\n * Inline **route-assurance evidence**: the enforcement posture this route carries, declared adjacent to\n * the handler (e.g. `[NIFRA_ASSURANCE.AUTHENTICATED]`). Each id becomes route-scoped `declared` evidence\n * in reflection, so a `nifra.assurance.ts` policy `require:` clause is satisfiable WITHOUT rewriting an\n * in-handler guard into a `withRouteAssurance`-marked middleware. Ids are lowercase dot/dash segments\n * (invalid ids throw at registration). Reflected for the assurance gate; never read on the hot path.\n *\n * This is an author ASSERTION (recorded as `source: \"declared\"`), not runtime proof - like every\n * assurance marker it is trusted by the static gate, which matches on the evidence id, not its source.\n * Declare an id only on a route whose guard actually enforces it; a false declaration silently satisfies\n * the policy. (`source` is retained in reflection, so a stricter policy or reviewer can still tell\n * declared evidence from enforcement-module evidence.)\n */\n readonly assurance?: readonly string[];\n /**\n * Mark this route a **dynamic route family**: a template (`/api/:slug/:resource`) whose concrete\n * resources are resolved at runtime (auto-CRUD over tenant-defined tables, a catch-all dispatcher).\n * Purely declarative - it does not change dispatch. It surfaces in reflection so the assurance gate and\n * tooling treat the one templated route as a deliberate family whose evidence covers every runtime-\n * resolved resource, instead of reading it as a single forgotten route.\n */\n readonly family?: boolean;\n /** Optional **path-params schema**. Path params arrive as strings (`/users/:id` -> `c.params.id`);\n * declaring a schema validates them at the boundary (a malformed `:id` is a `422` before the handler,\n * like `body`/`query`) and can coerce them (use `t.query({ id: t.integer() })` for a numeric param).\n * The schema must cover every path param; with the strict default an undeclared path param is rejected.\n * When omitted, `c.params` stays the path-inferred `Record<name, string>`. */\n readonly params?: StandardSchemaV1;\n readonly body?: StandardSchemaV1;\n readonly query?: StandardSchemaV1;\n /** Optional **response contract**. When declared: the handler's return is type-checked against it\n * (the implementation can't drift from the contract), the typed client sees THIS as the response type\n * (the contract — not the handler's incidental return), and it's emitted into OpenAPI/JSON-Schema so\n * tooling and coding agents can read the exact shape. It is **not** validated at runtime (zero\n * hot-path cost) — purely a compile-time + introspection contract. */\n readonly response?: StandardSchemaV1;\n /**\n * Optional **error-response contract**: a map of HTTP status code → the Standard Schema of that error's\n * body. Declares a route's failure modes so they flow into OpenAPI (as non-2xx `responses`), the\n * `/llms.txt` context, and other introspection — the whole contract, not just the happy path, is legible\n * to tooling and coding agents. Like `response`, it is **not** validated at runtime (zero hot-path cost);\n * it's a compile-time + introspection contract. Example: `{ 404: NotFound, 409: Conflict }`. */\n readonly errors?: Readonly<Record<number, StandardSchemaV1>>;\n /**\n * Optional **SSE event contract**: the Standard Schema of each event's `data` payload on a\n * streaming route (declared via `app.sse()`). Marks the route as a typed event stream — the\n * typed client grows a `.subscribe()` for it, and the schema flows into reflection. Like\n * `response`, it is **not** validated at runtime (zero hot-path cost); the server-side\n * `stream.send()` is compile-time-checked against it instead.\n */\n readonly sse?: StandardSchemaV1;\n /**\n * Hook fired when the request fails `body`/`query` validation, before the handler runs. `kind` says\n * which input failed (`\"body\"` | `\"query\"`). Its return value selects one of three outcomes (may be async):\n * - a **`Response`** → returned as-is, short-circuiting the route (custom error envelope, redirect, …).\n * - **any other value** → treated as a repaired payload and **re-validated once** against the same\n * schema. If it now passes, the handler runs with it; if it still fails, the original `422` stands.\n * Re-validation means a bad return can't bypass the schema — the trust boundary holds.\n * - **`undefined`** → give up; the original validation `422` is returned unchanged.\n * A route hook **overrides** the app-wide default set via `server({ onValidationError })`; return\n * `undefined` to fall through to the plain `422` even when an app default exists. Typical uses: a custom\n * error envelope, coercing the input, or prompting an LLM to repair the payload (re-validated, so it can't\n * bypass the schema).\n */\n readonly onValidationError?: (issues: ReadonlyArray<StandardIssue>, ctx: Context, kind: \"body\" | \"query\" | \"params\") => Response | unknown | Promise<Response | unknown>;\n}",
7431
7941
  "doc": "/** Per-route input schemas. Each is any Standard Schema (zod/valibot/arktype/…). */"
7432
7942
  },
7433
7943
  {
@@ -7543,13 +8053,6 @@
7543
8053
  "signature": "export declare function runCheck(cwd: string, opts?: {\n readonly json?: boolean;\n readonly lintsOnly?: boolean;\n}): Promise<boolean>;",
7544
8054
  "doc": "/** Run the full check; print a report (`--json` for machine output) and return whether it passed. */"
7545
8055
  },
7546
- {
7547
- "name": "runContractInvariants",
7548
- "kind": "function",
7549
- "package": "@nifrajs/core",
7550
- "signature": "export declare function runContractInvariants(app: ReflectableApp, options?: RunInvariantsOptions): Promise<InvariantReport>;",
7551
- "doc": "/**\n * @deprecated Use `runAdversarialContract` from `@nifrajs/testing`. The testing package is the\n * authoritative deep contract laboratory and powers CLI L4; this export remains for compatibility.\n */"
7552
- },
7553
8056
  {
7554
8057
  "name": "runDiff",
7555
8058
  "kind": "function",
@@ -7578,12 +8081,6 @@
7578
8081
  "signature": "export declare function runInitAgents(cwd: string, opts?: {\n readonly json?: boolean;\n readonly force?: boolean;\n}): Promise<boolean>;",
7579
8082
  "doc": "/**\n * CLI entry: run the retrofit at `cwd` and print the result. Returns `true` (the command always succeeds\n * unless a write throws — which propagates as a non-zero exit via the dispatcher's catch). `--json`\n * emits the structured result for agents/CI.\n */"
7580
8083
  },
7581
- {
7582
- "name": "RunInvariantsOptions",
7583
- "kind": "interface",
7584
- "package": "@nifrajs/core",
7585
- "signature": "export interface RunInvariantsOptions {\n /** Deterministic seed for the fuzzer. Default 1. */\n readonly seed?: number;\n /** Valid-input cases per route. Default 8. */\n readonly casesPerRoute?: number;\n /** Invalid-input (mutated) cases per route with a body schema. Default 4. */\n readonly invalidCasesPerRoute?: number;\n /**\n * Explicit isolated executor for dynamic cases. It must point at a disposable test app, sandbox,\n * or transaction that is rolled back. The runner never calls `source.fetch()` implicitly: doing so\n * could charge cards, send mail, or mutate production state merely by running a verification tool.\n */\n readonly executor?: InvariantExecutor;\n}"
7586
- },
7587
8084
  {
7588
8085
  "name": "runLevels",
7589
8086
  "kind": "function",
@@ -7617,7 +8114,7 @@
7617
8114
  "kind": "interface",
7618
8115
  "package": "@nifrajs/core",
7619
8116
  "signature": "export interface RunningServer {\n readonly port: number;\n readonly hostname: string;\n readonly pendingRequests: number;\n stop(closeActiveConnections?: boolean): void;\n}",
7620
- "doc": "/**\n * The handle `listen()` returns — the slice of Bun's server nifra holds and exposes.\n * Declared explicitly (rather than `ReturnType<typeof Bun.serve>`) so the public type\n * surface doesn't leak the ambient `Bun` global into consumers' `.d.ts` resolution.\n */"
8117
+ "doc": "/**\n * The handle `listen()` returns - the slice of Bun's server nifra holds and exposes.\n * Declared explicitly (rather than `ReturnType<typeof Bun.serve>`) so the public type\n * surface doesn't leak the ambient `Bun` global into consumers' `.d.ts` resolution.\n */"
7621
8118
  },
7622
8119
  {
7623
8120
  "name": "RunOptions",
@@ -7671,6 +8168,13 @@
7671
8168
  "signature": "export declare function runSnapshot(cwd: string, options: {\n out?: string;\n}): Promise<void>;",
7672
8169
  "doc": "/** `nifra snapshot`: write the current contract as the CI baseline. */"
7673
8170
  },
8171
+ {
8172
+ "name": "runSyncManifest",
8173
+ "kind": "function",
8174
+ "package": "@nifrajs/cli",
8175
+ "signature": "export declare function runSyncManifest(cwd: string): Promise<boolean>;",
8176
+ "doc": "/** CLI entry: sync every generated manifest, print a per-file summary + the client-rebuild caveat. */"
8177
+ },
7674
8178
  {
7675
8179
  "name": "runtimeAdapterCertificationProfile",
7676
8180
  "kind": "function",
@@ -7765,8 +8269,8 @@
7765
8269
  "name": "scanFetchText",
7766
8270
  "kind": "function",
7767
8271
  "package": "@nifrajs/cli",
7768
- "signature": "export declare function scanFetchText(file: string, content: string): SourceFinding[];",
7769
- "doc": "/** Scan one file's text for hand-rolled own-API `fetch()` calls. Pure + line-accurate. */"
8272
+ "signature": "export declare function scanFetchText(file: string, content: string, externalMounts?: readonly string[]): SourceFinding[];",
8273
+ "doc": "/** Scan one file's text for hand-rolled own-API `fetch()` calls. Pure + line-accurate. `externalMounts`\n * are intentional non-typed mount prefixes (from `nifra.check.json`, e.g. a mounted better-auth owning\n * `/auth/**`) - a relative fetch into one is deliberate, not drift, so it's skipped. A fetch with an\n * inline literal `x-nifra-data` header is Nifra's page-loader transport, not a backend API call, and is\n * skipped too. */"
7770
8274
  },
7771
8275
  {
7772
8276
  "name": "scanFileForFeatures",
@@ -7780,7 +8284,7 @@
7780
8284
  "kind": "function",
7781
8285
  "package": "@nifrajs/cli",
7782
8286
  "signature": "export declare function scanProject(cwd: string): Promise<SourceFinding[]>;",
7783
- "doc": "/** Collect own-API `fetch()` findings across the project (kept for back-compat + reuse). */"
8287
+ "doc": "/** Collect own-API `fetch()` findings across the project. */"
7784
8288
  },
7785
8289
  {
7786
8290
  "name": "scanResponseRoutes",
@@ -8035,8 +8539,7 @@
8035
8539
  "name": "serve",
8036
8540
  "kind": "function",
8037
8541
  "package": "@nifrajs/node",
8038
- "signature": "export declare function serve(app: FetchHandler, options: ServeOptions): Promise<NodeServer>;",
8039
- "doc": "/**\n * Serve a Web-`fetch` app on a Node `http` server. Resolves once bound — Node binds\n * the port asynchronously, so awaiting gives you the real port (matters for `port: 0`).\n */"
8542
+ "signature": "export declare function serve(app: FetchHandler, options: ServeOptions): Promise<NodeServer>;"
8040
8543
  },
8041
8544
  {
8042
8545
  "name": "serveDatabaseAsMcp",
@@ -8068,7 +8571,7 @@
8068
8571
  "name": "Server",
8069
8572
  "kind": "class",
8070
8573
  "package": "@nifrajs/core",
8071
- "signature": "export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext> {\n private readonly catalog;\n /** WebSocket routes, matched separately at upgrade time (a GET + `Upgrade: websocket`). */\n private readonly wsRouter;\n private wsRouteCount;\n /** In-process pub/sub backing `ws.subscribe(topic)` + `app.publish(topic, data)` (single-instance).\n * Created by the first `app.ws()` via the `@nifrajs/core/ws` runtime — `undefined` until then, so a\n * no-WebSocket app never constructs (or bundles) it. */\n private topics;\n private readonly maxBodyBytes;\n private readonly wsMaxPayloadBytes;\n private readonly requestTimeoutMs;\n private readonly acceptInboundDeadlines;\n private readonly maxInboundDeadlineMs;\n private readonly deadlineAdmissionOptions;\n private readonly gracefulSignals;\n /** Capacity-admission gate; `undefined` = off (the request path pays nothing). */\n private readonly capacityGate;\n private readonly onCapabilityUse;\n /** Effect-ledger defaults pinned at construction; per-route `ledgered` copies add route identity. */\n private readonly effectLedger;\n /** App-wide idempotency store (explicit option, else a lazily-created in-process default). */\n private readonly configuredIdempotencyStore;\n private lazyIdempotencyStore;\n private readonly logger;\n /** App-wide validation-error fallback; a route's own `schema.onValidationError` takes precedence. */\n private readonly defaultOnValidationError?;\n private bunServer;\n private sealed;\n private readonly derives;\n private readonly decorations;\n private readonly beforeHandleHooks;\n private readonly afterHandleHooks;\n private readonly onErrorHooks;\n private readonly aroundHooks;\n private readonly onRequestHooks;\n private readonly onResponseHooks;\n private readonly onResponseFinalizedHooks;\n private readonly responseRequests;\n /** Names of plugins/middleware already applied via `use` — for idempotent dedupe. */\n private readonly appliedPlugins;\n /** Order-scoped evidence captured by routes registered after an assured plugin. */\n private readonly activeAssurance;\n /** App-wide evidence from global hooks; applies retroactively to every route. */\n private readonly globalAssurance;\n /** App-declared MCP resources / prompts (via {@link resource} / {@link prompt}), read by `nifra mcp`. */\n private readonly mcpResourceList;\n private readonly mcpPromptList;\n constructor(options?: ServerOptions);\n private assertConfigurable;\n /** Add a per-request, computed context extension for subsequent routes. */\n derive<D extends object>(fn: (context: Context & Ctx) => MaybePromise<D>): Server<R, Ctx & D>;\n /** Add a static context value for subsequent routes. */\n decorate<const K extends string, V>(key: K, value: V): Server<R, Ctx & Record<K, V>>;\n /**\n * Run before routing on the raw request. Return a `Response` to short-circuit, or a replacement\n * `Request` to continue routing with a rewritten method/URL/headers. Global.\n */\n onRequest(fn: (req: Request, platform?: Platform<EnvOf<Ctx>>) => MaybePromise<OnRequestResult>): this;\n /** Run after validation, before the handler; a non-`undefined` return short-circuits. Order-scoped. */\n beforeHandle(fn: (context: Context & Ctx) => MaybePromise<unknown>): this;\n /**\n * Wrap the matched route lifecycle for subsequent routes. This is intentionally generic over the\n * route output, so wrappers like async context storage do not force Node's direct JSON path through\n * a Web `Response`. The first registered wrapper is outermost.\n */\n around(fn: <T>(context: Context & Ctx, next: () => MaybePromise<T>) => MaybePromise<T>): this;\n /** Transform the handler's result before it is serialized. Order-scoped. */\n afterHandle(fn: (result: unknown, context: Context & Ctx) => MaybePromise<unknown>): this;\n /** Handle a thrown error; a non-`undefined` return becomes the response (else the default 500). Order-scoped. */\n onError(fn: (error: unknown, context: Context & Ctx) => MaybePromise<unknown>): this;\n /** Transform every outgoing response — success, error, 404, 405, short-circuit. Global. */\n onResponse(fn: (response: Response, req: Request) => MaybePromise<Response>): this;\n /** Observe the terminal response after all transformations. Observers are ordered and fail-open. */\n onResponseFinalized(fn: (outcome: ResponseFinalization, req: Request) => MaybePromise<void>): this;\n /**\n * Apply a type-**identity** plugin ({@link IdentityPlugin}, from {@link defineIdentityPlugin}) — it\n * registers routes/hooks but doesn't change the types, so this returns `this` with the route registry\n * and context fully intact. This overload exists specifically so a *named* identity plugin (e.g.\n * `@nifrajs/better-auth`) threads the registry: its `& { pluginName }` intersection would otherwise\n * defeat the generic inference of the transforming overload below and collapse the result to `any`.\n */\n use(plugin: IdentityPlugin): this;\n /**\n * Apply a **plugin function** — `(app) => app`, typically built with {@link definePlugin}. It's\n * called with `this` and its result is returned, so an inline plugin's `derive`/`decorate` thread\n * the added context to handlers defined after `use` (the overload is generic over the concrete\n * `this`). A named plugin already applied is skipped (idempotent dedupe).\n */\n use<Out extends AnyServer>(plugin: (app: this) => Out): Out;\n /**\n * Apply a {@link Middleware} bundle — wire each hook it provides to its lifecycle point. Returns\n * `this` (no context-type merging); call it before the routes its `beforeHandle`/`afterHandle`\n * should cover (those are order-scoped; `onRequest`/`onResponse` are global). A named bundle already\n * applied is skipped (idempotent).\n */\n use(mw: Middleware): this;\n get<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"GET\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n get<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"GET\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n /**\n * Register a **typed SSE route** — a GET endpoint streaming `text/event-stream` whose event\n * payloads are contracted by `schema.sse`. The handler receives the validated context plus a\n * {@link TypedSSEStream}: `stream.send(event)` is compile-time-checked against the schema and\n * JSON-serialized into the SSE `data:` field. The typed client sees the marker and grows a\n * `.subscribe(onEvent)` for the route with the same payload type — end-to-end typed streaming.\n *\n * const app = server().sse(\"/feed\", { sse: t.object({ id: t.integer(), title: t.string() }) },\n * async (c, stream) => {\n * stream.send({ id: 1, title: \"hello\" }) // typed\n * await waitForDisconnect(stream.signal)\n * },\n * { keepAlive: 15_000 })\n *\n * // client: const off = api.feed.subscribe((post) => console.log(post.title))\n *\n * `init` passes through to the underlying {@link sse} helper (`keepAlive`, extra headers). The\n * connection closes when the handler resolves, `stream.close()` runs, or the client disconnects\n * (`stream.signal`). Query/body schemas validate exactly as on any other route.\n */\n sse<Path extends string, S extends RouteSchema & {\n sse: StandardSchemaV1;\n }>(path: Path, schema: S, run: (context: Context<Path, S> & Ctx, stream: TypedSSEStream<InferOutput<S[\"sse\"]>>) => void | Promise<void>, init?: SSEInit): Server<AddRoute<R, \"GET\", Path, RouteInfoFor<Path, S, Response>>, Ctx>;\n post<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"POST\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n post<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"POST\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n put<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"PUT\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n put<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"PUT\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n patch<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"PATCH\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n patch<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"PATCH\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n delete<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"DELETE\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n delete<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"DELETE\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n tool<Name extends string, S extends {\n description: string;\n input: StandardSchemaV1;\n output?: StandardSchemaV1;\n annotations?: ToolAnnotations;\n }, H extends (input: InferOutput<S[\"input\"]>, ctx: Context & Ctx) => MaybePromise<S[\"output\"] extends StandardSchemaV1 ? InferOutput<S[\"output\"]> : unknown>>(name: Name, config: S, handler: H): Server<AddRoute<R, \"POST\", `/_nifra/tool/${Name}`, RouteInfoFor<`/_nifra/tool/${Name}`, S[\"output\"] extends StandardSchemaV1 ? {\n body: S[\"input\"];\n response: S[\"output\"];\n } : {\n body: S[\"input\"];\n }, OutputOf<H>>>, Ctx>;\n /**\n * Declare an MCP **resource** — read-only data an agent can fetch through `nifra mcp` (app config, a\n * generated document, …). `read` runs in the app process, so capture whatever app state it needs in the\n * closure. `uri` is the MCP resource identifier (e.g. `\"myapp://config\"`). The sibling of {@link tool}\n * for the resource half of MCP.\n */\n resource(uri: string, config: {\n readonly name: string;\n readonly description?: string;\n readonly mimeType?: string;\n }, read: McpResourceDescriptor[\"read\"]): Server<R, Ctx>;\n /**\n * Declare an MCP **prompt** — a reusable prompt template an agent can fetch through `nifra mcp`.\n * `handler` receives the caller's arguments and returns the rendered messages.\n */\n prompt(name: string, config: {\n readonly description: string;\n readonly arguments?: readonly PromptArgument[];\n }, handler: McpPromptDescriptor[\"handler\"]): Server<R, Ctx>;\n /** The MCP resources declared via {@link resource} — enumerated by `nifra mcp`. */\n mcpResources(): readonly McpResourceDescriptor[];\n /** The MCP prompts declared via {@link prompt} — enumerated by `nifra mcp`. */\n mcpPrompts(): readonly McpPromptDescriptor[];\n /**\n * Register a **WebSocket** route. The connection upgrades on a `GET` to `path` carrying\n * `Upgrade: websocket`; the optional `handler.upgrade(c)` runs in the request context first and may\n * reject (return a `Response`) or seed per-connection `ws.data`. WebSockets are served by the\n * adapter (`listen()`, `@nifrajs/node`, `@nifrajs/deno`, `toFetchHandler`) — not by bare `app.fetch`, which\n * has no socket (a WS path through `app.fetch` is a normal HTTP response).\n *\n * app.ws(\"/chat\", { open: (ws) => ws.send(\"hi\"), message: (ws, data) => ws.send(data) })\n */\n ws<Data = unknown, Schema extends StandardSchemaV1 | undefined = undefined>(path: string, handler: WebSocketHandler<Data, EnvOf<Ctx>, Schema>): this;\n /**\n * Broadcast `data` to every WebSocket connection subscribed to `topic` (via `ws.subscribe(topic)`).\n * In-process and **single-instance** (see {@link TopicRegistry}) — a multi-instance deploy must bridge\n * an external fan-out (Redis, a Durable Object) to this. A no-op when nobody is subscribed.\n */\n publish(topic: string, data: string | ArrayBufferView | ArrayBuffer): void;\n private route;\n /**\n * Low-level route registration shared by the inline builder and `implement()`.\n * Captures the server's current `derive`/`decorate` chain into the route — this\n * is the \"compiled\", order-scoped per-route chain.\n */\n register(method: Method, path: string, schema: RouteSchema | undefined, handler: (context: never) => unknown): void;\n /** Register a contract/group route batch atomically. Every route captures the same current chain it\n * would capture through {@link register}; no route becomes visible unless the full batch validates. */\n registerBatch(routes: readonly {\n readonly method: Method;\n readonly path: string;\n readonly schema: RouteSchema | undefined;\n readonly handler: (context: never) => unknown;\n }[]): void;\n private prepareRoute;\n /** Collapse route-invariant lifecycle decisions into one runner at registration. The request path\n * performs no eligibility ladder: it supplies request state to this already-selected plan. */\n private compileExecutionPlan;\n /** Resolve a route's declared idempotency into a pinned store + defaults, or `undefined` when off. */\n private resolveIdempotency;\n /** The app-wide idempotency store: the configured one, else a lazily-created shared in-process store. */\n private defaultIdempotencyStore;\n /**\n * Merge another server's routes into this one — the composition escape hatch for large apps.\n *\n * WHY: the fluent chain accumulates one type-alias level per route, and TypeScript resolves\n * that stack in one recursion — a single chain hits TS2589 at ~95 routes. Groups keep every\n * chain short: build each domain (`listings`, `agents`, …) as its own `server()` (its registry\n * resolves independently), then `app.merge(listings).merge(agents)` — each merge adds ONE level\n * regardless of group size. 300+ routes stay fully typed (see many-routes.test-d.ts). The\n * other escape hatch is contract-first `implement()`, whose registry is a single object type.\n *\n * Semantics: merged routes keep the chains captured where they were DEFINED — the group's\n * `derive`/`decorate`/`beforeHandle`/`afterHandle`/`onError`/`around` apply to its routes\n * exactly as they did standalone, so a group wires its own plugins. The group's request-level\n * hooks (`onRequest`/`onResponse`/`onResponseFinalized`) are appended to this server's. This\n * server's route-scoped chains do NOT retroactively wrap merged routes (order-scoped, like\n * routes registered before a `derive`). Fail closed: a path+method collision throws\n * `RouteConfigError` at merge time, and a group with WebSocket routes is refused (register\n * those on the parent).\n */\n merge<R2 extends Registry, Ctx2>(other: Server<R2, Ctx2>): Server<R & R2, Ctx>;\n /** A fused renderer closes over runtime services to keep its seven-argument JSC fast path. Merging\n * rebinds that closure once to the executing server; generic plans already receive the runtime. */\n private bindFusedRuntime;\n /**\n * Enumerate the registered routes (method, path, input schemas), in registration\n * order. Powers `toOpenAPI` and other introspection; the router trie itself no\n * longer holds the original patterns.\n */\n routes(): ReadonlyArray<RouteDescriptor>;\n /**\n * Resolve a `Request` to a `Response` — the whole lifecycle, testable without a port. The\n * optional `platform` carries edge inputs (`env`, `waitUntil`); edge adapters pass it, and\n * Bun/Node/Deno omit it (then `c.env` is `undefined` and `c.waitUntil` runs fire-and-forget).\n */\n fetch(req: Request, platform?: Platform<EnvOf<Ctx>>): MaybePromise<Response>;\n private fetchSource;\n private fetchSourceInner;\n /** Web response path when Bun already matched the route. The lifecycle and response hooks remain\n * exactly the same as {@link fetchSource}; only portable URL scanning + trie lookup are skipped. */\n private fetchMatched;\n private fetchMatchedInner;\n /**\n * Run `produce` under the capacity gate: admit → run → release exactly once when the response is\n * produced (or the run throws). Only reached when {@link capacityGate} is set, so the off path pays\n * nothing. The slot is held for the duration of handler execution, not the streaming of the body —\n * capacity here bounds concurrent *work*, matching how in-flight is counted.\n */\n private admitGated;\n private runAdmitted;\n /**\n * Like {@link fetch}, but renders a plain-data result **without** building a Web `Response` — the\n * `@nifrajs/node` adapter serializes the returned primitives straight to the socket, skipping the undici\n * `Response` build + body drain (the bulk of the Node bridge cost, measured ≈4µs/req). A handler that\n * returns a `Response`, an error/short-circuit, or any registered `onResponse` hook falls back to the\n * full Web path (`{ kind: \"response\" }`), so behavior is identical — only the common JSON-data case is\n * faster. Same lifecycle as {@link fetch} (body cap, validation, hooks all run); only the final\n * render differs.\n */\n resolveNode(req: Request, platform?: Platform<EnvOf<Ctx>>): MaybePromise<NodeServeOutcome>;\n resolveNodeSource(source: RequestSource, platform?: Platform<EnvOf<Ctx>>): MaybePromise<NodeServeOutcome>;\n /**\n * Resolve a WebSocket upgrade — the seam every serving adapter uses. Returns `pass` (not a WS\n * upgrade for a registered route → handle as normal HTTP), `reject` (a WS route matched but\n * `upgrade()` rejected, or the path was malformed → return `response`), or `upgrade` (perform the\n * runtime upgrade, then dispatch the native socket's events to `handler`, seeding `ws.data` with\n * `data`). Runs the route's `upgrade(c)` guard in a real request context. Synchronous unless\n * `upgrade()` is async; a throw rejects with a flat 500 (no detail leaked).\n */\n resolveWebSocketUpgrade(req: Request, platform?: Platform<EnvOf<Ctx>>): MaybePromise<WebSocketUpgradeOutcome>;\n /** Bun `fetch` when WS routes exist: try a WS upgrade first, else run the normal HTTP lifecycle.\n * `undefined` ⇒ Bun owns the upgraded socket; a `Response` ⇒ a normal reply or a rejected upgrade.\n * (The socket dispatch itself lives in `ws-bun.ts`, loaded via `@nifrajs/core/ws`.) */\n private bunFetchWithWebSocket;\n /**\n * The shared lifecycle, generic over how the final value is rendered: `finalize` turns a handler's\n * result + `set` into the output `T` (`toResponse` → a Web `Response`; `toNodeOutcome` → node-direct\n * primitives), `wrapResponse` lifts an early/error `Response` into that same `T`, and `onTimeout`\n * produces the 503. The Web `fetch` and `resolveNode` are thin callers over this one routing +\n * context + lifecycle implementation — no duplication across the trust boundary.\n */\n private dispatch;\n /**\n * onRequest short-circuit path. Synchronous as long as every hook returns synchronously (the\n * common case — e.g. CORS returning `undefined` for a non-preflight request): an `async` version\n * here put EVERY request of any app with one onRequest hook onto the promise machinery, profiled\n * at ~13% of a realistic request. The first hook that returns a Promise hands the REMAINING\n * hooks to the async continuation; behavior is identical.\n */\n private runWithOnRequest;\n /** Async tail of {@link runWithOnRequest}: applies the first awaited hook's outcome, then runs\n * the remaining hooks (awaiting freely — we're already async here). */\n private continueOnRequest;\n private takeResponseRequest;\n /**\n * Route → build context → run. Synchronous through to the handler for a **bare** route\n * (selected by its compiled plan), so a sync handler produces its result with zero promise allocations;\n * routes with validation/hooks keep the full async {@link runLifecycle}, unchanged.\n */\n private routeAndRun;\n /** Run a route that has already been matched by the runtime or Nifra's portable router. */\n private runMatched;\n /**\n * Idempotency dedupe lane. Reads the `Idempotency-Key`, fingerprints the request, and consults the\n * store: a fresh key runs the handler (via {@link runMatchedLanes} with the body buffered) and stores\n * the response; a repeat key replays it without re-running; a key reused with a different body or an\n * in-flight duplicate is rejected. Every branch materializes a `Response`, then adapts to `T` via the\n * caller's `wrapResponse`, so it works on the Web fetch path and the Node-native outcome path alike.\n */\n private runIdempotent;\n /** Supply request-specific deadline state to the route's precompiled execution plan. */\n private runMatchedLanes;\n /**\n * Seal a ledgered request and deliver the sealed ledger to the sink. An empty ledger (declared\n * capabilities, none exercised) is not delivered — there is nothing to audit. This post-effect\n * ledger is observational: transactional/durable audit belongs in\n * the owned effect transaction, so a sink outage must not turn a successful effect into a retryable\n * 500 that can duplicate it.\n */\n private settleEffectLedger;\n /** The narrowest bare route: a syntactic `() => ...` handler cannot observe the context argument, so\n * successful requests can skip allocating `RequestContext`. Errors still allocate one for logging. */\n private runContextlessBare;\n private contextlessBareError;\n /**\n * The synchronous fast path selected by a route's execution plan: apply static decorations, call the\n * handler, render the result — **no `await`** unless the handler itself returns a promise. It mirrors\n * the bare slice of {@link runLifecycle} (which a bare route would otherwise no-op through) and shares\n * {@link logRequestError}; a bare route has no `onError` hooks, so error handling is fully synchronous\n * (a thrown `Response` is control flow; anything else is a logged flat 500). This is where nifra skips\n * the per-request async-frame tax — the same win codegen routers get, but without `eval`.\n */\n private runBare;\n /** Bare-route error rendering — identical to {@link runLifecycle}'s catch minus the (absent) onError\n * loop: a thrown `Response` is returned as deliberate control flow; anything else is logged + 500. */\n /**\n * Build a route's fused Web renderer. Composition happens once at\n * registration; the returned closure is what every request to the route runs. Behavior is\n * byte-identical to the generic `runBare`/`runContextlessBare` + `toResponse` pair — same\n * decoration order, same error routing (thrown `Response` = control flow; anything else logs and\n * 500s), same respond semantics (the lifecycle parity suite pins it).\n */\n private buildFusedWeb;\n private bareError;\n private runWithAround;\n private runAround;\n private runBodyOnly;\n /** Validate + run the handler for the bodyOnly path — shared by the inline fast path and the\n * streaming fallback. A method (not per-request closures) so the hot path allocates nothing\n * beyond the one `.then` continuation. */\n private finishBodyOnly;\n private executeHandler;\n private handleValidationErrorRecovery;\n private applyBodyValidation;\n private runQueryOnly;\n /** Validate-result → set `ctx.query` → run handler. A method (not a per-request closure), the\n * query analogue of {@link applyBodyValidation}. */\n private applyQueryValidation;\n /**\n * Thread the response through each global `onResponse` hook. Stays SYNCHRONOUS until a hook\n * actually returns a Promise — an `async` version forced a promise + microtask on EVERY response\n * of any app with an onResponse hook (cors/securityHeaders/etag/timing all use onResponse), the\n * same ~13%/req tax the onRequest walk was de-async'd to avoid. The first async hook hands the\n * rest to {@link continueOnResponse}.\n */\n private applyOnResponse;\n private applyOnResponseAndFinalize;\n private completeResponseFinalization;\n private failResponseFinalization;\n /** Notify terminal observers in order while isolating both sync and async failures. */\n private notifyResponseFinalized;\n /** Async tail of {@link applyOnResponse}: runs the remaining hooks once one has gone async. */\n private continueOnResponse;\n /**\n * Bound the response time. On timeout we abort `ctx.signal` (so cancellation-aware\n * handlers can bail) and return 503; the in-flight work keeps running but its\n * result is discarded — JS can't forcibly cancel a promise.\n */\n private withTimeout;\n /**\n * The post-match lifecycle: validate → derive → beforeHandle → handler → afterHandle, with onError.\n * Generic over the render: a success value goes through `finalize(result, set)` (a Web `Response`, or\n * node-direct primitives); an early/error `Response` (validation, thrown, 500) through `wrapResponse`.\n */\n private runLifecycle;\n private handleLifecycleError;\n /** Log an unhandled request error to the (redacting) logger — shared by {@link runLifecycle} and the\n * bare fast path ({@link bareError}) so both record the same fields. Never throws; never leaks. */\n private logRequestError;\n private readAndValidateBody;\n /** Apply validation and its recovery hook on the generic lifecycle lane. Recovery is completed\n * before derives/beforeHandle run, matching the body-only and query-only execution lanes. */\n private applyLifecycleValidation;\n /**\n * Read the body as text, capped at `maxBodyBytes`. Rejects (`null`) on a\n * `Content-Length` over the cap *before* buffering, and aborts mid-stream once the\n * running byte count exceeds it — so a lying or absent length can't force us to\n * buffer an oversized payload.\n *\n * Fast path: when a non-chunked request carries a `Content-Length` within the cap,\n * a native `req.json()` is already bounded — under HTTP/1.1 + HTTP/2 framing the\n * runtime delivers at most `Content-Length` bytes — so we skip the manual stream\n * loop and a separate text decode. It trusts the wire\n * *framing*, not the header value: nifra only ever receives framed Requests from the\n * runtime's HTTP server, never a hand-built one with a mismatched length. Chunked or\n * length-less bodies fall through to the streaming byte-cap guard below.\n */\n private readBoundedJson;\n /** Adapt one route's compiled execution plan to Bun's already-matched request shape. Route\n * semantics remain in the plan; this closure only supplies native params and deadline fallback. */\n private compileBunNativeHandler;\n /** Compile portable route registrations into Bun's native route table. Apps with request-rewrite\n * hooks or WebSockets retain the single portable dispatcher because those features must run before\n * route selection/upgrade. Named wildcards also stay on the fallback until Bun exposes their raw\n * capture semantics; static and `:param` routes take the native lane. */\n private buildBunNativeRoutes;\n /**\n * Start a `Bun.serve` instance bound to `port` (use `0` for an ephemeral port).\n *\n * `reusePort` sets `SO_REUSEPORT` so **multiple processes can bind the same port** and the kernel\n * load-balances connections across them — the standard way to use every core (Bun is\n * single-threaded per process). Spawn one process per core, each calling\n * `app.listen(PORT, { reusePort: true })`; see `examples/cluster.ts`. Every process must opt in,\n * and all of them must be the same app. Linux balances ~evenly; macOS accepts the flag but may\n * favor one socket (fine for dev, measure on Linux for production numbers).\n *\n * `hostname` is the bind address, defaulting to Bun's `0.0.0.0` (every interface). Pass\n * `\"127.0.0.1\"` to bind loopback only - an admin surface, a sidecar, or anything that must not be\n * reachable off the box. Omitting it when you meant to restrict is a real exposure, so it is a\n * first-class option rather than something a caller has to drop down to `Bun.serve` for.\n */\n listen(port: number, options?: {\n readonly reusePort?: boolean;\n readonly hostname?: string;\n }): RunningServer;\n /**\n * Gracefully stop: wait for in-flight requests to finish (up to `drainMs`), then\n * issue a single terminal stop — graceful if everything drained, forced if\n * stragglers remain. Safe to call when not listening.\n *\n * The Bun semantics: poll `pendingRequests` (awaiting\n * `stop()`'s promise drops in-flight requests), and decide graceful-vs-forced in\n * ONE call (Bun can't escalate an already-graceful `stop()` to a forced close).\n * New connections may be accepted during the drain window; in a real deploy the\n * load balancer has already stopped routing here, and `drainMs` bounds it.\n */\n stop({ drainMs }?: {\n drainMs?: number;\n }): Promise<void>;\n private installSignalHandlers;\n}",
8574
+ "signature": "export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext> {\n private readonly catalog;\n /** WebSocket routes, matched separately at upgrade time (a GET + `Upgrade: websocket`). */\n private readonly wsRouter;\n private wsRouteCount;\n /** In-process pub/sub backing `ws.subscribe(topic)` + `app.publish(topic, data)` (single-instance).\n * Created by the first `app.ws()` via the `@nifrajs/core/ws` runtime — `undefined` until then, so a\n * no-WebSocket app never constructs (or bundles) it. */\n private topics;\n private readonly maxBodyBytes;\n private readonly wsMaxPayloadBytes;\n private readonly requestTimeoutMs;\n /** Opt-in caller-IP trust declaration; `undefined` = socket peer only, no forwarded header believed. */\n private readonly clientIpTrust;\n private readonly acceptInboundDeadlines;\n private readonly maxInboundDeadlineMs;\n private readonly deadlineAdmissionOptions;\n private readonly gracefulSignals;\n /** Capacity-admission gate; `undefined` = off (the request path pays nothing). */\n private readonly capacityGate;\n private readonly onCapabilityUse;\n /** The installed effect-ledger runtime (owns the sink + per-route resolution + settle), or\n * `undefined` when the effect-ledger plugin is not installed. */\n private effectLedgerRuntime;\n /** The installed idempotency runtime (owns the app-wide default store + the dedupe lane), or\n * `undefined` when the idempotency plugin is not installed. */\n private idempotencyRuntime;\n /** Installed opt-in runtime for `.tool()`/`.resource()`/`.prompt()`; `undefined` until `.use(mcp())`. */\n private mcpRuntime;\n /** Installed Node-direct renderer for direct `resolveNode()` callers; `undefined` until `.use(nodeDirect())`. */\n private nodeOutcomeRuntime;\n /** Installed streaming runtime for `.sse()` routes; `undefined` until `.use(streaming())`. */\n private sseRuntime;\n /** Installed WebSocket runtime for `.ws()` routes; `undefined` until `.use(websocket())`. */\n private wsRuntime;\n private readonly logger;\n /** App-wide validation-error fallback; a route's own `schema.onValidationError` takes precedence. */\n private readonly defaultOnValidationError?;\n private bunServer;\n private sealed;\n private readonly derives;\n private readonly decorations;\n private readonly beforeHandleHooks;\n private readonly afterHandleHooks;\n private readonly onErrorHooks;\n private readonly aroundHooks;\n private readonly onRequestHooks;\n private readonly onResponseHooks;\n private readonly onResponseFinalizedHooks;\n private readonly responseRequests;\n /** Names of plugins/middleware already applied via `use` — for idempotent dedupe. */\n private readonly appliedPlugins;\n /** Order-scoped evidence captured by routes registered after an assured plugin. */\n private readonly activeAssurance;\n /** App-wide evidence from global hooks; applies retroactively to every route. */\n private readonly globalAssurance;\n /** App-declared MCP resources / prompts (via {@link resource} / {@link prompt}), read by `nifra mcp`. */\n private readonly mcpResourceList;\n private readonly mcpPromptList;\n constructor(options?: ServerOptions);\n private assertConfigurable;\n /** Add a per-request, computed context extension for subsequent routes. */\n derive<D extends object>(fn: (context: Context & Ctx) => MaybePromise<D>): Server<R, Ctx & D>;\n /** Add a static context value for subsequent routes. */\n decorate<const K extends string, V>(key: K, value: V): Server<R, Ctx & Record<K, V>>;\n /**\n * Run before routing on the raw request. Return a `Response` to short-circuit, or a replacement\n * `Request` to continue routing with a rewritten method/URL/headers. Global.\n */\n onRequest(fn: (req: Request, platform?: Platform<EnvOf<Ctx>>) => MaybePromise<OnRequestResult>): this;\n /** Run after validation, before the handler; a non-`undefined` return short-circuits. Order-scoped. */\n beforeHandle(fn: (context: Context & Ctx) => MaybePromise<unknown>): this;\n /**\n * Wrap the matched route lifecycle for subsequent routes. This is intentionally generic over the\n * route output, so wrappers like async context storage do not force Node's direct JSON path through\n * a Web `Response`. The first registered wrapper is outermost.\n */\n around(fn: <T>(context: Context & Ctx, next: () => MaybePromise<T>) => MaybePromise<T>): this;\n /** Transform the handler's result before it is serialized. Order-scoped. */\n afterHandle(fn: (result: unknown, context: Context & Ctx) => MaybePromise<unknown>): this;\n /** Handle a thrown error; a non-`undefined` return becomes the response (else the default 500). Order-scoped. */\n onError(fn: (error: unknown, context: Context & Ctx) => MaybePromise<unknown>): this;\n /** Transform every outgoing response — success, error, 404, 405, short-circuit. Global. */\n onResponse(fn: (response: Response, req: Request) => MaybePromise<Response>): this;\n /** Observe the terminal response after all transformations. Observers are ordered and fail-open. */\n onResponseFinalized(fn: (outcome: ResponseFinalization, req: Request) => MaybePromise<void>): this;\n /**\n * Apply a type-**identity** plugin ({@link IdentityPlugin}, from {@link defineIdentityPlugin}) — it\n * registers routes/hooks but doesn't change the types, so this returns `this` with the route registry\n * and context fully intact. This overload exists specifically so a *named* identity plugin (e.g.\n * `@nifrajs/better-auth`) threads the registry: its `& { pluginName }` intersection would otherwise\n * defeat the generic inference of the transforming overload below and collapse the result to `any`.\n */\n use(plugin: IdentityPlugin): this;\n /**\n * Apply a **plugin function** — `(app) => app`, typically built with {@link definePlugin}. It's\n * called with `this` and its result is returned, so an inline plugin's `derive`/`decorate` thread\n * the added context to handlers defined after `use` (the overload is generic over the concrete\n * `this`). A named plugin already applied is skipped (idempotent dedupe).\n */\n use<Out extends AnyServer>(plugin: (app: this) => Out): Out;\n /**\n * Apply a {@link Middleware} bundle — wire each hook it provides to its lifecycle point. Returns\n * `this` (no context-type merging); call it before the routes its `beforeHandle`/`afterHandle`\n * should cover (those are order-scoped; `onRequest`/`onResponse` are global). A named bundle already\n * applied is skipped (idempotent).\n */\n use(mw: Middleware): this;\n get<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"GET\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n get<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"GET\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n /**\n * Register a **typed SSE route** — a GET endpoint streaming `text/event-stream` whose event\n * payloads are contracted by `schema.sse`. The handler receives the validated context plus a\n * {@link TypedSSEStream}: `stream.send(event)` is compile-time-checked against the schema and\n * JSON-serialized into the SSE `data:` field. The typed client sees the marker and grows a\n * `.subscribe(onEvent)` for the route with the same payload type — end-to-end typed streaming.\n *\n * import { streaming } from \"@nifrajs/core/sse\" // .use(streaming()) enables .sse()\n * const app = server().use(streaming()).sse(\"/feed\", { sse: t.object({ id: t.integer(), title: t.string() }) },\n * async (c, stream) => {\n * stream.send({ id: 1, title: \"hello\" }) // typed\n * await waitForDisconnect(stream.signal)\n * },\n * { keepAlive: 15_000 })\n *\n * // client: const off = api.feed.subscribe((post) => console.log(post.title))\n *\n * `init` passes through to the underlying {@link sse} helper (`keepAlive`, extra headers). The\n * connection closes when the handler resolves, `stream.close()` runs, or the client disconnects\n * (`stream.signal`). Query/body schemas validate exactly as on any other route.\n */\n sse<Path extends string, S extends RouteSchema & {\n sse: StandardSchemaV1;\n }>(path: Path, schema: S, run: (context: Context<Path, S> & Ctx, stream: TypedSSEStream<InferOutput<S[\"sse\"]>>) => void | Promise<void>, init?: SSEInit): Server<AddRoute<R, \"GET\", Path, RouteInfoFor<Path, S, Response>>, Ctx>;\n post<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"POST\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n post<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"POST\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n put<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"PUT\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n put<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"PUT\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n patch<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"PATCH\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n patch<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"PATCH\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n delete<Path extends string, S extends RouteSchema, H extends Handler<Path, S, Ctx>>(path: Path, schema: S, handler: H): Server<AddRoute<R, \"DELETE\", Path, RouteInfoFor<Path, S, OutputOf<H>>>, Ctx>;\n delete<Path extends string, H extends Handler<Path, RouteSchema, Ctx>>(path: Path, handler: H): Server<AddRoute<R, \"DELETE\", Path, RouteInfoFor<Path, Record<never, never>, OutputOf<H>>>, Ctx>;\n /**\n * Declare an **MCP tool** an agent can call (via `nifra mcp`, or a mounted MCP endpoint): a typed\n * `POST /_nifra/tool/<name>` route whose `input`/`output` schemas contract the call and surface in\n * `tools/list`. Requires `.use(mcp())` - without it, `.tool()` is a registration error, so an\n * ordinary HTTP app never bundles the MCP wiring. Siblings: {@link resource}, {@link prompt}.\n *\n * import { mcp } from \"@nifrajs/core/mcp\"\n * const app = server().use(mcp()).tool(\n * \"search\",\n * { description: \"Search posts\", input: t.object({ q: t.string() }) },\n * ({ q }) => findPosts(q),\n * )\n */\n tool<Name extends string, S extends {\n description: string;\n input: StandardSchemaV1;\n output?: StandardSchemaV1;\n annotations?: ToolAnnotations;\n }, H extends (input: InferOutput<S[\"input\"]>, ctx: Context & Ctx) => MaybePromise<S[\"output\"] extends StandardSchemaV1 ? InferOutput<S[\"output\"]> : unknown>>(name: Name, config: S, handler: H): Server<AddRoute<R, \"POST\", `/_nifra/tool/${Name}`, RouteInfoFor<`/_nifra/tool/${Name}`, S[\"output\"] extends StandardSchemaV1 ? {\n body: S[\"input\"];\n response: S[\"output\"];\n } : {\n body: S[\"input\"];\n }, OutputOf<H>>>, Ctx>;\n /**\n * Declare an MCP **resource** — read-only data an agent can fetch through `nifra mcp` (app config, a\n * generated document, …). `read` runs in the app process, so capture whatever app state it needs in the\n * closure. `uri` is the MCP resource identifier (e.g. `\"myapp://config\"`). The sibling of {@link tool}\n * for the resource half of MCP.\n */\n resource(uri: string, config: {\n readonly name: string;\n readonly description?: string;\n readonly mimeType?: string;\n }, read: McpResourceDescriptor[\"read\"]): Server<R, Ctx>;\n /**\n * Declare an MCP **prompt** — a reusable prompt template an agent can fetch through `nifra mcp`.\n * `handler` receives the caller's arguments and returns the rendered messages.\n */\n prompt(name: string, config: {\n readonly description: string;\n readonly arguments?: readonly PromptArgument[];\n }, handler: McpPromptDescriptor[\"handler\"]): Server<R, Ctx>;\n /** The MCP resources declared via {@link resource} — enumerated by `nifra mcp`. */\n mcpResources(): readonly McpResourceDescriptor[];\n /** The MCP prompts declared via {@link prompt} — enumerated by `nifra mcp`. */\n mcpPrompts(): readonly McpPromptDescriptor[];\n /**\n * Register a **WebSocket** route. The connection upgrades on a `GET` to `path` carrying\n * `Upgrade: websocket`; the optional `handler.upgrade(c)` runs in the request context first and may\n * reject (return a `Response`) or seed per-connection `ws.data`. WebSockets are served by the\n * adapter (`listen()`, `@nifrajs/node`, `@nifrajs/deno`, `toFetchHandler`) — not by bare `app.fetch`, which\n * has no socket (a WS path through `app.fetch` is a normal HTTP response).\n *\n * The route also enters the type-level registry (under the pseudo-method `\"WS\"`), so the typed\n * client grows a `.ws()` handle for it: `messageSchema` types what the client may `send`,\n * `sendSchema` types the frames it receives. Passing explicit type arguments (`ws<MyData>(…)`)\n * defeats path-literal inference and skips the registry entry - the route still serves, it is just\n * invisible to `client<App>`; prefer typing `data` via `upgrade()`'s return.\n *\n * app.ws(\"/chat\", { open: (ws) => ws.send(\"hi\"), message: (ws, data) => ws.send(data) })\n */\n ws<Data = unknown, Schema extends StandardSchemaV1 | undefined = undefined, Send extends StandardSchemaV1 | undefined = undefined, Path extends string = string>(path: Path, handler: WebSocketHandler<Data, EnvOf<Ctx>, Schema, Send>): string extends Path ? Server<R, Ctx> : Server<AddRoute<R, \"WS\", Path, WsRouteInfoFor<Path, Schema, Send>>, Ctx>;\n /**\n * Broadcast `data` to every WebSocket connection subscribed to `topic` (via `ws.subscribe(topic)`).\n * In-process and **single-instance** (see {@link TopicRegistry}) — a multi-instance deploy must bridge\n * an external fan-out (Redis, a Durable Object) to this. A no-op when nobody is subscribed.\n */\n publish(topic: string, data: string | ArrayBufferView | ArrayBuffer): void;\n private route;\n /**\n * Low-level route registration shared by the inline builder and `implement()`.\n * Captures the server's current `derive`/`decorate` chain into the route — this\n * is the \"compiled\", order-scoped per-route chain.\n */\n register(method: Method, path: string, schema: RouteSchema | undefined, handler: (context: never) => unknown): void;\n /** Register a contract/group route batch atomically. Every route captures the same current chain it\n * would capture through {@link register}; no route becomes visible unless the full batch validates. */\n registerBatch(routes: readonly {\n readonly method: Method;\n readonly path: string;\n readonly schema: RouteSchema | undefined;\n readonly handler: (context: never) => unknown;\n }[]): void;\n private prepareRoute;\n /** Collapse route-invariant lifecycle decisions into one runner at registration. The request path\n * performs no eligibility ladder: it supplies request state to this already-selected plan. */\n private compileExecutionPlan;\n /** The idempotency lane's bridge back into the normal matched lanes, resolved to a concrete Response\n * (the lane buffers the body, then replays it through the route's real validation + handler). */\n private idempotencyRunLanes;\n /** @internal Symbol-keyed install seam for the `idempotency()` plugin. Off the public typed surface. */\n [INSTALL_IDEMPOTENCY](runtime: IdempotencyRuntime): void;\n /** @internal Symbol-keyed install seam for the `mcp()` plugin. Off the public typed surface. */\n [INSTALL_MCP](runtime: McpRuntime): void;\n /** @internal Symbol-keyed install seam for the `nodeDirect()` plugin. Off the public typed surface. */\n [INSTALL_NODE_DIRECT](runtime: NodeOutcomeRuntime): void;\n /** @internal Symbol-keyed install seam for the `streaming()` plugin. Off the public typed surface. */\n [INSTALL_SSE](runtime: SseRuntime): void;\n /** @internal Symbol-keyed install seam for the `websocket()` plugin. Off the public typed surface. */\n [INSTALL_WS](runtime: WsRuntime): void;\n /**\n * Merge another server's routes into this one — the composition escape hatch for large apps.\n *\n * WHY: the fluent chain accumulates one type-alias level per route, and TypeScript resolves\n * that stack in one recursion — a single chain hits TS2589 at ~95 routes. Groups keep every\n * chain short: build each domain (`listings`, `agents`, …) as its own `server()` (its registry\n * resolves independently), then `app.merge(listings).merge(agents)` — each merge adds ONE level\n * regardless of group size. 300+ routes stay fully typed (see many-routes.test-d.ts). The\n * other escape hatch is contract-first `implement()`, whose registry is a single object type.\n *\n * Semantics: merged routes keep the chains captured where they were DEFINED — the group's\n * `derive`/`decorate`/`beforeHandle`/`afterHandle`/`onError`/`around` apply to its routes\n * exactly as they did standalone, so a group wires its own plugins. The group's request-level\n * hooks (`onRequest`/`onResponse`/`onResponseFinalized`) are appended to this server's. This\n * server's route-scoped chains do NOT retroactively wrap merged routes (order-scoped, like\n * routes registered before a `derive`). Fail closed: a path+method collision throws\n * `RouteConfigError` at merge time, and a group with WebSocket routes is refused (register\n * those on the parent).\n */\n merge<R2 extends Registry, Ctx2>(other: Server<R2, Ctx2>): Server<R & R2, Ctx>;\n /** A fused renderer closes over runtime services to keep its seven-argument JSC fast path. Merging\n * rebinds that closure once to the executing server; generic plans already receive the runtime. */\n private bindFusedRuntime;\n /**\n * Enumerate the registered routes (method, path, input schemas), in registration\n * order. Powers `toOpenAPI` and other introspection; the router trie itself no\n * longer holds the original patterns.\n */\n routes(): ReadonlyArray<RouteDescriptor>;\n /**\n * Resolve a `Request` to a `Response` — the whole lifecycle, testable without a port. The\n * optional `platform` carries edge inputs (`env`, `waitUntil`); edge adapters pass it, and\n * Bun/Node/Deno omit it (then `c.env` is `undefined` and `c.waitUntil` runs fire-and-forget).\n */\n fetch(req: Request, platform?: Platform<EnvOf<Ctx>>): MaybePromise<Response>;\n private fetchSource;\n private fetchSourceInner;\n /** Web response path when Bun already matched the route. The lifecycle and response hooks remain\n * exactly the same as {@link fetchSource}; only portable URL scanning + trie lookup are skipped. */\n private fetchMatched;\n private fetchMatchedInner;\n /**\n * Run `produce` under the capacity gate: admit → run → release exactly once when the response is\n * produced (or the run throws). Only reached when {@link capacityGate} is set, so the off path pays\n * nothing. The slot is held for the duration of handler execution, not the streaming of the body —\n * capacity here bounds concurrent *work*, matching how in-flight is counted.\n */\n private admitGated;\n private runAdmitted;\n /**\n * Like {@link fetch}, but renders a plain-data result **without** building a Web `Response` — the\n * `@nifrajs/node` adapter serializes the returned primitives straight to the socket, skipping the undici\n * `Response` build + body drain (the bulk of the Node bridge cost, measured ≈4µs/req). A handler that\n * returns a `Response`, an error/short-circuit, or any registered `onResponse` hook falls back to the\n * full Web path (`{ kind: \"response\" }`), so behavior is identical — only the common JSON-data case is\n * faster. Same lifecycle as {@link fetch} (body cap, validation, hooks all run); only the final\n * render differs.\n */\n resolveNode(req: Request, platform?: Platform<EnvOf<Ctx>>): MaybePromise<NodeServeOutcome>;\n resolveNodeSource(source: RequestSource, platform?: Platform<EnvOf<Ctx>>, suppliedRuntime?: NodeOutcomeRuntime): MaybePromise<NodeServeOutcome>;\n /**\n * Resolve a WebSocket upgrade — the seam every serving adapter uses. Returns `pass` (not a WS\n * upgrade for a registered route → handle as normal HTTP), `reject` (a WS route matched but\n * `upgrade()` rejected, or the path was malformed → return `response`), or `upgrade` (perform the\n * runtime upgrade, then dispatch the native socket's events to `handler`, seeding `ws.data` with\n * `data`). Runs the route's `upgrade(c)` guard in a real request context. Synchronous unless\n * `upgrade()` is async; a throw rejects with a flat 500 (no detail leaked).\n */\n resolveWebSocketUpgrade(req: Request, platform?: Platform<EnvOf<Ctx>>): MaybePromise<WebSocketUpgradeOutcome>;\n /** Bun `fetch` when WS routes exist: try a WS upgrade first, else run the normal HTTP lifecycle.\n * `undefined` ⇒ Bun owns the upgraded socket; a `Response` ⇒ a normal reply or a rejected upgrade.\n * (The socket dispatch itself lives in `ws-bun.ts`, loaded via `@nifrajs/core/ws`.) */\n private bunFetchWithWebSocket;\n /**\n * The shared lifecycle, generic over how the final value is rendered: `finalize` turns a handler's\n * result + `set` into the output `T` (`toResponse` → a Web `Response`; `toNodeOutcome` → node-direct\n * primitives), `wrapResponse` lifts an early/error `Response` into that same `T`, and `onTimeout`\n * produces the 503. The Web `fetch` and `resolveNode` are thin callers over this one routing +\n * context + lifecycle implementation — no duplication across the trust boundary.\n */\n /** Apply the `clientIp` trust declaration to the adapter's raw socket peer, returning a platform\n * whose `clientIp` is the derived caller. Only called when a trust declaration is configured. */\n private deriveClientIp;\n private dispatch;\n /**\n * onRequest short-circuit path. Synchronous as long as every hook returns synchronously (the\n * common case — e.g. CORS returning `undefined` for a non-preflight request): an `async` version\n * here put EVERY request of any app with one onRequest hook onto the promise machinery, profiled\n * at ~13% of a realistic request. The first hook that returns a Promise hands the REMAINING\n * hooks to the async continuation; behavior is identical.\n */\n private runWithOnRequest;\n /** Async tail of {@link runWithOnRequest}: applies the first awaited hook's outcome, then runs\n * the remaining hooks (awaiting freely — we're already async here). */\n private continueOnRequest;\n private takeResponseRequest;\n /**\n * Route → build context → run. Synchronous through to the handler for a **bare** route\n * (selected by its compiled plan), so a sync handler produces its result with zero promise allocations;\n * routes with validation/hooks keep the full async {@link runLifecycle}, unchanged.\n */\n private routeAndRun;\n /** Run a route that has already been matched by the runtime or Nifra's portable router. */\n private runMatched;\n /** Supply request-specific deadline state to the route's precompiled execution plan. */\n private runMatchedLanes;\n /** @internal Symbol-keyed install seam for the `effectLedger()` plugin. Off the public typed surface. */\n [INSTALL_EFFECT_LEDGER](runtime: EffectLedgerRuntime): void;\n /** The narrowest bare route: a syntactic `() => ...` handler cannot observe the context argument, so\n * successful requests can skip allocating `RequestContext`. Errors still allocate one for logging. */\n private runContextlessBare;\n private contextlessBareError;\n /**\n * The synchronous fast path selected by a route's execution plan: apply static decorations, call the\n * handler, render the result — **no `await`** unless the handler itself returns a promise. It mirrors\n * the bare slice of {@link runLifecycle} (which a bare route would otherwise no-op through) and shares\n * {@link logRequestError}; a bare route has no `onError` hooks, so error handling is fully synchronous\n * (a thrown `Response` is control flow; anything else is a logged flat 500). This is where nifra skips\n * the per-request async-frame tax — the same win codegen routers get, but without `eval`.\n */\n private runBare;\n /** Bare-route error rendering — identical to {@link runLifecycle}'s catch minus the (absent) onError\n * loop: a thrown `Response` is returned as deliberate control flow; anything else is logged + 500. */\n /**\n * Build a route's fused Web renderer. Composition happens once at\n * registration; the returned closure is what every request to the route runs. Behavior is\n * byte-identical to the generic `runBare`/`runContextlessBare` + `toResponse` pair — same\n * decoration order, same error routing (thrown `Response` = control flow; anything else logs and\n * 500s), same respond semantics (the lifecycle parity suite pins it).\n */\n private buildFusedWeb;\n private bareError;\n private runWithAround;\n private runAround;\n private runBodyOnly;\n /** Validate + run the handler for the bodyOnly path — shared by the inline fast path and the\n * streaming fallback. A method (not per-request closures) so the hot path allocates nothing\n * beyond the one `.then` continuation. */\n private finishBodyOnly;\n private executeHandler;\n private handleValidationErrorRecovery;\n private applyBodyValidation;\n private runQueryOnly;\n /** Validate-result → set `ctx.query` → run handler. A method (not a per-request closure), the\n * query analogue of {@link applyBodyValidation}. */\n private applyQueryValidation;\n /**\n * Thread the response through each global `onResponse` hook. Stays SYNCHRONOUS until a hook\n * actually returns a Promise — an `async` version forced a promise + microtask on EVERY response\n * of any app with an onResponse hook (cors/securityHeaders/etag/timing all use onResponse), the\n * same ~13%/req tax the onRequest walk was de-async'd to avoid. The first async hook hands the\n * rest to {@link continueOnResponse}.\n */\n private applyOnResponse;\n private applyOnResponseAndFinalize;\n private completeResponseFinalization;\n private failResponseFinalization;\n /** Notify terminal observers in order while isolating both sync and async failures. */\n private notifyResponseFinalized;\n /** Async tail of {@link applyOnResponse}: runs the remaining hooks once one has gone async. */\n private continueOnResponse;\n /**\n * Bound the response time. On timeout we abort `ctx.signal` (so cancellation-aware\n * handlers can bail) and return 503; the in-flight work keeps running but its\n * result is discarded — JS can't forcibly cancel a promise.\n */\n private withTimeout;\n /**\n * The post-match lifecycle: validate → derive → beforeHandle → handler → afterHandle, with onError.\n * Generic over the render: a success value goes through `finalize(result, set)` (a Web `Response`, or\n * node-direct primitives); an early/error `Response` (validation, thrown, 500) through `wrapResponse`.\n */\n private runLifecycle;\n private handleLifecycleError;\n /** Log an unhandled request error to the (redacting) logger — shared by {@link runLifecycle} and the\n * bare fast path ({@link bareError}) so both record the same fields. Never throws; never leaks. */\n private logRequestError;\n private readAndValidateBody;\n /** Apply validation and its recovery hook on the generic lifecycle lane. Recovery is completed\n * before derives/beforeHandle run, matching the body-only and query-only execution lanes. */\n private applyLifecycleValidation;\n /**\n * Read the body as text, capped at `maxBodyBytes`. Rejects (`null`) on a\n * `Content-Length` over the cap *before* buffering, and aborts mid-stream once the\n * running byte count exceeds it — so a lying or absent length can't force us to\n * buffer an oversized payload.\n *\n * Fast path: when a non-chunked request carries a `Content-Length` within the cap,\n * a native `req.json()` is already bounded — under HTTP/1.1 + HTTP/2 framing the\n * runtime delivers at most `Content-Length` bytes — so we skip the manual stream\n * loop and a separate text decode. It trusts the wire\n * *framing*, not the header value: nifra only ever receives framed Requests from the\n * runtime's HTTP server, never a hand-built one with a mismatched length. Chunked or\n * length-less bodies fall through to the streaming byte-cap guard below.\n */\n private readBoundedJson;\n /** Adapt one route's compiled execution plan to Bun's already-matched request shape. Route\n * semantics remain in the plan; this closure only supplies native params and deadline fallback. */\n private compileBunNativeHandler;\n /** Compile portable route registrations into Bun's native route table. Apps with request-rewrite\n * hooks or WebSockets retain the single portable dispatcher because those features must run before\n * route selection/upgrade. Named wildcards also stay on the fallback until Bun exposes their raw\n * capture semantics; static and `:param` routes take the native lane. */\n private buildBunNativeRoutes;\n /**\n * Start a `Bun.serve` instance bound to `port` (use `0` for an ephemeral port).\n *\n * `reusePort` sets `SO_REUSEPORT` so **multiple processes can bind the same port** and the kernel\n * load-balances connections across them — the standard way to use every core (Bun is\n * single-threaded per process). Spawn one process per core, each calling\n * `app.listen(PORT, { reusePort: true })`; see `examples/cluster.ts`. Every process must opt in,\n * and all of them must be the same app. Linux balances ~evenly; macOS accepts the flag but may\n * favor one socket (fine for dev, measure on Linux for production numbers).\n *\n * `hostname` is the bind address, defaulting to Bun's `0.0.0.0` (every interface). Pass\n * `\"127.0.0.1\"` to bind loopback only - an admin surface, a sidecar, or anything that must not be\n * reachable off the box. Omitting it when you meant to restrict is a real exposure, so it is a\n * first-class option rather than something a caller has to drop down to `Bun.serve` for.\n */\n listen(port: number, options?: {\n readonly reusePort?: boolean;\n readonly hostname?: string;\n }): RunningServer;\n /**\n * Gracefully stop: wait for in-flight requests to finish (up to `drainMs`), then\n * issue a single terminal stop — graceful if everything drained, forced if\n * stragglers remain. Safe to call when not listening.\n *\n * The Bun semantics: poll `pendingRequests` (awaiting\n * `stop()`'s promise drops in-flight requests), and decide graceful-vs-forced in\n * ONE call (Bun can't escalate an already-graceful `stop()` to a forced close).\n * New connections may be accepted during the drain window; in a real deploy the\n * load balancer has already stopped routing here, and `drainMs` bounds it.\n */\n stop({ drainMs }?: {\n drainMs?: number;\n }): Promise<void>;\n private installSignalHandlers;\n}",
8072
8575
  "doc": "/**\n * The inline server. Routes are chainable and fully type-inferred. `derive`/\n * `decorate` extend the handler context (`Ctx`) for routes defined *after* them,\n * with full types; `Ctx` is server-only and never touches the client registry.\n *\n * app.decorate(\"db\", db).derive((c) => ({ user: auth(c) }))\n * .get(\"/me\", (c) => c.user) // c.user + c.db are typed\n */"
8073
8576
  },
8074
8577
  {
@@ -8116,7 +8619,7 @@
8116
8619
  "name": "ServerOptions",
8117
8620
  "kind": "interface",
8118
8621
  "package": "@nifrajs/core",
8119
- "signature": "export interface ServerOptions {\n /**\n * Max request body size (bytes), enforced **only when a route declares a body schema** — the cap\n * lives in the schema-validated read path. Default 1_000_000.\n *\n * A route WITHOUT a body schema (raw body, file upload, BYO-validation) that reads `c.req` directly\n * is not auto-bounded — use **`c.boundedBody(maxBytes?)`** / **`c.boundedJson(maxBytes?)`**, which\n * apply this same cap (override per route by passing `maxBytes` — larger for an upload endpoint,\n * smaller to tighten one).\n */\n readonly maxBodyBytes?: number;\n /** Max inbound WebSocket message size (bytes) when `listen()`ing on Bun — frames over this are rejected\n * by the runtime before reaching your handler (so a huge frame can't be JSON-parsed into memory).\n * Default: `maxBodyBytes` (1 MB). */\n readonly wsMaxPayloadBytes?: number;\n /** Per-request timeout (ms): a slower request gets a 503 and `ctx.signal` aborts. 0 disables (default). */\n readonly requestTimeoutMs?: number;\n /**\n * Admit the public `x-nifra-deadline` header and let it shorten local work. Disabled by default:\n * services that participate in trusted cross-service deadline propagation opt in explicitly,\n * while ordinary/public HTTP routes pay no header-admission tax and ignore hostile client values.\n */\n readonly acceptInboundDeadlines?: boolean;\n /**\n * Maximum time accepted from an inbound `x-nifra-deadline`, in milliseconds. An incoming absolute\n * deadline may shorten this cap (and `requestTimeoutMs`, when configured), never extend it.\n * Default 30_000; applies only when `acceptInboundDeadlines` is enabled and the header is present.\n */\n readonly maxInboundDeadlineMs?: number;\n /** When `listen()`ing, install SIGTERM/SIGINT handlers that gracefully `stop()`. Default false. */\n readonly gracefulSignals?: boolean;\n /**\n * Capacity-admission gate (see {@link AdmissionController}). Bounds concurrent in-flight work so a\n * healthy instance sheds load (`429` + `Retry-After`) instead of accepting more than it can finish.\n * Off by default. Enabling it disables the fused native-route fast path (requests route through the\n * shared matched lane where the gate runs); when unset, the request path pays nothing.\n */\n readonly admission?: AdmissionController;\n /**\n * Optional token-only observation hook called by `useCapability(c, id)`. It receives no request,\n * parameters, body, tenant, or values. Routes without capability declarations keep the old hot path.\n */\n readonly onCapabilityUse?: (event: CapabilityUseEvent) => void;\n /**\n * Enable the per-request effect ledger. Each route that declares `schema.capabilities` gets a\n * bounded, token-only ledger; `useCapability(c, id, …)` appends one entry per effect, and the sink\n * receives the sealed ledger when the response settles (only when it recorded entries). Token-only\n * by construction — capability ids, phases, counters, digests; never payloads, values, or the\n * concrete URL (the route *pattern* is recorded). Enabling it moves capability-declaring routes off\n * the fused fast path (they need a per-request context + a settle step); all other routes are\n * unaffected, and when unset the request path pays nothing.\n */\n readonly effectLedger?: EffectLedgerOptions;\n /**\n * Default store backing routes that declare `schema.idempotency` without their own `store`. Defaults\n * to a shared in-process {@link MemoryIdempotencyStore} (created lazily on first idempotent route).\n * Inject a durable store here to make request-scoped dedupe survive restarts app-wide.\n */\n readonly idempotencyStore?: IdempotencyStore;\n /** Structured logger for framework events (redacts secrets). Default: JSON to stderr. */\n readonly logger?: Logger;\n /**\n * App-wide fallback fired when a route **without its own `onValidationError`** fails body/query\n * validation. Same contract as the per-route hook (`(issues, ctx, kind) => Response | repaired-value |\n * undefined`): a route's own hook takes precedence, and a route can fall through to the plain `422` by\n * returning `undefined`. Use it for one app-wide error envelope (like tRPC's `errorFormatter` /\n * Fastify's `setErrorHandler`) instead of repeating a formatter per route.\n */\n readonly onValidationError?: RouteSchema[\"onValidationError\"];\n}"
8622
+ "signature": "export interface ServerOptions {\n /**\n * Max request body size (bytes), enforced **only when a route declares a body schema** - the cap\n * lives in the schema-validated read path. Default 1_000_000.\n *\n * A route WITHOUT a body schema (raw body, file upload, BYO-validation) that reads `c.req` directly\n * is not auto-bounded - use **`c.boundedBody(maxBytes?)`** / **`c.boundedJson(maxBytes?)`**, which\n * apply this same cap (override per route by passing `maxBytes` - larger for an upload endpoint,\n * smaller to tighten one).\n */\n readonly maxBodyBytes?: number;\n /** Max inbound WebSocket message size (bytes) when `listen()`ing on Bun - frames over this are rejected\n * by the runtime before reaching your handler (so a huge frame can't be JSON-parsed into memory).\n * Default: `maxBodyBytes` (1 MB). */\n readonly wsMaxPayloadBytes?: number;\n /** Per-request timeout (ms): a slower request gets a 503 and `ctx.signal` aborts. 0 disables (default). */\n readonly requestTimeoutMs?: number;\n /**\n * How to derive `c.clientIp` behind a reverse proxy or CDN. Omit (default) to trust only the raw\n * socket peer and never believe a forwarded header. Set `{ trustedHops: n }` when the app sits\n * behind `n` proxies you operate (the caller is read from `X-Forwarded-For` past those hops), or\n * `{ header: name }` to trust one edge-set header's first value. Declaring trust the app can't\n * actually enforce lets clients forge their IP, so leave it unset unless a proxy really fronts you.\n */\n readonly clientIp?: ClientIpTrust;\n /**\n * Admit the public `x-nifra-deadline` header and let it shorten local work. Disabled by default:\n * services that participate in trusted cross-service deadline propagation opt in explicitly,\n * while ordinary/public HTTP routes pay no header-admission tax and ignore hostile client values.\n */\n readonly acceptInboundDeadlines?: boolean;\n /**\n * Maximum time accepted from an inbound `x-nifra-deadline`, in milliseconds. An incoming absolute\n * deadline may shorten this cap (and `requestTimeoutMs`, when configured), never extend it.\n * Default 30_000; applies only when `acceptInboundDeadlines` is enabled and the header is present.\n */\n readonly maxInboundDeadlineMs?: number;\n /** When `listen()`ing, install SIGTERM/SIGINT handlers that gracefully `stop()`. Default false. */\n readonly gracefulSignals?: boolean;\n /**\n * Capacity-admission gate (see {@link AdmissionController}). Bounds concurrent in-flight work so a\n * healthy instance sheds load (`429` + `Retry-After`) instead of accepting more than it can finish.\n * Off by default. Enabling it disables the fused native-route fast path (requests route through the\n * shared matched lane where the gate runs); when unset, the request path pays nothing.\n */\n readonly admission?: AdmissionController;\n /**\n * Optional token-only observation hook called by `useCapability(c, id)`. It receives no request,\n * parameters, body, tenant, or values. Routes without capability declarations keep the old hot path.\n */\n readonly onCapabilityUse?: (event: CapabilityUseEvent) => void;\n /** Structured logger for framework events (redacts secrets). Default: JSON to stderr. */\n readonly logger?: Logger;\n /**\n * App-wide fallback fired when a route **without its own `onValidationError`** fails body/query\n * validation. Same contract as the per-route hook (`(issues, ctx, kind) => Response | repaired-value |\n * undefined`): a route's own hook takes precedence, and a route can fall through to the plain `422` by\n * returning `undefined`. Use it for one app-wide error envelope (like tRPC's `errorFormatter` /\n * Fastify's `setErrorHandler`) instead of repeating a formatter per route.\n */\n readonly onValidationError?: RouteSchema[\"onValidationError\"];\n}"
8120
8623
  },
8121
8624
  {
8122
8625
  "name": "ServeStaticOptions",
@@ -8179,6 +8682,13 @@
8179
8682
  "signature": "export interface SessionStore {\n /** The record for `id`, or `undefined` on a miss. */\n get(id: string): Promise<SessionRecord | undefined>;\n /** Store (or overwrite) the record for `id`. */\n set(id: string, record: SessionRecord): Promise<void>;\n /** Drop `id` (logout / regeneration). A no-op if absent. */\n delete(id: string): Promise<void>;\n}",
8180
8683
  "doc": "/**\n * Pluggable session backend (store mode). Async so a network store (KV/Redis) fits the same shape.\n * **Production needs a shared/durable store** so sessions hold across instances — {@link MemorySessionStore}\n * prod-guards against the per-instance footgun.\n */"
8181
8684
  },
8685
+ {
8686
+ "name": "SessionUserOf",
8687
+ "kind": "type",
8688
+ "package": "@nifrajs/better-auth",
8689
+ "signature": "export type SessionUserOf<A extends BetterAuthLike> = SessionOf<A> extends {\n user: infer U;\n} ? U : unknown;",
8690
+ "doc": "/**\n * The non-null user type of a concrete better-auth instance `A` (`SessionOf<A>[\"user\"]`). Collapses to\n * `unknown` only for the erased structural `BetterAuthLike`; a real instance recovers the concrete user.\n */"
8691
+ },
8182
8692
  {
8183
8693
  "name": "setBrowserNavigate",
8184
8694
  "kind": "function",
@@ -8234,13 +8744,6 @@
8234
8744
  "signature": "export type SetSearchParams = (next: SearchParamsInit | ((prev: URLSearchParams) => SearchParamsInit), options?: NavigateOptions) => void;",
8235
8745
  "doc": "/** Set the query string. Accepts a `URLSearchParams`, a record, a raw string, or an updater of the\n * current params; navigates to the same pathname with the new query (push, or replace via options). */"
8236
8746
  },
8237
- {
8238
- "name": "setWsRuntime",
8239
- "kind": "function",
8240
- "package": "@nifrajs/core",
8241
- "signature": "export declare function setWsRuntime(impl: WsRuntime): void;",
8242
- "doc": "/** Called by `@nifrajs/core/ws` on import. Last registration wins (idempotent in practice — there is\n * one implementation; double-import is a no-op re-set of the same functions). */"
8243
- },
8244
8747
  {
8245
8748
  "name": "sha256",
8246
8749
  "kind": "function",
@@ -8273,7 +8776,7 @@
8273
8776
  "kind": "type",
8274
8777
  "package": "@nifrajs/middleware",
8275
8778
  "signature": "export type ShedReason = \"inflight\" | \"loop-lag\" | \"queue-timeout\" | \"policy\" | \"cancelled\";",
8276
- "doc": "/**\n * Adaptive capacity admission. Rate limiting bounds request *frequency* and `@nifrajs/budget` bounds\n * request *duration*; neither stops a healthy instance from accepting more *concurrent* work than it\n * can finish. This gate admits on live capacity evidence — in-flight count + event-loop lag — briefly\n * queues at the edge, and sheds the rest with `429` + `Retry-After`, so p99 stays bounded under load\n * instead of collapsing.\n *\n * Public mechanics (in-flight + loop lag) know nothing about tenants. An application-supplied {@link AdmissionPolicy}\n * hook layers tenant priority and reserved capacity on top without leaking\n * those concerns into the OSS core.\n *\n * Wire it as the server's `admission` option (NOT an `onRequest` hook — a hook disables the native\n * route table). Off by default: when unset, the request path is untouched.\n */"
8779
+ "doc": "/**\n * Adaptive capacity admission. Rate limiting bounds request *frequency* and `@nifrajs/core/budget` bounds\n * request *duration*; neither stops a healthy instance from accepting more *concurrent* work than it\n * can finish. This gate admits on live capacity evidence — in-flight count + event-loop lag — briefly\n * queues at the edge, and sheds the rest with `429` + `Retry-After`, so p99 stays bounded under load\n * instead of collapsing.\n *\n * Public mechanics (in-flight + loop lag) know nothing about tenants. An application-supplied {@link AdmissionPolicy}\n * hook layers tenant priority and reserved capacity on top without leaking\n * those concerns into the OSS core.\n *\n * Wire it as the server's `admission` option (NOT an `onRequest` hook — a hook disables the native\n * route table). Off by default: when unset, the request path is untouched.\n */"
8277
8780
  },
8278
8781
  {
8279
8782
  "name": "signal",
@@ -8390,12 +8893,6 @@
8390
8893
  "signature": "export interface SizeReport {\n /** Per-chunk sizes, sorted biggest gzip first (the regression you want to see at the top). */\n readonly chunks: readonly ChunkSize[];\n /** Sum of every chunk's raw bytes. */\n readonly totalBytes: number;\n /** Sum of every chunk's gzip bytes. */\n readonly totalGzip: number;\n}",
8391
8894
  "doc": "/** A whole build's size report — every chunk (largest first) + the totals. */"
8392
8895
  },
8393
- {
8394
- "name": "SkippedRoute",
8395
- "kind": "interface",
8396
- "package": "@nifrajs/core",
8397
- "signature": "export interface SkippedRoute {\n readonly method: string;\n readonly path: string;\n readonly reason: string;\n}"
8398
- },
8399
8896
  {
8400
8897
  "name": "snapshotCapabilities",
8401
8898
  "kind": "function",
@@ -8438,6 +8935,13 @@
8438
8935
  "signature": "export declare function solidMdxBunPlugin(generate: \"dom\" | \"ssr\"): BunPlugin;",
8439
8936
  "doc": "/** Build a `Bun.build` plugin that loads `.mdx` files as Solid components. `generate`: `\"ssr\"` for the\n * server build, `\"dom\"` for the client (matches `solidBunPlugin`). */"
8440
8937
  },
8938
+ {
8939
+ "name": "solidSvgComponentBunPlugin",
8940
+ "kind": "function",
8941
+ "package": "@nifrajs/web-solid",
8942
+ "signature": "export declare function solidSvgComponentBunPlugin(generate: \"dom\" | \"ssr\"): BunPlugin;",
8943
+ "doc": "/** The Solid SVG-component plugin. `generate` selects the Solid `\"dom\"`/`\"ssr\"` output, matching\n * `solidBunPlugin`. A plain `import \"./icon.svg\"` (asset URL) is untouched - only `?component` matches. */"
8944
+ },
8441
8945
  {
8442
8946
  "name": "SourceFinding",
8443
8947
  "kind": "interface",
@@ -8445,13 +8949,6 @@
8445
8949
  "signature": "export interface SourceFinding {\n readonly file: string;\n readonly line: number;\n readonly snippet: string;\n}",
8446
8950
  "doc": "/**\n * `nifra check` — the agent's (and CI's) definition of done. It makes the guarantees that keep a nifra\n * app drift-proof actually *fire*, instead of relying on the agent to remember them:\n *\n * 1. **typecheck** (`tsc --noEmit`) — the frontend↔backend contract is compiler-enforced. The typed\n * client derives request + response types from the routes, so a shape mismatch is a type error.\n * 2. **typed-client lint** — flags hand-rolled `fetch()` to this app's *own* API (a relative URL),\n * which bypasses `client<typeof app>` so the compiler can't see the drift.\n * 3. **server-only-import lint** — flags a top-level import of server-only code (a DB driver, `node:`/\n * `bun:` builtins, the `./db` module) into a `routes/` page module. Those modules are bundled for\n * the browser too, so the import ships server code to the client and breaks the build — the #1\n * full-stack footgun. Reach server resources via `c.db` / `ctx.api`, never a top-level import.\n *\n * `collectCheckResult` returns a structured, machine-readable result (consumed by `--json` and the\n * `nifra_check` MCP tool, so an agent acts on diagnostics instead of scraping prose). Exits non-zero if\n * anything fails. Pure scanners (`scanFetchText`, `scanServerOnlyImports`) are unit-tested.\n */"
8447
8951
  },
8448
- {
8449
- "name": "SpanExporter",
8450
- "kind": "type",
8451
- "package": "@nifrajs/otel",
8452
- "signature": "export type SpanExporter = ObservationAdapter;",
8453
- "doc": "/** Backwards-compatible name for an observation sink. */"
8454
- },
8455
8952
  {
8456
8953
  "name": "SpanStatus",
8457
8954
  "kind": "type",
@@ -8499,6 +8996,12 @@
8499
8996
  "signature": "export interface SSEMessage {\n readonly data?: string;\n readonly event?: string;\n readonly id?: string;\n /** Client reconnection delay hint, ms (coerced to an integer). */\n readonly retry?: number;\n /** A `: comment` line (e.g. a keep-alive ping). */\n readonly comment?: string;\n}",
8500
8997
  "doc": "/** One SSE frame. Every field is optional; `data` may be multi-line (emitted as multiple `data:` lines). */"
8501
8998
  },
8999
+ {
9000
+ "name": "SseRuntime",
9001
+ "kind": "interface",
9002
+ "package": "@nifrajs/core",
9003
+ "signature": "export interface SseRuntime {\n response<Event>(context: SSEContext, run: (stream: TypedSSEStream<Event>) => void | Promise<void>, init?: SSEInit): Response;\n}"
9004
+ },
8502
9005
  {
8503
9006
  "name": "SSEStream",
8504
9007
  "kind": "interface",
@@ -8525,6 +9028,12 @@
8525
9028
  "signature": "export interface StandardIssue {\n readonly message: string;\n}",
8526
9029
  "doc": "/**\n * Minimal Standard Schema surface (the public https://standardschema.dev v1 spec), inlined so\n * `@nifrajs/env` stays dependency-free and accepts validators from `t` (@nifrajs/schema), zod, valibot,\n * or its own coercing `env.*` helpers interchangeably.\n */"
8527
9030
  },
9031
+ {
9032
+ "name": "StandardIssue",
9033
+ "kind": "interface",
9034
+ "package": "@nifrajs/mcp",
9035
+ "signature": "export interface StandardIssue {\n readonly message: string;\n readonly path?: ReadonlyArray<PropertyKey | {\n readonly key: PropertyKey;\n }> | undefined;\n}"
9036
+ },
8528
9037
  {
8529
9038
  "name": "StandardPathSegment",
8530
9039
  "kind": "interface",
@@ -8550,6 +9059,12 @@
8550
9059
  "signature": "export type StandardResult<Output> = {\n readonly value: Output;\n readonly issues?: undefined;\n} | {\n readonly issues: ReadonlyArray<{\n readonly message: string;\n }>;\n};",
8551
9060
  "doc": "/** The validate-result half of the Standard Schema spec. */"
8552
9061
  },
9062
+ {
9063
+ "name": "StandardResult",
9064
+ "kind": "type",
9065
+ "package": "@nifrajs/mcp",
9066
+ "signature": "export type StandardResult<Output> = {\n readonly value: Output;\n readonly issues?: undefined;\n} | {\n readonly issues: ReadonlyArray<StandardIssue>;\n};"
9067
+ },
8553
9068
  {
8554
9069
  "name": "StandardSchemaProps",
8555
9070
  "kind": "interface",
@@ -8576,6 +9091,13 @@
8576
9091
  "signature": "export interface StandardSchemaV1<Output = unknown> {\n readonly \"~standard\": {\n readonly version: 1;\n readonly vendor: string;\n readonly validate: (value: unknown) => StandardResult<Output> | Promise<StandardResult<Output>>;\n readonly types?: {\n readonly input: unknown;\n readonly output: Output;\n };\n };\n}",
8577
9092
  "doc": "/** A minimal structural view of a Standard Schema validator (v1). `t.object(...)` satisfies it. */"
8578
9093
  },
9094
+ {
9095
+ "name": "StandardSchemaV1",
9096
+ "kind": "interface",
9097
+ "package": "@nifrajs/mcp",
9098
+ "signature": "export interface StandardSchemaV1<Input = unknown, Output = Input> {\n readonly \"~standard\": {\n readonly version: 1;\n readonly vendor: string;\n readonly validate: (value: unknown) => StandardResult<Output> | Promise<StandardResult<Output>>;\n readonly types?: {\n readonly input: Input;\n readonly output: Output;\n } | undefined;\n };\n}",
9099
+ "doc": "/**\n * The Standard Schema v1 interface (https://standardschema.dev), vendored as types + a tiny\n * runtime so any compliant validator - nifra's `t`, zod, valibot, arktype, … - can type and\n * validate tool arguments without coupling this package to a validator. The spec is MIT-licensed\n * and explicitly designed to be copied; this package stays dependency-free.\n */"
9100
+ },
8579
9101
  {
8580
9102
  "name": "StandardSuccess",
8581
9103
  "kind": "interface",
@@ -8745,6 +9267,13 @@
8745
9267
  "signature": "export interface StoredResponse {\n readonly status: number;\n readonly headers: readonly (readonly [string, string])[];\n /** Base64-encoded response body; `\"\"` when the response had no body. */\n readonly body: string;\n}",
8746
9268
  "doc": "/** A serialized response held by a store. `body` is base64 so binary payloads round-trip intact. */"
8747
9269
  },
9270
+ {
9271
+ "name": "streaming",
9272
+ "kind": "function",
9273
+ "package": "@nifrajs/core",
9274
+ "signature": "export declare function streaming(): IdentityPlugin;",
9275
+ "doc": "/**\n * Enable `.sse()` streaming routes: `.use(streaming())` installs the SSE runtime. Without it, an\n * `.sse()` route is a registration error, so the ReadableStream framing stays out of non-SSE bundles.\n * The `sse()` / `typedSSEStream()` helpers ship from this same subpath for use inside handlers.\n */"
9276
+ },
8748
9277
  {
8749
9278
  "name": "string",
8750
9279
  "kind": "function",
@@ -8832,11 +9361,93 @@
8832
9361
  "signature": "export declare function svelteMdxBunPlugin(generate: \"dom\" | \"ssr\"): BunPlugin;",
8833
9362
  "doc": "/** Build a `Bun.build` plugin that loads `.mdx` files as Svelte components via mdsvex. `generate`:\n * `\"ssr\"` for the server build, `\"dom\"` for the client (matches `svelteBunPlugin`). */"
8834
9363
  },
9364
+ {
9365
+ "name": "svelteSvgComponentBunPlugin",
9366
+ "kind": "function",
9367
+ "package": "@nifrajs/web-svelte",
9368
+ "signature": "export declare function svelteSvgComponentBunPlugin(generate: \"dom\" | \"ssr\"): BunPlugin;",
9369
+ "doc": "/** The Svelte SVG-component plugin. `generate` selects Svelte's `\"client\"`/`\"server\"` output, matching\n * `svelteBunPlugin`. */"
9370
+ },
9371
+ {
9372
+ "name": "SVG_COMPONENT_FILTER",
9373
+ "kind": "const",
9374
+ "package": "@nifrajs/web",
9375
+ "signature": "export declare const SVG_COMPONENT_FILTER: RegExp;",
9376
+ "doc": "/** The Bun `onLoad` filter every adapter's SVG-component plugin matches: `*.svg?component`. */"
9377
+ },
9378
+ {
9379
+ "name": "svgComponentBunPlugin",
9380
+ "kind": "function",
9381
+ "package": "@nifrajs/web",
9382
+ "signature": "export declare function svgComponentBunPlugin(_generate: \"dom\" | \"ssr\", options?: SvgPluginOptions): BunPlugin;",
9383
+ "doc": "/**\n * The SVG-as-component Bun plugin (React/Preact). `generate` is accepted for parity with the other\n * plugin pairs; the emitted component is the same on `\"dom\"` and `\"ssr\"`.\n */"
9384
+ },
9385
+ {
9386
+ "name": "svgComponentSource",
9387
+ "kind": "function",
9388
+ "package": "@nifrajs/web",
9389
+ "signature": "export declare function svgComponentSource(xml: string, options?: SvgToJsxOptions): string;",
9390
+ "doc": "/** Emit the component module source for a `?component` SVG import. Identical on dom + ssr (isomorphic). */"
9391
+ },
9392
+ {
9393
+ "name": "SvgOptimizer",
9394
+ "kind": "interface",
9395
+ "package": "@nifrajs/web",
9396
+ "signature": "export interface SvgOptimizer {\n optimize(input: string, options?: Record<string, unknown>): {\n readonly data: string;\n };\n}",
9397
+ "doc": "/** The subset of the `svgo` API this plugin uses (structural, so no hard dependency on its types). */"
9398
+ },
9399
+ {
9400
+ "name": "SvgPluginOptions",
9401
+ "kind": "interface",
9402
+ "package": "@nifrajs/web",
9403
+ "signature": "export interface SvgPluginOptions {\n /** Optimize each SVG first. `true` loads the `svgo` peer; pass an optimizer to inject one (or a stub). */\n readonly svgo?: boolean | SvgOptimizer;\n}"
9404
+ },
9405
+ {
9406
+ "name": "svgToJsx",
9407
+ "kind": "function",
9408
+ "package": "@nifrajs/web",
9409
+ "signature": "export declare function svgToJsx(xml: string, options?: SvgToJsxOptions): string;",
9410
+ "doc": "/** Convert an SVG XML string into a JSX-safe `<svg>…</svg>` element with `{...props}` spread on the root. */"
9411
+ },
9412
+ {
9413
+ "name": "SvgToJsxOptions",
9414
+ "kind": "interface",
9415
+ "package": "@nifrajs/web",
9416
+ "signature": "export interface SvgToJsxOptions {\n /** The JSX prop name for `class`. `\"className\"` for React/Preact; `\"class\"` for Solid. */\n readonly classProp?: string;\n}"
9417
+ },
9418
+ {
9419
+ "name": "svgToSvelte",
9420
+ "kind": "function",
9421
+ "package": "@nifrajs/web-svelte",
9422
+ "signature": "export declare function svgToSvelte(xml: string): string;",
9423
+ "doc": "/** Wrap raw SVG XML in a Svelte 5 component: strip XML noise, spread props onto the root `<svg>`. */"
9424
+ },
9425
+ {
9426
+ "name": "svgToVueSfc",
9427
+ "kind": "function",
9428
+ "package": "@nifrajs/web-vue",
9429
+ "signature": "export declare function svgToVueSfc(xml: string): string;",
9430
+ "doc": "/** Wrap raw SVG XML in a template-only Vue SFC (single root → Vue inherits attrs onto the `<svg>`). */"
9431
+ },
9432
+ {
9433
+ "name": "SyncManifestResult",
9434
+ "kind": "interface",
9435
+ "package": "@nifrajs/cli",
9436
+ "signature": "export interface SyncManifestResult {\n /** The committed server-manifest file (relative to cwd). */\n readonly file: string;\n /** True when the file's route table changed and it was rewritten. */\n readonly changed: boolean;\n /** Route files now imported that weren't before (added). */\n readonly added: readonly string[];\n /** Route files no longer imported (removed/renamed away). */\n readonly removed: readonly string[];\n /** Set when the sync was REFUSED because discovery found zero routes for a manifest that had some\n * (`routes/` likely emptied by mistake) - the manifest was left untouched rather than wiped. */\n readonly refusedEmpty?: boolean;\n}",
9437
+ "doc": "/**\n * `nifra sync-manifest` - regenerate a committed web `server-manifest.ts` from the current `routes/` tree\n * WITHOUT a full build. The manifest is a generated file that bakes the route table (+ client-asset hashes)\n * for a disk-less edge worker; after adding/renaming/removing a route it drifts, and `nifra check` flags it.\n * Regenerating it used to require the whole `build` (server + worker + migrate bundles). This re-scans\n * `routes/` and rewrites just the manifest's route table, preserving the baked client-asset references.\n *\n * It does NOT rebuild the client bundle: a brand-new HYDRATING route still needs a full build so its client\n * chunk exists. This clears route-table drift for the common case (a loader edit, an SSR-only route, a\n * rename) in milliseconds, and prints that caveat for the case it can't cover.\n */"
9438
+ },
9439
+ {
9440
+ "name": "syncServerManifests",
9441
+ "kind": "function",
9442
+ "package": "@nifrajs/cli",
9443
+ "signature": "export declare function syncServerManifests(cwd: string): Promise<SyncManifestResult[]>;",
9444
+ "doc": "/**\n * Discover every generated `server-manifest.ts` under `cwd` and re-sync its route table from the live\n * `routes/` tree, preserving baked client assets. Returns one result per generated manifest. Never throws\n * on a per-manifest miss (an unreadable/absent routes dir is skipped).\n */"
9445
+ },
8835
9446
  {
8836
9447
  "name": "t",
8837
9448
  "kind": "const",
8838
9449
  "package": "@nifrajs/schema",
8839
- "signature": "export declare const t: {\n readonly string: (options?: StringOptions) => NifraSchema<import(\"@sinclair/typebox\").TString>;\n readonly number: (options?: NumberOptions) => NifraSchema<import(\"@sinclair/typebox\").TNumber>;\n readonly integer: (options?: IntegerOptions) => NifraSchema<import(\"@sinclair/typebox\").TInteger>;\n readonly boolean: () => NifraSchema<import(\"@sinclair/typebox\").TBoolean>;\n readonly null: () => NifraSchema<import(\"@sinclair/typebox\").TNull>;\n readonly literal: <const L extends TLiteralValue>(value: L) => NifraSchema<import(\"@sinclair/typebox\").TLiteral<L>>;\n readonly object: <P extends Props>(props: P, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TObject<{ [K in keyof P]: P[K][\"jsonSchema\"]; }>>;\n /** Like `t.object` but ACCEPTS (and passes through) unknown fields — the explicit opt-out of the\n * strict default. Prefer `t.object` unless you genuinely need an open object. */\n readonly looseObject: <P extends Props>(props: P, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TObject<{ [K in keyof P]: P[K][\"jsonSchema\"]; }>>;\n readonly array: <T extends TSchema>(item: NifraSchema<T>, options?: ArrayOptions) => NifraSchema<import(\"@sinclair/typebox\").TArray<T>>;\n /** Marks a property optional inside `t.object`; standalone it is `T | undefined`. */\n readonly optional: <T extends TSchema>(schema: NifraSchema<T>) => NifraSchema<T extends import(\"@sinclair/typebox\").TOptional<infer S extends TSchema> ? import(\"@sinclair/typebox\").TOptional<S> : import(\"@sinclair/typebox\").Ensure<import(\"@sinclair/typebox\").TOptional<T>>>;\n readonly union: <const S extends readonly NifraSchema[]>(schemas: S) => NifraSchema<TUnion<{ -readonly [K in keyof S]: S[K][\"jsonSchema\"]; }>>;\n readonly record: <T extends TSchema>(value: NifraSchema<T>, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TRecord<import(\"@sinclair/typebox\").TString, T>>;\n /** A cursor-pagination response envelope: `{ items: T[]; nextCursor: string | null }` (`null` = last page). */\n readonly paginated: <T extends TSchema>(item: NifraSchema<T>, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TObject<{\n items: import(\"@sinclair/typebox\").TArray<T>;\n nextCursor: TUnion<[import(\"@sinclair/typebox\").TString, import(\"@sinclair/typebox\").TNull]>;\n }>>;\n /** A request query schema for cursor pagination: `{ cursor?: string; limit?: number }`. `maxLimit`\n * caps `limit` — a larger value fails validation (a 422), so a client can't request an unbounded page.\n * `coerce` is on because query values arrive as strings (`?limit=20` → `\"20\"`); it's what makes `limit`\n * a real `number` in the handler (`c.query.limit`), not a string. */\n readonly pageQuery: (options?: {\n maxLimit?: number;\n }) => NifraSchema<import(\"@sinclair/typebox\").TObject<{\n cursor: import(\"@sinclair/typebox\").TOptional<import(\"@sinclair/typebox\").TString>;\n limit: import(\"@sinclair/typebox\").TOptional<import(\"@sinclair/typebox\").TInteger>;\n }>>;\n};",
9450
+ "signature": "export declare const t: {\n readonly string: (options?: StringOptions) => NifraSchema<import(\"@sinclair/typebox\").TString>;\n readonly number: (options?: NumberOptions) => NifraSchema<import(\"@sinclair/typebox\").TNumber>;\n readonly integer: (options?: IntegerOptions) => NifraSchema<import(\"@sinclair/typebox\").TInteger>;\n readonly boolean: () => NifraSchema<import(\"@sinclair/typebox\").TBoolean>;\n readonly null: () => NifraSchema<import(\"@sinclair/typebox\").TNull>;\n readonly literal: <const L extends TLiteralValue>(value: L) => NifraSchema<import(\"@sinclair/typebox\").TLiteral<L>>;\n readonly object: <P extends Props>(props: P, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TObject<{ [K in keyof P]: P[K][\"jsonSchema\"]; }>>;\n /** Like `t.object` but ACCEPTS (and passes through) unknown fields — the explicit opt-out of the\n * strict default. Prefer `t.object` unless you genuinely need an open object. */\n readonly looseObject: <P extends Props>(props: P, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TObject<{ [K in keyof P]: P[K][\"jsonSchema\"]; }>>;\n readonly array: <T extends TSchema>(item: NifraSchema<T>, options?: ArrayOptions) => NifraSchema<import(\"@sinclair/typebox\").TArray<T>>;\n /** Marks a property optional inside `t.object`; standalone it is `T | undefined`. */\n readonly optional: <T extends TSchema>(schema: NifraSchema<T>) => NifraSchema<T extends import(\"@sinclair/typebox\").TOptional<infer S extends TSchema> ? import(\"@sinclair/typebox\").TOptional<S> : import(\"@sinclair/typebox\").Ensure<import(\"@sinclair/typebox\").TOptional<T>>>;\n readonly union: <const S extends readonly NifraSchema[]>(schemas: S) => NifraSchema<TUnion<{ -readonly [K in keyof S]: S[K][\"jsonSchema\"]; }>>;\n readonly record: <T extends TSchema>(value: NifraSchema<T>, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TRecord<import(\"@sinclair/typebox\").TString, T>>;\n /** A cursor-pagination response envelope: `{ items: T[]; nextCursor: string | null }` (`null` = last page). */\n readonly paginated: <T extends TSchema>(item: NifraSchema<T>, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TObject<{\n items: import(\"@sinclair/typebox\").TArray<T>;\n nextCursor: TUnion<[import(\"@sinclair/typebox\").TString, import(\"@sinclair/typebox\").TNull]>;\n }>>;\n /** A request query schema for cursor pagination: `{ cursor?: string; limit?: number }`. `maxLimit`\n * caps `limit` — a larger value fails validation (a 422), so a client can't request an unbounded page.\n * `coerce` is on because query values arrive as strings (`?limit=20` → `\"20\"`); it's what makes `limit`\n * a real `number` in the handler (`c.query.limit`), not a string. */\n readonly pageQuery: (options?: {\n maxLimit?: number;\n }) => NifraSchema<import(\"@sinclair/typebox\").TObject<{\n cursor: import(\"@sinclair/typebox\").TOptional<import(\"@sinclair/typebox\").TString>;\n limit: import(\"@sinclair/typebox\").TOptional<import(\"@sinclair/typebox\").TInteger>;\n }>>;\n /** A request-query schema with string->scalar COERCION on. Query values always arrive as strings\n * (`?limit=20` -> `\"20\"`), so a plain `t.object({ limit: t.integer() })` in a `query` slot fails to\n * validate; use `t.query` and `t.integer()`/`t.number()`/`t.boolean()` fields become real numbers/\n * booleans in `c.query`. **Open by default** (unknown query fields pass through — `additionalProperties:\n * true`): query params are read by name, not spread into a DB write, so unknown params (UTM tracking,\n * `fbclid`, etc.) passing through is safe, and rejecting them is a production-only footgun (ad/social\n * traffic appends params your schema never declares, causing 422s that never appear in dev/CI). Pass\n * `{ additionalProperties: false }` to enforce a strict allowlist. This is the query-slot constructor;\n * `t.object` stays the constructor for body slots (no coercion, a JSON body is already typed). */\n readonly query: <P extends Props>(props: P, options?: ObjectOptions) => NifraSchema<import(\"@sinclair/typebox\").TObject<{ [K in keyof P]: P[K][\"jsonSchema\"]; }>>;\n};",
8840
9451
  "doc": "/**\n * The built-in schema builder. Each constructor returns a `NifraSchema` — a\n * Standard Schema whose validated output type flows into `c.body`/`c.query`, and\n * whose `jsonSchema` powers `toOpenAPI`. Options (min/max, length, pattern, …)\n * pass straight through to TypeBox and so become JSON Schema constraints.\n *\n * Composite constructors are generic over the *inner* TypeBox schema `T extends\n * TSchema` (not over `NifraSchema`): reading `.jsonSchema` off a value typed only as\n * `NifraSchema` would erase to the `TSchema` constraint and collapse the output type\n * to `unknown`. Capturing `T` keeps `Static<T>` precise (`string[]`, not\n * `unknown[]`).\n */"
8841
9452
  },
8842
9453
  {
@@ -8909,6 +9520,12 @@
8909
9520
  "package": "@nifrajs/cli",
8910
9521
  "signature": "export interface TestToolResult {\n readonly ok: boolean;\n readonly command: readonly string[];\n readonly durationMs: number;\n readonly exitCode: number | null;\n readonly timedOut: boolean;\n readonly cancelled?: boolean;\n readonly summary: TestSummary;\n readonly stdout: string;\n readonly stderr: string;\n readonly error?: string;\n}"
8911
9522
  },
9523
+ {
9524
+ "name": "TEXT_DECODER",
9525
+ "kind": "const",
9526
+ "package": "@nifrajs/core",
9527
+ "signature": "export declare const TEXT_DECODER: TextDecoder;"
9528
+ },
8912
9529
  {
8913
9530
  "name": "Thenable",
8914
9531
  "kind": "type",
@@ -8920,7 +9537,7 @@
8920
9537
  "name": "timing",
8921
9538
  "kind": "function",
8922
9539
  "package": "@nifrajs/middleware",
8923
- "signature": "export declare function timing(options?: TimingOptions): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").Server<any, any>>;",
9540
+ "signature": "export declare function timing(options?: TimingOptions): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").Server<any, any>>;",
8924
9541
  "doc": "/**\n * Adds a `Server-Timing` response header and typed `c.timing` controls for custom metrics.\n * Put request-rewriting middleware (for example `methodOverride`) before `timing()` so timing is\n * attached to the final routed request.\n */"
8925
9542
  },
8926
9543
  {
@@ -8985,12 +9602,19 @@
8985
9602
  "package": "@nifrajs/cli",
8986
9603
  "signature": "export declare function tokenSetHas(tokens: ReadonlySet<string>, group: SearchTermGroup): boolean;"
8987
9604
  },
9605
+ {
9606
+ "name": "toNodeOutcome",
9607
+ "kind": "function",
9608
+ "package": "@nifrajs/core",
9609
+ "signature": "export declare function toNodeOutcome(result: HandlerResult, set: CtxSet): NodeServeOutcome;",
9610
+ "doc": "/**\n * `finalize` for the node-direct path - mirror of `toResponse` that skips the `Response` build:\n * a plain value becomes pre-stringified JSON primitives (the adapter `JSON.stringify`s once, here, not\n * via `Response.json` + a body drain); a handler-returned `Response` is wrapped as-is, with queued\n * cookies appended exactly as `toResponse` does (so the set-cookie-then-`redirect()` pattern still\n * works on Node).\n */"
9611
+ },
8988
9612
  {
8989
9613
  "name": "ToolAnnotations",
8990
9614
  "kind": "interface",
8991
9615
  "package": "@nifrajs/core",
8992
- "signature": "export interface ToolAnnotations {\n /** Human-readable display title for the tool, distinct from the machine `name`. */\n readonly title?: string;\n /** The tool does not modify its environment (a pure read). */\n readonly readOnlyHint?: boolean;\n /** The tool may perform destructive updates — only meaningful when `readOnlyHint` is not `true`. */\n readonly destructiveHint?: boolean;\n /** Repeated calls with the same arguments have no additional effect beyond the first. */\n readonly idempotentHint?: boolean;\n /** The tool interacts with external entities (an \"open world\" beyond this server). */\n readonly openWorldHint?: boolean;\n}",
8993
- "doc": "/**\n * MCP tool safety hints, surfaced in `tools/list`, that tell an agent how risky a `.tool()` call is — so it\n * can decide whether to auto-invoke or confirm first. All optional; an omitted hint means \"unknown\". Mirrors\n * the MCP spec's tool `annotations`.\n */"
9616
+ "signature": "export interface ToolAnnotations {\n /** Human-readable display title for the tool, distinct from the machine `name`. */\n readonly title?: string;\n /** The tool does not modify its environment (a pure read). */\n readonly readOnlyHint?: boolean;\n /** The tool may perform destructive updates - only meaningful when `readOnlyHint` is not `true`. */\n readonly destructiveHint?: boolean;\n /** Repeated calls with the same arguments have no additional effect beyond the first. */\n readonly idempotentHint?: boolean;\n /** The tool interacts with external entities (an \"open world\" beyond this server). */\n readonly openWorldHint?: boolean;\n}",
9617
+ "doc": "/**\n * MCP tool safety hints, surfaced in `tools/list`, that tell an agent how risky a `.tool()` call is - so it\n * can decide whether to auto-invoke or confirm first. All optional; an omitted hint means \"unknown\". Mirrors\n * the MCP spec's tool `annotations`.\n */"
8994
9618
  },
8995
9619
  {
8996
9620
  "name": "toOpenAPI",
@@ -9012,6 +9636,12 @@
9012
9636
  "signature": "export declare class TopicRegistry {\n private readonly topics;\n private readonly memberships;\n subscribe(topic: string, ws: NifraWebSocket): void;\n unsubscribe(topic: string, ws: NifraWebSocket): void;\n /** Drop every subscription for a connection — called on close so a registry never leaks dead sockets. */\n unsubscribeAll(ws: NifraWebSocket): void;\n /** Send `data` to every connection subscribed to `topic`. Per-socket send errors are isolated. */\n publish(topic: string, data: string | ArrayBufferView | ArrayBuffer): void;\n}",
9013
9637
  "doc": "/**\n * In-process pub/sub for `ws.subscribe(topic)` + `app.publish(topic, data)`. **Single-instance only** —\n * topics live in this process's memory, so a multi-instance deploy (multiple servers behind a load\n * balancer) needs an external fan-out (Redis pub/sub, a Cloudflare Durable Object, NATS, …) bridged to\n * `app.publish`. The same registry instance is shared by an app's connections and its `publish`.\n */"
9014
9638
  },
9639
+ {
9640
+ "name": "toResponse",
9641
+ "kind": "function",
9642
+ "package": "@nifrajs/core",
9643
+ "signature": "export declare function toResponse(result: HandlerResult, set: CtxSet): Response;"
9644
+ },
9015
9645
  {
9016
9646
  "name": "TraceContext",
9017
9647
  "kind": "type",
@@ -9030,14 +9660,14 @@
9030
9660
  "name": "tracing",
9031
9661
  "kind": "function",
9032
9662
  "package": "@nifrajs/otel",
9033
- "signature": "export declare function tracing(options?: TracingOptions): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").Server<any, any>>;",
9663
+ "signature": "export declare function tracing(options?: TracingOptions): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").Server<any, any>>;",
9034
9664
  "doc": "/**\n * Distributed-tracing plugin. Each request continues the inbound trace (or starts one), opens a\n * server span, and ends it on response with the status + HTTP attributes. Idempotent.\n *\n * ```ts\n * app.use(tracing({ exporter: myOtelExporter, serviceName: \"orders-api\" }))\n * // in a handler: fetch(url, { headers: traceHeaders(c.trace) }) // continue the trace downstream\n * ```\n */"
9035
9665
  },
9036
9666
  {
9037
9667
  "name": "TracingOptions",
9038
9668
  "kind": "interface",
9039
9669
  "package": "@nifrajs/otel",
9040
- "signature": "export interface TracingOptions {\n /** Where spans are sent. Default: {@link consoleSpanExporter}. */\n readonly exporter?: SpanExporter;\n /** Additional observation adapters (DevTools, a private redacting backend, metrics, …). */\n readonly adapters?: readonly ObservationAdapter[];\n /** Sets the `service.name` attribute on every span. */\n readonly serviceName?: string;\n /**\n * Set the outbound `traceparent` on the RESPONSE too (handy for browser/client correlation).\n * Default false — most setups only propagate downstream, not back to the caller.\n */\n readonly responseHeader?: boolean;\n /**\n * Optional durable graph recorder. When configured, the request root is appended before the\n * handler runs and recorder failure fails closed. Without one, `c.causality` is still propagated.\n */\n readonly causality?: {\n readonly recorder?: CausalityRecorder;\n /** Injectable epoch clock for deterministic tests. */\n readonly now?: () => number;\n /**\n * Explicit trust gate for service-to-service causality headers. Internet clients are untrusted\n * by default; a false result or thrown/rejected check starts a fresh execution graph.\n */\n readonly acceptInbound?: (request: Request, context: CausalityContext) => boolean | Promise<boolean>;\n };\n}"
9670
+ "signature": "export interface TracingOptions {\n /** Where spans are sent. Default: {@link consoleSpanExporter}. */\n readonly exporter?: ObservationAdapter;\n /** Additional observation adapters (DevTools, a private redacting backend, metrics, …). */\n readonly adapters?: readonly ObservationAdapter[];\n /** Sets the `service.name` attribute on every span. */\n readonly serviceName?: string;\n /**\n * Set the outbound `traceparent` on the RESPONSE too (handy for browser/client correlation).\n * Default false — most setups only propagate downstream, not back to the caller.\n */\n readonly responseHeader?: boolean;\n /**\n * Optional durable graph recorder. When configured, the request root is appended before the\n * handler runs and recorder failure fails closed. Without one, `c.causality` is still propagated.\n */\n readonly causality?: {\n readonly recorder?: CausalityRecorder;\n /** Injectable epoch clock for deterministic tests. */\n readonly now?: () => number;\n /**\n * Explicit trust gate for service-to-service causality headers. Internet clients are untrusted\n * by default; a false result or thrown/rejected check starts a fresh execution graph.\n */\n readonly acceptInbound?: (request: Request, context: CausalityContext) => boolean | Promise<boolean>;\n };\n}"
9041
9671
  },
9042
9672
  {
9043
9673
  "name": "TrailingSlashOptions",
@@ -9077,7 +9707,7 @@
9077
9707
  "name": "trimTrailingSlash",
9078
9708
  "kind": "function",
9079
9709
  "package": "@nifrajs/middleware",
9080
- "signature": "export declare function trimTrailingSlash(options?: TrailingSlashOptions): import(\"@nifrajs/core\").NifraPlugin<import(\"@nifrajs/core\").AnyServer, import(\"@nifrajs/core\").AnyServer>;",
9710
+ "signature": "export declare function trimTrailingSlash(options?: TrailingSlashOptions): import(\"@nifrajs/core/server\").NifraPlugin<import(\"@nifrajs/core/server\").AnyServer, import(\"@nifrajs/core/server\").AnyServer>;",
9081
9711
  "doc": "/**\n * Remove trailing slashes from non-root paths. Redirect mode is the production default because it\n * canonicalizes URLs for clients and caches; rewrite mode is available for compatibility migrations.\n */"
9082
9712
  },
9083
9713
  {
@@ -9140,7 +9770,7 @@
9140
9770
  "kind": "function",
9141
9771
  "package": "@nifrajs/mcp",
9142
9772
  "signature": "export declare function uiResourceMeta(uri: string): Record<string, unknown>;",
9143
- "doc": "/** The MCP Apps `_meta.ui.resourceUri` link, emitted nested (current spec) AND flat (the deprecated\n * `ui/resourceUri`, still read by some hosts) so a tool renders across the transition. */"
9773
+ "doc": "/** The MCP Apps `_meta.ui.resourceUri` link. */"
9144
9774
  },
9145
9775
  {
9146
9776
  "name": "UNBOUNDED_DEADLINE",
@@ -9173,13 +9803,13 @@
9173
9803
  "name": "UpgradePlan",
9174
9804
  "kind": "interface",
9175
9805
  "package": "@nifrajs/cli",
9176
- "signature": "export interface UpgradePlan {\n readonly version: string;\n readonly pins: readonly PinChange[];\n readonly importMoves: readonly ImportChange[];\n readonly notes: readonly string[];\n}"
9806
+ "signature": "export interface UpgradePlan {\n readonly version: string;\n readonly pins: readonly PinChange[];\n readonly dependencyMoves: readonly DependencyMoveChange[];\n readonly importMoves: readonly ImportChange[];\n readonly notes: readonly string[];\n}"
9177
9807
  },
9178
9808
  {
9179
9809
  "name": "UpgradeRecipe",
9180
9810
  "kind": "interface",
9181
9811
  "package": "@nifrajs/cli",
9182
- "signature": "export interface UpgradeRecipe {\n readonly version: string;\n readonly pins: readonly PinRule[];\n readonly importMoves: readonly ImportMove[];\n /** Human notes printed after the plan — e.g. structural changes the runner deliberately can't do. */\n readonly notes?: readonly string[];\n}"
9812
+ "signature": "export interface UpgradeRecipe {\n readonly version: string;\n readonly pins: readonly PinRule[];\n readonly dependencyMoves?: readonly DependencyMove[];\n readonly importMoves: readonly ImportMove[];\n /** Human notes printed after the plan — e.g. structural changes the runner deliberately can't do. */\n readonly notes?: readonly string[];\n}"
9183
9813
  },
9184
9814
  {
9185
9815
  "name": "UploadResult",
@@ -9195,6 +9825,12 @@
9195
9825
  "signature": "export declare function url(opts?: Base<string> & Optional): StandardSchemaV1<string | undefined>;",
9196
9826
  "doc": "/** A valid absolute URL (parses with the WHATWG `URL`). Returns the normalized href string. */"
9197
9827
  },
9828
+ {
9829
+ "name": "UrlParts",
9830
+ "kind": "interface",
9831
+ "package": "@nifrajs/core",
9832
+ "signature": "export interface UrlParts {\n readonly pathname: string;\n readonly search: string;\n}"
9833
+ },
9198
9834
  {
9199
9835
  "name": "urlPartsOf",
9200
9836
  "kind": "function",
@@ -9334,6 +9970,13 @@
9334
9970
  "signature": "export declare function useNavigate(): NavigateFunction;",
9335
9971
  "doc": "/** Get the {@link NavigateFunction}. Stable across renders; resolves the browser navigate at call time\n * (so it works as soon as `installHistory` has run, and no-ops before then / on the server). */"
9336
9972
  },
9973
+ {
9974
+ "name": "useNavigation",
9975
+ "kind": "function",
9976
+ "package": "@nifrajs/web-react",
9977
+ "signature": "export declare function useNavigation(): Navigation;",
9978
+ "doc": "/**\n * Observe client navigation to drive loading UI (a top-bar spinner, dimmed content, a skeleton). nifra\n * navigates imperatively - it fetches the next route's chunk + loader data while the current route stays\n * on screen, then swaps - so `pending` is the signal for \"a transition is in flight,\" not a Suspense\n * boundary. Always `{ pending: false, state: \"idle\" }` on the server (loaders block before render), so\n * it is hydration-safe.\n *\n * ```tsx\n * const { pending } = useNavigation()\n * return <div className={pending ? \"opacity-60\" : \"\"}>{pending && <TopBarSpinner />}<Outlet /></div>\n * ```\n */"
9979
+ },
9337
9980
  {
9338
9981
  "name": "useParams",
9339
9982
  "kind": "function",
@@ -9341,6 +9984,13 @@
9341
9984
  "signature": "export declare function useParams<T extends Record<string, string | undefined> = Record<string, string>>(): Readonly<T>;",
9342
9985
  "doc": "/**\n * The matched route's decoded path params — `/users/:id` on `/users/7` → `{ id: \"7\" }`. SSR-correct:\n * `compose` provides the same value server-side (from the request match) and client-side (from router\n * state), so a param rendered into markup doesn't flash on hydration.\n */"
9343
9986
  },
9987
+ {
9988
+ "name": "usePending",
9989
+ "kind": "function",
9990
+ "package": "@nifrajs/web-react",
9991
+ "signature": "export declare function usePending(): boolean;",
9992
+ "doc": "/** Convenience boolean form of {@link useNavigation}: `true` while a client navigation is in flight. */"
9993
+ },
9344
9994
  {
9345
9995
  "name": "useQuery",
9346
9996
  "kind": "function",
@@ -9665,8 +10315,8 @@
9665
10315
  "name": "VERSION",
9666
10316
  "kind": "const",
9667
10317
  "package": "@nifrajs/core",
9668
- "signature": "export declare const VERSION: \"1.13.0\";",
9669
- "doc": "/**\n * Current package version. A hardcoded literal on purpose — core runs on the edge (no fs), so it can't\n * read its own package.json at runtime. `scripts/version.ts` rewrites it on every release bump and\n * `check:publish` asserts it equals `@nifrajs/core`'s package version, so the literal can't go stale\n * (it shipped at \"0.0.0\" through 1.0.0 before those guards existed). Kept narrow (`as const`) so\n * consumers can pin it at the type level — see `test/version.test-d.ts`.\n */"
10318
+ "signature": "export declare const VERSION: \"2.0.0\";",
10319
+ "doc": "/**\n * Current package version. A hardcoded literal on purpose — core runs on the edge (no fs), so it can't\n * read its own package.json at runtime. `scripts/version.ts` rewrites it on every release bump and\n * `check:publish` asserts it equals `@nifrajs/core`'s package version.\n */"
9670
10320
  },
9671
10321
  {
9672
10322
  "name": "ViteDevServer",
@@ -9694,6 +10344,13 @@
9694
10344
  "signature": "export declare function vueBunPlugin(generate: \"dom\" | \"ssr\"): BunPlugin;",
9695
10345
  "doc": "/**\n * The `.vue` compiler Bun plugin. `\"dom\"` → client-hydratable output; `\"ssr\"` → server render. On the\n * `\"dom\"` build, a SFC's `<style>` CSS is emitted as a virtual `?vue-css` module that `Bun.build`'s CSS\n * bundler folds into the app stylesheet (served as a `<link>`). The `\"ssr\"` build emits no CSS — the\n * scope attributes are already in the markup and the stylesheet ships from the client build. With\n * `nifra dev`, `@vitejs/plugin-vue` handles the styles instead.\n */"
9696
10346
  },
10347
+ {
10348
+ "name": "vueSvgComponentBunPlugin",
10349
+ "kind": "function",
10350
+ "package": "@nifrajs/web-vue",
10351
+ "signature": "export declare function vueSvgComponentBunPlugin(generate: \"dom\" | \"ssr\"): BunPlugin;",
10352
+ "doc": "/** The Vue SVG-component plugin. `generate` selects Vue's client/SSR render, matching `vueBunPlugin`. */"
10353
+ },
9697
10354
  {
9698
10355
  "name": "walkServerOnlyChain",
9699
10356
  "kind": "function",
@@ -9747,6 +10404,13 @@
9747
10404
  "signature": "export type WebhookResult = {\n readonly ok: true;\n readonly payload: string;\n} | {\n readonly ok: false;\n readonly reason: WebhookFailureReason;\n};",
9748
10405
  "doc": "/** Verified ⇒ the raw `payload` text (parse it with your schema). Rejected ⇒ a stable `reason`. */"
9749
10406
  },
10407
+ {
10408
+ "name": "websocket",
10409
+ "kind": "function",
10410
+ "package": "@nifrajs/core",
10411
+ "signature": "export declare function websocket(): IdentityPlugin;",
10412
+ "doc": "/**\n * Enable WebSocket routes on a server: `.use(websocket())` turns on `app.ws()`. Applying it twice is\n * a no-op (named plugin dedupe).\n */"
10413
+ },
9750
10414
  {
9751
10415
  "name": "WebSocketContext",
9752
10416
  "kind": "interface",
@@ -9765,14 +10429,14 @@
9765
10429
  "name": "WebSocketHandler",
9766
10430
  "kind": "interface",
9767
10431
  "package": "@nifrajs/core",
9768
- "signature": "export interface WebSocketHandler<Data = unknown, Env = unknown, Schema extends StandardSchemaV1 | undefined = undefined> {\n /**\n * Cross-site WebSocket hijacking (CSWSH) guard — checked BEFORE `upgrade()`. A browser does not\n * apply CORS to WebSocket handshakes and DOES send the page's cookies, so without an Origin check\n * any site can open an authenticated socket to your app. Set this to lock the route to known\n * origins: a string allow-list (exact `Origin` header match) or a predicate. A request whose\n * `Origin` doesn't match (or is absent, for the allow-list form) is rejected with `403` before any\n * per-connection work.\n *\n * **When omitted, the default is same-origin:** a cross-origin BROWSER handshake (an `Origin` header\n * whose host differs from the request's) is rejected with `403`. Non-browser clients (no `Origin`) and\n * same-origin browsers pass. Set this to allow specific cross-origin clients, or `() => true` for a\n * genuinely public socket. Non-browser clients can spoof `Origin`, so this is a browser-CSWSH defense,\n * not authentication — pair it with auth in `upgrade()`.\n */\n allowedOrigins?: ReadonlyArray<string> | ((origin: string | null) => boolean);\n /**\n * Runs in the HTTP request context **before** the upgrade (and after {@link allowedOrigins}) — the\n * place to authenticate or rate-limit. Return the initial per-connection `data` (→ `ws.data`), or a\n * `Response` to **reject** the upgrade (the client never connects). Omit to accept with\n * `data: undefined`. A thrown error rejects with a flat 500.\n */\n upgrade?(c: WebSocketContext<Env>): MaybePromise<Data | Response>;\n /**\n * Contract-first messages: a Standard Schema (`t`, zod, valibot, …) validating each **inbound** frame.\n * Text frames are parsed as JSON first. When set, `message` receives the validated, typed value; a\n * non-JSON or schema-invalid frame is routed to `onInvalidMessage` (or dropped if that's omitted).\n */\n messageSchema?: Schema;\n open?(ws: NifraWebSocket<Data>): MaybePromise<void>;\n message?(ws: NifraWebSocket<Data>, data: WsMessageInput<Schema>): MaybePromise<void>;\n /** Inbound frame that failed JSON parse or `messageSchema` validation (only fires when a schema is\n * set). `raw` is the original frame; `issues` are the Standard Schema issues (one synthetic issue for\n * a JSON parse failure). Omit to silently drop invalid frames. */\n onInvalidMessage?(ws: NifraWebSocket<Data>, issues: ReadonlyArray<StandardIssue>, raw: WebSocketData): MaybePromise<void>;\n close?(ws: NifraWebSocket<Data>, code: number, reason: string): MaybePromise<void>;\n error?(ws: NifraWebSocket<Data>, error: unknown): MaybePromise<void>;\n}",
10432
+ "signature": "export interface WebSocketHandler<Data = unknown, Env = unknown, Schema extends StandardSchemaV1 | undefined = undefined, Send extends StandardSchemaV1 | undefined = undefined> {\n /**\n * Cross-site WebSocket hijacking (CSWSH) guard — checked BEFORE `upgrade()`. A browser does not\n * apply CORS to WebSocket handshakes and DOES send the page's cookies, so without an Origin check\n * any site can open an authenticated socket to your app. Set this to lock the route to known\n * origins: a string allow-list (exact `Origin` header match) or a predicate. A request whose\n * `Origin` doesn't match (or is absent, for the allow-list form) is rejected with `403` before any\n * per-connection work.\n *\n * **When omitted, the default is same-origin:** a cross-origin BROWSER handshake (an `Origin` header\n * whose host differs from the request's) is rejected with `403`. Non-browser clients (no `Origin`) and\n * same-origin browsers pass. Set this to allow specific cross-origin clients, or `() => true` for a\n * genuinely public socket. Non-browser clients can spoof `Origin`, so this is a browser-CSWSH defense,\n * not authentication — pair it with auth in `upgrade()`.\n */\n allowedOrigins?: ReadonlyArray<string> | ((origin: string | null) => boolean);\n /**\n * Runs in the HTTP request context **before** the upgrade (and after {@link allowedOrigins}) — the\n * place to authenticate or rate-limit. Return the initial per-connection `data` (→ `ws.data`), or a\n * `Response` to **reject** the upgrade (the client never connects). Omit to accept with\n * `data: undefined`. A thrown error rejects with a flat 500.\n */\n upgrade?(c: WebSocketContext<Env>): MaybePromise<Data | Response>;\n /**\n * Contract-first messages: a Standard Schema (`t`, zod, valibot, …) validating each **inbound** frame.\n * Text frames are parsed as JSON first. When set, `message` receives the validated, typed value; a\n * non-JSON or schema-invalid frame is routed to `onInvalidMessage` (or dropped if that's omitted).\n */\n messageSchema?: Schema;\n /**\n * The **outbound** frame contract (server → client), a Standard Schema. Purely type-level: it types\n * the frames the typed client's `.ws()` handle receives, and documents what this route pushes. The\n * server does NOT runtime-validate its own sends - the inbound `messageSchema` guards the trust\n * boundary; outbound honesty is the handler author's code, checked by tests.\n */\n sendSchema?: Send;\n open?(ws: NifraWebSocket<Data>): MaybePromise<void>;\n message?(ws: NifraWebSocket<Data>, data: WsMessageInput<Schema>): MaybePromise<void>;\n /** Inbound frame that failed JSON parse or `messageSchema` validation (only fires when a schema is\n * set). `raw` is the original frame; `issues` are the Standard Schema issues (one synthetic issue for\n * a JSON parse failure). Omit to silently drop invalid frames. */\n onInvalidMessage?(ws: NifraWebSocket<Data>, issues: ReadonlyArray<StandardIssue>, raw: WebSocketData): MaybePromise<void>;\n close?(ws: NifraWebSocket<Data>, code: number, reason: string): MaybePromise<void>;\n error?(ws: NifraWebSocket<Data>, error: unknown): MaybePromise<void>;\n}",
9769
10433
  "doc": "/** A WebSocket route's lifecycle. All callbacks optional; only `message` is needed for an echo. */"
9770
10434
  },
9771
10435
  {
9772
10436
  "name": "WebSocketUpgradeOutcome",
9773
10437
  "kind": "type",
9774
10438
  "package": "@nifrajs/core",
9775
- "signature": "export type WebSocketUpgradeOutcome = {\n readonly kind: \"pass\";\n} | {\n readonly kind: \"reject\";\n readonly response: Response;\n} | {\n readonly kind: \"upgrade\";\n readonly handler: WebSocketHandler;\n readonly data: unknown;\n /** The app's pub/sub registry — the adapter wires `ws.subscribe` + close-cleanup to it. */\n readonly pubsub: TopicRegistry;\n};",
10439
+ "signature": "export type WebSocketUpgradeOutcome = {\n readonly kind: \"pass\";\n} | {\n readonly kind: \"reject\";\n readonly response: Response;\n} | {\n readonly kind: \"upgrade\";\n readonly handler: WebSocketHandler;\n readonly data: unknown;\n /** The app's pub/sub registry — the adapter wires `ws.subscribe` + close-cleanup to it. */\n readonly pubsub: TopicRegistry;\n /** The installed runtime's {@link attachWebSocket}, carried on the outcome so an adapter can wire\n * a standard socket without a static import of the WS implementation (which would defeat the\n * `.use(websocket())` tree-shaking). `@nifrajs/workers` may import `attachWebSocket` directly instead. */\n readonly attach: WsAttach;\n};",
9776
10440
  "doc": "/**\n * The outcome of `app.resolveWebSocketUpgrade(req)` — for serving adapters:\n * - `pass` — not a WS upgrade for a registered WS route; handle as a normal HTTP request.\n * - `reject` — a WS route matched but `upgrade()` rejected (or the path was malformed); return `response`.\n * - `upgrade` — perform the runtime upgrade, then dispatch the native socket's events to `handler`,\n * seeding `ws.data` with `data`.\n */"
9777
10441
  },
9778
10442
  {
@@ -9809,6 +10473,20 @@
9809
10473
  "signature": "export declare function withISR(app: ISRApp, options: ISROptions): (req: Request, platform?: ISRPlatform) => Promise<Response>;",
9810
10474
  "doc": "/**\n * Wrap a nifra app with **Incremental Static Regeneration**: a cacheable page is served from\n * {@link CacheStore} when fresh, served **stale while a fresh copy regenerates in the background**\n * (`platform.waitUntil` on edge), or rendered + stored on a miss. Framework-agnostic (it caches the\n * rendered bytes). Returns a `fetch(req, platform?)` handler — hand it to `Bun.serve`/the Workers\n * `export default`, etc. Regeneration is single-flight per key (no stampede on a hot stale page).\n *\n * Each route's freshness comes from the `revalidate` header the app sets (per-route\n * `export const revalidate`), falling back to `options.revalidate`. Only full-document `text/html`\n * GET 200s are cached; everything else (assets, data-mode GETs, redirects, errors) passes through.\n */"
9811
10475
  },
10476
+ {
10477
+ "name": "WithPrincipal",
10478
+ "kind": "type",
10479
+ "package": "@nifrajs/better-auth",
10480
+ "signature": "export type WithPrincipal<S extends AnyServer, P> = S extends Server<infer R, infer C> ? Server<R, C & {\n principal: P;\n}> : never;",
10481
+ "doc": "/** Add `{ principal: P }` to a server's context while preserving its route registry `R` (no collapse to\n * `any`). This is the type that makes `.use(authed(auth))` thread a NON-NULL `c.principal`. */"
10482
+ },
10483
+ {
10484
+ "name": "withResponseValidation",
10485
+ "kind": "function",
10486
+ "package": "@nifrajs/client",
10487
+ "signature": "export declare function withResponseValidation(app: unknown, bridge: FetchFn): FetchFn;",
10488
+ "doc": "/**\n * Wrap the in-process bridge so every response is checked against its route's declared contract.\n * Throws at wrap time when the app cannot enumerate routes - a misconfiguration, not a soft skip.\n */"
10489
+ },
9812
10490
  {
9813
10491
  "name": "withRouteAssurance",
9814
10492
  "kind": "function",
@@ -9862,11 +10540,38 @@
9862
10540
  "signature": "export declare function writeScaffoldRoute(cwd: string, urlPath: string, framework: Framework): Promise<ScaffoldWriteResult>;",
9863
10541
  "doc": "/** Write a scaffolded route stub when the framework has a verified ready-to-write body. The write is\n * intentionally conservative: it refuses non-JSX stubs (where we only return contract guidance) and\n * uses `wx`, so an agent cannot overwrite user work by accident. */"
9864
10542
  },
10543
+ {
10544
+ "name": "WsAttach",
10545
+ "kind": "type",
10546
+ "package": "@nifrajs/core",
10547
+ "signature": "export type WsAttach = (socket: StandardWebSocket, handler: WebSocketHandler, data: unknown, options: {\n openNow: boolean;\n pubsub: TopicRegistry;\n}) => NifraWebSocket;",
10548
+ "doc": "/** The socket-wiring signature the upgrade outcome carries (the installed runtime's `attach`). */"
10549
+ },
10550
+ {
10551
+ "name": "WsCallOptions",
10552
+ "kind": "interface",
10553
+ "package": "@nifrajs/client",
10554
+ "signature": "export interface WsCallOptions {\n query?: Record<string, string | number | boolean>;\n /** WebSocket subprotocols. A browser handshake cannot carry custom headers - authenticate via\n * `upgrade()` reading cookies/query/subprotocol, not an Authorization header. */\n protocols?: string | string[];\n /** Abort to close the socket (same effect as calling `close()`). */\n signal?: AbortSignal;\n /** Socket-level failures (connection refused, abnormal close). */\n onError?: (error: unknown) => void;\n}"
10555
+ },
10556
+ {
10557
+ "name": "WsHandle",
10558
+ "kind": "interface",
10559
+ "package": "@nifrajs/client",
10560
+ "signature": "export interface WsHandle<In, Out> {\n /** Send one typed frame (JSON-encoded). Queued until the socket opens, so it never throws. */\n send(message: In): void;\n /** Async-iterate incoming typed frames. Ends when the socket closes (or `signal` aborts). */\n messages(options?: {\n signal?: AbortSignal;\n }): AsyncIterableIterator<Out>;\n /** Callback form of {@link messages}; returns an unsubscribe. */\n onMessage(callback: (message: Out) => void): () => void;\n /** Resolves when the socket is open (rejects on a connect failure). */\n readonly opened: Promise<void>;\n close(code?: number, reason?: string): void;\n /** The underlying socket, for anything off the typed contract (binary frames, bufferedAmount…). */\n readonly raw: WebSocket;\n}",
10561
+ "doc": "/**\n * A live typed WebSocket connection to an `app.ws()` route. `send` accepts the route's\n * `messageSchema` input type (validated server-side at the trust boundary); received frames are\n * typed from its `sendSchema` and JSON-parsed. Binary frames are not part of the typed contract\n * and are ignored by `messages()`/`onMessage` - use `raw` for them.\n */"
10562
+ },
10563
+ {
10564
+ "name": "WsRouteInfoFor",
10565
+ "kind": "type",
10566
+ "package": "@nifrajs/core",
10567
+ "signature": "export type WsRouteInfoFor<Path extends string, In extends StandardSchemaV1 | undefined, Out extends StandardSchemaV1 | undefined> = {\n readonly params: Params<Path>;\n readonly query: never;\n readonly body: never;\n readonly output: never;\n readonly errors: unknown;\n readonly sse: never;\n readonly ws: {\n readonly in: In extends StandardSchemaV1 ? InferInput<In> : unknown;\n readonly out: Out extends StandardSchemaV1 ? InferOutput<Out> : unknown;\n };\n};",
10568
+ "doc": "/**\n * The registry entry for a WebSocket route (stored under the pseudo-method key `\"WS\"`, so WS routes\n * ride the same path → method map as HTTP routes - no extra Server generic). `in` is the client →\n * server frame type: the `messageSchema`'s INPUT side, since that is what goes on the wire before\n * validation transforms it. `out` is the server → client frame type from `sendSchema` (a type-level\n * contract; the server's own sends are not runtime-validated). Either is `unknown` when undeclared.\n */"
10569
+ },
9865
10570
  {
9866
10571
  "name": "WsRuntime",
9867
10572
  "kind": "interface",
9868
10573
  "package": "@nifrajs/core",
9869
- "signature": "export interface WsRuntime {\n /** `wrapWebSocketMessageValidation` — applied once at `app.ws()` registration. */\n wrapHandler(handler: WebSocketHandler): WebSocketHandler;\n /** One in-process pub/sub registry per app (backs `ws.subscribe` + `app.publish`). */\n createTopics(): TopicRegistry;\n /** The Bun `websocket` config for `listen()` when the app has WS routes. */\n bunHandlers(topics: TopicRegistry): BunWsHandlers;\n /** `attachWebSocket` — wires a standard server socket (Workers `WebSocketPair`) to a handler. */\n attach(socket: StandardWebSocket, handler: WebSocketHandler, data: unknown, options: {\n openNow: boolean;\n pubsub: TopicRegistry;\n }): NifraWebSocket;\n}",
10574
+ "signature": "export interface WsRuntime {\n /** `wrapWebSocketMessageValidation` - applied once at `app.ws()` registration. */\n wrapHandler(handler: WebSocketHandler): WebSocketHandler;\n /** One in-process pub/sub registry per app (backs `ws.subscribe` + `app.publish`). */\n createTopics(): TopicRegistry;\n /** The Bun `websocket` config for `listen()` when the app has WS routes. */\n bunHandlers(topics: TopicRegistry): BunWsHandlers;\n /** `attachWebSocket` - wires a standard server socket (Workers `WebSocketPair`) to a handler. */\n attach(socket: StandardWebSocket, handler: WebSocketHandler, data: unknown, options: {\n openNow: boolean;\n pubsub: TopicRegistry;\n }): NifraWebSocket;\n}",
9870
10575
  "doc": "/** What `@nifrajs/core/ws` registers: everything `server.ts` and `toFetchHandler` need at runtime. */"
9871
10576
  }
9872
10577
  ]