@nifrajs/cli 1.11.0 → 1.12.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.
package/docs/types.json CHANGED
@@ -33,6 +33,24 @@
33
33
  "package": "@nifrajs/otel",
34
34
  "signature": "export interface ActiveObservation {\n readonly span: NifraSpan;\n readonly context: ObservationContext;\n /** Adds a sink to this in-flight span. Re-adding the same adapter is idempotent. */\n addAdapter(adapter: ObservationAdapter): void;\n /** Starts a child that inherits this span's trace identity and sampling decision. */\n startChild(input: Omit<StartObservation, \"parent\" | \"traceparent\">, additionalAdapters?: readonly ObservationAdapter[]): ActiveObservation;\n /**\n * Merge attributes onto the in-flight span — the seam for plugins that learn something mid-request\n * (an authenticated principal, a feature-flag bucket, a cache verdict) after the span opened.\n * Silently ignored once the observation has ended (the exported span is immutable).\n */\n setAttributes(attributes: Readonly<Record<string, AttributeValue>>): void;\n /** Records failure evidence without deciding the final status until the response is known. */\n recordError(error: unknown): void;\n /** Ends and exports once. Repeated calls return the same completed span without notifying again. */\n end(input?: EndObservation): NifraSpan;\n}"
35
35
  },
36
+ {
37
+ "name": "AdapterCertificationError",
38
+ "kind": "class",
39
+ "package": "@nifrajs/testing",
40
+ "signature": "export declare class AdapterCertificationError extends Error {\n readonly report: AdapterCertificationReport;\n constructor(report: AdapterCertificationReport);\n}"
41
+ },
42
+ {
43
+ "name": "AdapterCertificationProfile",
44
+ "kind": "interface",
45
+ "package": "@nifrajs/testing",
46
+ "signature": "export interface AdapterCertificationProfile<Adapter> {\n readonly id: string;\n readonly version: number;\n readonly capabilities: readonly string[];\n readonly checks: readonly CertificationCheck<Adapter>[];\n}"
47
+ },
48
+ {
49
+ "name": "AdapterCertificationReport",
50
+ "kind": "interface",
51
+ "package": "@nifrajs/testing",
52
+ "signature": "export interface AdapterCertificationReport {\n readonly schemaVersion: 1;\n readonly ok: boolean;\n readonly profile: {\n readonly id: string;\n readonly version: number;\n };\n readonly adapterId: string;\n readonly checks: readonly CertificationCheckEvidence[];\n readonly capabilities: readonly CertificationCapabilityEvidence[];\n readonly evidenceHash: string;\n}"
53
+ },
36
54
  {
37
55
  "name": "AddRoute",
38
56
  "kind": "type",
@@ -293,6 +311,12 @@
293
311
  "signature": "export declare function applyResponseHeaders(headers: Headers, res: NodeHeaderSink): void;",
294
312
  "doc": "/**\n * Copy a Web `Response`'s headers onto a Node response, emitting EACH `Set-Cookie` as its own header. The\n * `Headers` iterator (and `.get`) join multiple set-cookie values with \", \", which corrupts cookies — e.g.\n * better-auth's `session_token` + `session_data` collapse into one unparseable cookie and the session is\n * silently lost. `getSetCookie()` returns them split; Node's `setHeader` emits one header per array element.\n */"
295
313
  },
314
+ {
315
+ "name": "assertAdapterCertification",
316
+ "kind": "function",
317
+ "package": "@nifrajs/testing",
318
+ "signature": "export declare function assertAdapterCertification(report: AdapterCertificationReport): void;"
319
+ },
296
320
  {
297
321
  "name": "assertAdversarialContract",
298
322
  "kind": "function",
@@ -905,6 +929,12 @@
905
929
  "signature": "export interface CacheStore {\n /** The cached entry for `key`, or `undefined` on a miss. */\n get(key: string): Promise<CachedResponse | undefined>;\n /** Store (or overwrite) the entry for `key`. */\n set(key: string, value: CachedResponse): Promise<void>;\n /** Drop `key` (on-demand revalidation / purge). A no-op if absent. */\n delete(key: string): Promise<void>;\n}",
906
930
  "doc": "/**\n * Pluggable ISR cache backend. **Production deploys MUST use a shared/durable store** (Workers KV,\n * Redis, the platform Cache API) so cached pages *and* revalidation hold across instances;\n * {@link MemoryCacheStore} is dev / single-instance only. Implementations are async so a network store\n * (KV/Redis) fits the same interface.\n */"
907
931
  },
932
+ {
933
+ "name": "cacheStoreCertificationProfile",
934
+ "kind": "function",
935
+ "package": "@nifrajs/testing",
936
+ "signature": "export declare function cacheStoreCertificationProfile(): AdapterCertificationProfile<CertifiableCacheStore>;"
937
+ },
908
938
  {
909
939
  "name": "canAttempt",
910
940
  "kind": "function",
@@ -1097,11 +1127,249 @@
1097
1127
  "package": "@nifrajs/testing",
1098
1128
  "signature": "export interface CaptureIncidentOptions {\n readonly id?: string;\n readonly capturedAt?: string;\n /** Header names to keep on the capsule (lowercased match). Default: only `content-type`. */\n readonly headerAllowList?: readonly string[];\n readonly note?: string;\n}"
1099
1129
  },
1130
+ {
1131
+ "name": "CAUSALITY_EXECUTION_HEADER",
1132
+ "kind": "const",
1133
+ "package": "@nifrajs/core",
1134
+ "signature": "export declare const CAUSALITY_EXECUTION_HEADER = \"x-nifra-execution-id\";"
1135
+ },
1136
+ {
1137
+ "name": "CAUSALITY_KIND_HEADER",
1138
+ "kind": "const",
1139
+ "package": "@nifrajs/core",
1140
+ "signature": "export declare const CAUSALITY_KIND_HEADER = \"x-nifra-causality-kind\";"
1141
+ },
1142
+ {
1143
+ "name": "CAUSALITY_NODE_HEADER",
1144
+ "kind": "const",
1145
+ "package": "@nifrajs/core",
1146
+ "signature": "export declare const CAUSALITY_NODE_HEADER = \"x-nifra-causality-id\";"
1147
+ },
1148
+ {
1149
+ "name": "CAUSALITY_TRACE_HEADER",
1150
+ "kind": "const",
1151
+ "package": "@nifrajs/core",
1152
+ "signature": "export declare const CAUSALITY_TRACE_HEADER = \"x-nifra-causality-trace\";"
1153
+ },
1154
+ {
1155
+ "name": "CausalityCapacityError",
1156
+ "kind": "class",
1157
+ "package": "@nifrajs/core",
1158
+ "signature": "export declare class CausalityCapacityError extends Error {\n readonly maxRecords: number;\n constructor(maxRecords: number);\n}"
1159
+ },
1160
+ {
1161
+ "name": "CausalityConflictError",
1162
+ "kind": "class",
1163
+ "package": "@nifrajs/core",
1164
+ "signature": "export declare class CausalityConflictError extends Error {\n readonly executionId: string;\n readonly node: CausalityRef;\n constructor(executionId: string, node: CausalityRef);\n}"
1165
+ },
1166
+ {
1167
+ "name": "CausalityContext",
1168
+ "kind": "interface",
1169
+ "package": "@nifrajs/core",
1170
+ "signature": "export interface CausalityContext {\n readonly executionId: string;\n readonly current: CausalityRef;\n /** Nearest observed ancestor; downstream observations can attach a real OTel span link to it. */\n readonly trace?: CausalityTrace;\n}",
1171
+ "doc": "/** The propagation shape carried across commands/events/jobs. */"
1172
+ },
1173
+ {
1174
+ "name": "CausalityGraphStore",
1175
+ "kind": "type",
1176
+ "package": "@nifrajs/core",
1177
+ "signature": "export type CausalityGraphStore<Tx = unknown> = CausalityRecorder<Tx> & CausalityReader;"
1178
+ },
1179
+ {
1180
+ "name": "causalityHeaders",
1181
+ "kind": "function",
1182
+ "package": "@nifrajs/core",
1183
+ "signature": "export declare function causalityHeaders(context: CausalityContext): Readonly<Record<string, string>>;",
1184
+ "doc": "/** Serialize the propagation context into bounded HTTP headers. */"
1185
+ },
1186
+ {
1187
+ "name": "CausalityKind",
1188
+ "kind": "type",
1189
+ "package": "@nifrajs/core",
1190
+ "signature": "export type CausalityKind = string;",
1191
+ "doc": "/** A node category such as `request`, `command`, `event`, `workflow`, `projection`, or `repair`. */"
1192
+ },
1193
+ {
1194
+ "name": "CausalityParent",
1195
+ "kind": "interface",
1196
+ "package": "@nifrajs/core",
1197
+ "signature": "export interface CausalityParent extends CausalityRef {\n readonly relation: string;\n}",
1198
+ "doc": "/** One immediate parent edge. Relation is a bounded token (`caused`, `emitted`, `projected`, …). */"
1199
+ },
1200
+ {
1201
+ "name": "CausalityParseResult",
1202
+ "kind": "type",
1203
+ "package": "@nifrajs/core",
1204
+ "signature": "export type CausalityParseResult = {\n readonly success: true;\n readonly context: CausalityContext;\n} | {\n readonly success: false;\n readonly reason: \"missing\" | \"incomplete\" | \"invalid\" | \"unknown-field\";\n};"
1205
+ },
1206
+ {
1207
+ "name": "CausalityReader",
1208
+ "kind": "interface",
1209
+ "package": "@nifrajs/core",
1210
+ "signature": "export interface CausalityReader {\n timeline(executionId: string, options?: {\n readonly after?: string;\n readonly limit?: number;\n }): Promise<CausalityTimelinePage>;\n}"
1211
+ },
1212
+ {
1213
+ "name": "CausalityRecord",
1214
+ "kind": "interface",
1215
+ "package": "@nifrajs/core",
1216
+ "signature": "export interface CausalityRecord {\n readonly executionId: string;\n readonly node: CausalityRef & {\n readonly at: number;\n /** Present only when this node itself opened an observation. */\n readonly trace?: CausalityTrace;\n };\n readonly parents: readonly CausalityParent[];\n}",
1217
+ "doc": "/** One append-only graph record. It intentionally has no payload or metadata field. */"
1218
+ },
1219
+ {
1220
+ "name": "CausalityRecorder",
1221
+ "kind": "interface",
1222
+ "package": "@nifrajs/core",
1223
+ "signature": "export interface CausalityRecorder<Tx = unknown> {\n /** Idempotently append one node and its immediate incoming edges. */\n record(record: CausalityRecord, tx?: Tx): Promise<\"inserted\" | \"duplicate\">;\n}"
1224
+ },
1225
+ {
1226
+ "name": "CausalityRecordParseResult",
1227
+ "kind": "type",
1228
+ "package": "@nifrajs/core",
1229
+ "signature": "export type CausalityRecordParseResult = {\n readonly success: true;\n readonly record: CausalityRecord;\n} | {\n readonly success: false;\n readonly reason: \"incomplete\" | \"invalid\" | \"unknown-field\";\n};"
1230
+ },
1231
+ {
1232
+ "name": "CausalityRef",
1233
+ "kind": "interface",
1234
+ "package": "@nifrajs/core",
1235
+ "signature": "export interface CausalityRef {\n readonly kind: CausalityKind;\n readonly id: string;\n}",
1236
+ "doc": "/** A bounded identity within one execution graph. */"
1237
+ },
1238
+ {
1239
+ "name": "causalitySpanLink",
1240
+ "kind": "function",
1241
+ "package": "@nifrajs/otel",
1242
+ "signature": "export declare function causalitySpanLink(context: CausalityContext): ObservationLink | undefined;",
1243
+ "doc": "/**\n * Convert the nearest observed causal ancestor into an OTel span link. Returns `undefined` instead\n * of inventing a trace identity when the durable context has no observation anchor.\n */"
1244
+ },
1245
+ {
1246
+ "name": "CausalityStep",
1247
+ "kind": "interface",
1248
+ "package": "@nifrajs/core",
1249
+ "signature": "export interface CausalityStep {\n readonly context: CausalityContext;\n readonly record: CausalityRecord;\n}",
1250
+ "doc": "/** A propagation context plus the graph record a durable adapter should append. */"
1251
+ },
1252
+ {
1253
+ "name": "CausalityTimelineItem",
1254
+ "kind": "interface",
1255
+ "package": "@nifrajs/core",
1256
+ "signature": "export interface CausalityTimelineItem {\n readonly cursor: string;\n readonly record: CausalityRecord;\n}"
1257
+ },
1258
+ {
1259
+ "name": "CausalityTimelinePage",
1260
+ "kind": "interface",
1261
+ "package": "@nifrajs/core",
1262
+ "signature": "export interface CausalityTimelinePage {\n readonly items: readonly CausalityTimelineItem[];\n readonly nextCursor?: string;\n}"
1263
+ },
1264
+ {
1265
+ "name": "CausalityTrace",
1266
+ "kind": "interface",
1267
+ "package": "@nifrajs/core",
1268
+ "signature": "export interface CausalityTrace {\n readonly traceId: string;\n readonly spanId: string;\n}",
1269
+ "doc": "/** Optional OpenTelemetry anchor for the nearest observed ancestor. */"
1270
+ },
1271
+ {
1272
+ "name": "CertifiableCacheEntry",
1273
+ "kind": "interface",
1274
+ "package": "@nifrajs/testing",
1275
+ "signature": "export interface CertifiableCacheEntry {\n readonly value: unknown;\n readonly staleAt: number;\n readonly expiresAt: number;\n}"
1276
+ },
1277
+ {
1278
+ "name": "CertifiableCacheStore",
1279
+ "kind": "interface",
1280
+ "package": "@nifrajs/testing",
1281
+ "signature": "export interface CertifiableCacheStore {\n get(key: string): CertifiableCacheEntry | undefined | Promise<CertifiableCacheEntry | undefined>;\n set(key: string, entry: CertifiableCacheEntry, tags: readonly string[]): void | Promise<void>;\n delete(key: string): void | Promise<void>;\n invalidateTag(tag: string): void | Promise<void>;\n clear(): void | Promise<void>;\n}"
1282
+ },
1283
+ {
1284
+ "name": "CertifiableDomainEvent",
1285
+ "kind": "interface",
1286
+ "package": "@nifrajs/testing",
1287
+ "signature": "export interface CertifiableDomainEvent {\n readonly id: string;\n readonly type: string;\n readonly version?: number;\n readonly aggregateId: string;\n readonly payload: unknown;\n readonly timestamp: string;\n}"
1288
+ },
1289
+ {
1290
+ "name": "CertifiableEventDeliveryAdapter",
1291
+ "kind": "interface",
1292
+ "package": "@nifrajs/testing",
1293
+ "signature": "export interface CertifiableEventDeliveryAdapter {\n append(event: CertifiableDomainEvent): Promise<void>;\n claimPending(limit: number, now: string): Promise<CertifiableEventRecord[]>;\n markDelivered(id: string, claimId: string, at: string): Promise<boolean>;\n readPage(options?: {\n readonly after?: string;\n readonly limit?: number;\n }): Promise<{\n readonly records: readonly CertifiableEventRecord[];\n readonly nextPosition: string | null;\n readonly hasMore: boolean;\n }>;\n}"
1294
+ },
1295
+ {
1296
+ "name": "CertifiableEventRecord",
1297
+ "kind": "interface",
1298
+ "package": "@nifrajs/testing",
1299
+ "signature": "export interface CertifiableEventRecord {\n readonly position: string;\n readonly event: CertifiableDomainEvent;\n readonly claimId: string | null;\n}"
1300
+ },
1301
+ {
1302
+ "name": "CertifiableJobStore",
1303
+ "kind": "interface",
1304
+ "package": "@nifrajs/testing",
1305
+ "signature": "export interface CertifiableJobStore {\n enqueue(job: {\n name: string;\n payload: unknown;\n runAt: number;\n maxAttempts: number;\n }): string | Promise<string>;\n lease(now: number, limit: number, leaseMs: number): CertifiableStoredJob[] | Promise<CertifiableStoredJob[]>;\n complete(id: string): void | Promise<void>;\n retry(id: string, runAt: number): void | Promise<void>;\n deadLetter(id: string, error: string): void | Promise<void>;\n counts(): {\n pending: number;\n active: number;\n dead: number;\n } | Promise<{\n pending: number;\n active: number;\n dead: number;\n }>;\n}"
1306
+ },
1307
+ {
1308
+ "name": "CertifiableRuntimeAdapter",
1309
+ "kind": "interface",
1310
+ "package": "@nifrajs/testing",
1311
+ "signature": "export interface CertifiableRuntimeAdapter {\n start(app: {\n fetch(request: Request): Response | Promise<Response>;\n }): CertifiableRuntimeServer | Promise<CertifiableRuntimeServer>;\n}"
1312
+ },
1313
+ {
1314
+ "name": "CertifiableRuntimeServer",
1315
+ "kind": "interface",
1316
+ "package": "@nifrajs/testing",
1317
+ "signature": "export interface CertifiableRuntimeServer {\n readonly origin: string;\n stop(): void | Promise<void>;\n}"
1318
+ },
1319
+ {
1320
+ "name": "CertifiableStorageAdapter",
1321
+ "kind": "interface",
1322
+ "package": "@nifrajs/testing",
1323
+ "signature": "export interface CertifiableStorageAdapter {\n put(key: string, data: Uint8Array | ArrayBuffer | string, options?: {\n readonly contentType?: string;\n readonly metadata?: Readonly<Record<string, string>>;\n }): Promise<void>;\n get(key: string): Promise<CertifiableStorageObject | null>;\n delete(key: string): Promise<void>;\n exists(key: string): Promise<boolean>;\n list(options?: {\n readonly prefix?: string;\n readonly limit?: number;\n }): Promise<string[]>;\n listPage?(options?: {\n readonly prefix?: string;\n readonly limit?: number;\n readonly cursor?: string;\n }): Promise<{\n readonly keys: readonly string[];\n readonly cursor?: string;\n }>;\n presign?(key: string, operation: \"get\" | \"put\", options?: {\n readonly expiresInSeconds?: number;\n readonly contentType?: string;\n readonly contentLength?: number;\n }): Promise<{\n readonly url: string;\n readonly expiresAt?: Date;\n }>;\n copy?(sourceKey: string, destinationKey: string): Promise<void>;\n move?(sourceKey: string, destinationKey: string): Promise<void>;\n}"
1324
+ },
1325
+ {
1326
+ "name": "CertifiableStorageObject",
1327
+ "kind": "interface",
1328
+ "package": "@nifrajs/testing",
1329
+ "signature": "export interface CertifiableStorageObject {\n readonly body: Uint8Array;\n readonly size: number;\n readonly contentType?: string;\n readonly metadata?: Readonly<Record<string, string>>;\n}"
1330
+ },
1331
+ {
1332
+ "name": "CertifiableStoredJob",
1333
+ "kind": "interface",
1334
+ "package": "@nifrajs/testing",
1335
+ "signature": "export interface CertifiableStoredJob {\n readonly id: string;\n readonly name: string;\n readonly payload: unknown;\n readonly attempt: number;\n readonly maxAttempts: number;\n}"
1336
+ },
1337
+ {
1338
+ "name": "CertificationCapabilityEvidence",
1339
+ "kind": "interface",
1340
+ "package": "@nifrajs/testing",
1341
+ "signature": "export interface CertificationCapabilityEvidence {\n readonly capability: string;\n readonly status: \"passed\" | \"failed\";\n readonly checks: readonly string[];\n}"
1342
+ },
1343
+ {
1344
+ "name": "CertificationCheck",
1345
+ "kind": "interface",
1346
+ "package": "@nifrajs/testing",
1347
+ "signature": "export interface CertificationCheck<Adapter> {\n readonly id: string;\n readonly capability: string;\n readonly run: (adapter: Adapter, context: CertificationContext) => void | Promise<void>;\n}"
1348
+ },
1349
+ {
1350
+ "name": "CertificationCheckEvidence",
1351
+ "kind": "interface",
1352
+ "package": "@nifrajs/testing",
1353
+ "signature": "export interface CertificationCheckEvidence {\n readonly id: string;\n readonly capability: string;\n readonly ok: boolean;\n /** Error class only. Messages may contain credentials/provider payloads and are never evidence. */\n readonly errorName?: string;\n}"
1354
+ },
1355
+ {
1356
+ "name": "CertificationContext",
1357
+ "kind": "interface",
1358
+ "package": "@nifrajs/testing",
1359
+ "signature": "export interface CertificationContext {\n /** Deterministic per-check key safe for shared test backends and stable re-runs. */\n readonly key: (suffix: string) => string;\n}",
1360
+ "doc": "/**\n * Profile-based adapter certification. Profiles are structural and dependency-free: an adapter package\n * uses this only in its test/CI surface, while the resulting capability matrix is portable JSON evidence.\n */"
1361
+ },
1362
+ {
1363
+ "name": "certifyAdapter",
1364
+ "kind": "function",
1365
+ "package": "@nifrajs/testing",
1366
+ "signature": "export declare function certifyAdapter<Adapter>(options: {\n readonly profile: AdapterCertificationProfile<Adapter>;\n readonly adapterId: string;\n /** A fresh adapter per check prevents one failed check from contaminating the next. */\n readonly createAdapter: () => Adapter | Promise<Adapter>;\n readonly cleanup?: (adapter: Adapter) => void | Promise<void>;\n}): Promise<AdapterCertificationReport>;"
1367
+ },
1100
1368
  {
1101
1369
  "name": "CheckDiagnostic",
1102
1370
  "kind": "interface",
1103
1371
  "package": "@nifrajs/cli",
1104
- "signature": "export interface CheckDiagnostic {\n readonly rule: \"typecheck\" | \"typed-client\" | \"untyped-client\" | \"server-only-import\" | \"response-route\" | \"undeclared-dependency\" | \"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}",
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}",
1105
1373
  "doc": "/** A single machine-readable check failure — the unit an agent (or CI) acts on. */"
1106
1374
  },
1107
1375
  {
@@ -1250,6 +1518,13 @@
1250
1518
  "signature": "export declare function collectDoctorResult(cwd: string): Promise<DoctorResult>;",
1251
1519
  "doc": "/** Run doctor against the project at `cwd`: diff source imports vs declared deps. */"
1252
1520
  },
1521
+ {
1522
+ "name": "collectDuplicateInstalls",
1523
+ "kind": "function",
1524
+ "package": "@nifrajs/cli",
1525
+ "signature": "export declare function collectDuplicateInstalls(cwd: string, rootPackage: Record<string, unknown>): Promise<DuplicateInstallFinding[]>;",
1526
+ "doc": "/** Find identity-sensitive dependencies that resolve to multiple physical directories. Two copies at\n * the same version still fail: module identity (React hooks, Nifra symbols/registries) is path-based. */"
1527
+ },
1253
1528
  {
1254
1529
  "name": "CollectLevelsOptions",
1255
1530
  "kind": "interface",
@@ -1495,6 +1770,19 @@
1495
1770
  "signature": "export declare function contextStorage(): Middleware;",
1496
1771
  "doc": "/**\n * Store the current nifra `Context` in `AsyncLocalStorage` for helpers that run away from the handler\n * argument, e.g. repository/logger functions called deep in the stack.\n *\n * Import from `@nifrajs/middleware/context-storage` so ordinary `@nifrajs/middleware` imports stay\n * node-compat-free on edge runtimes. The runtime must support `node:async_hooks` AsyncLocalStorage.\n */"
1497
1772
  },
1773
+ {
1774
+ "name": "continueCausality",
1775
+ "kind": "function",
1776
+ "package": "@nifrajs/core",
1777
+ "signature": "export declare function continueCausality(parent: CausalityContext, nodeKind: CausalityKind, id: string, options?: ContinueCausalityOptions): CausalityStep;",
1778
+ "doc": "/** Continue one execution from a single immediate parent. */"
1779
+ },
1780
+ {
1781
+ "name": "ContinueCausalityOptions",
1782
+ "kind": "interface",
1783
+ "package": "@nifrajs/core",
1784
+ "signature": "export interface ContinueCausalityOptions {\n /** Edge relation. Default `caused`. */\n readonly relation?: string;\n /** Epoch milliseconds. Injectable for deterministic tests. Default `Date.now()`. */\n readonly at?: number;\n /** A new observation opened for this exact node; otherwise the nearest anchor is propagated. */\n readonly trace?: CausalityTrace;\n}"
1785
+ },
1498
1786
  {
1499
1787
  "name": "ContractCaseContext",
1500
1788
  "kind": "interface",
@@ -1668,6 +1956,13 @@
1668
1956
  "signature": "export declare function createEventRegistry(contracts: readonly EventContract[]): EventRegistry;",
1669
1957
  "doc": "/** Build a registry from a set of contracts. Throws on a duplicate `type@version`. */"
1670
1958
  },
1959
+ {
1960
+ "name": "createFailureLab",
1961
+ "kind": "function",
1962
+ "package": "@nifrajs/testing",
1963
+ "signature": "export declare function createFailureLab(options: FailureLabOptions): FailureLab;",
1964
+ "doc": "/** Build one isolated deterministic controller. Construct a fresh lab for every replay. */"
1965
+ },
1671
1966
  {
1672
1967
  "name": "createFetcher",
1673
1968
  "kind": "function",
@@ -1714,6 +2009,13 @@
1714
2009
  "package": "@nifrajs/mcp",
1715
2010
  "signature": "export interface CreateMcpServerOptions {\n readonly name: string;\n readonly version: string;\n readonly tools?: readonly McpTool[];\n /** MCP Apps widgets — their resources are registered and the UI capability is advertised. */\n readonly widgets?: readonly McpWidget[];\n /** Extra (non-widget) resources to expose. */\n readonly resources?: readonly McpResource[];\n readonly prompts?: readonly McpPrompt[];\n /** GET health-page text. */\n readonly health?: string;\n /** Max JSON-RPC body size in bytes (default 1 MB). */\n readonly maxBodyBytes?: number;\n}"
1716
2011
  },
2012
+ {
2013
+ "name": "createMemoryCausalityStore",
2014
+ "kind": "function",
2015
+ "package": "@nifrajs/core",
2016
+ "signature": "export declare function createMemoryCausalityStore(options?: MemoryCausalityStoreOptions): CausalityGraphStore;",
2017
+ "doc": "/** Bounded dev/test graph store. Production callers should provide a durable adapter. */"
2018
+ },
1717
2019
  {
1718
2020
  "name": "createMemoryIdempotencyStore",
1719
2021
  "kind": "function",
@@ -2141,6 +2443,13 @@
2141
2443
  "signature": "export declare function defineCapabilityPolicy(policy: CapabilityPolicy): CapabilityPolicy;",
2142
2444
  "doc": "/** Validate and freeze a capability/provenance policy. */"
2143
2445
  },
2446
+ {
2447
+ "name": "defineCertificationProfile",
2448
+ "kind": "function",
2449
+ "package": "@nifrajs/testing",
2450
+ "signature": "export declare function defineCertificationProfile<Adapter>(profile: AdapterCertificationProfile<Adapter>): AdapterCertificationProfile<Adapter>;",
2451
+ "doc": "/** Define and validate a custom domain/provider profile at module initialization. */"
2452
+ },
2144
2453
  {
2145
2454
  "name": "defineContract",
2146
2455
  "kind": "function",
@@ -2413,7 +2722,7 @@
2413
2722
  "name": "DoctorResult",
2414
2723
  "kind": "interface",
2415
2724
  "package": "@nifrajs/cli",
2416
- "signature": "export interface DoctorResult {\n readonly ok: boolean;\n /** `false` when no `package.json` was found at cwd — doctor can't run (reported, not a crash). */\n readonly ran: boolean;\n readonly findings: readonly DoctorFinding[];\n /** Dependencies written by `--auto-fix` / MCP `autoFix:true`. */\n readonly fixed?: readonly DoctorAppliedFix[];\n /** Findings that were safe to report but not safe to write automatically. */\n readonly skippedFixes?: readonly DoctorSkippedFix[];\n}"
2725
+ "signature": "export interface DoctorResult {\n readonly ok: boolean;\n /** `false` when no `package.json` was found at cwd — doctor can't run (reported, not a crash). */\n readonly ran: boolean;\n readonly findings: readonly DoctorFinding[];\n /** Packages that resolve to more than one physical install across this workspace. */\n readonly duplicateInstalls: readonly DuplicateInstallFinding[];\n /** Dependencies written by `--auto-fix` / MCP `autoFix:true`. */\n readonly fixed?: readonly DoctorAppliedFix[];\n /** Findings that were safe to report but not safe to write automatically. */\n readonly skippedFixes?: readonly DoctorSkippedFix[];\n}"
2417
2726
  },
2418
2727
  {
2419
2728
  "name": "DoctorSkippedFix",
@@ -2442,6 +2751,18 @@
2442
2751
  "signature": "export declare function drainCapped(body: ReadableStream<Uint8Array>, maxBytes: number): Promise<{\n ok: true;\n bytes: Uint8Array;\n} | {\n ok: false;\n status: 413;\n}>;",
2443
2752
  "doc": "/** The shared streaming byte-cap loop: read until done, or cancel + 413 once over `maxBytes`.\n * A single-chunk body (the common case for small chunked payloads) returns the runtime's own\n * chunk directly — no chunk array, no copy-merge. */"
2444
2753
  },
2754
+ {
2755
+ "name": "DuplicateInstallCopy",
2756
+ "kind": "interface",
2757
+ "package": "@nifrajs/cli",
2758
+ "signature": "export interface DuplicateInstallCopy {\n /** Installed version, or `unknown` when package metadata is incomplete. */\n readonly version: string;\n /** Physical package directory, relative to the doctor root when possible. */\n readonly path: string;\n /** Workspace package roots whose normal Node/Bun resolution selects this copy. */\n readonly importers: readonly string[];\n}"
2759
+ },
2760
+ {
2761
+ "name": "DuplicateInstallFinding",
2762
+ "kind": "interface",
2763
+ "package": "@nifrajs/cli",
2764
+ "signature": "export interface DuplicateInstallFinding {\n readonly package: string;\n readonly copies: readonly DuplicateInstallCopy[];\n}"
2765
+ },
2445
2766
  {
2446
2767
  "name": "DurableObjectNamespaceLike",
2447
2768
  "kind": "interface",
@@ -2686,7 +3007,7 @@
2686
3007
  "name": "EventContract",
2687
3008
  "kind": "interface",
2688
3009
  "package": "@nifrajs/events",
2689
- "signature": "export interface EventContract<Schema extends StandardSchemaV1 = StandardSchemaV1> {\n readonly type: string;\n readonly version: number;\n readonly payload: Schema;\n /**\n * Validate a payload and stamp a full envelope (`id`, `occurredAt`). Throws {@link EventContractError}\n * on an invalid payload. Sync validators only — an async schema throws (use a sync payload schema for\n * events; the whole point is a cheap boundary check).\n */\n create(payload: InferInput<Schema>, options?: {\n id?: string;\n occurredAt?: string;\n }): EventEnvelope<InferOutput<Schema>>;\n /** Parse untrusted input against this exact contract (type + version + payload). Never throws. */\n parse(input: unknown): EventParseResult<InferOutput<Schema>>;\n /** Boolean guard form of {@link parse}. */\n is(input: unknown): input is EventEnvelope<InferOutput<Schema>>;\n}"
3010
+ "signature": "export interface EventContract<Schema extends StandardSchemaV1 = StandardSchemaV1> {\n readonly type: string;\n readonly version: number;\n readonly payload: Schema;\n /**\n * Validate a payload and stamp a full envelope (`id`, `occurredAt`). Throws {@link EventContractError}\n * on an invalid payload. Sync validators only — an async schema throws (use a sync payload schema for\n * events; the whole point is a cheap boundary check).\n */\n create(payload: InferInput<Schema>, options?: {\n id?: string;\n occurredAt?: string;\n causality?: CausalityContext;\n }): EventEnvelope<InferOutput<Schema>>;\n /** Parse untrusted input against this exact contract (type + version + payload). Never throws. */\n parse(input: unknown): EventParseResult<InferOutput<Schema>>;\n /** Boolean guard form of {@link parse}. */\n is(input: unknown): input is EventEnvelope<InferOutput<Schema>>;\n}"
2690
3011
  },
2691
3012
  {
2692
3013
  "name": "EventContractError",
@@ -2695,11 +3016,17 @@
2695
3016
  "signature": "export declare class EventContractError extends Error {\n readonly type: string;\n readonly version: number;\n readonly issues: readonly StandardIssue[];\n constructor(type: string, version: number, issues: readonly StandardIssue[]);\n}",
2696
3017
  "doc": "/** Thrown by {@link EventContract.create} when the payload fails the contract schema. */"
2697
3018
  },
3019
+ {
3020
+ "name": "eventDeliveryCertificationProfile",
3021
+ "kind": "function",
3022
+ "package": "@nifrajs/testing",
3023
+ "signature": "export declare function eventDeliveryCertificationProfile(): AdapterCertificationProfile<CertifiableEventDeliveryAdapter>;"
3024
+ },
2698
3025
  {
2699
3026
  "name": "EventEnvelope",
2700
3027
  "kind": "interface",
2701
3028
  "package": "@nifrajs/events",
2702
- "signature": "export interface EventEnvelope<Payload = unknown> {\n /** Unique event id (`evt_<uuid>`), stable across redeliveries. */\n readonly id: string;\n /** Event type name, e.g. `order.paid`. */\n readonly type: string;\n /** Contract version. Bump on a breaking payload change; old + new versions coexist in a registry. */\n readonly version: number;\n /** ISO-8601 instant the event occurred. */\n readonly occurredAt: string;\n readonly payload: Payload;\n}",
3029
+ "signature": "export interface EventEnvelope<Payload = unknown> {\n /** Unique event id (`evt_<uuid>`), stable across redeliveries. */\n readonly id: string;\n /** Event type name, e.g. `order.paid`. */\n readonly type: string;\n /** Contract version. Bump on a breaking payload change; old + new versions coexist in a registry. */\n readonly version: number;\n /** ISO-8601 instant the event occurred. */\n readonly occurredAt: string;\n /** Optional durable lineage. Its current node must be this exact event id. */\n readonly causality?: CausalityContext;\n readonly payload: Payload;\n}",
2703
3030
  "doc": "/** The portable wire shape: identity + versioned type + timestamp + validated payload. */"
2704
3031
  },
2705
3032
  {
@@ -2769,6 +3096,61 @@
2769
3096
  "signature": "export declare function extractBackendTools(backend: unknown): McpTool[];",
2770
3097
  "doc": "/** Extract tools registered via .tool() routes on the Nifra backend. Exported for the test that proves a\n * `server().tool()` route surfaces in `tools/list` and executes through `tools/call`. */"
2771
3098
  },
3099
+ {
3100
+ "name": "FailureDirective",
3101
+ "kind": "type",
3102
+ "package": "@nifrajs/testing",
3103
+ "signature": "export type FailureDirective = (FailureDirectiveBase & {\n readonly kind: \"crash\";\n}) | (FailureDirectiveBase & {\n readonly kind: \"duplicate-delivery\";\n /** Total copies of every delivery, including the original. Default 2, maximum 10. */\n readonly copies?: number;\n}) | (FailureDirectiveBase & {\n readonly kind: \"reorder-events\";\n}) | (FailureDirectiveBase & {\n readonly kind: \"delay\";\n readonly delayMs: number;\n}) | (FailureDirectiveBase & {\n readonly kind: \"expire-budget\";\n}) | (FailureDirectiveBase & {\n readonly kind: \"lose-provider-reply\";\n}) | (FailureDirectiveBase & {\n readonly kind: \"contend-checkpoint\";\n});"
3104
+ },
3105
+ {
3106
+ "name": "FailureEvidence",
3107
+ "kind": "interface",
3108
+ "package": "@nifrajs/testing",
3109
+ "signature": "export interface FailureEvidence {\n readonly sequence: number;\n readonly kind: FailureKind;\n readonly point: string;\n readonly occurrence: number;\n readonly virtualTimeMs: number;\n}"
3110
+ },
3111
+ {
3112
+ "name": "FailureInjectedError",
3113
+ "kind": "class",
3114
+ "package": "@nifrajs/testing",
3115
+ "signature": "export declare class FailureInjectedError extends Error {\n readonly kind: \"crash\" | \"lose-provider-reply\";\n readonly point: string;\n readonly occurrence: number;\n readonly name = \"FailureInjectedError\";\n constructor(kind: \"crash\" | \"lose-provider-reply\", point: string, occurrence: number);\n}"
3116
+ },
3117
+ {
3118
+ "name": "FailureKind",
3119
+ "kind": "type",
3120
+ "package": "@nifrajs/testing",
3121
+ "signature": "export type FailureKind = \"crash\" | \"duplicate-delivery\" | \"reorder-events\" | \"delay\" | \"expire-budget\" | \"lose-provider-reply\" | \"contend-checkpoint\";",
3122
+ "doc": "/**\n * Deterministic durable-failure laboratory.\n *\n * The controller is an off-hot-path port: tests place named checkpoints around real adapters and a\n * replayable schedule injects crashes, duplicate/reordered delivery, virtual delay, deadline expiry,\n * lost provider replies, or checkpoint contention. Evidence contains tokens only - never payloads,\n * provider results, exception messages, or stacks.\n */"
3123
+ },
3124
+ {
3125
+ "name": "FailureLab",
3126
+ "kind": "interface",
3127
+ "package": "@nifrajs/testing",
3128
+ "signature": "export interface FailureLab {\n /** Apply virtual delay and/or crash directives at a named durability seam. */\n checkpoint(point: string): void;\n /** Apply duplicate/reorder directives to a delivery batch without inspecting its values. */\n deliveries<T>(point: string, values: readonly T[]): readonly T[];\n /** Run the provider operation, then optionally lose only its reply. */\n provider<T>(point: string, operation: () => T | Promise<T>): Promise<T>;\n /** Return zero when this budget seam is scheduled to expire; otherwise clamp the supplied value. */\n remaining(point: string, remainingMs: number): number;\n /** True only for a scheduled checkpoint conflict occurrence. */\n checkpointContended(point: string): boolean;\n /** Current virtual time. */\n now(): number;\n /** Immutable, token-only injection evidence. */\n evidence(): readonly FailureEvidence[];\n /** Exact normalized replay inputs. */\n replay(): FailureReplay;\n}"
3129
+ },
3130
+ {
3131
+ "name": "FailureLabOptions",
3132
+ "kind": "interface",
3133
+ "package": "@nifrajs/testing",
3134
+ "signature": "export interface FailureLabOptions {\n /** Replayable unsigned seed. Default is stable. */\n readonly seed?: number;\n readonly schedule: readonly FailureDirective[];\n /** Virtual epoch/monotonic start. No real sleep is ever performed. Default 0. */\n readonly startTimeMs?: number;\n}"
3135
+ },
3136
+ {
3137
+ "name": "FailureReplay",
3138
+ "kind": "interface",
3139
+ "package": "@nifrajs/testing",
3140
+ "signature": "export interface FailureReplay {\n readonly seed: number;\n readonly schedule: readonly NormalizedFailureDirective[];\n}"
3141
+ },
3142
+ {
3143
+ "name": "FailureScenario",
3144
+ "kind": "interface",
3145
+ "package": "@nifrajs/testing",
3146
+ "signature": "export interface FailureScenario<Output> {\n readonly name: string;\n execute(lab: FailureLab): Output | Promise<Output>;\n /** The scenario passes only when this post-failure invariant returns true. */\n verify(context: {\n readonly lab: FailureLab;\n readonly result?: Output;\n readonly error?: unknown;\n }): boolean | Promise<boolean>;\n}"
3147
+ },
3148
+ {
3149
+ "name": "FailureScenarioReport",
3150
+ "kind": "interface",
3151
+ "package": "@nifrajs/testing",
3152
+ "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}"
3153
+ },
2772
3154
  {
2773
3155
  "name": "FEATURE_IDS",
2774
3156
  "kind": "const",
@@ -4039,6 +4421,12 @@
4039
4421
  "signature": "export interface JobStore {\n /** Persist a new job; return its id. */\n enqueue(job: {\n name: string;\n payload: unknown;\n runAt: number;\n maxAttempts: number;\n }): string | Promise<string>;\n /** Atomically claim up to `limit` jobs due at/before `now`, hiding them for `leaseMs`. */\n lease(now: number, limit: number, leaseMs: number): StoredJob[] | Promise<StoredJob[]>;\n /** A job finished successfully — remove it. */\n complete(id: string): void | Promise<void>;\n /** A job failed but has attempts left — bump its attempt count and reschedule for `runAt`. */\n retry(id: string, runAt: number): void | Promise<void>;\n /** A job exhausted its attempts — move it to the dead-letter set with the last error. */\n deadLetter(id: string, error: string): void | Promise<void>;\n /** Snapshot counts (observability + tests). */\n counts(): JobCounts | Promise<JobCounts>;\n}",
4040
4422
  "doc": "/**\n * Persistence + leasing for the queue. The default {@link MemoryJobStore} is single-process (dev / a\n * single long-running server); implement this over Redis/Postgres/etc. for durability or multiple\n * workers. All methods may be sync or async — the queue awaits them.\n */"
4041
4423
  },
4424
+ {
4425
+ "name": "jobStoreCertificationProfile",
4426
+ "kind": "function",
4427
+ "package": "@nifrajs/testing",
4428
+ "signature": "export declare function jobStoreCertificationProfile(): AdapterCertificationProfile<CertifiableJobStore>;"
4429
+ },
4042
4430
  {
4043
4431
  "name": "JobValidationError",
4044
4432
  "kind": "class",
@@ -4046,6 +4434,13 @@
4046
4434
  "signature": "export declare class JobValidationError extends Error {\n readonly job: string;\n readonly issues: ReadonlyArray<{\n readonly message: string;\n }>;\n readonly name = \"JobValidationError\";\n constructor(job: string, issues: ReadonlyArray<{\n readonly message: string;\n }>);\n}",
4047
4435
  "doc": "/** Thrown by `enqueue` when the payload fails the job's `input` schema (validation at the trust boundary). */"
4048
4436
  },
4437
+ {
4438
+ "name": "joinCausality",
4439
+ "kind": "function",
4440
+ "package": "@nifrajs/core",
4441
+ "signature": "export declare function joinCausality(parents: readonly CausalityContext[], nodeKind: CausalityKind, id: string, options?: ContinueCausalityOptions): CausalityStep;",
4442
+ "doc": "/** Join several immediate parents. Cross-execution joins fail closed. */"
4443
+ },
4049
4444
  {
4050
4445
  "name": "jsonError",
4051
4446
  "kind": "function",
@@ -4729,6 +5124,12 @@
4729
5124
  "package": "@nifrajs/web",
4730
5125
  "signature": "export interface MemoryCacheStoreOptions {\n /** Allow the in-memory store in production. Off by default — per-instance caching means revalidation\n * won't propagate across instances and each instance caches separately. */\n readonly allowInProduction?: boolean;\n /** Hard cap on entries; the least-recently-used is evicted past it (default 500). */\n readonly max?: number;\n}"
4731
5126
  },
5127
+ {
5128
+ "name": "MemoryCausalityStoreOptions",
5129
+ "kind": "interface",
5130
+ "package": "@nifrajs/core",
5131
+ "signature": "export interface MemoryCausalityStoreOptions {\n /** Global record bound. Default 10,000. */\n readonly maxRecords?: number;\n /** In-memory evidence disappears on restart and is rejected in production unless explicitly allowed. */\n readonly allowInProduction?: boolean;\n}"
5132
+ },
4732
5133
  {
4733
5134
  "name": "MemoryIdempotencyStore",
4734
5135
  "kind": "class",
@@ -5214,7 +5615,7 @@
5214
5615
  "name": "NifraSpan",
5215
5616
  "kind": "interface",
5216
5617
  "package": "@nifrajs/otel",
5217
- "signature": "export interface NifraSpan {\n /** 32-hex W3C trace id — shared across every span/service in the trace. */\n readonly traceId: string;\n /** 16-hex id of this span. */\n readonly spanId: string;\n /** The inbound span's id, if this request continued an upstream trace. */\n readonly parentSpanId?: string;\n /** Whether the trace is sampled (the W3C flag). */\n readonly sampled: boolean;\n /** Span name — `\"<METHOD> <path>\"`. */\n readonly name: string;\n /** Wall-clock start (epoch ms). */\n readonly startTime: number;\n /** Wall-clock end (epoch ms) — set on completion. */\n endTime?: number;\n /** Duration in ms (monotonic). */\n durationMs?: number;\n status: SpanStatus;\n /** OTel-semantic-convention attributes. */\n readonly attributes: Record<string, AttributeValue>;\n}",
5618
+ "signature": "export interface NifraSpan {\n /** 32-hex W3C trace id — shared across every span/service in the trace. */\n readonly traceId: string;\n /** 16-hex id of this span. */\n readonly spanId: string;\n /** The inbound span's id, if this request continued an upstream trace. */\n readonly parentSpanId?: string;\n /** Whether the trace is sampled (the W3C flag). */\n readonly sampled: boolean;\n /** Span name — `\"<METHOD> <path>\"`. */\n readonly name: string;\n /** Wall-clock start (epoch ms). */\n readonly startTime: number;\n /** Wall-clock end (epoch ms) — set on completion. */\n endTime?: number;\n /** Duration in ms (monotonic). */\n durationMs?: number;\n status: SpanStatus;\n /** OTel-semantic-convention attributes. */\n readonly attributes: Record<string, AttributeValue>;\n /** Durable/asynchronous parents that are related but are not this span's single trace parent. */\n readonly links?: readonly ObservationLink[];\n}",
5218
5619
  "doc": "/** A completed (or in-flight) server span for one request. */"
5219
5620
  },
5220
5621
  {
@@ -5309,6 +5710,13 @@
5309
5710
  "package": "@nifrajs/otel",
5310
5711
  "signature": "export interface ObservationLifecycleOptions {\n readonly adapters?: readonly ObservationAdapter[];\n /** Injectable seams are primarily useful for deterministic tests and constrained runtimes. */\n readonly clock?: ObservationClock;\n readonly generateTraceId?: () => string;\n readonly generateSpanId?: () => string;\n}"
5311
5712
  },
5713
+ {
5714
+ "name": "ObservationLink",
5715
+ "kind": "interface",
5716
+ "package": "@nifrajs/otel",
5717
+ "signature": "export interface ObservationLink {\n readonly traceId: string;\n readonly spanId: string;\n readonly attributes?: Readonly<Record<string, AttributeValue>>;\n}",
5718
+ "doc": "/** A non-parent causal relationship to a span in another trace (the OTel `Link` model). */"
5719
+ },
5312
5720
  {
5313
5721
  "name": "ObservationParent",
5314
5722
  "kind": "interface",
@@ -5493,6 +5901,20 @@
5493
5901
  "package": "@nifrajs/cli",
5494
5902
  "signature": "export declare function parseCapabilityLockfile(content: string, sourcePath: string): CapabilitySnapshot;"
5495
5903
  },
5904
+ {
5905
+ "name": "parseCausalityContext",
5906
+ "kind": "function",
5907
+ "package": "@nifrajs/core",
5908
+ "signature": "export declare function parseCausalityContext(input: unknown): CausalityParseResult;",
5909
+ "doc": "/** Parse an untrusted JSON causality context. Unknown fields fail closed so payloads cannot hitchhike. */"
5910
+ },
5911
+ {
5912
+ "name": "parseCausalityRecord",
5913
+ "kind": "function",
5914
+ "package": "@nifrajs/core",
5915
+ "signature": "export declare function parseCausalityRecord(input: unknown): CausalityRecordParseResult;",
5916
+ "doc": "/** Parse an untrusted durable graph record. Unknown fields fail closed at every nesting level. */"
5917
+ },
5496
5918
  {
5497
5919
  "name": "parseContentLength",
5498
5920
  "kind": "function",
@@ -6165,6 +6587,13 @@
6165
6587
  "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}>;",
6166
6588
  "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 */"
6167
6589
  },
6590
+ {
6591
+ "name": "readCausalityHeaders",
6592
+ "kind": "function",
6593
+ "package": "@nifrajs/core",
6594
+ "signature": "export declare function readCausalityHeaders(headers: Headers): CausalityParseResult;",
6595
+ "doc": "/** Parse the public header convention without ever throwing on hostile input. */"
6596
+ },
6168
6597
  {
6169
6598
  "name": "readDeferred",
6170
6599
  "kind": "function",
@@ -7072,7 +7501,7 @@
7072
7501
  "kind": "function",
7073
7502
  "package": "@nifrajs/core",
7074
7503
  "signature": "export declare function runContractInvariants(app: ReflectableApp, options?: RunInvariantsOptions): Promise<InvariantReport>;",
7075
- "doc": "/** Run the contract-derived invariant suite against a reflectable app. Pure; no ambient state. */"
7504
+ "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 */"
7076
7505
  },
7077
7506
  {
7078
7507
  "name": "runDiff",
@@ -7088,6 +7517,13 @@
7088
7517
  "signature": "export declare function runDoctor(cwd: string, opts?: {\n readonly json?: boolean;\n readonly autoFix?: boolean;\n}): Promise<boolean>;",
7089
7518
  "doc": "/** Run doctor; print a report (`--json` for machine output) and return whether it passed. */"
7090
7519
  },
7520
+ {
7521
+ "name": "runFailureScenario",
7522
+ "kind": "function",
7523
+ "package": "@nifrajs/testing",
7524
+ "signature": "export declare function runFailureScenario<Output>(scenario: FailureScenario<Output>, options: FailureLabOptions): Promise<FailureScenarioReport>;",
7525
+ "doc": "/** Run one scenario and evaluate its post-failure invariant without leaking its result or error text. */"
7526
+ },
7091
7527
  {
7092
7528
  "name": "runInitAgents",
7093
7529
  "kind": "function",
@@ -7188,6 +7624,12 @@
7188
7624
  "signature": "export declare function runSnapshot(cwd: string, options: {\n out?: string;\n}): Promise<void>;",
7189
7625
  "doc": "/** `nifra snapshot`: write the current contract as the CI baseline. */"
7190
7626
  },
7627
+ {
7628
+ "name": "runtimeAdapterCertificationProfile",
7629
+ "kind": "function",
7630
+ "package": "@nifrajs/testing",
7631
+ "signature": "export declare function runtimeAdapterCertificationProfile(): AdapterCertificationProfile<CertifiableRuntimeAdapter>;"
7632
+ },
7191
7633
  {
7192
7634
  "name": "runUpgrade",
7193
7635
  "kind": "function",
@@ -7579,7 +8021,7 @@
7579
8021
  "name": "Server",
7580
8022
  "kind": "class",
7581
8023
  "package": "@nifrajs/core",
7582
- "signature": "export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext> {\n private readonly router;\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 routeList;\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 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 /**\n * Every registered route's raw router entry + descriptor, in order — the replay source for\n * {@link merge}. The entry already carries the chains captured at registration (derives,\n * decorations, before/after/around/onError), so a merged route behaves exactly as it did on\n * the server that defined it.\n */\n private readonly rawEntries;\n constructor(options?: ServerOptions);\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 /** 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 /**\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 * ({@link RouteEntry.bare}), 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 /** Run a matched route through its selected execution lane (fused/bare/bodyOnly/queryOnly/lifecycle). */\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 for a {@link RouteEntry.bare} route: 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 lane (see {@link RouteEntry.fusedWeb}). 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 /**\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 /** 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 listen(port: number, options?: {\n readonly reusePort?: boolean;\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}",
8024
+ "signature": "export declare class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext> {\n private readonly router;\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 routeList;\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 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 /**\n * Every registered route's raw router entry + descriptor, in order — the replay source for\n * {@link merge}. The entry already carries the chains captured at registration (derives,\n * decorations, before/after/around/onError), so a merged route behaves exactly as it did on\n * the server that defined it.\n */\n private readonly rawEntries;\n constructor(options?: ServerOptions);\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 /** 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 /**\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 * ({@link RouteEntry.bare}), 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 /** Run a matched route through its selected execution lane (fused/bare/bodyOnly/queryOnly/lifecycle). */\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 for a {@link RouteEntry.bare} route: 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 lane (see {@link RouteEntry.fusedWeb}). 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 /**\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 /** 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}",
7583
8025
  "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 */"
7584
8026
  },
7585
8027
  {
@@ -8106,11 +8548,24 @@
8106
8548
  "signature": "export interface StandardWebSocket {\n send(data: string | ArrayBufferView | ArrayBuffer): void;\n close(code?: number, reason?: string): void;\n readonly readyState: number;\n binaryType?: string;\n addEventListener(type: string, listener: (event: never) => void): void;\n}",
8107
8549
  "doc": "/**\n * A standard server-side `WebSocket` — the half returned by Deno's `Deno.upgradeWebSocket` and the\n * Workers `WebSocketPair`. {@link attachWebSocket} wires one to a nifra handler, so the Deno and Workers\n * bridges share all the dispatch/normalization/error-isolation logic (only the upgrade call differs).\n */"
8108
8550
  },
8551
+ {
8552
+ "name": "startCausality",
8553
+ "kind": "function",
8554
+ "package": "@nifrajs/core",
8555
+ "signature": "export declare function startCausality(nodeKind: CausalityKind, id: string, options: StartCausalityOptions): CausalityStep;",
8556
+ "doc": "/** Start a root execution node at an ingress boundary. */"
8557
+ },
8558
+ {
8559
+ "name": "StartCausalityOptions",
8560
+ "kind": "interface",
8561
+ "package": "@nifrajs/core",
8562
+ "signature": "export interface StartCausalityOptions {\n /** Stable graph identity. Generate once at the ingress boundary, then propagate it. */\n readonly executionId: string;\n /** Epoch milliseconds. Injectable for deterministic tests. Default `Date.now()`. */\n readonly at?: number;\n /** Observation opened for this exact node. */\n readonly trace?: CausalityTrace;\n}"
8563
+ },
8109
8564
  {
8110
8565
  "name": "StartObservation",
8111
8566
  "kind": "interface",
8112
8567
  "package": "@nifrajs/otel",
8113
- "signature": "export interface StartObservation {\n readonly name: string;\n /** Explicit parent. `null` forces a root span; `undefined` falls back to `traceparent`. */\n readonly parent?: ObservationParent | null;\n /** Inbound W3C header used when `parent` is undefined. */\n readonly traceparent?: string | null;\n readonly attributes?: Readonly<Record<string, AttributeValue>>;\n}"
8568
+ "signature": "export interface StartObservation {\n readonly name: string;\n /** Explicit parent. `null` forces a root span; `undefined` falls back to `traceparent`. */\n readonly parent?: ObservationParent | null;\n /** Inbound W3C header used when `parent` is undefined. */\n readonly traceparent?: string | null;\n readonly attributes?: Readonly<Record<string, AttributeValue>>;\n /** Non-parent causal relationships, for example an outbox event that resumed this workflow. */\n readonly links?: readonly ObservationLink[];\n}"
8114
8569
  },
8115
8570
  {
8116
8571
  "name": "StaticPath",
@@ -8146,6 +8601,12 @@
8146
8601
  "signature": "export interface StorageAdapter {\n /** Store `data` under `key`, overwriting any existing object. */\n put(key: string, data: StorageData, options?: PutOptions): Promise<void>;\n /** Read the object at `key`, or `null` if it doesn't exist. */\n get(key: string): Promise<StorageObject | null>;\n /** Remove `key`. No-op if it doesn't exist. */\n delete(key: string): Promise<void>;\n /** Whether an object exists at `key`. */\n exists(key: string): Promise<boolean>;\n /** List stored keys (optionally filtered by prefix + capped). */\n list(options?: ListOptions): Promise<string[]>;\n}",
8147
8602
  "doc": "/**\n * A blob store keyed by string. Keys are POSIX-ish paths (`avatars/u1.png`); every adapter rejects unsafe\n * keys (absolute, `..` traversal, NUL, backslash) so a key valid in one adapter is valid in all. All\n * methods are async.\n */"
8148
8603
  },
8604
+ {
8605
+ "name": "storageAdapterCertificationProfile",
8606
+ "kind": "function",
8607
+ "package": "@nifrajs/testing",
8608
+ "signature": "export declare function storageAdapterCertificationProfile(options?: {\n readonly paging?: boolean;\n readonly presign?: boolean;\n readonly move?: boolean;\n}): AdapterCertificationProfile<CertifiableStorageAdapter>;"
8609
+ },
8149
8610
  {
8150
8611
  "name": "StorageAdapterConformanceError",
8151
8612
  "kind": "class",
@@ -8515,7 +8976,7 @@
8515
8976
  "name": "traceHeaders",
8516
8977
  "kind": "function",
8517
8978
  "package": "@nifrajs/otel",
8518
- "signature": "export declare function traceHeaders(trace: TraceContext): {\n traceparent: string;\n};",
8979
+ "signature": "export declare function traceHeaders(trace: TraceContext, causality?: CausalityContext): {\n readonly traceparent: string;\n} & Readonly<Record<string, string>>;",
8519
8980
  "doc": "/** Spread into an outgoing `fetch`/`ctx.api` call's headers to continue the trace downstream:\n * `fetch(url, { headers: traceHeaders(c.trace) })`. */"
8520
8981
  },
8521
8982
  {
@@ -8529,7 +8990,7 @@
8529
8990
  "name": "TracingOptions",
8530
8991
  "kind": "interface",
8531
8992
  "package": "@nifrajs/otel",
8532
- "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}"
8993
+ "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}"
8533
8994
  },
8534
8995
  {
8535
8996
  "name": "TrailingSlashOptions",
@@ -9076,6 +9537,13 @@
9076
9537
  "package": "@nifrajs/middleware",
9077
9538
  "signature": "export interface VerifiedJwt<C extends JwtClaims = JwtClaims> {\n readonly header: JwtHeader;\n readonly claims: C;\n readonly token: string;\n}"
9078
9539
  },
9540
+ {
9541
+ "name": "verifyAdapterCertification",
9542
+ "kind": "function",
9543
+ "package": "@nifrajs/testing",
9544
+ "signature": "export declare function verifyAdapterCertification(report: AdapterCertificationReport): Promise<boolean>;",
9545
+ "doc": "/** Recompute the portable evidence hash. Consumers should verify before trusting a stored report. */"
9546
+ },
9079
9547
  {
9080
9548
  "name": "verifyCsrfToken",
9081
9549
  "kind": "function",
@@ -9150,7 +9618,7 @@
9150
9618
  "name": "VERSION",
9151
9619
  "kind": "const",
9152
9620
  "package": "@nifrajs/core",
9153
- "signature": "export declare const VERSION: \"1.11.0\";",
9621
+ "signature": "export declare const VERSION: \"1.12.0\";",
9154
9622
  "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 */"
9155
9623
  },
9156
9624
  {