@kya-os/checkpoint-nextjs 1.0.0 → 1.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/CHANGELOG.md +165 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapt.js +0 -2
- package/dist/adapt.mjs +0 -2
- package/dist/api-client.js +38 -24
- package/dist/api-client.mjs +38 -24
- package/dist/api-middleware.js +48 -28
- package/dist/api-middleware.mjs +48 -28
- package/dist/create-middleware.d.mts +1 -1
- package/dist/create-middleware.d.ts +1 -1
- package/dist/create-middleware.js +0 -2
- package/dist/create-middleware.mjs +0 -2
- package/dist/edge/index.d.mts +1 -1
- package/dist/edge/index.d.ts +1 -1
- package/dist/edge/index.js +4 -6
- package/dist/edge/index.mjs +4 -6
- package/dist/edge-runtime-loader.js +7 -2
- package/dist/edge-runtime-loader.mjs +7 -2
- package/dist/edge-wasm-middleware.js +0 -2
- package/dist/edge-wasm-middleware.mjs +0 -2
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +77 -42
- package/dist/index.mjs +77 -42
- package/dist/middleware-edge.js +17 -10
- package/dist/middleware-edge.mjs +17 -10
- package/dist/middleware-node.d.mts +36 -0
- package/dist/middleware-node.d.ts +36 -0
- package/dist/middleware-node.js +17 -10
- package/dist/middleware-node.mjs +17 -10
- package/dist/middleware.d.mts +1 -1
- package/dist/middleware.d.ts +1 -1
- package/dist/middleware.js +0 -2
- package/dist/middleware.mjs +0 -2
- package/dist/nodejs-wasm-loader.js +0 -2
- package/dist/nodejs-wasm-loader.mjs +0 -2
- package/dist/policy.js +10 -6
- package/dist/policy.mjs +10 -6
- package/dist/session-tracker.js +1 -3
- package/dist/session-tracker.mjs +1 -3
- package/dist/signature-verifier.js +0 -2
- package/dist/signature-verifier.mjs +0 -2
- package/dist/translate.d.mts +36 -9
- package/dist/translate.d.ts +36 -9
- package/dist/translate.js +13 -8
- package/dist/translate.mjs +13 -8
- package/dist/{types-C-xCUNTr.d.mts → types-D9RQvPNy.d.mts} +1 -1
- package/dist/{types-C-xCUNTr.d.ts → types-D9RQvPNy.d.ts} +1 -1
- package/dist/wasm-middleware.d.mts +29 -10
- package/dist/wasm-middleware.d.ts +29 -10
- package/dist/wasm-middleware.js +0 -2
- package/dist/wasm-middleware.mjs +0 -2
- package/dist/wasm-setup.js +0 -2
- package/dist/wasm-setup.mjs +0 -2
- package/package.json +3 -3
- package/dist/adapt.js.map +0 -1
- package/dist/adapt.mjs.map +0 -1
- package/dist/api-client.js.map +0 -1
- package/dist/api-client.mjs.map +0 -1
- package/dist/api-middleware.js.map +0 -1
- package/dist/api-middleware.mjs.map +0 -1
- package/dist/create-middleware.js.map +0 -1
- package/dist/create-middleware.mjs.map +0 -1
- package/dist/edge/index.js.map +0 -1
- package/dist/edge/index.mjs.map +0 -1
- package/dist/edge-runtime-loader.js.map +0 -1
- package/dist/edge-runtime-loader.mjs.map +0 -1
- package/dist/edge-wasm-middleware.js.map +0 -1
- package/dist/edge-wasm-middleware.mjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/middleware-edge.js.map +0 -1
- package/dist/middleware-edge.mjs.map +0 -1
- package/dist/middleware-node.js.map +0 -1
- package/dist/middleware-node.mjs.map +0 -1
- package/dist/middleware.js.map +0 -1
- package/dist/middleware.mjs.map +0 -1
- package/dist/nodejs-wasm-loader.js.map +0 -1
- package/dist/nodejs-wasm-loader.mjs.map +0 -1
- package/dist/policy.js.map +0 -1
- package/dist/policy.mjs.map +0 -1
- package/dist/session-tracker.js.map +0 -1
- package/dist/session-tracker.mjs.map +0 -1
- package/dist/signature-verifier.js.map +0 -1
- package/dist/signature-verifier.mjs.map +0 -1
- package/dist/translate.js.map +0 -1
- package/dist/translate.mjs.map +0 -1
- package/dist/wasm-middleware.js.map +0 -1
- package/dist/wasm-middleware.mjs.map +0 -1
- package/dist/wasm-setup.js.map +0 -1
- package/dist/wasm-setup.mjs.map +0 -1
package/dist/middleware-edge.js
CHANGED
|
@@ -57,21 +57,28 @@ function applyHeaders(res, headers) {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
// src/translate.ts
|
|
60
|
-
function nextRequestToHttpLike(req) {
|
|
60
|
+
async function nextRequestToHttpLike(req, opts = {}) {
|
|
61
61
|
const url = new URL(req.url);
|
|
62
|
+
const body = await tryDrainJsonBody(req, opts);
|
|
62
63
|
return {
|
|
63
64
|
method: req.method,
|
|
64
65
|
// Path + query only — orchestrator's URL parsing expects no scheme/host.
|
|
65
66
|
url: url.pathname + url.search,
|
|
66
67
|
headers: headersToRecord(req.headers),
|
|
67
|
-
|
|
68
|
-
// The orchestrator routes to PlainHttp when body is falsy, which
|
|
69
|
-
// is the right call for streaming middlewares that don't want to
|
|
70
|
-
// buffer the request body just to detect agents.
|
|
71
|
-
body: null,
|
|
68
|
+
body,
|
|
72
69
|
remoteAddress: extractRemoteAddress(req)
|
|
73
70
|
};
|
|
74
71
|
}
|
|
72
|
+
async function tryDrainJsonBody(req, opts) {
|
|
73
|
+
if (opts.drainJsonBody === false) return null;
|
|
74
|
+
const contentType = req.headers.get("content-type") ?? "";
|
|
75
|
+
if (!contentType.toLowerCase().includes("application/json")) return null;
|
|
76
|
+
try {
|
|
77
|
+
return await req.clone().text();
|
|
78
|
+
} catch {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
75
82
|
function headersToRecord(headers) {
|
|
76
83
|
const out = {};
|
|
77
84
|
headers.forEach((value, key) => {
|
|
@@ -101,7 +108,8 @@ function buildVerifyOpts(config) {
|
|
|
101
108
|
tenantHost: config.tenantHost,
|
|
102
109
|
enforcementMode: config.enforcementMode ?? "enforce",
|
|
103
110
|
reputationBaseline: config.reputationBaseline,
|
|
104
|
-
argusUrl: config.argusUrl
|
|
111
|
+
argusUrl: config.argusUrl,
|
|
112
|
+
legacyEnvelopeFallback: config.legacyEnvelopeFallback ?? false
|
|
105
113
|
};
|
|
106
114
|
}
|
|
107
115
|
|
|
@@ -109,8 +117,9 @@ function buildVerifyOpts(config) {
|
|
|
109
117
|
function withCheckpoint(config) {
|
|
110
118
|
void edge.initEngineEdge();
|
|
111
119
|
const opts = buildVerifyOpts(config);
|
|
120
|
+
const translateOpts = { drainJsonBody: config.drainJsonBody };
|
|
112
121
|
return async function checkpointMiddlewareEdge(req) {
|
|
113
|
-
const httpLike = nextRequestToHttpLike(req);
|
|
122
|
+
const httpLike = await nextRequestToHttpLike(req, translateOpts);
|
|
114
123
|
const result = await edge.verifyRequestEdge(httpLike, opts);
|
|
115
124
|
await dispatchOnResult(config, result, req);
|
|
116
125
|
const rendered = edge.renderDecisionAsResponse(result);
|
|
@@ -130,5 +139,3 @@ Object.defineProperty(exports, "initEngineEdge", {
|
|
|
130
139
|
get: function () { return edge.initEngineEdge; }
|
|
131
140
|
});
|
|
132
141
|
exports.withCheckpoint = withCheckpoint;
|
|
133
|
-
//# sourceMappingURL=middleware-edge.js.map
|
|
134
|
-
//# sourceMappingURL=middleware-edge.js.map
|
package/dist/middleware-edge.mjs
CHANGED
|
@@ -56,21 +56,28 @@ function applyHeaders(res, headers) {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// src/translate.ts
|
|
59
|
-
function nextRequestToHttpLike(req) {
|
|
59
|
+
async function nextRequestToHttpLike(req, opts = {}) {
|
|
60
60
|
const url = new URL(req.url);
|
|
61
|
+
const body = await tryDrainJsonBody(req, opts);
|
|
61
62
|
return {
|
|
62
63
|
method: req.method,
|
|
63
64
|
// Path + query only — orchestrator's URL parsing expects no scheme/host.
|
|
64
65
|
url: url.pathname + url.search,
|
|
65
66
|
headers: headersToRecord(req.headers),
|
|
66
|
-
|
|
67
|
-
// The orchestrator routes to PlainHttp when body is falsy, which
|
|
68
|
-
// is the right call for streaming middlewares that don't want to
|
|
69
|
-
// buffer the request body just to detect agents.
|
|
70
|
-
body: null,
|
|
67
|
+
body,
|
|
71
68
|
remoteAddress: extractRemoteAddress(req)
|
|
72
69
|
};
|
|
73
70
|
}
|
|
71
|
+
async function tryDrainJsonBody(req, opts) {
|
|
72
|
+
if (opts.drainJsonBody === false) return null;
|
|
73
|
+
const contentType = req.headers.get("content-type") ?? "";
|
|
74
|
+
if (!contentType.toLowerCase().includes("application/json")) return null;
|
|
75
|
+
try {
|
|
76
|
+
return await req.clone().text();
|
|
77
|
+
} catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
74
81
|
function headersToRecord(headers) {
|
|
75
82
|
const out = {};
|
|
76
83
|
headers.forEach((value, key) => {
|
|
@@ -100,7 +107,8 @@ function buildVerifyOpts(config) {
|
|
|
100
107
|
tenantHost: config.tenantHost,
|
|
101
108
|
enforcementMode: config.enforcementMode ?? "enforce",
|
|
102
109
|
reputationBaseline: config.reputationBaseline,
|
|
103
|
-
argusUrl: config.argusUrl
|
|
110
|
+
argusUrl: config.argusUrl,
|
|
111
|
+
legacyEnvelopeFallback: config.legacyEnvelopeFallback ?? false
|
|
104
112
|
};
|
|
105
113
|
}
|
|
106
114
|
|
|
@@ -108,8 +116,9 @@ function buildVerifyOpts(config) {
|
|
|
108
116
|
function withCheckpoint(config) {
|
|
109
117
|
void initEngineEdge();
|
|
110
118
|
const opts = buildVerifyOpts(config);
|
|
119
|
+
const translateOpts = { drainJsonBody: config.drainJsonBody };
|
|
111
120
|
return async function checkpointMiddlewareEdge(req) {
|
|
112
|
-
const httpLike = nextRequestToHttpLike(req);
|
|
121
|
+
const httpLike = await nextRequestToHttpLike(req, translateOpts);
|
|
113
122
|
const result = await verifyRequestEdge(httpLike, opts);
|
|
114
123
|
await dispatchOnResult(config, result, req);
|
|
115
124
|
const rendered = renderDecisionAsResponse(result);
|
|
@@ -125,5 +134,3 @@ async function dispatchOnResult(config, result, req) {
|
|
|
125
134
|
}
|
|
126
135
|
|
|
127
136
|
export { withCheckpoint };
|
|
128
|
-
//# sourceMappingURL=middleware-edge.mjs.map
|
|
129
|
-
//# sourceMappingURL=middleware-edge.mjs.map
|
|
@@ -58,6 +58,41 @@ interface CheckpointConfig {
|
|
|
58
58
|
* response.
|
|
59
59
|
*/
|
|
60
60
|
onResult?: (result: VerifyResult, req: NextRequest) => void | Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Accept legacy `KYA-Delegation`-header envelope form alongside the
|
|
63
|
+
* canonical `_meta.proof.jws` body form. Default `false`.
|
|
64
|
+
*
|
|
65
|
+
* **When to enable** — customers whose agents pre-date Envelope-1
|
|
66
|
+
* (#2537) and ship MCP-I proofs as `{protected,payload,signature}`
|
|
67
|
+
* JSON in a `KYA-Delegation` HTTP header. Post-Envelope-1 agents
|
|
68
|
+
* ship compact JWS in the request body's `_meta.proof.jws` field;
|
|
69
|
+
* those don't need this flag.
|
|
70
|
+
*
|
|
71
|
+
* Forwarded to the orchestrator's `VerifyRequestOpts.legacyEnvelopeFallback`.
|
|
72
|
+
* Both transports (header + body) are honored when this is `true`;
|
|
73
|
+
* the orchestrator's detection order is body first, then header
|
|
74
|
+
* (`packages/checkpoint-wasm-runtime/src/engine/orchestrator/build-agent-request.ts`).
|
|
75
|
+
*
|
|
76
|
+
* SDK-Envelope-Plumbing-1 (#2594). Added in `@kya-os/checkpoint-nextjs@1.1.0`.
|
|
77
|
+
*/
|
|
78
|
+
legacyEnvelopeFallback?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Read the request body when `content-type` is `application/json` so
|
|
81
|
+
* the orchestrator can extract an MCP-I envelope from
|
|
82
|
+
* `_meta.proof.jws`. Default `true`.
|
|
83
|
+
*
|
|
84
|
+
* **When to disable** — streaming middlewares that can't tolerate
|
|
85
|
+
* the `req.clone()` memory overhead (one full-body copy is buffered
|
|
86
|
+
* during the read). For those, set `false` and route MCP-I
|
|
87
|
+
* envelopes through the `KYA-Delegation` header transport instead
|
|
88
|
+
* (requires `legacyEnvelopeFallback: true`).
|
|
89
|
+
*
|
|
90
|
+
* The clone preserves `req.body` for downstream handlers — disabling
|
|
91
|
+
* is a performance optimization, not a correctness fix.
|
|
92
|
+
*
|
|
93
|
+
* SDK-Envelope-Plumbing-1 (#2594). Added in `@kya-os/checkpoint-nextjs@1.1.0`.
|
|
94
|
+
*/
|
|
95
|
+
drainJsonBody?: boolean;
|
|
61
96
|
}
|
|
62
97
|
/**
|
|
63
98
|
* Build the Checkpoint middleware. Returns a function `(req) => NextResponse`
|
|
@@ -84,6 +119,7 @@ declare function buildVerifyOpts(config: CheckpointConfig): {
|
|
|
84
119
|
enforcementMode: EnforcementMode;
|
|
85
120
|
reputationBaseline: number | undefined;
|
|
86
121
|
argusUrl: string | undefined;
|
|
122
|
+
legacyEnvelopeFallback: boolean;
|
|
87
123
|
};
|
|
88
124
|
|
|
89
125
|
export { type CheckpointConfig, buildVerifyOpts as _buildVerifyOpts, withCheckpoint };
|
|
@@ -58,6 +58,41 @@ interface CheckpointConfig {
|
|
|
58
58
|
* response.
|
|
59
59
|
*/
|
|
60
60
|
onResult?: (result: VerifyResult, req: NextRequest) => void | Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Accept legacy `KYA-Delegation`-header envelope form alongside the
|
|
63
|
+
* canonical `_meta.proof.jws` body form. Default `false`.
|
|
64
|
+
*
|
|
65
|
+
* **When to enable** — customers whose agents pre-date Envelope-1
|
|
66
|
+
* (#2537) and ship MCP-I proofs as `{protected,payload,signature}`
|
|
67
|
+
* JSON in a `KYA-Delegation` HTTP header. Post-Envelope-1 agents
|
|
68
|
+
* ship compact JWS in the request body's `_meta.proof.jws` field;
|
|
69
|
+
* those don't need this flag.
|
|
70
|
+
*
|
|
71
|
+
* Forwarded to the orchestrator's `VerifyRequestOpts.legacyEnvelopeFallback`.
|
|
72
|
+
* Both transports (header + body) are honored when this is `true`;
|
|
73
|
+
* the orchestrator's detection order is body first, then header
|
|
74
|
+
* (`packages/checkpoint-wasm-runtime/src/engine/orchestrator/build-agent-request.ts`).
|
|
75
|
+
*
|
|
76
|
+
* SDK-Envelope-Plumbing-1 (#2594). Added in `@kya-os/checkpoint-nextjs@1.1.0`.
|
|
77
|
+
*/
|
|
78
|
+
legacyEnvelopeFallback?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Read the request body when `content-type` is `application/json` so
|
|
81
|
+
* the orchestrator can extract an MCP-I envelope from
|
|
82
|
+
* `_meta.proof.jws`. Default `true`.
|
|
83
|
+
*
|
|
84
|
+
* **When to disable** — streaming middlewares that can't tolerate
|
|
85
|
+
* the `req.clone()` memory overhead (one full-body copy is buffered
|
|
86
|
+
* during the read). For those, set `false` and route MCP-I
|
|
87
|
+
* envelopes through the `KYA-Delegation` header transport instead
|
|
88
|
+
* (requires `legacyEnvelopeFallback: true`).
|
|
89
|
+
*
|
|
90
|
+
* The clone preserves `req.body` for downstream handlers — disabling
|
|
91
|
+
* is a performance optimization, not a correctness fix.
|
|
92
|
+
*
|
|
93
|
+
* SDK-Envelope-Plumbing-1 (#2594). Added in `@kya-os/checkpoint-nextjs@1.1.0`.
|
|
94
|
+
*/
|
|
95
|
+
drainJsonBody?: boolean;
|
|
61
96
|
}
|
|
62
97
|
/**
|
|
63
98
|
* Build the Checkpoint middleware. Returns a function `(req) => NextResponse`
|
|
@@ -84,6 +119,7 @@ declare function buildVerifyOpts(config: CheckpointConfig): {
|
|
|
84
119
|
enforcementMode: EnforcementMode;
|
|
85
120
|
reputationBaseline: number | undefined;
|
|
86
121
|
argusUrl: string | undefined;
|
|
122
|
+
legacyEnvelopeFallback: boolean;
|
|
87
123
|
};
|
|
88
124
|
|
|
89
125
|
export { type CheckpointConfig, buildVerifyOpts as _buildVerifyOpts, withCheckpoint };
|
package/dist/middleware-node.js
CHANGED
|
@@ -56,21 +56,28 @@ function applyHeaders(res, headers) {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// src/translate.ts
|
|
59
|
-
function nextRequestToHttpLike(req) {
|
|
59
|
+
async function nextRequestToHttpLike(req, opts = {}) {
|
|
60
60
|
const url = new URL(req.url);
|
|
61
|
+
const body = await tryDrainJsonBody(req, opts);
|
|
61
62
|
return {
|
|
62
63
|
method: req.method,
|
|
63
64
|
// Path + query only — orchestrator's URL parsing expects no scheme/host.
|
|
64
65
|
url: url.pathname + url.search,
|
|
65
66
|
headers: headersToRecord(req.headers),
|
|
66
|
-
|
|
67
|
-
// The orchestrator routes to PlainHttp when body is falsy, which
|
|
68
|
-
// is the right call for streaming middlewares that don't want to
|
|
69
|
-
// buffer the request body just to detect agents.
|
|
70
|
-
body: null,
|
|
67
|
+
body,
|
|
71
68
|
remoteAddress: extractRemoteAddress(req)
|
|
72
69
|
};
|
|
73
70
|
}
|
|
71
|
+
async function tryDrainJsonBody(req, opts) {
|
|
72
|
+
if (opts.drainJsonBody === false) return null;
|
|
73
|
+
const contentType = req.headers.get("content-type") ?? "";
|
|
74
|
+
if (!contentType.toLowerCase().includes("application/json")) return null;
|
|
75
|
+
try {
|
|
76
|
+
return await req.clone().text();
|
|
77
|
+
} catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
74
81
|
function headersToRecord(headers) {
|
|
75
82
|
const out = {};
|
|
76
83
|
headers.forEach((value, key) => {
|
|
@@ -91,8 +98,9 @@ function extractRemoteAddress(req) {
|
|
|
91
98
|
// src/middleware-node.ts
|
|
92
99
|
function withCheckpoint(config) {
|
|
93
100
|
const opts = buildVerifyOpts(config);
|
|
101
|
+
const translateOpts = { drainJsonBody: config.drainJsonBody };
|
|
94
102
|
return async function checkpointMiddleware(req) {
|
|
95
|
-
const httpLike = nextRequestToHttpLike(req);
|
|
103
|
+
const httpLike = await nextRequestToHttpLike(req, translateOpts);
|
|
96
104
|
const result = await orchestrator.verifyRequest(httpLike, opts);
|
|
97
105
|
await dispatchOnResult(config, result, req);
|
|
98
106
|
const rendered = orchestrator.renderDecisionAsResponse(result);
|
|
@@ -110,7 +118,8 @@ function buildVerifyOpts(config) {
|
|
|
110
118
|
tenantHost: config.tenantHost,
|
|
111
119
|
enforcementMode: config.enforcementMode ?? "enforce",
|
|
112
120
|
reputationBaseline: config.reputationBaseline,
|
|
113
|
-
argusUrl: config.argusUrl
|
|
121
|
+
argusUrl: config.argusUrl,
|
|
122
|
+
legacyEnvelopeFallback: config.legacyEnvelopeFallback ?? false
|
|
114
123
|
};
|
|
115
124
|
}
|
|
116
125
|
async function dispatchOnResult(config, result, req) {
|
|
@@ -123,5 +132,3 @@ async function dispatchOnResult(config, result, req) {
|
|
|
123
132
|
|
|
124
133
|
exports._buildVerifyOpts = buildVerifyOpts;
|
|
125
134
|
exports.withCheckpoint = withCheckpoint;
|
|
126
|
-
//# sourceMappingURL=middleware-node.js.map
|
|
127
|
-
//# sourceMappingURL=middleware-node.js.map
|
package/dist/middleware-node.mjs
CHANGED
|
@@ -54,21 +54,28 @@ function applyHeaders(res, headers) {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
// src/translate.ts
|
|
57
|
-
function nextRequestToHttpLike(req) {
|
|
57
|
+
async function nextRequestToHttpLike(req, opts = {}) {
|
|
58
58
|
const url = new URL(req.url);
|
|
59
|
+
const body = await tryDrainJsonBody(req, opts);
|
|
59
60
|
return {
|
|
60
61
|
method: req.method,
|
|
61
62
|
// Path + query only — orchestrator's URL parsing expects no scheme/host.
|
|
62
63
|
url: url.pathname + url.search,
|
|
63
64
|
headers: headersToRecord(req.headers),
|
|
64
|
-
|
|
65
|
-
// The orchestrator routes to PlainHttp when body is falsy, which
|
|
66
|
-
// is the right call for streaming middlewares that don't want to
|
|
67
|
-
// buffer the request body just to detect agents.
|
|
68
|
-
body: null,
|
|
65
|
+
body,
|
|
69
66
|
remoteAddress: extractRemoteAddress(req)
|
|
70
67
|
};
|
|
71
68
|
}
|
|
69
|
+
async function tryDrainJsonBody(req, opts) {
|
|
70
|
+
if (opts.drainJsonBody === false) return null;
|
|
71
|
+
const contentType = req.headers.get("content-type") ?? "";
|
|
72
|
+
if (!contentType.toLowerCase().includes("application/json")) return null;
|
|
73
|
+
try {
|
|
74
|
+
return await req.clone().text();
|
|
75
|
+
} catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
72
79
|
function headersToRecord(headers) {
|
|
73
80
|
const out = {};
|
|
74
81
|
headers.forEach((value, key) => {
|
|
@@ -89,8 +96,9 @@ function extractRemoteAddress(req) {
|
|
|
89
96
|
// src/middleware-node.ts
|
|
90
97
|
function withCheckpoint(config) {
|
|
91
98
|
const opts = buildVerifyOpts(config);
|
|
99
|
+
const translateOpts = { drainJsonBody: config.drainJsonBody };
|
|
92
100
|
return async function checkpointMiddleware(req) {
|
|
93
|
-
const httpLike = nextRequestToHttpLike(req);
|
|
101
|
+
const httpLike = await nextRequestToHttpLike(req, translateOpts);
|
|
94
102
|
const result = await verifyRequest(httpLike, opts);
|
|
95
103
|
await dispatchOnResult(config, result, req);
|
|
96
104
|
const rendered = renderDecisionAsResponse(result);
|
|
@@ -108,7 +116,8 @@ function buildVerifyOpts(config) {
|
|
|
108
116
|
tenantHost: config.tenantHost,
|
|
109
117
|
enforcementMode: config.enforcementMode ?? "enforce",
|
|
110
118
|
reputationBaseline: config.reputationBaseline,
|
|
111
|
-
argusUrl: config.argusUrl
|
|
119
|
+
argusUrl: config.argusUrl,
|
|
120
|
+
legacyEnvelopeFallback: config.legacyEnvelopeFallback ?? false
|
|
112
121
|
};
|
|
113
122
|
}
|
|
114
123
|
async function dispatchOnResult(config, result, req) {
|
|
@@ -120,5 +129,3 @@ async function dispatchOnResult(config, result, req) {
|
|
|
120
129
|
}
|
|
121
130
|
|
|
122
131
|
export { buildVerifyOpts as _buildVerifyOpts, withCheckpoint };
|
|
123
|
-
//# sourceMappingURL=middleware-node.mjs.map
|
|
124
|
-
//# sourceMappingURL=middleware-node.mjs.map
|
package/dist/middleware.d.mts
CHANGED
package/dist/middleware.d.ts
CHANGED
package/dist/middleware.js
CHANGED
package/dist/middleware.mjs
CHANGED
|
@@ -91,5 +91,3 @@ exports.getWasmModule = getWasmModule;
|
|
|
91
91
|
exports.isNodejsRuntime = isNodejsRuntime;
|
|
92
92
|
exports.isWasmInitialized = isWasmInitialized;
|
|
93
93
|
exports.loadWasmNodejs = loadWasmNodejs;
|
|
94
|
-
//# sourceMappingURL=nodejs-wasm-loader.js.map
|
|
95
|
-
//# sourceMappingURL=nodejs-wasm-loader.js.map
|
package/dist/policy.js
CHANGED
|
@@ -74,7 +74,7 @@ async function handlePolicyDecision(request, decision, config, detection) {
|
|
|
74
74
|
case checkpointShared.ENFORCEMENT_ACTIONS.CHALLENGE:
|
|
75
75
|
return buildChallengeResponse(request, decision, config, detection);
|
|
76
76
|
case checkpointShared.ENFORCEMENT_ACTIONS.LOG:
|
|
77
|
-
console.log("[
|
|
77
|
+
console.log("[Checkpoint] Policy decision (log):", {
|
|
78
78
|
path: request.nextUrl.pathname,
|
|
79
79
|
action: decision.action,
|
|
80
80
|
reason: decision.reason,
|
|
@@ -119,7 +119,7 @@ async function getPolicy(config) {
|
|
|
119
119
|
return await fetcher.getPolicy(config.fetchPolicy.projectId);
|
|
120
120
|
} catch (error) {
|
|
121
121
|
if (config.debug) {
|
|
122
|
-
console.warn("[
|
|
122
|
+
console.warn("[Checkpoint] Policy fetch failed, using fallback:", error);
|
|
123
123
|
}
|
|
124
124
|
return checkpointShared.PolicyConfigSchema.parse({
|
|
125
125
|
...checkpointShared.DEFAULT_POLICY,
|
|
@@ -144,12 +144,18 @@ async function applyPolicy(request, detection, config) {
|
|
|
144
144
|
const context = createContextFromDetection(detection, request);
|
|
145
145
|
const decision = checkpointShared.evaluatePolicy(policy, context);
|
|
146
146
|
if (config.onPolicyDecision) {
|
|
147
|
-
|
|
147
|
+
try {
|
|
148
|
+
await config.onPolicyDecision(request, decision, context);
|
|
149
|
+
} catch (error) {
|
|
150
|
+
if (config.debug) {
|
|
151
|
+
console.error("[Checkpoint] onPolicyDecision callback failed:", error);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
148
154
|
}
|
|
149
155
|
return await handlePolicyDecision(request, decision, config, detection);
|
|
150
156
|
} catch (error) {
|
|
151
157
|
if (config.debug) {
|
|
152
|
-
console.error("[
|
|
158
|
+
console.error("[Checkpoint] Policy evaluation error:", error);
|
|
153
159
|
}
|
|
154
160
|
if (config.failOpen !== false) {
|
|
155
161
|
return null;
|
|
@@ -185,5 +191,3 @@ exports.createContextFromDetection = createContextFromDetection;
|
|
|
185
191
|
exports.evaluatePolicyForDetection = evaluatePolicyForDetection;
|
|
186
192
|
exports.getPolicy = getPolicy;
|
|
187
193
|
exports.handlePolicyDecision = handlePolicyDecision;
|
|
188
|
-
//# sourceMappingURL=policy.js.map
|
|
189
|
-
//# sourceMappingURL=policy.js.map
|
package/dist/policy.mjs
CHANGED
|
@@ -73,7 +73,7 @@ async function handlePolicyDecision(request, decision, config, detection) {
|
|
|
73
73
|
case ENFORCEMENT_ACTIONS.CHALLENGE:
|
|
74
74
|
return buildChallengeResponse(request, decision, config, detection);
|
|
75
75
|
case ENFORCEMENT_ACTIONS.LOG:
|
|
76
|
-
console.log("[
|
|
76
|
+
console.log("[Checkpoint] Policy decision (log):", {
|
|
77
77
|
path: request.nextUrl.pathname,
|
|
78
78
|
action: decision.action,
|
|
79
79
|
reason: decision.reason,
|
|
@@ -118,7 +118,7 @@ async function getPolicy(config) {
|
|
|
118
118
|
return await fetcher.getPolicy(config.fetchPolicy.projectId);
|
|
119
119
|
} catch (error) {
|
|
120
120
|
if (config.debug) {
|
|
121
|
-
console.warn("[
|
|
121
|
+
console.warn("[Checkpoint] Policy fetch failed, using fallback:", error);
|
|
122
122
|
}
|
|
123
123
|
return PolicyConfigSchema.parse({
|
|
124
124
|
...DEFAULT_POLICY,
|
|
@@ -143,12 +143,18 @@ async function applyPolicy(request, detection, config) {
|
|
|
143
143
|
const context = createContextFromDetection(detection, request);
|
|
144
144
|
const decision = evaluatePolicy(policy, context);
|
|
145
145
|
if (config.onPolicyDecision) {
|
|
146
|
-
|
|
146
|
+
try {
|
|
147
|
+
await config.onPolicyDecision(request, decision, context);
|
|
148
|
+
} catch (error) {
|
|
149
|
+
if (config.debug) {
|
|
150
|
+
console.error("[Checkpoint] onPolicyDecision callback failed:", error);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
147
153
|
}
|
|
148
154
|
return await handlePolicyDecision(request, decision, config, detection);
|
|
149
155
|
} catch (error) {
|
|
150
156
|
if (config.debug) {
|
|
151
|
-
console.error("[
|
|
157
|
+
console.error("[Checkpoint] Policy evaluation error:", error);
|
|
152
158
|
}
|
|
153
159
|
if (config.failOpen !== false) {
|
|
154
160
|
return null;
|
|
@@ -161,5 +167,3 @@ async function applyPolicy(request, detection, config) {
|
|
|
161
167
|
}
|
|
162
168
|
|
|
163
169
|
export { applyPolicy, buildBlockedResponse, buildChallengeResponse, buildRedirectResponse, createContextFromDetection, evaluatePolicyForDetection, getPolicy, handlePolicyDecision };
|
|
164
|
-
//# sourceMappingURL=policy.mjs.map
|
|
165
|
-
//# sourceMappingURL=policy.mjs.map
|
package/dist/session-tracker.js
CHANGED
|
@@ -11,7 +11,7 @@ var EdgeSessionTracker = class {
|
|
|
11
11
|
cookieName: config.cookieName || "__agentshield_session",
|
|
12
12
|
cookieMaxAge: config.cookieMaxAge || 3600,
|
|
13
13
|
// 1 hour default
|
|
14
|
-
encryptionKey: config.encryptionKey || process.env.
|
|
14
|
+
encryptionKey: config.encryptionKey || process.env.CHECKPOINT_SECRET || "agentshield-default-key"
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
@@ -166,5 +166,3 @@ var StatelessSessionChecker = class {
|
|
|
166
166
|
|
|
167
167
|
exports.EdgeSessionTracker = EdgeSessionTracker;
|
|
168
168
|
exports.StatelessSessionChecker = StatelessSessionChecker;
|
|
169
|
-
//# sourceMappingURL=session-tracker.js.map
|
|
170
|
-
//# sourceMappingURL=session-tracker.js.map
|
package/dist/session-tracker.mjs
CHANGED
|
@@ -9,7 +9,7 @@ var EdgeSessionTracker = class {
|
|
|
9
9
|
cookieName: config.cookieName || "__agentshield_session",
|
|
10
10
|
cookieMaxAge: config.cookieMaxAge || 3600,
|
|
11
11
|
// 1 hour default
|
|
12
|
-
encryptionKey: config.encryptionKey || process.env.
|
|
12
|
+
encryptionKey: config.encryptionKey || process.env.CHECKPOINT_SECRET || "agentshield-default-key"
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
@@ -163,5 +163,3 @@ var StatelessSessionChecker = class {
|
|
|
163
163
|
};
|
|
164
164
|
|
|
165
165
|
export { EdgeSessionTracker, StatelessSessionChecker };
|
|
166
|
-
//# sourceMappingURL=session-tracker.mjs.map
|
|
167
|
-
//# sourceMappingURL=session-tracker.mjs.map
|
|
@@ -382,5 +382,3 @@ function isChatGPTSignature(headers) {
|
|
|
382
382
|
exports.hasSignatureHeaders = hasSignatureHeaders;
|
|
383
383
|
exports.isChatGPTSignature = isChatGPTSignature;
|
|
384
384
|
exports.verifyAgentSignature = verifyAgentSignature;
|
|
385
|
-
//# sourceMappingURL=signature-verifier.js.map
|
|
386
|
-
//# sourceMappingURL=signature-verifier.js.map
|
package/dist/translate.d.mts
CHANGED
|
@@ -16,18 +16,45 @@ import { IncomingHttpLike } from '@kya-os/checkpoint-wasm-runtime/orchestrator';
|
|
|
16
16
|
* `x-forwarded-for` first IP).
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Options controlling translator side effects.
|
|
21
|
+
*
|
|
22
|
+
* `drainJsonBody` (default `true`) controls whether the translator
|
|
23
|
+
* reads the request body so the orchestrator can extract an MCP-I
|
|
24
|
+
* envelope from `_meta.proof.jws` (the canonical spec-form transport).
|
|
25
|
+
*
|
|
26
|
+
* Trade-off — body draining consumes the request stream. We use
|
|
27
|
+
* `req.clone().text()` so the original `req.body` stream is preserved
|
|
28
|
+
* for downstream Next.js handlers. Cloning has memory overhead
|
|
29
|
+
* proportional to the body size; for large request bodies (>1 MB) or
|
|
30
|
+
* streaming-sensitive routes, set `drainJsonBody: false` and verify
|
|
31
|
+
* envelopes via the `KYA-Delegation` header transport instead (the
|
|
32
|
+
* legacy form, requires `legacyEnvelopeFallback: true` on
|
|
33
|
+
* `withCheckpoint`).
|
|
34
|
+
*/
|
|
35
|
+
interface NextRequestToHttpLikeOpts {
|
|
36
|
+
/**
|
|
37
|
+
* Read the request body when `content-type` is `application/json` so
|
|
38
|
+
* the orchestrator can extract an MCP-I envelope from
|
|
39
|
+
* `_meta.proof.jws`. Default `true`. Set `false` for streaming
|
|
40
|
+
* middlewares that can't tolerate the clone/read overhead.
|
|
41
|
+
*/
|
|
42
|
+
drainJsonBody?: boolean;
|
|
43
|
+
}
|
|
19
44
|
/**
|
|
20
45
|
* Translate a Next.js `NextRequest` into the orchestrator's
|
|
21
46
|
* `IncomingHttpLike` shape.
|
|
22
47
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
48
|
+
* When `opts.drainJsonBody !== false` and the request is JSON, the
|
|
49
|
+
* translator clones the request and reads the body into a string so
|
|
50
|
+
* the orchestrator's `buildAgentRequest` can extract a
|
|
51
|
+
* `_meta.proof.jws` envelope. The original `req.body` stream is
|
|
52
|
+
* preserved for downstream handlers via `req.clone()`.
|
|
53
|
+
*
|
|
54
|
+
* When the body can't be read (drain disabled, non-JSON, or a stream
|
|
55
|
+
* error) we pass `body: null` and the orchestrator routes to
|
|
56
|
+
* PlainHttp — same behavior as the pre-1.1.0 default.
|
|
30
57
|
*/
|
|
31
|
-
declare function nextRequestToHttpLike(req: NextRequest): IncomingHttpLike
|
|
58
|
+
declare function nextRequestToHttpLike(req: NextRequest, opts?: NextRequestToHttpLikeOpts): Promise<IncomingHttpLike>;
|
|
32
59
|
|
|
33
|
-
export { nextRequestToHttpLike };
|
|
60
|
+
export { type NextRequestToHttpLikeOpts, nextRequestToHttpLike };
|
package/dist/translate.d.ts
CHANGED
|
@@ -16,18 +16,45 @@ import { IncomingHttpLike } from '@kya-os/checkpoint-wasm-runtime/orchestrator';
|
|
|
16
16
|
* `x-forwarded-for` first IP).
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Options controlling translator side effects.
|
|
21
|
+
*
|
|
22
|
+
* `drainJsonBody` (default `true`) controls whether the translator
|
|
23
|
+
* reads the request body so the orchestrator can extract an MCP-I
|
|
24
|
+
* envelope from `_meta.proof.jws` (the canonical spec-form transport).
|
|
25
|
+
*
|
|
26
|
+
* Trade-off — body draining consumes the request stream. We use
|
|
27
|
+
* `req.clone().text()` so the original `req.body` stream is preserved
|
|
28
|
+
* for downstream Next.js handlers. Cloning has memory overhead
|
|
29
|
+
* proportional to the body size; for large request bodies (>1 MB) or
|
|
30
|
+
* streaming-sensitive routes, set `drainJsonBody: false` and verify
|
|
31
|
+
* envelopes via the `KYA-Delegation` header transport instead (the
|
|
32
|
+
* legacy form, requires `legacyEnvelopeFallback: true` on
|
|
33
|
+
* `withCheckpoint`).
|
|
34
|
+
*/
|
|
35
|
+
interface NextRequestToHttpLikeOpts {
|
|
36
|
+
/**
|
|
37
|
+
* Read the request body when `content-type` is `application/json` so
|
|
38
|
+
* the orchestrator can extract an MCP-I envelope from
|
|
39
|
+
* `_meta.proof.jws`. Default `true`. Set `false` for streaming
|
|
40
|
+
* middlewares that can't tolerate the clone/read overhead.
|
|
41
|
+
*/
|
|
42
|
+
drainJsonBody?: boolean;
|
|
43
|
+
}
|
|
19
44
|
/**
|
|
20
45
|
* Translate a Next.js `NextRequest` into the orchestrator's
|
|
21
46
|
* `IncomingHttpLike` shape.
|
|
22
47
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
48
|
+
* When `opts.drainJsonBody !== false` and the request is JSON, the
|
|
49
|
+
* translator clones the request and reads the body into a string so
|
|
50
|
+
* the orchestrator's `buildAgentRequest` can extract a
|
|
51
|
+
* `_meta.proof.jws` envelope. The original `req.body` stream is
|
|
52
|
+
* preserved for downstream handlers via `req.clone()`.
|
|
53
|
+
*
|
|
54
|
+
* When the body can't be read (drain disabled, non-JSON, or a stream
|
|
55
|
+
* error) we pass `body: null` and the orchestrator routes to
|
|
56
|
+
* PlainHttp — same behavior as the pre-1.1.0 default.
|
|
30
57
|
*/
|
|
31
|
-
declare function nextRequestToHttpLike(req: NextRequest): IncomingHttpLike
|
|
58
|
+
declare function nextRequestToHttpLike(req: NextRequest, opts?: NextRequestToHttpLikeOpts): Promise<IncomingHttpLike>;
|
|
32
59
|
|
|
33
|
-
export { nextRequestToHttpLike };
|
|
60
|
+
export { type NextRequestToHttpLikeOpts, nextRequestToHttpLike };
|