@peac/schema 0.10.13 → 0.11.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.
Files changed (41) hide show
  1. package/dist/agent-identity.d.ts +62 -416
  2. package/dist/agent-identity.d.ts.map +1 -1
  3. package/dist/attestation-receipt.d.ts +5 -39
  4. package/dist/attestation-receipt.d.ts.map +1 -1
  5. package/dist/attribution.cjs +4 -2
  6. package/dist/attribution.cjs.map +1 -1
  7. package/dist/attribution.d.ts +69 -448
  8. package/dist/attribution.d.ts.map +1 -1
  9. package/dist/attribution.mjs +4 -2
  10. package/dist/attribution.mjs.map +1 -1
  11. package/dist/constraints.d.ts +68 -0
  12. package/dist/constraints.d.ts.map +1 -0
  13. package/dist/dispute.d.ts +262 -780
  14. package/dist/dispute.d.ts.map +1 -1
  15. package/dist/errors.d.ts +13 -0
  16. package/dist/errors.d.ts.map +1 -1
  17. package/dist/index.cjs +125 -10
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.ts +2 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.mjs +123 -11
  22. package/dist/index.mjs.map +1 -1
  23. package/dist/interaction.cjs +1 -1
  24. package/dist/interaction.cjs.map +1 -1
  25. package/dist/interaction.d.ts +104 -596
  26. package/dist/interaction.d.ts.map +1 -1
  27. package/dist/interaction.mjs +1 -1
  28. package/dist/interaction.mjs.map +1 -1
  29. package/dist/json.d.ts +4 -3
  30. package/dist/json.d.ts.map +1 -1
  31. package/dist/obligations.d.ts +39 -139
  32. package/dist/obligations.d.ts.map +1 -1
  33. package/dist/receipt-parser.cjs +4 -2
  34. package/dist/receipt-parser.cjs.map +1 -1
  35. package/dist/receipt-parser.mjs +4 -2
  36. package/dist/receipt-parser.mjs.map +1 -1
  37. package/dist/validators.d.ts +200 -659
  38. package/dist/validators.d.ts.map +1 -1
  39. package/dist/workflow.d.ts +32 -345
  40. package/dist/workflow.d.ts.map +1 -1
  41. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"attestation-receipt.d.ts","sourceRoot":"","sources":["../src/attestation-receipt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;GAEG;AACH,eAAO,MAAM,wBAAwB,EAAG,0BAAmC,CAAC;AAE5E;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,gDAAgD,CAAC;AAExF;;GAEG;AACH,eAAO,MAAM,kBAAkB;IAC7B,gCAAgC;;IAEhC,kCAAkC;;IAElC,6BAA6B;;IAE7B,iDAAiD;;IAEjD,4BAA4B;;IAE5B,+BAA+B;;IAE/B,+BAA+B;;CAEvB,CAAC;AAyBX;;;;;;;;GAQG;AACH,eAAO,MAAM,+BAA+B;IAExC,+CAA+C;;IAM/C,gDAAgD;;IAEhD,gCAAgC;;;;;;;;;;EAOzB,CAAC;AAEZ;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,wCAAoC,CAAC;AAE7E;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B;IAEvC,iDAAiD;;IAEjD,mBAAmB;;IAEnB,+BAA+B;;IAE/B,gCAAgC;;IAEhC,0BAA0B;;IAE1B,oCAAoC;;IAEpC,4BAA4B;;;;;;;;;;;;;;;;;;EAGrB,CAAC;AAMZ,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AACxF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAChF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAMtF;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,GAAG,2BAA2B,CAW5F;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,wBAAwB,CAE9F;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,OAAO,GAAG,2BAA2B,CAW7F;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,OAAO,GACf,OAAO,IAAI,yBAAyB,CAEtC;AAMD;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,oCAAoC;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,WAAW,CAAC,EAAE,yBAAyB,CAAC;IACxC,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,8BAA8B,GACrC,wBAAwB,CA4B1B;AAMD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAEzE"}
1
+ {"version":3,"file":"attestation-receipt.d.ts","sourceRoot":"","sources":["../src/attestation-receipt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;GAEG;AACH,eAAO,MAAM,wBAAwB,EAAG,0BAAmC,CAAC;AAE5E;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,gDAAgD,CAAC;AAExF;;GAEG;AACH,eAAO,MAAM,kBAAkB;IAC7B,gCAAgC;;IAEhC,kCAAkC;;IAElC,6BAA6B;;IAE7B,iDAAiD;;IAEjD,4BAA4B;;IAE5B,+BAA+B;;IAE/B,+BAA+B;;CAEvB,CAAC;AAyBX;;;;;;;;GAQG;AACH,eAAO,MAAM,+BAA+B;;;;kBAiBjC,CAAC;AAEZ;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,wCAAoC,CAAC;AAE7E;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B;;;;;;;;kBAiBhC,CAAC;AAMZ,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AACxF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAChF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAMtF;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,GAAG,2BAA2B,CAW5F;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,wBAAwB,CAE9F;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,OAAO,GAAG,2BAA2B,CAW7F;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,OAAO,GACf,OAAO,IAAI,yBAAyB,CAEtC;AAMD;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,oCAAoC;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,WAAW,CAAC,EAAE,yBAAyB,CAAC;IACxC,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,8BAA8B,GACrC,wBAAwB,CA4B1B;AAMD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAEzE"}
@@ -3,6 +3,8 @@
3
3
  var zod = require('zod');
4
4
 
5
5
  // src/attribution.ts
6
+
7
+ // src/json.ts
6
8
  function isPlainObject(value) {
7
9
  if (value === null || typeof value !== "object") {
8
10
  return false;
@@ -21,13 +23,13 @@ var JsonValueSchema = zod.z.lazy(
21
23
  zod.z.array(JsonValueSchema),
22
24
  // Plain object check then record validation
23
25
  PlainObjectSchema.transform((obj) => obj).pipe(
24
- zod.z.record(JsonValueSchema)
26
+ zod.z.record(zod.z.string(), JsonValueSchema)
25
27
  )
26
28
  ])
27
29
  );
28
30
  PlainObjectSchema.transform(
29
31
  (obj) => obj
30
- ).pipe(zod.z.record(JsonValueSchema));
32
+ ).pipe(zod.z.record(zod.z.string(), JsonValueSchema));
31
33
  zod.z.array(JsonValueSchema);
32
34
 
33
35
  // src/attribution.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/json.ts","../src/attribution.ts"],"names":["z"],"mappings":"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","file":"attribution.cjs","sourcesContent":["/**\n * JSON-safe validation schemas\n *\n * Provides Zod schemas that guarantee JSON roundtrip safety:\n * - Rejects NaN, Infinity, -Infinity (not valid JSON numbers)\n * - Rejects undefined (dropped by JSON.stringify)\n * - Rejects non-plain objects (Date, Map, Set, class instances)\n * - Rejects functions, symbols, bigints\n */\n\nimport { z } from 'zod';\nimport type { JsonValue, JsonObject, JsonArray } from '@peac/kernel';\n\n/**\n * Check if value is a plain object (not Date, Map, Set, class instance, etc.)\n *\n * A plain object has prototype of Object.prototype or null.\n * This rejects Date, Map, Set, Array, and class instances even when\n * they have zero enumerable properties (which would pass z.record()).\n */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * JSON number schema - rejects NaN and Infinity\n *\n * JSON.stringify(NaN) === \"null\" and JSON.stringify(Infinity) === \"null\"\n * which silently corrupts data. We reject these at validation time.\n */\nconst JsonNumberSchema = z.number().finite();\n\n/**\n * JSON primitive schema - string, finite number, boolean, null\n */\nexport const JsonPrimitiveSchema = z.union([z.string(), JsonNumberSchema, z.boolean(), z.null()]);\n\n/**\n * Plain object schema (internal) - validates object is plain before recursive validation\n */\nconst PlainObjectSchema = z.unknown().refine(isPlainObject, {\n message: 'Expected plain object, received non-plain object (Date, Map, Set, or class instance)',\n});\n\n/**\n * JSON value schema - recursive type for any valid JSON value\n *\n * Validates:\n * - Primitives: string, finite number, boolean, null\n * - Arrays: containing valid JSON values\n * - Objects: plain objects with string keys and valid JSON values\n *\n * Rejects:\n * - undefined (dropped by JSON.stringify)\n * - NaN, Infinity, -Infinity (become null in JSON)\n * - BigInt (throws in JSON.stringify)\n * - Date (becomes ISO string - implicit conversion)\n * - Map, Set (become {} in JSON)\n * - Functions, Symbols (dropped by JSON.stringify)\n * - Class instances (prototype chain lost)\n */\nexport const JsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>\n z.union([\n JsonPrimitiveSchema,\n z.array(JsonValueSchema),\n // Plain object check then record validation\n PlainObjectSchema.transform((obj) => obj as Record<string, unknown>).pipe(\n z.record(JsonValueSchema)\n ),\n ])\n) as z.ZodType<JsonValue>;\n\n/**\n * JSON object schema - plain object with string keys and JSON values\n *\n * Rejects non-plain objects (Date, Map, Set, class instances).\n */\nexport const JsonObjectSchema: z.ZodType<JsonObject> = PlainObjectSchema.transform(\n (obj) => obj as Record<string, unknown>\n).pipe(z.record(JsonValueSchema)) as z.ZodType<JsonObject>;\n\n/**\n * JSON array schema - array of JSON values\n */\nexport const JsonArraySchema: z.ZodType<JsonArray> = z.array(JsonValueSchema);\n\n/**\n * Default limits for JSON evidence validation\n *\n * These are conservative defaults to prevent DoS attacks via deeply nested\n * or excessively large JSON structures.\n */\nexport const JSON_EVIDENCE_LIMITS = {\n /** Maximum nesting depth (default: 32) */\n maxDepth: 32,\n /** Maximum array length (default: 10,000) */\n maxArrayLength: 10_000,\n /** Maximum object keys (default: 1,000) */\n maxObjectKeys: 1_000,\n /** Maximum string length in bytes (default: 65,536 = 64KB) */\n maxStringLength: 65_536,\n /** Maximum total nodes to visit (default: 100,000) */\n maxTotalNodes: 100_000,\n} as const;\n\n/**\n * Limits for JSON evidence validation\n *\n * @internal - Not part of public API. Use validateEvidence() with defaults.\n *\n * For testing only: import via UNSAFE_JsonEvidenceLimits\n */\nexport interface JsonEvidenceLimits {\n maxDepth?: number;\n maxArrayLength?: number;\n maxObjectKeys?: number;\n maxStringLength?: number;\n maxTotalNodes?: number;\n}\n\n/**\n * Result of JSON safety validation\n */\nexport type JsonSafetyResult =\n | { ok: true }\n | { ok: false; error: string; path: (string | number)[] };\n\n/**\n * Stack entry type for iterative traversal\n *\n * - \"enter\": entering an object/array, need to validate and push children\n * - \"exit\": exiting an object/array, remove from current path (for cycle detection)\n */\ntype StackEntry =\n | { type: 'enter'; value: unknown; path: (string | number)[]; depth: number }\n | { type: 'exit'; obj: object };\n\n/**\n * Iterative JSON safety validator\n *\n * Validates that a value is JSON-safe without using recursion, preventing\n * stack overflow on deeply nested structures. Uses an explicit stack for\n * traversal with entry/exit markers for correct cycle detection.\n *\n * Cycle Detection:\n * Uses a path-based approach where only objects on the current traversal\n * path are tracked. This correctly allows diamond structures (same object\n * referenced from multiple paths) while rejecting actual cycles (object\n * references itself through its descendants).\n *\n * Rejects:\n * - Cycles (object references itself directly or indirectly)\n * - Non-plain objects (Date, Map, Set, class instances)\n * - Non-finite numbers (NaN, Infinity, -Infinity)\n * - undefined, BigInt, functions, symbols\n * - Structures exceeding depth/size limits\n *\n * Allows:\n * - Diamond structures (same object referenced from multiple paths)\n *\n * @param value - Value to validate\n * @param limits - Optional limits (defaults to JSON_EVIDENCE_LIMITS)\n * @returns Result indicating success or failure with error details\n */\nexport function assertJsonSafeIterative(\n value: unknown,\n limits: JsonEvidenceLimits = {}\n): JsonSafetyResult {\n const maxDepth = limits.maxDepth ?? JSON_EVIDENCE_LIMITS.maxDepth;\n const maxArrayLength = limits.maxArrayLength ?? JSON_EVIDENCE_LIMITS.maxArrayLength;\n const maxObjectKeys = limits.maxObjectKeys ?? JSON_EVIDENCE_LIMITS.maxObjectKeys;\n const maxStringLength = limits.maxStringLength ?? JSON_EVIDENCE_LIMITS.maxStringLength;\n const maxTotalNodes = limits.maxTotalNodes ?? JSON_EVIDENCE_LIMITS.maxTotalNodes;\n\n // Track objects on the current traversal path for cycle detection.\n // An object appearing twice on the same path is a cycle.\n // An object appearing on different paths (diamond) is NOT a cycle.\n const pathSet = new WeakSet<object>();\n\n // Track total nodes visited for DoS protection\n let nodeCount = 0;\n\n // Stack with entry/exit markers for path tracking\n const stack: StackEntry[] = [{ type: 'enter', value, path: [], depth: 0 }];\n\n while (stack.length > 0) {\n const entry = stack.pop()!;\n\n // Handle exit marker - remove object from current path\n if (entry.type === 'exit') {\n pathSet.delete(entry.obj);\n continue;\n }\n\n const { value: current, path, depth } = entry;\n\n // Check total node limit\n nodeCount++;\n if (nodeCount > maxTotalNodes) {\n return {\n ok: false,\n error: `Maximum total nodes exceeded (limit: ${maxTotalNodes})`,\n path,\n };\n }\n\n // Check depth limit\n if (depth > maxDepth) {\n return {\n ok: false,\n error: `Maximum depth exceeded (limit: ${maxDepth})`,\n path,\n };\n }\n\n // Handle null (valid JSON)\n if (current === null) {\n continue;\n }\n\n // Handle primitives\n const type = typeof current;\n\n if (type === 'string') {\n if ((current as string).length > maxStringLength) {\n return {\n ok: false,\n error: `String exceeds maximum length (limit: ${maxStringLength})`,\n path,\n };\n }\n continue;\n }\n\n if (type === 'number') {\n if (!Number.isFinite(current as number)) {\n return {\n ok: false,\n error: `Non-finite number: ${current}`,\n path,\n };\n }\n continue;\n }\n\n if (type === 'boolean') {\n continue;\n }\n\n // Reject non-JSON types\n if (type === 'undefined') {\n return { ok: false, error: 'undefined is not valid JSON', path };\n }\n\n if (type === 'bigint') {\n return { ok: false, error: 'BigInt is not valid JSON', path };\n }\n\n if (type === 'function') {\n return { ok: false, error: 'Function is not valid JSON', path };\n }\n\n if (type === 'symbol') {\n return { ok: false, error: 'Symbol is not valid JSON', path };\n }\n\n // Handle objects (arrays and plain objects)\n if (type === 'object') {\n const obj = current as object;\n\n // Cycle detection - check if object is already on the current path\n // (not just visited anywhere, but specifically an ancestor)\n if (pathSet.has(obj)) {\n return { ok: false, error: 'Cycle detected in object graph', path };\n }\n\n // Add to current path and push exit marker to remove when done\n pathSet.add(obj);\n stack.push({ type: 'exit', obj });\n\n // Handle arrays\n if (Array.isArray(obj)) {\n if (obj.length > maxArrayLength) {\n return {\n ok: false,\n error: `Array exceeds maximum length (limit: ${maxArrayLength})`,\n path,\n };\n }\n // Push array elements to stack in reverse order for correct traversal\n for (let i = obj.length - 1; i >= 0; i--) {\n stack.push({ type: 'enter', value: obj[i], path: [...path, i], depth: depth + 1 });\n }\n continue;\n }\n\n // Check for non-plain objects (Date, Map, Set, class instances, etc.)\n const proto = Object.getPrototypeOf(obj);\n if (proto !== Object.prototype && proto !== null) {\n const constructorName = obj.constructor?.name ?? 'unknown';\n return {\n ok: false,\n error: `Non-plain object (${constructorName}) is not valid JSON`,\n path,\n };\n }\n\n // Handle plain objects\n const keys = Object.keys(obj);\n if (keys.length > maxObjectKeys) {\n return {\n ok: false,\n error: `Object exceeds maximum key count (limit: ${maxObjectKeys})`,\n path,\n };\n }\n // Push object values to stack\n for (let i = keys.length - 1; i >= 0; i--) {\n const key = keys[i];\n stack.push({\n type: 'enter',\n value: (obj as Record<string, unknown>)[key],\n path: [...path, key],\n depth: depth + 1,\n });\n }\n continue;\n }\n\n // Shouldn't reach here, but reject unknown types\n return { ok: false, error: `Unknown type: ${type}`, path };\n }\n\n return { ok: true };\n}\n","/**\n * Attribution Attestation Types and Validators (v0.9.26+)\n *\n * Provides content derivation and usage proof for PEAC receipts,\n * enabling chain tracking and compliance artifacts.\n *\n * @see docs/specs/ATTRIBUTION.md for normative specification\n */\nimport { z } from 'zod';\nimport type { JsonValue } from '@peac/kernel';\nimport { JsonValueSchema } from './json';\n\n// =============================================================================\n// ATTRIBUTION LIMITS (v0.9.26+)\n// =============================================================================\n\n/**\n * Attribution limits for DoS protection and verification feasibility.\n *\n * These are implementation safety limits, not protocol constraints.\n */\nexport const ATTRIBUTION_LIMITS = {\n /** Maximum sources per attestation */\n maxSources: 100,\n /** Maximum chain resolution depth */\n maxDepth: 8,\n /** Maximum attestation size in bytes (64KB) */\n maxAttestationSize: 65536,\n /** Per-hop resolution timeout in milliseconds */\n resolutionTimeout: 5000,\n /** Maximum receipt reference length */\n maxReceiptRefLength: 2048,\n /** Maximum model ID length */\n maxModelIdLength: 256,\n} as const;\n\n// =============================================================================\n// CONTENT HASH (v0.9.26+)\n// =============================================================================\n\n/**\n * Supported hash algorithms for content hashing.\n * Only sha-256 is supported in v0.9.26.\n */\nexport const HashAlgorithmSchema = z.literal('sha-256');\nexport type HashAlgorithm = z.infer<typeof HashAlgorithmSchema>;\n\n/**\n * Supported encoding formats for hash values.\n */\nexport const HashEncodingSchema = z.literal('base64url');\nexport type HashEncoding = z.infer<typeof HashEncodingSchema>;\n\n/**\n * ContentHash - deterministic content identification.\n *\n * Provides cryptographic verification of content identity using SHA-256.\n * The hash value is base64url-encoded without padding (RFC 4648 Section 5).\n *\n * @example\n * ```typescript\n * const hash: ContentHash = {\n * alg: 'sha-256',\n * value: 'n4bQgYhMfWWaL28IoEbM8Qa8jG7x0QXJZJqL-w_zZdA',\n * enc: 'base64url',\n * };\n * ```\n */\nexport const ContentHashSchema = z\n .object({\n /** Hash algorithm (REQUIRED, must be 'sha-256') */\n alg: HashAlgorithmSchema,\n\n /** Base64url-encoded hash value without padding (REQUIRED, 43 chars for SHA-256) */\n value: z\n .string()\n .min(43)\n .max(43)\n .regex(/^[A-Za-z0-9_-]+$/, 'Invalid base64url characters'),\n\n /** Encoding format (REQUIRED, must be 'base64url') */\n enc: HashEncodingSchema,\n })\n .strict();\nexport type ContentHash = z.infer<typeof ContentHashSchema>;\n\n// =============================================================================\n// ATTRIBUTION USAGE (v0.9.26+)\n// =============================================================================\n\n/**\n * How source content was used in derivation.\n *\n * - 'training_input': Used to train a model\n * - 'rag_context': Retrieved for RAG context\n * - 'direct_reference': Directly quoted or referenced\n * - 'synthesis_source': Combined with other sources to create new content\n * - 'embedding_source': Used to create embeddings/vectors\n */\nexport const AttributionUsageSchema = z.enum([\n 'training_input',\n 'rag_context',\n 'direct_reference',\n 'synthesis_source',\n 'embedding_source',\n]);\nexport type AttributionUsage = z.infer<typeof AttributionUsageSchema>;\n\n/**\n * Array of valid attribution usage types for runtime checks.\n */\nexport const ATTRIBUTION_USAGES = [\n 'training_input',\n 'rag_context',\n 'direct_reference',\n 'synthesis_source',\n 'embedding_source',\n] as const;\n\n// =============================================================================\n// DERIVATION TYPE (v0.9.26+)\n// =============================================================================\n\n/**\n * Type of content derivation.\n *\n * - 'training': Model training or fine-tuning\n * - 'inference': Runtime inference with RAG/grounding\n * - 'rag': Retrieval-augmented generation\n * - 'synthesis': Multi-source content synthesis\n * - 'embedding': Vector embedding generation\n */\nexport const DerivationTypeSchema = z.enum([\n 'training',\n 'inference',\n 'rag',\n 'synthesis',\n 'embedding',\n]);\nexport type DerivationType = z.infer<typeof DerivationTypeSchema>;\n\n/**\n * Array of valid derivation types for runtime checks.\n */\nexport const DERIVATION_TYPES = ['training', 'inference', 'rag', 'synthesis', 'embedding'] as const;\n\n// =============================================================================\n// ATTRIBUTION SOURCE (v0.9.26+)\n// =============================================================================\n\n/**\n * Receipt reference format validation.\n *\n * Valid formats:\n * - jti:{receipt_id} - Direct receipt identifier\n * - https://... - Resolvable receipt URL\n * - urn:peac:receipt:{id} - URN-formatted identifier\n */\nconst ReceiptRefSchema = z\n .string()\n .min(1)\n .max(ATTRIBUTION_LIMITS.maxReceiptRefLength)\n .refine(\n (ref) => {\n // jti: prefix\n if (ref.startsWith('jti:')) return true;\n // URL\n if (ref.startsWith('https://') || ref.startsWith('http://')) return true;\n // URN\n if (ref.startsWith('urn:peac:receipt:')) return true;\n return false;\n },\n { message: 'Invalid receipt reference format. Must be jti:{id}, URL, or urn:peac:receipt:{id}' }\n );\n\n/**\n * AttributionSource - links to a source receipt and describes how content was used.\n *\n * For cross-issuer resolution, include `receipt_issuer` when using `jti:*` references.\n * URL-based references (`https://...`) are self-resolvable.\n *\n * @example\n * ```typescript\n * const source: AttributionSource = {\n * receipt_ref: 'jti:rec_abc123def456',\n * receipt_issuer: 'https://publisher.example.com',\n * content_hash: { alg: 'sha-256', value: '...', enc: 'base64url' },\n * usage: 'rag_context',\n * weight: 0.3,\n * };\n * ```\n */\nexport const AttributionSourceSchema = z\n .object({\n /** Reference to source PEAC receipt (REQUIRED) */\n receipt_ref: ReceiptRefSchema,\n\n /**\n * Issuer of the referenced receipt (OPTIONAL but RECOMMENDED for jti: refs).\n *\n * Required for cross-issuer resolution when receipt_ref is jti:{id} format.\n * Not needed for URL-based references which are self-resolvable.\n * Used to construct resolution URL: {receipt_issuer}/.well-known/peac/receipts/{id}\n */\n receipt_issuer: z.string().url().max(2048).optional(),\n\n /** Hash of source content (OPTIONAL) */\n content_hash: ContentHashSchema.optional(),\n\n /** Hash of used excerpt (OPTIONAL, content-minimizing, not privacy-preserving for short text) */\n excerpt_hash: ContentHashSchema.optional(),\n\n /** How the source was used (REQUIRED) */\n usage: AttributionUsageSchema,\n\n /** Relative contribution weight 0.0-1.0 (OPTIONAL) */\n weight: z.number().min(0).max(1).optional(),\n })\n .strict();\nexport type AttributionSource = z.infer<typeof AttributionSourceSchema>;\n\n// =============================================================================\n// ATTRIBUTION EVIDENCE (v0.9.26+)\n// =============================================================================\n\n/**\n * AttributionEvidence - the payload of an AttributionAttestation.\n *\n * Contains the sources, derivation type, and optional output metadata.\n */\nexport const AttributionEvidenceSchema = z\n .object({\n /** Array of attribution sources (REQUIRED, 1-100 sources) */\n sources: z.array(AttributionSourceSchema).min(1).max(ATTRIBUTION_LIMITS.maxSources),\n\n /** Type of derivation (REQUIRED) */\n derivation_type: DerivationTypeSchema,\n\n /** Hash of derived output (OPTIONAL) */\n output_hash: ContentHashSchema.optional(),\n\n /** Model identifier (OPTIONAL) */\n model_id: z.string().max(ATTRIBUTION_LIMITS.maxModelIdLength).optional(),\n\n /** Inference provider URL (OPTIONAL) */\n inference_provider: z.string().url().max(2048).optional(),\n\n /** Session correlation ID (OPTIONAL) */\n session_id: z.string().max(256).optional(),\n\n /** Additional type-specific metadata (OPTIONAL) */\n metadata: z.record(z.string(), JsonValueSchema).optional(),\n })\n .strict();\nexport type AttributionEvidence = z.infer<typeof AttributionEvidenceSchema>;\n\n// =============================================================================\n// ATTRIBUTION ATTESTATION (v0.9.26+)\n// =============================================================================\n\n/**\n * Attestation type literal for attribution\n */\nexport const ATTRIBUTION_TYPE = 'peac/attribution' as const;\n\n/**\n * AttributionAttestation - proves content derivation and usage.\n *\n * This attestation provides cryptographic evidence that content was derived\n * from specific sources, enabling chain tracking and compliance.\n *\n * @example\n * ```typescript\n * const attestation: AttributionAttestation = {\n * type: 'peac/attribution',\n * issuer: 'https://ai.example.com',\n * issued_at: '2026-01-04T12:00:00Z',\n * evidence: {\n * sources: [\n * { receipt_ref: 'jti:rec_abc123', usage: 'rag_context', weight: 0.5 },\n * { receipt_ref: 'jti:rec_def456', usage: 'rag_context', weight: 0.5 },\n * ],\n * derivation_type: 'rag',\n * model_id: 'gpt-4',\n * },\n * };\n * ```\n */\nexport const AttributionAttestationSchema = z\n .object({\n /** Attestation type (MUST be 'peac/attribution') */\n type: z.literal(ATTRIBUTION_TYPE),\n\n /** Issuer of the attestation (inference provider, platform) */\n issuer: z.string().min(1).max(2048),\n\n /** When the attestation was issued (RFC 3339) */\n issued_at: z.string().datetime(),\n\n /** When the attestation expires (RFC 3339, OPTIONAL) */\n expires_at: z.string().datetime().optional(),\n\n /** Reference to external verification endpoint (OPTIONAL) */\n ref: z.string().url().max(2048).optional(),\n\n /** Attribution evidence */\n evidence: AttributionEvidenceSchema,\n })\n .strict();\nexport type AttributionAttestation = z.infer<typeof AttributionAttestationSchema>;\n\n// =============================================================================\n// CHAIN VERIFICATION RESULT (v0.9.26+)\n// =============================================================================\n\n/**\n * Result of chain verification including depth and resolved sources.\n */\nexport interface ChainVerificationResult {\n /** Whether the chain is valid */\n valid: boolean;\n /** Maximum depth encountered in the chain */\n maxDepth: number;\n /** Total number of sources across the chain */\n totalSources: number;\n /** Any cycle detected in the chain */\n cycleDetected?: string;\n /** Error message if validation failed */\n error?: string;\n}\n\n// =============================================================================\n// VALIDATION HELPERS (v0.9.26+)\n// =============================================================================\n\n/**\n * Validate a ContentHash.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated hash or error message\n */\nexport function validateContentHash(\n data: unknown\n): { ok: true; value: ContentHash } | { ok: false; error: string } {\n const result = ContentHashSchema.safeParse(data);\n if (result.success) {\n return { ok: true, value: result.data };\n }\n return { ok: false, error: result.error.message };\n}\n\n/**\n * Validate an AttributionSource.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated source or error message\n */\nexport function validateAttributionSource(\n data: unknown\n): { ok: true; value: AttributionSource } | { ok: false; error: string } {\n const result = AttributionSourceSchema.safeParse(data);\n if (result.success) {\n return { ok: true, value: result.data };\n }\n return { ok: false, error: result.error.message };\n}\n\n/**\n * Validate an AttributionAttestation.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated attestation or error message\n *\n * @example\n * ```typescript\n * const result = validateAttributionAttestation(data);\n * if (result.ok) {\n * console.log('Sources:', result.value.evidence.sources.length);\n * } else {\n * console.error('Validation error:', result.error);\n * }\n * ```\n */\nexport function validateAttributionAttestation(\n data: unknown\n): { ok: true; value: AttributionAttestation } | { ok: false; error: string } {\n const result = AttributionAttestationSchema.safeParse(data);\n if (result.success) {\n return { ok: true, value: result.data };\n }\n return { ok: false, error: result.error.message };\n}\n\n/**\n * Check if an object is an AttributionAttestation.\n *\n * @param attestation - Object with a type field\n * @returns True if the type is 'peac/attribution'\n */\nexport function isAttributionAttestation(attestation: {\n type: string;\n}): attestation is AttributionAttestation {\n return attestation.type === ATTRIBUTION_TYPE;\n}\n\n/**\n * Parameters for creating an AttributionAttestation.\n */\nexport interface CreateAttributionAttestationParams {\n /** Issuer of the attestation */\n issuer: string;\n /** Attribution sources */\n sources: AttributionSource[];\n /** Type of derivation */\n derivation_type: DerivationType;\n /** Hash of derived output (optional) */\n output_hash?: ContentHash;\n /** Model identifier (optional) */\n model_id?: string;\n /** Inference provider URL (optional) */\n inference_provider?: string;\n /** Session correlation ID (optional) */\n session_id?: string;\n /** When the attestation expires (optional) */\n expires_at?: string;\n /** External verification endpoint (optional) */\n ref?: string;\n /** Additional metadata (optional, must be JSON-safe) */\n metadata?: Record<string, JsonValue>;\n}\n\n/**\n * Create an AttributionAttestation with current timestamp.\n *\n * @param params - Attestation parameters\n * @returns A valid AttributionAttestation\n *\n * @example\n * ```typescript\n * const attestation = createAttributionAttestation({\n * issuer: 'https://ai.example.com',\n * sources: [\n * { receipt_ref: 'jti:rec_abc123', usage: 'rag_context' },\n * ],\n * derivation_type: 'rag',\n * model_id: 'gpt-4',\n * });\n * ```\n */\nexport function createAttributionAttestation(\n params: CreateAttributionAttestationParams\n): AttributionAttestation {\n const evidence: AttributionEvidence = {\n sources: params.sources,\n derivation_type: params.derivation_type,\n };\n\n if (params.output_hash) {\n evidence.output_hash = params.output_hash;\n }\n if (params.model_id) {\n evidence.model_id = params.model_id;\n }\n if (params.inference_provider) {\n evidence.inference_provider = params.inference_provider;\n }\n if (params.session_id) {\n evidence.session_id = params.session_id;\n }\n if (params.metadata) {\n evidence.metadata = params.metadata;\n }\n\n const attestation: AttributionAttestation = {\n type: ATTRIBUTION_TYPE,\n issuer: params.issuer,\n issued_at: new Date().toISOString(),\n evidence,\n };\n\n if (params.expires_at) {\n attestation.expires_at = params.expires_at;\n }\n if (params.ref) {\n attestation.ref = params.ref;\n }\n\n return attestation;\n}\n\n/**\n * Check if an attribution attestation is expired.\n *\n * @param attestation - The attestation to check\n * @param clockSkew - Optional clock skew tolerance in milliseconds (default: 30000)\n * @returns True if the attestation has expired\n */\nexport function isAttributionExpired(\n attestation: AttributionAttestation,\n clockSkew: number = 30000\n): boolean {\n if (!attestation.expires_at) {\n return false; // No expiry = never expires\n }\n const expiresAt = new Date(attestation.expires_at).getTime();\n const now = Date.now();\n return expiresAt < now - clockSkew;\n}\n\n/**\n * Check if an attribution attestation is not yet valid.\n *\n * @param attestation - The attestation to check\n * @param clockSkew - Optional clock skew tolerance in milliseconds (default: 30000)\n * @returns True if the attestation is not yet valid (issued_at in the future)\n */\nexport function isAttributionNotYetValid(\n attestation: AttributionAttestation,\n clockSkew: number = 30000\n): boolean {\n const issuedAt = new Date(attestation.issued_at).getTime();\n const now = Date.now();\n return issuedAt > now + clockSkew;\n}\n\n/**\n * Compute total weight of sources (for validation).\n *\n * @param sources - Array of attribution sources\n * @returns Total weight, or undefined if no weights specified\n */\nexport function computeTotalWeight(sources: AttributionSource[]): number | undefined {\n const weights = sources.filter((s) => s.weight !== undefined).map((s) => s.weight as number);\n if (weights.length === 0) {\n return undefined;\n }\n return weights.reduce((sum, w) => sum + w, 0);\n}\n\n/**\n * Detect cycles in attribution sources (for chain validation).\n *\n * @param sources - Array of attribution sources\n * @param visited - Set of visited receipt refs (for recursion)\n * @returns Receipt ref that caused cycle, or undefined if no cycle\n */\nexport function detectCycleInSources(\n sources: AttributionSource[],\n visited: Set<string> = new Set()\n): string | undefined {\n for (const source of sources) {\n if (visited.has(source.receipt_ref)) {\n return source.receipt_ref;\n }\n }\n return undefined;\n}\n"]}
1
+ {"version":3,"sources":["../src/json.ts","../src/attribution.ts"],"names":["z"],"mappings":"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","file":"attribution.cjs","sourcesContent":["/**\n * JSON-safe validation schemas\n *\n * Provides Zod schemas that guarantee JSON roundtrip safety:\n * - Rejects NaN, Infinity, -Infinity (not valid JSON numbers)\n * - Rejects undefined (dropped by JSON.stringify)\n * - Rejects non-plain objects (Date, Map, Set, class instances)\n * - Rejects functions, symbols, bigints\n */\n\nimport { z } from 'zod';\nimport type { JsonValue, JsonObject, JsonArray } from '@peac/kernel';\nimport { KERNEL_CONSTRAINTS } from './constraints';\n\n/**\n * Check if value is a plain object (not Date, Map, Set, class instance, etc.)\n *\n * A plain object has prototype of Object.prototype or null.\n * This rejects Date, Map, Set, Array, and class instances even when\n * they have zero enumerable properties (which would pass z.record()).\n */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * JSON number schema - rejects NaN and Infinity\n *\n * JSON.stringify(NaN) === \"null\" and JSON.stringify(Infinity) === \"null\"\n * which silently corrupts data. We reject these at validation time.\n */\nconst JsonNumberSchema = z.number().finite();\n\n/**\n * JSON primitive schema - string, finite number, boolean, null\n */\nexport const JsonPrimitiveSchema = z.union([z.string(), JsonNumberSchema, z.boolean(), z.null()]);\n\n/**\n * Plain object schema (internal) - validates object is plain before recursive validation\n */\nconst PlainObjectSchema = z.unknown().refine(isPlainObject, {\n message: 'Expected plain object, received non-plain object (Date, Map, Set, or class instance)',\n});\n\n/**\n * JSON value schema - recursive type for any valid JSON value\n *\n * Validates:\n * - Primitives: string, finite number, boolean, null\n * - Arrays: containing valid JSON values\n * - Objects: plain objects with string keys and valid JSON values\n *\n * Rejects:\n * - undefined (dropped by JSON.stringify)\n * - NaN, Infinity, -Infinity (become null in JSON)\n * - BigInt (throws in JSON.stringify)\n * - Date (becomes ISO string - implicit conversion)\n * - Map, Set (become {} in JSON)\n * - Functions, Symbols (dropped by JSON.stringify)\n * - Class instances (prototype chain lost)\n */\nexport const JsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>\n z.union([\n JsonPrimitiveSchema,\n z.array(JsonValueSchema),\n // Plain object check then record validation\n PlainObjectSchema.transform((obj) => obj as Record<string, unknown>).pipe(\n z.record(z.string(), JsonValueSchema)\n ),\n ])\n) as z.ZodType<JsonValue>;\n\n/**\n * JSON object schema - plain object with string keys and JSON values\n *\n * Rejects non-plain objects (Date, Map, Set, class instances).\n */\nexport const JsonObjectSchema: z.ZodType<JsonObject> = PlainObjectSchema.transform(\n (obj) => obj as Record<string, unknown>\n).pipe(z.record(z.string(), JsonValueSchema)) as z.ZodType<JsonObject>;\n\n/**\n * JSON array schema - array of JSON values\n */\nexport const JsonArraySchema: z.ZodType<JsonArray> = z.array(JsonValueSchema);\n\n/**\n * Default limits for JSON evidence validation.\n *\n * Derived from KERNEL_CONSTRAINTS (single source of truth).\n * These are conservative defaults to prevent DoS attacks via deeply nested\n * or excessively large JSON structures.\n */\nexport const JSON_EVIDENCE_LIMITS = {\n /** Maximum nesting depth (default: 32) */\n maxDepth: KERNEL_CONSTRAINTS.MAX_NESTED_DEPTH,\n /** Maximum array length (default: 10,000) */\n maxArrayLength: KERNEL_CONSTRAINTS.MAX_ARRAY_LENGTH,\n /** Maximum object keys (default: 1,000) */\n maxObjectKeys: KERNEL_CONSTRAINTS.MAX_OBJECT_KEYS,\n /** Maximum string length in code units (default: 65,536) */\n maxStringLength: KERNEL_CONSTRAINTS.MAX_STRING_LENGTH,\n /** Maximum total nodes to visit (default: 100,000) */\n maxTotalNodes: KERNEL_CONSTRAINTS.MAX_TOTAL_NODES,\n} as const;\n\n/**\n * Limits for JSON evidence validation\n *\n * @internal - Not part of public API. Use validateEvidence() with defaults.\n *\n * For testing only: import via UNSAFE_JsonEvidenceLimits\n */\nexport interface JsonEvidenceLimits {\n maxDepth?: number;\n maxArrayLength?: number;\n maxObjectKeys?: number;\n maxStringLength?: number;\n maxTotalNodes?: number;\n}\n\n/**\n * Result of JSON safety validation\n */\nexport type JsonSafetyResult =\n | { ok: true }\n | { ok: false; error: string; path: (string | number)[] };\n\n/**\n * Stack entry type for iterative traversal\n *\n * - \"enter\": entering an object/array, need to validate and push children\n * - \"exit\": exiting an object/array, remove from current path (for cycle detection)\n */\ntype StackEntry =\n | { type: 'enter'; value: unknown; path: (string | number)[]; depth: number }\n | { type: 'exit'; obj: object };\n\n/**\n * Iterative JSON safety validator\n *\n * Validates that a value is JSON-safe without using recursion, preventing\n * stack overflow on deeply nested structures. Uses an explicit stack for\n * traversal with entry/exit markers for correct cycle detection.\n *\n * Cycle Detection:\n * Uses a path-based approach where only objects on the current traversal\n * path are tracked. This correctly allows diamond structures (same object\n * referenced from multiple paths) while rejecting actual cycles (object\n * references itself through its descendants).\n *\n * Rejects:\n * - Cycles (object references itself directly or indirectly)\n * - Non-plain objects (Date, Map, Set, class instances)\n * - Non-finite numbers (NaN, Infinity, -Infinity)\n * - undefined, BigInt, functions, symbols\n * - Structures exceeding depth/size limits\n *\n * Allows:\n * - Diamond structures (same object referenced from multiple paths)\n *\n * @param value - Value to validate\n * @param limits - Optional limits (defaults to JSON_EVIDENCE_LIMITS)\n * @returns Result indicating success or failure with error details\n */\nexport function assertJsonSafeIterative(\n value: unknown,\n limits: JsonEvidenceLimits = {}\n): JsonSafetyResult {\n const maxDepth = limits.maxDepth ?? JSON_EVIDENCE_LIMITS.maxDepth;\n const maxArrayLength = limits.maxArrayLength ?? JSON_EVIDENCE_LIMITS.maxArrayLength;\n const maxObjectKeys = limits.maxObjectKeys ?? JSON_EVIDENCE_LIMITS.maxObjectKeys;\n const maxStringLength = limits.maxStringLength ?? JSON_EVIDENCE_LIMITS.maxStringLength;\n const maxTotalNodes = limits.maxTotalNodes ?? JSON_EVIDENCE_LIMITS.maxTotalNodes;\n\n // Track objects on the current traversal path for cycle detection.\n // An object appearing twice on the same path is a cycle.\n // An object appearing on different paths (diamond) is NOT a cycle.\n const pathSet = new WeakSet<object>();\n\n // Track total nodes visited for DoS protection\n let nodeCount = 0;\n\n // Stack with entry/exit markers for path tracking\n const stack: StackEntry[] = [{ type: 'enter', value, path: [], depth: 0 }];\n\n while (stack.length > 0) {\n const entry = stack.pop()!;\n\n // Handle exit marker - remove object from current path\n if (entry.type === 'exit') {\n pathSet.delete(entry.obj);\n continue;\n }\n\n const { value: current, path, depth } = entry;\n\n // Check total node limit\n nodeCount++;\n if (nodeCount > maxTotalNodes) {\n return {\n ok: false,\n error: `Maximum total nodes exceeded (limit: ${maxTotalNodes})`,\n path,\n };\n }\n\n // Check depth limit\n if (depth > maxDepth) {\n return {\n ok: false,\n error: `Maximum depth exceeded (limit: ${maxDepth})`,\n path,\n };\n }\n\n // Handle null (valid JSON)\n if (current === null) {\n continue;\n }\n\n // Handle primitives\n const type = typeof current;\n\n if (type === 'string') {\n if ((current as string).length > maxStringLength) {\n return {\n ok: false,\n error: `String exceeds maximum length (limit: ${maxStringLength})`,\n path,\n };\n }\n continue;\n }\n\n if (type === 'number') {\n if (!Number.isFinite(current as number)) {\n return {\n ok: false,\n error: `Non-finite number: ${current}`,\n path,\n };\n }\n continue;\n }\n\n if (type === 'boolean') {\n continue;\n }\n\n // Reject non-JSON types\n if (type === 'undefined') {\n return { ok: false, error: 'undefined is not valid JSON', path };\n }\n\n if (type === 'bigint') {\n return { ok: false, error: 'BigInt is not valid JSON', path };\n }\n\n if (type === 'function') {\n return { ok: false, error: 'Function is not valid JSON', path };\n }\n\n if (type === 'symbol') {\n return { ok: false, error: 'Symbol is not valid JSON', path };\n }\n\n // Handle objects (arrays and plain objects)\n if (type === 'object') {\n const obj = current as object;\n\n // Cycle detection - check if object is already on the current path\n // (not just visited anywhere, but specifically an ancestor)\n if (pathSet.has(obj)) {\n return { ok: false, error: 'Cycle detected in object graph', path };\n }\n\n // Add to current path and push exit marker to remove when done\n pathSet.add(obj);\n stack.push({ type: 'exit', obj });\n\n // Handle arrays\n if (Array.isArray(obj)) {\n if (obj.length > maxArrayLength) {\n return {\n ok: false,\n error: `Array exceeds maximum length (limit: ${maxArrayLength})`,\n path,\n };\n }\n // Push array elements to stack in reverse order for correct traversal\n for (let i = obj.length - 1; i >= 0; i--) {\n stack.push({ type: 'enter', value: obj[i], path: [...path, i], depth: depth + 1 });\n }\n continue;\n }\n\n // Check for non-plain objects (Date, Map, Set, class instances, etc.)\n const proto = Object.getPrototypeOf(obj);\n if (proto !== Object.prototype && proto !== null) {\n const constructorName = obj.constructor?.name ?? 'unknown';\n return {\n ok: false,\n error: `Non-plain object (${constructorName}) is not valid JSON`,\n path,\n };\n }\n\n // Handle plain objects\n const keys = Object.keys(obj);\n if (keys.length > maxObjectKeys) {\n return {\n ok: false,\n error: `Object exceeds maximum key count (limit: ${maxObjectKeys})`,\n path,\n };\n }\n // Push object values to stack\n for (let i = keys.length - 1; i >= 0; i--) {\n const key = keys[i];\n stack.push({\n type: 'enter',\n value: (obj as Record<string, unknown>)[key],\n path: [...path, key],\n depth: depth + 1,\n });\n }\n continue;\n }\n\n // Shouldn't reach here, but reject unknown types\n return { ok: false, error: `Unknown type: ${type}`, path };\n }\n\n return { ok: true };\n}\n","/**\n * Attribution Attestation Types and Validators (v0.9.26+)\n *\n * Provides content derivation and usage proof for PEAC receipts,\n * enabling chain tracking and compliance artifacts.\n *\n * @see docs/specs/ATTRIBUTION.md for normative specification\n */\nimport { z } from 'zod';\nimport type { JsonValue } from '@peac/kernel';\nimport { JsonValueSchema } from './json';\n\n// =============================================================================\n// ATTRIBUTION LIMITS (v0.9.26+)\n// =============================================================================\n\n/**\n * Attribution limits for DoS protection and verification feasibility.\n *\n * These are implementation safety limits, not protocol constraints.\n */\nexport const ATTRIBUTION_LIMITS = {\n /** Maximum sources per attestation */\n maxSources: 100,\n /** Maximum chain resolution depth */\n maxDepth: 8,\n /** Maximum attestation size in bytes (64KB) */\n maxAttestationSize: 65536,\n /** Per-hop resolution timeout in milliseconds */\n resolutionTimeout: 5000,\n /** Maximum receipt reference length */\n maxReceiptRefLength: 2048,\n /** Maximum model ID length */\n maxModelIdLength: 256,\n} as const;\n\n// =============================================================================\n// CONTENT HASH (v0.9.26+)\n// =============================================================================\n\n/**\n * Supported hash algorithms for content hashing.\n * Only sha-256 is supported in v0.9.26.\n */\nexport const HashAlgorithmSchema = z.literal('sha-256');\nexport type HashAlgorithm = z.infer<typeof HashAlgorithmSchema>;\n\n/**\n * Supported encoding formats for hash values.\n */\nexport const HashEncodingSchema = z.literal('base64url');\nexport type HashEncoding = z.infer<typeof HashEncodingSchema>;\n\n/**\n * ContentHash - deterministic content identification.\n *\n * Provides cryptographic verification of content identity using SHA-256.\n * The hash value is base64url-encoded without padding (RFC 4648 Section 5).\n *\n * @example\n * ```typescript\n * const hash: ContentHash = {\n * alg: 'sha-256',\n * value: 'n4bQgYhMfWWaL28IoEbM8Qa8jG7x0QXJZJqL-w_zZdA',\n * enc: 'base64url',\n * };\n * ```\n */\nexport const ContentHashSchema = z\n .object({\n /** Hash algorithm (REQUIRED, must be 'sha-256') */\n alg: HashAlgorithmSchema,\n\n /** Base64url-encoded hash value without padding (REQUIRED, 43 chars for SHA-256) */\n value: z\n .string()\n .min(43)\n .max(43)\n .regex(/^[A-Za-z0-9_-]+$/, 'Invalid base64url characters'),\n\n /** Encoding format (REQUIRED, must be 'base64url') */\n enc: HashEncodingSchema,\n })\n .strict();\nexport type ContentHash = z.infer<typeof ContentHashSchema>;\n\n// =============================================================================\n// ATTRIBUTION USAGE (v0.9.26+)\n// =============================================================================\n\n/**\n * How source content was used in derivation.\n *\n * - 'training_input': Used to train a model\n * - 'rag_context': Retrieved for RAG context\n * - 'direct_reference': Directly quoted or referenced\n * - 'synthesis_source': Combined with other sources to create new content\n * - 'embedding_source': Used to create embeddings/vectors\n */\nexport const AttributionUsageSchema = z.enum([\n 'training_input',\n 'rag_context',\n 'direct_reference',\n 'synthesis_source',\n 'embedding_source',\n]);\nexport type AttributionUsage = z.infer<typeof AttributionUsageSchema>;\n\n/**\n * Array of valid attribution usage types for runtime checks.\n */\nexport const ATTRIBUTION_USAGES = [\n 'training_input',\n 'rag_context',\n 'direct_reference',\n 'synthesis_source',\n 'embedding_source',\n] as const;\n\n// =============================================================================\n// DERIVATION TYPE (v0.9.26+)\n// =============================================================================\n\n/**\n * Type of content derivation.\n *\n * - 'training': Model training or fine-tuning\n * - 'inference': Runtime inference with RAG/grounding\n * - 'rag': Retrieval-augmented generation\n * - 'synthesis': Multi-source content synthesis\n * - 'embedding': Vector embedding generation\n */\nexport const DerivationTypeSchema = z.enum([\n 'training',\n 'inference',\n 'rag',\n 'synthesis',\n 'embedding',\n]);\nexport type DerivationType = z.infer<typeof DerivationTypeSchema>;\n\n/**\n * Array of valid derivation types for runtime checks.\n */\nexport const DERIVATION_TYPES = ['training', 'inference', 'rag', 'synthesis', 'embedding'] as const;\n\n// =============================================================================\n// ATTRIBUTION SOURCE (v0.9.26+)\n// =============================================================================\n\n/**\n * Receipt reference format validation.\n *\n * Valid formats:\n * - jti:{receipt_id} - Direct receipt identifier\n * - https://... - Resolvable receipt URL\n * - urn:peac:receipt:{id} - URN-formatted identifier\n */\nconst ReceiptRefSchema = z\n .string()\n .min(1)\n .max(ATTRIBUTION_LIMITS.maxReceiptRefLength)\n .refine(\n (ref) => {\n // jti: prefix\n if (ref.startsWith('jti:')) return true;\n // URL\n if (ref.startsWith('https://') || ref.startsWith('http://')) return true;\n // URN\n if (ref.startsWith('urn:peac:receipt:')) return true;\n return false;\n },\n { message: 'Invalid receipt reference format. Must be jti:{id}, URL, or urn:peac:receipt:{id}' }\n );\n\n/**\n * AttributionSource - links to a source receipt and describes how content was used.\n *\n * For cross-issuer resolution, include `receipt_issuer` when using `jti:*` references.\n * URL-based references (`https://...`) are self-resolvable.\n *\n * @example\n * ```typescript\n * const source: AttributionSource = {\n * receipt_ref: 'jti:rec_abc123def456',\n * receipt_issuer: 'https://publisher.example.com',\n * content_hash: { alg: 'sha-256', value: '...', enc: 'base64url' },\n * usage: 'rag_context',\n * weight: 0.3,\n * };\n * ```\n */\nexport const AttributionSourceSchema = z\n .object({\n /** Reference to source PEAC receipt (REQUIRED) */\n receipt_ref: ReceiptRefSchema,\n\n /**\n * Issuer of the referenced receipt (OPTIONAL but RECOMMENDED for jti: refs).\n *\n * Required for cross-issuer resolution when receipt_ref is jti:{id} format.\n * Not needed for URL-based references which are self-resolvable.\n * Used to construct resolution URL: {receipt_issuer}/.well-known/peac/receipts/{id}\n */\n receipt_issuer: z.string().url().max(2048).optional(),\n\n /** Hash of source content (OPTIONAL) */\n content_hash: ContentHashSchema.optional(),\n\n /** Hash of used excerpt (OPTIONAL, content-minimizing, not privacy-preserving for short text) */\n excerpt_hash: ContentHashSchema.optional(),\n\n /** How the source was used (REQUIRED) */\n usage: AttributionUsageSchema,\n\n /** Relative contribution weight 0.0-1.0 (OPTIONAL) */\n weight: z.number().min(0).max(1).optional(),\n })\n .strict();\nexport type AttributionSource = z.infer<typeof AttributionSourceSchema>;\n\n// =============================================================================\n// ATTRIBUTION EVIDENCE (v0.9.26+)\n// =============================================================================\n\n/**\n * AttributionEvidence - the payload of an AttributionAttestation.\n *\n * Contains the sources, derivation type, and optional output metadata.\n */\nexport const AttributionEvidenceSchema = z\n .object({\n /** Array of attribution sources (REQUIRED, 1-100 sources) */\n sources: z.array(AttributionSourceSchema).min(1).max(ATTRIBUTION_LIMITS.maxSources),\n\n /** Type of derivation (REQUIRED) */\n derivation_type: DerivationTypeSchema,\n\n /** Hash of derived output (OPTIONAL) */\n output_hash: ContentHashSchema.optional(),\n\n /** Model identifier (OPTIONAL) */\n model_id: z.string().max(ATTRIBUTION_LIMITS.maxModelIdLength).optional(),\n\n /** Inference provider URL (OPTIONAL) */\n inference_provider: z.string().url().max(2048).optional(),\n\n /** Session correlation ID (OPTIONAL) */\n session_id: z.string().max(256).optional(),\n\n /** Additional type-specific metadata (OPTIONAL) */\n metadata: z.record(z.string(), JsonValueSchema).optional(),\n })\n .strict();\nexport type AttributionEvidence = z.infer<typeof AttributionEvidenceSchema>;\n\n// =============================================================================\n// ATTRIBUTION ATTESTATION (v0.9.26+)\n// =============================================================================\n\n/**\n * Attestation type literal for attribution\n */\nexport const ATTRIBUTION_TYPE = 'peac/attribution' as const;\n\n/**\n * AttributionAttestation - proves content derivation and usage.\n *\n * This attestation provides cryptographic evidence that content was derived\n * from specific sources, enabling chain tracking and compliance.\n *\n * @example\n * ```typescript\n * const attestation: AttributionAttestation = {\n * type: 'peac/attribution',\n * issuer: 'https://ai.example.com',\n * issued_at: '2026-01-04T12:00:00Z',\n * evidence: {\n * sources: [\n * { receipt_ref: 'jti:rec_abc123', usage: 'rag_context', weight: 0.5 },\n * { receipt_ref: 'jti:rec_def456', usage: 'rag_context', weight: 0.5 },\n * ],\n * derivation_type: 'rag',\n * model_id: 'gpt-4',\n * },\n * };\n * ```\n */\nexport const AttributionAttestationSchema = z\n .object({\n /** Attestation type (MUST be 'peac/attribution') */\n type: z.literal(ATTRIBUTION_TYPE),\n\n /** Issuer of the attestation (inference provider, platform) */\n issuer: z.string().min(1).max(2048),\n\n /** When the attestation was issued (RFC 3339) */\n issued_at: z.string().datetime(),\n\n /** When the attestation expires (RFC 3339, OPTIONAL) */\n expires_at: z.string().datetime().optional(),\n\n /** Reference to external verification endpoint (OPTIONAL) */\n ref: z.string().url().max(2048).optional(),\n\n /** Attribution evidence */\n evidence: AttributionEvidenceSchema,\n })\n .strict();\nexport type AttributionAttestation = z.infer<typeof AttributionAttestationSchema>;\n\n// =============================================================================\n// CHAIN VERIFICATION RESULT (v0.9.26+)\n// =============================================================================\n\n/**\n * Result of chain verification including depth and resolved sources.\n */\nexport interface ChainVerificationResult {\n /** Whether the chain is valid */\n valid: boolean;\n /** Maximum depth encountered in the chain */\n maxDepth: number;\n /** Total number of sources across the chain */\n totalSources: number;\n /** Any cycle detected in the chain */\n cycleDetected?: string;\n /** Error message if validation failed */\n error?: string;\n}\n\n// =============================================================================\n// VALIDATION HELPERS (v0.9.26+)\n// =============================================================================\n\n/**\n * Validate a ContentHash.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated hash or error message\n */\nexport function validateContentHash(\n data: unknown\n): { ok: true; value: ContentHash } | { ok: false; error: string } {\n const result = ContentHashSchema.safeParse(data);\n if (result.success) {\n return { ok: true, value: result.data };\n }\n return { ok: false, error: result.error.message };\n}\n\n/**\n * Validate an AttributionSource.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated source or error message\n */\nexport function validateAttributionSource(\n data: unknown\n): { ok: true; value: AttributionSource } | { ok: false; error: string } {\n const result = AttributionSourceSchema.safeParse(data);\n if (result.success) {\n return { ok: true, value: result.data };\n }\n return { ok: false, error: result.error.message };\n}\n\n/**\n * Validate an AttributionAttestation.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated attestation or error message\n *\n * @example\n * ```typescript\n * const result = validateAttributionAttestation(data);\n * if (result.ok) {\n * console.log('Sources:', result.value.evidence.sources.length);\n * } else {\n * console.error('Validation error:', result.error);\n * }\n * ```\n */\nexport function validateAttributionAttestation(\n data: unknown\n): { ok: true; value: AttributionAttestation } | { ok: false; error: string } {\n const result = AttributionAttestationSchema.safeParse(data);\n if (result.success) {\n return { ok: true, value: result.data };\n }\n return { ok: false, error: result.error.message };\n}\n\n/**\n * Check if an object is an AttributionAttestation.\n *\n * @param attestation - Object with a type field\n * @returns True if the type is 'peac/attribution'\n */\nexport function isAttributionAttestation(attestation: {\n type: string;\n}): attestation is AttributionAttestation {\n return attestation.type === ATTRIBUTION_TYPE;\n}\n\n/**\n * Parameters for creating an AttributionAttestation.\n */\nexport interface CreateAttributionAttestationParams {\n /** Issuer of the attestation */\n issuer: string;\n /** Attribution sources */\n sources: AttributionSource[];\n /** Type of derivation */\n derivation_type: DerivationType;\n /** Hash of derived output (optional) */\n output_hash?: ContentHash;\n /** Model identifier (optional) */\n model_id?: string;\n /** Inference provider URL (optional) */\n inference_provider?: string;\n /** Session correlation ID (optional) */\n session_id?: string;\n /** When the attestation expires (optional) */\n expires_at?: string;\n /** External verification endpoint (optional) */\n ref?: string;\n /** Additional metadata (optional, must be JSON-safe) */\n metadata?: Record<string, JsonValue>;\n}\n\n/**\n * Create an AttributionAttestation with current timestamp.\n *\n * @param params - Attestation parameters\n * @returns A valid AttributionAttestation\n *\n * @example\n * ```typescript\n * const attestation = createAttributionAttestation({\n * issuer: 'https://ai.example.com',\n * sources: [\n * { receipt_ref: 'jti:rec_abc123', usage: 'rag_context' },\n * ],\n * derivation_type: 'rag',\n * model_id: 'gpt-4',\n * });\n * ```\n */\nexport function createAttributionAttestation(\n params: CreateAttributionAttestationParams\n): AttributionAttestation {\n const evidence: AttributionEvidence = {\n sources: params.sources,\n derivation_type: params.derivation_type,\n };\n\n if (params.output_hash) {\n evidence.output_hash = params.output_hash;\n }\n if (params.model_id) {\n evidence.model_id = params.model_id;\n }\n if (params.inference_provider) {\n evidence.inference_provider = params.inference_provider;\n }\n if (params.session_id) {\n evidence.session_id = params.session_id;\n }\n if (params.metadata) {\n evidence.metadata = params.metadata;\n }\n\n const attestation: AttributionAttestation = {\n type: ATTRIBUTION_TYPE,\n issuer: params.issuer,\n issued_at: new Date().toISOString(),\n evidence,\n };\n\n if (params.expires_at) {\n attestation.expires_at = params.expires_at;\n }\n if (params.ref) {\n attestation.ref = params.ref;\n }\n\n return attestation;\n}\n\n/**\n * Check if an attribution attestation is expired.\n *\n * @param attestation - The attestation to check\n * @param clockSkew - Optional clock skew tolerance in milliseconds (default: 30000)\n * @returns True if the attestation has expired\n */\nexport function isAttributionExpired(\n attestation: AttributionAttestation,\n clockSkew: number = 30000\n): boolean {\n if (!attestation.expires_at) {\n return false; // No expiry = never expires\n }\n const expiresAt = new Date(attestation.expires_at).getTime();\n const now = Date.now();\n return expiresAt < now - clockSkew;\n}\n\n/**\n * Check if an attribution attestation is not yet valid.\n *\n * @param attestation - The attestation to check\n * @param clockSkew - Optional clock skew tolerance in milliseconds (default: 30000)\n * @returns True if the attestation is not yet valid (issued_at in the future)\n */\nexport function isAttributionNotYetValid(\n attestation: AttributionAttestation,\n clockSkew: number = 30000\n): boolean {\n const issuedAt = new Date(attestation.issued_at).getTime();\n const now = Date.now();\n return issuedAt > now + clockSkew;\n}\n\n/**\n * Compute total weight of sources (for validation).\n *\n * @param sources - Array of attribution sources\n * @returns Total weight, or undefined if no weights specified\n */\nexport function computeTotalWeight(sources: AttributionSource[]): number | undefined {\n const weights = sources.filter((s) => s.weight !== undefined).map((s) => s.weight as number);\n if (weights.length === 0) {\n return undefined;\n }\n return weights.reduce((sum, w) => sum + w, 0);\n}\n\n/**\n * Detect cycles in attribution sources (for chain validation).\n *\n * @param sources - Array of attribution sources\n * @param visited - Set of visited receipt refs (for recursion)\n * @returns Receipt ref that caused cycle, or undefined if no cycle\n */\nexport function detectCycleInSources(\n sources: AttributionSource[],\n visited: Set<string> = new Set()\n): string | undefined {\n for (const source of sources) {\n if (visited.has(source.receipt_ref)) {\n return source.receipt_ref;\n }\n }\n return undefined;\n}\n"]}