@kya-os/checkpoint-nextjs 1.7.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.
@@ -236,7 +236,7 @@ export function createAgentShieldMiddleware(options: {
236
236
  { pattern: /openai/i, name: 'OpenAI' },
237
237
  { pattern: /gpt-/i, name: 'GPT' },
238
238
  { pattern: /copilot/i, name: 'GitHub Copilot' },
239
- { pattern: /bard/i, name: 'Google Bard' },
239
+ { pattern: /bard/i, name: 'Google Gemini' },
240
240
  { pattern: /gemini/i, name: 'Google Gemini' },
241
241
  ];
242
242
 
@@ -310,7 +310,7 @@ function patternDetection(
310
310
  { pattern: /openai/i, name: 'OpenAI', confidence: 0.90 },
311
311
  { pattern: /gpt-crawler/i, name: 'GPT Crawler', confidence: 0.95 },
312
312
  { pattern: /copilot/i, name: 'GitHub Copilot', confidence: 0.85 },
313
- { pattern: /bard/i, name: 'Google Bard', confidence: 0.85 },
313
+ { pattern: /bard/i, name: 'Google Gemini', confidence: 0.85 }, // legacy Bard UA → Gemini (brand retired 2024)
314
314
  { pattern: /gemini/i, name: 'Google Gemini', confidence: 0.85 },
315
315
  { pattern: /perplexity/i, name: 'Perplexity', confidence: 0.85 },
316
316
  ];
@@ -1,6 +1,6 @@
1
1
  import { NextRequest, NextResponse } from 'next/server';
2
+ import { ChallengeEnvelopeMode } from '@kya-os/checkpoint-shared';
2
3
  import { EnforcementDecision } from './api-client.mjs';
3
- import '@kya-os/checkpoint-shared';
4
4
 
5
5
  /**
6
6
  * API-based AgentShield Middleware for Next.js
@@ -76,6 +76,14 @@ interface CheckpointApiMiddlewareConfig {
76
76
  * @default 'instruct'
77
77
  */
78
78
  redirectMode?: 'instruct' | 'http';
79
+ /**
80
+ * Challenge-emission envelope mode (draft-kya-http-02 §8.1 fetcher-200).
81
+ * `negotiated` serves a body-readable HTTP 200 instruct response to
82
+ * cooperative agents (so fetchers that drop 4xx bodies can read it),
83
+ * keeping the spec 401 for everyone else. Defaults to `spec-401`.
84
+ * A cooperative-UX bridge, NOT an access control.
85
+ */
86
+ delegationChallengeMode?: ChallengeEnvelopeMode;
79
87
  /**
80
88
  * Custom blocked response
81
89
  */
@@ -1,6 +1,6 @@
1
1
  import { NextRequest, NextResponse } from 'next/server';
2
+ import { ChallengeEnvelopeMode } from '@kya-os/checkpoint-shared';
2
3
  import { EnforcementDecision } from './api-client.js';
3
- import '@kya-os/checkpoint-shared';
4
4
 
5
5
  /**
6
6
  * API-based AgentShield Middleware for Next.js
@@ -76,6 +76,14 @@ interface CheckpointApiMiddlewareConfig {
76
76
  * @default 'instruct'
77
77
  */
78
78
  redirectMode?: 'instruct' | 'http';
79
+ /**
80
+ * Challenge-emission envelope mode (draft-kya-http-02 §8.1 fetcher-200).
81
+ * `negotiated` serves a body-readable HTTP 200 instruct response to
82
+ * cooperative agents (so fetchers that drop 4xx bodies can read it),
83
+ * keeping the spec 401 for everyone else. Defaults to `spec-401`.
84
+ * A cooperative-UX bridge, NOT an access control.
85
+ */
86
+ delegationChallengeMode?: ChallengeEnvelopeMode;
79
87
  /**
80
88
  * Custom blocked response
81
89
  */
@@ -237,7 +237,7 @@ function safeHostname(url) {
237
237
  // src/responses/agent-instruction.ts
238
238
  var MCP_I_DOCS_URL = "https://docs.knowthat.ai/mcp-i/getting-started";
239
239
  var DEFAULT_CONNECT_PATH = "/connect";
240
- function buildAgentInstructionResponse(request, decision, redirectUrl) {
240
+ function buildAgentInstructionResponse(request, decision, redirectUrl, options) {
241
241
  const resolved = resolveUrl(redirectUrl ?? DEFAULT_CONNECT_PATH, request.url);
242
242
  const agentName = decision.agentName || decision.agentType || "unknown";
243
243
  if (!resolved.searchParams.has("agent")) {
@@ -288,8 +288,11 @@ It only takes a moment and you won't need to do it again. Once you're done, ask
288
288
  confidence: decision.confidence
289
289
  }
290
290
  };
291
- const response = server.NextResponse.json(body, { status: 401 });
292
- response.headers.set("WWW-Authenticate", `KYA realm="api", authorization_uri="${authUrl}"`);
291
+ const bodyReadable200 = options?.bodyReadable200 ?? false;
292
+ const response = server.NextResponse.json(body, { status: bodyReadable200 ? 200 : 401 });
293
+ if (!bodyReadable200) {
294
+ response.headers.set("WWW-Authenticate", `KYA realm="api", authorization_uri="${authUrl}"`);
295
+ }
293
296
  response.headers.set(
294
297
  "Link",
295
298
  `<${authUrl}>; rel="kya-authorize", <${MCP_I_DOCS_URL}>; rel="help"`
@@ -482,7 +485,14 @@ function withCheckpointApi(config = {}) {
482
485
  return buildRedirectResponse(request, decision, config);
483
486
  }
484
487
  const targetUrl = config.redirectUrl || decision.redirectUrl;
485
- return buildAgentInstructionResponse(request, decision, targetUrl);
488
+ const bodyReadable200 = checkpointShared.selectBodyReadable200(
489
+ config.delegationChallengeMode ?? "spec-401",
490
+ request.headers,
491
+ result.data.detection?.detectionClass
492
+ );
493
+ return buildAgentInstructionResponse(request, decision, targetUrl, {
494
+ bodyReadable200
495
+ });
486
496
  }
487
497
  case "challenge": {
488
498
  return buildRedirectResponse(request, decision, config);
@@ -1,5 +1,5 @@
1
1
  import { NextResponse } from 'next/server';
2
- import { matchPath } from '@kya-os/checkpoint-shared';
2
+ import { selectBodyReadable200, matchPath } from '@kya-os/checkpoint-shared';
3
3
 
4
4
  // src/api-middleware.ts
5
5
 
@@ -235,7 +235,7 @@ function safeHostname(url) {
235
235
  // src/responses/agent-instruction.ts
236
236
  var MCP_I_DOCS_URL = "https://docs.knowthat.ai/mcp-i/getting-started";
237
237
  var DEFAULT_CONNECT_PATH = "/connect";
238
- function buildAgentInstructionResponse(request, decision, redirectUrl) {
238
+ function buildAgentInstructionResponse(request, decision, redirectUrl, options) {
239
239
  const resolved = resolveUrl(redirectUrl ?? DEFAULT_CONNECT_PATH, request.url);
240
240
  const agentName = decision.agentName || decision.agentType || "unknown";
241
241
  if (!resolved.searchParams.has("agent")) {
@@ -286,8 +286,11 @@ It only takes a moment and you won't need to do it again. Once you're done, ask
286
286
  confidence: decision.confidence
287
287
  }
288
288
  };
289
- const response = NextResponse.json(body, { status: 401 });
290
- response.headers.set("WWW-Authenticate", `KYA realm="api", authorization_uri="${authUrl}"`);
289
+ const bodyReadable200 = options?.bodyReadable200 ?? false;
290
+ const response = NextResponse.json(body, { status: bodyReadable200 ? 200 : 401 });
291
+ if (!bodyReadable200) {
292
+ response.headers.set("WWW-Authenticate", `KYA realm="api", authorization_uri="${authUrl}"`);
293
+ }
291
294
  response.headers.set(
292
295
  "Link",
293
296
  `<${authUrl}>; rel="kya-authorize", <${MCP_I_DOCS_URL}>; rel="help"`
@@ -480,7 +483,14 @@ function withCheckpointApi(config = {}) {
480
483
  return buildRedirectResponse(request, decision, config);
481
484
  }
482
485
  const targetUrl = config.redirectUrl || decision.redirectUrl;
483
- return buildAgentInstructionResponse(request, decision, targetUrl);
486
+ const bodyReadable200 = selectBodyReadable200(
487
+ config.delegationChallengeMode ?? "spec-401",
488
+ request.headers,
489
+ result.data.detection?.detectionClass
490
+ );
491
+ return buildAgentInstructionResponse(request, decision, targetUrl, {
492
+ bodyReadable200
493
+ });
484
494
  }
485
495
  case "challenge": {
486
496
  return buildRedirectResponse(request, decision, config);
@@ -45,6 +45,13 @@ interface ShadowDivergenceInfo {
45
45
  interface ComposedPolicyApplyResult {
46
46
  decision: Decision;
47
47
  acted: boolean;
48
+ /**
49
+ * SSOT-served revision pin (sha256 of the evaluated bundle, byte-identical
50
+ * to `policy_revisions.composed_blob_hash`) — set ONLY when `acted`, echoed
51
+ * from `PolicyConfig.policySourceHash` (#3246 PR5). Absent on structured
52
+ * decisions and when the dashboard predates the field.
53
+ */
54
+ composedBlobHash?: string;
48
55
  }
49
56
  interface ComposedPolicyContext {
50
57
  /**
@@ -45,6 +45,13 @@ interface ShadowDivergenceInfo {
45
45
  interface ComposedPolicyApplyResult {
46
46
  decision: Decision;
47
47
  acted: boolean;
48
+ /**
49
+ * SSOT-served revision pin (sha256 of the evaluated bundle, byte-identical
50
+ * to `policy_revisions.composed_blob_hash`) — set ONLY when `acted`, echoed
51
+ * from `PolicyConfig.policySourceHash` (#3246 PR5). Absent on structured
52
+ * decisions and when the dashboard predates the field.
53
+ */
54
+ composedBlobHash?: string;
48
55
  }
49
56
  interface ComposedPolicyContext {
50
57
  /**
@@ -48,7 +48,13 @@ function makeComposedPolicyContext(opts) {
48
48
  return structured;
49
49
  }
50
50
  if (outcome.status === "acting") {
51
- return { decision: outcome.engineDecision, acted: true };
51
+ return {
52
+ decision: outcome.engineDecision,
53
+ acted: true,
54
+ // Echo the SSOT revision pin with the decision it produced (#3246
55
+ // PR5). Conditional spread: absent upstream stays absent here.
56
+ ...policy.policySourceHash ? { composedBlobHash: policy.policySourceHash } : {}
57
+ };
52
58
  }
53
59
  return structured;
54
60
  },
@@ -68,7 +74,12 @@ async function applyComposedPolicy(context, result, path) {
68
74
  if (!context) return;
69
75
  try {
70
76
  const outcome = await context.apply(result, path);
71
- if (outcome.acted) result.decision = outcome.decision;
77
+ if (outcome.acted) {
78
+ result.decision = outcome.decision;
79
+ if (outcome.composedBlobHash) {
80
+ result.composedBlobHash = outcome.composedBlobHash;
81
+ }
82
+ }
72
83
  } catch {
73
84
  }
74
85
  }
@@ -46,7 +46,13 @@ function makeComposedPolicyContext(opts) {
46
46
  return structured;
47
47
  }
48
48
  if (outcome.status === "acting") {
49
- return { decision: outcome.engineDecision, acted: true };
49
+ return {
50
+ decision: outcome.engineDecision,
51
+ acted: true,
52
+ // Echo the SSOT revision pin with the decision it produced (#3246
53
+ // PR5). Conditional spread: absent upstream stays absent here.
54
+ ...policy.policySourceHash ? { composedBlobHash: policy.policySourceHash } : {}
55
+ };
50
56
  }
51
57
  return structured;
52
58
  },
@@ -66,7 +72,12 @@ async function applyComposedPolicy(context, result, path) {
66
72
  if (!context) return;
67
73
  try {
68
74
  const outcome = await context.apply(result, path);
69
- if (outcome.acted) result.decision = outcome.decision;
75
+ if (outcome.acted) {
76
+ result.decision = outcome.decision;
77
+ if (outcome.composedBlobHash) {
78
+ result.composedBlobHash = outcome.composedBlobHash;
79
+ }
80
+ }
70
81
  } catch {
71
82
  }
72
83
  }
@@ -1,6 +1,7 @@
1
1
  import { NextRequest } from 'next/server';
2
2
  import { DidResolverAdapter, StatusListCacheAdapter, ReputationOracleAdapter, PolicyEvaluatorAdapter } from '@kya-os/checkpoint-wasm-runtime/adapters';
3
3
  import { EnforcementMode, VerifyResult, EngineConfig } from '@kya-os/checkpoint-wasm-runtime/engine';
4
+ import { ChallengeEnvelopeMode } from '@kya-os/checkpoint-shared';
4
5
  import { ComposedPolicyContext } from './composed-policy.mjs';
5
6
 
6
7
  /**
@@ -30,6 +31,14 @@ interface CheckpointConfig {
30
31
  * through with `X-Checkpoint-Would-Have-Been` headers. Per Phase 0.2.
31
32
  */
32
33
  enforcementMode?: EnforcementMode;
34
+ /**
35
+ * Challenge-emission envelope mode (draft-kya-http-02 §8.1 fetcher-200).
36
+ * `negotiated` serves a body-readable HTTP 200 step-up response to
37
+ * cooperative agents (fetchers that drop 4xx/5xx bodies), keeping the spec
38
+ * 401/422 for everyone else. Defaults to `spec-401`. A cooperative-UX
39
+ * bridge, NOT an access control.
40
+ */
41
+ delegationChallengeMode?: ChallengeEnvelopeMode;
33
42
  /**
34
43
  * Argus reputation oracle base URL. Omit to use the trust-by-default
35
44
  * baseline (reputation defaults to 1.0; orchestrator logs a one-shot
@@ -1,6 +1,7 @@
1
1
  import { NextRequest } from 'next/server';
2
2
  import { DidResolverAdapter, StatusListCacheAdapter, ReputationOracleAdapter, PolicyEvaluatorAdapter } from '@kya-os/checkpoint-wasm-runtime/adapters';
3
3
  import { EnforcementMode, VerifyResult, EngineConfig } from '@kya-os/checkpoint-wasm-runtime/engine';
4
+ import { ChallengeEnvelopeMode } from '@kya-os/checkpoint-shared';
4
5
  import { ComposedPolicyContext } from './composed-policy.js';
5
6
 
6
7
  /**
@@ -30,6 +31,14 @@ interface CheckpointConfig {
30
31
  * through with `X-Checkpoint-Would-Have-Been` headers. Per Phase 0.2.
31
32
  */
32
33
  enforcementMode?: EnforcementMode;
34
+ /**
35
+ * Challenge-emission envelope mode (draft-kya-http-02 §8.1 fetcher-200).
36
+ * `negotiated` serves a body-readable HTTP 200 step-up response to
37
+ * cooperative agents (fetchers that drop 4xx/5xx bodies), keeping the spec
38
+ * 401/422 for everyone else. Defaults to `spec-401`. A cooperative-UX
39
+ * bridge, NOT an access control.
40
+ */
41
+ delegationChallengeMode?: ChallengeEnvelopeMode;
33
42
  /**
34
43
  * Argus reputation oracle base URL. Omit to use the trust-by-default
35
44
  * baseline (reputation defaults to 1.0; orchestrator logs a one-shot
package/dist/index.d.mts CHANGED
@@ -6,7 +6,7 @@ export { EdgeSessionTracker, SessionData, SessionTrackingConfig, StatelessSessio
6
6
  export { AgentShieldClient, AgentShieldClientConfig, CheckpointApiClient, CheckpointApiClientConfig, EnforceInput, EnforceResponse, EnforcementDecision, LogDetectionInput, getAgentShieldClient, getCheckpointApiClient, resetAgentShieldClient, resetCheckpointApiClient } from './api-client.mjs';
7
7
  export { A as AgentShieldRequest, D as DetectionContext, N as NextJSMiddlewareConfig } from './types-D9RQvPNy.mjs';
8
8
  export { NextJSPolicyMiddlewareConfig, PolicyMiddlewareConfig, applyPolicy, buildBlockedResponse as buildPolicyBlockedResponse, buildRedirectResponse as buildPolicyRedirectResponse, createContextFromDetection, evaluatePolicyForDetection, getPolicy, handlePolicyDecision } from './policy.mjs';
9
- export { C as CheckpointConfig } from './config-_nfPN3E3.mjs';
9
+ export { C as CheckpointConfig } from './config-DAwIA4DB.mjs';
10
10
  export { DEFAULT_POLICY, ENFORCEMENT_ACTIONS, EnforcementAction, PolicyConfig, PolicyEvaluationContext, PolicyEvaluationResult, createEvaluationContext, evaluatePolicy } from '@kya-os/checkpoint-shared';
11
11
  import '@kya-os/checkpoint-wasm-runtime/engine';
12
12
  import '@kya-os/checkpoint-wasm-runtime/adapters';
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ export { EdgeSessionTracker, SessionData, SessionTrackingConfig, StatelessSessio
6
6
  export { AgentShieldClient, AgentShieldClientConfig, CheckpointApiClient, CheckpointApiClientConfig, EnforceInput, EnforceResponse, EnforcementDecision, LogDetectionInput, getAgentShieldClient, getCheckpointApiClient, resetAgentShieldClient, resetCheckpointApiClient } from './api-client.js';
7
7
  export { A as AgentShieldRequest, D as DetectionContext, N as NextJSMiddlewareConfig } from './types-D9RQvPNy.js';
8
8
  export { NextJSPolicyMiddlewareConfig, PolicyMiddlewareConfig, applyPolicy, buildBlockedResponse as buildPolicyBlockedResponse, buildRedirectResponse as buildPolicyRedirectResponse, createContextFromDetection, evaluatePolicyForDetection, getPolicy, handlePolicyDecision } from './policy.js';
9
- export { C as CheckpointConfig } from './config-kxFihzR_.js';
9
+ export { C as CheckpointConfig } from './config-DyU4l5er.js';
10
10
  export { DEFAULT_POLICY, ENFORCEMENT_ACTIONS, EnforcementAction, PolicyConfig, PolicyEvaluationContext, PolicyEvaluationResult, createEvaluationContext, evaluatePolicy } from '@kya-os/checkpoint-shared';
11
11
  import '@kya-os/checkpoint-wasm-runtime/engine';
12
12
  import '@kya-os/checkpoint-wasm-runtime/adapters';
package/dist/index.js CHANGED
@@ -100,7 +100,13 @@ function makeComposedPolicyContext(opts) {
100
100
  return structured;
101
101
  }
102
102
  if (outcome.status === "acting") {
103
- return { decision: outcome.engineDecision, acted: true };
103
+ return {
104
+ decision: outcome.engineDecision,
105
+ acted: true,
106
+ // Echo the SSOT revision pin with the decision it produced (#3246
107
+ // PR5). Conditional spread: absent upstream stays absent here.
108
+ ...policy.policySourceHash ? { composedBlobHash: policy.policySourceHash } : {}
109
+ };
104
110
  }
105
111
  return structured;
106
112
  },
@@ -120,7 +126,12 @@ async function applyComposedPolicy(context, result, path) {
120
126
  if (!context) return;
121
127
  try {
122
128
  const outcome = await context.apply(result, path);
123
- if (outcome.acted) result.decision = outcome.decision;
129
+ if (outcome.acted) {
130
+ result.decision = outcome.decision;
131
+ if (outcome.composedBlobHash) {
132
+ result.composedBlobHash = outcome.composedBlobHash;
133
+ }
134
+ }
124
135
  } catch {
125
136
  }
126
137
  }
@@ -201,12 +212,17 @@ function withCheckpoint(config) {
201
212
  }
202
213
  }
203
214
  await dispatchOnResult(config, result, req);
204
- const rendered = orchestrator.renderDecisionAsResponse(result);
215
+ const bodyReadable200 = checkpointShared.selectBodyReadable200(
216
+ config.delegationChallengeMode ?? "spec-401",
217
+ req.headers,
218
+ result.detectionDetail.detectionClass
219
+ );
220
+ const rendered = orchestrator.renderDecisionAsResponse(result, { bodyReadable200 });
205
221
  return adaptToNextResponse(rendered, req);
206
222
  };
207
223
  }
208
224
  var SDK_NAME = "@kya-os/checkpoint-nextjs";
209
- var VERSION = "1.7.0";
225
+ var VERSION = "1.7.1";
210
226
  function buildReporter(config, runtime = "node") {
211
227
  if (!config.apiKey) return null;
212
228
  return reporter.makeDetectionReporter({
@@ -552,7 +568,7 @@ function safeHostname(url) {
552
568
  // src/responses/agent-instruction.ts
553
569
  var MCP_I_DOCS_URL = "https://docs.knowthat.ai/mcp-i/getting-started";
554
570
  var DEFAULT_CONNECT_PATH = "/connect";
555
- function buildAgentInstructionResponse(request, decision, redirectUrl) {
571
+ function buildAgentInstructionResponse(request, decision, redirectUrl, options) {
556
572
  const resolved = resolveUrl(redirectUrl ?? DEFAULT_CONNECT_PATH, request.url);
557
573
  const agentName = decision.agentName || decision.agentType || "unknown";
558
574
  if (!resolved.searchParams.has("agent")) {
@@ -603,8 +619,11 @@ It only takes a moment and you won't need to do it again. Once you're done, ask
603
619
  confidence: decision.confidence
604
620
  }
605
621
  };
606
- const response = server.NextResponse.json(body, { status: 401 });
607
- response.headers.set("WWW-Authenticate", `KYA realm="api", authorization_uri="${authUrl}"`);
622
+ const bodyReadable200 = options?.bodyReadable200 ?? false;
623
+ const response = server.NextResponse.json(body, { status: bodyReadable200 ? 200 : 401 });
624
+ if (!bodyReadable200) {
625
+ response.headers.set("WWW-Authenticate", `KYA realm="api", authorization_uri="${authUrl}"`);
626
+ }
608
627
  response.headers.set(
609
628
  "Link",
610
629
  `<${authUrl}>; rel="kya-authorize", <${MCP_I_DOCS_URL}>; rel="help"`
@@ -797,7 +816,14 @@ function withCheckpointApi(config = {}) {
797
816
  return buildRedirectResponse(request, decision, config);
798
817
  }
799
818
  const targetUrl = config.redirectUrl || decision.redirectUrl;
800
- return buildAgentInstructionResponse(request, decision, targetUrl);
819
+ const bodyReadable200 = checkpointShared.selectBodyReadable200(
820
+ config.delegationChallengeMode ?? "spec-401",
821
+ request.headers,
822
+ result.data.detection?.detectionClass
823
+ );
824
+ return buildAgentInstructionResponse(request, decision, targetUrl, {
825
+ bodyReadable200
826
+ });
801
827
  }
802
828
  case "challenge": {
803
829
  return buildRedirectResponse(request, decision, config);
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { verifyRequest, renderDecisionAsResponse } from '@kya-os/checkpoint-wasm-runtime/orchestrator';
2
2
  import { makeSystemClock, makePolicyEvaluator, makeReputationOracle, makeStatusListCache, makeDidResolver } from '@kya-os/checkpoint-wasm-runtime/adapters';
3
3
  import { makeDetectionReporter } from '@kya-os/checkpoint-wasm-runtime/reporter';
4
- import { PolicyFetcher, isKnownAiCrawler, createEvaluationContext, evaluatePolicy, ENFORCEMENT_ACTIONS, PolicyConfigSchema, DEFAULT_POLICY, matchPath, requestCarriesDelegationProof, acceptsHtml, encodeVerdictCookie, classifyResponseShape, BLOCKED_PATH, createPolicyFetcher, VERDICT_COOKIE_NAME } from '@kya-os/checkpoint-shared';
4
+ import { selectBodyReadable200, PolicyFetcher, isKnownAiCrawler, createEvaluationContext, evaluatePolicy, ENFORCEMENT_ACTIONS, PolicyConfigSchema, DEFAULT_POLICY, matchPath, requestCarriesDelegationProof, acceptsHtml, encodeVerdictCookie, classifyResponseShape, BLOCKED_PATH, createPolicyFetcher, VERDICT_COOKIE_NAME } from '@kya-os/checkpoint-shared';
5
5
  export { DEFAULT_POLICY, ENFORCEMENT_ACTIONS, createEvaluationContext, evaluatePolicy } from '@kya-os/checkpoint-shared';
6
6
  import { NextResponse } from 'next/server';
7
7
  import { makeComposedPolicyCache, evaluateComposedPolicy, verifyResultToAuthorizeInput } from '@kya-os/checkpoint-wasm-runtime/composed-policy';
@@ -99,7 +99,13 @@ function makeComposedPolicyContext(opts) {
99
99
  return structured;
100
100
  }
101
101
  if (outcome.status === "acting") {
102
- return { decision: outcome.engineDecision, acted: true };
102
+ return {
103
+ decision: outcome.engineDecision,
104
+ acted: true,
105
+ // Echo the SSOT revision pin with the decision it produced (#3246
106
+ // PR5). Conditional spread: absent upstream stays absent here.
107
+ ...policy.policySourceHash ? { composedBlobHash: policy.policySourceHash } : {}
108
+ };
103
109
  }
104
110
  return structured;
105
111
  },
@@ -119,7 +125,12 @@ async function applyComposedPolicy(context, result, path) {
119
125
  if (!context) return;
120
126
  try {
121
127
  const outcome = await context.apply(result, path);
122
- if (outcome.acted) result.decision = outcome.decision;
128
+ if (outcome.acted) {
129
+ result.decision = outcome.decision;
130
+ if (outcome.composedBlobHash) {
131
+ result.composedBlobHash = outcome.composedBlobHash;
132
+ }
133
+ }
123
134
  } catch {
124
135
  }
125
136
  }
@@ -200,12 +211,17 @@ function withCheckpoint(config) {
200
211
  }
201
212
  }
202
213
  await dispatchOnResult(config, result, req);
203
- const rendered = renderDecisionAsResponse(result);
214
+ const bodyReadable200 = selectBodyReadable200(
215
+ config.delegationChallengeMode ?? "spec-401",
216
+ req.headers,
217
+ result.detectionDetail.detectionClass
218
+ );
219
+ const rendered = renderDecisionAsResponse(result, { bodyReadable200 });
204
220
  return adaptToNextResponse(rendered, req);
205
221
  };
206
222
  }
207
223
  var SDK_NAME = "@kya-os/checkpoint-nextjs";
208
- var VERSION = "1.7.0";
224
+ var VERSION = "1.7.1";
209
225
  function buildReporter(config, runtime = "node") {
210
226
  if (!config.apiKey) return null;
211
227
  return makeDetectionReporter({
@@ -551,7 +567,7 @@ function safeHostname(url) {
551
567
  // src/responses/agent-instruction.ts
552
568
  var MCP_I_DOCS_URL = "https://docs.knowthat.ai/mcp-i/getting-started";
553
569
  var DEFAULT_CONNECT_PATH = "/connect";
554
- function buildAgentInstructionResponse(request, decision, redirectUrl) {
570
+ function buildAgentInstructionResponse(request, decision, redirectUrl, options) {
555
571
  const resolved = resolveUrl(redirectUrl ?? DEFAULT_CONNECT_PATH, request.url);
556
572
  const agentName = decision.agentName || decision.agentType || "unknown";
557
573
  if (!resolved.searchParams.has("agent")) {
@@ -602,8 +618,11 @@ It only takes a moment and you won't need to do it again. Once you're done, ask
602
618
  confidence: decision.confidence
603
619
  }
604
620
  };
605
- const response = NextResponse.json(body, { status: 401 });
606
- response.headers.set("WWW-Authenticate", `KYA realm="api", authorization_uri="${authUrl}"`);
621
+ const bodyReadable200 = options?.bodyReadable200 ?? false;
622
+ const response = NextResponse.json(body, { status: bodyReadable200 ? 200 : 401 });
623
+ if (!bodyReadable200) {
624
+ response.headers.set("WWW-Authenticate", `KYA realm="api", authorization_uri="${authUrl}"`);
625
+ }
607
626
  response.headers.set(
608
627
  "Link",
609
628
  `<${authUrl}>; rel="kya-authorize", <${MCP_I_DOCS_URL}>; rel="help"`
@@ -796,7 +815,14 @@ function withCheckpointApi(config = {}) {
796
815
  return buildRedirectResponse(request, decision, config);
797
816
  }
798
817
  const targetUrl = config.redirectUrl || decision.redirectUrl;
799
- return buildAgentInstructionResponse(request, decision, targetUrl);
818
+ const bodyReadable200 = selectBodyReadable200(
819
+ config.delegationChallengeMode ?? "spec-401",
820
+ request.headers,
821
+ result.data.detection?.detectionClass
822
+ );
823
+ return buildAgentInstructionResponse(request, decision, targetUrl, {
824
+ bodyReadable200
825
+ });
800
826
  }
801
827
  case "challenge": {
802
828
  return buildRedirectResponse(request, decision, config);
@@ -1,12 +1,12 @@
1
1
  import { NextRequest, NextFetchEvent, NextResponse } from 'next/server';
2
2
  export { initEngineEdge } from '@kya-os/checkpoint-wasm-runtime/orchestrator/edge';
3
3
  export { initPolicyEvaluatorEdge } from '@kya-os/checkpoint-wasm-runtime/policy-edge';
4
- import { C as CheckpointConfig } from './config-_nfPN3E3.mjs';
4
+ import { C as CheckpointConfig } from './config-DAwIA4DB.mjs';
5
5
  import '@kya-os/checkpoint-wasm-runtime/adapters';
6
6
  import '@kya-os/checkpoint-wasm-runtime/engine';
7
+ import '@kya-os/checkpoint-shared';
7
8
  import './composed-policy.mjs';
8
9
  import '@kya-os/checkpoint-wasm-runtime/composed-policy';
9
- import '@kya-os/checkpoint-shared';
10
10
 
11
11
  /**
12
12
  * D.3 — Edge-runtime Next.js middleware entry.
@@ -1,12 +1,12 @@
1
1
  import { NextRequest, NextFetchEvent, NextResponse } from 'next/server';
2
2
  export { initEngineEdge } from '@kya-os/checkpoint-wasm-runtime/orchestrator/edge';
3
3
  export { initPolicyEvaluatorEdge } from '@kya-os/checkpoint-wasm-runtime/policy-edge';
4
- import { C as CheckpointConfig } from './config-kxFihzR_.js';
4
+ import { C as CheckpointConfig } from './config-DyU4l5er.js';
5
5
  import '@kya-os/checkpoint-wasm-runtime/adapters';
6
6
  import '@kya-os/checkpoint-wasm-runtime/engine';
7
+ import '@kya-os/checkpoint-shared';
7
8
  import './composed-policy.js';
8
9
  import '@kya-os/checkpoint-wasm-runtime/composed-policy';
9
- import '@kya-os/checkpoint-shared';
10
10
 
11
11
  /**
12
12
  * D.3 — Edge-runtime Next.js middleware entry.
@@ -102,7 +102,13 @@ function makeComposedPolicyContext(opts) {
102
102
  return structured;
103
103
  }
104
104
  if (outcome.status === "acting") {
105
- return { decision: outcome.engineDecision, acted: true };
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
+ };
106
112
  }
107
113
  return structured;
108
114
  },
@@ -122,7 +128,12 @@ async function applyComposedPolicy(context, result, path) {
122
128
  if (!context) return;
123
129
  try {
124
130
  const outcome = await context.apply(result, path);
125
- if (outcome.acted) result.decision = outcome.decision;
131
+ if (outcome.acted) {
132
+ result.decision = outcome.decision;
133
+ if (outcome.composedBlobHash) {
134
+ result.composedBlobHash = outcome.composedBlobHash;
135
+ }
136
+ }
126
137
  } catch {
127
138
  }
128
139
  }
@@ -180,7 +191,7 @@ function extractRemoteAddress(req) {
180
191
 
181
192
  // src/middleware-node.ts
182
193
  var SDK_NAME = "@kya-os/checkpoint-nextjs";
183
- var VERSION = "1.7.0";
194
+ var VERSION = "1.7.1";
184
195
  function buildReporter(config, runtime = "node") {
185
196
  if (!config.apiKey) return null;
186
197
  return reporter.makeDetectionReporter({
@@ -258,7 +269,12 @@ function withCheckpoint(config) {
258
269
  }
259
270
  }
260
271
  await dispatchOnResult(config, result, req);
261
- 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 });
262
278
  return adaptToNextResponse(rendered, req);
263
279
  };
264
280
  }
@@ -2,7 +2,7 @@ import { initEngineEdge, verifyRequestEdge, renderDecisionAsResponse } from '@ky
2
2
  export { initEngineEdge } from '@kya-os/checkpoint-wasm-runtime/orchestrator/edge';
3
3
  import { initPolicyEvaluatorEdge, evaluatePolicy } from '@kya-os/checkpoint-wasm-runtime/policy-edge';
4
4
  export { initPolicyEvaluatorEdge } from '@kya-os/checkpoint-wasm-runtime/policy-edge';
5
- import { PolicyFetcher, requestCarriesDelegationProof, acceptsHtml, encodeVerdictCookie, classifyResponseShape, BLOCKED_PATH, VERDICT_COOKIE_NAME } from '@kya-os/checkpoint-shared';
5
+ import { selectBodyReadable200, PolicyFetcher, requestCarriesDelegationProof, acceptsHtml, encodeVerdictCookie, classifyResponseShape, BLOCKED_PATH, VERDICT_COOKIE_NAME } from '@kya-os/checkpoint-shared';
6
6
  import { NextResponse } from 'next/server';
7
7
  import { makeComposedPolicyCache, evaluateComposedPolicy, verifyResultToAuthorizeInput } from '@kya-os/checkpoint-wasm-runtime/composed-policy';
8
8
  import '@kya-os/checkpoint-wasm-runtime/orchestrator';
@@ -102,7 +102,13 @@ function makeComposedPolicyContext(opts) {
102
102
  return structured;
103
103
  }
104
104
  if (outcome.status === "acting") {
105
- return { decision: outcome.engineDecision, acted: true };
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
+ };
106
112
  }
107
113
  return structured;
108
114
  },
@@ -122,7 +128,12 @@ async function applyComposedPolicy(context, result, path) {
122
128
  if (!context) return;
123
129
  try {
124
130
  const outcome = await context.apply(result, path);
125
- if (outcome.acted) result.decision = outcome.decision;
131
+ if (outcome.acted) {
132
+ result.decision = outcome.decision;
133
+ if (outcome.composedBlobHash) {
134
+ result.composedBlobHash = outcome.composedBlobHash;
135
+ }
136
+ }
126
137
  } catch {
127
138
  }
128
139
  }
@@ -180,7 +191,7 @@ function extractRemoteAddress(req) {
180
191
 
181
192
  // src/middleware-node.ts
182
193
  var SDK_NAME = "@kya-os/checkpoint-nextjs";
183
- var VERSION = "1.7.0";
194
+ var VERSION = "1.7.1";
184
195
  function buildReporter(config, runtime = "node") {
185
196
  if (!config.apiKey) return null;
186
197
  return makeDetectionReporter({
@@ -258,7 +269,12 @@ function withCheckpoint(config) {
258
269
  }
259
270
  }
260
271
  await dispatchOnResult(config, result, req);
261
- 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 });
262
278
  return adaptToNextResponse(rendered, req);
263
279
  };
264
280
  }