@nifrajs/core 2.2.0 → 2.4.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/README.md +2 -2
- package/dist/assurance.d.ts +48 -4
- package/dist/assurance.d.ts.map +1 -1
- package/dist/assurance.js +87 -9
- package/dist/assurance.js.map +1 -1
- package/dist/binary.d.ts +54 -0
- package/dist/binary.d.ts.map +1 -0
- package/dist/binary.js +90 -0
- package/dist/binary.js.map +1 -0
- package/dist/budget.d.ts +1 -1
- package/dist/budget.js +1 -1
- package/dist/capabilities.d.ts +19 -2
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +60 -8
- package/dist/capabilities.js.map +1 -1
- package/dist/classification.d.ts +1 -1
- package/dist/classification.js +1 -1
- package/dist/diff.d.ts +6 -6
- package/dist/diff.js +6 -6
- package/dist/durable-adapters.d.ts.map +1 -1
- package/dist/durable-adapters.js +36 -70
- package/dist/durable-adapters.js.map +1 -1
- package/dist/durable-execution.d.ts +2 -2
- package/dist/durable-execution.js +2 -2
- package/dist/idempotency.d.ts +3 -3
- package/dist/idempotency.js +4 -4
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/internal/brand.d.ts +1 -1
- package/dist/internal/brand.js +1 -1
- package/dist/internal/route-catalog.d.ts +58 -0
- package/dist/internal/route-catalog.d.ts.map +1 -0
- package/dist/internal/route-catalog.js +58 -0
- package/dist/internal/route-catalog.js.map +1 -0
- package/dist/internal/route-execution.d.ts +75 -0
- package/dist/internal/route-execution.d.ts.map +1 -0
- package/dist/internal/route-execution.js +2 -0
- package/dist/internal/route-execution.js.map +1 -0
- package/dist/internal/same-origin.d.ts +29 -0
- package/dist/internal/same-origin.d.ts.map +1 -0
- package/dist/internal/same-origin.js +47 -0
- package/dist/internal/same-origin.js.map +1 -0
- package/dist/internal/secret.d.ts +1 -1
- package/dist/internal/secret.js +1 -1
- package/dist/ledger.d.ts +9 -9
- package/dist/ledger.js +5 -5
- package/dist/reflection.d.ts +1 -1
- package/dist/router/pattern.d.ts +9 -0
- package/dist/router/pattern.d.ts.map +1 -1
- package/dist/router/pattern.js +13 -4
- package/dist/router/pattern.js.map +1 -1
- package/dist/router/router.js +3 -3
- package/dist/schema/standard.d.ts +2 -2
- package/dist/schema/standard.js +2 -2
- package/dist/seo.d.ts +3 -3
- package/dist/seo.js +4 -4
- package/dist/server/body.d.ts +2 -2
- package/dist/server/body.js +2 -2
- package/dist/server/context.d.ts +18 -18
- package/dist/server/contract.d.ts +7 -7
- package/dist/server/contract.js +3 -3
- package/dist/server/cookies.d.ts +4 -4
- package/dist/server/cookies.js +8 -8
- package/dist/server/edge.d.ts +83 -0
- package/dist/server/edge.d.ts.map +1 -0
- package/dist/server/edge.js +71 -0
- package/dist/server/edge.js.map +1 -0
- package/dist/server/install.d.ts +2 -0
- package/dist/server/install.d.ts.map +1 -1
- package/dist/server/install.js +2 -0
- package/dist/server/install.js.map +1 -1
- package/dist/server/logger.d.ts +7 -7
- package/dist/server/logger.js +4 -4
- package/dist/server/registry.d.ts +5 -5
- package/dist/server/response-contract-lane.d.ts +91 -0
- package/dist/server/response-contract-lane.d.ts.map +1 -0
- package/dist/server/response-contract-lane.js +81 -0
- package/dist/server/response-contract-lane.js.map +1 -0
- package/dist/server/server.d.ts +52 -91
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +130 -186
- package/dist/server/server.js.map +1 -1
- package/dist/server/sse.d.ts +4 -4
- package/dist/server/sse.js +7 -7
- package/dist/server/webhook.d.ts +1 -1
- package/dist/server/webhook.js +5 -5
- package/dist/server/websocket.d.ts +19 -19
- package/dist/server/websocket.js +9 -9
- package/dist/server/ws-bun.d.ts +4 -4
- package/dist/server/ws-bun.js +3 -3
- package/dist/server.d.ts +3 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +3 -1
- package/dist/server.js.map +1 -1
- package/dist/transport-codec.d.ts +12 -0
- package/dist/transport-codec.d.ts.map +1 -1
- package/dist/transport-codec.js +19 -4
- package/dist/transport-codec.js.map +1 -1
- package/package.json +12 -2
- package/src/assurance.ts +154 -8
- package/src/binary.ts +128 -0
- package/src/budget.ts +1 -1
- package/src/capabilities.ts +71 -9
- package/src/classification.ts +1 -1
- package/src/diff.ts +8 -8
- package/src/durable-adapters.ts +40 -70
- package/src/durable-execution.ts +2 -2
- package/src/idempotency.ts +4 -4
- package/src/index.ts +3 -3
- package/src/internal/brand.ts +1 -1
- package/src/internal/route-catalog.ts +94 -0
- package/src/internal/route-execution.ts +106 -0
- package/src/internal/same-origin.ts +43 -0
- package/src/internal/secret.ts +1 -1
- package/src/ledger.ts +11 -11
- package/src/reflection.ts +1 -1
- package/src/router/pattern.ts +16 -4
- package/src/router/router.ts +5 -5
- package/src/schema/standard.ts +2 -2
- package/src/seo.ts +6 -6
- package/src/server/body.ts +2 -2
- package/src/server/context.ts +18 -18
- package/src/server/contract.ts +13 -13
- package/src/server/cookies.ts +8 -8
- package/src/server/edge.ts +150 -0
- package/src/server/install.ts +5 -0
- package/src/server/logger.ts +8 -8
- package/src/server/registry.ts +5 -5
- package/src/server/response-contract-lane.ts +164 -0
- package/src/server/server.ts +159 -366
- package/src/server/sse.ts +11 -11
- package/src/server/webhook.ts +5 -5
- package/src/server/websocket.ts +22 -22
- package/src/server/ws-bun.ts +4 -4
- package/src/server.ts +8 -5
- package/src/transport-codec.ts +24 -5
package/dist/server/websocket.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* WebSocket seam
|
|
2
|
+
* WebSocket seam - portable types shared by `@nifrajs/core`'s `app.ws()` and every serving adapter
|
|
3
3
|
* (Bun `listen()`, `@nifrajs/node`, `@nifrajs/deno`, `toFetchHandler` on Workers). No runtime code here, so
|
|
4
4
|
* it stays edge-safe and dependency-free; each adapter implements {@link NifraWebSocket} over its
|
|
5
5
|
* runtime's native socket and dispatches to the handler.
|
|
6
6
|
*
|
|
7
|
-
* A WS upgrade can't go through `app.fetch` (which has no socket)
|
|
7
|
+
* A WS upgrade can't go through `app.fetch` (which has no socket) - it's adapter-integrated. The
|
|
8
8
|
* adapter calls `app.resolveWebSocketUpgrade(req)` (runs the route's `upgrade()` guard in a real
|
|
9
9
|
* request context), then performs the runtime upgrade with the returned data.
|
|
10
10
|
*/
|
|
11
11
|
import { validateStandard } from "../schema/standard.js";
|
|
12
12
|
import { decodeTransportFrame } from "../transport-codec.js";
|
|
13
13
|
/**
|
|
14
|
-
* In-process pub/sub for `ws.subscribe(topic)` + `app.publish(topic, data)`. **Single-instance only**
|
|
14
|
+
* In-process pub/sub for `ws.subscribe(topic)` + `app.publish(topic, data)`. **Single-instance only** -
|
|
15
15
|
* topics live in this process's memory, so a multi-instance deploy (multiple servers behind a load
|
|
16
16
|
* balancer) needs an external fan-out (Redis pub/sub, a Cloudflare Durable Object, NATS, …) bridged to
|
|
17
17
|
* `app.publish`. The same registry instance is shared by an app's connections and its `publish`.
|
|
@@ -38,11 +38,11 @@ export class TopicRegistry {
|
|
|
38
38
|
if (subs !== undefined) {
|
|
39
39
|
subs.delete(ws);
|
|
40
40
|
if (subs.size === 0)
|
|
41
|
-
this.topics.delete(topic); // reclaim empty topics
|
|
41
|
+
this.topics.delete(topic); // reclaim empty topics - no unbounded growth
|
|
42
42
|
}
|
|
43
43
|
this.memberships.get(ws)?.delete(topic);
|
|
44
44
|
}
|
|
45
|
-
/** Drop every subscription for a connection
|
|
45
|
+
/** Drop every subscription for a connection - called on close so a registry never leaks dead sockets. */
|
|
46
46
|
unsubscribeAll(ws) {
|
|
47
47
|
const mine = this.memberships.get(ws);
|
|
48
48
|
if (mine === undefined)
|
|
@@ -80,13 +80,13 @@ function toBinary(raw) {
|
|
|
80
80
|
return new Uint8Array(raw);
|
|
81
81
|
if (ArrayBuffer.isView(raw))
|
|
82
82
|
return new Uint8Array(raw.buffer, raw.byteOffset, raw.byteLength);
|
|
83
|
-
return new Uint8Array(0); // unknown (e.g. an unconverted Blob)
|
|
83
|
+
return new Uint8Array(0); // unknown (e.g. an unconverted Blob) - adapters set binaryType to avoid this
|
|
84
84
|
}
|
|
85
85
|
/**
|
|
86
86
|
* Wire a standard server-side `WebSocket` to a nifra {@link WebSocketHandler}, returning the portable
|
|
87
87
|
* {@link NifraWebSocket}. Shared by the Deno and Workers bridges. `openNow` fires `open` immediately
|
|
88
88
|
* (Workers, where the socket is already open after `accept()`); otherwise `open` waits for the socket's
|
|
89
|
-
* `open` event (Deno). Lifecycle callbacks are error-isolated
|
|
89
|
+
* `open` event (Deno). Lifecycle callbacks are error-isolated - a throw (or async rejection) routes to
|
|
90
90
|
* `error()` and never tears the process down; binary frames are normalized to `Uint8Array`.
|
|
91
91
|
*/
|
|
92
92
|
export function attachWebSocket(socket, handler, data, options) {
|
|
@@ -111,7 +111,7 @@ export function attachWebSocket(socket, handler, data, options) {
|
|
|
111
111
|
r.catch(() => { });
|
|
112
112
|
}
|
|
113
113
|
catch {
|
|
114
|
-
/* the error handler itself failed
|
|
114
|
+
/* the error handler itself failed - last resort, swallow */
|
|
115
115
|
}
|
|
116
116
|
};
|
|
117
117
|
const safe = (call) => {
|
|
@@ -147,7 +147,7 @@ export function attachWebSocket(socket, handler, data, options) {
|
|
|
147
147
|
}
|
|
148
148
|
const WS_MESSAGE_DECODER = new TextDecoder();
|
|
149
149
|
/**
|
|
150
|
-
* If the handler declares a `messageSchema`, return a copy whose `message` validates each frame
|
|
150
|
+
* If the handler declares a `messageSchema`, return a copy whose `message` validates each frame -
|
|
151
151
|
* parse as JSON, run the Standard Schema, then call the user's `message` with the typed value, or
|
|
152
152
|
* `onInvalidMessage` on failure. Returns the handler unchanged when no schema is set. Called once at
|
|
153
153
|
* `app.ws()` registration, so every adapter dispatches validated messages with no per-adapter code.
|
package/dist/server/ws-bun.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Bun WebSocket plumbing
|
|
2
|
+
* Bun WebSocket plumbing - the `websocket` dispatcher config `listen()` hands to Bun's serve when
|
|
3
3
|
* the app has WS routes. Lives behind the `@nifrajs/core/ws` subpath (via `ws-hook.ts`) so the base
|
|
4
4
|
* bundle of a no-WebSocket app never ships it; `server.ts` only imports the **types** from here
|
|
5
|
-
* (erased). No `Bun.*` calls here
|
|
5
|
+
* (erased). No `Bun.*` calls here - the runtime seam stays in `server.ts` (see runtime-boundary.test).
|
|
6
6
|
*/
|
|
7
7
|
import type { NifraWebSocket, TopicRegistry, WebSocketHandler } from "./websocket.js";
|
|
8
8
|
import type { BunWsHandlers } from "./ws-hook.js";
|
|
@@ -13,7 +13,7 @@ export interface BunWsData {
|
|
|
13
13
|
data: unknown;
|
|
14
14
|
nifra?: NifraWebSocket;
|
|
15
15
|
}
|
|
16
|
-
/** Structural view of Bun's `ServerWebSocket`
|
|
16
|
+
/** Structural view of Bun's `ServerWebSocket` - keeps `Bun.*` types out of the public `.d.ts`
|
|
17
17
|
* (`listen()` casts for the same reason). The real socket satisfies this. */
|
|
18
18
|
export interface BunSocket {
|
|
19
19
|
send(data: string | ArrayBufferView | ArrayBuffer, compress?: boolean): number;
|
|
@@ -21,7 +21,7 @@ export interface BunSocket {
|
|
|
21
21
|
readonly readyState: number;
|
|
22
22
|
readonly data: BunWsData;
|
|
23
23
|
}
|
|
24
|
-
/** The shared Bun `websocket` dispatcher config for one app
|
|
24
|
+
/** The shared Bun `websocket` dispatcher config for one app - each connection's
|
|
25
25
|
* `ws.data.handler` is the matched route's handler, set by `server.upgrade`. */
|
|
26
26
|
export declare function createBunWsHandlers(topics: TopicRegistry): BunWsHandlers;
|
|
27
27
|
//# sourceMappingURL=ws-bun.d.ts.map
|
package/dist/server/ws-bun.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Bun WebSocket plumbing
|
|
2
|
+
* Bun WebSocket plumbing - the `websocket` dispatcher config `listen()` hands to Bun's serve when
|
|
3
3
|
* the app has WS routes. Lives behind the `@nifrajs/core/ws` subpath (via `ws-hook.ts`) so the base
|
|
4
4
|
* bundle of a no-WebSocket app never ships it; `server.ts` only imports the **types** from here
|
|
5
|
-
* (erased). No `Bun.*` calls here
|
|
5
|
+
* (erased). No `Bun.*` calls here - the runtime seam stays in `server.ts` (see runtime-boundary.test).
|
|
6
6
|
*/
|
|
7
7
|
/** Normalize a received binary frame to `Uint8Array` (Bun hands a `Buffer`, already one; an
|
|
8
8
|
* `ArrayBuffer` is wrapped). Text frames stay `string`. */
|
|
@@ -55,7 +55,7 @@ function dispatchWsCallback(call, ws, handler) {
|
|
|
55
55
|
reportWsError(error, ws, handler);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
/** The shared Bun `websocket` dispatcher config for one app
|
|
58
|
+
/** The shared Bun `websocket` dispatcher config for one app - each connection's
|
|
59
59
|
* `ws.data.handler` is the matched route's handler, set by `server.upgrade`. */
|
|
60
60
|
export function createBunWsHandlers(topics) {
|
|
61
61
|
return {
|
package/dist/server.d.ts
CHANGED
|
@@ -9,13 +9,15 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export { FrameworkError, RouteConfigError, type RouteConfigErrorCode } from "./errors.js";
|
|
11
11
|
export { FRAMEWORK_NAME, type FrameworkName } from "./internal/brand.js";
|
|
12
|
+
export { isSameOriginRequest } from "./internal/same-origin.js";
|
|
12
13
|
export { METHODS, type Method, Router, type RouterMatch } from "./router/router.js";
|
|
13
14
|
export type { InferInput, InferOutput, StandardIssue, StandardResult, StandardSchemaV1, StandardTypes, ValidationOutcome, } from "./schema/standard.js";
|
|
14
15
|
export type { Context, Params, Platform, Prettify, ResponseControls, RouteSchema, } from "./server/context.js";
|
|
15
16
|
export { type CookieOptions, parseCookies, serializeCookie, signValue, unsignValue, } from "./server/cookies.js";
|
|
17
|
+
export { type DurableObjectNamespaceLike, type ExecutionContext, type ScheduledController, type ScheduledHandler, toFetchHandler, } from "./server/edge.js";
|
|
16
18
|
export { commonSecretPatterns, jsonLogger, type LogFields, type Logger, type RedactOptions, redactLogFields, silentLogger, } from "./server/logger.js";
|
|
17
19
|
export type { Registry, RouteInfo } from "./server/registry.js";
|
|
18
|
-
export { type AdmissionController, type AdmissionDecision, type AnyServer,
|
|
20
|
+
export { type AdmissionController, type AdmissionDecision, type AnyServer, defineIdentityPlugin, definePlugin, defineRouterPlugin, type Handler, type IdentityPlugin, type McpPromptDescriptor, type McpResourceDescriptor, type Middleware, type NifraPlugin, type NodeServeOutcome, type OnRequestResult, type PromptArgument, type PromptMessage, type ResponseFinalization, type RouteDescriptor, type RunningServer, Server, type ServerOptions, server, type ToolAnnotations, } from "./server/server.js";
|
|
19
21
|
export type { SSEContext, SSEInit, SSEMessage, SSEStream, TypedSSEStream, } from "./server/sse.js";
|
|
20
22
|
export type { NifraWebSocket, StandardWebSocket, WebSocketContext, WebSocketData, WebSocketHandler, WebSocketUpgradeOutcome, } from "./server/websocket.js";
|
|
21
23
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACzF,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxE,OAAO,EAAE,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACnF,YAAY,EACV,UAAU,EACV,WAAW,EACX,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,iBAAiB,GAClB,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EACV,OAAO,EACP,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,WAAW,GACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,KAAK,aAAa,EAClB,YAAY,EACZ,eAAe,EACf,SAAS,EACT,WAAW,GACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,KAAK,SAAS,EACd,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,eAAe,EACf,YAAY,GACb,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAC/D,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACzF,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAAE,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACnF,YAAY,EACV,UAAU,EACV,WAAW,EACX,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,iBAAiB,GAClB,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EACV,OAAO,EACP,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,WAAW,GACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,KAAK,aAAa,EAClB,YAAY,EACZ,eAAe,EACf,SAAS,EACT,WAAW,GACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,cAAc,GACf,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,KAAK,SAAS,EACd,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,eAAe,EACf,YAAY,GACb,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAC/D,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,SAAS,EACd,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,EAClB,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,MAAM,EACN,KAAK,aAAa,EAClB,MAAM,EACN,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,UAAU,EACV,OAAO,EACP,UAAU,EACV,SAAS,EACT,cAAc,GACf,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,uBAAuB,CAAA"}
|
package/dist/server.js
CHANGED
|
@@ -9,8 +9,10 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export { FrameworkError, RouteConfigError } from "./errors.js";
|
|
11
11
|
export { FRAMEWORK_NAME } from "./internal/brand.js";
|
|
12
|
+
export { isSameOriginRequest } from "./internal/same-origin.js";
|
|
12
13
|
export { METHODS, Router } from "./router/router.js";
|
|
13
14
|
export { parseCookies, serializeCookie, signValue, unsignValue, } from "./server/cookies.js";
|
|
15
|
+
export { toFetchHandler, } from "./server/edge.js";
|
|
14
16
|
export { commonSecretPatterns, jsonLogger, redactLogFields, silentLogger, } from "./server/logger.js";
|
|
15
|
-
export { defineIdentityPlugin, definePlugin, defineRouterPlugin, Server, server,
|
|
17
|
+
export { defineIdentityPlugin, definePlugin, defineRouterPlugin, Server, server, } from "./server/server.js";
|
|
16
18
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAA6B,MAAM,aAAa,CAAA;AACzF,OAAO,EAAE,cAAc,EAAsB,MAAM,qBAAqB,CAAA;AACxE,OAAO,EAAE,OAAO,EAAe,MAAM,EAAoB,MAAM,oBAAoB,CAAA;AAkBnF,OAAO,EAEL,YAAY,EACZ,eAAe,EACf,SAAS,EACT,WAAW,GACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,oBAAoB,EACpB,UAAU,EAIV,eAAe,EACf,YAAY,GACb,MAAM,oBAAoB,CAAA;AAE3B,OAAO,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAA6B,MAAM,aAAa,CAAA;AACzF,OAAO,EAAE,cAAc,EAAsB,MAAM,qBAAqB,CAAA;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAAE,OAAO,EAAe,MAAM,EAAoB,MAAM,oBAAoB,CAAA;AAkBnF,OAAO,EAEL,YAAY,EACZ,eAAe,EACf,SAAS,EACT,WAAW,GACZ,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAKL,cAAc,GACf,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,oBAAoB,EACpB,UAAU,EAIV,eAAe,EACf,YAAY,GACb,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAIL,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,EAclB,MAAM,EAEN,MAAM,GAEP,MAAM,oBAAoB,CAAA"}
|
|
@@ -25,6 +25,18 @@ export interface TransportCodecRegistry {
|
|
|
25
25
|
export declare function createTransportCodecRegistry(codecs: readonly TransportCodec[], fallback?: TransportCodec): TransportCodecRegistry;
|
|
26
26
|
export declare const defaultTransportCodecs: TransportCodecRegistry;
|
|
27
27
|
export declare function encodeTransportResponse(value: unknown, codec?: TransportCodec, init?: ResponseInit): Response;
|
|
28
|
+
/**
|
|
29
|
+
* Read a response body into memory, refusing to exceed `maxBytes`.
|
|
30
|
+
*
|
|
31
|
+
* Bounded while STREAMING rather than after the fact: the `content-length` shortcut only helps when a
|
|
32
|
+
* sender declares one, so the loop also counts as it goes and cancels the reader the moment the total
|
|
33
|
+
* passes the limit. A cap that buffers first and complains afterwards has already spent the memory it
|
|
34
|
+
* was meant to protect.
|
|
35
|
+
*
|
|
36
|
+
* Exported so the client can bound a plain-text body with the same reader it bounds JSON with, rather
|
|
37
|
+
* than growing a second copy of this loop that could drift from it.
|
|
38
|
+
*/
|
|
39
|
+
export declare function readBoundedBytes(response: Response, options: TransportDecodeOptions): Promise<Uint8Array>;
|
|
28
40
|
export declare function decodeTransportResponse(response: Response, registry?: TransportCodecRegistry, options?: TransportDecodeOptions): Promise<unknown>;
|
|
29
41
|
export declare function encodeTransportFrame(value: unknown, codec?: TransportCodec): string;
|
|
30
42
|
export declare function decodeTransportFrame(frame: string, registry?: TransportCodecRegistry, options?: TransportDecodeOptions): unknown;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport-codec.d.ts","sourceRoot":"","sources":["../src/transport-codec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;IAC9B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAC9B;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD;AAsCD,eAAO,MAAM,cAAc,EAAE,cAY3B,CAAA;AAEF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAAA;IAC1D,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAAA;IAChD,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAAA;CACxD;AAUD,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,QAAQ,GAAE,cAA+B,GACxC,sBAAsB,CA0ExB;AAED,eAAO,MAAM,sBAAsB,EAAE,sBAEnC,CAAA;AAEF,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,KAAK,GAAE,cAA+B,EACtC,IAAI,GAAE,YAAiB,GACtB,QAAQ,CAKV;
|
|
1
|
+
{"version":3,"file":"transport-codec.d.ts","sourceRoot":"","sources":["../src/transport-codec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;IAC9B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAC9B;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD;AAsCD,eAAO,MAAM,cAAc,EAAE,cAY3B,CAAA;AAEF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAAA;IAC1D,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAAA;IAChD,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAAA;CACxD;AAUD,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,QAAQ,GAAE,cAA+B,GACxC,sBAAsB,CA0ExB;AAED,eAAO,MAAM,sBAAsB,EAAE,sBAEnC,CAAA;AAEF,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,KAAK,GAAE,cAA+B,EACtC,IAAI,GAAE,YAAiB,GACtB,QAAQ,CAKV;AAQD;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,UAAU,CAAC,CA8BrB;AAaD,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,QAAQ,EAClB,QAAQ,GAAE,sBAA+C,EACzD,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,OAAO,CAAC,CAQlB;AAQD,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,EACd,KAAK,GAAE,cAA+B,GACrC,MAAM,CAER;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,sBAA+C,EACzD,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAsBT"}
|
package/dist/transport-codec.js
CHANGED
|
@@ -14,9 +14,9 @@ export class TransportCodecError extends TypeError {
|
|
|
14
14
|
* Run a decode step and normalize whatever it throws into {@link TransportCodecError}.
|
|
15
15
|
*
|
|
16
16
|
* Decoding is the one place this module touches attacker-controlled bytes, and the primitives it
|
|
17
|
-
* delegates to raise their own native types
|
|
17
|
+
* delegates to raise their own native types - `JSON.parse` throws `SyntaxError`, a BYO codec throws
|
|
18
18
|
* whatever it likes. Every other failure here is a `TransportCodecError`, so letting those escape
|
|
19
|
-
* would mean a malformed payload
|
|
19
|
+
* would mean a malformed payload - the single most likely hostile input - is the one case that slips
|
|
20
20
|
* past a caller catching the documented error type. The original is kept as `cause`, so the parse
|
|
21
21
|
* failure stays diagnosable; a codec already speaking the contract is re-thrown untouched.
|
|
22
22
|
*/
|
|
@@ -152,13 +152,24 @@ function appendVary(current, name) {
|
|
|
152
152
|
const values = current.split(",").map((value) => value.trim().toLowerCase());
|
|
153
153
|
return values.includes(name.toLowerCase()) ? current : `${current}, ${name}`;
|
|
154
154
|
}
|
|
155
|
-
|
|
155
|
+
/**
|
|
156
|
+
* Read a response body into memory, refusing to exceed `maxBytes`.
|
|
157
|
+
*
|
|
158
|
+
* Bounded while STREAMING rather than after the fact: the `content-length` shortcut only helps when a
|
|
159
|
+
* sender declares one, so the loop also counts as it goes and cancels the reader the moment the total
|
|
160
|
+
* passes the limit. A cap that buffers first and complains afterwards has already spent the memory it
|
|
161
|
+
* was meant to protect.
|
|
162
|
+
*
|
|
163
|
+
* Exported so the client can bound a plain-text body with the same reader it bounds JSON with, rather
|
|
164
|
+
* than growing a second copy of this loop that could drift from it.
|
|
165
|
+
*/
|
|
166
|
+
export async function readBoundedBytes(response, options) {
|
|
156
167
|
const maxBytes = maxBytesOf(options);
|
|
157
168
|
const declared = response.headers.get("content-length");
|
|
158
169
|
if (declared !== null && /^\d+$/u.test(declared) && Number(declared) > maxBytes)
|
|
159
170
|
throw new TransportCodecError("transport payload exceeds maxBytes");
|
|
160
171
|
if (response.body === null)
|
|
161
|
-
return
|
|
172
|
+
return new Uint8Array(0);
|
|
162
173
|
const reader = response.body.getReader();
|
|
163
174
|
const chunks = [];
|
|
164
175
|
let total = 0;
|
|
@@ -184,6 +195,10 @@ async function readBoundedText(response, options) {
|
|
|
184
195
|
bytes.set(chunk, offset);
|
|
185
196
|
offset += chunk.byteLength;
|
|
186
197
|
}
|
|
198
|
+
return bytes;
|
|
199
|
+
}
|
|
200
|
+
async function readBoundedText(response, options) {
|
|
201
|
+
const bytes = await readBoundedBytes(response, options);
|
|
187
202
|
return decodeOrThrow(() => new TextDecoder("utf-8", { fatal: true }).decode(bytes), "transport payload is not valid UTF-8");
|
|
188
203
|
}
|
|
189
204
|
export async function decodeTransportResponse(response, registry = defaultTransportCodecs, options = {}) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport-codec.js","sourceRoot":"","sources":["../src/transport-codec.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"transport-codec.js","sourceRoot":"","sources":["../src/transport-codec.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nifrajs/core",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "Bun-native, contract-first HTTP framework
|
|
3
|
+
"version": "2.4.0",
|
|
4
|
+
"description": "Bun-native, contract-first HTTP framework - the router, server, and route descriptor.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
7
7
|
"typescript",
|
|
@@ -72,6 +72,11 @@
|
|
|
72
72
|
"types": "./dist/assurance.d.ts",
|
|
73
73
|
"default": "./dist/assurance.js"
|
|
74
74
|
},
|
|
75
|
+
"./binary": {
|
|
76
|
+
"bun": "./src/binary.ts",
|
|
77
|
+
"types": "./dist/binary.d.ts",
|
|
78
|
+
"default": "./dist/binary.js"
|
|
79
|
+
},
|
|
75
80
|
"./capabilities": {
|
|
76
81
|
"bun": "./src/capabilities.ts",
|
|
77
82
|
"types": "./dist/capabilities.d.ts",
|
|
@@ -201,6 +206,11 @@
|
|
|
201
206
|
"bun": "./src/server/webhook.ts",
|
|
202
207
|
"types": "./dist/server/webhook.d.ts",
|
|
203
208
|
"default": "./dist/server/webhook.js"
|
|
209
|
+
},
|
|
210
|
+
"./response-contract": {
|
|
211
|
+
"bun": "./src/server/response-contract-lane.ts",
|
|
212
|
+
"types": "./dist/server/response-contract-lane.d.ts",
|
|
213
|
+
"default": "./dist/server/response-contract-lane.js"
|
|
204
214
|
}
|
|
205
215
|
},
|
|
206
216
|
"files": [
|
package/src/assurance.ts
CHANGED
|
@@ -4,8 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
+
type CapabilityAccess,
|
|
7
8
|
type CapabilityAssuranceReport,
|
|
9
|
+
type CapabilityDefinition,
|
|
8
10
|
type CapabilityPolicy,
|
|
11
|
+
type CapabilityZone,
|
|
9
12
|
defineCapabilityPolicy,
|
|
10
13
|
} from "./capabilities.ts"
|
|
11
14
|
import type {
|
|
@@ -40,6 +43,62 @@ export interface AssuranceRouteSelector {
|
|
|
40
43
|
readonly paths?: readonly string[]
|
|
41
44
|
/** Restrict the rule to MCP tool routes (`true`) or non-tool routes (`false`). */
|
|
42
45
|
readonly tools?: boolean
|
|
46
|
+
/**
|
|
47
|
+
* Match routes declaring ANY of these capability tokens.
|
|
48
|
+
*
|
|
49
|
+
* Lets a policy be written about what a route DOES rather than where it lives: "anything that writes
|
|
50
|
+
* to the database must be authenticated" survives a route being moved or renamed, which a path glob
|
|
51
|
+
* does not. Reflection already carries the declared tokens, so this reads what the route said about
|
|
52
|
+
* itself.
|
|
53
|
+
*
|
|
54
|
+
* Naming exact tokens is precise but closed: a rule listing `db.write` does not cover `storage.write`,
|
|
55
|
+
* and a capability added next year escapes it in silence. Prefer `access`/`zone` for a rule that is
|
|
56
|
+
* meant to hold for a CLASS of effect.
|
|
57
|
+
*/
|
|
58
|
+
readonly capabilities?: readonly string[]
|
|
59
|
+
/**
|
|
60
|
+
* Match routes declaring any capability whose definition has this access.
|
|
61
|
+
*
|
|
62
|
+
* This is the selector to reach for when the rule is "anything that writes must prove who asked":
|
|
63
|
+
* it is keyed on what the capability IS rather than what it is called, so a token introduced later
|
|
64
|
+
* is covered the day it is declared instead of the day someone remembers to widen the rule.
|
|
65
|
+
*
|
|
66
|
+
* Requires capability definitions. A policy using it without them is refused rather than quietly
|
|
67
|
+
* matching nothing - a selector that matches nothing lets the route fall through to a laxer rule.
|
|
68
|
+
*/
|
|
69
|
+
readonly access?: CapabilityAccess
|
|
70
|
+
/**
|
|
71
|
+
* Match routes declaring any capability in this zone. Combined with `access`, both must hold for the
|
|
72
|
+
* SAME capability, so `{ access: "write", zone: "domain" }` is "writes business state" and does not
|
|
73
|
+
* match a route that only writes an audit log.
|
|
74
|
+
*/
|
|
75
|
+
readonly zone?: CapabilityZone
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Extra inputs an assurance evaluation needs beyond the routes themselves. */
|
|
79
|
+
export interface AssuranceEvaluationOptions {
|
|
80
|
+
/**
|
|
81
|
+
* Capability definitions, required by any rule selecting on `access`/`zone`. Normally
|
|
82
|
+
* `config.capabilities.definitions`.
|
|
83
|
+
*/
|
|
84
|
+
readonly definitions?: readonly CapabilityDefinition[]
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Selector keys that cannot be resolved from reflection alone. */
|
|
88
|
+
const CLASS_SELECTOR_KEYS = ["access", "zone"] as const
|
|
89
|
+
|
|
90
|
+
const usesClassSelector = (selector: AssuranceRouteSelector): boolean =>
|
|
91
|
+
selector.access !== undefined || selector.zone !== undefined
|
|
92
|
+
|
|
93
|
+
/** The rules whose selector needs capability definitions to mean anything. */
|
|
94
|
+
function rulesNeedingDefinitions(policy: AssurancePolicy): readonly string[] {
|
|
95
|
+
return policy.rules.filter((rule) => usesClassSelector(rule.match)).map((rule) => rule.name)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function definitionMap(
|
|
99
|
+
definitions: readonly CapabilityDefinition[] | undefined,
|
|
100
|
+
): ReadonlyMap<string, CapabilityDefinition> {
|
|
101
|
+
return new Map((definitions ?? []).map((definition) => [definition.id, definition]))
|
|
43
102
|
}
|
|
44
103
|
|
|
45
104
|
export interface AssuranceRule {
|
|
@@ -166,6 +225,19 @@ export function defineAssurancePolicy(policy: AssurancePolicy): AssurancePolicy
|
|
|
166
225
|
if (names.has(name))
|
|
167
226
|
throw new Error(`route assurance: duplicate rule name ${JSON.stringify(name)}`)
|
|
168
227
|
names.add(name)
|
|
228
|
+
// The selector is rebuilt from known keys below, so an unrecognised one would be dropped in
|
|
229
|
+
// silence - and a selector that loses its only constraint matches EVERY route, making the rule
|
|
230
|
+
// swallow everything after it. A misspelled key is a policy hole, so it is refused here.
|
|
231
|
+
const unknown = Object.keys(rule.match).filter(
|
|
232
|
+
(key) => !["methods", "paths", "tools", "capabilities", ...CLASS_SELECTOR_KEYS].includes(key),
|
|
233
|
+
)
|
|
234
|
+
if (unknown.length > 0) {
|
|
235
|
+
throw new Error(
|
|
236
|
+
`route assurance: rule ${JSON.stringify(rule.name)} has unknown selector key(s) ${unknown
|
|
237
|
+
.map((key) => JSON.stringify(key))
|
|
238
|
+
.join(", ")} - a dropped selector would match every route`,
|
|
239
|
+
)
|
|
240
|
+
}
|
|
169
241
|
if (rule.match.tools !== undefined && typeof rule.match.tools !== "boolean") {
|
|
170
242
|
throw new Error(
|
|
171
243
|
`route assurance: rule ${JSON.stringify(name)} tools selector must be boolean`,
|
|
@@ -181,6 +253,24 @@ export function defineAssurancePolicy(policy: AssurancePolicy): AssurancePolicy
|
|
|
181
253
|
routeGlob(path)
|
|
182
254
|
return path
|
|
183
255
|
})
|
|
256
|
+
const capabilities = rule.match.capabilities
|
|
257
|
+
if (capabilities !== undefined && (!Array.isArray(capabilities) || capabilities.length === 0)) {
|
|
258
|
+
throw new Error(
|
|
259
|
+
`route assurance: rule ${JSON.stringify(name)} capabilities selector must be a non-empty array`,
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
const access = rule.match.access
|
|
263
|
+
if (access !== undefined && access !== "read" && access !== "write") {
|
|
264
|
+
throw new Error(
|
|
265
|
+
`route assurance: rule ${JSON.stringify(name)} access selector must be "read" or "write"`,
|
|
266
|
+
)
|
|
267
|
+
}
|
|
268
|
+
const zone = rule.match.zone
|
|
269
|
+
if (zone !== undefined && zone !== "domain" && zone !== "operational") {
|
|
270
|
+
throw new Error(
|
|
271
|
+
`route assurance: rule ${JSON.stringify(name)} zone selector must be "domain" or "operational"`,
|
|
272
|
+
)
|
|
273
|
+
}
|
|
184
274
|
const required = normalizeEvidenceIds(rule.require, "required")
|
|
185
275
|
const forbidden = normalizeEvidenceIds(rule.forbid, "forbidden")
|
|
186
276
|
const overlap = required.find((id) => forbidden.includes(id))
|
|
@@ -195,6 +285,9 @@ export function defineAssurancePolicy(policy: AssurancePolicy): AssurancePolicy
|
|
|
195
285
|
...(methods !== undefined ? { methods: Object.freeze(methods as Method[]) } : {}),
|
|
196
286
|
...(paths !== undefined ? { paths: Object.freeze(paths) } : {}),
|
|
197
287
|
...(rule.match.tools !== undefined ? { tools: rule.match.tools } : {}),
|
|
288
|
+
...(capabilities !== undefined ? { capabilities: Object.freeze([...capabilities]) } : {}),
|
|
289
|
+
...(access !== undefined ? { access } : {}),
|
|
290
|
+
...(zone !== undefined ? { zone } : {}),
|
|
198
291
|
}),
|
|
199
292
|
require: required,
|
|
200
293
|
forbid: forbidden,
|
|
@@ -219,12 +312,27 @@ export function defineAssuranceConfig(config: AssuranceConfig): AssuranceConfig
|
|
|
219
312
|
if (config.invariants !== undefined && typeof config.invariants.executor !== "function") {
|
|
220
313
|
throw new Error("route assurance: invariant executor must be a function")
|
|
221
314
|
}
|
|
315
|
+
const policy = defineAssurancePolicy(config.policy)
|
|
316
|
+
const capabilities =
|
|
317
|
+
config.capabilities !== undefined ? defineCapabilityPolicy(config.capabilities) : undefined
|
|
318
|
+
// An `access`/`zone` selector is resolved through the capability definitions. Without them it can
|
|
319
|
+
// only ever match nothing, and a rule that matches nothing does not fail - the route falls past it
|
|
320
|
+
// to whatever laxer rule comes next. Refuse the config here rather than ship a policy whose
|
|
321
|
+
// strictest rule is inert.
|
|
322
|
+
const needDefinitions = rulesNeedingDefinitions(policy)
|
|
323
|
+
if (needDefinitions.length > 0 && (capabilities?.definitions.length ?? 0) === 0) {
|
|
324
|
+
throw new Error(
|
|
325
|
+
`route assurance: rule(s) ${needDefinitions
|
|
326
|
+
.map((name) => JSON.stringify(name))
|
|
327
|
+
.join(
|
|
328
|
+
", ",
|
|
329
|
+
)} select on ${CLASS_SELECTOR_KEYS.join("/")}, which needs capability definitions - add a \`capabilities\` policy defining the tokens your routes declare`,
|
|
330
|
+
)
|
|
331
|
+
}
|
|
222
332
|
return Object.freeze({
|
|
223
333
|
source: config.source,
|
|
224
|
-
policy
|
|
225
|
-
...(
|
|
226
|
-
? { capabilities: defineCapabilityPolicy(config.capabilities) }
|
|
227
|
-
: {}),
|
|
334
|
+
policy,
|
|
335
|
+
...(capabilities !== undefined ? { capabilities } : {}),
|
|
228
336
|
...(config.manifest !== undefined
|
|
229
337
|
? {
|
|
230
338
|
manifest: Object.freeze({
|
|
@@ -239,16 +347,38 @@ export function defineAssuranceConfig(config: AssuranceConfig): AssuranceConfig
|
|
|
239
347
|
})
|
|
240
348
|
}
|
|
241
349
|
|
|
242
|
-
/**
|
|
350
|
+
/**
|
|
351
|
+
* Shared selector semantics for policy rules and framework adapters.
|
|
352
|
+
*
|
|
353
|
+
* `definitions` is only consulted by the `access`/`zone` selectors; every other selector reads
|
|
354
|
+
* reflection alone. A caller that omits it while the selector needs it gets no match, so callers that
|
|
355
|
+
* accept user policy must reject that combination up front - `defineAssuranceConfig` does.
|
|
356
|
+
*/
|
|
243
357
|
export function matchesAssuranceSelector(
|
|
244
|
-
route: Pick<ReflectedRoute, "method" | "path" | "tool">,
|
|
358
|
+
route: Pick<ReflectedRoute, "method" | "path" | "tool" | "capabilities">,
|
|
245
359
|
selector: AssuranceRouteSelector,
|
|
360
|
+
definitions?: ReadonlyMap<string, CapabilityDefinition>,
|
|
246
361
|
): boolean {
|
|
247
|
-
const { methods, paths, tools } = selector
|
|
362
|
+
const { methods, paths, tools, capabilities, access, zone } = selector
|
|
248
363
|
if (methods !== undefined && !methods.includes(route.method as Method)) return false
|
|
249
364
|
if (paths !== undefined && !paths.some((pattern) => routeGlob(pattern).test(route.path)))
|
|
250
365
|
return false
|
|
251
366
|
if (tools !== undefined && (route.tool !== undefined) !== tools) return false
|
|
367
|
+
const declared = route.capabilities ?? []
|
|
368
|
+
if (capabilities !== undefined && !capabilities.some((token) => declared.includes(token)))
|
|
369
|
+
return false
|
|
370
|
+
if (access !== undefined || zone !== undefined) {
|
|
371
|
+
// Both constraints must hold for the SAME capability: a route that reads the database and writes
|
|
372
|
+
// an audit log must not satisfy "writes business state" by combining halves of two tokens.
|
|
373
|
+
const matched = declared.some((token) => {
|
|
374
|
+
const definition = definitions?.get(token)
|
|
375
|
+
if (definition === undefined) return false
|
|
376
|
+
if (access !== undefined && definition.access !== access) return false
|
|
377
|
+
if (zone !== undefined && definition.zone !== zone) return false
|
|
378
|
+
return true
|
|
379
|
+
})
|
|
380
|
+
if (!matched) return false
|
|
381
|
+
}
|
|
252
382
|
return true
|
|
253
383
|
}
|
|
254
384
|
|
|
@@ -256,8 +386,22 @@ export function matchesAssuranceSelector(
|
|
|
256
386
|
export function evaluateRouteAssurance(
|
|
257
387
|
source: unknown,
|
|
258
388
|
policyInput: AssurancePolicy,
|
|
389
|
+
options?: AssuranceEvaluationOptions,
|
|
259
390
|
): AssuranceReport {
|
|
260
391
|
const policy = defineAssurancePolicy(policyInput)
|
|
392
|
+
const definitions = definitionMap(options?.definitions)
|
|
393
|
+
// Same reasoning as `defineAssuranceConfig`, repeated for callers that evaluate a bare policy: a
|
|
394
|
+
// class selector with nothing to resolve against is an inert rule, not a lenient one.
|
|
395
|
+
const needDefinitions = rulesNeedingDefinitions(policy)
|
|
396
|
+
if (needDefinitions.length > 0 && definitions.size === 0) {
|
|
397
|
+
throw new Error(
|
|
398
|
+
`route assurance: rule(s) ${needDefinitions
|
|
399
|
+
.map((name) => JSON.stringify(name))
|
|
400
|
+
.join(
|
|
401
|
+
", ",
|
|
402
|
+
)} select on ${CLASS_SELECTOR_KEYS.join("/")} but no capability definitions were supplied`,
|
|
403
|
+
)
|
|
404
|
+
}
|
|
261
405
|
const findings: AssuranceFinding[] = []
|
|
262
406
|
const routes: AssuredRoute[] = []
|
|
263
407
|
const reflected = reflectRoutes(source)
|
|
@@ -272,7 +416,9 @@ export function evaluateRouteAssurance(
|
|
|
272
416
|
}
|
|
273
417
|
|
|
274
418
|
for (const route of reflected) {
|
|
275
|
-
const rule = policy.rules.find((candidate) =>
|
|
419
|
+
const rule = policy.rules.find((candidate) =>
|
|
420
|
+
matchesAssuranceSelector(route, candidate.match, definitions),
|
|
421
|
+
)
|
|
276
422
|
const evidence = route.assurance ?? []
|
|
277
423
|
const evidenceIds = new Set(evidence.map((item) => item.id))
|
|
278
424
|
if (rule === undefined) {
|