@peac/protocol 0.13.3 → 0.14.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/dist/_internal/record-core/bounded-validator.d.ts +65 -29
- package/dist/_internal/record-core/bounded-validator.d.ts.map +1 -1
- package/dist/_internal/record-core/validation-gate.d.ts +102 -0
- package/dist/_internal/record-core/validation-gate.d.ts.map +1 -0
- package/dist/_internal/record-core/validators/iat-not-yet-valid.d.ts +29 -0
- package/dist/_internal/record-core/validators/iat-not-yet-valid.d.ts.map +1 -0
- package/dist/_internal/record-core/validators/index.d.ts +7 -0
- package/dist/_internal/record-core/validators/index.d.ts.map +1 -1
- package/dist/_internal/record-core/validators/jose-typ-strictness.d.ts +39 -0
- package/dist/_internal/record-core/validators/jose-typ-strictness.d.ts.map +1 -0
- package/dist/_internal/record-core/validators/policy-binding.d.ts +33 -0
- package/dist/_internal/record-core/validators/policy-binding.d.ts.map +1 -0
- package/dist/_internal/record-core/validators/schema-parse.d.ts +72 -0
- package/dist/_internal/record-core/validators/schema-parse.d.ts.map +1 -0
- package/dist/_internal/record-core/validators/signature.d.ts +31 -0
- package/dist/_internal/record-core/validators/signature.d.ts.map +1 -0
- package/dist/_internal/record-core/validators/type-extension-enforcement.d.ts +42 -0
- package/dist/_internal/record-core/validators/type-extension-enforcement.d.ts.map +1 -0
- package/dist/_internal/record-core/validators/unknown-extension-grammar.d.ts +39 -0
- package/dist/_internal/record-core/validators/unknown-extension-grammar.d.ts.map +1 -0
- package/dist/_internal/test-helpers/candidate-runner.d.ts +52 -0
- package/dist/_internal/test-helpers/candidate-runner.d.ts.map +1 -0
- package/dist/index.cjs +360 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +360 -59
- package/dist/index.mjs.map +1 -1
- package/dist/issue.d.ts.map +1 -1
- package/dist/verify-local.cjs +285 -18
- package/dist/verify-local.cjs.map +1 -1
- package/dist/verify-local.d.ts.map +1 -1
- package/dist/verify-local.mjs +285 -18
- package/dist/verify-local.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -310,6 +310,141 @@ function validateExtensionBudgetInternal(extensions) {
|
|
|
310
310
|
if (violations.length === 0) return ACCEPTED4;
|
|
311
311
|
return { accepted: false, violations };
|
|
312
312
|
}
|
|
313
|
+
function validateSchemaParseInternal(payload) {
|
|
314
|
+
const pr = parseReceiptClaims(payload);
|
|
315
|
+
if (!pr.ok) {
|
|
316
|
+
return {
|
|
317
|
+
accepted: false,
|
|
318
|
+
errorCode: pr.error.code,
|
|
319
|
+
errorMessage: pr.error.message,
|
|
320
|
+
...pr.error.issues !== void 0 && { errorIssues: pr.error.issues }
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
if (pr.wireVersion !== "0.2") {
|
|
324
|
+
return {
|
|
325
|
+
accepted: false,
|
|
326
|
+
errorCode: "E_UNSUPPORTED_WIRE_VERSION",
|
|
327
|
+
errorMessage: `Unsupported wire version: ${pr.wireVersion}`
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
accepted: true,
|
|
332
|
+
claims: pr.claims,
|
|
333
|
+
wireVersion: "0.2",
|
|
334
|
+
warnings: pr.warnings
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// src/_internal/record-core/validators/jose-typ-strictness.ts
|
|
339
|
+
var ACCEPTED_NO_WARN = { accepted: true };
|
|
340
|
+
var ACCEPTED_TYP_MISSING = {
|
|
341
|
+
accepted: true,
|
|
342
|
+
warnings: [{ code: "typ_missing" }]
|
|
343
|
+
};
|
|
344
|
+
var REJECTED_INVALID_FORMAT = {
|
|
345
|
+
accepted: false,
|
|
346
|
+
errorCode: "E_INVALID_FORMAT"
|
|
347
|
+
};
|
|
348
|
+
function validateJoseTypStrictnessInternal(typ, strictness) {
|
|
349
|
+
const present = typeof typ === "string" && typ.length > 0;
|
|
350
|
+
if (present) return ACCEPTED_NO_WARN;
|
|
351
|
+
if (strictness === "strict") return REJECTED_INVALID_FORMAT;
|
|
352
|
+
return ACCEPTED_TYP_MISSING;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// src/_internal/record-core/validators/iat-not-yet-valid.ts
|
|
356
|
+
var ACCEPTED5 = { accepted: true };
|
|
357
|
+
var REJECTED2 = {
|
|
358
|
+
accepted: false,
|
|
359
|
+
errorCode: "E_NOT_YET_VALID"
|
|
360
|
+
};
|
|
361
|
+
function validateIatNotYetValidInternal(iat, now, maxClockSkew) {
|
|
362
|
+
if (iat > now + maxClockSkew) return REJECTED2;
|
|
363
|
+
return ACCEPTED5;
|
|
364
|
+
}
|
|
365
|
+
function validatePolicyBindingInternal(receiptPolicyDigest, localPolicyDigest) {
|
|
366
|
+
if (receiptPolicyDigest === void 0 || localPolicyDigest === void 0) {
|
|
367
|
+
return { accepted: true, status: "unavailable" };
|
|
368
|
+
}
|
|
369
|
+
const status = verifyPolicyBinding(receiptPolicyDigest, localPolicyDigest);
|
|
370
|
+
if (status === "failed") {
|
|
371
|
+
return { accepted: false, errorCode: "E_POLICY_BINDING_FAILED", status };
|
|
372
|
+
}
|
|
373
|
+
return { accepted: true, status };
|
|
374
|
+
}
|
|
375
|
+
var ACCEPTED_EMPTY = {
|
|
376
|
+
accepted: true,
|
|
377
|
+
warnings: []
|
|
378
|
+
};
|
|
379
|
+
function escapeJsonPointer(token) {
|
|
380
|
+
return token.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
381
|
+
}
|
|
382
|
+
function validateUnknownExtensionGrammarInternal(extensions) {
|
|
383
|
+
if (extensions === void 0) return ACCEPTED_EMPTY;
|
|
384
|
+
const keys = Object.keys(extensions);
|
|
385
|
+
if (keys.length === 0) return ACCEPTED_EMPTY;
|
|
386
|
+
const warnings = [];
|
|
387
|
+
for (const key of keys) {
|
|
388
|
+
if (!REGISTERED_EXTENSION_GROUP_KEYS.has(key) && isValidExtensionKey(key)) {
|
|
389
|
+
warnings.push({
|
|
390
|
+
code: "unknown_extension_preserved",
|
|
391
|
+
pointer: `/extensions/${escapeJsonPointer(key)}`
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return { accepted: true, warnings };
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// src/type-extension-check.ts
|
|
399
|
+
function checkTypeExtensionMapping(kind, type, extensions, typeToExtensionMap, registeredExtensionGroupKeys) {
|
|
400
|
+
if (kind === "challenge") {
|
|
401
|
+
return { status: "skip" };
|
|
402
|
+
}
|
|
403
|
+
const expectedGroup = typeToExtensionMap.get(type);
|
|
404
|
+
if (expectedGroup === void 0) {
|
|
405
|
+
return { status: "skip" };
|
|
406
|
+
}
|
|
407
|
+
if (extensions !== void 0 && Object.prototype.hasOwnProperty.call(extensions, expectedGroup)) {
|
|
408
|
+
return { status: "ok" };
|
|
409
|
+
}
|
|
410
|
+
const presentRegistered = [];
|
|
411
|
+
if (extensions !== void 0) {
|
|
412
|
+
for (const key of Object.keys(extensions)) {
|
|
413
|
+
if (key !== expectedGroup && registeredExtensionGroupKeys.has(key)) {
|
|
414
|
+
presentRegistered.push(key);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return {
|
|
419
|
+
status: presentRegistered.length > 0 ? "mismatch" : "missing",
|
|
420
|
+
expected_extension_group: expectedGroup,
|
|
421
|
+
present_registered_extension_groups: presentRegistered
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// src/_internal/record-core/validators/type-extension-enforcement.ts
|
|
426
|
+
var ACCEPTED_NO_WARN2 = { accepted: true };
|
|
427
|
+
function validateTypeExtensionEnforcementInternal(kind, type, extensions, strictness) {
|
|
428
|
+
const result = checkTypeExtensionMapping(
|
|
429
|
+
kind,
|
|
430
|
+
type,
|
|
431
|
+
extensions,
|
|
432
|
+
TYPE_TO_EXTENSION_MAP,
|
|
433
|
+
REGISTERED_EXTENSION_GROUP_KEYS
|
|
434
|
+
);
|
|
435
|
+
if (result.status === "ok" || result.status === "skip") {
|
|
436
|
+
return ACCEPTED_NO_WARN2;
|
|
437
|
+
}
|
|
438
|
+
if (strictness === "strict") {
|
|
439
|
+
const errorCode = result.status === "missing" ? "E_EXTENSION_GROUP_REQUIRED" : "E_EXTENSION_GROUP_MISMATCH";
|
|
440
|
+
return { accepted: false, errorCode, pointer: "/type" };
|
|
441
|
+
}
|
|
442
|
+
const warningCode = result.status === "missing" ? "extension_group_missing" : "extension_group_mismatch";
|
|
443
|
+
return {
|
|
444
|
+
accepted: true,
|
|
445
|
+
warnings: [{ code: warningCode, pointer: "/type" }]
|
|
446
|
+
};
|
|
447
|
+
}
|
|
313
448
|
|
|
314
449
|
// src/_internal/record-core/bounded-validator.ts
|
|
315
450
|
function runBoundedValidatorShadow(input) {
|
|
@@ -369,12 +504,154 @@ function runBoundedValidatorShadow(input) {
|
|
|
369
504
|
violations.push({ layer: "extension-budget", code: v.code, path: v.path });
|
|
370
505
|
}
|
|
371
506
|
}
|
|
507
|
+
if (input.fullClaims !== void 0) {
|
|
508
|
+
const schemaRes = validateSchemaParseInternal(input.fullClaims);
|
|
509
|
+
if (!schemaRes.accepted && schemaRes.errorCode !== void 0) {
|
|
510
|
+
violations.push({ layer: "schema-parse", code: schemaRes.errorCode });
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
if (input.header !== void 0 && input.strictness !== void 0) {
|
|
514
|
+
const typRes = validateJoseTypStrictnessInternal(input.header.typ, input.strictness);
|
|
515
|
+
if (!typRes.accepted) {
|
|
516
|
+
violations.push({ layer: "jose-typ-strictness", code: typRes.errorCode });
|
|
517
|
+
} else if (typRes.warnings) {
|
|
518
|
+
for (const w of typRes.warnings) {
|
|
519
|
+
warnings.push({ layer: "jose-typ-strictness", code: w.code });
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
if (input.maxClockSkew !== void 0) {
|
|
524
|
+
const iatRes = validateIatNotYetValidInternal(input.claims.iat, input.now, input.maxClockSkew);
|
|
525
|
+
if (!iatRes.accepted && iatRes.errorCode !== void 0) {
|
|
526
|
+
violations.push({ layer: "iat-not-yet-valid", code: iatRes.errorCode });
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
if (input.receiptPolicyDigest !== void 0 && input.localPolicyDigest !== void 0) {
|
|
530
|
+
const policyRes = validatePolicyBindingInternal(
|
|
531
|
+
input.receiptPolicyDigest,
|
|
532
|
+
input.localPolicyDigest
|
|
533
|
+
);
|
|
534
|
+
if (!policyRes.accepted && policyRes.errorCode !== void 0) {
|
|
535
|
+
violations.push({ layer: "policy-binding", code: policyRes.errorCode });
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
const unknownExtRes = validateUnknownExtensionGrammarInternal(input.claims.extensions);
|
|
539
|
+
for (const w of unknownExtRes.warnings) {
|
|
540
|
+
warnings.push({
|
|
541
|
+
layer: "unknown-extension-grammar",
|
|
542
|
+
code: w.code,
|
|
543
|
+
path: w.pointer
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
if (input.strictness !== void 0) {
|
|
547
|
+
const enforceRes = validateTypeExtensionEnforcementInternal(
|
|
548
|
+
input.claims.kind,
|
|
549
|
+
input.claims.type,
|
|
550
|
+
input.claims.extensions,
|
|
551
|
+
input.strictness
|
|
552
|
+
);
|
|
553
|
+
if (!enforceRes.accepted) {
|
|
554
|
+
violations.push({
|
|
555
|
+
layer: "type-extension-enforcement",
|
|
556
|
+
code: enforceRes.errorCode,
|
|
557
|
+
path: enforceRes.pointer
|
|
558
|
+
});
|
|
559
|
+
} else if (enforceRes.warnings) {
|
|
560
|
+
for (const w of enforceRes.warnings) {
|
|
561
|
+
warnings.push({
|
|
562
|
+
layer: "type-extension-enforcement",
|
|
563
|
+
code: w.code,
|
|
564
|
+
path: w.pointer
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
372
569
|
return {
|
|
373
570
|
accepted: violations.length === 0,
|
|
374
571
|
violations,
|
|
375
572
|
warnings
|
|
376
573
|
};
|
|
377
574
|
}
|
|
575
|
+
var MAX_SANITIZED_ISSUES = 25;
|
|
576
|
+
function sanitizeIssues(issues) {
|
|
577
|
+
if (!Array.isArray(issues)) return void 0;
|
|
578
|
+
return issues.slice(0, MAX_SANITIZED_ISSUES).map((issue2) => {
|
|
579
|
+
const candidate = issue2;
|
|
580
|
+
const path = Array.isArray(candidate.path) ? candidate.path.map(
|
|
581
|
+
(segment) => typeof segment === "string" || typeof segment === "number" ? String(segment) : ""
|
|
582
|
+
).join(".") : "";
|
|
583
|
+
const message = typeof candidate.message === "string" ? candidate.message : String(candidate.message ?? issue2);
|
|
584
|
+
return { path, message };
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
function runBoundedValidationGate(input) {
|
|
588
|
+
if (input.surface === "issueWire02") {
|
|
589
|
+
return runIssueWire02(input.payload);
|
|
590
|
+
}
|
|
591
|
+
return runVerifyLocal(input.payload);
|
|
592
|
+
}
|
|
593
|
+
function runIssueWire02(payload) {
|
|
594
|
+
const schemaRes = validateSchemaParseInternal(payload);
|
|
595
|
+
if (!schemaRes.accepted) {
|
|
596
|
+
const firstIssueMessage = schemaRes.errorIssues?.[0]?.message;
|
|
597
|
+
return {
|
|
598
|
+
ok: false,
|
|
599
|
+
code: "E_INVALID_FORMAT",
|
|
600
|
+
message: `Wire 0.2 claims schema validation failed: ${firstIssueMessage ?? "unknown"}`
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
return { ok: true };
|
|
604
|
+
}
|
|
605
|
+
function runVerifyLocal(payload) {
|
|
606
|
+
const kernelRes = validateKernelConstraints(payload);
|
|
607
|
+
if (!kernelRes.valid) {
|
|
608
|
+
const v = kernelRes.violations[0];
|
|
609
|
+
return {
|
|
610
|
+
ok: false,
|
|
611
|
+
code: "E_CONSTRAINT_VIOLATION",
|
|
612
|
+
message: `Kernel constraint violated: ${v.constraint} (actual: ${v.actual}, limit: ${v.limit})`
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
const schemaRes = validateSchemaParseInternal(payload);
|
|
616
|
+
if (!schemaRes.accepted) {
|
|
617
|
+
if (schemaRes.errorCode === "E_UNSUPPORTED_WIRE_VERSION") {
|
|
618
|
+
return {
|
|
619
|
+
ok: false,
|
|
620
|
+
code: "E_UNSUPPORTED_WIRE_VERSION",
|
|
621
|
+
message: "Wire 0.1 receipts are not supported. Re-issue as Wire 0.2 using issue()."
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
const sanitized = sanitizeIssues(schemaRes.errorIssues);
|
|
625
|
+
const details = {};
|
|
626
|
+
if (schemaRes.errorCode !== void 0) {
|
|
627
|
+
Object.assign(details, { parse_code: schemaRes.errorCode });
|
|
628
|
+
}
|
|
629
|
+
if (sanitized !== void 0) {
|
|
630
|
+
Object.assign(details, { issues: sanitized });
|
|
631
|
+
}
|
|
632
|
+
return {
|
|
633
|
+
ok: false,
|
|
634
|
+
code: "E_INVALID_FORMAT",
|
|
635
|
+
message: `Receipt schema validation failed: ${schemaRes.errorMessage ?? "unknown"}`,
|
|
636
|
+
...Object.keys(details).length > 0 && { details }
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
if (schemaRes.wireVersion !== "0.2" || schemaRes.claims === void 0) {
|
|
640
|
+
return {
|
|
641
|
+
ok: false,
|
|
642
|
+
code: "E_UNSUPPORTED_WIRE_VERSION",
|
|
643
|
+
message: "Wire 0.1 receipts are not supported. Re-issue as Wire 0.2 using issue()."
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
return {
|
|
647
|
+
ok: true,
|
|
648
|
+
parsed: {
|
|
649
|
+
wireVersion: "0.2",
|
|
650
|
+
claims: schemaRes.claims,
|
|
651
|
+
parserWarnings: schemaRes.warnings ?? []
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
}
|
|
378
655
|
var SECRET_PATTERNS = [
|
|
379
656
|
// Compact JWS / JWT (header.payload.signature with eyJ-prefixed header).
|
|
380
657
|
/eyJ[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,
|
|
@@ -812,7 +1089,7 @@ async function issue(options) {
|
|
|
812
1089
|
return issueWire02(options);
|
|
813
1090
|
}
|
|
814
1091
|
async function issueWire02(options) {
|
|
815
|
-
|
|
1092
|
+
const legacyPath = readLegacyPathFlag(options);
|
|
816
1093
|
if (!isCanonicalIss(options.iss)) {
|
|
817
1094
|
throw new IssueError({
|
|
818
1095
|
code: "E_ISS_NOT_CANONICAL",
|
|
@@ -841,22 +1118,39 @@ async function issueWire02(options) {
|
|
|
841
1118
|
...options.policy !== void 0 && { policy: options.policy },
|
|
842
1119
|
...options.extensions !== void 0 && { extensions: options.extensions }
|
|
843
1120
|
};
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
1121
|
+
if (legacyPath) {
|
|
1122
|
+
const parseResult = Wire02ClaimsSchema.safeParse(claims);
|
|
1123
|
+
if (!parseResult.success) {
|
|
1124
|
+
const firstIssue = parseResult.error.issues[0];
|
|
1125
|
+
throw new IssueError({
|
|
1126
|
+
code: "E_INVALID_FORMAT",
|
|
1127
|
+
category: "validation",
|
|
1128
|
+
severity: "error",
|
|
1129
|
+
retryable: false,
|
|
1130
|
+
http_status: 400,
|
|
1131
|
+
details: {
|
|
1132
|
+
message: `Wire 0.2 claims schema validation failed: ${firstIssue?.message ?? "unknown"}`
|
|
1133
|
+
}
|
|
1134
|
+
});
|
|
1135
|
+
}
|
|
1136
|
+
} else {
|
|
1137
|
+
const gateResult = runBoundedValidationGate({
|
|
1138
|
+
surface: "issueWire02",
|
|
1139
|
+
payload: claims
|
|
856
1140
|
});
|
|
1141
|
+
if (!gateResult.ok) {
|
|
1142
|
+
throw new IssueError({
|
|
1143
|
+
code: gateResult.code,
|
|
1144
|
+
category: "validation",
|
|
1145
|
+
severity: "error",
|
|
1146
|
+
retryable: false,
|
|
1147
|
+
http_status: 400,
|
|
1148
|
+
details: { message: gateResult.message }
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
857
1151
|
}
|
|
858
1152
|
const jws = await defaultCodec.encode(claims, options.privateKey, options.kid);
|
|
859
|
-
if (isShadowEnabled(options)) {
|
|
1153
|
+
if (legacyPath && isShadowEnabled(options)) {
|
|
860
1154
|
scheduleShadow({
|
|
861
1155
|
call: "issue",
|
|
862
1156
|
realResult: realObservationForIssue(),
|
|
@@ -2062,33 +2356,6 @@ async function verifyReceipt(optionsOrJws) {
|
|
|
2062
2356
|
}
|
|
2063
2357
|
}
|
|
2064
2358
|
|
|
2065
|
-
// src/type-extension-check.ts
|
|
2066
|
-
function checkTypeExtensionMapping(kind, type, extensions, typeToExtensionMap, registeredExtensionGroupKeys) {
|
|
2067
|
-
if (kind === "challenge") {
|
|
2068
|
-
return { status: "skip" };
|
|
2069
|
-
}
|
|
2070
|
-
const expectedGroup = typeToExtensionMap.get(type);
|
|
2071
|
-
if (expectedGroup === void 0) {
|
|
2072
|
-
return { status: "skip" };
|
|
2073
|
-
}
|
|
2074
|
-
if (extensions !== void 0 && Object.prototype.hasOwnProperty.call(extensions, expectedGroup)) {
|
|
2075
|
-
return { status: "ok" };
|
|
2076
|
-
}
|
|
2077
|
-
const presentRegistered = [];
|
|
2078
|
-
if (extensions !== void 0) {
|
|
2079
|
-
for (const key of Object.keys(extensions)) {
|
|
2080
|
-
if (key !== expectedGroup && registeredExtensionGroupKeys.has(key)) {
|
|
2081
|
-
presentRegistered.push(key);
|
|
2082
|
-
}
|
|
2083
|
-
}
|
|
2084
|
-
}
|
|
2085
|
-
return {
|
|
2086
|
-
status: presentRegistered.length > 0 ? "mismatch" : "missing",
|
|
2087
|
-
expected_extension_group: expectedGroup,
|
|
2088
|
-
present_registered_extension_groups: presentRegistered
|
|
2089
|
-
};
|
|
2090
|
-
}
|
|
2091
|
-
|
|
2092
2359
|
// src/_internal/record-core/shadow-hook.ts
|
|
2093
2360
|
function maybeRunShadowValidation(input) {
|
|
2094
2361
|
return void 0;
|
|
@@ -2120,7 +2387,7 @@ function sanitizeParseIssues(issues) {
|
|
|
2120
2387
|
}));
|
|
2121
2388
|
}
|
|
2122
2389
|
async function verifyLocal(jws, publicKey, options = {}) {
|
|
2123
|
-
|
|
2390
|
+
const legacyPath = readLegacyPathFlag(options);
|
|
2124
2391
|
const {
|
|
2125
2392
|
issuer,
|
|
2126
2393
|
subjectUri,
|
|
@@ -2153,22 +2420,56 @@ async function verifyLocal(jws, publicKey, options = {}) {
|
|
|
2153
2420
|
message: "JWS typ header is absent; accepted in interop mode"
|
|
2154
2421
|
});
|
|
2155
2422
|
}
|
|
2156
|
-
|
|
2157
|
-
if (
|
|
2158
|
-
const
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2423
|
+
let pr;
|
|
2424
|
+
if (legacyPath) {
|
|
2425
|
+
const constraintResult = validateKernelConstraints(result.payload);
|
|
2426
|
+
if (!constraintResult.valid) {
|
|
2427
|
+
const v = constraintResult.violations[0];
|
|
2428
|
+
return {
|
|
2429
|
+
valid: false,
|
|
2430
|
+
code: "E_CONSTRAINT_VIOLATION",
|
|
2431
|
+
message: `Kernel constraint violated: ${v.constraint} (actual: ${v.actual}, limit: ${v.limit})`
|
|
2432
|
+
};
|
|
2433
|
+
}
|
|
2434
|
+
const parsed = parseReceiptClaims(result.payload);
|
|
2435
|
+
if (!parsed.ok) {
|
|
2436
|
+
return {
|
|
2437
|
+
valid: false,
|
|
2438
|
+
code: "E_INVALID_FORMAT",
|
|
2439
|
+
message: `Receipt schema validation failed: ${parsed.error.message}`,
|
|
2440
|
+
details: {
|
|
2441
|
+
parse_code: parsed.error.code,
|
|
2442
|
+
issues: sanitizeParseIssues(parsed.error.issues)
|
|
2443
|
+
}
|
|
2444
|
+
};
|
|
2445
|
+
}
|
|
2446
|
+
pr = parsed;
|
|
2447
|
+
} else {
|
|
2448
|
+
const gateResult = runBoundedValidationGate({
|
|
2449
|
+
surface: "verifyLocal",
|
|
2450
|
+
payload: result.payload
|
|
2451
|
+
});
|
|
2452
|
+
if (!gateResult.ok) {
|
|
2453
|
+
return {
|
|
2454
|
+
valid: false,
|
|
2455
|
+
code: gateResult.code,
|
|
2456
|
+
message: gateResult.message,
|
|
2457
|
+
...gateResult.details !== void 0 && { details: gateResult.details }
|
|
2458
|
+
};
|
|
2459
|
+
}
|
|
2460
|
+
const parsedFromGate = gateResult.parsed;
|
|
2461
|
+
if (parsedFromGate === void 0) {
|
|
2462
|
+
return {
|
|
2463
|
+
valid: false,
|
|
2464
|
+
code: "E_INTERNAL",
|
|
2465
|
+
message: "Bounded validation gate accepted without surfacing parsed claims"
|
|
2466
|
+
};
|
|
2467
|
+
}
|
|
2468
|
+
pr = {
|
|
2469
|
+
ok: true,
|
|
2470
|
+
wireVersion: parsedFromGate.wireVersion,
|
|
2471
|
+
warnings: parsedFromGate.parserWarnings,
|
|
2472
|
+
claims: parsedFromGate.claims
|
|
2172
2473
|
};
|
|
2173
2474
|
}
|
|
2174
2475
|
if (pr.wireVersion === "0.2") {
|
|
@@ -2285,7 +2586,7 @@ async function verifyLocal(jws, publicKey, options = {}) {
|
|
|
2285
2586
|
...callerBindings?.documents !== void 0 && callerBindings.documents.length > 0 && { documents: callerBindings.documents }
|
|
2286
2587
|
};
|
|
2287
2588
|
const sortedWarnings = sortWarnings(accumulatedWarnings);
|
|
2288
|
-
if (isShadowEnabled(options)) {
|
|
2589
|
+
if (legacyPath && isShadowEnabled(options)) {
|
|
2289
2590
|
const headerSnapshot = { ...result.header };
|
|
2290
2591
|
scheduleShadow({
|
|
2291
2592
|
call: "verifyLocal",
|