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