@nifrajs/cli 1.6.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.
Files changed (62) hide show
  1. package/README.md +33 -1
  2. package/dist/assure.d.ts +11 -0
  3. package/dist/assure.d.ts.map +1 -0
  4. package/dist/assure.js +67 -0
  5. package/dist/assure.js.map +1 -0
  6. package/dist/capabilities-tool.d.ts +33 -0
  7. package/dist/capabilities-tool.d.ts.map +1 -0
  8. package/dist/capabilities-tool.js +320 -0
  9. package/dist/capabilities-tool.js.map +1 -0
  10. package/dist/check.d.ts +1 -1
  11. package/dist/check.d.ts.map +1 -1
  12. package/dist/check.js +136 -11
  13. package/dist/check.js.map +1 -1
  14. package/dist/cli.d.ts.map +1 -1
  15. package/dist/cli.js +199 -12
  16. package/dist/cli.js.map +1 -1
  17. package/dist/doctor.d.ts +17 -0
  18. package/dist/doctor.d.ts.map +1 -1
  19. package/dist/doctor.js +146 -10
  20. package/dist/doctor.js.map +1 -1
  21. package/dist/levels-tool.d.ts +37 -0
  22. package/dist/levels-tool.d.ts.map +1 -0
  23. package/dist/levels-tool.js +183 -0
  24. package/dist/levels-tool.js.map +1 -0
  25. package/dist/manifest-tool.d.ts +15 -0
  26. package/dist/manifest-tool.d.ts.map +1 -0
  27. package/dist/manifest-tool.js +67 -0
  28. package/dist/manifest-tool.js.map +1 -0
  29. package/dist/mcp-http.js +1 -1
  30. package/dist/mcp-http.js.map +1 -1
  31. package/dist/mcp.d.ts +1 -0
  32. package/dist/mcp.d.ts.map +1 -1
  33. package/dist/mcp.js +31 -0
  34. package/dist/mcp.js.map +1 -1
  35. package/dist/recipes/1.8.0.d.ts +12 -0
  36. package/dist/recipes/1.8.0.d.ts.map +1 -0
  37. package/dist/recipes/1.8.0.js +20 -0
  38. package/dist/recipes/1.8.0.js.map +1 -0
  39. package/dist/recipes/index.d.ts +28 -0
  40. package/dist/recipes/index.d.ts.map +1 -0
  41. package/dist/recipes/index.js +27 -0
  42. package/dist/recipes/index.js.map +1 -0
  43. package/dist/upgrade.d.ts +82 -0
  44. package/dist/upgrade.d.ts.map +1 -0
  45. package/dist/upgrade.js +220 -0
  46. package/dist/upgrade.js.map +1 -0
  47. package/docs/examples.json +12 -0
  48. package/docs/llms-full.txt +524 -15
  49. package/docs/types.json +2409 -50
  50. package/package.json +9 -8
  51. package/src/assure.ts +88 -0
  52. package/src/capabilities-tool.ts +406 -0
  53. package/src/check.ts +155 -12
  54. package/src/cli.ts +206 -17
  55. package/src/doctor.ts +179 -11
  56. package/src/levels-tool.ts +232 -0
  57. package/src/manifest-tool.ts +103 -0
  58. package/src/mcp-http.ts +1 -1
  59. package/src/mcp.ts +37 -0
  60. package/src/recipes/1.8.0.ts +21 -0
  61. package/src/recipes/index.ts +52 -0
  62. package/src/upgrade.ts +269 -0
@@ -1682,6 +1682,89 @@ trustworthy client IP can be derived, and never trusts `X-Forwarded-For` unless
1682
1682
  bodies before routing (fails closed with `411` on a length-less body). The read-time
1683
1683
  guard above (`c.boundedBody` / schema cap) remains the source of truth.
1684
1684
 
1685
+ ### Route assurance — prove every route is guarded
1686
+
1687
+ Installing security middleware is not the same as proving it covers every route. Nifra's
1688
+ official auth, CSRF, body-limit, rate-limit, idempotency, IP-restriction, and security-header
1689
+ modules publish reflection-safe evidence at the hook where they enforce it. A policy then
1690
+ classifies every route and fails closed when evidence is missing or forbidden.
1691
+
1692
+ ```ts
1693
+ // doc-check: skip — configuration file imports your application backend.
1694
+ // nifra.assurance.ts
1695
+ import { defineAssuranceConfig, NIFRA_ASSURANCE } from "@nifrajs/core/assurance"
1696
+ import { app } from "./backend.ts"
1697
+
1698
+ export default defineAssuranceConfig({
1699
+ source: app,
1700
+ policy: {
1701
+ // First match owns the route: put narrow exceptions before broad defaults.
1702
+ rules: [
1703
+ { name: "health", match: { paths: ["/health"] }, require: [],
1704
+ forbid: [NIFRA_ASSURANCE.AUTHENTICATED] },
1705
+ { name: "mutation", match: { methods: ["POST", "PUT", "PATCH", "DELETE"] },
1706
+ require: [NIFRA_ASSURANCE.AUTHENTICATED, NIFRA_ASSURANCE.CSRF,
1707
+ NIFRA_ASSURANCE.BODY_BOUNDED] },
1708
+ { name: "read", match: { methods: ["GET", "HEAD"] },
1709
+ require: [NIFRA_ASSURANCE.AUTHENTICATED] },
1710
+ ],
1711
+ },
1712
+ })
1713
+
1714
+ // CI: nifra assure # human diagnostics
1715
+ // CI: nifra assure --json # complete machine-readable report
1716
+ ```
1717
+
1718
+ Evidence follows real lifecycle semantics: pre-routing and response hooks cover the whole app,
1719
+ while authentication and other order-scoped hooks cover only routes registered after them.
1720
+ Method and path filters prevent a narrow guard from claiming broader coverage. The evaluation
1721
+ runs only through reflection or `nifra assure`, so requests pay no assurance cost.
1722
+
1723
+ ### Effect assurance — declared capability versus provenance
1724
+
1725
+ Authentication does not reveal what a route can do. Capability assurance compares an exact
1726
+ route declaration against every approved effect import reachable through that route's local
1727
+ module graph. Static, dynamic, `require`, and re-export edges are scanned; raw provider
1728
+ imports fail `nifra check`. Runtime beacons add denial at owned adapters, but are never
1729
+ treated as a substitute for static provenance.
1730
+
1731
+ ```ts
1732
+ // doc-check: skip — combines route and assurance-config excerpts.
1733
+ // route: exact effect declaration + runtime beacon at the owned adapter seam
1734
+ import { useCapability } from "@nifrajs/core/capabilities"
1735
+
1736
+ app.post("/orders", { capabilities: ["db.write"] }, async (c) => {
1737
+ useCapability(c, "db.write") // undeclared use fails before the effect
1738
+ return orders.write(c.body)
1739
+ })
1740
+
1741
+ // in nifra.assurance.ts, alongside policy:
1742
+ capabilities: {
1743
+ definitions: [
1744
+ { id: "db.read", zone: "domain", access: "read" },
1745
+ { id: "db.write", zone: "domain", access: "write", idempotency: "request" },
1746
+ { id: "telemetry.write", zone: "operational", access: "write" },
1747
+ ],
1748
+ provenance: {
1749
+ // Use effect-specific facades. A broad module that mixes reads/writes cannot prove either.
1750
+ imports: [
1751
+ { specifier: "@app/db/read", capabilities: ["db.read"] },
1752
+ { specifier: "@app/db/write", capabilities: ["db.write"] },
1753
+ ],
1754
+ forbiddenImports: [
1755
+ { specifier: "postgres", reason: "use the tenant-scoped DB facade" },
1756
+ ],
1757
+ },
1758
+ }
1759
+
1760
+ // developer: nifra capabilities snapshot
1761
+ // CI: nifra check && nifra assure && nifra capabilities check
1762
+ ```
1763
+
1764
+ Domain writes on `GET`/`HEAD` are hard violations. Each write definition may
1765
+ require request idempotency or durable command/provider-key evidence. The lockfile contains only
1766
+ method, path, and capability tokens—no payloads or tenant data—and CI never rewrites it.
1767
+
1685
1768
  ### Already built in
1686
1769
 
1687
1770
  These add to Nifra's standing defaults: strict-by-default schema validation (unknown fields
@@ -3148,9 +3231,10 @@ backend over HTTP — so a browser `POST /api/sync` hit the page router and 404/
3148
3231
  until you hand-wrote a dispatch branch in `server-bun.ts`. Now
3149
3232
  `createWebApp` mounts it for you: a request whose pathname is exactly
3150
3233
  `apiPrefix` (default `/api`) or starts with
3151
- `apiPrefix + "/"` is dispatched to `api.fetch(req.url, req)`
3152
- **before** page routing, and the backend's `Response` is returned
3153
- untouched (the request body is passed through, never pre-read).
3234
+ `apiPrefix + "/"` is dispatched through Nifra's platform-aware backend mount
3235
+ interface **before** page routing. The backend receives the same Workers
3236
+ `env` bindings and `waitUntil` lifetime as the web app, and its
3237
+ `Response` is returned untouched (the request body is passed through, never pre-read).
3154
3238
 
3155
3239
  ```ts
3156
3240
  // server.ts (prod) — createWebApp serves pages AND auto-mounts the backend at /api/*.
@@ -3224,6 +3308,55 @@ They share the backend: a route `action` and a browser `fetch` can both
3224
3308
  call `POST /api/sync` — one in-process, one over the mount — and get identical
3225
3309
  validation and behavior.
3226
3310
 
3311
+ ## Nifra — Request budgets
3312
+
3313
+ > Propagate one absolute deadline through Nifra requests and downstream adapters without resetting time at each hop.
3314
+
3315
+ A timeout should not restart at every hop. Nifra admits one absolute wire deadline, clamps it
3316
+ to local policy, and exposes monotonic remaining time beside the existing cancellation signal.
3317
+
3318
+ ### Clamp once at admission
3319
+
3320
+ ```ts
3321
+ import { server } from "@nifrajs/core"
3322
+
3323
+ const app = server({
3324
+ requestTimeoutMs: 2_000,
3325
+ acceptInboundDeadlines: true,
3326
+ maxInboundDeadlineMs: 5_000,
3327
+ }).get("/report", async (c) => {
3328
+ // c.signal aborts at the SAME effective deadline.
3329
+ // remaining() is monotonic even if the wall clock jumps.
3330
+ return { remainingMs: c.budget.remaining() }
3331
+ })
3332
+ ```
3333
+
3334
+ The canonical header is `x-nifra-deadline`, containing Unix epoch milliseconds.
3335
+ Admission is an explicit trust-boundary choice via `acceptInboundDeadlines`; ordinary
3336
+ public routes ignore the header by default. Once enabled, a client value can only shorten
3337
+ local work. Malformed values return 400, expired values return 408, and a request that exhausts
3338
+ an inherited deadline returns 504.
3339
+
3340
+ ### Reserve time for the caller
3341
+
3342
+ ```ts
3343
+ // doc-check: skip — context and downstream adapter are established by the app
3344
+ const child = c.budget.child(50) // keep 50ms to serialize the response
3345
+
3346
+ await fetch(url, {
3347
+ signal: child.signal,
3348
+ headers: withDeadlineHeader(undefined, child),
3349
+ })
3350
+ ```
3351
+
3352
+ `child(reserveMs)` preserves response cleanup time without resetting the absolute
3353
+ deadline. Downstream adapters must also use `remaining()` for their actual timeout;
3354
+ forwarding the header alone is decorative.
3355
+
3356
+ Configure a finite `requestTimeoutMs` before handing `c.budget` to a
3357
+ production adapter. The no-timeout compatibility path is deliberately unbounded and is not
3358
+ written to the wire.
3359
+
3227
3360
  ## Nifra — Framework contract
3228
3361
 
3229
3362
  > The one-page contract: LoaderContext shape, loader/action/meta/head signatures, the client↔server boundary, and the build-output contract — every signature verified against the source.
@@ -4160,6 +4293,117 @@ backend you can also ship on its own. Start with [Getting started](/docs).
4160
4293
  Moving a backend (Express, Hono, Fastify, Elysia) instead? See
4161
4294
  [Migrating a backend](/docs/migrate-backend).
4162
4295
 
4296
+ ## Nifra — Contract-derived adversarial testing
4297
+
4298
+ > Turn route schemas into hostile input, response-conformance, replay, shrinking, and runtime-matrix tests with @nifrajs/testing.
4299
+
4300
+ A route contract should be more than documentation. `@nifrajs/testing` turns it
4301
+ into a laboratory: valid requests, hostile inputs, real boundary rejection, response
4302
+ conformance, shrinking, replay seeds, and adapter parity from one small test interface.
4303
+
4304
+ ### One assertion, every contracted boundary
4305
+
4306
+ ```ts
4307
+ import { assertAdversarialContract } from "@nifrajs/testing"
4308
+ import { app } from "../src/app"
4309
+
4310
+ const { test } = await import("bun:test")
4311
+
4312
+ test("the API contract withstands hostile inputs", async () => {
4313
+ await assertAdversarialContract(app, { seed: 73 })
4314
+ })
4315
+ ```
4316
+
4317
+ For every selected route, the laboratory synthesizes a valid **contract witness**. It then
4318
+ changes types, removes required fields, crosses numeric and length bounds, inserts unknown
4319
+ properties, and descends into nested objects and arrays. A mutation is sent only after the
4320
+ route's own Standard Schema validator proves it invalid. Query values are proved after URL
4321
+ serialization, exactly as the server receives them.
4322
+
4323
+ Invalid inputs must produce 422 by default. A valid witness is also executed for every
4324
+ declared `response`, and the real JSON body is validated off the request hot path.
4325
+ Use `expectedValidationStatuses` or `isRejected` when your app deliberately
4326
+ has a different validation response.
4327
+
4328
+ ### Opaque schemas stay validator-neutral
4329
+
4330
+ Nifra's `t` schemas carry inspectable JSON Schema, so witness generation is
4331
+ automatic. Other Standard Schema libraries do not have to expose structure. Supply a known-good
4332
+ witness; their own validator still proves every hostile mutation.
4333
+
4334
+ ```ts
4335
+ // Standard Schema guarantees validation, not introspection.
4336
+ // Give opaque Zod/Valibot/ArkType routes only their known-good request values.
4337
+ await assertAdversarialContract(app, {
4338
+ witnesses: {
4339
+ "POST /users/:id": {
4340
+ params: { id: "user-1" },
4341
+ body: { name: "Ada" },
4342
+ query: { notify: "true" },
4343
+ },
4344
+ },
4345
+ })
4346
+ ```
4347
+
4348
+ Missing, invalid, or unsynthesizable witnesses become explicit coverage gaps. The default is
4349
+ fail-closed; `requireCoverage: false` makes gaps advisory.
4350
+
4351
+ ### Auth and tenant context
4352
+
4353
+ `prepareRequest` runs for every case and runtime. Use it to attach a test session,
4354
+ tenant identity, signed headers, or platform bindings without putting secrets into reports.
4355
+
4356
+ ```ts
4357
+ await assertAdversarialContract(app, {
4358
+ prepareRequest(request, context) {
4359
+ const headers = new Headers(request.headers)
4360
+ headers.set("authorization", "Bearer test-session")
4361
+ headers.set("x-tenant-id", context.runtime === "worker" ? "edge-test" : "local-test")
4362
+ return new Request(request, { headers })
4363
+ },
4364
+ })
4365
+ ```
4366
+
4367
+ ### One contract, many runtimes
4368
+
4369
+ Supply fetch targets to exercise the identical cases through Bun, Node, Deno, or Workers
4370
+ adapters. Reflection still comes from the original app, so there is one authoritative contract.
4371
+
4372
+ ```ts
4373
+ const report = await assertAdversarialContract(app, {
4374
+ runtimes: [
4375
+ { name: "bun", fetch: (request) => bunApp.fetch(request) },
4376
+ { name: "node", fetch: (request) => nodeAdapter.fetch(request) },
4377
+ { name: "worker", fetch: (request) => worker.fetch(request, env) },
4378
+ ],
4379
+ })
4380
+
4381
+ // Each target receives the same case IDs and deterministic witnesses.
4382
+ console.log(report.seed, report.counts)
4383
+ ```
4384
+
4385
+ ### Shrink and replay failures
4386
+
4387
+ Unexpectedly accepted hostile inputs are greedily reduced to a smaller validator-invalid
4388
+ request. Results do not print request bodies or headers; the stable case ID, runtime, and seed
4389
+ are enough to replay deterministically.
4390
+
4391
+ ```ts
4392
+ const report = await runAdversarialContract(app, { seed: 73 })
4393
+ const failure = report.failures[0]
4394
+
4395
+ // CI can print this small, payload-free replay tuple.
4396
+ console.error(failure.replay) // { seed: 73, caseId: "...", runtime: "worker" }
4397
+
4398
+ await assertAdversarialContract(app, {
4399
+ seed: failure.replay.seed,
4400
+ only: failure.replay.caseId,
4401
+ })
4402
+ ```
4403
+
4404
+ The response-conformance pass executes handlers, including POST/DELETE handlers. Run it with
4405
+ isolated fixtures and a test database. Never point a contract laboratory at production.
4406
+
4163
4407
  ## Nifra — Types-first architecture
4164
4408
 
4165
4409
  > One schema is the single source of truth: it drives runtime validation, inferred TypeScript types, the no-codegen typed client, an OpenAPI document, and the MCP contract your agents read.
@@ -4411,6 +4655,38 @@ one cheap read instead of the whole corpus. For the wider framework: the repo's
4411
4655
  [`llms-full.txt`](../../llms-full.txt) is the full machine-readable corpus. Run `nifra check` as the
4412
4656
  done-gate, or `nifra mcp` to give the agent live project tools.
4413
4657
 
4658
+ ## @nifrajs/budget
4659
+
4660
+ Compatibility import for the request-deadline mechanics owned by `@nifrajs/core/budget`. Existing
4661
+ Nifra, Hono, and Fetch consumers can keep this import unchanged; new core consumers may use the
4662
+ subpath directly. Both paths resolve to the same implementation and classes.
4663
+
4664
+ ```ts
4665
+ import {
4666
+ assertBudgetRemaining,
4667
+ createRequestBudget,
4668
+ withDeadlineHeader,
4669
+ } from "@nifrajs/budget"
4670
+
4671
+ const budget = createRequestBudget({
4672
+ deadline: Date.now() + 2_000,
4673
+ signal: request.signal,
4674
+ })
4675
+
4676
+ assertBudgetRemaining(budget, 100)
4677
+ await fetch(url, {
4678
+ signal: budget.signal,
4679
+ headers: withDeadlineHeader(undefined, budget.child(50)),
4680
+ })
4681
+ ```
4682
+
4683
+ The wire value is an absolute Unix epoch deadline. `remaining()` samples wall time once, then uses a
4684
+ monotonic clock so NTP changes cannot extend or shorten admitted work. A budget does not choose retry,
4685
+ provider, tenant, or money policy; it only answers how much time remains.
4686
+
4687
+ Nifra route handlers receive the same primitive as `c.budget`. `c.signal` remains the cancellation
4688
+ signal and aborts at the effective server deadline.
4689
+
4414
4690
  ## @nifrajs/cache
4415
4691
 
4416
4692
  Typed KV cache for nifra — **TTL**, **stale-while-revalidate**, **tag invalidation**, and **single-flight
@@ -4479,9 +4755,40 @@ nifra start [--port <n>] [--out <dir>] Serve the built app (client + SSR) on
4479
4755
  nifra context Print this project's API + page routes + conventions.
4480
4756
  nifra mcp MCP server (stdio) exposing this project to a coding agent.
4481
4757
  nifra check [--json] Gate: typecheck + lints; --json includes fixes/suggestions.
4482
- nifra doctor [--json] [--auto-fix] Catch undeclared imported packages; auto-fix safe local versions.
4758
+ nifra assure [--config <file>] [--json] Gate reflected routes against enforcement evidence.
4759
+ nifra capabilities check [--json] Gate effect provenance + the reviewed capability lockfile.
4760
+ nifra manifest emit [--sign <key-ref>] Emit the hash-verified route trust artifact after assurance.
4761
+ nifra manifest diff <before> <after> Block promotion on contract/governance regressions.
4762
+ nifra doctor [--json] [--auto-fix] Catch undeclared imports and duplicate Nifra/React installs.
4483
4763
  ```
4484
4764
 
4765
+ ## `nifra doctor` - dependency health
4766
+
4767
+ Doctor diffs source imports against declared dependencies, then resolves identity-sensitive
4768
+ dependencies from every workspace package. More than one physical `@nifrajs/*`, `react`, or
4769
+ `react-dom` copy fails even when versions match; module identity is path-based. Doctor reports
4770
+ paths/importers and never deletes installations.
4771
+
4772
+ ## `nifra assure` — the route-enforcement gate
4773
+
4774
+ Create `nifra.assurance.ts` with a default `defineAssuranceConfig({ source, policy })` export, then run
4775
+ `nifra assure` in CI. Official middleware publishes evidence at the same seam where it installs its
4776
+ hooks; the gate classifies every reflected route with the first matching rule and exits non-zero for an
4777
+ unclassified route, missing evidence, or forbidden evidence. Evaluation is startup/CI-only and adds no
4778
+ request-path overhead. Use `--json` for the complete per-route report or `--config` for another file.
4779
+
4780
+ ## `nifra manifest` — the deploy trust artifact
4781
+
4782
+ Add optional `manifest: { path, signer }` settings to `nifra.assurance.ts`, then run
4783
+ `nifra manifest emit`. Emission refuses failing route or capability assurance and joins the route
4784
+ schemas, enforcement evidence, effect tokens, and field-level response classification into one
4785
+ deterministic SHA-256 artifact. `--sign <key-ref>` asks the configured callback to produce a detached
4786
+ Ed25519 sidecar, so the private key can stay inside KMS/HSM infrastructure.
4787
+
4788
+ At promotion time, `nifra manifest diff previous.json candidate.json` hash-verifies both files and exits
4789
+ non-zero on a breaking API change, removed assurance, expanded effect, lost provenance coverage, or
4790
+ increased data sensitivity. This is separate from the frontend asset `dist/manifest.json`.
4791
+
4485
4792
  ## `nifra check` — the drift gate (run as "done")
4486
4793
 
4487
4794
  `nifra check` makes nifra's anti-drift guarantees actually fire instead of relying on the agent to
@@ -4534,6 +4841,7 @@ an agent can act on the project, not just read about it. Core tools:
4534
4841
  - **`nifra_test`** — run bounded `bun test` with structured output.
4535
4842
  - **`nifra_check`** — run the drift gate and get the structured `{ ok, typecheck, diagnostics[] }`
4536
4843
  result with suggestions, so the agent verifies its own work and fixes each diagnostic before finishing.
4844
+ - **`nifra_assure`** — evaluate `nifra.assurance.ts` and return the complete per-route evidence report.
4537
4845
  - **`nifra_doctor`** — catch imported packages missing from `package.json`; with `autoFix:true`, write
4538
4846
  safe dependency entries when a version can be inferred locally and return exact `bun add` commands
4539
4847
  for anything that needs a package-manager decision.
@@ -4671,8 +4979,32 @@ export type App = typeof app // hand this to @nifrajs/client for end-to-end type
4671
4979
  `onRequest`/`beforeHandle`/`afterHandle`/`onResponse`/`onError` run around handlers;
4672
4980
  `use(middleware)` applies a bundle.
4673
4981
  - **Hardening built in.** `stop({ drainMs })` graceful shutdown (+ opt-in SIGTERM/
4674
- SIGINT), `requestTimeoutMs` (+ `ctx.signal`), a streaming body-size cap, and a
4982
+ SIGINT), `requestTimeoutMs` (+ `ctx.signal` and `ctx.budget`), a streaming body-size cap, and a
4675
4983
  redacting structured `Logger`.
4984
+ - **One request budget.** `ctx.budget` carries the admitted absolute deadline and monotonic
4985
+ `remaining()` time. An inbound `x-nifra-deadline` can only shorten `requestTimeoutMs`/
4986
+ `maxInboundDeadlineMs`; malformed and expired values fail before the handler. `ctx.signal`
4987
+ remains the cancellation primitive and aborts at that same effective deadline.
4988
+ - **Route assurance.** Official auth, CSRF, body-limit, rate-limit, idempotency,
4989
+ IP-restriction, and security-header modules publish reflection-safe enforcement evidence.
4990
+ An ordered `AssurancePolicy` classifies every route and fails closed on missing or forbidden
4991
+ evidence without adding work to the request path.
4992
+
4993
+ ```ts
4994
+ import { defineAssurancePolicy, evaluateRouteAssurance, NIFRA_ASSURANCE } from "@nifrajs/core/assurance"
4995
+
4996
+ const policy = defineAssurancePolicy({
4997
+ rules: [
4998
+ { name: "health", match: { paths: ["/health"] }, require: [] },
4999
+ { name: "mutation", match: { methods: ["POST", "PUT", "PATCH", "DELETE"] },
5000
+ require: [NIFRA_ASSURANCE.AUTHENTICATED, NIFRA_ASSURANCE.CSRF] },
5001
+ { name: "read", match: { methods: ["GET", "HEAD"] },
5002
+ require: [NIFRA_ASSURANCE.AUTHENTICATED] },
5003
+ ],
5004
+ })
5005
+
5006
+ evaluateRouteAssurance(app, policy).ok // pure reflection-time evaluation
5007
+ ```
4676
5008
 
4677
5009
  ESM-only; requires Bun at runtime. MIT.
4678
5010
 
@@ -4873,6 +5205,16 @@ one cheap read instead of the whole corpus. For the wider framework: the repo's
4873
5205
  [`llms-full.txt`](../../llms-full.txt) is the full machine-readable corpus. Run `nifra check` as the
4874
5206
  done-gate, or `nifra mcp` to give the agent live project tools.
4875
5207
 
5208
+ ## @nifrajs/events
5209
+
5210
+ Portable, versioned event contracts — a typed, transport-agnostic event envelope validated by any Standard Schema.
5211
+
5212
+ An envelope may carry the bounded `@nifrajs/core/causality` context for its exact event id. Creation
5213
+ and parsing reject mismatched nodes and unknown fields, so arbitrary payloads cannot hitchhike in the
5214
+ lineage metadata.
5215
+
5216
+ See the [nifra docs](https://github.com/nifrajs/nifra#readme).
5217
+
4876
5218
  ## @nifrajs/i18n
4877
5219
 
4878
5220
  Framework-agnostic i18n for nifra — locale negotiation + a tiny ICU message formatter on the platform Intl. Dependency-free.
@@ -5268,10 +5610,38 @@ const app = server()
5268
5610
  (`error` for 5xx, `ok` otherwise).
5269
5611
  - **Exposes `c.trace`** (`{ traceId, spanId, parentSpanId?, sampled, traceparent }`) — spread
5270
5612
  `traceHeaders(c.trace)` into any downstream `fetch`/`ctx.api` call to continue the trace.
5613
+ - **Exposes `c.causality`** - a bounded, payload-free request node that survives durable command,
5614
+ event, workflow, projection, and repair seams. `traceHeaders(c.trace, c.causality)` forwards both
5615
+ conventions to a trusted downstream service.
5271
5616
  - **Exposes `c.observation`** — integrations can start correctly-parented child observations or
5272
5617
  attach an adapter without rebuilding request lifecycle state.
5273
5618
  - `responseHeader: true` also sets `traceparent` on the response (browser/client correlation).
5274
5619
 
5620
+ ## Durable causality and trust
5621
+
5622
+ Pass a durable recorder to append the request root before the handler runs. An explicitly configured
5623
+ recorder is correctness evidence, so its failure fails the request closed:
5624
+
5625
+ ```ts
5626
+ app.use(tracing({
5627
+ exporter,
5628
+ causality: {
5629
+ recorder: durableGraphStore,
5630
+ acceptInbound: (request) => verifyInternalServiceCredential(request),
5631
+ },
5632
+ }))
5633
+ ```
5634
+
5635
+ Inbound causality headers are **not trusted by default**. This prevents an internet client from
5636
+ injecting fake parents into another execution timeline. Supply `acceptInbound` only at an authenticated
5637
+ service-to-service boundary; a false, thrown, or rejected decision starts a fresh graph. W3C
5638
+ `traceparent` remains normal observability context, but a fresh durable execution id includes the
5639
+ server-generated span id and is not copied from the untrusted header.
5640
+
5641
+ Use `causalitySpanLink(context)` when durable work opens a later observation. It creates a real OTel
5642
+ link to the nearest observed causal ancestor and drops invalid/unanchored contexts rather than
5643
+ inventing trace identity.
5644
+
5275
5645
  ## Adapters
5276
5646
 
5277
5647
  Implement `ObservationAdapter` to send spans wherever you collect them. `SpanExporter` remains as a
@@ -5467,10 +5837,139 @@ import { assertSafeKey, StorageKeyError } from "@nifrajs/storage"
5467
5837
 
5468
5838
  ## @nifrajs/testing
5469
5839
 
5470
- Testing helpers for nifra apps. [`@nifrajs/client`](../client)'s **`testClient`** is already the typed,
5471
- no-network in-process request client (nifra's supertest / `inject`). This package adds what it doesn't: a
5472
- **cookie jar** and a **cookie-persisting `testSession`**, so a login → authenticated-request flow tests as
5473
- easily as a single request.
5840
+ Contract-derived adversarial testing and stateful in-process helpers for Nifra apps.
5841
+
5842
+ ## Contract laboratory
5843
+
5844
+ `assertAdversarialContract` turns the schemas already registered on an app into executable tests. It:
5845
+
5846
+ - synthesizes a valid **contract witness** from inspectable JSON Schema;
5847
+ - makes small nested **hostile mutations** and sends only values the route's own Standard Schema
5848
+ validator has proved invalid after HTTP transport normalization;
5849
+ - expects rejection at the real request boundary (422 by default);
5850
+ - executes a valid witness and validates the real success body against `response`;
5851
+ - runs the same stable case IDs across a Bun/Node/Workers runtime matrix; and
5852
+ - retains a replay seed and greedily shrinks unexpected acceptance failures.
5853
+
5854
+ ```ts
5855
+ import { test } from "bun:test"
5856
+ import { assertAdversarialContract } from "@nifrajs/testing"
5857
+ import { app } from "../src/app"
5858
+
5859
+ test("the API contract withstands hostile inputs", async () => {
5860
+ await assertAdversarialContract(app, {
5861
+ seed: 73,
5862
+ prepareRequest(request) {
5863
+ const headers = new Headers(request.headers)
5864
+ headers.set("authorization", "Bearer test-session")
5865
+ return new Request(request, { headers })
5866
+ },
5867
+ })
5868
+ })
5869
+ ```
5870
+
5871
+ Nifra's `t` schemas carry JSON Schema, so witnesses are automatic. Standard Schema deliberately does
5872
+ not require introspection; for an opaque Zod/Valibot/ArkType schema, provide only its known-good values:
5873
+
5874
+ ```ts
5875
+ await assertAdversarialContract(app, {
5876
+ witnesses: {
5877
+ "POST /users/:id": {
5878
+ params: { id: "user-1" },
5879
+ body: { name: "Ada" },
5880
+ query: { notify: "true" },
5881
+ },
5882
+ },
5883
+ })
5884
+ ```
5885
+
5886
+ The validator still decides which generated mutations are truly invalid; the supplied witness does not
5887
+ weaken validation. A missing/invalid witness is a coverage gap, not a silent pass. Set
5888
+ `requireCoverage: false` only when gaps are intentionally advisory.
5889
+
5890
+ To exercise adapter parity, pass runtime fetch targets. The reflected `app` remains the one source of
5891
+ the contract:
5892
+
5893
+ ```ts
5894
+ const report = await assertAdversarialContract(app, {
5895
+ runtimes: [
5896
+ { name: "bun", fetch: (request) => bunApp.fetch(request) },
5897
+ { name: "node", fetch: (request) => nodeAdapter.fetch(request) },
5898
+ { name: "worker", fetch: (request) => worker.fetch(request, env) },
5899
+ ],
5900
+ })
5901
+ ```
5902
+
5903
+ `runAdversarialContract` returns the same structured report without throwing. Every failure includes
5904
+ `replay: { seed, caseId, runtime }`; rerun one case with `only: caseId`. Contract runs execute one valid
5905
+ request for each declared response schema, so use an isolated test app/database—never point the
5906
+ laboratory at production.
5907
+
5908
+ `nifra levels` L4 uses this same deep engine through the explicitly configured isolated executor;
5909
+ the older core invariant runner remains only as a compatibility export.
5910
+
5911
+ ## Durable failure laboratory
5912
+
5913
+ `createFailureLab` injects replayable failures at named seams in a disposable test adapter. It
5914
+ supports crash-after-commit, duplicate delivery, event reordering, virtual delay, budget expiry,
5915
+ lost provider replies, and checkpoint contention. It never sleeps and its evidence records only
5916
+ the schedule tokens - not requests, events, provider results, error messages, or stacks.
5917
+
5918
+ ```ts
5919
+ import { FailureInjectedError, runFailureScenario } from "@nifrajs/testing"
5920
+
5921
+ let committed = false
5922
+ const report = await runFailureScenario({
5923
+ name: "outbox-crash-after-commit",
5924
+ execute(lab) {
5925
+ committed = true // the real disposable transaction committed
5926
+ lab.checkpoint("outbox.after_commit")
5927
+ },
5928
+ verify: ({ error }) => committed && error instanceof FailureInjectedError,
5929
+ }, {
5930
+ seed: 73,
5931
+ schedule: [{ kind: "crash", point: "outbox.after_commit" }],
5932
+ })
5933
+
5934
+ expect(report.ok).toBe(true)
5935
+ // Re-run with report.replay.seed + report.replay.schedule.
5936
+ ```
5937
+
5938
+ Use `lab.deliveries()` around a relay batch, `lab.provider()` around a provider call,
5939
+ `lab.remaining()` before a deadline-bound hop, and `lab.checkpointContended()` at a projection CAS.
5940
+ The laboratory is a test port: production code does not import it and pays no hot-path cost.
5941
+
5942
+ ## Adapter certification
5943
+
5944
+ `@nifrajs/testing/certification` turns an adapter interface into portable, hash-verifiable evidence.
5945
+ Built-in profiles cover storage (including optional paging/signing/copy-move), cache, jobs, Node/Deno-
5946
+ style runtimes, and durable event delivery. Every check receives a fresh adapter, capability status is
5947
+ explicit, and failures retain only the error class - never provider messages or credentials.
5948
+
5949
+ ```ts
5950
+ import {
5951
+ certifyAdapter,
5952
+ storageAdapterCertificationProfile,
5953
+ verifyAdapterCertification,
5954
+ } from "@nifrajs/testing/certification"
5955
+
5956
+ const report = await certifyAdapter({
5957
+ profile: storageAdapterCertificationProfile({ paging: true, presign: true, move: true }),
5958
+ adapterId: "s3-production-shape",
5959
+ createAdapter: () => createDisposableS3Adapter(),
5960
+ })
5961
+
5962
+ if (!report.ok || !(await verifyAdapterCertification(report))) throw new Error("adapter uncertified")
5963
+ ```
5964
+
5965
+ Run profiles only against disposable namespaces. The certification module is structural and
5966
+ dependency-free, so adapter packages keep it in test/CI and acquire no production runtime dependency.
5967
+
5968
+ ## Stateful sessions
5969
+
5970
+ [`@nifrajs/client`](../client)'s **`testClient`** is already the typed, no-network in-process request
5971
+ client (Nifra's supertest / `inject`). `testSession` adds a **cookie jar**, so a login → authenticated
5972
+ request flow tests as easily as a single request.
5474
5973
 
5475
5974
  ```ts
5476
5975
  import { testSession } from "@nifrajs/testing"
@@ -5493,6 +5992,12 @@ that every call carries and captures cookies via a shared jar.
5493
5992
 
5494
5993
  ## API
5495
5994
 
5995
+ - `assertAdversarialContract(app, options?)` → green report or throws `AdversarialContractError`.
5996
+ - `runAdversarialContract(app, options?)` → structured `{ ok, results, failures, gaps, seed }` report.
5997
+ - `createFailureLab(options)` → deterministic controller for isolated durable adapters.
5998
+ - `runFailureScenario(scenario, options)` → token-only `{ ok, replay, evidence, error? }` report.
5999
+ - `certifyAdapter({ profile, adapterId, createAdapter })` → capability matrix + SHA-256 evidence.
6000
+ - `verifyAdapterCertification(report)` → recompute and verify portable certification evidence.
5496
6001
  - `testSession<App>(app, { origin?, cookies? })` → `{ client: Treaty<App>, cookies: CookieJar }`.
5497
6002
  - `cookieJar()` → `CookieJar` — `header()` · `applyTo(headers)` · `store(response)` · `set` · `get` · `clear` · `size`.
5498
6003
  Honours removal (`Max-Age=0` / past `Expires`); other cookie attributes are ignored (in-process, same-origin).
@@ -5841,7 +6346,7 @@ done-gate, or `nifra mcp` to give the agent live project tools.
5841
6346
 
5842
6347
  ## @nifrajs/client
5843
6348
 
5844
- `ActionArgs`, `ActionData`, `ApiError`, `ApiProxy`, `client`, `ClientOptions`, `FetchFn`, `inProcessClient`, `Jsonify`, `LoaderArgs`, `LoaderData`, `RegistryOf`, `Result`, `SubscribeOptions`, `Subscription`, `testClient`, `Treaty`, `TreatyFromRegistry`
6349
+ `ActionArgs`, `ActionData`, `ApiError`, `ApiProxy`, `client`, `ClientOptions`, `FetchFn`, `inProcessClient`, `InProcessClient`, `Jsonify`, `LoaderArgs`, `LoaderData`, `RegistryOf`, `Result`, `SubscribeOptions`, `Subscription`, `testClient`, `Treaty`, `TreatyFromRegistry`
5845
6350
 
5846
6351
  ## @nifrajs/content
5847
6352
 
@@ -5849,7 +6354,7 @@ done-gate, or `nifra mcp` to give the agent live project tools.
5849
6354
 
5850
6355
  ## @nifrajs/core
5851
6356
 
5852
- `AnyServer`, `attachWebSocket`, `commonSecretPatterns`, `Context`, `ContextForOp`, `ContractShape`, `CookieOptions`, `defineContract`, `defineIdentityPlugin`, `definePlugin`, `defineRouterPlugin`, `DurableObjectNamespaceLike`, `ExecutionContext`, `FRAMEWORK_NAME`, `FrameworkError`, `FrameworkName`, `Handler`, `HandlersFor`, `IdentityPlugin`, `implement`, `InferInput`, `InferOutput`, `jsonLogger`, `LogFields`, `Logger`, `McpPromptDescriptor`, `McpResourceDescriptor`, `Method`, `METHODS`, `Middleware`, `NifraPlugin`, `NifraWebSocket`, `NodeServeOutcome`, `OnRequestResult`, `OperationDef`, `Params`, `parseCookies`, `Platform`, `Prettify`, `PromptArgument`, `PromptMessage`, `redactLogFields`, `RedactOptions`, `Registry`, `RegistryFor`, `RegistryFromImpl`, `ResponseControls`, `ResponseDef`, `ResponseFinalization`, `robots`, `RobotsOptions`, `RobotsRule`, `RouteConfigError`, `RouteConfigErrorCode`, `RouteDescriptor`, `RouteInfo`, `Router`, `RouterMatch`, `RouteSchema`, `RunningServer`, `ScheduledController`, `ScheduledHandler`, `serializeCookie`, `server`, `Server`, `ServerOptions`, `SignatureEncoding`, `signValue`, `silentLogger`, `sitemap`, `SitemapChangeFreq`, `SitemapEntry`, `SitemapOptions`, `sse`, `SSEContext`, `SSEInit`, `SSEMessage`, `SSEStream`, `StandardIssue`, `StandardResult`, `StandardSchemaV1`, `StandardTypes`, `StandardWebSocket`, `toFetchHandler`, `ToolAnnotations`, `TopicRegistry`, `typedSSEStream`, `TypedSSEStream`, `unsignValue`, `validateStandard`, `ValidationOutcome`, `verifyWebhook`, `VerifyWebhookOptions`, `Version`, `VERSION`, `WebhookFailureReason`, `WebhookProvider`, `WebhookResult`, `WebSocketContext`, `WebSocketData`, `WebSocketHandler`, `WebSocketUpgradeOutcome`
6357
+ `AdmissionController`, `AdmissionDecision`, `AnyServer`, `attachWebSocket`, `commonSecretPatterns`, `Context`, `ContextForOp`, `ContractShape`, `CookieOptions`, `defineContract`, `defineIdentityPlugin`, `definePlugin`, `defineRouterPlugin`, `DurableObjectNamespaceLike`, `ExecutionContext`, `FRAMEWORK_NAME`, `FrameworkError`, `FrameworkName`, `Handler`, `HandlersFor`, `IdentityPlugin`, `implement`, `InferInput`, `InferOutput`, `jsonLogger`, `LogFields`, `Logger`, `McpPromptDescriptor`, `McpResourceDescriptor`, `Method`, `METHODS`, `Middleware`, `NifraPlugin`, `NifraWebSocket`, `NodeServeOutcome`, `OnRequestResult`, `OperationDef`, `Params`, `parseCookies`, `Platform`, `Prettify`, `PromptArgument`, `PromptMessage`, `redactLogFields`, `RedactOptions`, `Registry`, `RegistryFor`, `RegistryFromImpl`, `ResponseControls`, `ResponseDef`, `ResponseFinalization`, `robots`, `RobotsOptions`, `RobotsRule`, `RouteConfigError`, `RouteConfigErrorCode`, `RouteDescriptor`, `RouteInfo`, `Router`, `RouterMatch`, `RouteSchema`, `RunningServer`, `ScheduledController`, `ScheduledHandler`, `serializeCookie`, `server`, `Server`, `ServerOptions`, `SignatureEncoding`, `signValue`, `silentLogger`, `sitemap`, `SitemapChangeFreq`, `SitemapEntry`, `SitemapOptions`, `sse`, `SSEContext`, `SSEInit`, `SSEMessage`, `SSEStream`, `StandardIssue`, `StandardResult`, `StandardSchemaV1`, `StandardTypes`, `StandardWebSocket`, `toFetchHandler`, `ToolAnnotations`, `TopicRegistry`, `typedSSEStream`, `TypedSSEStream`, `unsignValue`, `validateStandard`, `ValidationOutcome`, `verifyWebhook`, `VerifyWebhookOptions`, `Version`, `VERSION`, `WebhookFailureReason`, `WebhookProvider`, `WebhookResult`, `WebSocketContext`, `WebSocketData`, `WebSocketHandler`, `WebSocketUpgradeOutcome`
5853
6358
 
5854
6359
  ## @nifrajs/cron
5855
6360
 
@@ -5867,6 +6372,10 @@ done-gate, or `nifra mcp` to give the agent live project tools.
5867
6372
 
5868
6373
  `boolean`, `defineEnv`, `DefineEnvOptions`, `enumValue`, `env`, `EnvResult`, `EnvShape`, `InferOutput`, `number`, `port`, `StandardResult`, `StandardSchemaV1`, `string`, `url`
5869
6374
 
6375
+ ## @nifrajs/events
6376
+
6377
+ `createEventRegistry`, `defineEventContract`, `EventContract`, `EventContractError`, `EventEnvelope`, `EventParseResult`, `EventRegistry`, `RegistryParseResult`
6378
+
5870
6379
  ## @nifrajs/i18n
5871
6380
 
5872
6381
  `createFormatter`, `Formatter`, `Locale`, `Messages`, `negotiateLocale`, `NegotiateOptions`
@@ -5893,7 +6402,7 @@ done-gate, or `nifra mcp` to give the agent live project tools.
5893
6402
 
5894
6403
  ## @nifrajs/middleware
5895
6404
 
5896
- `apiKey`, `ApiKeyStaticOptions`, `ApiKeyVerifyOptions`, `appendTrailingSlash`, `AuthPlugin`, `basicAuth`, `BasicAuthPlugin`, `BasicAuthStaticOptions`, `BasicAuthVerifyOptions`, `bearer`, `BearerOptions`, `bodyLimit`, `BodyLimitOptions`, `buildOpenApiDocument`, `cache`, `cacheControl`, `CacheControlOptions`, `CachedResponse`, `CacheOptions`, `combine`, `Composable`, `compression`, `CompressionOptions`, `cors`, `CorsOptions`, `createCsrfToken`, `csrf`, `CsrfOptions`, `etag`, `ETagOptions`, `healthcheck`, `HealthcheckOptions`, `idempotency`, `IdempotencyClaim`, `IdempotencyOptions`, `IdempotencyRecord`, `IdempotencyStore`, `IpMatcher`, `ipRestriction`, `IpRestrictionOptions`, `jwk`, `JwkKey`, `jwks`, `JwksOptions`, `jwt`, `JwtAlgorithm`, `JwtClaims`, `JwtHeader`, `JwtKeyResolver`, `JwtOptions`, `JwtPlugin`, `JwtVerificationKey`, `language`, `LanguageMatch`, `LanguageOptions`, `logger`, `LoggerOptions`, `MemoryIdempotencyStore`, `MemoryIdempotencyStoreOptions`, `MemoryResponseCache`, `MemoryResponseCacheOptions`, `MemoryStore`, `MemoryStoreOptions`, `methodOverride`, `MethodOverrideOptions`, `namedCombine`, `openapi`, `OpenApiInfo`, `OpenApiOptions`, `OpenApiServer`, `OpenApiTag`, `OpenApiUiOptions`, `pickLanguage`, `poweredBy`, `PoweredByOptions`, `prettyJson`, `PrettyJsonOptions`, `rateLimit`, `RateLimitOptions`, `RateLimitResult`, `RateLimitStore`, `requestId`, `RequestIdOptions`, `RequestLogFields`, `responseCache`, `ResponseCacheStore`, `RouteLike`, `securityHeaders`, `SecurityHeadersOptions`, `SecurityRequirement`, `timing`, `TimingControls`, `TimingMetric`, `TimingOptions`, `TrailingSlashOptions`, `trimTrailingSlash`, `tryVerifyJwt`, `VerifiedJwt`, `verifyCsrfToken`, `verifyJwt`, `VerifyJwtOptions`, `VerifyJwtResult`
6405
+ `AdmissionControllerHandle`, `AdmissionEvidence`, `AdmissionOptions`, `AdmissionPolicy`, `AdmissionSnapshot`, `apiKey`, `ApiKeyStaticOptions`, `ApiKeyVerifyOptions`, `appendTrailingSlash`, `AuthPlugin`, `basicAuth`, `BasicAuthPlugin`, `BasicAuthStaticOptions`, `BasicAuthVerifyOptions`, `bearer`, `BearerOptions`, `bodyLimit`, `BodyLimitOptions`, `buildOpenApiDocument`, `cache`, `cacheControl`, `CacheControlOptions`, `CachedResponse`, `CacheOptions`, `combine`, `Composable`, `compression`, `CompressionOptions`, `cors`, `CorsOptions`, `createAdmissionController`, `createCsrfToken`, `createEventLoopLagSampler`, `csrf`, `CsrfOptions`, `etag`, `ETagOptions`, `healthcheck`, `HealthcheckOptions`, `idempotency`, `IdempotencyClaim`, `IdempotencyOptions`, `IdempotencyRecord`, `IdempotencyStore`, `IpMatcher`, `ipRestriction`, `IpRestrictionOptions`, `jwk`, `JwkKey`, `jwks`, `JwksOptions`, `jwt`, `JwtAlgorithm`, `JwtClaims`, `JwtHeader`, `JwtKeyResolver`, `JwtOptions`, `JwtPlugin`, `JwtVerificationKey`, `language`, `LanguageMatch`, `LanguageOptions`, `logger`, `LoggerOptions`, `LoopDelayHistogram`, `LoopDelayMonitor`, `MemoryIdempotencyStore`, `MemoryIdempotencyStoreOptions`, `MemoryResponseCache`, `MemoryResponseCacheOptions`, `MemoryStore`, `MemoryStoreOptions`, `methodOverride`, `MethodOverrideOptions`, `namedCombine`, `openapi`, `OpenApiInfo`, `OpenApiOptions`, `OpenApiServer`, `OpenApiTag`, `OpenApiUiOptions`, `pickLanguage`, `poweredBy`, `PoweredByOptions`, `prettyJson`, `PrettyJsonOptions`, `rateLimit`, `RateLimitOptions`, `RateLimitResult`, `RateLimitStore`, `requestId`, `RequestIdOptions`, `RequestLogFields`, `responseCache`, `ResponseCacheStore`, `RouteLike`, `securityHeaders`, `SecurityHeadersOptions`, `SecurityRequirement`, `ShedReason`, `timing`, `TimingControls`, `TimingMetric`, `TimingOptions`, `TrailingSlashOptions`, `trimTrailingSlash`, `tryVerifyJwt`, `VerifiedJwt`, `verifyCsrfToken`, `verifyJwt`, `VerifyJwtOptions`, `VerifyJwtResult`
5897
6406
 
5898
6407
  ## @nifrajs/mock
5899
6408
 
@@ -5905,7 +6414,7 @@ done-gate, or `nifra mcp` to give the agent live project tools.
5905
6414
 
5906
6415
  ## @nifrajs/otel
5907
6416
 
5908
- `ActiveObservation`, `AttributeValue`, `combineObservationAdapters`, `consoleSpanExporter`, `createObservationLifecycle`, `EndObservation`, `formatTraceparent`, `generateSpanId`, `generateTraceId`, `NifraSpan`, `ObservationAdapter`, `ObservationClock`, `ObservationContext`, `ObservationLifecycle`, `ObservationLifecycleOptions`, `ObservationParent`, `ParsedTraceparent`, `parseTraceparent`, `SpanExporter`, `SpanStatus`, `StartObservation`, `TraceContext`, `traceHeaders`, `tracing`, `TracingOptions`
6417
+ `ActiveObservation`, `AttributeValue`, `causalitySpanLink`, `combineObservationAdapters`, `consoleSpanExporter`, `createObservationLifecycle`, `EndObservation`, `formatTraceparent`, `generateSpanId`, `generateTraceId`, `NifraSpan`, `ObservationAdapter`, `ObservationClock`, `ObservationContext`, `ObservationLifecycle`, `ObservationLifecycleOptions`, `ObservationLink`, `ObservationParent`, `ParsedTraceparent`, `parseTraceparent`, `SpanExporter`, `SpanStatus`, `StartObservation`, `TraceContext`, `traceHeaders`, `tracing`, `TracingOptions`
5909
6418
 
5910
6419
  ## @nifrajs/prompt
5911
6420
 
@@ -5925,7 +6434,7 @@ done-gate, or `nifra mcp` to give the agent live project tools.
5925
6434
 
5926
6435
  ## @nifrajs/testing
5927
6436
 
5928
- `AppLike`, `cookieJar`, `CookieJar`, `testSession`, `TestSession`, `TestSessionOptions`
6437
+ `AdapterCertificationError`, `AdapterCertificationProfile`, `AdapterCertificationReport`, `AdversarialContractError`, `AdversarialContractOptions`, `AdversarialContractReport`, `AdversarialContractResult`, `AppLike`, `assertAdapterCertification`, `assertAdversarialContract`, `assertIncidentReplays`, `cacheStoreCertificationProfile`, `CapturedRequest`, `CapturedRequestInput`, `captureIncident`, `CaptureIncidentOptions`, `CertifiableCacheEntry`, `CertifiableCacheStore`, `CertifiableDomainEvent`, `CertifiableEventDeliveryAdapter`, `CertifiableEventRecord`, `CertifiableJobStore`, `CertifiableRuntimeAdapter`, `CertifiableRuntimeServer`, `CertifiableStorageAdapter`, `CertificationCapabilityEvidence`, `CertificationCheck`, `CertificationCheckEvidence`, `certifyAdapter`, `ContractCaseContext`, `ContractCaseKind`, `ContractCoverageGap`, `ContractCoverageGapCode`, `ContractReplay`, `ContractRuntime`, `ContractTarget`, `ContractTestApp`, `ContractWitness`, `cookieJar`, `CookieJar`, `createFailureLab`, `defineCertificationProfile`, `eventDeliveryCertificationProfile`, `FailureDirective`, `FailureEvidence`, `FailureInjectedError`, `FailureKind`, `FailureLab`, `FailureLabOptions`, `FailureReplay`, `FailureScenario`, `FailureScenarioReport`, `generateRegressionTest`, `GenerateRegressionTestOptions`, `IncidentCapsule`, `IncidentReplayError`, `IncidentReplayResult`, `jobStoreCertificationProfile`, `redactForEmission`, `replayIncident`, `ReplayIncidentOptions`, `runAdversarialContract`, `runFailureScenario`, `runtimeAdapterCertificationProfile`, `shapeOf`, `storageAdapterCertificationProfile`, `testSession`, `TestSession`, `TestSessionOptions`, `verifyAdapterCertification`
5929
6438
 
5930
6439
  ## @nifrajs/uploads
5931
6440
 
@@ -5933,7 +6442,7 @@ done-gate, or `nifra mcp` to give the agent live project tools.
5933
6442
 
5934
6443
  ## @nifrajs/web
5935
6444
 
5936
- `Action`, `ACTION_GLOBAL`, `apiKey`, `assertRenderAdapterConformance`, `buildManifest`, `CachedResponse`, `CacheStore`, `canonical`, `clientEntry`, `ClientRouter`, `ClientRouterOptions`, `createClientRouter`, `createMatcher`, `createQueryClient`, `createWebApp`, `CreateWebAppOptions`, `DATA_GLOBAL`, `DATA_HEADER`, `DEFAULT_DEV_PORT`, `defer`, `Deferred`, `disableDraft`, `DRAFT_COOKIE`, `DraftCookieControls`, `enableDraft`, `EnableDraftOptions`, `enumeratePrerenderedPaths`, `enumerateStaticRoutes`, `Fetcher`, `FetcherState`, `FetchRouteData`, `filePathToPattern`, `filePathToPatterns`, `FontDisplay`, `fontFace`, `FontFace`, `fontPreload`, `FontPreloadInput`, `FontSource`, `generateClientEntry`, `GenerateClientEntryOptions`, `generateServerManifest`, `GenerateServerManifestOptions`, `GetStaticPaths`, `hashQueryKey`, `isDraftEnabled`, `ISR_REVALIDATE_HEADER`, `ISR_STATUS_HEADER`, `ISRApp`, `ISROptions`, `ISRPlatform`, `jsonLd`, `KVCacheStore`, `KVCacheStoreOptions`, `KVNamespaceLike`, `LayoutEntry`, `LinkDescriptor`, `Loader`, `LoaderContext`, `manifest`, `Manifest`, `MemoryCacheStore`, `MemoryCacheStoreOptions`, `mergeHeads`, `meta`, `Meta`, `MetaArgs`, `MetaInput`, `MountRouterOptions`, `openGraph`, `OpenGraphInput`, `PRE_HYDRATION_GUARD`, `QueryClient`, `QueryClientOptions`, `QueryHandle`, `QueryState`, `QueryStatus`, `redirect`, `REDIRECT_HEADER`, `RedirectOptions`, `RenderAdapter`, `RenderAdapterConformanceError`, `RenderAdapterConformanceFixture`, `RenderedPage`, `renderPage`, `RenderPageOptions`, `renderPageResult`, `RenderProps`, `resolveMeta`, `revalidate`, `REVALIDATE_HEADER`, `revalidateEndpoint`, `RevalidateEndpointOptions`, `RevalidateResult`, `ROUTE_GLOBAL`, `RouteEntry`, `RouteMatch`, `RouteModule`, `RoutePattern`, `RouterState`, `routeStyles`, `ScriptDescriptor`, `serializeData`, `ServerOnly`, `StaticPath`, `StaticPaths`, `StaticRoutes`, `styles`, `Submission`, `SubmitOptions`, `withISR`
6445
+ `Action`, `ACTION_GLOBAL`, `apiKey`, `assertRenderAdapterConformance`, `BrowserNavigate`, `buildManifest`, `CachedResponse`, `CacheStore`, `canonical`, `clientEntry`, `ClientRouter`, `ClientRouterOptions`, `createClientRouter`, `createMatcher`, `createMutation`, `createQueryClient`, `createWebApp`, `CreateWebAppOptions`, `DATA_GLOBAL`, `DATA_HEADER`, `DEFAULT_DEV_PORT`, `defer`, `Deferred`, `DehydratedState`, `disableDraft`, `DRAFT_COOKIE`, `DraftCookieControls`, `enableDraft`, `EnableDraftOptions`, `enumeratePrerenderedPaths`, `enumerateStaticRoutes`, `Fetcher`, `FetcherState`, `FetchRouteData`, `filePathToPattern`, `filePathToPatterns`, `FontDisplay`, `fontFace`, `FontFace`, `fontPreload`, `FontPreloadInput`, `FontSource`, `generateClientEntry`, `GenerateClientEntryOptions`, `generateServerManifest`, `GenerateServerManifestOptions`, `getBrowserNavigate`, `GetStaticPaths`, `hashQueryKey`, `InfiniteData`, `InfiniteQueryHandle`, `InfiniteQueryOptions`, `isDraftEnabled`, `ISR_REVALIDATE_HEADER`, `ISR_STATUS_HEADER`, `ISRApp`, `ISROptions`, `ISRPlatform`, `jsonLd`, `KVCacheStore`, `KVCacheStoreOptions`, `KVNamespaceLike`, `LayoutEntry`, `LinkDescriptor`, `Loader`, `LoaderContext`, `manifest`, `Manifest`, `MemoryCacheStore`, `MemoryCacheStoreOptions`, `mergeHeads`, `meta`, `Meta`, `MetaArgs`, `MetaInput`, `MountRouterOptions`, `MutationCallbacks`, `MutationHandle`, `MutationState`, `MutationStatus`, `NavigateOptions`, `openGraph`, `OpenGraphInput`, `PRE_HYDRATION_GUARD`, `QueryClient`, `QueryClientOptions`, `QueryHandle`, `QueryOptions`, `QueryState`, `QueryStatus`, `redirect`, `REDIRECT_HEADER`, `RedirectOptions`, `RenderAdapter`, `RenderAdapterConformanceError`, `RenderAdapterConformanceFixture`, `RenderedPage`, `renderPage`, `RenderPageOptions`, `renderPageResult`, `RenderProps`, `resolveMeta`, `revalidate`, `REVALIDATE_HEADER`, `revalidateEndpoint`, `RevalidateEndpointOptions`, `RevalidateResult`, `ROUTE_GLOBAL`, `RouteEntry`, `RouteMatch`, `RouteModule`, `RoutePattern`, `RouterState`, `routeStyles`, `ScriptDescriptor`, `serializeData`, `ServerOnly`, `setBrowserNavigate`, `StaticPath`, `StaticPaths`, `StaticRoutes`, `styles`, `Submission`, `SubmitOptions`, `withISR`
5937
6446
 
5938
6447
  ## @nifrajs/web-preact
5939
6448