@nifrajs/cli 2.0.0 → 2.1.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/dist/cli.js CHANGED
@@ -112,7 +112,7 @@ routes/ from the current directory. Run from your project root.
112
112
  Port: \`dev\` and \`start\` share the default ${DEFAULT_DEV_PORT}. Override with \`--port <n>\` (alias \`-p\`) or the
113
113
  \`PORT\` env var (\`--port\` wins over \`PORT\`, which wins over the default).`;
114
114
  // Kept in lockstep with packages/cli/package.json by check:publish's version-consistency gate.
115
- const CLI_VERSION = "2.0.0";
115
+ const CLI_VERSION = "2.1.0";
116
116
  // A render adapter + nifra server are opaque to the CLI (it just forwards them); cast at the seam.
117
117
  const asAdapter = (v) => v;
118
118
  const asBunPlugins = (v) => v;
package/dist/mcp-http.js CHANGED
@@ -19,7 +19,7 @@ import { loadTypesCorpus } from "./types-search.js";
19
19
  // tool factory + the transport core from one entry: `import { respondMcpHttp, docsTools } from "@nifrajs/cli/mcp"`.
20
20
  export { docsTools } from "./mcp-docs-tools.js";
21
21
  // Kept in lockstep with packages/cli/package.json by check:publish's version-consistency gate.
22
- const VERSION = "2.0.0";
22
+ const VERSION = "2.1.0";
23
23
  const SERVER_INFO = { name: "nifra-docs", version: VERSION };
24
24
  const DOCS_HEALTH = "nifra docs MCP — POST JSON-RPC 2.0 here (methods: initialize, tools/list, tools/call). Tools: nifra_docs, nifra_example.";
25
25
  /** The two project-independent tools, reading the package's bundled corpus from disk (CLI use). */
@@ -1731,12 +1731,23 @@ treated as a substitute for static provenance.
1731
1731
 
1732
1732
  ```ts
1733
1733
  // doc-check: skip — combines route and assurance-config excerpts.
1734
- // route: exact effect declaration + runtime beacon at the owned adapter seam
1735
- import { useCapability } from "@nifrajs/core/capabilities"
1734
+ // route: exact effect declaration + correlated execution at the owned adapter seam
1735
+ import { executeCapability } from "@nifrajs/core/capabilities"
1736
+
1737
+ app.aroundCapability(async (effect, next) => {
1738
+ // Ask an entitlement service or short-lived approval gate using token-only metadata.
1739
+ // effect.signal aborts on request cancellation or the interceptor timeout.
1740
+ if (!policyAllows(effect.capability, effect.target)) return // deny fail-closed
1741
+ await next()
1742
+ }, { timeoutMs: 5_000 })
1736
1743
 
1737
1744
  app.post("/orders", { capabilities: ["db.write"] }, async (c) => {
1738
- useCapability(c, "db.write") // undeclared use fails before the effect
1739
- return orders.write(c.body)
1745
+ return executeCapability(
1746
+ c,
1747
+ "db.write",
1748
+ { target: "repo:orders" },
1749
+ ({ signal }) => orders.write(c.body, { signal }),
1750
+ )
1740
1751
  })
1741
1752
 
1742
1753
  // in nifra.assurance.ts, alongside policy:
@@ -1766,6 +1777,51 @@ Domain writes on `GET`/`HEAD` are hard violations. Each write definition may
1766
1777
  require request idempotency or durable command/provider-key evidence. The lockfile contains only
1767
1778
  method, path, and capability tokens—no payloads or tenant data—and CI never rewrites it.
1768
1779
 
1780
+ ### Durable approval, compensation, and reconciliation
1781
+
1782
+ The durable execution subpath turns the capability boundary into a crash-visible workflow.
1783
+ Approval resumes are HMAC-signed, expire, bind to the tenant, principal, capability, target, and
1784
+ digest, and are consumed atomically once. The effect journal marks execution before the provider
1785
+ call, so a crash after an external commit remains `ambiguous` for reconciliation instead
1786
+ of being retried blindly. Typed sagas persist compensation arguments separately from the sealed
1787
+ token-only ledger and compensate committed steps in reverse order with retry/backoff state.
1788
+
1789
+ ```ts
1790
+ // doc-check: skip — durable store implementations are deployment-specific.
1791
+ import {
1792
+ createApprovalCoordinator,
1793
+ createDurableEffectJournal,
1794
+ createSagaEngine,
1795
+ } from "@nifrajs/core/durable-execution"
1796
+ import { effectTracing } from "@nifrajs/otel/effects"
1797
+
1798
+ const effects = effectTracing({ exporter })
1799
+ app.use(effects)
1800
+
1801
+ const approval = createApprovalCoordinator({
1802
+ store: durableApprovalStore, // must declare durability: "durable"
1803
+ secret: approvalHmacKey, // 32+ random bytes, stored separately
1804
+ })
1805
+ const journal = createDurableEffectJournal({ store: durableEffectStore })
1806
+
1807
+ await executeCapability(c, "payments.charge", {
1808
+ target: "provider:stripe",
1809
+ digest,
1810
+ journal,
1811
+ approval: {
1812
+ gate: approval,
1813
+ tenantId: c.principal.tenantId,
1814
+ principalId: c.principal.userId,
1815
+ resumeToken,
1816
+ },
1817
+ }, ({ effectId, signal }) => payments.charge(input, { idempotencyKey: effectId, signal }))
1818
+
1819
+ const sagas = createSagaEngine({
1820
+ store: durableSagaStore,
1821
+ observer: effects.observer,
1822
+ })
1823
+ ```
1824
+
1769
1825
  ### Already built in
1770
1826
 
1771
1827
  These add to Nifra's standing defaults: strict-by-default schema validation (unknown fields
@@ -5754,6 +5810,33 @@ import { defineAssurancePolicy } from "@nifrajs/core/assurance"
5754
5810
  IP-restriction, and security-header modules publish reflection-safe enforcement evidence.
5755
5811
  An ordered `AssurancePolicy` classifies every route and fails closed on missing or forbidden
5756
5812
  evidence without adding work to the request path.
5813
+ - **Owned effect execution.** `executeCapability()` correlates intent and terminal evidence with an
5814
+ opaque `effectId`, records outcomes automatically, and forwards request cancellation. Add
5815
+ order-scoped `aroundCapability()` policies for async approval/admission; they receive token-only
5816
+ metadata, have bounded timeouts, and must call `next()` exactly once before the effect can run.
5817
+ - **Durable workflows (opt in).** `@nifrajs/core/durable-execution` provides tenant/principal-bound,
5818
+ signed single-use approval resumes; a durable effect journal + reconciliation scanner; and a typed
5819
+ saga state machine with reverse compensation, retry/backoff, and ambiguous-crash detection. Production
5820
+ constructors reject stores that do not declare `durability: "durable"`. Operational scans use bounded
5821
+ cursor pages through `reconcileEffectsPage()` / `reconcileSagasPage()`. Provider-confirmed manual
5822
+ review uses effect-ID-bound `resolveAmbiguity()`, followed by `resume()` or `compensate()`.
5823
+ - **Production durable adapters.** `@nifrajs/core/durable-adapters` supplies
5824
+ `PostgresDurableExecutionAdapter`, `SQLiteDurableExecutionAdapter`, and
5825
+ `DurableObjectExecutionAdapter`. Each exposes compatible `effects`, `approvals`, `sagas`, and
5826
+ `leases` stores. Run `runDurableExecutionAdapterConformance()` against the deployment backend.
5827
+ - **Bounded reconciliation workers.** `@nifrajs/core/reconciliation-worker` runs effect or saga
5828
+ scans under an atomic lease with durable cursor checkpoints, a finite page budget, bounded handler
5829
+ concurrency, filters, cancellation, and token-only metrics. A worker invocation always terminates.
5830
+ - **Rich wire values (opt in).** `@nifrajs/core/wire` round-trips dates, bigints, maps, sets, binary,
5831
+ shared references, and cycles through JSON transports. Decoding validates every reachable shape,
5832
+ preserves owned `__proto__` keys without prototype mutation, and enforces configurable node, depth,
5833
+ collection-entry, and decoded-byte limits.
5834
+ - **Versioned transport codecs (opt in).** Add `.use(transportCodecs(registry))` from
5835
+ `@nifrajs/core/transport-plugin` and configure the typed
5836
+ client's `transport` option with the same registry. `@nifrajs/core/transport-codec` negotiates
5837
+ bounded HTTP representations and supplies the same frame/loader adapters for WebSockets and
5838
+ deferred data. Import `richWireCodec()` from `@nifrajs/core/transport-codec-rich`; the separate
5839
+ subpath keeps rich-wire code out of plain JSON bundles.
5757
5840
 
5758
5841
  ```ts
5759
5842
  import { defineAssurancePolicy, evaluateRouteAssurance, NIFRA_ASSURANCE } from "@nifrajs/core/assurance"
@@ -7375,7 +7458,7 @@ done-gate, or `nifra mcp` to give the agent live project tools.
7375
7458
 
7376
7459
  ## @nifrajs/otel
7377
7460
 
7378
- `ActiveObservation`, `AttributeValue`, `causalitySpanLink`, `combineObservationAdapters`, `consoleSpanExporter`, `createObservationLifecycle`, `EndObservation`, `formatTraceparent`, `generateSpanId`, `generateTraceId`, `NifraSpan`, `ObservationAdapter`, `ObservationClock`, `ObservationContext`, `ObservationLifecycle`, `ObservationLifecycleOptions`, `ObservationLink`, `ObservationParent`, `otlpExporter`, `OtlpExporter`, `OtlpExporterOptions`, `ParsedTraceparent`, `parseTraceparent`, `SpanStatus`, `StartObservation`, `TraceContext`, `traceHeaders`, `tracing`, `TracingOptions`
7461
+ `ActiveObservation`, `AttributeValue`, `causalitySpanLink`, `combineObservationAdapters`, `consoleSpanExporter`, `createObservationLifecycle`, `effectTracing`, `EffectTracingOptions`, `EffectTracingPlugin`, `EndObservation`, `formatTraceparent`, `generateSpanId`, `generateTraceId`, `NifraSpan`, `ObservationAdapter`, `ObservationClock`, `ObservationContext`, `ObservationLifecycle`, `ObservationLifecycleOptions`, `ObservationLink`, `ObservationParent`, `otlpExporter`, `OtlpExporter`, `OtlpExporterOptions`, `ParsedTraceparent`, `parseTraceparent`, `SpanStatus`, `StartObservation`, `TraceContext`, `traceHeaders`, `tracing`, `TracingOptions`
7379
7462
 
7380
7463
  ## @nifrajs/prompt
7381
7464