@peac/protocol 0.13.4 → 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/validation-gate.d.ts +102 -0
- package/dist/_internal/record-core/validation-gate.d.ts.map +1 -0
- package/dist/_internal/record-core/validators/schema-parse.d.ts +53 -23
- package/dist/_internal/record-core/validators/schema-parse.d.ts.map +1 -1
- package/dist/index.cjs +180 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +180 -35
- package/dist/index.mjs.map +1 -1
- package/dist/issue.d.ts.map +1 -1
- package/dist/verify-local.cjs +134 -21
- package/dist/verify-local.cjs.map +1 -1
- package/dist/verify-local.d.ts.map +1 -1
- package/dist/verify-local.mjs +134 -21
- package/dist/verify-local.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -313,12 +313,26 @@ function validateExtensionBudgetInternal(extensions) {
|
|
|
313
313
|
function validateSchemaParseInternal(payload) {
|
|
314
314
|
const pr = parseReceiptClaims(payload);
|
|
315
315
|
if (!pr.ok) {
|
|
316
|
-
return {
|
|
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
|
+
};
|
|
317
322
|
}
|
|
318
323
|
if (pr.wireVersion !== "0.2") {
|
|
319
|
-
return {
|
|
324
|
+
return {
|
|
325
|
+
accepted: false,
|
|
326
|
+
errorCode: "E_UNSUPPORTED_WIRE_VERSION",
|
|
327
|
+
errorMessage: `Unsupported wire version: ${pr.wireVersion}`
|
|
328
|
+
};
|
|
320
329
|
}
|
|
321
|
-
return {
|
|
330
|
+
return {
|
|
331
|
+
accepted: true,
|
|
332
|
+
claims: pr.claims,
|
|
333
|
+
wireVersion: "0.2",
|
|
334
|
+
warnings: pr.warnings
|
|
335
|
+
};
|
|
322
336
|
}
|
|
323
337
|
|
|
324
338
|
// src/_internal/record-core/validators/jose-typ-strictness.ts
|
|
@@ -558,6 +572,86 @@ function runBoundedValidatorShadow(input) {
|
|
|
558
572
|
warnings
|
|
559
573
|
};
|
|
560
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
|
+
}
|
|
561
655
|
var SECRET_PATTERNS = [
|
|
562
656
|
// Compact JWS / JWT (header.payload.signature with eyJ-prefixed header).
|
|
563
657
|
/eyJ[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,
|
|
@@ -995,7 +1089,7 @@ async function issue(options) {
|
|
|
995
1089
|
return issueWire02(options);
|
|
996
1090
|
}
|
|
997
1091
|
async function issueWire02(options) {
|
|
998
|
-
|
|
1092
|
+
const legacyPath = readLegacyPathFlag(options);
|
|
999
1093
|
if (!isCanonicalIss(options.iss)) {
|
|
1000
1094
|
throw new IssueError({
|
|
1001
1095
|
code: "E_ISS_NOT_CANONICAL",
|
|
@@ -1024,22 +1118,39 @@ async function issueWire02(options) {
|
|
|
1024
1118
|
...options.policy !== void 0 && { policy: options.policy },
|
|
1025
1119
|
...options.extensions !== void 0 && { extensions: options.extensions }
|
|
1026
1120
|
};
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
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
|
|
1039
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
|
+
}
|
|
1040
1151
|
}
|
|
1041
1152
|
const jws = await defaultCodec.encode(claims, options.privateKey, options.kid);
|
|
1042
|
-
if (isShadowEnabled(options)) {
|
|
1153
|
+
if (legacyPath && isShadowEnabled(options)) {
|
|
1043
1154
|
scheduleShadow({
|
|
1044
1155
|
call: "issue",
|
|
1045
1156
|
realResult: realObservationForIssue(),
|
|
@@ -2276,7 +2387,7 @@ function sanitizeParseIssues(issues) {
|
|
|
2276
2387
|
}));
|
|
2277
2388
|
}
|
|
2278
2389
|
async function verifyLocal(jws, publicKey, options = {}) {
|
|
2279
|
-
|
|
2390
|
+
const legacyPath = readLegacyPathFlag(options);
|
|
2280
2391
|
const {
|
|
2281
2392
|
issuer,
|
|
2282
2393
|
subjectUri,
|
|
@@ -2309,22 +2420,56 @@ async function verifyLocal(jws, publicKey, options = {}) {
|
|
|
2309
2420
|
message: "JWS typ header is absent; accepted in interop mode"
|
|
2310
2421
|
});
|
|
2311
2422
|
}
|
|
2312
|
-
|
|
2313
|
-
if (
|
|
2314
|
-
const
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
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
|
|
2328
2473
|
};
|
|
2329
2474
|
}
|
|
2330
2475
|
if (pr.wireVersion === "0.2") {
|
|
@@ -2441,7 +2586,7 @@ async function verifyLocal(jws, publicKey, options = {}) {
|
|
|
2441
2586
|
...callerBindings?.documents !== void 0 && callerBindings.documents.length > 0 && { documents: callerBindings.documents }
|
|
2442
2587
|
};
|
|
2443
2588
|
const sortedWarnings = sortWarnings(accumulatedWarnings);
|
|
2444
|
-
if (isShadowEnabled(options)) {
|
|
2589
|
+
if (legacyPath && isShadowEnabled(options)) {
|
|
2445
2590
|
const headerSnapshot = { ...result.header };
|
|
2446
2591
|
scheduleShadow({
|
|
2447
2592
|
call: "verifyLocal",
|