@kya-os/checkpoint-wasm-runtime 1.5.0 → 1.6.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 +215 -0
- package/dist/engine-edge.d.mts +52 -16
- package/dist/engine-edge.d.ts +52 -16
- package/dist/engine-edge.js +11 -4
- package/dist/engine-edge.mjs +11 -4
- package/dist/index.d.mts +118 -1
- package/dist/index.d.ts +118 -1
- package/dist/orchestrator-edge.js +46 -13
- package/dist/orchestrator-edge.mjs +46 -13
- package/dist/orchestrator-node.js +35 -9
- package/dist/orchestrator-node.mjs +35 -9
- package/dist/orchestrator.d.mts +52 -16
- package/dist/orchestrator.d.ts +52 -16
- package/dist/orchestrator.js +46 -13
- package/dist/orchestrator.mjs +46 -13
- package/dist/policy.d.mts +148 -0
- package/dist/policy.d.ts +148 -0
- package/dist/policy.js +52 -0
- package/dist/policy.mjs +53 -0
- package/dist/reporter.d.mts +102 -0
- package/dist/reporter.d.ts +102 -0
- package/dist/reporter.js +125 -0
- package/dist/reporter.mjs +122 -0
- package/package.json +15 -5
- package/wasm/kya-os-engine/kya_os_engine_bg.wasm +0 -0
- package/wasm/kya-os-engine/package.json +4 -2
- package/wasm/kya-os-engine-bundler/kya_os_engine_bg.wasm +0 -0
- package/wasm/kya-os-engine-cedar/README.md +26 -0
- package/wasm/kya-os-engine-cedar/kya_os_engine.d.ts +77 -0
- package/wasm/kya-os-engine-cedar/kya_os_engine.js +636 -0
- package/wasm/kya-os-engine-cedar/kya_os_engine_bg.wasm +0 -0
- package/wasm/kya-os-engine-cedar/kya_os_engine_bg.wasm.d.ts +11 -0
- package/wasm/kya-os-engine-cedar/package.json +29 -0
- package/wasm/kya-os-engine-cedar-web/README.md +26 -0
- package/wasm/kya-os-engine-cedar-web/kya_os_engine.d.ts +117 -0
- package/wasm/kya-os-engine-cedar-web/kya_os_engine.js +694 -0
- package/wasm/kya-os-engine-cedar-web/kya_os_engine_bg.wasm +0 -0
- package/wasm/kya-os-engine-cedar-web/kya_os_engine_bg.wasm.d.ts +11 -0
- package/wasm/kya-os-engine-cedar-web/package.json +31 -0
- package/wasm/kya-os-engine-web/kya_os_engine_bg.wasm +0 -0
- package/wasm/kya-os-engine-web/package.json +5 -3
- package/wasm/agentshield_wasm.d.ts +0 -485
- package/wasm/agentshield_wasm.js +0 -1551
- package/wasm/agentshield_wasm_bg.wasm +0 -0
- package/wasm/agentshield_wasm_bg.wasm.d.ts +0 -97
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { D as Decision } from './types-C3RniIOM.js';
|
|
2
|
+
export { B as BlockReason } from './types-C3RniIOM.js';
|
|
3
|
+
import '@kya-os/checkpoint-shared';
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
6
|
* AgentShield WASM Runtime Types
|
|
3
7
|
*
|
|
@@ -598,6 +602,119 @@ declare class RulesDetector implements IDetector {
|
|
|
598
602
|
*/
|
|
599
603
|
declare function createRulesDetector(): RulesDetector;
|
|
600
604
|
|
|
605
|
+
/**
|
|
606
|
+
* Cedar policy-evaluator bridge — Node fallback.
|
|
607
|
+
*
|
|
608
|
+
* Surfaces the `PolicyEvaluator` class exported by the cedar-enabled
|
|
609
|
+
* `kya-os-engine` WASM artifact (built by
|
|
610
|
+
* `rust/scripts/build-engine-cedar-wasm.sh`, gated on the Rust
|
|
611
|
+
* `wasm,cedar` features). A JS host (the gateway) compiles a tenant
|
|
612
|
+
* policy bundle once and authorizes many requests against it in-process,
|
|
613
|
+
* with no round-trip to a separate policy service.
|
|
614
|
+
*
|
|
615
|
+
* The cedar artifact is a SEPARATE, larger binary than the lean
|
|
616
|
+
* detection artifact — it pulls in `cedar-policy`. Detection-only
|
|
617
|
+
* consumers load `./engine` (the lean `verify()` glue); only callers that
|
|
618
|
+
* need in-process authorization reach for this bridge.
|
|
619
|
+
*
|
|
620
|
+
* ## Lazy loading
|
|
621
|
+
*
|
|
622
|
+
* The cedar `--target nodejs` glue instantiates the ~2 MB cedar WASM the
|
|
623
|
+
* moment it is `require`d (it `fs.readFileSync`s its `.wasm` sibling at
|
|
624
|
+
* module load). To keep the separate-artifact promise — detection-only
|
|
625
|
+
* consumers must NOT pay cedar's memory/startup — the glue is loaded
|
|
626
|
+
* LAZILY: nothing happens on `import`; the artifact is `require`d (and
|
|
627
|
+
* memoised) only on the first {@link createPolicyEvaluator} call. This is
|
|
628
|
+
* also why cedar lives behind the dedicated `./policy` subpath and is NOT
|
|
629
|
+
* re-exported from the `./node` barrel.
|
|
630
|
+
*
|
|
631
|
+
* `createRequire(__filename)` resolves the glue at call time in both
|
|
632
|
+
* builds — native `require` under CJS, the tsup `shims` / `createRequire`
|
|
633
|
+
* banner under ESM. The glue stays external (regex
|
|
634
|
+
* `wasm/kya-os-engine-cedar/` in tsup's `commonOpts.external`), so its
|
|
635
|
+
* `__dirname` resolves against `node_modules/.../wasm/kya-os-engine-cedar/`
|
|
636
|
+
* where the `.wasm` lives, and `"type": "commonjs"` on the artifact's
|
|
637
|
+
* package.json keeps Node from throwing `ERR_REQUIRE_ESM`.
|
|
638
|
+
*
|
|
639
|
+
* Direct .wasm path (for callers building their own loaders):
|
|
640
|
+
* `@kya-os/checkpoint-wasm-runtime/wasm/kya-os-engine-cedar/kya_os_engine_bg.wasm`
|
|
641
|
+
*/
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Owned, plain-data request the host hands to
|
|
645
|
+
* {@link PolicyEvaluatorRuntime.authorize}. Mirrors the Rust
|
|
646
|
+
* `AuthorizeInput` (`rust/crates/kya-os-engine/src/policy/authorize.rs`);
|
|
647
|
+
* keys are camelCase across the wasm-bindgen boundary, matching every
|
|
648
|
+
* other engine wire type.
|
|
649
|
+
*
|
|
650
|
+
* The evaluator is **synchronous over pre-resolved facts** (H-1 Kickoff
|
|
651
|
+
* § 4.5): the host pre-fetches the agent's delegation chain, reputation,
|
|
652
|
+
* etc. and ships the results here — no JS callbacks cross the boundary.
|
|
653
|
+
*
|
|
654
|
+
* `agentDid` and `reputation` are optional (omit or pass `undefined` for
|
|
655
|
+
* an anonymous or reputation-less request); `grantedScopes` defaults to an
|
|
656
|
+
* empty list when omitted.
|
|
657
|
+
*/
|
|
658
|
+
interface AuthorizeInput {
|
|
659
|
+
/** Agent DID if identity has been established, otherwise omitted. */
|
|
660
|
+
agentDid?: string;
|
|
661
|
+
/** The action being requested (e.g., `"book_flight"`). */
|
|
662
|
+
action: string;
|
|
663
|
+
/** The resource being acted on (e.g., `"travel_api"`). */
|
|
664
|
+
resource: string;
|
|
665
|
+
/** Scopes granted by the agent's delegation chain. Defaults to `[]`. */
|
|
666
|
+
grantedScopes?: string[];
|
|
667
|
+
/** Agent's reputation score in `[0.0, 1.0]`, if computed. */
|
|
668
|
+
reputation?: number;
|
|
669
|
+
/** Tenant identifier. */
|
|
670
|
+
tenantId: string;
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Structural type of the WASM `PolicyEvaluator` class the cedar glue
|
|
674
|
+
* exports. Pinned here so this bridge type-checks against the artifact's
|
|
675
|
+
* `.d.ts` (`constructor(policy_text: string)`, `authorize(input): any`,
|
|
676
|
+
* `free()`).
|
|
677
|
+
*/
|
|
678
|
+
interface WasmPolicyEvaluator {
|
|
679
|
+
authorize(input: AuthorizeInput): unknown;
|
|
680
|
+
free(): void;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Host-facing wrapper around one compiled Cedar policy bundle.
|
|
684
|
+
*
|
|
685
|
+
* Construction compiles the bundle once; every {@link authorize} call
|
|
686
|
+
* evaluates a single owned request against it without re-parsing policy
|
|
687
|
+
* text (the compile-once / evaluate-many contract the engine upholds,
|
|
688
|
+
* carried across the boundary).
|
|
689
|
+
*/
|
|
690
|
+
declare class PolicyEvaluatorRuntime {
|
|
691
|
+
private readonly inner;
|
|
692
|
+
/**
|
|
693
|
+
* @param inner - The compiled WASM `PolicyEvaluator` handle. Built in
|
|
694
|
+
* {@link createPolicyEvaluator}; reused by every {@link authorize}
|
|
695
|
+
* call for the lifetime of this wrapper.
|
|
696
|
+
*/
|
|
697
|
+
constructor(inner: WasmPolicyEvaluator);
|
|
698
|
+
/**
|
|
699
|
+
* Authorize one owned request against the compiled policy bundle.
|
|
700
|
+
*
|
|
701
|
+
* The evaluator owns the fail-closed posture — a request it cannot
|
|
702
|
+
* marshal into Cedar, or one matching no `permit`, comes back as a
|
|
703
|
+
* {@link Decision} `Block` (not a thrown error). Authorization
|
|
704
|
+
* *verdicts* never throw; they surface inside the returned value.
|
|
705
|
+
*
|
|
706
|
+
* @throws {Error} only for boundary faults the WASM glue rejects: a
|
|
707
|
+
* malformed `input` that fails `AuthorizeInput` deserialisation, or a
|
|
708
|
+
* failure serialising the resulting `Decision`.
|
|
709
|
+
*/
|
|
710
|
+
authorize(input: AuthorizeInput): Decision;
|
|
711
|
+
/**
|
|
712
|
+
* Release the compiled bundle's WASM memory. Call when the evaluator is
|
|
713
|
+
* no longer needed; after this the wrapper must not be reused.
|
|
714
|
+
*/
|
|
715
|
+
free(): void;
|
|
716
|
+
}
|
|
717
|
+
|
|
601
718
|
/**
|
|
602
719
|
* Create a detector with automatic runtime selection
|
|
603
720
|
*
|
|
@@ -650,4 +767,4 @@ declare function createEdgeDetector(wasmModule: WebAssembly.Module, options?: ID
|
|
|
650
767
|
*/
|
|
651
768
|
declare function createFallbackDetector(): IDetector;
|
|
652
769
|
|
|
653
|
-
export { CONFIDENCE, type DetectionClass, DynamicWasmLoader, type ForgeabilityRisk, type ICustomerPolicy, type IDetectedAgent, type IDetectionInput, type IDetectionResult, type IDetector, type IDetectorOptions, type IPathRule, type IPolicyLoader, type IWasmBindings, type IWasmLoader, PolicyLoadError, PolicyLoader, type PolicyLoaderConfig, RulesDetector, StaticWasmLoader, type VerificationMethod, WasmDetector, createDetector, createDynamicLoader, createEdgeDetector, createFallbackDetector, createPolicyLoader, createRulesDetector, createStaticLoader };
|
|
770
|
+
export { type AuthorizeInput, CONFIDENCE, Decision, type DetectionClass, DynamicWasmLoader, type ForgeabilityRisk, type ICustomerPolicy, type IDetectedAgent, type IDetectionInput, type IDetectionResult, type IDetector, type IDetectorOptions, type IPathRule, type IPolicyLoader, type IWasmBindings, type IWasmLoader, PolicyEvaluatorRuntime, PolicyLoadError, PolicyLoader, type PolicyLoaderConfig, RulesDetector, StaticWasmLoader, type VerificationMethod, WasmDetector, createDetector, createDynamicLoader, createEdgeDetector, createFallbackDetector, createPolicyLoader, createRulesDetector, createStaticLoader };
|
|
@@ -77,20 +77,27 @@ function isBlockedIpv6(hostname) {
|
|
|
77
77
|
|
|
78
78
|
// src/engine/edge.ts
|
|
79
79
|
var initialised = null;
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
var providedModule;
|
|
81
|
+
function initEngineEdge(wasmModule) {
|
|
82
|
+
if (wasmModule !== void 0 && providedModule === void 0) {
|
|
83
|
+
providedModule = wasmModule;
|
|
84
|
+
}
|
|
85
|
+
return ensureReady().then(() => void 0);
|
|
82
86
|
}
|
|
83
|
-
function ensureReady(
|
|
87
|
+
function ensureReady() {
|
|
84
88
|
if (initialised) return initialised;
|
|
85
89
|
const pending = (async () => {
|
|
86
90
|
const mod = await import('@kya-os/checkpoint-wasm-runtime/wasm/kya-os-engine-web/kya_os_engine.js');
|
|
87
|
-
await mod.default(
|
|
91
|
+
await mod.default(
|
|
92
|
+
providedModule !== void 0 ? { module_or_path: providedModule } : void 0
|
|
93
|
+
);
|
|
88
94
|
return mod.verify;
|
|
89
95
|
})();
|
|
90
96
|
initialised = pending;
|
|
91
97
|
pending.catch(() => {
|
|
92
98
|
if (initialised === pending) {
|
|
93
99
|
initialised = null;
|
|
100
|
+
providedModule = void 0;
|
|
94
101
|
}
|
|
95
102
|
});
|
|
96
103
|
return initialised;
|
|
@@ -191,21 +198,30 @@ function parseBodyAsObject(body) {
|
|
|
191
198
|
function tryBuildMcpIFromLegacyHeader(req) {
|
|
192
199
|
const header = getHeader(req, "kya-delegation");
|
|
193
200
|
if (!header) return null;
|
|
194
|
-
let parsed;
|
|
201
|
+
let parsed = void 0;
|
|
195
202
|
try {
|
|
196
203
|
parsed = JSON.parse(header);
|
|
197
204
|
} catch {
|
|
198
|
-
return null;
|
|
199
205
|
}
|
|
200
|
-
if (
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
+
if (parsed && typeof parsed === "object") {
|
|
207
|
+
const obj = parsed;
|
|
208
|
+
const protectedSeg = obj.protected;
|
|
209
|
+
const payloadSeg = obj.payload;
|
|
210
|
+
const signatureSeg = obj.signature;
|
|
211
|
+
if (typeof protectedSeg === "string" && typeof payloadSeg === "string" && typeof signatureSeg === "string") {
|
|
212
|
+
const compact = `${protectedSeg}.${payloadSeg}.${signatureSeg}`;
|
|
213
|
+
return buildMcpIRequestFromCompact(compact);
|
|
214
|
+
}
|
|
206
215
|
return null;
|
|
207
216
|
}
|
|
208
|
-
const
|
|
217
|
+
const trimmed = header.trim();
|
|
218
|
+
if (COMPACT_JWS_PATTERN.test(trimmed)) {
|
|
219
|
+
return buildMcpIRequestFromCompact(trimmed);
|
|
220
|
+
}
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
var COMPACT_JWS_PATTERN = /^[A-Za-z0-9_-]+=*\.[A-Za-z0-9_-]+=*\.[A-Za-z0-9_-]+=*$/;
|
|
224
|
+
function buildMcpIRequestFromCompact(compact) {
|
|
209
225
|
const raw = Array.from(Buffer.from(compact, "utf8"));
|
|
210
226
|
const payload = parseJwsPayloadStruct(raw);
|
|
211
227
|
if (!payload) return null;
|
|
@@ -404,6 +420,23 @@ function buildBaseHeaders(result) {
|
|
|
404
420
|
if (result.engineInfo.rulesetHash) {
|
|
405
421
|
headers["X-Checkpoint-Ruleset-Hash"] = result.engineInfo.rulesetHash;
|
|
406
422
|
}
|
|
423
|
+
const meta = result.detectionDetail.metadata;
|
|
424
|
+
if (meta) {
|
|
425
|
+
const verifiedTier = meta.verified_tier;
|
|
426
|
+
if (typeof verifiedTier === "number" && Number.isFinite(verifiedTier)) {
|
|
427
|
+
headers["X-Checkpoint-Verified-Tier"] = String(verifiedTier);
|
|
428
|
+
} else if (typeof verifiedTier === "string" && verifiedTier.length > 0) {
|
|
429
|
+
headers["X-Checkpoint-Verified-Tier"] = verifiedTier;
|
|
430
|
+
}
|
|
431
|
+
const verifiedVendor = meta.verified_vendor;
|
|
432
|
+
if (typeof verifiedVendor === "string" && verifiedVendor.length > 0) {
|
|
433
|
+
headers["X-Checkpoint-Verified-Vendor"] = verifiedVendor;
|
|
434
|
+
}
|
|
435
|
+
const verifiedProtocol = meta.verified_protocol;
|
|
436
|
+
if (typeof verifiedProtocol === "string" && verifiedProtocol.length > 0) {
|
|
437
|
+
headers["X-Checkpoint-Verified-Protocol"] = verifiedProtocol;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
407
440
|
return headers;
|
|
408
441
|
}
|
|
409
442
|
function httpStatusForBlockReason(reason) {
|
|
@@ -75,20 +75,27 @@ function isBlockedIpv6(hostname) {
|
|
|
75
75
|
|
|
76
76
|
// src/engine/edge.ts
|
|
77
77
|
var initialised = null;
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
var providedModule;
|
|
79
|
+
function initEngineEdge(wasmModule) {
|
|
80
|
+
if (wasmModule !== void 0 && providedModule === void 0) {
|
|
81
|
+
providedModule = wasmModule;
|
|
82
|
+
}
|
|
83
|
+
return ensureReady().then(() => void 0);
|
|
80
84
|
}
|
|
81
|
-
function ensureReady(
|
|
85
|
+
function ensureReady() {
|
|
82
86
|
if (initialised) return initialised;
|
|
83
87
|
const pending = (async () => {
|
|
84
88
|
const mod = await import('@kya-os/checkpoint-wasm-runtime/wasm/kya-os-engine-web/kya_os_engine.js');
|
|
85
|
-
await mod.default(
|
|
89
|
+
await mod.default(
|
|
90
|
+
providedModule !== void 0 ? { module_or_path: providedModule } : void 0
|
|
91
|
+
);
|
|
86
92
|
return mod.verify;
|
|
87
93
|
})();
|
|
88
94
|
initialised = pending;
|
|
89
95
|
pending.catch(() => {
|
|
90
96
|
if (initialised === pending) {
|
|
91
97
|
initialised = null;
|
|
98
|
+
providedModule = void 0;
|
|
92
99
|
}
|
|
93
100
|
});
|
|
94
101
|
return initialised;
|
|
@@ -189,21 +196,30 @@ function parseBodyAsObject(body) {
|
|
|
189
196
|
function tryBuildMcpIFromLegacyHeader(req) {
|
|
190
197
|
const header = getHeader(req, "kya-delegation");
|
|
191
198
|
if (!header) return null;
|
|
192
|
-
let parsed;
|
|
199
|
+
let parsed = void 0;
|
|
193
200
|
try {
|
|
194
201
|
parsed = JSON.parse(header);
|
|
195
202
|
} catch {
|
|
196
|
-
return null;
|
|
197
203
|
}
|
|
198
|
-
if (
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
+
if (parsed && typeof parsed === "object") {
|
|
205
|
+
const obj = parsed;
|
|
206
|
+
const protectedSeg = obj.protected;
|
|
207
|
+
const payloadSeg = obj.payload;
|
|
208
|
+
const signatureSeg = obj.signature;
|
|
209
|
+
if (typeof protectedSeg === "string" && typeof payloadSeg === "string" && typeof signatureSeg === "string") {
|
|
210
|
+
const compact = `${protectedSeg}.${payloadSeg}.${signatureSeg}`;
|
|
211
|
+
return buildMcpIRequestFromCompact(compact);
|
|
212
|
+
}
|
|
204
213
|
return null;
|
|
205
214
|
}
|
|
206
|
-
const
|
|
215
|
+
const trimmed = header.trim();
|
|
216
|
+
if (COMPACT_JWS_PATTERN.test(trimmed)) {
|
|
217
|
+
return buildMcpIRequestFromCompact(trimmed);
|
|
218
|
+
}
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
var COMPACT_JWS_PATTERN = /^[A-Za-z0-9_-]+=*\.[A-Za-z0-9_-]+=*\.[A-Za-z0-9_-]+=*$/;
|
|
222
|
+
function buildMcpIRequestFromCompact(compact) {
|
|
207
223
|
const raw = Array.from(Buffer.from(compact, "utf8"));
|
|
208
224
|
const payload = parseJwsPayloadStruct(raw);
|
|
209
225
|
if (!payload) return null;
|
|
@@ -402,6 +418,23 @@ function buildBaseHeaders(result) {
|
|
|
402
418
|
if (result.engineInfo.rulesetHash) {
|
|
403
419
|
headers["X-Checkpoint-Ruleset-Hash"] = result.engineInfo.rulesetHash;
|
|
404
420
|
}
|
|
421
|
+
const meta = result.detectionDetail.metadata;
|
|
422
|
+
if (meta) {
|
|
423
|
+
const verifiedTier = meta.verified_tier;
|
|
424
|
+
if (typeof verifiedTier === "number" && Number.isFinite(verifiedTier)) {
|
|
425
|
+
headers["X-Checkpoint-Verified-Tier"] = String(verifiedTier);
|
|
426
|
+
} else if (typeof verifiedTier === "string" && verifiedTier.length > 0) {
|
|
427
|
+
headers["X-Checkpoint-Verified-Tier"] = verifiedTier;
|
|
428
|
+
}
|
|
429
|
+
const verifiedVendor = meta.verified_vendor;
|
|
430
|
+
if (typeof verifiedVendor === "string" && verifiedVendor.length > 0) {
|
|
431
|
+
headers["X-Checkpoint-Verified-Vendor"] = verifiedVendor;
|
|
432
|
+
}
|
|
433
|
+
const verifiedProtocol = meta.verified_protocol;
|
|
434
|
+
if (typeof verifiedProtocol === "string" && verifiedProtocol.length > 0) {
|
|
435
|
+
headers["X-Checkpoint-Verified-Protocol"] = verifiedProtocol;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
405
438
|
return headers;
|
|
406
439
|
}
|
|
407
440
|
function httpStatusForBlockReason(reason) {
|
|
@@ -194,21 +194,30 @@ function parseBodyAsObject(body) {
|
|
|
194
194
|
function tryBuildMcpIFromLegacyHeader(req) {
|
|
195
195
|
const header = getHeader(req, "kya-delegation");
|
|
196
196
|
if (!header) return null;
|
|
197
|
-
let parsed;
|
|
197
|
+
let parsed = void 0;
|
|
198
198
|
try {
|
|
199
199
|
parsed = JSON.parse(header);
|
|
200
200
|
} catch {
|
|
201
|
-
return null;
|
|
202
201
|
}
|
|
203
|
-
if (
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
202
|
+
if (parsed && typeof parsed === "object") {
|
|
203
|
+
const obj = parsed;
|
|
204
|
+
const protectedSeg = obj.protected;
|
|
205
|
+
const payloadSeg = obj.payload;
|
|
206
|
+
const signatureSeg = obj.signature;
|
|
207
|
+
if (typeof protectedSeg === "string" && typeof payloadSeg === "string" && typeof signatureSeg === "string") {
|
|
208
|
+
const compact = `${protectedSeg}.${payloadSeg}.${signatureSeg}`;
|
|
209
|
+
return buildMcpIRequestFromCompact(compact);
|
|
210
|
+
}
|
|
209
211
|
return null;
|
|
210
212
|
}
|
|
211
|
-
const
|
|
213
|
+
const trimmed = header.trim();
|
|
214
|
+
if (COMPACT_JWS_PATTERN.test(trimmed)) {
|
|
215
|
+
return buildMcpIRequestFromCompact(trimmed);
|
|
216
|
+
}
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
var COMPACT_JWS_PATTERN = /^[A-Za-z0-9_-]+=*\.[A-Za-z0-9_-]+=*\.[A-Za-z0-9_-]+=*$/;
|
|
220
|
+
function buildMcpIRequestFromCompact(compact) {
|
|
212
221
|
const raw = Array.from(Buffer.from(compact, "utf8"));
|
|
213
222
|
const payload = parseJwsPayloadStruct(raw);
|
|
214
223
|
if (!payload) return null;
|
|
@@ -508,6 +517,23 @@ function buildBaseHeaders(result) {
|
|
|
508
517
|
if (result.engineInfo.rulesetHash) {
|
|
509
518
|
headers["X-Checkpoint-Ruleset-Hash"] = result.engineInfo.rulesetHash;
|
|
510
519
|
}
|
|
520
|
+
const meta = result.detectionDetail.metadata;
|
|
521
|
+
if (meta) {
|
|
522
|
+
const verifiedTier = meta.verified_tier;
|
|
523
|
+
if (typeof verifiedTier === "number" && Number.isFinite(verifiedTier)) {
|
|
524
|
+
headers["X-Checkpoint-Verified-Tier"] = String(verifiedTier);
|
|
525
|
+
} else if (typeof verifiedTier === "string" && verifiedTier.length > 0) {
|
|
526
|
+
headers["X-Checkpoint-Verified-Tier"] = verifiedTier;
|
|
527
|
+
}
|
|
528
|
+
const verifiedVendor = meta.verified_vendor;
|
|
529
|
+
if (typeof verifiedVendor === "string" && verifiedVendor.length > 0) {
|
|
530
|
+
headers["X-Checkpoint-Verified-Vendor"] = verifiedVendor;
|
|
531
|
+
}
|
|
532
|
+
const verifiedProtocol = meta.verified_protocol;
|
|
533
|
+
if (typeof verifiedProtocol === "string" && verifiedProtocol.length > 0) {
|
|
534
|
+
headers["X-Checkpoint-Verified-Protocol"] = verifiedProtocol;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
511
537
|
return headers;
|
|
512
538
|
}
|
|
513
539
|
function httpStatusForBlockReason(reason) {
|
|
@@ -173,21 +173,30 @@ function parseBodyAsObject(body) {
|
|
|
173
173
|
function tryBuildMcpIFromLegacyHeader(req) {
|
|
174
174
|
const header = getHeader(req, "kya-delegation");
|
|
175
175
|
if (!header) return null;
|
|
176
|
-
let parsed;
|
|
176
|
+
let parsed = void 0;
|
|
177
177
|
try {
|
|
178
178
|
parsed = JSON.parse(header);
|
|
179
179
|
} catch {
|
|
180
|
-
return null;
|
|
181
180
|
}
|
|
182
|
-
if (
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
181
|
+
if (parsed && typeof parsed === "object") {
|
|
182
|
+
const obj = parsed;
|
|
183
|
+
const protectedSeg = obj.protected;
|
|
184
|
+
const payloadSeg = obj.payload;
|
|
185
|
+
const signatureSeg = obj.signature;
|
|
186
|
+
if (typeof protectedSeg === "string" && typeof payloadSeg === "string" && typeof signatureSeg === "string") {
|
|
187
|
+
const compact = `${protectedSeg}.${payloadSeg}.${signatureSeg}`;
|
|
188
|
+
return buildMcpIRequestFromCompact(compact);
|
|
189
|
+
}
|
|
188
190
|
return null;
|
|
189
191
|
}
|
|
190
|
-
const
|
|
192
|
+
const trimmed = header.trim();
|
|
193
|
+
if (COMPACT_JWS_PATTERN.test(trimmed)) {
|
|
194
|
+
return buildMcpIRequestFromCompact(trimmed);
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
var COMPACT_JWS_PATTERN = /^[A-Za-z0-9_-]+=*\.[A-Za-z0-9_-]+=*\.[A-Za-z0-9_-]+=*$/;
|
|
199
|
+
function buildMcpIRequestFromCompact(compact) {
|
|
191
200
|
const raw = Array.from(Buffer.from(compact, "utf8"));
|
|
192
201
|
const payload = parseJwsPayloadStruct(raw);
|
|
193
202
|
if (!payload) return null;
|
|
@@ -487,6 +496,23 @@ function buildBaseHeaders(result) {
|
|
|
487
496
|
if (result.engineInfo.rulesetHash) {
|
|
488
497
|
headers["X-Checkpoint-Ruleset-Hash"] = result.engineInfo.rulesetHash;
|
|
489
498
|
}
|
|
499
|
+
const meta = result.detectionDetail.metadata;
|
|
500
|
+
if (meta) {
|
|
501
|
+
const verifiedTier = meta.verified_tier;
|
|
502
|
+
if (typeof verifiedTier === "number" && Number.isFinite(verifiedTier)) {
|
|
503
|
+
headers["X-Checkpoint-Verified-Tier"] = String(verifiedTier);
|
|
504
|
+
} else if (typeof verifiedTier === "string" && verifiedTier.length > 0) {
|
|
505
|
+
headers["X-Checkpoint-Verified-Tier"] = verifiedTier;
|
|
506
|
+
}
|
|
507
|
+
const verifiedVendor = meta.verified_vendor;
|
|
508
|
+
if (typeof verifiedVendor === "string" && verifiedVendor.length > 0) {
|
|
509
|
+
headers["X-Checkpoint-Verified-Vendor"] = verifiedVendor;
|
|
510
|
+
}
|
|
511
|
+
const verifiedProtocol = meta.verified_protocol;
|
|
512
|
+
if (typeof verifiedProtocol === "string" && verifiedProtocol.length > 0) {
|
|
513
|
+
headers["X-Checkpoint-Verified-Protocol"] = verifiedProtocol;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
490
516
|
return headers;
|
|
491
517
|
}
|
|
492
518
|
function httpStatusForBlockReason(reason) {
|
package/dist/orchestrator.d.mts
CHANGED
|
@@ -222,11 +222,44 @@ interface RenderedResponse {
|
|
|
222
222
|
* no sync wasm load).
|
|
223
223
|
*
|
|
224
224
|
* This module loads the `wasm-pack --target web` artifact via the
|
|
225
|
-
* async `__wbg_init` default export
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
225
|
+
* async `__wbg_init` default export. The web target's `init()`
|
|
226
|
+
* accepts a pre-instantiated `WebAssembly.Module` argument — the
|
|
227
|
+
* canonical Cloudflare-Workers + wasm-bindgen pattern.
|
|
228
|
+
*
|
|
229
|
+
* # Why the caller MUST pass `wasmModule` on Cloudflare Workers
|
|
230
|
+
*
|
|
231
|
+
* Both `--target web` (URL fetch) and `--target bundler` (auto-
|
|
232
|
+
* instantiated `__wbg_set_wasm(wasm)`) have failure modes on wrangler:
|
|
233
|
+
*
|
|
234
|
+
* - `--target web` falls back to `new URL('<wasm>', import.meta.url)`
|
|
235
|
+
* when `init()` is called with no arg. Cloudflare Workers don't
|
|
236
|
+
* materialise `import.meta.url` the way browsers do → throws
|
|
237
|
+
* `TypeError: Invalid URL string`. (Broke production 2026-05-23,
|
|
238
|
+
* captured via dev tail in run 26352287112.)
|
|
239
|
+
*
|
|
240
|
+
* - `--target bundler` expects the host bundler to AUTO-INSTANTIATE
|
|
241
|
+
* `import * as wasm from './foo.wasm'` so `wasm` is the
|
|
242
|
+
* `Instance.exports` object. Webpack does this. **Wrangler does
|
|
243
|
+
* NOT** — wrangler gives you a raw `WebAssembly.Module`, and the
|
|
244
|
+
* bundler-target shim's `__wbg_set_wasm(rawModule)` happily
|
|
245
|
+
* accepts it, then every export lookup (`wasm.__wbindgen_add_
|
|
246
|
+
* to_stack_pointer`, etc.) returns undefined → throws
|
|
247
|
+
* `TypeError: wasm.__wbindgen_add_to_stack_pointer is not a function`.
|
|
248
|
+
* (Broke production 2026-05-24 after switching to bundler target
|
|
249
|
+
* in PR #2785; captured via prod tail.)
|
|
250
|
+
*
|
|
251
|
+
* The fix is the standard Cloudflare-Workers + wasm-bindgen pattern:
|
|
252
|
+
* the consumer statically imports the `.wasm` file (wrangler then
|
|
253
|
+
* bundles it + hands the worker a `WebAssembly.Module`), then passes
|
|
254
|
+
* it to `init(wasmModule)`. The web target's init detects the Module
|
|
255
|
+
* input + calls `WebAssembly.instantiate(Module, imports)` internally
|
|
256
|
+
* to produce a real `Instance` whose exports populate the JS shim's
|
|
257
|
+
* `wasm` binding correctly.
|
|
258
|
+
*
|
|
259
|
+
* Vercel Edge / webpack consumers MAY omit the argument — webpack's
|
|
260
|
+
* async-WASM support handles the URL fetch correctly. But the typed
|
|
261
|
+
* signature here marks `wasmModule` optional for backward compat;
|
|
262
|
+
* Cloudflare-Workers consumers MUST pass it.
|
|
230
263
|
*
|
|
231
264
|
* **Why this matters for the consolidation narrative.** Phase A
|
|
232
265
|
* shipped Node-only. Without an edge build, the first Vercel-edge
|
|
@@ -240,18 +273,21 @@ interface RenderedResponse {
|
|
|
240
273
|
|
|
241
274
|
/**
|
|
242
275
|
* Initialise the edge wasm module. Idempotent — subsequent calls
|
|
243
|
-
* return the same in-flight or resolved promise. Host wrappers
|
|
244
|
-
* call this at startup
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
* @param
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
276
|
+
* return the same in-flight or resolved promise. Host wrappers
|
|
277
|
+
* should call this once at startup with the `wasmModule` they
|
|
278
|
+
* statically imported from the package's `./wasm/kya-os-engine-web/`
|
|
279
|
+
* subpath (see CLAUDE.md for the wrangler/webpack import pattern).
|
|
280
|
+
*
|
|
281
|
+
* @param wasmModule REQUIRED on Cloudflare Workers (wrangler hands
|
|
282
|
+
* the consumer a `WebAssembly.Module` from the
|
|
283
|
+
* static `.wasm` import; pass it here so the
|
|
284
|
+
* web-target's `init()` instantiates it). OPTIONAL
|
|
285
|
+
* on Vercel Edge / webpack — webpack's async-WASM
|
|
286
|
+
* support resolves the URL fetch correctly, but
|
|
287
|
+
* passing the module explicitly is recommended
|
|
288
|
+
* for cross-runtime consistency.
|
|
253
289
|
*/
|
|
254
|
-
declare function initEngineEdge(
|
|
290
|
+
declare function initEngineEdge(wasmModule?: WebAssembly.Module | URL | string | Request | BufferSource): Promise<void>;
|
|
255
291
|
|
|
256
292
|
/**
|
|
257
293
|
* HTTP-to-`AgentRequest` translator — Phase C.1.
|
package/dist/orchestrator.d.ts
CHANGED
|
@@ -222,11 +222,44 @@ interface RenderedResponse {
|
|
|
222
222
|
* no sync wasm load).
|
|
223
223
|
*
|
|
224
224
|
* This module loads the `wasm-pack --target web` artifact via the
|
|
225
|
-
* async `__wbg_init` default export
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
225
|
+
* async `__wbg_init` default export. The web target's `init()`
|
|
226
|
+
* accepts a pre-instantiated `WebAssembly.Module` argument — the
|
|
227
|
+
* canonical Cloudflare-Workers + wasm-bindgen pattern.
|
|
228
|
+
*
|
|
229
|
+
* # Why the caller MUST pass `wasmModule` on Cloudflare Workers
|
|
230
|
+
*
|
|
231
|
+
* Both `--target web` (URL fetch) and `--target bundler` (auto-
|
|
232
|
+
* instantiated `__wbg_set_wasm(wasm)`) have failure modes on wrangler:
|
|
233
|
+
*
|
|
234
|
+
* - `--target web` falls back to `new URL('<wasm>', import.meta.url)`
|
|
235
|
+
* when `init()` is called with no arg. Cloudflare Workers don't
|
|
236
|
+
* materialise `import.meta.url` the way browsers do → throws
|
|
237
|
+
* `TypeError: Invalid URL string`. (Broke production 2026-05-23,
|
|
238
|
+
* captured via dev tail in run 26352287112.)
|
|
239
|
+
*
|
|
240
|
+
* - `--target bundler` expects the host bundler to AUTO-INSTANTIATE
|
|
241
|
+
* `import * as wasm from './foo.wasm'` so `wasm` is the
|
|
242
|
+
* `Instance.exports` object. Webpack does this. **Wrangler does
|
|
243
|
+
* NOT** — wrangler gives you a raw `WebAssembly.Module`, and the
|
|
244
|
+
* bundler-target shim's `__wbg_set_wasm(rawModule)` happily
|
|
245
|
+
* accepts it, then every export lookup (`wasm.__wbindgen_add_
|
|
246
|
+
* to_stack_pointer`, etc.) returns undefined → throws
|
|
247
|
+
* `TypeError: wasm.__wbindgen_add_to_stack_pointer is not a function`.
|
|
248
|
+
* (Broke production 2026-05-24 after switching to bundler target
|
|
249
|
+
* in PR #2785; captured via prod tail.)
|
|
250
|
+
*
|
|
251
|
+
* The fix is the standard Cloudflare-Workers + wasm-bindgen pattern:
|
|
252
|
+
* the consumer statically imports the `.wasm` file (wrangler then
|
|
253
|
+
* bundles it + hands the worker a `WebAssembly.Module`), then passes
|
|
254
|
+
* it to `init(wasmModule)`. The web target's init detects the Module
|
|
255
|
+
* input + calls `WebAssembly.instantiate(Module, imports)` internally
|
|
256
|
+
* to produce a real `Instance` whose exports populate the JS shim's
|
|
257
|
+
* `wasm` binding correctly.
|
|
258
|
+
*
|
|
259
|
+
* Vercel Edge / webpack consumers MAY omit the argument — webpack's
|
|
260
|
+
* async-WASM support handles the URL fetch correctly. But the typed
|
|
261
|
+
* signature here marks `wasmModule` optional for backward compat;
|
|
262
|
+
* Cloudflare-Workers consumers MUST pass it.
|
|
230
263
|
*
|
|
231
264
|
* **Why this matters for the consolidation narrative.** Phase A
|
|
232
265
|
* shipped Node-only. Without an edge build, the first Vercel-edge
|
|
@@ -240,18 +273,21 @@ interface RenderedResponse {
|
|
|
240
273
|
|
|
241
274
|
/**
|
|
242
275
|
* Initialise the edge wasm module. Idempotent — subsequent calls
|
|
243
|
-
* return the same in-flight or resolved promise. Host wrappers
|
|
244
|
-
* call this at startup
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
* @param
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
276
|
+
* return the same in-flight or resolved promise. Host wrappers
|
|
277
|
+
* should call this once at startup with the `wasmModule` they
|
|
278
|
+
* statically imported from the package's `./wasm/kya-os-engine-web/`
|
|
279
|
+
* subpath (see CLAUDE.md for the wrangler/webpack import pattern).
|
|
280
|
+
*
|
|
281
|
+
* @param wasmModule REQUIRED on Cloudflare Workers (wrangler hands
|
|
282
|
+
* the consumer a `WebAssembly.Module` from the
|
|
283
|
+
* static `.wasm` import; pass it here so the
|
|
284
|
+
* web-target's `init()` instantiates it). OPTIONAL
|
|
285
|
+
* on Vercel Edge / webpack — webpack's async-WASM
|
|
286
|
+
* support resolves the URL fetch correctly, but
|
|
287
|
+
* passing the module explicitly is recommended
|
|
288
|
+
* for cross-runtime consistency.
|
|
253
289
|
*/
|
|
254
|
-
declare function initEngineEdge(
|
|
290
|
+
declare function initEngineEdge(wasmModule?: WebAssembly.Module | URL | string | Request | BufferSource): Promise<void>;
|
|
255
291
|
|
|
256
292
|
/**
|
|
257
293
|
* HTTP-to-`AgentRequest` translator — Phase C.1.
|