@peac/schema 0.12.1 → 0.12.3
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/actor-binding.d.ts +10 -10
- package/dist/agent-identity.d.ts +8 -6
- package/dist/agent-identity.d.ts.map +1 -1
- package/dist/carrier.d.ts +7 -7
- package/dist/carrier.d.ts.map +1 -1
- package/dist/constraints.d.ts +4 -4
- package/dist/constraints.d.ts.map +1 -1
- package/dist/extensions/control-action.d.ts +1 -1
- package/dist/extensions/credential-event.d.ts +4 -4
- package/dist/extensions/fingerprint-ref.d.ts +1 -1
- package/dist/extensions/index.d.ts +1 -1
- package/dist/extensions/tool-registry.d.ts +1 -1
- package/dist/extensions/treaty.d.ts +2 -2
- package/dist/index.cjs +733 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +684 -46
- package/dist/index.mjs.map +1 -1
- package/dist/issuer-config.d.ts +1 -1
- package/dist/policy-binding.d.ts +2 -2
- package/dist/receipt-parser.cjs +626 -14
- package/dist/receipt-parser.cjs.map +1 -1
- package/dist/receipt-parser.mjs +627 -15
- package/dist/receipt-parser.mjs.map +1 -1
- package/dist/subject.d.ts +33 -12
- package/dist/subject.d.ts.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/wire-02-envelope.d.ts +2 -2
- package/dist/wire-02-extensions/access.d.ts +19 -0
- package/dist/wire-02-extensions/access.d.ts.map +1 -0
- package/dist/wire-02-extensions/accessors.d.ts +44 -0
- package/dist/wire-02-extensions/accessors.d.ts.map +1 -0
- package/dist/wire-02-extensions/attribution.d.ts +44 -0
- package/dist/wire-02-extensions/attribution.d.ts.map +1 -0
- package/dist/wire-02-extensions/challenge.d.ts +60 -0
- package/dist/wire-02-extensions/challenge.d.ts.map +1 -0
- package/dist/wire-02-extensions/commerce.d.ts +29 -0
- package/dist/wire-02-extensions/commerce.d.ts.map +1 -0
- package/dist/wire-02-extensions/compliance.d.ts +49 -0
- package/dist/wire-02-extensions/compliance.d.ts.map +1 -0
- package/dist/wire-02-extensions/consent.d.ts +48 -0
- package/dist/wire-02-extensions/consent.d.ts.map +1 -0
- package/dist/wire-02-extensions/correlation.d.ts +18 -0
- package/dist/wire-02-extensions/correlation.d.ts.map +1 -0
- package/dist/wire-02-extensions/grammar.d.ts +40 -0
- package/dist/wire-02-extensions/grammar.d.ts.map +1 -0
- package/dist/wire-02-extensions/identity.d.ts +13 -0
- package/dist/wire-02-extensions/identity.d.ts.map +1 -0
- package/dist/wire-02-extensions/index.d.ts +40 -0
- package/dist/wire-02-extensions/index.d.ts.map +1 -0
- package/dist/wire-02-extensions/limits.d.ts +80 -0
- package/dist/wire-02-extensions/limits.d.ts.map +1 -0
- package/dist/wire-02-extensions/privacy.d.ts +64 -0
- package/dist/wire-02-extensions/privacy.d.ts.map +1 -0
- package/dist/wire-02-extensions/provenance.d.ts +58 -0
- package/dist/wire-02-extensions/provenance.d.ts.map +1 -0
- package/dist/wire-02-extensions/purpose-extension.d.ts +26 -0
- package/dist/wire-02-extensions/purpose-extension.d.ts.map +1 -0
- package/dist/wire-02-extensions/safety.d.ts +65 -0
- package/dist/wire-02-extensions/safety.d.ts.map +1 -0
- package/dist/wire-02-extensions/schema-map.d.ts +13 -0
- package/dist/wire-02-extensions/schema-map.d.ts.map +1 -0
- package/dist/wire-02-extensions/shared-validators.d.ts +192 -0
- package/dist/wire-02-extensions/shared-validators.d.ts.map +1 -0
- package/dist/wire-02-extensions/validation.d.ts +57 -0
- package/dist/wire-02-extensions/validation.d.ts.map +1 -0
- package/dist/wire-02-extensions.d.ts +7 -211
- package/dist/wire-02-extensions.d.ts.map +1 -1
- package/dist/wire-02-registries.d.ts +5 -2
- package/dist/wire-02-registries.d.ts.map +1 -1
- package/dist/wire-02-representation.d.ts +3 -3
- package/dist/wire-02-warnings.d.ts +5 -1
- package/dist/wire-02-warnings.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/receipt-parser.cjs
CHANGED
|
@@ -46,7 +46,7 @@ var JsonObjectSchema = PlainObjectSchema.transform(
|
|
|
46
46
|
).pipe(zod.z.record(zod.z.string(), JsonValueSchema));
|
|
47
47
|
zod.z.array(JsonValueSchema);
|
|
48
48
|
var ERROR_CODES = {
|
|
49
|
-
// Wire 0.2 extension errors (400
|
|
49
|
+
// Wire 0.2 extension errors (400/)
|
|
50
50
|
E_INVALID_EXTENSION_KEY: "E_INVALID_EXTENSION_KEY"
|
|
51
51
|
};
|
|
52
52
|
|
|
@@ -325,7 +325,7 @@ function isOriginOnly(value) {
|
|
|
325
325
|
var ActorBindingSchema = zod.z.object({
|
|
326
326
|
/** Stable actor identifier (opaque, no PII) */
|
|
327
327
|
id: zod.z.string().min(1).max(256),
|
|
328
|
-
/** Proof type from
|
|
328
|
+
/** Proof type from multi-root vocabulary */
|
|
329
329
|
proof_type: ProofTypeSchema,
|
|
330
330
|
/** URI or hash of external proof artifact */
|
|
331
331
|
proof_ref: zod.z.string().max(2048).optional(),
|
|
@@ -333,7 +333,7 @@ var ActorBindingSchema = zod.z.object({
|
|
|
333
333
|
origin: zod.z.string().max(2048).refine(isOriginOnly, {
|
|
334
334
|
message: "origin must be an origin-only URL (scheme + host + optional port; no path, query, or fragment)"
|
|
335
335
|
}),
|
|
336
|
-
/** SHA-256 hash of the intent (hash-first per
|
|
336
|
+
/** SHA-256 hash of the intent (hash-first per ) */
|
|
337
337
|
intent_hash: zod.z.string().regex(/^sha256:[a-f0-9]{64}$/, {
|
|
338
338
|
message: "intent_hash must match sha256:<64 hex chars>"
|
|
339
339
|
}).optional()
|
|
@@ -459,8 +459,52 @@ var EXTENSION_LIMITS = {
|
|
|
459
459
|
maxSpanIdLength: 16,
|
|
460
460
|
maxWorkflowIdLength: 256,
|
|
461
461
|
maxParentJtiLength: 256,
|
|
462
|
-
maxDependsOnLength: 64
|
|
463
|
-
|
|
462
|
+
maxDependsOnLength: 64,
|
|
463
|
+
// Consent
|
|
464
|
+
maxConsentBasisLength: 128,
|
|
465
|
+
maxConsentMethodLength: 128,
|
|
466
|
+
maxDataCategoriesCount: 64,
|
|
467
|
+
maxDataCategoryLength: 128,
|
|
468
|
+
maxConsentScopeLength: 256,
|
|
469
|
+
maxJurisdictionLength: 16,
|
|
470
|
+
// Compliance
|
|
471
|
+
maxFrameworkLength: 256,
|
|
472
|
+
maxAuditRefLength: 256,
|
|
473
|
+
maxAuditorLength: 256,
|
|
474
|
+
maxComplianceScopeLength: 512,
|
|
475
|
+
// Privacy
|
|
476
|
+
maxDataClassificationLength: 128,
|
|
477
|
+
maxProcessingBasisLength: 128,
|
|
478
|
+
maxAnonymizationMethodLength: 128,
|
|
479
|
+
maxDataSubjectCategoryLength: 128,
|
|
480
|
+
maxTransferMechanismLength: 128,
|
|
481
|
+
// Safety
|
|
482
|
+
maxAssessmentMethodLength: 256,
|
|
483
|
+
maxSafetyMeasuresCount: 32,
|
|
484
|
+
maxSafetyMeasureLength: 256,
|
|
485
|
+
maxIncidentRefLength: 256,
|
|
486
|
+
maxModelRefLength: 256,
|
|
487
|
+
maxSafetyCategoryLength: 128,
|
|
488
|
+
// Provenance
|
|
489
|
+
maxSourceTypeLength: 128,
|
|
490
|
+
maxSourceRefLength: 256,
|
|
491
|
+
maxVerificationMethodLength: 128,
|
|
492
|
+
maxCustodyChainCount: 16,
|
|
493
|
+
maxCustodianLength: 256,
|
|
494
|
+
maxCustodyActionLength: 128,
|
|
495
|
+
maxSlsaTrackLength: 64,
|
|
496
|
+
maxSlsaVersionLength: 16,
|
|
497
|
+
// Attribution
|
|
498
|
+
maxCreatorRefLength: 256,
|
|
499
|
+
maxObligationTypeLength: 128,
|
|
500
|
+
maxAttributionTextLength: 1024,
|
|
501
|
+
// Purpose
|
|
502
|
+
maxExternalPurposesCount: 32,
|
|
503
|
+
maxExternalPurposeLength: 128,
|
|
504
|
+
maxPurposeBasisLength: 128,
|
|
505
|
+
maxCompatiblePurposesCount: 32};
|
|
506
|
+
|
|
507
|
+
// src/wire-02-extensions/grammar.ts
|
|
464
508
|
var DNS_LABEL = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
|
|
465
509
|
var SEGMENT_PATTERN = /^[a-z0-9][a-z0-9_-]*$/;
|
|
466
510
|
function isValidExtensionKey(key) {
|
|
@@ -481,10 +525,6 @@ function isValidExtensionKey(key) {
|
|
|
481
525
|
return true;
|
|
482
526
|
}
|
|
483
527
|
var COMMERCE_EXTENSION_KEY = "org.peacprotocol/commerce";
|
|
484
|
-
var ACCESS_EXTENSION_KEY = "org.peacprotocol/access";
|
|
485
|
-
var CHALLENGE_EXTENSION_KEY = "org.peacprotocol/challenge";
|
|
486
|
-
var IDENTITY_EXTENSION_KEY = "org.peacprotocol/identity";
|
|
487
|
-
var CORRELATION_EXTENSION_KEY = "org.peacprotocol/correlation";
|
|
488
528
|
var AMOUNT_MINOR_PATTERN = /^-?[0-9]+$/;
|
|
489
529
|
var CommerceExtensionSchema = zod.z.object({
|
|
490
530
|
/** Payment rail identifier (e.g., 'stripe', 'x402', 'lightning') */
|
|
@@ -505,8 +545,11 @@ var CommerceExtensionSchema = zod.z.object({
|
|
|
505
545
|
/** Asset identifier for non-fiat (e.g., token address) */
|
|
506
546
|
asset: zod.z.string().max(EXTENSION_LIMITS.maxAssetLength).optional(),
|
|
507
547
|
/** Environment discriminant */
|
|
508
|
-
env: zod.z.enum(["live", "test"]).optional()
|
|
548
|
+
env: zod.z.enum(["live", "test"]).optional(),
|
|
549
|
+
/** Commerce lifecycle phase. Observational metadata only: does not encode settlement finality or protocol state transitions */
|
|
550
|
+
event: zod.z.enum(["authorization", "capture", "settlement", "refund", "void", "chargeback"]).optional()
|
|
509
551
|
}).strict();
|
|
552
|
+
var ACCESS_EXTENSION_KEY = "org.peacprotocol/access";
|
|
510
553
|
var AccessExtensionSchema = zod.z.object({
|
|
511
554
|
/** Resource being accessed (URI or identifier) */
|
|
512
555
|
resource: zod.z.string().min(1).max(EXTENSION_LIMITS.maxResourceLength),
|
|
@@ -515,6 +558,7 @@ var AccessExtensionSchema = zod.z.object({
|
|
|
515
558
|
/** Access decision */
|
|
516
559
|
decision: zod.z.enum(["allow", "deny", "review"])
|
|
517
560
|
}).strict();
|
|
561
|
+
var CHALLENGE_EXTENSION_KEY = "org.peacprotocol/challenge";
|
|
518
562
|
var CHALLENGE_TYPES = [
|
|
519
563
|
"payment_required",
|
|
520
564
|
"identity_required",
|
|
@@ -549,10 +593,12 @@ var ChallengeExtensionSchema = zod.z.object({
|
|
|
549
593
|
/** Caller-defined requirements for resolving the challenge */
|
|
550
594
|
requirements: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
551
595
|
}).strict();
|
|
596
|
+
var IDENTITY_EXTENSION_KEY = "org.peacprotocol/identity";
|
|
552
597
|
var IdentityExtensionSchema = zod.z.object({
|
|
553
598
|
/** Proof reference (opaque string; no actor_binding: top-level actor is sole location) */
|
|
554
599
|
proof_ref: zod.z.string().max(EXTENSION_LIMITS.maxProofRefLength).optional()
|
|
555
600
|
}).strict();
|
|
601
|
+
var CORRELATION_EXTENSION_KEY = "org.peacprotocol/correlation";
|
|
556
602
|
var TRACE_ID_PATTERN = /^[0-9a-f]{32}$/;
|
|
557
603
|
var SPAN_ID_PATTERN = /^[0-9a-f]{16}$/;
|
|
558
604
|
var CorrelationExtensionSchema = zod.z.object({
|
|
@@ -567,15 +613,554 @@ var CorrelationExtensionSchema = zod.z.object({
|
|
|
567
613
|
/** JTIs this receipt depends on */
|
|
568
614
|
depends_on: zod.z.array(zod.z.string().min(1).max(EXTENSION_LIMITS.maxParentJtiLength)).max(EXTENSION_LIMITS.maxDependsOnLength).optional()
|
|
569
615
|
}).strict();
|
|
616
|
+
var Sha256DigestSchema = zod.z.string().max(71).regex(kernel.HASH.pattern, "must be a valid SHA-256 digest (sha256:<64 lowercase hex>)");
|
|
617
|
+
var CONTROL_CHAR_PATTERN = /[\x00-\x1f\x7f]/;
|
|
618
|
+
var HttpsUriHintSchema = zod.z.string().min(1).max(2048).refine(
|
|
619
|
+
(value) => {
|
|
620
|
+
if (CONTROL_CHAR_PATTERN.test(value)) return false;
|
|
621
|
+
if (value.includes("#")) return false;
|
|
622
|
+
try {
|
|
623
|
+
const url = new URL(value);
|
|
624
|
+
if (url.protocol !== "https:") return false;
|
|
625
|
+
if (url.username !== "" || url.password !== "") return false;
|
|
626
|
+
if (!url.hostname) return false;
|
|
627
|
+
return true;
|
|
628
|
+
} catch {
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
message: "must be a valid HTTPS URI (no credentials, no fragments, no control characters)"
|
|
634
|
+
}
|
|
635
|
+
);
|
|
636
|
+
var DATE_DESIGNATOR_ORDER = ["Y", "M", "W", "D"];
|
|
637
|
+
var TIME_DESIGNATOR_ORDER = ["H", "M", "S"];
|
|
638
|
+
function parseIso8601Duration(value) {
|
|
639
|
+
if (typeof value !== "string" || value.length === 0 || value.length > 64) {
|
|
640
|
+
return null;
|
|
641
|
+
}
|
|
642
|
+
if (value.charAt(0) !== "P") return null;
|
|
643
|
+
let pos = 1;
|
|
644
|
+
const len = value.length;
|
|
645
|
+
if (pos >= len) return null;
|
|
646
|
+
const result = {
|
|
647
|
+
years: 0,
|
|
648
|
+
months: 0,
|
|
649
|
+
weeks: 0,
|
|
650
|
+
days: 0,
|
|
651
|
+
hours: 0,
|
|
652
|
+
minutes: 0,
|
|
653
|
+
seconds: 0
|
|
654
|
+
};
|
|
655
|
+
let inTimePart = false;
|
|
656
|
+
let hasAnyComponent = false;
|
|
657
|
+
const seenDesignators = /* @__PURE__ */ new Set();
|
|
658
|
+
let dateOrderIdx = 0;
|
|
659
|
+
let timeOrderIdx = 0;
|
|
660
|
+
while (pos < len) {
|
|
661
|
+
if (value.charAt(pos) === "T") {
|
|
662
|
+
if (inTimePart) return null;
|
|
663
|
+
inTimePart = true;
|
|
664
|
+
pos++;
|
|
665
|
+
if (pos >= len) return null;
|
|
666
|
+
continue;
|
|
667
|
+
}
|
|
668
|
+
const numStart = pos;
|
|
669
|
+
while (pos < len && value.charAt(pos) >= "0" && value.charAt(pos) <= "9") {
|
|
670
|
+
pos++;
|
|
671
|
+
}
|
|
672
|
+
if (pos === numStart) return null;
|
|
673
|
+
const digits = value.slice(numStart, pos);
|
|
674
|
+
if (digits.length > 15) return null;
|
|
675
|
+
const num = parseInt(digits, 10);
|
|
676
|
+
if (!Number.isFinite(num) || num < 0) return null;
|
|
677
|
+
if (pos >= len) return null;
|
|
678
|
+
const designator = value.charAt(pos);
|
|
679
|
+
pos++;
|
|
680
|
+
const designatorKey = (inTimePart ? "T" : "") + designator;
|
|
681
|
+
if (seenDesignators.has(designatorKey)) return null;
|
|
682
|
+
seenDesignators.add(designatorKey);
|
|
683
|
+
if (inTimePart) {
|
|
684
|
+
const timeIdx = TIME_DESIGNATOR_ORDER.indexOf(designator);
|
|
685
|
+
if (timeIdx === -1) return null;
|
|
686
|
+
if (timeIdx < timeOrderIdx) return null;
|
|
687
|
+
timeOrderIdx = timeIdx + 1;
|
|
688
|
+
switch (designator) {
|
|
689
|
+
case "H":
|
|
690
|
+
result.hours = num;
|
|
691
|
+
break;
|
|
692
|
+
case "M":
|
|
693
|
+
result.minutes = num;
|
|
694
|
+
break;
|
|
695
|
+
case "S":
|
|
696
|
+
result.seconds = num;
|
|
697
|
+
break;
|
|
698
|
+
}
|
|
699
|
+
} else {
|
|
700
|
+
const dateIdx = DATE_DESIGNATOR_ORDER.indexOf(designator);
|
|
701
|
+
if (dateIdx === -1) return null;
|
|
702
|
+
if (dateIdx < dateOrderIdx) return null;
|
|
703
|
+
dateOrderIdx = dateIdx + 1;
|
|
704
|
+
switch (designator) {
|
|
705
|
+
case "Y":
|
|
706
|
+
result.years = num;
|
|
707
|
+
break;
|
|
708
|
+
case "M":
|
|
709
|
+
result.months = num;
|
|
710
|
+
break;
|
|
711
|
+
case "W":
|
|
712
|
+
result.weeks = num;
|
|
713
|
+
break;
|
|
714
|
+
case "D":
|
|
715
|
+
result.days = num;
|
|
716
|
+
break;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
hasAnyComponent = true;
|
|
720
|
+
}
|
|
721
|
+
if (!hasAnyComponent) return null;
|
|
722
|
+
if (result.weeks > 0 && (result.years > 0 || result.months > 0 || result.days > 0)) {
|
|
723
|
+
return null;
|
|
724
|
+
}
|
|
725
|
+
return result;
|
|
726
|
+
}
|
|
727
|
+
var Iso8601DurationSchema = zod.z.string().min(2).max(64).refine((value) => parseIso8601Duration(value) !== null, {
|
|
728
|
+
message: "must be a valid ISO 8601 duration (e.g., P30D, P1Y6M, PT1H30M)"
|
|
729
|
+
});
|
|
730
|
+
var Iso8601DateStringSchema = zod.z.string().length(10).regex(/^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$/, {
|
|
731
|
+
message: "must be a structurally valid date string (YYYY-MM-DD)"
|
|
732
|
+
});
|
|
733
|
+
zod.z.iso.datetime({ offset: true });
|
|
734
|
+
var RFC3339_SECONDS_PATTERN = /T\d{2}:\d{2}:\d{2}/;
|
|
735
|
+
var Rfc3339DateTimeSchema = zod.z.iso.datetime({ offset: true }).refine((value) => RFC3339_SECONDS_PATTERN.test(value), {
|
|
736
|
+
message: "RFC 3339 requires seconds precision (e.g., 2026-03-14T12:00:00Z)"
|
|
737
|
+
});
|
|
738
|
+
function isValidSpdxSubsetExpression(expr) {
|
|
739
|
+
if (typeof expr !== "string" || expr.length === 0 || expr.length > 128) {
|
|
740
|
+
return false;
|
|
741
|
+
}
|
|
742
|
+
const tokens = [];
|
|
743
|
+
let current = "";
|
|
744
|
+
for (let i = 0; i < expr.length; i++) {
|
|
745
|
+
const ch = expr.charAt(i);
|
|
746
|
+
if (ch === "(" || ch === ")") {
|
|
747
|
+
if (current.length > 0) {
|
|
748
|
+
tokens.push(current);
|
|
749
|
+
current = "";
|
|
750
|
+
}
|
|
751
|
+
tokens.push(ch);
|
|
752
|
+
} else if (ch === " " || ch === " ") {
|
|
753
|
+
if (current.length > 0) {
|
|
754
|
+
tokens.push(current);
|
|
755
|
+
current = "";
|
|
756
|
+
}
|
|
757
|
+
} else {
|
|
758
|
+
current += ch;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
if (current.length > 0) {
|
|
762
|
+
tokens.push(current);
|
|
763
|
+
}
|
|
764
|
+
if (tokens.length === 0) return false;
|
|
765
|
+
let pos = 0;
|
|
766
|
+
function peek() {
|
|
767
|
+
return tokens[pos];
|
|
768
|
+
}
|
|
769
|
+
function advance() {
|
|
770
|
+
return tokens[pos++];
|
|
771
|
+
}
|
|
772
|
+
function isLicenseId(token) {
|
|
773
|
+
const base = token.endsWith("+") ? token.slice(0, -1) : token;
|
|
774
|
+
if (base.length === 0) return false;
|
|
775
|
+
if (base.startsWith("LicenseRef-")) {
|
|
776
|
+
const ref = base.slice(11);
|
|
777
|
+
return ref.length > 0 && /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(ref);
|
|
778
|
+
}
|
|
779
|
+
return /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(base);
|
|
780
|
+
}
|
|
781
|
+
function isExceptionId(token) {
|
|
782
|
+
return /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(token);
|
|
783
|
+
}
|
|
784
|
+
function parseExpr() {
|
|
785
|
+
if (!parseTerm()) return false;
|
|
786
|
+
while (pos < tokens.length) {
|
|
787
|
+
const op = peek();
|
|
788
|
+
if (op === "AND" || op === "OR") {
|
|
789
|
+
advance();
|
|
790
|
+
if (!parseTerm()) return false;
|
|
791
|
+
} else {
|
|
792
|
+
break;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
return true;
|
|
796
|
+
}
|
|
797
|
+
function parseTerm() {
|
|
798
|
+
if (!parseAtom()) return false;
|
|
799
|
+
if (peek() === "WITH") {
|
|
800
|
+
advance();
|
|
801
|
+
const exception = peek();
|
|
802
|
+
if (exception === void 0 || !isExceptionId(exception)) return false;
|
|
803
|
+
advance();
|
|
804
|
+
}
|
|
805
|
+
return true;
|
|
806
|
+
}
|
|
807
|
+
function parseAtom() {
|
|
808
|
+
const token = peek();
|
|
809
|
+
if (token === void 0) return false;
|
|
810
|
+
if (token === "(") {
|
|
811
|
+
advance();
|
|
812
|
+
if (!parseExpr()) return false;
|
|
813
|
+
if (peek() !== ")") return false;
|
|
814
|
+
advance();
|
|
815
|
+
return true;
|
|
816
|
+
}
|
|
817
|
+
if (token === ")" || token === "AND" || token === "OR" || token === "WITH") {
|
|
818
|
+
return false;
|
|
819
|
+
}
|
|
820
|
+
if (!isLicenseId(token)) return false;
|
|
821
|
+
advance();
|
|
822
|
+
return true;
|
|
823
|
+
}
|
|
824
|
+
const result = parseExpr();
|
|
825
|
+
return result && pos === tokens.length;
|
|
826
|
+
}
|
|
827
|
+
var SpdxExpressionSchema = zod.z.string().min(1).max(128).refine(isValidSpdxSubsetExpression, {
|
|
828
|
+
message: "must be a valid SPDX license expression (e.g., MIT, Apache-2.0, MIT AND Apache-2.0). DocumentRef-* not yet supported."
|
|
829
|
+
});
|
|
830
|
+
|
|
831
|
+
// src/wire-02-extensions/consent.ts
|
|
832
|
+
var CONSENT_EXTENSION_KEY = "org.peacprotocol/consent";
|
|
833
|
+
var CONSENT_STATUSES = ["granted", "withdrawn", "denied", "expired"];
|
|
834
|
+
var ConsentStatusSchema = zod.z.enum(CONSENT_STATUSES);
|
|
835
|
+
var ConsentExtensionSchema = zod.z.object({
|
|
836
|
+
/**
|
|
837
|
+
* Legal basis identifier for consent.
|
|
838
|
+
* Open string: jurisdictions define different bases
|
|
839
|
+
* (e.g., explicit, implied, opt_out, legitimate_interest, contractual, legal_obligation).
|
|
840
|
+
*/
|
|
841
|
+
consent_basis: zod.z.string().min(1).max(EXTENSION_LIMITS.maxConsentBasisLength),
|
|
842
|
+
/** Consent lifecycle state (closed vocabulary) */
|
|
843
|
+
consent_status: ConsentStatusSchema,
|
|
844
|
+
/**
|
|
845
|
+
* Data categories covered by this consent.
|
|
846
|
+
* Open vocabulary (e.g., personal, sensitive, biometric).
|
|
847
|
+
*/
|
|
848
|
+
data_categories: zod.z.array(zod.z.string().min(1).max(EXTENSION_LIMITS.maxDataCategoryLength)).max(EXTENSION_LIMITS.maxDataCategoriesCount).optional(),
|
|
849
|
+
/** Data retention period as ISO 8601 duration. */
|
|
850
|
+
retention_period: Iso8601DurationSchema.optional(),
|
|
851
|
+
/**
|
|
852
|
+
* How consent was collected.
|
|
853
|
+
* Open vocabulary (e.g., click_through, double_opt_in, verbal, written).
|
|
854
|
+
*/
|
|
855
|
+
consent_method: zod.z.string().min(1).max(EXTENSION_LIMITS.maxConsentMethodLength).optional(),
|
|
856
|
+
/**
|
|
857
|
+
* HTTPS URI hint for consent withdrawal.
|
|
858
|
+
* Locator hint only: callers MUST NOT auto-fetch.
|
|
859
|
+
* Rejects non-HTTPS, embedded credentials, fragments, control chars.
|
|
860
|
+
*/
|
|
861
|
+
withdrawal_uri: HttpsUriHintSchema.optional(),
|
|
862
|
+
/** Free-text scope description */
|
|
863
|
+
scope: zod.z.string().min(1).max(EXTENSION_LIMITS.maxConsentScopeLength).optional(),
|
|
864
|
+
/**
|
|
865
|
+
* Jurisdiction code: ISO 3166-1 alpha-2 or composite.
|
|
866
|
+
* Examples: EU, US-CA, BR, GB, DE, JP, IN.
|
|
867
|
+
*/
|
|
868
|
+
jurisdiction: zod.z.string().min(1).max(EXTENSION_LIMITS.maxJurisdictionLength).optional()
|
|
869
|
+
}).strict();
|
|
870
|
+
var PRIVACY_EXTENSION_KEY = "org.peacprotocol/privacy";
|
|
871
|
+
var RETENTION_MODES = ["time_bound", "indefinite", "session_only"];
|
|
872
|
+
var RetentionModeSchema = zod.z.enum(RETENTION_MODES);
|
|
873
|
+
var RECIPIENT_SCOPES = ["internal", "processor", "third_party", "public"];
|
|
874
|
+
var RecipientScopeSchema = zod.z.enum(RECIPIENT_SCOPES);
|
|
875
|
+
var PrivacyExtensionSchema = zod.z.object({
|
|
876
|
+
/**
|
|
877
|
+
* Data classification level.
|
|
878
|
+
* Open taxonomy (e.g., public, internal, confidential, restricted, pii, sensitive_pii).
|
|
879
|
+
*/
|
|
880
|
+
data_classification: zod.z.string().min(1).max(EXTENSION_LIMITS.maxDataClassificationLength),
|
|
881
|
+
/**
|
|
882
|
+
* Legal basis for data processing.
|
|
883
|
+
* Open vocabulary (e.g., consent, legitimate_interest, contract, legal_obligation).
|
|
884
|
+
*/
|
|
885
|
+
processing_basis: zod.z.string().min(1).max(EXTENSION_LIMITS.maxProcessingBasisLength).optional(),
|
|
886
|
+
/**
|
|
887
|
+
* Data retention period as ISO 8601 duration.
|
|
888
|
+
* For non-duration retention semantics, use retention_mode instead.
|
|
889
|
+
*/
|
|
890
|
+
retention_period: Iso8601DurationSchema.optional(),
|
|
891
|
+
/**
|
|
892
|
+
* Retention mode for non-duration semantics.
|
|
893
|
+
* Closed enum: time_bound, indefinite, session_only.
|
|
894
|
+
* When time_bound, retention_period SHOULD also be present.
|
|
895
|
+
*/
|
|
896
|
+
retention_mode: RetentionModeSchema.optional(),
|
|
897
|
+
/**
|
|
898
|
+
* Data recipient classification.
|
|
899
|
+
* Closed enum aligned with GDPR Art 13-14 disclosure categories.
|
|
900
|
+
*/
|
|
901
|
+
recipient_scope: RecipientScopeSchema.optional(),
|
|
902
|
+
/**
|
|
903
|
+
* Anonymization or pseudonymization method applied.
|
|
904
|
+
* Open vocabulary (e.g., k_anonymity, differential_privacy, pseudonymization,
|
|
905
|
+
* tokenization, aggregation).
|
|
906
|
+
*/
|
|
907
|
+
anonymization_method: zod.z.string().min(1).max(EXTENSION_LIMITS.maxAnonymizationMethodLength).optional(),
|
|
908
|
+
/**
|
|
909
|
+
* Data subject category.
|
|
910
|
+
* Open vocabulary (e.g., customer, employee, minor, patient, student).
|
|
911
|
+
*/
|
|
912
|
+
data_subject_category: zod.z.string().min(1).max(EXTENSION_LIMITS.maxDataSubjectCategoryLength).optional(),
|
|
913
|
+
/**
|
|
914
|
+
* Cross-border data transfer mechanism.
|
|
915
|
+
* Open vocabulary (e.g., adequacy_decision, scc, bcr, derogation, consent).
|
|
916
|
+
*/
|
|
917
|
+
transfer_mechanism: zod.z.string().min(1).max(EXTENSION_LIMITS.maxTransferMechanismLength).optional()
|
|
918
|
+
}).strict();
|
|
919
|
+
var SAFETY_EXTENSION_KEY = "org.peacprotocol/safety";
|
|
920
|
+
var REVIEW_STATUSES = ["reviewed", "pending", "flagged", "not_applicable"];
|
|
921
|
+
var ReviewStatusSchema = zod.z.enum(REVIEW_STATUSES);
|
|
922
|
+
var RISK_LEVELS = ["unacceptable", "high", "limited", "minimal"];
|
|
923
|
+
var RiskLevelSchema = zod.z.enum(RISK_LEVELS);
|
|
924
|
+
var SafetyExtensionSchema = zod.z.object({
|
|
925
|
+
/** Safety review status (closed vocabulary, universal lifecycle) */
|
|
926
|
+
review_status: ReviewStatusSchema,
|
|
927
|
+
/**
|
|
928
|
+
* Risk classification level.
|
|
929
|
+
* Optional at schema level; usage profiles may require it.
|
|
930
|
+
* Converges across EU AI Act Art 6, NIST AI RMF, ISO 23894.
|
|
931
|
+
*/
|
|
932
|
+
risk_level: RiskLevelSchema.optional(),
|
|
933
|
+
/**
|
|
934
|
+
* Assessment method used.
|
|
935
|
+
* Open vocabulary (e.g., automated_scan, human_review, red_team,
|
|
936
|
+
* penetration_test, static_analysis, model_evaluation).
|
|
937
|
+
*/
|
|
938
|
+
assessment_method: zod.z.string().min(1).max(EXTENSION_LIMITS.maxAssessmentMethodLength).optional(),
|
|
939
|
+
/**
|
|
940
|
+
* Safety measures applied.
|
|
941
|
+
* Open vocabulary. Array bounded by maxSafetyMeasuresCount.
|
|
942
|
+
*/
|
|
943
|
+
safety_measures: zod.z.array(zod.z.string().min(1).max(EXTENSION_LIMITS.maxSafetyMeasureLength)).max(EXTENSION_LIMITS.maxSafetyMeasuresCount).optional(),
|
|
944
|
+
/** Incident report reference. Opaque identifier (e.g., ticket ID or digest). */
|
|
945
|
+
incident_ref: zod.z.string().min(1).max(EXTENSION_LIMITS.maxIncidentRefLength).optional(),
|
|
946
|
+
/** AI model reference. Opaque identifier (e.g., model version string). */
|
|
947
|
+
model_ref: zod.z.string().min(1).max(EXTENSION_LIMITS.maxModelRefLength).optional(),
|
|
948
|
+
/**
|
|
949
|
+
* Safety category.
|
|
950
|
+
* Open vocabulary (e.g., content_safety, bias, hallucination,
|
|
951
|
+
* toxicity, fairness, robustness, privacy_risk).
|
|
952
|
+
*/
|
|
953
|
+
category: zod.z.string().min(1).max(EXTENSION_LIMITS.maxSafetyCategoryLength).optional()
|
|
954
|
+
}).strict();
|
|
955
|
+
var COMPLIANCE_EXTENSION_KEY = "org.peacprotocol/compliance";
|
|
956
|
+
var COMPLIANCE_STATUSES = [
|
|
957
|
+
"compliant",
|
|
958
|
+
"non_compliant",
|
|
959
|
+
"partial",
|
|
960
|
+
"under_review",
|
|
961
|
+
"exempt"
|
|
962
|
+
];
|
|
963
|
+
var ComplianceStatusSchema = zod.z.enum(COMPLIANCE_STATUSES);
|
|
964
|
+
var ComplianceExtensionSchema = zod.z.object({
|
|
965
|
+
/**
|
|
966
|
+
* Framework identifier evaluated.
|
|
967
|
+
* Open string: preferred grammar is lowercase slugs with hyphens
|
|
968
|
+
* (e.g., eu-ai-act, soc2-type2, iso-27001, nist-ai-rmf, gdpr, hipaa).
|
|
969
|
+
*/
|
|
970
|
+
framework: zod.z.string().min(1).max(EXTENSION_LIMITS.maxFrameworkLength),
|
|
971
|
+
/** Observed compliance status (closed vocabulary) */
|
|
972
|
+
compliance_status: ComplianceStatusSchema,
|
|
973
|
+
/** Opaque reference to audit report or evidence (e.g., report ID, ticket number). */
|
|
974
|
+
audit_ref: zod.z.string().min(1).max(EXTENSION_LIMITS.maxAuditRefLength).optional(),
|
|
975
|
+
/** Auditor identifier (organization name or DID). */
|
|
976
|
+
auditor: zod.z.string().min(1).max(EXTENSION_LIMITS.maxAuditorLength).optional(),
|
|
977
|
+
/** Date the compliance check was performed (YYYY-MM-DD). */
|
|
978
|
+
audit_date: Iso8601DateStringSchema.optional(),
|
|
979
|
+
/** Scope of the compliance check. */
|
|
980
|
+
scope: zod.z.string().min(1).max(EXTENSION_LIMITS.maxComplianceScopeLength).optional(),
|
|
981
|
+
/** How long this finding remains valid as an ISO 8601 duration. */
|
|
982
|
+
validity_period: Iso8601DurationSchema.optional(),
|
|
983
|
+
/** SHA-256 digest of supporting evidence document. */
|
|
984
|
+
evidence_ref: Sha256DigestSchema.optional()
|
|
985
|
+
}).strict();
|
|
986
|
+
var PROVENANCE_EXTENSION_KEY = "org.peacprotocol/provenance";
|
|
987
|
+
var CustodyEntrySchema = zod.z.object({
|
|
988
|
+
/** Custodian identifier (organization name, DID, or opaque ID). */
|
|
989
|
+
custodian: zod.z.string().min(1).max(EXTENSION_LIMITS.maxCustodianLength),
|
|
990
|
+
/** Action performed (e.g., received, transformed, verified, released). */
|
|
991
|
+
action: zod.z.string().min(1).max(EXTENSION_LIMITS.maxCustodyActionLength),
|
|
992
|
+
/** When the custody event occurred (RFC 3339 with seconds). */
|
|
993
|
+
timestamp: Rfc3339DateTimeSchema
|
|
994
|
+
}).strict();
|
|
995
|
+
var SlsaLevelSchema = zod.z.object({
|
|
996
|
+
/** SLSA track identifier (e.g., build, source). */
|
|
997
|
+
track: zod.z.string().min(1).max(EXTENSION_LIMITS.maxSlsaTrackLength),
|
|
998
|
+
/** SLSA level within the track (0-4). */
|
|
999
|
+
level: zod.z.number().int().min(0).max(4),
|
|
1000
|
+
/** SLSA spec version this metadata references (e.g., 1.0, 1.2). */
|
|
1001
|
+
version: zod.z.string().min(1).max(EXTENSION_LIMITS.maxSlsaVersionLength)
|
|
1002
|
+
}).strict();
|
|
1003
|
+
var ProvenanceExtensionSchema = zod.z.object({
|
|
1004
|
+
/**
|
|
1005
|
+
* Type of source or derivation.
|
|
1006
|
+
* Open vocabulary (e.g., original, derived, curated, synthetic, aggregated, transformed).
|
|
1007
|
+
*/
|
|
1008
|
+
source_type: zod.z.string().min(1).max(EXTENSION_LIMITS.maxSourceTypeLength),
|
|
1009
|
+
/** Opaque source reference identifier (e.g., commit hash, artifact ID). */
|
|
1010
|
+
source_ref: zod.z.string().min(1).max(EXTENSION_LIMITS.maxSourceRefLength).optional(),
|
|
1011
|
+
/**
|
|
1012
|
+
* HTTPS URI hint for the source artifact.
|
|
1013
|
+
* Locator hint only: callers MUST NOT auto-fetch.
|
|
1014
|
+
*/
|
|
1015
|
+
source_uri: HttpsUriHintSchema.optional(),
|
|
1016
|
+
/**
|
|
1017
|
+
* HTTPS URI hint for build provenance metadata.
|
|
1018
|
+
* Locator hint only: callers MUST NOT auto-fetch.
|
|
1019
|
+
*/
|
|
1020
|
+
build_provenance_uri: HttpsUriHintSchema.optional(),
|
|
1021
|
+
/**
|
|
1022
|
+
* How provenance was verified.
|
|
1023
|
+
* Open vocabulary (e.g., signature_check, hash_chain,
|
|
1024
|
+
* manual_attestation, transparency_log).
|
|
1025
|
+
*/
|
|
1026
|
+
verification_method: zod.z.string().min(1).max(EXTENSION_LIMITS.maxVerificationMethodLength).optional(),
|
|
1027
|
+
/**
|
|
1028
|
+
* Ordered custody chain entries.
|
|
1029
|
+
* Each entry records a custodian, action, and timestamp.
|
|
1030
|
+
*/
|
|
1031
|
+
custody_chain: zod.z.array(CustodyEntrySchema).max(EXTENSION_LIMITS.maxCustodyChainCount).optional(),
|
|
1032
|
+
/**
|
|
1033
|
+
* Structured SLSA-aligned provenance metadata.
|
|
1034
|
+
* Records track, level, and spec version.
|
|
1035
|
+
*/
|
|
1036
|
+
slsa: SlsaLevelSchema.optional()
|
|
1037
|
+
}).strict();
|
|
1038
|
+
var ATTRIBUTION_EXTENSION_KEY = "org.peacprotocol/attribution";
|
|
1039
|
+
var CONTENT_SIGNAL_SOURCES = [
|
|
1040
|
+
"tdmrep_json",
|
|
1041
|
+
"content_signal_header",
|
|
1042
|
+
"content_usage_header",
|
|
1043
|
+
"robots_txt",
|
|
1044
|
+
"custom"
|
|
1045
|
+
];
|
|
1046
|
+
var ContentSignalSourceSchema = zod.z.enum(CONTENT_SIGNAL_SOURCES);
|
|
1047
|
+
var AttributionExtensionSchema = zod.z.object({
|
|
1048
|
+
/**
|
|
1049
|
+
* Creator identifier (DID, URI, or opaque ID).
|
|
1050
|
+
* Not an identity attestation; records observed attribution metadata.
|
|
1051
|
+
*/
|
|
1052
|
+
creator_ref: zod.z.string().min(1).max(EXTENSION_LIMITS.maxCreatorRefLength),
|
|
1053
|
+
/** SPDX license expression (parser-grade structural subset validator). */
|
|
1054
|
+
license_spdx: SpdxExpressionSchema.optional(),
|
|
1055
|
+
/**
|
|
1056
|
+
* Obligation type.
|
|
1057
|
+
* Open vocabulary (e.g., attribution_required, share_alike, non_commercial).
|
|
1058
|
+
*/
|
|
1059
|
+
obligation_type: zod.z.string().min(1).max(EXTENSION_LIMITS.maxObligationTypeLength).optional(),
|
|
1060
|
+
/** Required attribution text. */
|
|
1061
|
+
attribution_text: zod.z.string().min(1).max(EXTENSION_LIMITS.maxAttributionTextLength).optional(),
|
|
1062
|
+
/** Content signal observation source (closed vocabulary). */
|
|
1063
|
+
content_signal_source: ContentSignalSourceSchema.optional(),
|
|
1064
|
+
/** SHA-256 digest of the attributed content. */
|
|
1065
|
+
content_digest: Sha256DigestSchema.optional()
|
|
1066
|
+
}).strict();
|
|
1067
|
+
var PURPOSE_EXTENSION_KEY = "org.peacprotocol/purpose";
|
|
1068
|
+
var MachineSafePurposeTokenSchema = zod.z.string().min(1).max(EXTENSION_LIMITS.maxExternalPurposeLength).regex(PURPOSE_TOKEN_REGEX, "must be a machine-safe lowercase token");
|
|
1069
|
+
function hasUniqueItems(items) {
|
|
1070
|
+
return new Set(items).size === items.length;
|
|
1071
|
+
}
|
|
1072
|
+
var PurposeExtensionSchema = zod.z.object({
|
|
1073
|
+
/**
|
|
1074
|
+
* External/legal/business purpose labels.
|
|
1075
|
+
* Machine-safe tokens: lowercase alphanumeric with underscores, hyphens,
|
|
1076
|
+
* and optional vendor prefix (e.g., ai_training, analytics, marketing).
|
|
1077
|
+
* Not PEAC operational tokens; use peac_purpose_mapping for bridging.
|
|
1078
|
+
* Items must be unique.
|
|
1079
|
+
*/
|
|
1080
|
+
external_purposes: zod.z.array(MachineSafePurposeTokenSchema).min(1).max(EXTENSION_LIMITS.maxExternalPurposesCount).refine(hasUniqueItems, { message: "external_purposes must contain unique items" }),
|
|
1081
|
+
/**
|
|
1082
|
+
* Legal or policy basis for the declared purposes.
|
|
1083
|
+
* Open vocabulary (e.g., consent, legitimate_interest, contract).
|
|
1084
|
+
*/
|
|
1085
|
+
purpose_basis: zod.z.string().min(1).max(EXTENSION_LIMITS.maxPurposeBasisLength).optional(),
|
|
1086
|
+
/** Whether purpose limitation applies. */
|
|
1087
|
+
purpose_limitation: zod.z.boolean().optional(),
|
|
1088
|
+
/** Whether data minimization was applied. */
|
|
1089
|
+
data_minimization: zod.z.boolean().optional(),
|
|
1090
|
+
/**
|
|
1091
|
+
* Compatible purposes for secondary use.
|
|
1092
|
+
* Same machine-safe token grammar as external_purposes.
|
|
1093
|
+
* Items must be unique.
|
|
1094
|
+
*/
|
|
1095
|
+
compatible_purposes: zod.z.array(MachineSafePurposeTokenSchema).max(EXTENSION_LIMITS.maxCompatiblePurposesCount).refine(hasUniqueItems, { message: "compatible_purposes must contain unique items" }).optional(),
|
|
1096
|
+
/**
|
|
1097
|
+
* Explicit mapping to a PEAC operational CanonicalPurpose token.
|
|
1098
|
+
* Validated against PURPOSE_TOKEN_REGEX from purpose.ts.
|
|
1099
|
+
* Bridges external purpose vocabulary to operational tokens.
|
|
1100
|
+
*/
|
|
1101
|
+
peac_purpose_mapping: zod.z.string().min(1).max(MAX_PURPOSE_TOKEN_LENGTH).regex(PURPOSE_TOKEN_REGEX, "must be a valid PEAC purpose token").optional()
|
|
1102
|
+
}).strict();
|
|
1103
|
+
|
|
1104
|
+
// src/wire-02-extensions/schema-map.ts
|
|
570
1105
|
var EXTENSION_SCHEMA_MAP = /* @__PURE__ */ new Map();
|
|
571
1106
|
EXTENSION_SCHEMA_MAP.set(COMMERCE_EXTENSION_KEY, CommerceExtensionSchema);
|
|
572
1107
|
EXTENSION_SCHEMA_MAP.set(ACCESS_EXTENSION_KEY, AccessExtensionSchema);
|
|
573
1108
|
EXTENSION_SCHEMA_MAP.set(CHALLENGE_EXTENSION_KEY, ChallengeExtensionSchema);
|
|
574
1109
|
EXTENSION_SCHEMA_MAP.set(IDENTITY_EXTENSION_KEY, IdentityExtensionSchema);
|
|
575
1110
|
EXTENSION_SCHEMA_MAP.set(CORRELATION_EXTENSION_KEY, CorrelationExtensionSchema);
|
|
1111
|
+
EXTENSION_SCHEMA_MAP.set(CONSENT_EXTENSION_KEY, ConsentExtensionSchema);
|
|
1112
|
+
EXTENSION_SCHEMA_MAP.set(PRIVACY_EXTENSION_KEY, PrivacyExtensionSchema);
|
|
1113
|
+
EXTENSION_SCHEMA_MAP.set(SAFETY_EXTENSION_KEY, SafetyExtensionSchema);
|
|
1114
|
+
EXTENSION_SCHEMA_MAP.set(COMPLIANCE_EXTENSION_KEY, ComplianceExtensionSchema);
|
|
1115
|
+
EXTENSION_SCHEMA_MAP.set(PROVENANCE_EXTENSION_KEY, ProvenanceExtensionSchema);
|
|
1116
|
+
EXTENSION_SCHEMA_MAP.set(ATTRIBUTION_EXTENSION_KEY, AttributionExtensionSchema);
|
|
1117
|
+
EXTENSION_SCHEMA_MAP.set(PURPOSE_EXTENSION_KEY, PurposeExtensionSchema);
|
|
1118
|
+
|
|
1119
|
+
// src/wire-02-extensions/validation.ts
|
|
1120
|
+
var textEncoder = new TextEncoder();
|
|
1121
|
+
function jsonUtf8ByteLength(value) {
|
|
1122
|
+
try {
|
|
1123
|
+
return textEncoder.encode(JSON.stringify(value)).byteLength;
|
|
1124
|
+
} catch {
|
|
1125
|
+
return Infinity;
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
var MAX_JSON_GUARD_DEPTH = 64;
|
|
1129
|
+
function isPlainJsonValueRecursive(value, depth, seen) {
|
|
1130
|
+
if (depth > MAX_JSON_GUARD_DEPTH) return false;
|
|
1131
|
+
if (value === null) return true;
|
|
1132
|
+
const t = typeof value;
|
|
1133
|
+
if (t === "string" || t === "boolean") return true;
|
|
1134
|
+
if (t === "number") return Number.isFinite(value);
|
|
1135
|
+
if (t === "function" || t === "symbol" || t === "bigint" || t === "undefined") return false;
|
|
1136
|
+
if (t !== "object") return false;
|
|
1137
|
+
const obj = value;
|
|
1138
|
+
if (seen.has(obj)) return false;
|
|
1139
|
+
seen.add(obj);
|
|
1140
|
+
if (Array.isArray(obj)) {
|
|
1141
|
+
for (let i = 0; i < obj.length; i++) {
|
|
1142
|
+
if (!isPlainJsonValueRecursive(obj[i], depth + 1, seen)) return false;
|
|
1143
|
+
}
|
|
1144
|
+
return true;
|
|
1145
|
+
}
|
|
1146
|
+
const proto = Object.getPrototypeOf(obj);
|
|
1147
|
+
if (proto !== Object.prototype && proto !== null) return false;
|
|
1148
|
+
if (typeof obj.toJSON === "function") return false;
|
|
1149
|
+
const keys = Object.keys(obj);
|
|
1150
|
+
for (const key of keys) {
|
|
1151
|
+
if (!isPlainJsonValueRecursive(obj[key], depth + 1, seen)) {
|
|
1152
|
+
return false;
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
return true;
|
|
1156
|
+
}
|
|
1157
|
+
function isPlainJsonValue(value) {
|
|
1158
|
+
return isPlainJsonValueRecursive(value, 0, /* @__PURE__ */ new WeakSet());
|
|
1159
|
+
}
|
|
576
1160
|
function validateKnownExtensions(extensions, ctx) {
|
|
577
1161
|
if (extensions === void 0) return;
|
|
578
|
-
|
|
1162
|
+
const keys = Object.keys(extensions);
|
|
1163
|
+
for (const key of keys) {
|
|
579
1164
|
if (!isValidExtensionKey(key)) {
|
|
580
1165
|
ctx.addIssue({
|
|
581
1166
|
code: "custom",
|
|
@@ -584,6 +1169,14 @@ function validateKnownExtensions(extensions, ctx) {
|
|
|
584
1169
|
});
|
|
585
1170
|
continue;
|
|
586
1171
|
}
|
|
1172
|
+
if (!isPlainJsonValue(extensions[key])) {
|
|
1173
|
+
ctx.addIssue({
|
|
1174
|
+
code: "custom",
|
|
1175
|
+
message: kernel.ERROR_CODES.E_EXTENSION_NON_JSON_VALUE,
|
|
1176
|
+
path: ["extensions", key]
|
|
1177
|
+
});
|
|
1178
|
+
continue;
|
|
1179
|
+
}
|
|
587
1180
|
const schema = EXTENSION_SCHEMA_MAP.get(key);
|
|
588
1181
|
if (schema !== void 0) {
|
|
589
1182
|
const result = schema.safeParse(extensions[key]);
|
|
@@ -598,6 +1191,25 @@ function validateKnownExtensions(extensions, ctx) {
|
|
|
598
1191
|
}
|
|
599
1192
|
}
|
|
600
1193
|
}
|
|
1194
|
+
const totalBytes = jsonUtf8ByteLength(extensions);
|
|
1195
|
+
if (totalBytes > kernel.EXTENSION_BUDGET.maxTotalBytes) {
|
|
1196
|
+
ctx.addIssue({
|
|
1197
|
+
code: "custom",
|
|
1198
|
+
message: kernel.ERROR_CODES.E_EXTENSION_SIZE_EXCEEDED,
|
|
1199
|
+
path: ["extensions"]
|
|
1200
|
+
});
|
|
1201
|
+
return;
|
|
1202
|
+
}
|
|
1203
|
+
for (const key of keys) {
|
|
1204
|
+
const groupBytes = jsonUtf8ByteLength(extensions[key]);
|
|
1205
|
+
if (groupBytes > kernel.EXTENSION_BUDGET.maxGroupBytes) {
|
|
1206
|
+
ctx.addIssue({
|
|
1207
|
+
code: "custom",
|
|
1208
|
+
message: kernel.ERROR_CODES.E_EXTENSION_SIZE_EXCEEDED,
|
|
1209
|
+
path: ["extensions", key]
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
601
1213
|
}
|
|
602
1214
|
|
|
603
1215
|
// src/wire-02-envelope.ts
|
|
@@ -675,7 +1287,7 @@ var PolicyBlockSchema = zod.z.object({
|
|
|
675
1287
|
/**
|
|
676
1288
|
* HTTPS locator hint for the policy document.
|
|
677
1289
|
* MUST be an https:// URL (max 2048 chars).
|
|
678
|
-
* MUST NOT trigger auto-fetch; callers use this as a hint only
|
|
1290
|
+
* MUST NOT trigger auto-fetch; callers use this as a hint only.
|
|
679
1291
|
*/
|
|
680
1292
|
uri: zod.z.string().max(kernel.POLICY_BLOCK.uriMaxLength).url().refine((u) => u.startsWith("https://"), "policy.uri must be an https:// URL").optional(),
|
|
681
1293
|
/** Caller-assigned version label (max 256 chars) */
|
|
@@ -700,9 +1312,9 @@ var Wire02ClaimsSchema = zod.z.object({
|
|
|
700
1312
|
pillars: PillarsSchema.optional(),
|
|
701
1313
|
/** Top-level actor binding (sole location for ActorBinding in Wire 0.2) */
|
|
702
1314
|
actor: ActorBindingSchema.optional(),
|
|
703
|
-
/** Policy binding block
|
|
1315
|
+
/** Policy binding block */
|
|
704
1316
|
policy: PolicyBlockSchema.optional(),
|
|
705
|
-
/** Representation fields
|
|
1317
|
+
/** Representation fields: FingerprintRef validation, sha256-only, strict */
|
|
706
1318
|
representation: Wire02RepresentationFieldsSchema.optional(),
|
|
707
1319
|
/** ISO 8601 / RFC 3339 timestamp when the interaction occurred; evidence kind only */
|
|
708
1320
|
occurred_at: zod.z.string().datetime({ offset: true }).optional(),
|