@kya-os/checkpoint-nextjs 1.2.0 → 1.7.1

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 (52) hide show
  1. package/CHANGELOG.md +159 -0
  2. package/EDGE_RUNTIME_WASM_SETUP.md +1 -1
  3. package/bin/setup-edge-wasm.js +1 -1
  4. package/dist/api-middleware.d.mts +9 -1
  5. package/dist/api-middleware.d.ts +9 -1
  6. package/dist/api-middleware.js +14 -4
  7. package/dist/api-middleware.mjs +15 -5
  8. package/dist/composed-policy.d.mts +115 -0
  9. package/dist/composed-policy.d.ts +115 -0
  10. package/dist/composed-policy.js +102 -0
  11. package/dist/composed-policy.mjs +96 -0
  12. package/dist/config-DAwIA4DB.d.mts +214 -0
  13. package/dist/config-DyU4l5er.d.ts +214 -0
  14. package/dist/create-middleware.js +0 -2
  15. package/dist/create-middleware.mjs +0 -2
  16. package/dist/edge-runtime-loader.js +3 -1
  17. package/dist/edge-runtime-loader.mjs +3 -1
  18. package/dist/edge-wasm-middleware.d.mts +6 -6
  19. package/dist/edge-wasm-middleware.d.ts +6 -6
  20. package/dist/index.d.mts +6 -14
  21. package/dist/index.d.ts +6 -14
  22. package/dist/index.js +191 -13
  23. package/dist/index.mjs +192 -14
  24. package/dist/middleware-edge.d.mts +7 -3
  25. package/dist/middleware-edge.d.ts +7 -3
  26. package/dist/middleware-edge.js +174 -4
  27. package/dist/middleware-edge.mjs +171 -4
  28. package/dist/middleware-node.d.mts +39 -116
  29. package/dist/middleware-node.d.ts +39 -116
  30. package/dist/middleware-node.js +181 -4
  31. package/dist/middleware-node.mjs +178 -5
  32. package/dist/middleware.d.mts +10 -1
  33. package/dist/middleware.d.ts +10 -1
  34. package/dist/middleware.js +6 -0
  35. package/dist/middleware.mjs +6 -1
  36. package/dist/nodejs-wasm-loader.d.mts +3 -4
  37. package/dist/nodejs-wasm-loader.d.ts +3 -4
  38. package/dist/nodejs-wasm-loader.js +1 -1
  39. package/dist/nodejs-wasm-loader.mjs +1 -1
  40. package/dist/wasm-setup.js +1 -1
  41. package/dist/wasm-setup.mjs +1 -1
  42. package/package.json +4 -9
  43. package/dist/.tsbuildinfo +0 -1
  44. package/dist/signature-verifier.d.mts +0 -33
  45. package/dist/signature-verifier.d.ts +0 -33
  46. package/dist/signature-verifier.js +0 -384
  47. package/dist/signature-verifier.mjs +0 -360
  48. package/dist/wasm-middleware.d.mts +0 -98
  49. package/dist/wasm-middleware.d.ts +0 -98
  50. package/dist/wasm-middleware.js +0 -125
  51. package/dist/wasm-middleware.mjs +0 -121
  52. package/templates/middleware-wasm-100.ts +0 -161
@@ -1,10 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  var edge = require('@kya-os/checkpoint-wasm-runtime/orchestrator/edge');
4
- var server = require('next/server');
4
+ var policyEdge = require('@kya-os/checkpoint-wasm-runtime/policy-edge');
5
5
  var checkpointShared = require('@kya-os/checkpoint-shared');
6
+ var server = require('next/server');
7
+ var composedPolicy = require('@kya-os/checkpoint-wasm-runtime/composed-policy');
6
8
  require('@kya-os/checkpoint-wasm-runtime/orchestrator');
7
9
  var adapters = require('@kya-os/checkpoint-wasm-runtime/adapters');
10
+ var reporter = require('@kya-os/checkpoint-wasm-runtime/reporter');
8
11
 
9
12
  // src/middleware-edge.ts
10
13
  function adaptToNextResponse(rendered, req) {
@@ -55,6 +58,96 @@ function applyHeaders(res, headers) {
55
58
  res.headers.set(key, value);
56
59
  }
57
60
  }
61
+ var DEFAULT_DASHBOARD_URL = "https://kya.vouched.id";
62
+ var NOOP_LOGGER = {
63
+ shadowDivergence: () => {
64
+ },
65
+ evaluationError: () => {
66
+ }
67
+ };
68
+ function makeComposedPolicyContext(opts) {
69
+ const { projectId, fetcher } = opts;
70
+ const cache = composedPolicy.makeComposedPolicyCache({ compile: opts.compile, cacheMax: opts.cacheMax });
71
+ const logger = opts.logger ?? NOOP_LOGGER;
72
+ return {
73
+ async apply(result, path) {
74
+ const structured = { decision: result.decision, acted: false };
75
+ const policy = await fetcher.getPolicy(projectId);
76
+ const outcome = await composedPolicy.evaluateComposedPolicy({
77
+ cache,
78
+ projectId,
79
+ flags: {
80
+ policyLanguage: policy.policyLanguage,
81
+ policySourceText: policy.policySourceText,
82
+ engineEnforcementEnabled: policy.engineEnforcementEnabled,
83
+ enabled: policy.enabled
84
+ },
85
+ authorizeInput: composedPolicy.verifyResultToAuthorizeInput(result, { tenantId: projectId, path }),
86
+ baselineDecisionKind: result.decision.kind
87
+ });
88
+ if ((outcome.status === "acting" || outcome.status === "shadow") && outcome.diverged) {
89
+ logger.shadowDivergence({
90
+ projectId,
91
+ path,
92
+ engineDecision: outcome.engineDecision.kind,
93
+ structuredDecision: result.decision.kind,
94
+ detectionClass: result.detectionDetail.detectionClass.type,
95
+ verificationMethod: result.detectionDetail.verificationMethod,
96
+ confidence: result.detectionDetail.confidence,
97
+ agentName: result.detectionDetail.detectedAgent?.name
98
+ });
99
+ }
100
+ if (outcome.status === "error") {
101
+ logger.evaluationError(projectId, outcome.error);
102
+ return structured;
103
+ }
104
+ if (outcome.status === "acting") {
105
+ return {
106
+ decision: outcome.engineDecision,
107
+ acted: true,
108
+ // Echo the SSOT revision pin with the decision it produced (#3246
109
+ // PR5). Conditional spread: absent upstream stays absent here.
110
+ ...policy.policySourceHash ? { composedBlobHash: policy.policySourceHash } : {}
111
+ };
112
+ }
113
+ return structured;
114
+ },
115
+ async trustedDelegationRoots() {
116
+ const policy = await fetcher.getPolicy(projectId);
117
+ return policy.trustedDelegationRoots ?? [];
118
+ }
119
+ };
120
+ }
121
+ async function resolveTrustedDelegationRootsForRequest(resolver, headers) {
122
+ if (!resolver) return void 0;
123
+ if (!checkpointShared.requestCarriesDelegationProof(headers)) return void 0;
124
+ const roots = await resolver();
125
+ return roots.length > 0 ? roots : void 0;
126
+ }
127
+ async function applyComposedPolicy(context, result, path) {
128
+ if (!context) return;
129
+ try {
130
+ const outcome = await context.apply(result, path);
131
+ if (outcome.acted) {
132
+ result.decision = outcome.decision;
133
+ if (outcome.composedBlobHash) {
134
+ result.composedBlobHash = outcome.composedBlobHash;
135
+ }
136
+ }
137
+ } catch {
138
+ }
139
+ }
140
+ var consoleComposedPolicyLogger = {
141
+ shadowDivergence(info) {
142
+ console.warn("[checkpoint/composed-policy] shadow-divergence", info);
143
+ },
144
+ evaluationError(projectId, error) {
145
+ console.error(
146
+ `[checkpoint/composed-policy] evaluation failed for ${projectId}; using structured decision:`,
147
+ error
148
+ );
149
+ }
150
+ };
58
151
 
59
152
  // src/translate.ts
60
153
  async function nextRequestToHttpLike(req, opts = {}) {
@@ -97,6 +190,42 @@ function extractRemoteAddress(req) {
97
190
  }
98
191
 
99
192
  // src/middleware-node.ts
193
+ var SDK_NAME = "@kya-os/checkpoint-nextjs";
194
+ var VERSION = "1.7.1";
195
+ function buildReporter(config, runtime = "node") {
196
+ if (!config.apiKey) return null;
197
+ return reporter.makeDetectionReporter({
198
+ apiKey: config.apiKey,
199
+ baseUrl: config.baseUrl,
200
+ debug: config.debug,
201
+ // Self-identify (incl. node-vs-edge) so the dashboard can version-gate
202
+ // enforcement. Next.js EDGE composed enforcement is opt-in (needs
203
+ // `cedarWasmModule`), so the dashboard shows it as opt-in, never "Enforcing".
204
+ sdk: { name: SDK_NAME, version: VERSION, runtime }
205
+ });
206
+ }
207
+ function buildTrustedRootsResolver(config, composed) {
208
+ if (composed?.trustedDelegationRoots) {
209
+ return () => composed.trustedDelegationRoots();
210
+ }
211
+ if (!config.projectId) return null;
212
+ const fetcher = new checkpointShared.PolicyFetcher({
213
+ apiBaseUrl: config.dashboardUrl ?? config.baseUrl ?? DEFAULT_DASHBOARD_URL,
214
+ apiKey: config.apiKey,
215
+ cacheTtlSeconds: config.policyCacheTtlSeconds
216
+ });
217
+ const projectId = config.projectId;
218
+ return async () => (await fetcher.getPolicy(projectId)).trustedDelegationRoots ?? [];
219
+ }
220
+ function extractReporterContext(req) {
221
+ return {
222
+ userAgent: req.headers.get("user-agent") ?? void 0,
223
+ ipAddress: req.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ?? req.headers.get("x-real-ip") ?? void 0,
224
+ path: req.nextUrl.pathname,
225
+ url: req.nextUrl.href,
226
+ method: req.method
227
+ };
228
+ }
100
229
  function buildVerifyOpts(config) {
101
230
  const overrides = config.adapters ?? {};
102
231
  return {
@@ -118,12 +247,34 @@ function buildVerifyOpts(config) {
118
247
  function withCheckpoint(config) {
119
248
  void edge.initEngineEdge();
120
249
  const opts = buildVerifyOpts(config);
250
+ const reporter = buildReporter(config, "edge");
251
+ const composed = buildComposedContext(config);
252
+ const trustedRootsResolver = buildTrustedRootsResolver(config, composed);
121
253
  const translateOpts = { drainJsonBody: config.drainJsonBody };
122
- return async function checkpointMiddlewareEdge(req) {
254
+ return async function checkpointMiddlewareEdge(req, event) {
123
255
  const httpLike = await nextRequestToHttpLike(req, translateOpts);
124
- const result = await edge.verifyRequestEdge(httpLike, opts);
256
+ const trustedDelegationRoots = await resolveTrustedDelegationRootsForRequest(
257
+ trustedRootsResolver,
258
+ req.headers
259
+ );
260
+ const result = await edge.verifyRequestEdge(
261
+ httpLike,
262
+ trustedDelegationRoots ? { ...opts, trustedDelegationRoots } : opts
263
+ );
264
+ await applyComposedPolicy(composed, result, req.nextUrl.pathname);
265
+ if (reporter) {
266
+ const reportPromise = reporter(result, extractReporterContext(req));
267
+ if (event) {
268
+ event.waitUntil(reportPromise);
269
+ }
270
+ }
125
271
  await dispatchOnResult(config, result, req);
126
- const rendered = edge.renderDecisionAsResponse(result);
272
+ const bodyReadable200 = checkpointShared.selectBodyReadable200(
273
+ config.delegationChallengeMode ?? "spec-401",
274
+ req.headers,
275
+ result.detectionDetail.detectionClass
276
+ );
277
+ const rendered = edge.renderDecisionAsResponse(result, { bodyReadable200 });
127
278
  return adaptToNextResponse(rendered, req);
128
279
  };
129
280
  }
@@ -134,9 +285,28 @@ async function dispatchOnResult(config, result, req) {
134
285
  } catch {
135
286
  }
136
287
  }
288
+ function buildComposedContext(config) {
289
+ if (config.composedPolicyEnforcer) return config.composedPolicyEnforcer;
290
+ if (!config.projectId || !config.cedarWasmModule) return null;
291
+ policyEdge.initPolicyEvaluatorEdge(config.cedarWasmModule);
292
+ return makeComposedPolicyContext({
293
+ projectId: config.projectId,
294
+ fetcher: new checkpointShared.PolicyFetcher({
295
+ apiBaseUrl: config.dashboardUrl ?? config.baseUrl ?? DEFAULT_DASHBOARD_URL,
296
+ apiKey: config.apiKey,
297
+ cacheTtlSeconds: config.policyCacheTtlSeconds
298
+ }),
299
+ compile: (language, source) => policyEdge.evaluatePolicy(language, source),
300
+ logger: config.debug ? consoleComposedPolicyLogger : void 0
301
+ });
302
+ }
137
303
 
138
304
  Object.defineProperty(exports, "initEngineEdge", {
139
305
  enumerable: true,
140
306
  get: function () { return edge.initEngineEdge; }
141
307
  });
308
+ Object.defineProperty(exports, "initPolicyEvaluatorEdge", {
309
+ enumerable: true,
310
+ get: function () { return policyEdge.initPolicyEvaluatorEdge; }
311
+ });
142
312
  exports.withCheckpoint = withCheckpoint;
@@ -1,9 +1,13 @@
1
1
  import { initEngineEdge, verifyRequestEdge, renderDecisionAsResponse } from '@kya-os/checkpoint-wasm-runtime/orchestrator/edge';
2
2
  export { initEngineEdge } from '@kya-os/checkpoint-wasm-runtime/orchestrator/edge';
3
+ import { initPolicyEvaluatorEdge, evaluatePolicy } from '@kya-os/checkpoint-wasm-runtime/policy-edge';
4
+ export { initPolicyEvaluatorEdge } from '@kya-os/checkpoint-wasm-runtime/policy-edge';
5
+ import { selectBodyReadable200, PolicyFetcher, requestCarriesDelegationProof, acceptsHtml, encodeVerdictCookie, classifyResponseShape, BLOCKED_PATH, VERDICT_COOKIE_NAME } from '@kya-os/checkpoint-shared';
3
6
  import { NextResponse } from 'next/server';
4
- import { acceptsHtml, encodeVerdictCookie, classifyResponseShape, BLOCKED_PATH, VERDICT_COOKIE_NAME } from '@kya-os/checkpoint-shared';
7
+ import { makeComposedPolicyCache, evaluateComposedPolicy, verifyResultToAuthorizeInput } from '@kya-os/checkpoint-wasm-runtime/composed-policy';
5
8
  import '@kya-os/checkpoint-wasm-runtime/orchestrator';
6
9
  import { makeSystemClock, makePolicyEvaluator, makeReputationOracle, makeStatusListCache, makeDidResolver } from '@kya-os/checkpoint-wasm-runtime/adapters';
10
+ import { makeDetectionReporter } from '@kya-os/checkpoint-wasm-runtime/reporter';
7
11
 
8
12
  // src/middleware-edge.ts
9
13
  function adaptToNextResponse(rendered, req) {
@@ -54,6 +58,96 @@ function applyHeaders(res, headers) {
54
58
  res.headers.set(key, value);
55
59
  }
56
60
  }
61
+ var DEFAULT_DASHBOARD_URL = "https://kya.vouched.id";
62
+ var NOOP_LOGGER = {
63
+ shadowDivergence: () => {
64
+ },
65
+ evaluationError: () => {
66
+ }
67
+ };
68
+ function makeComposedPolicyContext(opts) {
69
+ const { projectId, fetcher } = opts;
70
+ const cache = makeComposedPolicyCache({ compile: opts.compile, cacheMax: opts.cacheMax });
71
+ const logger = opts.logger ?? NOOP_LOGGER;
72
+ return {
73
+ async apply(result, path) {
74
+ const structured = { decision: result.decision, acted: false };
75
+ const policy = await fetcher.getPolicy(projectId);
76
+ const outcome = await evaluateComposedPolicy({
77
+ cache,
78
+ projectId,
79
+ flags: {
80
+ policyLanguage: policy.policyLanguage,
81
+ policySourceText: policy.policySourceText,
82
+ engineEnforcementEnabled: policy.engineEnforcementEnabled,
83
+ enabled: policy.enabled
84
+ },
85
+ authorizeInput: verifyResultToAuthorizeInput(result, { tenantId: projectId, path }),
86
+ baselineDecisionKind: result.decision.kind
87
+ });
88
+ if ((outcome.status === "acting" || outcome.status === "shadow") && outcome.diverged) {
89
+ logger.shadowDivergence({
90
+ projectId,
91
+ path,
92
+ engineDecision: outcome.engineDecision.kind,
93
+ structuredDecision: result.decision.kind,
94
+ detectionClass: result.detectionDetail.detectionClass.type,
95
+ verificationMethod: result.detectionDetail.verificationMethod,
96
+ confidence: result.detectionDetail.confidence,
97
+ agentName: result.detectionDetail.detectedAgent?.name
98
+ });
99
+ }
100
+ if (outcome.status === "error") {
101
+ logger.evaluationError(projectId, outcome.error);
102
+ return structured;
103
+ }
104
+ if (outcome.status === "acting") {
105
+ return {
106
+ decision: outcome.engineDecision,
107
+ acted: true,
108
+ // Echo the SSOT revision pin with the decision it produced (#3246
109
+ // PR5). Conditional spread: absent upstream stays absent here.
110
+ ...policy.policySourceHash ? { composedBlobHash: policy.policySourceHash } : {}
111
+ };
112
+ }
113
+ return structured;
114
+ },
115
+ async trustedDelegationRoots() {
116
+ const policy = await fetcher.getPolicy(projectId);
117
+ return policy.trustedDelegationRoots ?? [];
118
+ }
119
+ };
120
+ }
121
+ async function resolveTrustedDelegationRootsForRequest(resolver, headers) {
122
+ if (!resolver) return void 0;
123
+ if (!requestCarriesDelegationProof(headers)) return void 0;
124
+ const roots = await resolver();
125
+ return roots.length > 0 ? roots : void 0;
126
+ }
127
+ async function applyComposedPolicy(context, result, path) {
128
+ if (!context) return;
129
+ try {
130
+ const outcome = await context.apply(result, path);
131
+ if (outcome.acted) {
132
+ result.decision = outcome.decision;
133
+ if (outcome.composedBlobHash) {
134
+ result.composedBlobHash = outcome.composedBlobHash;
135
+ }
136
+ }
137
+ } catch {
138
+ }
139
+ }
140
+ var consoleComposedPolicyLogger = {
141
+ shadowDivergence(info) {
142
+ console.warn("[checkpoint/composed-policy] shadow-divergence", info);
143
+ },
144
+ evaluationError(projectId, error) {
145
+ console.error(
146
+ `[checkpoint/composed-policy] evaluation failed for ${projectId}; using structured decision:`,
147
+ error
148
+ );
149
+ }
150
+ };
57
151
 
58
152
  // src/translate.ts
59
153
  async function nextRequestToHttpLike(req, opts = {}) {
@@ -96,6 +190,42 @@ function extractRemoteAddress(req) {
96
190
  }
97
191
 
98
192
  // src/middleware-node.ts
193
+ var SDK_NAME = "@kya-os/checkpoint-nextjs";
194
+ var VERSION = "1.7.1";
195
+ function buildReporter(config, runtime = "node") {
196
+ if (!config.apiKey) return null;
197
+ return makeDetectionReporter({
198
+ apiKey: config.apiKey,
199
+ baseUrl: config.baseUrl,
200
+ debug: config.debug,
201
+ // Self-identify (incl. node-vs-edge) so the dashboard can version-gate
202
+ // enforcement. Next.js EDGE composed enforcement is opt-in (needs
203
+ // `cedarWasmModule`), so the dashboard shows it as opt-in, never "Enforcing".
204
+ sdk: { name: SDK_NAME, version: VERSION, runtime }
205
+ });
206
+ }
207
+ function buildTrustedRootsResolver(config, composed) {
208
+ if (composed?.trustedDelegationRoots) {
209
+ return () => composed.trustedDelegationRoots();
210
+ }
211
+ if (!config.projectId) return null;
212
+ const fetcher = new PolicyFetcher({
213
+ apiBaseUrl: config.dashboardUrl ?? config.baseUrl ?? DEFAULT_DASHBOARD_URL,
214
+ apiKey: config.apiKey,
215
+ cacheTtlSeconds: config.policyCacheTtlSeconds
216
+ });
217
+ const projectId = config.projectId;
218
+ return async () => (await fetcher.getPolicy(projectId)).trustedDelegationRoots ?? [];
219
+ }
220
+ function extractReporterContext(req) {
221
+ return {
222
+ userAgent: req.headers.get("user-agent") ?? void 0,
223
+ ipAddress: req.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ?? req.headers.get("x-real-ip") ?? void 0,
224
+ path: req.nextUrl.pathname,
225
+ url: req.nextUrl.href,
226
+ method: req.method
227
+ };
228
+ }
99
229
  function buildVerifyOpts(config) {
100
230
  const overrides = config.adapters ?? {};
101
231
  return {
@@ -117,12 +247,34 @@ function buildVerifyOpts(config) {
117
247
  function withCheckpoint(config) {
118
248
  void initEngineEdge();
119
249
  const opts = buildVerifyOpts(config);
250
+ const reporter = buildReporter(config, "edge");
251
+ const composed = buildComposedContext(config);
252
+ const trustedRootsResolver = buildTrustedRootsResolver(config, composed);
120
253
  const translateOpts = { drainJsonBody: config.drainJsonBody };
121
- return async function checkpointMiddlewareEdge(req) {
254
+ return async function checkpointMiddlewareEdge(req, event) {
122
255
  const httpLike = await nextRequestToHttpLike(req, translateOpts);
123
- const result = await verifyRequestEdge(httpLike, opts);
256
+ const trustedDelegationRoots = await resolveTrustedDelegationRootsForRequest(
257
+ trustedRootsResolver,
258
+ req.headers
259
+ );
260
+ const result = await verifyRequestEdge(
261
+ httpLike,
262
+ trustedDelegationRoots ? { ...opts, trustedDelegationRoots } : opts
263
+ );
264
+ await applyComposedPolicy(composed, result, req.nextUrl.pathname);
265
+ if (reporter) {
266
+ const reportPromise = reporter(result, extractReporterContext(req));
267
+ if (event) {
268
+ event.waitUntil(reportPromise);
269
+ }
270
+ }
124
271
  await dispatchOnResult(config, result, req);
125
- const rendered = renderDecisionAsResponse(result);
272
+ const bodyReadable200 = selectBodyReadable200(
273
+ config.delegationChallengeMode ?? "spec-401",
274
+ req.headers,
275
+ result.detectionDetail.detectionClass
276
+ );
277
+ const rendered = renderDecisionAsResponse(result, { bodyReadable200 });
126
278
  return adaptToNextResponse(rendered, req);
127
279
  };
128
280
  }
@@ -133,5 +285,20 @@ async function dispatchOnResult(config, result, req) {
133
285
  } catch {
134
286
  }
135
287
  }
288
+ function buildComposedContext(config) {
289
+ if (config.composedPolicyEnforcer) return config.composedPolicyEnforcer;
290
+ if (!config.projectId || !config.cedarWasmModule) return null;
291
+ initPolicyEvaluatorEdge(config.cedarWasmModule);
292
+ return makeComposedPolicyContext({
293
+ projectId: config.projectId,
294
+ fetcher: new PolicyFetcher({
295
+ apiBaseUrl: config.dashboardUrl ?? config.baseUrl ?? DEFAULT_DASHBOARD_URL,
296
+ apiKey: config.apiKey,
297
+ cacheTtlSeconds: config.policyCacheTtlSeconds
298
+ }),
299
+ compile: (language, source) => evaluatePolicy(language, source),
300
+ logger: config.debug ? consoleComposedPolicyLogger : void 0
301
+ });
302
+ }
136
303
 
137
304
  export { withCheckpoint };
@@ -1,113 +1,12 @@
1
+ import * as _kya_os_checkpoint_wasm_runtime_engine from '@kya-os/checkpoint-wasm-runtime/engine';
1
2
  import * as _kya_os_checkpoint_wasm_runtime_adapters from '@kya-os/checkpoint-wasm-runtime/adapters';
2
- import { DidResolverAdapter, StatusListCacheAdapter, ReputationOracleAdapter, PolicyEvaluatorAdapter } from '@kya-os/checkpoint-wasm-runtime/adapters';
3
- import { NextRequest, NextResponse } from 'next/server';
4
- import { EnforcementMode, VerifyResult, EngineConfig } from '@kya-os/checkpoint-wasm-runtime/engine';
3
+ import { NextRequest, NextFetchEvent, NextResponse } from 'next/server';
4
+ import { DetectionReporter, ReporterContext } from '@kya-os/checkpoint-wasm-runtime/reporter';
5
+ import { C as CheckpointConfig } from './config-DAwIA4DB.mjs';
6
+ import { ComposedPolicyContext, TrustedDelegationRootsResolver } from './composed-policy.mjs';
7
+ import '@kya-os/checkpoint-shared';
8
+ import '@kya-os/checkpoint-wasm-runtime/composed-policy';
5
9
 
6
- /**
7
- * Configuration for `withCheckpoint`.
8
- *
9
- * The new minimal shape Phase D's middleware needs. Legacy
10
- * `AgentShieldMiddlewareConfig` (from `./api-middleware`) remains
11
- * exported during the deprecation window — see D.4 cutover.
12
- */
13
- interface CheckpointConfig {
14
- /**
15
- * Tenant identifier — typically the customer's dashboard hostname
16
- * (e.g. `acme.checkpoint.example`). The PolicyEvaluator uses this
17
- * to look up tenant policy from the dashboard.
18
- */
19
- tenantHost: string;
20
- /**
21
- * `'enforce'` (default) blocks; `'observe'` passes everything
22
- * through with `X-Checkpoint-Would-Have-Been` headers. Per Phase 0.2.
23
- */
24
- enforcementMode?: EnforcementMode;
25
- /**
26
- * Argus reputation oracle base URL. Omit to use the trust-by-default
27
- * baseline (reputation defaults to 1.0; orchestrator logs a one-shot
28
- * warning at first request).
29
- */
30
- argusUrl?: string;
31
- /**
32
- * Dashboard base URL for the PolicyEvaluator to fetch tenant policy
33
- * from. Omit to use the open-by-default tenant policy.
34
- */
35
- dashboardUrl?: string;
36
- /**
37
- * Returned to the PolicyEvaluator for anonymous requests (no agent
38
- * DID). Default 1.0 (trust-by-default).
39
- */
40
- reputationBaseline?: number;
41
- /**
42
- * Pre-built adapter instances. Production deployments use the
43
- * factory-built defaults from `@kya-os/checkpoint-wasm-runtime/adapters`;
44
- * tests use stubs. The factory composes any provided overrides over
45
- * defaults — partial overrides are supported.
46
- */
47
- adapters?: Partial<{
48
- didResolver: DidResolverAdapter;
49
- statusListCache: StatusListCacheAdapter;
50
- reputationOracle: ReputationOracleAdapter;
51
- policyEvaluator: PolicyEvaluatorAdapter;
52
- }>;
53
- /**
54
- * Optional callback for the post-verdict path — fires after every
55
- * verification, regardless of permit/block, with the full
56
- * `VerifyResult`. Use for logging, dashboards, telemetry. Errors
57
- * thrown here are swallowed so user code can't break the middleware
58
- * response.
59
- */
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;
96
- /**
97
- * Engine-default behaviour knobs forwarded to every composed
98
- * `ContextSpec`. Defaults to `{ tier3Action: 'monitor' }` —
99
- * customer-onboarding-safe (tenant policy decides; engine doesn't
100
- * short-circuit known-agent UAs with an engine-default Block).
101
- *
102
- * Opt into `{ tier3Action: 'block' }` when the host wants the
103
- * calibrated engine-default block for KnownAiAgent / AiCrawler /
104
- * HeadlessBrowser classifications BEFORE the tenant policy seam.
105
- *
106
- * Added in `@kya-os/checkpoint-nextjs@1.2.0` (Engine-Tier3-Monitor-
107
- * Default, #2653 + this PR's plumbing follow-up).
108
- */
109
- engineConfig?: EngineConfig;
110
- }
111
10
  /**
112
11
  * Build the Checkpoint middleware. Returns a function `(req) => NextResponse`
113
12
  * suitable for `export default withCheckpoint({...})` in `middleware.ts`.
@@ -117,24 +16,48 @@ interface CheckpointConfig {
117
16
  * `verifyRequest`, and translates the verdict to `NextResponse`. No
118
17
  * verification logic lives in this file.
119
18
  */
120
- declare function withCheckpoint(config: CheckpointConfig): (req: NextRequest) => Promise<NextResponse>;
19
+ declare function withCheckpoint(config: CheckpointConfig): (req: NextRequest, event?: NextFetchEvent) => Promise<NextResponse>;
20
+ /**
21
+ * Installed SDK version, self-reported to the detection reporter so the
22
+ * dashboard can version-gate "composed policy enforces here". MUST equal
23
+ * `package.json` version — pinned by a unit test (the old hardcoded `0.1.0` had
24
+ * drifted). Re-exported as `VERSION` from the package index.
25
+ */
26
+ declare const VERSION = "1.7.1";
27
+ declare function buildReporter(config: CheckpointConfig, runtime?: 'node' | 'edge'): DetectionReporter | null;
28
+ /**
29
+ * Build the per-factory trusted-delegation-roots resolver (P2 / DR-1). Root
30
+ * pinning is a security concern INDEPENDENT of composed Cedar enforcement, so it
31
+ * must resolve wherever a `projectId` exists — including Edge setups that never
32
+ * wire `cedarWasmModule` (where `buildComposedContext` returns null). Prefers the
33
+ * composed context's accessor (reuses its cached fetcher / honors an injected
34
+ * enforcer); otherwise falls back to a `projectId`-only policy fetch. Returns
35
+ * `null` when no source is configured (no roots → engine open default).
36
+ */
37
+ declare function buildTrustedRootsResolver(config: CheckpointConfig, composed: ComposedPolicyContext | null): TrustedDelegationRootsResolver | null;
38
+ /**
39
+ * Pull the request context the dashboard's `/api/v1/log-detection`
40
+ * endpoint expects out of a `NextRequest`. Works under both Node and
41
+ * Edge runtimes — no runtime-specific APIs.
42
+ */
43
+ declare function extractReporterContext(req: NextRequest): ReporterContext;
121
44
  /**
122
45
  * Compose adapter defaults with caller-supplied overrides. Factored
123
46
  * out so the Edge entry (which uses the same composition) can reuse
124
47
  * the shape.
125
48
  */
126
49
  declare function buildVerifyOpts(config: CheckpointConfig): {
127
- didResolver: DidResolverAdapter;
128
- statusListCache: StatusListCacheAdapter;
129
- reputationOracle: ReputationOracleAdapter;
130
- policyEvaluator: PolicyEvaluatorAdapter;
50
+ didResolver: _kya_os_checkpoint_wasm_runtime_adapters.DidResolverAdapter;
51
+ statusListCache: _kya_os_checkpoint_wasm_runtime_adapters.StatusListCacheAdapter;
52
+ reputationOracle: _kya_os_checkpoint_wasm_runtime_adapters.ReputationOracleAdapter;
53
+ policyEvaluator: _kya_os_checkpoint_wasm_runtime_adapters.PolicyEvaluatorAdapter;
131
54
  clock: _kya_os_checkpoint_wasm_runtime_adapters.ClockAdapter;
132
55
  tenantHost: string;
133
- enforcementMode: EnforcementMode;
56
+ enforcementMode: _kya_os_checkpoint_wasm_runtime_engine.EnforcementMode;
134
57
  reputationBaseline: number | undefined;
135
58
  argusUrl: string | undefined;
136
59
  legacyEnvelopeFallback: boolean;
137
- engineConfig: EngineConfig | undefined;
60
+ engineConfig: _kya_os_checkpoint_wasm_runtime_engine.EngineConfig | undefined;
138
61
  };
139
62
 
140
- export { type CheckpointConfig, buildVerifyOpts as _buildVerifyOpts, withCheckpoint };
63
+ export { CheckpointConfig, VERSION, buildReporter as _buildReporter, buildTrustedRootsResolver as _buildTrustedRootsResolver, buildVerifyOpts as _buildVerifyOpts, extractReporterContext as _extractReporterContext, withCheckpoint };