@tinycloud/sdk-core 2.11.0-beta.9 → 2.11.1-beta.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 (32) hide show
  1. package/dist/{capability-BA49Uboq.d.cts → capability-BjzXwtNw.d.cts} +1 -1
  2. package/dist/{capability-BA49Uboq.d.ts → capability-BjzXwtNw.d.ts} +1 -1
  3. package/dist/credential-admission-C_cO1QqB.d.cts +781 -0
  4. package/dist/credential-admission-cvHe-HUC.d.ts +781 -0
  5. package/dist/delegations/index.cjs +620 -221
  6. package/dist/delegations/index.cjs.map +1 -1
  7. package/dist/delegations/index.d.cts +32 -32
  8. package/dist/delegations/index.d.ts +32 -32
  9. package/dist/delegations/index.js +622 -223
  10. package/dist/delegations/index.js.map +1 -1
  11. package/dist/index.cjs +3162 -1255
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +348 -18
  14. package/dist/index.d.ts +348 -18
  15. package/dist/index.js +3959 -2050
  16. package/dist/index.js.map +1 -1
  17. package/dist/policy/index.cjs +1273 -175
  18. package/dist/policy/index.cjs.map +1 -1
  19. package/dist/policy/index.d.cts +5 -4
  20. package/dist/policy/index.d.ts +5 -4
  21. package/dist/policy/index.js +1274 -176
  22. package/dist/policy/index.js.map +1 -1
  23. package/dist/{recipient-types.schema-D5pDlIqn.d.cts → recipient-types.schema-G8NEKRoo.d.cts} +240 -183
  24. package/dist/{recipient-types.schema-D5pDlIqn.d.ts → recipient-types.schema-G8NEKRoo.d.ts} +240 -183
  25. package/dist/requester/index.cjs.map +1 -1
  26. package/dist/requester/index.d.cts +1 -1
  27. package/dist/requester/index.d.ts +1 -1
  28. package/dist/requester/index.js +1 -1
  29. package/dist/requester/index.js.map +1 -1
  30. package/package.json +5 -5
  31. package/dist/signed-object-B3dMzh8O.d.ts +0 -149
  32. package/dist/signed-object-DwPZl6kV.d.cts +0 -149
@@ -323,16 +323,16 @@ function policyCapabilityContains(authority, request) {
323
323
  return caveatsContain(auth.caveats, req.caveats);
324
324
  }
325
325
  function normalizePolicyCapabilityWithOptions(input, options) {
326
- const object = expectObject(input, "$");
327
- assertExactKeys(object, ["service", "space", "path", "actions", "caveats"], "$");
328
- const service = requiredString(object, "service", "$", "policy-capability-malformed-service");
326
+ const object2 = expectObject(input, "$");
327
+ assertExactKeys(object2, ["service", "space", "path", "actions", "caveats"], "$");
328
+ const service = requiredString(object2, "service", "$", "policy-capability-malformed-service");
329
329
  if (!CEILING_SERVICES.has(service)) {
330
330
  throw new PolicyCapabilityError(
331
331
  "policy-capability-malformed-service",
332
332
  "$.service is outside the frozen permissionsCeiling vocabulary"
333
333
  );
334
334
  }
335
- const space = requiredString(object, "space", "$", "policy-capability-malformed-space");
335
+ const space = requiredString(object2, "space", "$", "policy-capability-malformed-space");
336
336
  validateConcreteSpace(space);
337
337
  const canonicalSpace = space.normalize("NFC");
338
338
  if (options.requireCanonical && canonicalSpace !== space) {
@@ -341,7 +341,7 @@ function normalizePolicyCapabilityWithOptions(input, options) {
341
341
  "$.space must already be canonical NFC"
342
342
  );
343
343
  }
344
- const rawPath = requiredString(object, "path", "$", "policy-capability-malformed-path");
344
+ const rawPath = requiredString(object2, "path", "$", "policy-capability-malformed-path");
345
345
  validateRawPath(rawPath, options);
346
346
  const path = normalizePath(rawPath);
347
347
  if (options.requireCanonical && path !== rawPath) {
@@ -352,7 +352,7 @@ function normalizePolicyCapabilityWithOptions(input, options) {
352
352
  }
353
353
  validateRawPath(path, options);
354
354
  const actions = normalizeActions(
355
- requiredArray(object, "actions", "$", "policy-capability-malformed-action"),
355
+ requiredArray(object2, "actions", "$", "policy-capability-malformed-action"),
356
356
  service,
357
357
  options
358
358
  );
@@ -361,9 +361,9 @@ function normalizePolicyCapabilityWithOptions(input, options) {
361
361
  output.space = canonicalSpace;
362
362
  output.path = path;
363
363
  output.actions = actions;
364
- if (hasOwn(object, "caveats")) {
364
+ if (hasOwn(object2, "caveats")) {
365
365
  output.caveats = validateCaveats(
366
- requiredValue(object, "caveats", "$", "policy-capability-malformed-caveats"),
366
+ requiredValue(object2, "caveats", "$", "policy-capability-malformed-caveats"),
367
367
  output.service
368
368
  );
369
369
  }
@@ -386,9 +386,9 @@ function expectObject(input, path) {
386
386
  );
387
387
  }
388
388
  }
389
- function assertExactKeys(object, allowed, path) {
389
+ function assertExactKeys(object2, allowed, path) {
390
390
  const allowedSet = new Set(allowed);
391
- for (const key of Object.keys(object)) {
391
+ for (const key of Object.keys(object2)) {
392
392
  if (!allowedSet.has(key)) {
393
393
  throw new PolicyCapabilityError(
394
394
  key === "id" || key === "scope" ? "policy-capability-malformed" : "policy-capability-unknown-key",
@@ -397,21 +397,21 @@ function assertExactKeys(object, allowed, path) {
397
397
  }
398
398
  }
399
399
  }
400
- function requiredValue(object, key, path, code2) {
401
- if (!hasOwn(object, key)) {
400
+ function requiredValue(object2, key, path, code2) {
401
+ if (!hasOwn(object2, key)) {
402
402
  throw new PolicyCapabilityError(code2, `${path}.${key} is required`);
403
403
  }
404
- return object[key];
404
+ return object2[key];
405
405
  }
406
- function requiredString(object, key, path, code2) {
407
- const value = requiredValue(object, key, path, code2);
406
+ function requiredString(object2, key, path, code2) {
407
+ const value = requiredValue(object2, key, path, code2);
408
408
  if (typeof value !== "string" || value.length === 0) {
409
409
  throw new PolicyCapabilityError(code2, `${path}.${key} must be a non-empty string`);
410
410
  }
411
411
  return value;
412
412
  }
413
- function requiredArray(object, key, path, code2) {
414
- const value = requiredValue(object, key, path, code2);
413
+ function requiredArray(object2, key, path, code2) {
414
+ const value = requiredValue(object2, key, path, code2);
415
415
  if (!Array.isArray(value)) {
416
416
  throw new PolicyCapabilityError(code2, `${path}.${key} must be an array`);
417
417
  }
@@ -556,11 +556,11 @@ function validateSqlStatement(input, path) {
556
556
  if (input === null || typeof input !== "object" || Array.isArray(input)) {
557
557
  throw new PolicyCapabilityError("policy-capability-malformed-caveats", `${path} must be an object`);
558
558
  }
559
- const object = input;
560
- assertCaveatKeys(object, ["name", "sql", "fixedParams"], path);
561
- caveatString(object, "name", path);
562
- caveatString(object, "sql", path);
563
- const fixedParams = requiredCaveat(object, "fixedParams", path);
559
+ const object2 = input;
560
+ assertCaveatKeys(object2, ["name", "sql", "fixedParams"], path);
561
+ caveatString(object2, "name", path);
562
+ caveatString(object2, "sql", path);
563
+ const fixedParams = requiredCaveat(object2, "fixedParams", path);
564
564
  if (!Array.isArray(fixedParams)) {
565
565
  throw new PolicyCapabilityError(
566
566
  "policy-capability-malformed-caveats",
@@ -575,20 +575,20 @@ function validateFixedParam(input, path) {
575
575
  if (input === null || typeof input !== "object" || Array.isArray(input)) {
576
576
  throw new PolicyCapabilityError("policy-capability-malformed-caveats", `${path} must be an object`);
577
577
  }
578
- const object = input;
579
- assertCaveatKeys(object, ["index", "value"], path);
580
- const index = requiredCaveat(object, "index", path);
578
+ const object2 = input;
579
+ assertCaveatKeys(object2, ["index", "value"], path);
580
+ const index = requiredCaveat(object2, "index", path);
581
581
  if (typeof index !== "number" || !Number.isSafeInteger(index) || index < 0) {
582
582
  throw new PolicyCapabilityError(
583
583
  "policy-capability-malformed-caveats",
584
584
  `${path}.index must be a non-negative integer`
585
585
  );
586
586
  }
587
- requiredCaveat(object, "value", path);
587
+ requiredCaveat(object2, "value", path);
588
588
  }
589
- function assertCaveatKeys(object, allowed, path) {
589
+ function assertCaveatKeys(object2, allowed, path) {
590
590
  const allowedSet = new Set(allowed);
591
- for (const key of Object.keys(object)) {
591
+ for (const key of Object.keys(object2)) {
592
592
  if (!allowedSet.has(key)) {
593
593
  throw new PolicyCapabilityError(
594
594
  "policy-capability-malformed-caveats",
@@ -597,17 +597,17 @@ function assertCaveatKeys(object, allowed, path) {
597
597
  }
598
598
  }
599
599
  }
600
- function requiredCaveat(object, key, path) {
601
- if (!hasOwn(object, key)) {
600
+ function requiredCaveat(object2, key, path) {
601
+ if (!hasOwn(object2, key)) {
602
602
  throw new PolicyCapabilityError(
603
603
  "policy-capability-malformed-caveats",
604
604
  `${path}.${key} is required`
605
605
  );
606
606
  }
607
- return object[key];
607
+ return object2[key];
608
608
  }
609
- function caveatString(object, key, path) {
610
- const value = requiredCaveat(object, key, path);
609
+ function caveatString(object2, key, path) {
610
+ const value = requiredCaveat(object2, key, path);
611
611
  if (typeof value !== "string" || value.length === 0) {
612
612
  throw new PolicyCapabilityError(
613
613
  "policy-capability-malformed-caveats",
@@ -638,8 +638,8 @@ function caveatsContain(authority, request) {
638
638
  (statement) => authorityStatements.some((candidate) => jcsCanonicalize(candidate) === jcsCanonicalize(statement))
639
639
  );
640
640
  }
641
- function hasOwn(object, key) {
642
- return objectHasOwn2(object, key);
641
+ function hasOwn(object2, key) {
642
+ return objectHasOwn2(object2, key);
643
643
  }
644
644
 
645
645
  // src/policy/signed-object.ts
@@ -1798,7 +1798,7 @@ var hashes = { ...sha2_browser_exports, ...identity_exports2 };
1798
1798
  import { bytesToHex as bytesToHex2, sha256 as sha2563, verifyMessage } from "viem";
1799
1799
 
1800
1800
  // src/identity.ts
1801
- import { getAddress, isAddress } from "viem";
1801
+ import { getAddress, isAddress, recoverMessageAddress } from "viem";
1802
1802
  var IdentityParseError = class extends Error {
1803
1803
  constructor(message) {
1804
1804
  super(message);
@@ -1909,17 +1909,17 @@ async function createAndSignSignedObject(input, signer) {
1909
1909
  }
1910
1910
  function createAndSignPolicy(input, signer) {
1911
1911
  return createAndSignSignedObject(input, signer).then(
1912
- (object) => validatePolicySignedShape(object)
1912
+ (object2) => validatePolicySignedShape(object2)
1913
1913
  );
1914
1914
  }
1915
1915
  function createAndSignPolicyStatus(input, signer) {
1916
1916
  return createAndSignSignedObject(input, signer).then(
1917
- (object) => validatePolicyStatusSignedShape(object)
1917
+ (object2) => validatePolicyStatusSignedShape(object2)
1918
1918
  );
1919
1919
  }
1920
1920
  function createAndSignPolicyEngineRecord(input, signer) {
1921
1921
  return createAndSignSignedObject(input, signer).then(
1922
- (object) => validatePolicyEngineRecordSignedShape(object)
1922
+ (object2) => validatePolicyEngineRecordSignedShape(object2)
1923
1923
  );
1924
1924
  }
1925
1925
  async function verifySignedObject(input) {
@@ -2023,9 +2023,9 @@ function validateUnsignedForDescriptor(input, descriptor) {
2023
2023
  }
2024
2024
  }
2025
2025
  function validatePolicyShape(input, signed) {
2026
- const object = expectJsonObject(normalizeJson(input), "$");
2026
+ const object2 = expectJsonObject(normalizeJson(input), "$");
2027
2027
  assertExactKeys2(
2028
- object,
2028
+ object2,
2029
2029
  signed ? [
2030
2030
  "schema",
2031
2031
  "policyId",
@@ -2053,30 +2053,30 @@ function validatePolicyShape(input, signed) {
2053
2053
  ],
2054
2054
  "$"
2055
2055
  );
2056
- expectConst(requiredString2(object, "schema", "$"), POLICY_SCHEMA, "$.schema");
2056
+ expectConst(requiredString2(object2, "schema", "$"), POLICY_SCHEMA, "$.schema");
2057
2057
  if (signed) {
2058
- requiredString2(object, "policyId", "$");
2059
- validateSignature(requiredValue2(object, "signature", "$"));
2058
+ requiredString2(object2, "policyId", "$");
2059
+ validateSignature(requiredValue2(object2, "signature", "$"));
2060
2060
  }
2061
- requiredString2(object, "ownerDid", "$");
2062
- requiredString2(object, "signingKeyDid", "$");
2063
- requiredDateString(object, "createdAt", "$");
2064
- optionalDateString(object, "expiresAt", "$");
2065
- validatePolicyResource(requiredValue2(object, "resource", "$"), "$.resource");
2066
- validateExpression(requiredValue2(object, "when", "$"), "$.when");
2067
- validateGrant(requiredValue2(object, "grant", "$"), "$.grant");
2068
- if (hasOwn2(object, "disclosure")) {
2069
- validateDisclosure(requiredValue2(object, "disclosure", "$"), "$.disclosure");
2061
+ requiredString2(object2, "ownerDid", "$");
2062
+ requiredString2(object2, "signingKeyDid", "$");
2063
+ requiredDateString(object2, "createdAt", "$");
2064
+ optionalDateString(object2, "expiresAt", "$");
2065
+ validatePolicyResource(requiredValue2(object2, "resource", "$"), "$.resource");
2066
+ validateExpression(requiredValue2(object2, "when", "$"), "$.when");
2067
+ validateGrant(requiredValue2(object2, "grant", "$"), "$.grant");
2068
+ if (hasOwn2(object2, "disclosure")) {
2069
+ validateDisclosure(requiredValue2(object2, "disclosure", "$"), "$.disclosure");
2070
2070
  }
2071
- if (hasOwn2(object, "audit")) {
2072
- validateAudit(requiredValue2(object, "audit", "$"), "$.audit");
2071
+ if (hasOwn2(object2, "audit")) {
2072
+ validateAudit(requiredValue2(object2, "audit", "$"), "$.audit");
2073
2073
  }
2074
- return object;
2074
+ return object2;
2075
2075
  }
2076
2076
  function validatePolicyStatusShape(input, signed) {
2077
- const object = expectJsonObject(normalizeJson(input), "$");
2077
+ const object2 = expectJsonObject(normalizeJson(input), "$");
2078
2078
  assertExactKeys2(
2079
- object,
2079
+ object2,
2080
2080
  signed ? [
2081
2081
  "schema",
2082
2082
  "statusId",
@@ -2100,28 +2100,28 @@ function validatePolicyStatusShape(input, signed) {
2100
2100
  ],
2101
2101
  "$"
2102
2102
  );
2103
- expectConst(requiredString2(object, "schema", "$"), POLICY_STATUS_SCHEMA, "$.schema");
2103
+ expectConst(requiredString2(object2, "schema", "$"), POLICY_STATUS_SCHEMA, "$.schema");
2104
2104
  if (signed) {
2105
- requiredString2(object, "statusId", "$");
2106
- validateSignature(requiredValue2(object, "signature", "$"));
2105
+ requiredString2(object2, "statusId", "$");
2106
+ validateSignature(requiredValue2(object2, "signature", "$"));
2107
2107
  }
2108
- requiredString2(object, "policyId", "$");
2109
- requiredString2(object, "ownerDid", "$");
2110
- requiredInteger(object, "sequence", "$", 0);
2111
- expectOneOf(requiredString2(object, "disposition", "$"), [
2108
+ requiredString2(object2, "policyId", "$");
2109
+ requiredString2(object2, "ownerDid", "$");
2110
+ requiredInteger(object2, "sequence", "$", 0);
2111
+ expectOneOf(requiredString2(object2, "disposition", "$"), [
2112
2112
  "active",
2113
2113
  "suspended",
2114
2114
  "revoked"
2115
2115
  ], "$.disposition");
2116
- requiredDateString(object, "effectiveAt", "$");
2117
- optionalString(object, "reasonCode", "$");
2118
- requiredString2(object, "signingKeyDid", "$");
2119
- return object;
2116
+ requiredDateString(object2, "effectiveAt", "$");
2117
+ optionalString(object2, "reasonCode", "$");
2118
+ requiredString2(object2, "signingKeyDid", "$");
2119
+ return object2;
2120
2120
  }
2121
2121
  function validatePolicyEngineRecordShape(input, signed) {
2122
- const object = expectJsonObject(normalizeJson(input), "$");
2122
+ const object2 = expectJsonObject(normalizeJson(input), "$");
2123
2123
  assertExactKeys2(
2124
- object,
2124
+ object2,
2125
2125
  signed ? [
2126
2126
  "schema",
2127
2127
  "engineRecordId",
@@ -2146,44 +2146,44 @@ function validatePolicyEngineRecordShape(input, signed) {
2146
2146
  "$"
2147
2147
  );
2148
2148
  expectConst(
2149
- requiredString2(object, "schema", "$"),
2149
+ requiredString2(object2, "schema", "$"),
2150
2150
  POLICY_ENGINE_RECORD_SCHEMA,
2151
2151
  "$.schema"
2152
2152
  );
2153
2153
  if (signed) {
2154
- requiredString2(object, "engineRecordId", "$");
2155
- validateSignature(requiredValue2(object, "signature", "$"));
2154
+ requiredString2(object2, "engineRecordId", "$");
2155
+ validateSignature(requiredValue2(object2, "signature", "$"));
2156
2156
  }
2157
- requiredString2(object, "ownerDid", "$");
2158
- requiredString2(object, "endpoint", "$");
2159
- requiredString2(object, "audience", "$");
2157
+ requiredString2(object2, "ownerDid", "$");
2158
+ requiredString2(object2, "endpoint", "$");
2159
+ requiredString2(object2, "audience", "$");
2160
2160
  requiredStringArray(
2161
- object,
2161
+ object2,
2162
2162
  "supportedPolicyVersions",
2163
2163
  "$",
2164
2164
  (value, path) => expectConst(value, "v0", path)
2165
2165
  );
2166
- requiredStringArray(object, "supportedEvidenceVerifiers", "$");
2167
- requiredString2(object, "grantIssuerDid", "$");
2168
- requiredDateString(object, "expiresAt", "$");
2169
- return object;
2166
+ requiredStringArray(object2, "supportedEvidenceVerifiers", "$");
2167
+ requiredString2(object2, "grantIssuerDid", "$");
2168
+ requiredDateString(object2, "expiresAt", "$");
2169
+ return object2;
2170
2170
  }
2171
2171
  function validateSignature(input) {
2172
- const object = expectJsonObject(input, "$.signature");
2173
- assertExactKeys2(object, ["suite", "signerDid", "value"], "$.signature");
2174
- const suite = requiredString2(object, "suite", "$.signature");
2172
+ const object2 = expectJsonObject(input, "$.signature");
2173
+ assertExactKeys2(object2, ["suite", "signerDid", "value"], "$.signature");
2174
+ const suite = requiredString2(object2, "suite", "$.signature");
2175
2175
  assertSupportedSignatureSuite(suite);
2176
- const signerDid = requiredString2(object, "signerDid", "$.signature");
2177
- const value = requiredString2(object, "value", "$.signature");
2176
+ const signerDid = requiredString2(object2, "signerDid", "$.signature");
2177
+ const value = requiredString2(object2, "value", "$.signature");
2178
2178
  decodeSignatureValue(value, suite);
2179
2179
  return { suite, signerDid, value };
2180
2180
  }
2181
2181
  function validatePolicyResource(input, path) {
2182
- const object = expectJsonObject(input, path);
2183
- assertExactKeys2(object, ["resourceType", "resourceId", "permissionsCeiling"], path);
2184
- requiredString2(object, "resourceType", path);
2185
- requiredString2(object, "resourceId", path);
2186
- const ceiling = requiredArray2(object, "permissionsCeiling", path, 1);
2182
+ const object2 = expectJsonObject(input, path);
2183
+ assertExactKeys2(object2, ["resourceType", "resourceId", "permissionsCeiling"], path);
2184
+ requiredString2(object2, "resourceType", path);
2185
+ requiredString2(object2, "resourceId", path);
2186
+ const ceiling = requiredArray2(object2, "permissionsCeiling", path, 1);
2187
2187
  for (let index = 0; index < ceiling.length; index++) {
2188
2188
  validatePolicyCapability(ceiling[index], `${path}.permissionsCeiling[${index}]`);
2189
2189
  }
@@ -2199,10 +2199,10 @@ function validatePolicyPermissionsCeilingForSigning(input) {
2199
2199
  }
2200
2200
  }
2201
2201
  function validatePolicyCapability(input, path) {
2202
- const object = expectJsonObject(input, path);
2202
+ const object2 = expectJsonObject(input, path);
2203
2203
  try {
2204
- const canonical = canonicalizePolicyCapability(object);
2205
- if (jcsCanonicalize(object) !== jcsCanonicalize(canonical)) {
2204
+ const canonical = canonicalizePolicyCapability(object2);
2205
+ if (jcsCanonicalize(object2) !== jcsCanonicalize(canonical)) {
2206
2206
  throw new SignedObjectSchemaError(`${path} must be canonical PolicyCapability JSON`);
2207
2207
  }
2208
2208
  } catch (error) {
@@ -2215,10 +2215,10 @@ function validatePolicyCapability(input, path) {
2215
2215
  }
2216
2216
  }
2217
2217
  function validatePolicyCapabilityForSigning(input, path) {
2218
- const object = expectJsonObject(input, path);
2218
+ const object2 = expectJsonObject(input, path);
2219
2219
  try {
2220
- const canonical = normalizePolicyCapability(object);
2221
- if (jcsCanonicalize(object) !== jcsCanonicalize(canonical)) {
2220
+ const canonical = normalizePolicyCapability(object2);
2221
+ if (jcsCanonicalize(object2) !== jcsCanonicalize(canonical)) {
2222
2222
  throw new SignedObjectSchemaError(`${path} must be strict canonical PolicyCapability JSON`);
2223
2223
  }
2224
2224
  } catch (error) {
@@ -2231,43 +2231,43 @@ function validatePolicyCapabilityForSigning(input, path) {
2231
2231
  }
2232
2232
  }
2233
2233
  function validateExpression(input, path) {
2234
- const object = expectJsonObject(input, path);
2235
- const keys = Object.keys(object);
2234
+ const object2 = expectJsonObject(input, path);
2235
+ const keys = Object.keys(object2);
2236
2236
  if (keys.length !== 1) {
2237
2237
  throw new SignedObjectSchemaError(`${path} must have exactly one expression key`);
2238
2238
  }
2239
2239
  const key = keys[0];
2240
2240
  if (key === "allOf" || key === "anyOf") {
2241
- const values = requiredArray2(object, key, path, 1);
2241
+ const values = requiredArray2(object2, key, path, 1);
2242
2242
  for (let index = 0; index < values.length; index++) {
2243
2243
  validateExpression(values[index], `${path}.${key}[${index}]`);
2244
2244
  }
2245
2245
  return;
2246
2246
  }
2247
2247
  if (key === "subject") {
2248
- const subject = expectJsonObject(requiredValue2(object, "subject", path), `${path}.subject`);
2248
+ const subject = expectJsonObject(requiredValue2(object2, "subject", path), `${path}.subject`);
2249
2249
  assertExactKeys2(subject, ["did"], `${path}.subject`);
2250
2250
  requiredString2(subject, "did", `${path}.subject`);
2251
2251
  return;
2252
2252
  }
2253
2253
  if (key === "evidence") {
2254
- validateEvidenceRequirement(requiredValue2(object, "evidence", path), `${path}.evidence`);
2254
+ validateEvidenceRequirement(requiredValue2(object2, "evidence", path), `${path}.evidence`);
2255
2255
  return;
2256
2256
  }
2257
2257
  throw new SignedObjectSchemaError(`${path} has unknown expression key ${key}`);
2258
2258
  }
2259
2259
  function validateEvidenceRequirement(input, path) {
2260
- const object = expectJsonObject(input, path);
2260
+ const object2 = expectJsonObject(input, path);
2261
2261
  assertExactKeys2(
2262
- object,
2262
+ object2,
2263
2263
  ["requirementId", "verifier", "requirements", "authority", "freshness"],
2264
2264
  path
2265
2265
  );
2266
- requiredString2(object, "requirementId", path);
2267
- requiredString2(object, "verifier", path);
2268
- requiredValue2(object, "requirements", path);
2269
- if (hasOwn2(object, "authority")) {
2270
- const authority = expectJsonObject(requiredValue2(object, "authority", path), `${path}.authority`);
2266
+ requiredString2(object2, "requirementId", path);
2267
+ requiredString2(object2, "verifier", path);
2268
+ requiredValue2(object2, "requirements", path);
2269
+ if (hasOwn2(object2, "authority")) {
2270
+ const authority = expectJsonObject(requiredValue2(object2, "authority", path), `${path}.authority`);
2271
2271
  assertExactKeys2(
2272
2272
  authority,
2273
2273
  ["profile", "acceptedIssuers", "allowOwnerAuthorizedIssuer"],
@@ -2279,35 +2279,35 @@ function validateEvidenceRequirement(input, path) {
2279
2279
  }
2280
2280
  optionalBoolean(authority, "allowOwnerAuthorizedIssuer", `${path}.authority`);
2281
2281
  }
2282
- if (hasOwn2(object, "freshness")) {
2283
- const freshness = expectJsonObject(requiredValue2(object, "freshness", path), `${path}.freshness`);
2282
+ if (hasOwn2(object2, "freshness")) {
2283
+ const freshness = expectJsonObject(requiredValue2(object2, "freshness", path), `${path}.freshness`);
2284
2284
  assertExactKeys2(freshness, ["maxStatusAgeSeconds"], `${path}.freshness`);
2285
2285
  requiredInteger(freshness, "maxStatusAgeSeconds", `${path}.freshness`, 0);
2286
2286
  }
2287
2287
  }
2288
2288
  function validateGrant(input, path) {
2289
- const object = expectJsonObject(input, path);
2290
- assertExactKeys2(object, ["output", "maxTtlSeconds", "delegationMode", "revocation"], path);
2291
- expectConst(requiredString2(object, "output", path), "portable-delegation", `${path}.output`);
2292
- requiredInteger(object, "maxTtlSeconds", path, 1);
2293
- expectOneOf(requiredString2(object, "delegationMode", path), [
2289
+ const object2 = expectJsonObject(input, path);
2290
+ assertExactKeys2(object2, ["output", "maxTtlSeconds", "delegationMode", "revocation"], path);
2291
+ expectConst(requiredString2(object2, "output", path), "portable-delegation", `${path}.output`);
2292
+ requiredInteger(object2, "maxTtlSeconds", path, 1);
2293
+ expectOneOf(requiredString2(object2, "delegationMode", path), [
2294
2294
  "terminal",
2295
2295
  "attenuable"
2296
2296
  ], `${path}.delegationMode`);
2297
- expectOneOf(requiredString2(object, "revocation", path), [
2297
+ expectOneOf(requiredString2(object2, "revocation", path), [
2298
2298
  "refresh_only",
2299
2299
  "active_cutoff"
2300
2300
  ], `${path}.revocation`);
2301
2301
  }
2302
2302
  function validateDisclosure(input, path) {
2303
- const object = expectJsonObject(input, path);
2304
- assertExactKeys2(object, ["denial"], path);
2305
- expectOneOf(requiredString2(object, "denial", path), ["none", "code", "debug"], `${path}.denial`);
2303
+ const object2 = expectJsonObject(input, path);
2304
+ assertExactKeys2(object2, ["denial"], path);
2305
+ expectOneOf(requiredString2(object2, "denial", path), ["none", "code", "debug"], `${path}.denial`);
2306
2306
  }
2307
2307
  function validateAudit(input, path) {
2308
- const object = expectJsonObject(input, path);
2309
- assertExactKeys2(object, ["issuance"], path);
2310
- expectOneOf(requiredString2(object, "issuance", path), ["off", "security", "full"], `${path}.issuance`);
2308
+ const object2 = expectJsonObject(input, path);
2309
+ assertExactKeys2(object2, ["issuance"], path);
2310
+ expectOneOf(requiredString2(object2, "issuance", path), ["off", "security", "full"], `${path}.issuance`);
2311
2311
  }
2312
2312
  function materialForUnsigned(unsigned, descriptor) {
2313
2313
  const jcs = jcsCanonicalize(unsigned);
@@ -2456,9 +2456,9 @@ function encodeSignatureValue(value, suite) {
2456
2456
  decodeSignatureValue(encoded, suite);
2457
2457
  return encoded;
2458
2458
  }
2459
- function stripOwnIdAndSignature(object, descriptor) {
2459
+ function stripOwnIdAndSignature(object2, descriptor) {
2460
2460
  const output = /* @__PURE__ */ Object.create(null);
2461
- for (const [key, value] of Object.entries(object)) {
2461
+ for (const [key, value] of Object.entries(object2)) {
2462
2462
  if (key === descriptor.idField || key === "signature") {
2463
2463
  continue;
2464
2464
  }
@@ -2467,8 +2467,8 @@ function stripOwnIdAndSignature(object, descriptor) {
2467
2467
  return output;
2468
2468
  }
2469
2469
  function descriptorForUnsigned(input) {
2470
- const object = expectJsonObject(normalizeJson(input), "$");
2471
- return descriptorForSchema(requiredString2(object, "schema", "$"));
2470
+ const object2 = expectJsonObject(normalizeJson(input), "$");
2471
+ return descriptorForSchema(requiredString2(object2, "schema", "$"));
2472
2472
  }
2473
2473
  function descriptorForSchema(schema) {
2474
2474
  if (schema === POLICY_SCHEMA) return DESCRIPTORS.Policy;
@@ -2482,28 +2482,28 @@ function expectJsonObject(input, path) {
2482
2482
  }
2483
2483
  return input;
2484
2484
  }
2485
- function assertExactKeys2(object, allowed, path) {
2485
+ function assertExactKeys2(object2, allowed, path) {
2486
2486
  const allowedSet = new Set(allowed);
2487
- for (const key of Object.keys(object)) {
2487
+ for (const key of Object.keys(object2)) {
2488
2488
  if (!allowedSet.has(key)) {
2489
2489
  throw new SignedObjectSchemaError(`${path} has unknown field ${key}`);
2490
2490
  }
2491
2491
  }
2492
2492
  }
2493
- function requiredValue2(object, key, path) {
2494
- if (!hasOwn2(object, key)) {
2493
+ function requiredValue2(object2, key, path) {
2494
+ if (!hasOwn2(object2, key)) {
2495
2495
  throw new SignedObjectSchemaError(`${path}.${key} is required`);
2496
2496
  }
2497
- return object[key];
2497
+ return object2[key];
2498
2498
  }
2499
- function requiredString2(object, key, path) {
2500
- return requireStringType(requiredValue2(object, key, path), `${path}.${key}`);
2499
+ function requiredString2(object2, key, path) {
2500
+ return requireStringType(requiredValue2(object2, key, path), `${path}.${key}`);
2501
2501
  }
2502
- function optionalString(object, key, path) {
2503
- if (!hasOwn2(object, key)) {
2502
+ function optionalString(object2, key, path) {
2503
+ if (!hasOwn2(object2, key)) {
2504
2504
  return;
2505
2505
  }
2506
- requireStringType(requiredValue2(object, key, path), `${path}.${key}`);
2506
+ requireStringType(requiredValue2(object2, key, path), `${path}.${key}`);
2507
2507
  }
2508
2508
  function requireStringType(value, path) {
2509
2509
  if (typeof value !== "string" || value.length === 0) {
@@ -2511,16 +2511,16 @@ function requireStringType(value, path) {
2511
2511
  }
2512
2512
  return value;
2513
2513
  }
2514
- function optionalBoolean(object, key, path) {
2515
- if (!hasOwn2(object, key)) {
2514
+ function optionalBoolean(object2, key, path) {
2515
+ if (!hasOwn2(object2, key)) {
2516
2516
  return;
2517
2517
  }
2518
- if (typeof requiredValue2(object, key, path) !== "boolean") {
2518
+ if (typeof requiredValue2(object2, key, path) !== "boolean") {
2519
2519
  throw new SignedObjectSchemaError(`${path}.${key} must be a boolean`);
2520
2520
  }
2521
2521
  }
2522
- function requiredInteger(object, key, path, minimum) {
2523
- const value = requiredValue2(object, key, path);
2522
+ function requiredInteger(object2, key, path, minimum) {
2523
+ const value = requiredValue2(object2, key, path);
2524
2524
  if (typeof value !== "number" || !Number.isSafeInteger(value) || value < minimum) {
2525
2525
  throw new SignedObjectSchemaError(
2526
2526
  `${path}.${key} must be an integer >= ${minimum}`
@@ -2528,8 +2528,8 @@ function requiredInteger(object, key, path, minimum) {
2528
2528
  }
2529
2529
  return value;
2530
2530
  }
2531
- function requiredArray2(object, key, path, minimum) {
2532
- const value = requiredValue2(object, key, path);
2531
+ function requiredArray2(object2, key, path, minimum) {
2532
+ const value = requiredValue2(object2, key, path);
2533
2533
  if (!Array.isArray(value) || value.length < minimum) {
2534
2534
  throw new SignedObjectSchemaError(
2535
2535
  `${path}.${key} must be an array with at least ${minimum} item(s)`
@@ -2537,22 +2537,22 @@ function requiredArray2(object, key, path, minimum) {
2537
2537
  }
2538
2538
  return value;
2539
2539
  }
2540
- function requiredStringArray(object, key, path, check) {
2541
- const values = requiredArray2(object, key, path, 0);
2540
+ function requiredStringArray(object2, key, path, check) {
2541
+ const values = requiredArray2(object2, key, path, 0);
2542
2542
  for (let index = 0; index < values.length; index++) {
2543
2543
  const itemPath = `${path}.${key}[${index}]`;
2544
2544
  const value = requireStringType(values[index], itemPath);
2545
2545
  check?.(value, itemPath);
2546
2546
  }
2547
2547
  }
2548
- function requiredDateString(object, key, path) {
2549
- assertRfc3339(requiredString2(object, key, path), `${path}.${key}`);
2548
+ function requiredDateString(object2, key, path) {
2549
+ assertRfc3339(requiredString2(object2, key, path), `${path}.${key}`);
2550
2550
  }
2551
- function optionalDateString(object, key, path) {
2552
- if (!hasOwn2(object, key)) {
2551
+ function optionalDateString(object2, key, path) {
2552
+ if (!hasOwn2(object2, key)) {
2553
2553
  return;
2554
2554
  }
2555
- assertRfc3339(requiredString2(object, key, path), `${path}.${key}`);
2555
+ assertRfc3339(requiredString2(object2, key, path), `${path}.${key}`);
2556
2556
  }
2557
2557
  function assertRfc3339(value, path) {
2558
2558
  const match = value.match(
@@ -2584,8 +2584,8 @@ function expectOneOf(actual, allowed, path) {
2584
2584
  }
2585
2585
  throw new SignedObjectSchemaError(`${path} has unsupported value ${actual}`);
2586
2586
  }
2587
- function hasOwn2(object, key) {
2588
- return objectHasOwn3(object, key);
2587
+ function hasOwn2(object2, key) {
2588
+ return objectHasOwn3(object2, key);
2589
2589
  }
2590
2590
  function assertSupportedSignatureSuite(suite) {
2591
2591
  if (suite !== ED25519_JCS_SIGNATURE_SUITE && suite !== EIP191_JCS_SIGNATURE_SUITE) {
@@ -2664,13 +2664,13 @@ function base64UrlDecode(value) {
2664
2664
  return decoded;
2665
2665
  }
2666
2666
  function hexToBytes(value) {
2667
- const hex = value.slice(2);
2668
- if (hex.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex)) {
2667
+ const hex3 = value.slice(2);
2668
+ if (hex3.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex3)) {
2669
2669
  throw new SignatureMaterialError("hex signature must have even length");
2670
2670
  }
2671
- const output = new Uint8Array(hex.length / 2);
2671
+ const output = new Uint8Array(hex3.length / 2);
2672
2672
  for (let index = 0; index < output.length; index++) {
2673
- output[index] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);
2673
+ output[index] = Number.parseInt(hex3.slice(index * 2, index * 2 + 2), 16);
2674
2674
  }
2675
2675
  return output;
2676
2676
  }
@@ -3021,9 +3021,9 @@ function expectPolicyEngineRecord(input) {
3021
3021
  );
3022
3022
  }
3023
3023
  }
3024
- function assertExactKeys3(object, allowed, path) {
3024
+ function assertExactKeys3(object2, allowed, path) {
3025
3025
  const allowedSet = new Set(allowed);
3026
- for (const key of Object.keys(object)) {
3026
+ for (const key of Object.keys(object2)) {
3027
3027
  if (!allowedSet.has(key)) {
3028
3028
  throw new PolicyAuthoringError(
3029
3029
  "policy-authoring-unknown-key",
@@ -3032,17 +3032,17 @@ function assertExactKeys3(object, allowed, path) {
3032
3032
  }
3033
3033
  }
3034
3034
  }
3035
- function requiredValue3(object, key, path) {
3036
- if (!hasOwn3(object, key)) {
3035
+ function requiredValue3(object2, key, path) {
3036
+ if (!hasOwn3(object2, key)) {
3037
3037
  throw new PolicyAuthoringError(
3038
3038
  "policy-authoring-malformed",
3039
3039
  `${path}.${key} is required`
3040
3040
  );
3041
3041
  }
3042
- return object[key];
3042
+ return object2[key];
3043
3043
  }
3044
- function requiredString3(object, key, path) {
3045
- const value = requiredValue3(object, key, path);
3044
+ function requiredString3(object2, key, path) {
3045
+ const value = requiredValue3(object2, key, path);
3046
3046
  if (typeof value !== "string" || value.length === 0) {
3047
3047
  throw new PolicyAuthoringError(
3048
3048
  "policy-authoring-malformed",
@@ -3051,11 +3051,11 @@ function requiredString3(object, key, path) {
3051
3051
  }
3052
3052
  return value;
3053
3053
  }
3054
- function fieldString(object, key, path, code2) {
3055
- if (!hasOwn3(object, key)) {
3054
+ function fieldString(object2, key, path, code2) {
3055
+ if (!hasOwn3(object2, key)) {
3056
3056
  throw new PolicyAuthoringError(code2, `${path}.${key} is required`);
3057
3057
  }
3058
- const value = object[key];
3058
+ const value = object2[key];
3059
3059
  if (typeof value !== "string" || value.length === 0) {
3060
3060
  throw new PolicyAuthoringError(
3061
3061
  code2,
@@ -3064,8 +3064,8 @@ function fieldString(object, key, path, code2) {
3064
3064
  }
3065
3065
  return value;
3066
3066
  }
3067
- function requiredObject(object, key, path) {
3068
- const value = requiredValue3(object, key, path);
3067
+ function requiredObject(object2, key, path) {
3068
+ const value = requiredValue3(object2, key, path);
3069
3069
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
3070
3070
  throw new PolicyAuthoringError(
3071
3071
  "policy-authoring-malformed",
@@ -3074,8 +3074,8 @@ function requiredObject(object, key, path) {
3074
3074
  }
3075
3075
  return value;
3076
3076
  }
3077
- function requiredArray3(object, key, path) {
3078
- const value = requiredValue3(object, key, path);
3077
+ function requiredArray3(object2, key, path) {
3078
+ const value = requiredValue3(object2, key, path);
3079
3079
  if (!Array.isArray(value)) {
3080
3080
  throw new PolicyAuthoringError(
3081
3081
  "policy-authoring-malformed",
@@ -3084,8 +3084,8 @@ function requiredArray3(object, key, path) {
3084
3084
  }
3085
3085
  return value;
3086
3086
  }
3087
- function requiredStringArray2(object, key, path) {
3088
- const values = requiredArray3(object, key, path);
3087
+ function requiredStringArray2(object2, key, path) {
3088
+ const values = requiredArray3(object2, key, path);
3089
3089
  return values.map((value, index) => {
3090
3090
  if (typeof value !== "string" || value.length === 0) {
3091
3091
  throw new PolicyAuthoringError(
@@ -3182,19 +3182,1086 @@ function parseStrictRfc3339(value, path) {
3182
3182
  var objectHasOwn4 = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
3183
3183
  Object.prototype.hasOwnProperty
3184
3184
  );
3185
- function hasOwn3(object, key) {
3186
- return objectHasOwn4(object, key);
3185
+ function hasOwn3(object2, key) {
3186
+ return objectHasOwn4(object2, key);
3187
+ }
3188
+
3189
+ // src/policy/unified.ts
3190
+ import { sha256 as sha2564 } from "@noble/hashes/sha256";
3191
+ import { blake3 } from "@noble/hashes/blake3";
3192
+ import { ed25519 as ed255192 } from "@noble/curves/ed25519";
3193
+ import { z } from "zod";
3194
+ var POLICY_V1_SCHEMA = "xyz.tinycloud.policy/policy/v1";
3195
+ var POLICY_CAPABILITY_V1_SCHEMA = "xyz.tinycloud.policy/capability/v1";
3196
+ var POLICY_ENFORCEMENT_DELEGATION_V2_SCHEMA = "xyz.tinycloud.policy/enforcement-delegation/v2";
3197
+ var ATTESTED_ENFORCER_BINDING_V2_SCHEMA = "xyz.tinycloud.policy/attested-enforcer/v2";
3198
+ var ROOT_STATUS_CHECKPOINT_V1_SCHEMA = "xyz.tinycloud.policy/root-status/v1";
3199
+ var ROOT_REVOCATION_V1_SCHEMA = "xyz.tinycloud.policy/root-revocation/v1";
3200
+ var POLICY_SESSION_UCAN_V1_PROFILE = "policy-session-ucan/v1";
3201
+ var POLICY_V1_DOMAIN = "xyz.tinycloud.policy/policy/v1\0";
3202
+ var POLICY_CAPABILITY_V1_DOMAIN = "xyz.tinycloud.policy/PolicyCapability/v1\0";
3203
+ var CONTENT_SOURCE_V1_DOMAIN = "xyz.tinycloud.policy/ContentSource/v1\0";
3204
+ var NATIVE_PROJECTION_V1_DOMAIN = "xyz.tinycloud.policy/NativeProjection/v1\0";
3205
+ var ROOT_STATUS_V1_DOMAIN = "xyz.tinycloud.policy/RootStatusCheckpoint/v1\0";
3206
+ var ROOT_STATUS_RENEWAL_V1_DOMAIN = "xyz.tinycloud.policy/RootStatusRenewal/v1\0";
3207
+ var ROOT_REVOCATION_V1_DOMAIN = "xyz.tinycloud.policy/RootRevocation/v1\0";
3208
+ var LAST_V2_CREATE_AT = "2026-09-30T00:00:00Z";
3209
+ var MAX_LEGACY_ENVELOPE_EXPIRES_AT = "2026-12-29T00:00:00Z";
3210
+ var LAST_V2_READ_AT = "2027-01-05T00:00:00Z";
3211
+ async function requestPolicyChallengeV3(input) {
3212
+ const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
3213
+ const response = await fetchFn(new URL("/share/v3/policy/challenges", input.nodeOrigin), {
3214
+ method: "POST",
3215
+ redirect: "error",
3216
+ headers: { accept: "application/json", "content-type": "application/json" },
3217
+ body: JSON.stringify({ policyCid: input.policyCid, recipientDid: input.recipientDid, requestedCapabilities: input.requestedCapabilities.map(normalizeUnifiedPolicyCapability) })
3218
+ });
3219
+ if (!response.ok) throw new Error(`policy challenge rejected (${response.status})`);
3220
+ const value = object(await response.json(), "policy challenge");
3221
+ if (typeof value.challengeId !== "string" || typeof value.nonce !== "string" || value.policyCid !== input.policyCid || value.recipientDid !== input.recipientDid)
3222
+ throw new Error("policy challenge binding is invalid");
3223
+ return value;
3224
+ }
3225
+ async function mintPolicySessionV3(input) {
3226
+ const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
3227
+ const challenge = input.challenge ?? await requestPolicyChallengeV3(input);
3228
+ if (challenge.policyCid !== input.policyCid || challenge.recipientDid !== input.recipientDid)
3229
+ throw new Error("policy challenge binding is invalid");
3230
+ const response = await fetchFn(new URL("/share/v3/policy/delegations", input.nodeOrigin), {
3231
+ method: "POST",
3232
+ redirect: "error",
3233
+ headers: { accept: "application/json", "content-type": "application/json" },
3234
+ body: JSON.stringify({ policyCid: input.policyCid, challengeId: challenge.challengeId, nonce: challenge.nonce, claim: input.claim, presentation: input.presentation })
3235
+ });
3236
+ if (!response.ok) throw new Error(`policy delegation rejected (${response.status})`);
3237
+ const value = object(await response.json(), "policy delegation");
3238
+ if (value.admitted !== true || typeof value.sessionCid !== "string" || typeof value.authorization !== "string")
3239
+ throw new Error("policy delegation response is invalid");
3240
+ const session = parsePolicySessionUcan(value.authorization, [input.policyRootCid, input.enforcementRootCid]);
3241
+ const expectedAttenuation = compactAttenuationForPolicyCapabilities(input.requestedCapabilities);
3242
+ if (session.cid !== value.sessionCid || session.aud !== input.recipientDid || session.fact.policyCid !== input.policyCid || session.fact.recipientDid !== input.recipientDid || session.fact.policyDelegationCid !== input.policyRootCid || session.fact.enforcementDelegationCid !== input.enforcementRootCid || jcsCanonicalize(session.att) !== jcsCanonicalize(expectedAttenuation) || Object.entries(input.expectedFacts ?? {}).some(([key, expected]) => session.fact[key] !== expected))
3243
+ throw new Error("policy delegation signed binding is invalid");
3244
+ return session;
3245
+ }
3246
+ function compactAttenuationForPolicyCapabilities(input) {
3247
+ const attenuation = {};
3248
+ for (const raw of input) {
3249
+ const capability = normalizeUnifiedPolicyCapability(raw);
3250
+ if (attenuation[capability.resource] !== void 0)
3251
+ throw new Error("policy capabilities contain a duplicate resource");
3252
+ attenuation[capability.resource] = capability.kind === "encryption" ? { [capability.action]: [{}] } : Object.fromEntries(capability.actions.map((action) => [action, [{
3253
+ type: "xyz.tinycloud.resource/selector",
3254
+ kind: capability.selector,
3255
+ value: capability.resource
3256
+ }]]));
3257
+ }
3258
+ return attenuation;
3259
+ }
3260
+ function verifyPolicyRootStatusCheckpointV3(input) {
3261
+ const checkpoint = input.checkpoint;
3262
+ const allowed = /* @__PURE__ */ new Set(["schema", "targetCid", "targetRole", "ownerDid", "nodeAudience", "state", "sequence", "checkedAt", "freshUntil", "revokedAt", "revocationCid", "previousCheckpointDigestHex", "issuerDid", "signature"]);
3263
+ if (Object.keys(checkpoint).some((key) => !allowed.has(key)) || checkpoint.schema !== ROOT_STATUS_CHECKPOINT_V1_SCHEMA || checkpoint.targetCid !== input.rootCid || checkpoint.targetRole !== "policy-authority" && checkpoint.targetRole !== "policy-enforcement" || checkpoint.state !== "active" && checkpoint.state !== "revoked" || typeof checkpoint.ownerDid !== "string" || typeof checkpoint.nodeAudience !== "string" || checkpoint.issuerDid !== checkpoint.nodeAudience || input.expectedNodeAudience !== void 0 && checkpoint.nodeAudience !== input.expectedNodeAudience || !Number.isInteger(checkpoint.sequence) || checkpoint.sequence < 1 || typeof checkpoint.checkedAt !== "string" || typeof checkpoint.freshUntil !== "string") return false;
3264
+ const checkedAt = Date.parse(checkpoint.checkedAt);
3265
+ const freshUntil = Date.parse(checkpoint.freshUntil);
3266
+ const now = (input.now ?? /* @__PURE__ */ new Date()).getTime();
3267
+ if (!Number.isFinite(checkedAt) || !Number.isFinite(freshUntil) || freshUntil < now || freshUntil <= checkedAt || freshUntil - checkedAt > 3e5) return false;
3268
+ if (checkpoint.sequence === 1 !== (checkpoint.previousCheckpointDigestHex === void 0)) return false;
3269
+ if (checkpoint.sequence !== 1 && (typeof checkpoint.previousCheckpointDigestHex !== "string" || !/^[0-9a-f]{64}$/.test(checkpoint.previousCheckpointDigestHex))) return false;
3270
+ if (checkpoint.state === "active" && (checkpoint.revokedAt !== void 0 || checkpoint.revocationCid !== void 0)) return false;
3271
+ if (checkpoint.state === "revoked" && (typeof checkpoint.revokedAt !== "string" || typeof checkpoint.revocationCid !== "string")) return false;
3272
+ const signature = checkpoint.signature;
3273
+ if (!isRecordValue(signature) || Object.keys(signature).length !== 3 || signature.suite !== "Ed25519" || signature.signerDid !== checkpoint.issuerDid || typeof signature.value !== "string") return false;
3274
+ try {
3275
+ const principal = checkpoint.issuerDid.split("#", 1)[0];
3276
+ const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
3277
+ if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1) return false;
3278
+ const unsigned = { ...checkpoint };
3279
+ delete unsigned.signature;
3280
+ return ed255192.verify(
3281
+ decodeBase64Url(signature.value),
3282
+ sha2564(new TextEncoder().encode(ROOT_STATUS_V1_DOMAIN + jcsCanonicalize(unsigned))),
3283
+ didMaterial.slice(2)
3284
+ );
3285
+ } catch {
3286
+ return false;
3287
+ }
3288
+ }
3289
+ async function getPolicyRootStatusV3(input) {
3290
+ const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
3291
+ const response = await fetchFn(new URL(`/share/v3/policy/status/${encodeURIComponent(input.rootCid)}`, input.nodeOrigin), {
3292
+ method: "GET",
3293
+ redirect: "error",
3294
+ headers: { accept: "application/json" }
3295
+ });
3296
+ if (!response.ok) throw new Error(`policy root status rejected (${response.status})`);
3297
+ const value = object(await response.json(), "policy root status");
3298
+ const checkpoint = object(value.checkpoint, "policy root checkpoint");
3299
+ if (value.rootCid !== input.rootCid || value.state !== "active" && value.state !== "revoked" || value.state !== checkpoint.state || !verifyPolicyRootStatusCheckpointV3({ rootCid: input.rootCid, checkpoint, expectedNodeAudience: input.expectedNodeAudience, now: input.now }))
3300
+ throw new Error("policy root status binding is invalid");
3301
+ const revocation = value.revocation === void 0 ? void 0 : object(value.revocation, "policy root revocation");
3302
+ if (value.state === "revoked" !== (revocation !== void 0) || revocation !== void 0 && !verifyPolicyRootRevocationV3({
3303
+ rootCid: input.rootCid,
3304
+ checkpoint,
3305
+ revocation,
3306
+ expectedEnforcerDid: input.expectedEnforcerDid
3307
+ })) throw new Error("policy root status revocation evidence is invalid");
3308
+ return { rootCid: input.rootCid, state: value.state, checkpoint, ...revocation === void 0 ? {} : { revocation } };
3309
+ }
3310
+ function verifyPolicyRootRevocationV3(input) {
3311
+ const value = input.revocation;
3312
+ const allowed = ["schema", "targetCid", "targetRole", "ownerDid", "nodeAudience", "revokedAt", "reason", "issuerDid", "signature"];
3313
+ if (Object.keys(value).length !== allowed.length || Object.keys(value).some((key) => !allowed.includes(key)) || value.schema !== ROOT_REVOCATION_V1_SCHEMA || value.targetCid !== input.rootCid || value.targetRole !== input.checkpoint.targetRole || value.ownerDid !== input.checkpoint.ownerDid || value.nodeAudience !== input.checkpoint.nodeAudience || value.revokedAt !== input.checkpoint.revokedAt || typeof value.reason !== "string" || value.reason.length === 0 || typeof value.issuerDid !== "string") return false;
3314
+ const authorized = value.issuerDid === value.ownerDid || value.targetRole === "policy-enforcement" && value.issuerDid === input.expectedEnforcerDid;
3315
+ if (!authorized) return false;
3316
+ const signature = value.signature;
3317
+ if (!isRecordValue(signature) || Object.keys(signature).length !== 3 || signature.suite !== "Ed25519" || signature.signerDid !== value.issuerDid || typeof signature.value !== "string") return false;
3318
+ try {
3319
+ const principal = value.issuerDid.split("#", 1)[0];
3320
+ const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
3321
+ if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1) return false;
3322
+ const unsigned = { ...value };
3323
+ delete unsigned.signature;
3324
+ const digest2 = sha2564(new TextEncoder().encode(ROOT_REVOCATION_V1_DOMAIN + jcsCanonicalize(unsigned)));
3325
+ return input.checkpoint.revocationCid === hex(digest2) && ed255192.verify(decodeBase64Url(signature.value), digest2, didMaterial.slice(2));
3326
+ } catch {
3327
+ return false;
3328
+ }
3329
+ }
3330
+ async function renewPolicyRootStatusV3(input) {
3331
+ const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
3332
+ const current = await getPolicyRootStatusV3({ nodeOrigin: input.nodeOrigin, rootCid: input.rootCid, expectedNodeAudience: input.nodeAudience, now: input.now, fetch: fetchFn });
3333
+ if (current.state !== "active" || current.checkpoint.ownerDid !== input.ownerDid || current.checkpoint.nodeAudience !== input.nodeAudience || current.checkpoint.state !== "active" || !Number.isInteger(current.checkpoint.sequence))
3334
+ throw new Error("policy root status cannot be renewed");
3335
+ const currentUnsigned = { ...current.checkpoint };
3336
+ delete currentUnsigned.signature;
3337
+ const previousCheckpointDigestHex = hex(sha2564(new TextEncoder().encode(ROOT_STATUS_V1_DOMAIN + jcsCanonicalize(currentUnsigned))));
3338
+ const unsigned = {
3339
+ schema: "xyz.tinycloud.policy/root-status-renewal/v1",
3340
+ targetCid: input.rootCid,
3341
+ ownerDid: input.ownerDid,
3342
+ nodeAudience: input.nodeAudience,
3343
+ issuedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
3344
+ nonce: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
3345
+ sequence: current.checkpoint.sequence + 1,
3346
+ previousCheckpointDigestHex
3347
+ };
3348
+ const signature = await input.sign(sha2564(new TextEncoder().encode(ROOT_STATUS_RENEWAL_V1_DOMAIN + jcsCanonicalize(unsigned))));
3349
+ if (signature.length !== 64) throw new Error("policy root renewal signature must be Ed25519");
3350
+ const response = await fetchFn(new URL("/share/v3/policy/status", input.nodeOrigin), {
3351
+ method: "POST",
3352
+ redirect: "error",
3353
+ headers: { accept: "application/json", "content-type": "application/json" },
3354
+ body: JSON.stringify({ rootCid: input.rootCid, renewal: { ...unsigned, signature: { suite: "Ed25519", signerDid: input.ownerDid, value: encodeBase64Url(signature) } } })
3355
+ });
3356
+ if (!response.ok) throw new Error(`policy root renewal rejected (${response.status})`);
3357
+ return object(await response.json(), "policy root renewal");
3358
+ }
3359
+ async function revokePolicyRootV3(input) {
3360
+ if (input.reason.length === 0) throw new Error("policy root revocation reason is required");
3361
+ const unsigned = {
3362
+ schema: ROOT_REVOCATION_V1_SCHEMA,
3363
+ targetCid: input.rootCid,
3364
+ targetRole: input.targetRole,
3365
+ ownerDid: input.ownerDid,
3366
+ nodeAudience: input.nodeAudience,
3367
+ revokedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
3368
+ reason: input.reason,
3369
+ issuerDid: input.issuerDid
3370
+ };
3371
+ const signature = await input.sign(sha2564(new TextEncoder().encode(ROOT_REVOCATION_V1_DOMAIN + jcsCanonicalize(unsigned))));
3372
+ if (signature.length !== 64) throw new Error("policy root revocation signature must be Ed25519");
3373
+ const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
3374
+ const response = await fetchFn(new URL("/revoke", input.nodeOrigin), {
3375
+ method: "POST",
3376
+ redirect: "error",
3377
+ headers: { accept: "application/json", "content-type": "application/json" },
3378
+ body: JSON.stringify({ revocation: { ...unsigned, signature: { suite: "Ed25519", signerDid: input.issuerDid, value: encodeBase64Url(signature) } } })
3379
+ });
3380
+ if (!response.ok) throw new Error(`policy root revocation rejected (${response.status})`);
3381
+ return object(await response.json(), "policy root revocation");
3382
+ }
3383
+ var POLICY_SESSION_FACT_KEYS = [
3384
+ "profile",
3385
+ "ownerDid",
3386
+ "policyId",
3387
+ "policyDigestHex",
3388
+ "policyCid",
3389
+ "policyDelegationCid",
3390
+ "enforcementDelegationCid",
3391
+ "contentSourceDigestHex",
3392
+ "capabilityCeilingHashHex",
3393
+ "nativeProjectionHashHex",
3394
+ "enforcerDid",
3395
+ "nodeAudience",
3396
+ "recipientDid",
3397
+ "challengeId",
3398
+ "claimDigestHex",
3399
+ "claimJti",
3400
+ "vpDigestHex",
3401
+ "credentialEvidenceDigestHex",
3402
+ "decisionContextDigestHex",
3403
+ "issuanceAuditDigestHex",
3404
+ "remainingRedelegationDepth"
3405
+ ];
3406
+ var KV_ACTIONS = /* @__PURE__ */ new Set([
3407
+ "tinycloud.kv/get",
3408
+ "tinycloud.kv/list",
3409
+ "tinycloud.kv/metadata",
3410
+ "tinycloud.kv/put"
3411
+ ]);
3412
+ function object(value, label) {
3413
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
3414
+ throw new Error(`${label} must be an object`);
3415
+ }
3416
+ return value;
3417
+ }
3418
+ function exactKeys(value, allowed, label) {
3419
+ const keys = new Set(allowed);
3420
+ if (Object.keys(value).some((key) => !keys.has(key)))
3421
+ throw new Error(`${label} contains an unknown field`);
3422
+ }
3423
+ function nonEmptyString(value, label) {
3424
+ if (typeof value !== "string" || value.length === 0)
3425
+ throw new Error(`${label} must be a non-empty string`);
3426
+ return value;
3427
+ }
3428
+ function parseKvResource(resource) {
3429
+ const marker = resource.indexOf("/kv/");
3430
+ const encodedSpace = marker < 1 ? "" : resource.slice(0, marker);
3431
+ const legacy = encodedSpace.startsWith("tinycloud://");
3432
+ const space = legacy ? encodedSpace.slice("tinycloud://".length) : encodedSpace;
3433
+ const path = marker < 1 ? "" : resource.slice(marker + 4);
3434
+ if (marker < 1 || (legacy ? /[:/?#%]/.test(space) : !encodedSpace.startsWith("tinycloud:") || /[/?#%]/.test(encodedSpace)) || path.startsWith("/") || path.endsWith("/") || path.includes("//") || path.split("/").some((part) => part === "." || part === ".." || part.length === 0)) {
3435
+ throw new Error("KV resource is not canonical");
3436
+ }
3437
+ return { space, path };
3438
+ }
3439
+ function parseEncryptionResource(resource) {
3440
+ if (!resource.startsWith("urn:tinycloud:encryption:")) throw new Error("encryption capability is invalid");
3441
+ const rest = resource.slice("urn:tinycloud:encryption:".length);
3442
+ const separator = rest.lastIndexOf(":");
3443
+ const ownerDid = separator < 0 ? "" : rest.slice(0, separator);
3444
+ const network = separator < 0 ? "" : rest.slice(separator + 1);
3445
+ if (!ownerDid.startsWith("did:") || network.length === 0 || network.includes(":") || network.includes("/") || network.includes("%") || network.includes("?") || network.includes("#")) {
3446
+ throw new Error("encryption capability is invalid");
3447
+ }
3448
+ }
3449
+ function normalizeUnifiedPolicyCapability(input) {
3450
+ const value = object(input, "capability");
3451
+ const kind = nonEmptyString(value.kind, "capability.kind");
3452
+ if (kind === "kv") {
3453
+ exactKeys(
3454
+ value,
3455
+ ["kind", "resource", "selector", "actions"],
3456
+ "KV capability"
3457
+ );
3458
+ const resource = nonEmptyString(value.resource, "capability.resource");
3459
+ parseKvResource(resource);
3460
+ if (value.selector !== "exact" && value.selector !== "prefix")
3461
+ throw new Error("capability.selector is invalid");
3462
+ if (!Array.isArray(value.actions) || value.actions.length === 0)
3463
+ throw new Error("capability.actions is invalid");
3464
+ const actions = value.actions.map(
3465
+ (action) => nonEmptyString(action, "capability.actions[]")
3466
+ );
3467
+ if (new Set(actions).size !== actions.length || actions.some((action) => !KV_ACTIONS.has(action)))
3468
+ throw new Error("capability.actions is invalid");
3469
+ return {
3470
+ kind: "kv",
3471
+ resource,
3472
+ selector: value.selector,
3473
+ actions: [...actions].sort()
3474
+ };
3475
+ }
3476
+ if (kind === "encryption") {
3477
+ exactKeys(value, ["kind", "resource", "action"], "encryption capability");
3478
+ const resource = nonEmptyString(value.resource, "capability.resource");
3479
+ if (value.action !== "tinycloud.encryption/decrypt")
3480
+ throw new Error("encryption capability is invalid");
3481
+ parseEncryptionResource(resource);
3482
+ return {
3483
+ kind: "encryption",
3484
+ resource,
3485
+ action: "tinycloud.encryption/decrypt"
3486
+ };
3487
+ }
3488
+ throw new Error("capability.kind is invalid");
3489
+ }
3490
+ function canonicalizeUnifiedPolicyCapability(input) {
3491
+ return normalizeUnifiedPolicyCapability(input);
3492
+ }
3493
+ function unifiedPolicyCapabilityDigestHex(input) {
3494
+ return hex(
3495
+ sha2564(
3496
+ new TextEncoder().encode(
3497
+ POLICY_CAPABILITY_V1_DOMAIN + jcsCanonicalize(normalizeUnifiedPolicyCapability(input))
3498
+ )
3499
+ )
3500
+ );
3501
+ }
3502
+ function unifiedPolicyCapabilityContains(authorityInput, requestedInput) {
3503
+ try {
3504
+ const authority = normalizeUnifiedPolicyCapability(authorityInput);
3505
+ const requested = normalizeUnifiedPolicyCapability(requestedInput);
3506
+ if (authority.kind !== requested.kind) return false;
3507
+ if (authority.kind === "encryption" && requested.kind === "encryption")
3508
+ return authority.resource === requested.resource && authority.action === requested.action;
3509
+ if (authority.kind !== "kv" || requested.kind !== "kv") return false;
3510
+ const { resource: authorized } = authority;
3511
+ const { resource: requestedResource } = requested;
3512
+ const pathContained = authority.selector === "exact" ? authorized === requestedResource : authorized === requestedResource || requestedResource.startsWith(`${authorized}/`);
3513
+ if (!pathContained || authority.selector === "exact" && requested.selector === "prefix")
3514
+ return false;
3515
+ return requested.actions.every(
3516
+ (action) => authority.actions.includes(action)
3517
+ );
3518
+ } catch {
3519
+ return false;
3520
+ }
3521
+ }
3522
+ function projectUnifiedPolicyCapability(input) {
3523
+ const capability = normalizeUnifiedPolicyCapability(input);
3524
+ if (capability.kind === "encryption") {
3525
+ return {
3526
+ service: "tinycloud.encryption",
3527
+ space: capability.resource,
3528
+ path: capability.resource,
3529
+ actions: [capability.action]
3530
+ };
3531
+ }
3532
+ const { space, path } = parseKvResource(capability.resource);
3533
+ return {
3534
+ service: "tinycloud.kv",
3535
+ space,
3536
+ path,
3537
+ actions: [...capability.actions],
3538
+ caveat: {
3539
+ type: "xyz.tinycloud.resource/selector",
3540
+ kind: capability.selector,
3541
+ value: capability.resource
3542
+ }
3543
+ };
3544
+ }
3545
+ function projectUnifiedPolicyCapabilities(input) {
3546
+ return input.map(projectUnifiedPolicyCapability).sort((left, right) => {
3547
+ const a = jcsCanonicalize(left);
3548
+ const b = jcsCanonicalize(right);
3549
+ return a < b ? -1 : a > b ? 1 : 0;
3550
+ });
3551
+ }
3552
+ function unifiedNativeProjectionHashHex(input) {
3553
+ return hex(
3554
+ sha2564(
3555
+ new TextEncoder().encode(
3556
+ NATIVE_PROJECTION_V1_DOMAIN + jcsCanonicalize(projectUnifiedPolicyCapabilities(input))
3557
+ )
3558
+ )
3559
+ );
3560
+ }
3561
+ function unifiedPolicyCapabilityFromNative(input) {
3562
+ const value = object(input, "native capability");
3563
+ exactKeys(
3564
+ value,
3565
+ ["service", "space", "path", "actions", "caveat"],
3566
+ "native capability"
3567
+ );
3568
+ const service = nonEmptyString(value.service, "native.service");
3569
+ const actions = value.actions;
3570
+ if (!Array.isArray(actions)) throw new Error("native.actions is invalid");
3571
+ if (service === "tinycloud.encryption" && value.caveat === void 0 && value.space === value.path && actions.length === 1 && actions[0] === "tinycloud.encryption/decrypt") {
3572
+ return normalizeUnifiedPolicyCapability({
3573
+ kind: "encryption",
3574
+ resource: value.space,
3575
+ action: actions[0]
3576
+ });
3577
+ }
3578
+ if (service !== "tinycloud.kv" || typeof value.space !== "string" || typeof value.path !== "string")
3579
+ throw new Error("native capability is not supported");
3580
+ const caveat = object(value.caveat, "native.caveat");
3581
+ exactKeys(caveat, ["type", "kind", "value"], "native selector caveat");
3582
+ if (caveat.type !== "xyz.tinycloud.resource/selector" || caveat.kind !== "exact" && caveat.kind !== "prefix" || caveat.value !== `${value.space.startsWith("tinycloud:") ? value.space : `tinycloud://${value.space}`}/kv/${value.path}`)
3583
+ throw new Error("native selector caveat does not match capability");
3584
+ return normalizeUnifiedPolicyCapability({
3585
+ kind: "kv",
3586
+ resource: caveat.value,
3587
+ selector: caveat.kind,
3588
+ actions
3589
+ });
3590
+ }
3591
+ function contentSourceDigestHex(input) {
3592
+ return hex(
3593
+ sha2564(
3594
+ new TextEncoder().encode(
3595
+ CONTENT_SOURCE_V1_DOMAIN + jcsCanonicalize(input)
3596
+ )
3597
+ )
3598
+ );
3599
+ }
3600
+ function policyDigestHex(policy) {
3601
+ const canonicalPolicy = {
3602
+ ...policy,
3603
+ capabilityCeiling: policy.capabilityCeiling.map(
3604
+ normalizeUnifiedPolicyCapability
3605
+ )
3606
+ };
3607
+ return hex(
3608
+ sha2564(
3609
+ new TextEncoder().encode(
3610
+ POLICY_V1_DOMAIN + jcsCanonicalize(canonicalPolicy)
3611
+ )
3612
+ )
3613
+ );
3614
+ }
3615
+ function policyIdForDigestHex(digestHex) {
3616
+ const digest2 = Uint8Array.from(
3617
+ (digestHex.match(/.{2}/g) ?? []).map((byte) => Number.parseInt(byte, 16))
3618
+ );
3619
+ if (digest2.length !== 32) throw new Error("policy digest must be 32 bytes");
3620
+ return `pol_${base32Lower(digest2)}`;
3621
+ }
3622
+ function policyCidFromCanonicalBytes(bytes) {
3623
+ return CID.createV1(85, create(18, sha2564(bytes))).toString();
3624
+ }
3625
+ var CompactHeaderSchema = z.object({
3626
+ alg: z.literal("EdDSA"),
3627
+ jwk: z.object({ alg: z.literal("EdDSA"), crv: z.literal("Ed25519"), kty: z.literal("OKP"), x: z.string().min(1) }).strict(),
3628
+ typ: z.literal("JWT"),
3629
+ ucv: z.literal("0.10.0")
3630
+ }).strict();
3631
+ var CompactPayloadSchema = z.object({
3632
+ att: z.record(z.record(z.array(z.unknown()).min(1))),
3633
+ aud: z.string().min(1),
3634
+ exp: z.number().int(),
3635
+ fct: z.array(z.record(z.unknown())).length(1),
3636
+ iss: z.string().min(1),
3637
+ nbf: z.number().int(),
3638
+ nnc: z.string().min(1),
3639
+ prf: z.array(z.string().min(1))
3640
+ }).strict();
3641
+ async function signCompactUcan(input) {
3642
+ const principal = input.issuerDid.split("#", 1)[0];
3643
+ const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
3644
+ if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
3645
+ throw new Error("compact UCAN signer must be did:key Ed25519");
3646
+ const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(didMaterial.slice(2)) }, typ: "JWT", ucv: "0.10.0" };
3647
+ const payload = {
3648
+ att: input.attenuation,
3649
+ aud: input.audienceDid,
3650
+ exp: input.expiresAt,
3651
+ fct: input.facts,
3652
+ iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
3653
+ nbf: input.notBefore,
3654
+ nnc: input.nonce,
3655
+ prf: input.proofs
3656
+ };
3657
+ const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
3658
+ const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
3659
+ const signature = await input.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`));
3660
+ if (signature.length !== 64) throw new Error("compact Authorization signature must be Ed25519");
3661
+ return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
3662
+ }
3663
+ async function signCompactUcanAuthorization(input) {
3664
+ if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > 60)
3665
+ throw new Error("compact invocation lifetime must be between one and 60 seconds");
3666
+ return signCompactUcan(input);
3667
+ }
3668
+ async function signCompactUcanRootAuthorization(input) {
3669
+ if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > 31 * 24 * 60 * 60)
3670
+ throw new Error("compact policy root lifetime must be between one second and 31 days");
3671
+ return signCompactUcan({ ...input, proofs: [] });
3672
+ }
3673
+ function createCompactPolicyInvocation(input) {
3674
+ const session = parsePolicySessionUcan(input.sessionAuthorization);
3675
+ if (session.cid !== input.sessionCid || session.aud !== input.recipientDid)
3676
+ throw new Error("policy session does not bind the recipient signer");
3677
+ const principal = input.recipientDid.split("#", 1)[0];
3678
+ const didMaterial = base58btc.decode(principal.slice("did:key:".length));
3679
+ if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
3680
+ throw new Error("policy invocation signer must be did:key Ed25519");
3681
+ const publicKey = ed255192.getPublicKey(input.privateKey);
3682
+ if (!equalBytes(publicKey, didMaterial.slice(2)))
3683
+ throw new Error("policy invocation private key does not bind recipient DID");
3684
+ const now = input.now ?? Math.floor(Date.now() / 1e3);
3685
+ const exp = Math.min(now + 60, session.exp);
3686
+ if (exp <= now) throw new Error("policy session has expired");
3687
+ const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
3688
+ const payload = {
3689
+ att: { [input.resource]: { [input.action]: [input.caveat ?? {}] } },
3690
+ aud: input.audienceDid,
3691
+ exp,
3692
+ fct: [input.facts ?? { type: "tinycloud.policy.invocation/v1", policyCid: session.fact.policyCid, sessionCid: session.cid }],
3693
+ iss: input.recipientDid.includes("#") ? input.recipientDid : `${principal}#${principal.slice("did:key:".length)}`,
3694
+ nbf: now,
3695
+ nnc: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
3696
+ prf: [session.cid]
3697
+ };
3698
+ const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
3699
+ const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
3700
+ const signingInput = new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`);
3701
+ const signature = ed255192.sign(signingInput, input.privateKey);
3702
+ return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
3703
+ }
3704
+ function createCompactPolicyDescendant(input) {
3705
+ const parent = parseCompactUcanAuthorization(input.parentAuthorization, input.parentCid);
3706
+ if (parent.payload.aud !== input.issuerDid) throw new Error("policy descendant issuer is not the parent audience");
3707
+ const parentFact = parent.payload.fct[0];
3708
+ const depth = parentFact.remainingRedelegationDepth;
3709
+ if (!Number.isInteger(depth) || depth <= 0) throw new Error("policy descendant depth is exhausted");
3710
+ if (!compactAttenuationContains(parent.payload.att, input.attenuation))
3711
+ throw new Error("policy descendant exceeds the parent attenuation");
3712
+ const principal = input.issuerDid.split("#", 1)[0];
3713
+ const didMaterial = base58btc.decode(principal.slice("did:key:".length));
3714
+ const publicKey = ed255192.getPublicKey(input.privateKey);
3715
+ if (didMaterial.length !== 34 || !equalBytes(publicKey, didMaterial.slice(2))) throw new Error("policy descendant signer does not bind issuer DID");
3716
+ const now = Math.max(input.now ?? Math.floor(Date.now() / 1e3), parent.payload.nbf + 1);
3717
+ const exp = Math.min(input.expiresAt ?? now + 60, now + 60, parent.payload.exp - 1);
3718
+ if (exp <= now) throw new Error("policy parent has no strictly narrower validity window");
3719
+ const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
3720
+ const payload = {
3721
+ att: input.attenuation,
3722
+ aud: input.audienceDid,
3723
+ exp,
3724
+ fct: [{ ...parentFact, remainingRedelegationDepth: depth - 1 }],
3725
+ iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
3726
+ nbf: now,
3727
+ nnc: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
3728
+ prf: [parent.cid]
3729
+ };
3730
+ const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
3731
+ const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
3732
+ const signature = ed255192.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`), input.privateKey);
3733
+ return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
3734
+ }
3735
+ function compactAttenuationContains(parent, child) {
3736
+ const selector = (value) => {
3737
+ if (value.length !== 1 || !isRecordValue(value[0])) return void 0;
3738
+ const caveat = value[0];
3739
+ if (Object.keys(caveat).length !== 3 || caveat.type !== "xyz.tinycloud.resource/selector" || caveat.kind !== "exact" && caveat.kind !== "prefix" || typeof caveat.value !== "string") return void 0;
3740
+ return { kind: caveat.kind, value: caveat.value };
3741
+ };
3742
+ const equal = (left, right) => jcsCanonicalize(left) === jcsCanonicalize(right);
3743
+ return Object.entries(child).every(
3744
+ ([childResource, childActions]) => Object.entries(childActions).every(
3745
+ ([action, childCaveats]) => Object.entries(parent).some(([parentResource, parentActions]) => {
3746
+ const parentCaveats = parentActions[action];
3747
+ if (parentCaveats === void 0) return false;
3748
+ if (parentResource === childResource && equal(parentCaveats, childCaveats)) return true;
3749
+ const parentSelector = selector(parentCaveats);
3750
+ const childSelector = selector(childCaveats);
3751
+ return parentSelector?.kind === "prefix" && childSelector !== void 0 && parentSelector.value === parentResource && childSelector.value === childResource && (childResource === parentResource || childResource.startsWith(`${parentResource}/`));
3752
+ })
3753
+ )
3754
+ );
3755
+ }
3756
+ function isRecordValue(value) {
3757
+ return value !== null && typeof value === "object" && !Array.isArray(value);
3758
+ }
3759
+ function parseCompactUcanAuthorization(input, expectedCid) {
3760
+ if (typeof input !== "string" || /\s/.test(input))
3761
+ throw new Error("Authorization must be compact UCAN bytes");
3762
+ const segments = input.split(".");
3763
+ if (segments.length !== 3 || segments.some((segment) => segment.length === 0))
3764
+ throw new Error("Authorization must have three compact segments");
3765
+ const [headerSegment, payloadSegment, signatureSegment] = segments;
3766
+ const headerBytes = decodeBase64Url(headerSegment);
3767
+ const payloadBytes = decodeBase64Url(payloadSegment);
3768
+ const signature = decodeBase64Url(signatureSegment);
3769
+ const headerValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(headerBytes));
3770
+ const payloadValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(payloadBytes));
3771
+ if (jcsCanonicalize(headerValue) !== new TextDecoder().decode(headerBytes) || jcsCanonicalize(payloadValue) !== new TextDecoder().decode(payloadBytes))
3772
+ throw new Error("compact UCAN segments are not canonical JCS");
3773
+ const header = CompactHeaderSchema.parse(headerValue);
3774
+ const payload = CompactPayloadSchema.parse(payloadValue);
3775
+ if (payload.nbf >= payload.exp) throw new Error("compact UCAN validity is empty");
3776
+ const principal = payload.iss.split("#", 1)[0];
3777
+ const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
3778
+ if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
3779
+ throw new Error("compact UCAN issuer must be did:key Ed25519");
3780
+ const publicKey = didMaterial.slice(2);
3781
+ if (!equalBytes(publicKey, decodeBase64Url(header.jwk.x)))
3782
+ throw new Error("compact UCAN JWK does not bind issuer");
3783
+ if (!ed255192.verify(signature, new TextEncoder().encode(`${headerSegment}.${payloadSegment}`), publicKey))
3784
+ throw new Error("compact UCAN signature is invalid");
3785
+ const cid = CID.createV1(85, create(30, blake3(new TextEncoder().encode(input)))).toString();
3786
+ if (expectedCid !== void 0 && cid !== expectedCid)
3787
+ throw new Error("compact UCAN CID does not match exact Authorization bytes");
3788
+ return { authorization: input, cid, header, payload };
3789
+ }
3790
+ function parsePolicySessionUcan(authorization, expectedProofs) {
3791
+ const parsed = parseCompactUcanAuthorization(authorization);
3792
+ const fact = parsed.payload.fct[0];
3793
+ if (parsed.payload.prf.length !== 2 || parsed.payload.prf[0] === parsed.payload.prf[1])
3794
+ throw new Error("policy session UCAN requires two distinct ordered proofs");
3795
+ if (expectedProofs !== void 0 && (parsed.payload.prf[0] !== expectedProofs[0] || parsed.payload.prf[1] !== expectedProofs[1]))
3796
+ throw new Error("policy session UCAN ordered proofs do not match");
3797
+ const factKeys = Object.keys(fact);
3798
+ if (factKeys.length !== POLICY_SESSION_FACT_KEYS.length || factKeys.some((key) => !POLICY_SESSION_FACT_KEYS.includes(key)) || POLICY_SESSION_FACT_KEYS.some((key) => !(key in fact)))
3799
+ throw new Error("policy session UCAN fact is incomplete");
3800
+ if (fact.profile !== POLICY_SESSION_UCAN_V1_PROFILE || typeof fact.remainingRedelegationDepth !== "number" || !Number.isInteger(fact.remainingRedelegationDepth) || fact.remainingRedelegationDepth < 0 || fact.remainingRedelegationDepth > 8 || parsed.payload.exp - parsed.payload.nbf > 60 || parsed.payload.iss.split("#", 1)[0] !== fact.enforcerDid || parsed.payload.aud !== fact.recipientDid)
3801
+ throw new Error("policy session UCAN fact is invalid");
3802
+ return {
3803
+ authorization,
3804
+ cid: parsed.cid,
3805
+ iss: parsed.payload.iss,
3806
+ aud: parsed.payload.aud,
3807
+ prf: parsed.payload.prf,
3808
+ att: parsed.payload.att,
3809
+ nbf: parsed.payload.nbf,
3810
+ exp: parsed.payload.exp,
3811
+ nnc: parsed.payload.nnc,
3812
+ fact
3813
+ };
3814
+ }
3815
+ function decodeBase64Url(value) {
3816
+ if (!/^[A-Za-z0-9_-]+$/.test(value) || value.length % 4 === 1)
3817
+ throw new Error("value is not canonical base64url");
3818
+ const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
3819
+ const binary = typeof atob === "function" ? atob(normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "=")) : Buffer.from(normalized, "base64").toString("binary");
3820
+ const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
3821
+ const encoded = typeof btoa === "function" ? btoa(String.fromCharCode(...bytes)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_") : Buffer.from(bytes).toString("base64url");
3822
+ if (encoded !== value) throw new Error("value is not canonical base64url");
3823
+ return bytes;
3824
+ }
3825
+ function encodeBase64Url(value) {
3826
+ return typeof btoa === "function" ? btoa(String.fromCharCode(...value)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_") : Buffer.from(value).toString("base64url");
3827
+ }
3828
+ function equalBytes(left, right) {
3829
+ return left.length === right.length && left.every((byte, index) => byte === right[index]);
3830
+ }
3831
+ function hex(bytes) {
3832
+ return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
3833
+ }
3834
+ function base32Lower(bytes) {
3835
+ const alphabet2 = "abcdefghijklmnopqrstuvwxyz234567";
3836
+ let output = "";
3837
+ let buffer = 0;
3838
+ let bits = 0;
3839
+ for (const byte of bytes) {
3840
+ buffer = buffer << 8 | byte;
3841
+ bits += 8;
3842
+ while (bits >= 5) {
3843
+ output += alphabet2[buffer >>> bits - 5 & 31];
3844
+ bits -= 5;
3845
+ }
3846
+ }
3847
+ if (bits > 0) output += alphabet2[buffer << 5 - bits & 31];
3848
+ return output;
3849
+ }
3850
+
3851
+ // src/policy/credential-admission.ts
3852
+ import { ed25519 as ed255193 } from "@noble/curves/ed25519";
3853
+ import { sha256 as sha2565 } from "@noble/hashes/sha256";
3854
+
3855
+ // src/credentials/digest.ts
3856
+ function encodeBase64Url2(bytes) {
3857
+ if (typeof btoa === "function") {
3858
+ let binary = "";
3859
+ for (const byte of bytes) binary += String.fromCharCode(byte);
3860
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
3861
+ }
3862
+ return Buffer.from(bytes).toString("base64url");
3863
+ }
3864
+ async function sha256Base64Url(value) {
3865
+ const bytes = typeof value === "string" ? new TextEncoder().encode(value) : value;
3866
+ return encodeBase64Url2(new Uint8Array(await crypto.subtle.digest("SHA-256", bytes)));
3867
+ }
3868
+ async function canonicalDigest(value) {
3869
+ return sha256Base64Url(jcsCanonicalize(value));
3870
+ }
3871
+ function isDigest(value) {
3872
+ return typeof value === "string" && /^[A-Za-z0-9_-]{43}$/.test(value);
3873
+ }
3874
+
3875
+ // src/credentials/errors.ts
3876
+ var RECOVERABLE = /* @__PURE__ */ new Set([
3877
+ "CANCELED",
3878
+ "ISSUER_UNREADY",
3879
+ "OFFLINE",
3880
+ "POPUP_BLOCKED",
3881
+ "REQUEST_EXPIRED",
3882
+ "SIGNATURE_REJECTED",
3883
+ "UNSUPPORTED_PROFILE",
3884
+ "UNSUPPORTED_VERSION",
3885
+ "VERIFIED_NOT_SAVED"
3886
+ ]);
3887
+ var CredentialError = class extends Error {
3888
+ constructor(code2, message, details = {}) {
3889
+ super(message);
3890
+ this.code = code2;
3891
+ this.details = details;
3892
+ this.name = "CredentialError";
3893
+ this.recoverable = RECOVERABLE.has(code2);
3894
+ }
3895
+ };
3896
+
3897
+ // src/credentials/requirement.ts
3898
+ var ID = /^[a-z0-9][a-z0-9._-]{0,127}(?:\/v1)?$/;
3899
+ function validateCredentialRequirement(value) {
3900
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw new CredentialError("UNSUPPORTED_PROFILE", "Credential requirement is invalid");
3901
+ const raw = value;
3902
+ if (Object.keys(raw).some((key) => !["type", "version", "profile", "credentialType", "claims", "maxAgeSeconds"].includes(key)) || raw.type !== "TinyCloudCredentialRequirement" || raw.version !== 1) throw new CredentialError("UNSUPPORTED_PROFILE", "Credential requirement version is unsupported");
3903
+ const pair = (candidate, label) => {
3904
+ if (typeof candidate !== "object" || candidate === null || Array.isArray(candidate)) throw new CredentialError("UNSUPPORTED_PROFILE", `${label} is invalid`);
3905
+ const item = candidate;
3906
+ if (Object.keys(item).length !== 2 || typeof item.id !== "string" || !ID.test(item.id) || item.version !== 1) throw new CredentialError("UNSUPPORTED_PROFILE", `${label} version is unsupported`);
3907
+ return { id: item.id, version: 1 };
3908
+ };
3909
+ if (typeof raw.claims !== "object" || raw.claims === null || Array.isArray(raw.claims)) throw new CredentialError("UNSUPPORTED_PROFILE", "Credential claims are invalid");
3910
+ const claims = {};
3911
+ for (const [key, value2] of Object.entries(raw.claims).sort(([a], [b]) => a.localeCompare(b))) {
3912
+ if (!ID.test(key) || typeof value2 !== "string" || value2.length === 0 || value2.length > 4096) throw new CredentialError("UNSUPPORTED_PROFILE", "Credential claim is invalid");
3913
+ claims[key] = value2;
3914
+ }
3915
+ if (raw.maxAgeSeconds !== void 0 && (!Number.isSafeInteger(raw.maxAgeSeconds) || raw.maxAgeSeconds < 1)) throw new CredentialError("UNSUPPORTED_PROFILE", "Credential freshness is invalid");
3916
+ return Object.freeze({ type: "TinyCloudCredentialRequirement", version: 1, profile: pair(raw.profile, "profile"), credentialType: pair(raw.credentialType, "credentialType"), claims: Object.freeze(claims), ...raw.maxAgeSeconds === void 0 ? {} : { maxAgeSeconds: raw.maxAgeSeconds } });
3917
+ }
3918
+ async function credentialRequirementDigest(requirement) {
3919
+ return canonicalDigest(validateCredentialRequirement(requirement));
3920
+ }
3921
+
3922
+ // src/policy/credential-admission.ts
3923
+ var POLICY_V2_SCHEMA = "xyz.tinycloud.policy/policy/v2";
3924
+ var POLICY_V2_DOMAIN = "xyz.tinycloud.policy/policy/v2\0";
3925
+ var POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE = "TinyCloudPolicyCredentialRequirement";
3926
+ var POLICY_PRESENTATION_V3_SCHEMA = "xyz.tinycloud.policy/presentation/v3";
3927
+ var POLICY_PRESENTATION_V3_DOMAIN = "xyz.tinycloud.policy/Presentation/v3\0";
3928
+ function record(value, label) {
3929
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
3930
+ throw new Error(`${label} must be an object`);
3931
+ }
3932
+ return value;
3933
+ }
3934
+ function exactKeys2(value, keys, label) {
3935
+ const expected = [...keys].sort();
3936
+ const actual = Object.keys(value).sort();
3937
+ if (actual.length !== expected.length || actual.some((key, index) => key !== expected[index])) {
3938
+ throw new Error(`${label} contains an unknown or missing field`);
3939
+ }
3940
+ }
3941
+ function nonEmpty(value, label) {
3942
+ if (typeof value !== "string" || value.length === 0) {
3943
+ throw new Error(`${label} must be a non-empty string`);
3944
+ }
3945
+ return value;
3946
+ }
3947
+ function policyNodeOrigin(value) {
3948
+ let url;
3949
+ try {
3950
+ url = new URL(value);
3951
+ } catch {
3952
+ throw new Error("policy node origin is invalid");
3953
+ }
3954
+ if (url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.pathname !== "/" || url.search !== "" || url.hash !== "") {
3955
+ throw new Error("policy node origin is invalid");
3956
+ }
3957
+ return url.origin;
3958
+ }
3959
+ function versionPair(value, label) {
3960
+ const item = record(value, label);
3961
+ exactKeys2(item, ["id", "version"], label);
3962
+ if (item.version !== 1) throw new Error(`${label} version is unsupported`);
3963
+ return Object.freeze({ id: nonEmpty(item.id, `${label}.id`), version: 1 });
3964
+ }
3965
+ function validatePolicyCredentialRequirementV1(value) {
3966
+ const item = record(value, "policy credential requirement");
3967
+ exactKeys2(
3968
+ item,
3969
+ [
3970
+ "type",
3971
+ "version",
3972
+ "requirementDigest",
3973
+ "descriptorDigest",
3974
+ "issuerDid",
3975
+ "issuerKid",
3976
+ "profile",
3977
+ "credentialType"
3978
+ ],
3979
+ "policy credential requirement"
3980
+ );
3981
+ if (item.type !== POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE || item.version !== 1 || !isDigest(item.requirementDigest) || !isDigest(item.descriptorDigest)) {
3982
+ throw new Error("policy credential requirement is invalid");
3983
+ }
3984
+ return Object.freeze({
3985
+ type: POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE,
3986
+ version: 1,
3987
+ requirementDigest: item.requirementDigest,
3988
+ descriptorDigest: item.descriptorDigest,
3989
+ issuerDid: nonEmpty(item.issuerDid, "policy credential issuer"),
3990
+ issuerKid: nonEmpty(item.issuerKid, "policy credential issuer key"),
3991
+ profile: versionPair(item.profile, "policy credential profile"),
3992
+ credentialType: versionPair(
3993
+ item.credentialType,
3994
+ "policy credential type"
3995
+ )
3996
+ });
3997
+ }
3998
+ function hex2(bytes) {
3999
+ return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
4000
+ }
4001
+ function policyV2DigestHex(input) {
4002
+ const canonicalPolicy = {
4003
+ ...input,
4004
+ credentialRequirement: validatePolicyCredentialRequirementV1(
4005
+ input.credentialRequirement
4006
+ ),
4007
+ capabilityCeiling: input.capabilityCeiling.map(
4008
+ normalizeUnifiedPolicyCapability
4009
+ )
4010
+ };
4011
+ return hex2(
4012
+ sha2565(
4013
+ new TextEncoder().encode(
4014
+ POLICY_V2_DOMAIN + jcsCanonicalize(canonicalPolicy)
4015
+ )
4016
+ )
4017
+ );
4018
+ }
4019
+ function date(value, label) {
4020
+ const text = nonEmpty(value, label);
4021
+ if (!Number.isFinite(Date.parse(text))) throw new Error(`${label} is invalid`);
4022
+ return text;
4023
+ }
4024
+ function rfc3339Seconds(value) {
4025
+ return new Date(Math.floor(value.getTime() / 1e3) * 1e3).toISOString().replace(/\.000Z$/, "Z");
4026
+ }
4027
+ function validateUnifiedPolicyV2(value, expectedPolicyCid) {
4028
+ const item = record(value, "Policy/v2");
4029
+ const allowed = [
4030
+ "schema",
4031
+ "policyId",
4032
+ "ownerDid",
4033
+ "createdAt",
4034
+ "contentSource",
4035
+ "capabilityCeiling",
4036
+ "credentialRequirement",
4037
+ "signature",
4038
+ ...item.expiresAt === void 0 ? [] : ["expiresAt"]
4039
+ ];
4040
+ exactKeys2(item, allowed, "Policy/v2");
4041
+ if (item.schema !== POLICY_V2_SCHEMA || !Array.isArray(item.capabilityCeiling)) {
4042
+ throw new Error("Policy/v2 is invalid");
4043
+ }
4044
+ const ownerDid = nonEmpty(item.ownerDid, "Policy/v2 ownerDid");
4045
+ const signature = record(item.signature, "Policy/v2 signature");
4046
+ exactKeys2(signature, ["suite", "signerDid", "value"], "Policy/v2 signature");
4047
+ if (signature.suite !== "Ed25519" || signature.signerDid !== ownerDid || typeof signature.value !== "string" || signature.value.length === 0) {
4048
+ throw new Error("Policy/v2 signature binding is invalid");
4049
+ }
4050
+ const policy = Object.freeze({
4051
+ schema: POLICY_V2_SCHEMA,
4052
+ policyId: nonEmpty(item.policyId, "Policy/v2 policyId"),
4053
+ ownerDid,
4054
+ createdAt: date(item.createdAt, "Policy/v2 createdAt"),
4055
+ ...item.expiresAt === void 0 ? {} : { expiresAt: date(item.expiresAt, "Policy/v2 expiresAt") },
4056
+ contentSource: item.contentSource,
4057
+ capabilityCeiling: Object.freeze(
4058
+ item.capabilityCeiling.map(normalizeUnifiedPolicyCapability)
4059
+ ),
4060
+ credentialRequirement: validatePolicyCredentialRequirementV1(
4061
+ item.credentialRequirement
4062
+ ),
4063
+ signature: Object.freeze({
4064
+ suite: "Ed25519",
4065
+ signerDid: ownerDid,
4066
+ value: signature.value
4067
+ })
4068
+ });
4069
+ const unsigned = { ...policy };
4070
+ delete unsigned.policyId;
4071
+ delete unsigned.signature;
4072
+ const digestHex = policyV2DigestHex(unsigned);
4073
+ if (policy.policyId !== policyIdForDigestHex(digestHex)) {
4074
+ throw new Error("Policy/v2 policyId binding is invalid");
4075
+ }
4076
+ if (expectedPolicyCid !== void 0) {
4077
+ const cid = policyCidFromCanonicalBytes(
4078
+ new TextEncoder().encode(jcsCanonicalize(policy))
4079
+ );
4080
+ if (cid !== expectedPolicyCid) throw new Error("Policy/v2 CID binding is invalid");
4081
+ }
4082
+ return policy;
4083
+ }
4084
+ function didKeyBytes(did) {
4085
+ const principal = did.split("#", 1)[0];
4086
+ if (!principal.startsWith("did:key:")) throw new Error("holder DID must be did:key");
4087
+ const material = base58btc.decode(principal.slice("did:key:".length));
4088
+ if (material.length !== 34 || material[0] !== 237 || material[1] !== 1) {
4089
+ throw new Error("holder DID must contain an Ed25519 key");
4090
+ }
4091
+ return material.slice(2);
4092
+ }
4093
+ function envelopeFromVerified(verified) {
4094
+ const {
4095
+ verifiedAt: _verifiedAt,
4096
+ credentialDigest: _credentialDigest,
4097
+ statusCheckedAt: _statusCheckedAt,
4098
+ ...envelope
4099
+ } = verified;
4100
+ return envelope;
4101
+ }
4102
+ async function buildPolicyCredentialPresentationV3(input) {
4103
+ const policy = validateUnifiedPolicyV2(input.policy, input.policyCid);
4104
+ const requirement = validateCredentialRequirement(input.requirement);
4105
+ const commitment = policy.credentialRequirement;
4106
+ const requirementDigest = await credentialRequirementDigest(requirement);
4107
+ const credentialDigest = await sha256Base64Url(input.credential.credential);
4108
+ if (requirementDigest !== commitment.requirementDigest || input.credential.descriptorDigest !== commitment.descriptorDigest || input.credential.credentialDigest !== credentialDigest || input.credential.issuerDid !== commitment.issuerDid || input.credential.issuerKid !== commitment.issuerKid || jcsCanonicalize(input.credential.profile) !== jcsCanonicalize(commitment.profile) || jcsCanonicalize(input.credential.credentialType) !== jcsCanonicalize(commitment.credentialType)) {
4109
+ throw new Error("credential does not match the signed Policy/v2 requirement");
4110
+ }
4111
+ const requestedCapabilities = input.requestedCapabilities.map(
4112
+ normalizeUnifiedPolicyCapability
4113
+ );
4114
+ if (requestedCapabilities.length === 0 || requestedCapabilities.some(
4115
+ (requested) => !policy.capabilityCeiling.some(
4116
+ (authority) => unifiedPolicyCapabilityContains(authority, requested)
4117
+ )
4118
+ )) {
4119
+ throw new Error("requested capabilities exceed the signed Policy/v2 ceiling");
4120
+ }
4121
+ const challenge = input.challenge;
4122
+ const holderDid = input.credential.holderDid;
4123
+ if (challenge.policyCid !== input.policyCid || challenge.recipientDid !== holderDid || input.credential.subjectDid !== holderDid || typeof challenge.nodeAudience !== "string" || challenge.nodeAudience.length === 0 || typeof challenge.expiresAt !== "string" || !Number.isFinite(Date.parse(challenge.expiresAt))) {
4124
+ throw new Error("policy challenge binding is invalid");
4125
+ }
4126
+ didKeyBytes(holderDid);
4127
+ const now = input.now ?? /* @__PURE__ */ new Date();
4128
+ const challengeExpiry = Date.parse(challenge.expiresAt);
4129
+ const credentialExpiry = Date.parse(input.credential.expiresAt);
4130
+ const expiresAtMs = Math.min(
4131
+ now.getTime() + 6e4,
4132
+ challengeExpiry,
4133
+ credentialExpiry
4134
+ );
4135
+ if (expiresAtMs <= now.getTime()) throw new Error("policy challenge is expired");
4136
+ const unsigned = Object.freeze({
4137
+ schema: POLICY_PRESENTATION_V3_SCHEMA,
4138
+ jti: input.jti ?? encodeBase64Url2(crypto.getRandomValues(new Uint8Array(16))),
4139
+ challengeId: challenge.challengeId,
4140
+ nonce: challenge.nonce,
4141
+ policyCid: input.policyCid,
4142
+ nodeAudience: challenge.nodeAudience,
4143
+ holderDid,
4144
+ subjectDid: input.credential.subjectDid,
4145
+ credentialSpaceOwnerDid: nonEmpty(
4146
+ input.credentialSpaceOwnerDid,
4147
+ "credential space owner DID"
4148
+ ),
4149
+ credentialDigest,
4150
+ requirementDigest,
4151
+ descriptorDigest: input.credential.descriptorDigest,
4152
+ requestedCapabilities: Object.freeze(requestedCapabilities),
4153
+ issuedAt: rfc3339Seconds(now),
4154
+ expiresAt: rfc3339Seconds(new Date(expiresAtMs))
4155
+ });
4156
+ const digest2 = sha2565(
4157
+ new TextEncoder().encode(
4158
+ POLICY_PRESENTATION_V3_DOMAIN + jcsCanonicalize(unsigned)
4159
+ )
4160
+ );
4161
+ const signature = await input.sign(digest2);
4162
+ if (signature.length !== 64 || !ed255193.verify(signature, digest2, didKeyBytes(holderDid))) {
4163
+ throw new Error("policy presentation signature is invalid");
4164
+ }
4165
+ return Object.freeze({
4166
+ ...unsigned,
4167
+ signature: Object.freeze({
4168
+ suite: "Ed25519",
4169
+ signerDid: holderDid,
4170
+ value: encodeBase64Url2(signature)
4171
+ })
4172
+ });
4173
+ }
4174
+ async function admitPolicyCredentialV3(input) {
4175
+ const policy = validateUnifiedPolicyV2(input.policy, input.policyCid);
4176
+ const nodeOrigin = policyNodeOrigin(input.nodeOrigin);
4177
+ const accountAuthorizationCid = nonEmpty(
4178
+ input.accountAuthorizationCid,
4179
+ "account authorization CID"
4180
+ );
4181
+ const credentialSpaceId = nonEmpty(
4182
+ input.credentialSpaceId,
4183
+ "credential space ID"
4184
+ );
4185
+ const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
4186
+ const challenge = await requestPolicyChallengeV3({
4187
+ nodeOrigin,
4188
+ policyCid: input.policyCid,
4189
+ recipientDid: input.credential.holderDid,
4190
+ requestedCapabilities: input.requestedCapabilities,
4191
+ fetch: fetchFn
4192
+ });
4193
+ const presentation = await buildPolicyCredentialPresentationV3({
4194
+ ...input,
4195
+ policy,
4196
+ challenge
4197
+ });
4198
+ const response = await fetchFn(
4199
+ new URL("/share/v3/policy/delegations", nodeOrigin),
4200
+ {
4201
+ method: "POST",
4202
+ redirect: "error",
4203
+ headers: { accept: "application/json", "content-type": "application/json" },
4204
+ body: JSON.stringify({
4205
+ policyCid: input.policyCid,
4206
+ challengeId: challenge.challengeId,
4207
+ nonce: challenge.nonce,
4208
+ requirement: validateCredentialRequirement(input.requirement),
4209
+ credential: envelopeFromVerified(input.credential),
4210
+ accountAuthorizationCid,
4211
+ credentialSpaceId,
4212
+ presentation
4213
+ })
4214
+ }
4215
+ );
4216
+ if (!response.ok) throw new Error(`policy delegation rejected (${response.status})`);
4217
+ const value = record(await response.json(), "policy delegation");
4218
+ if (value.admitted !== true || typeof value.sessionCid !== "string" || typeof value.authorization !== "string") {
4219
+ throw new Error("policy delegation response is invalid");
4220
+ }
4221
+ const session = parsePolicySessionUcan(value.authorization, [
4222
+ input.policyRootCid,
4223
+ input.enforcementRootCid
4224
+ ]);
4225
+ const expectedAttenuation = compactAttenuationForPolicyCapabilities(
4226
+ input.requestedCapabilities
4227
+ );
4228
+ if (session.cid !== value.sessionCid || session.aud !== input.credential.holderDid || session.fact.policyCid !== input.policyCid || session.fact.recipientDid !== input.credential.holderDid || session.fact.policyDelegationCid !== input.policyRootCid || session.fact.enforcementDelegationCid !== input.enforcementRootCid || jcsCanonicalize(session.att) !== jcsCanonicalize(expectedAttenuation)) {
4229
+ throw new Error("policy delegation signed binding is invalid");
4230
+ }
4231
+ return Object.freeze({ challenge, presentation, session });
3187
4232
  }
3188
4233
  export {
4234
+ ATTESTED_ENFORCER_BINDING_V2_SCHEMA,
4235
+ CONTENT_SOURCE_V1_DOMAIN,
3189
4236
  ED25519_JCS_SIGNATURE_SUITE,
3190
4237
  EIP191_JCS_SIGNATURE_SUITE,
4238
+ LAST_V2_CREATE_AT,
4239
+ LAST_V2_READ_AT,
4240
+ MAX_LEGACY_ENVELOPE_EXPIRES_AT,
4241
+ NATIVE_PROJECTION_V1_DOMAIN,
3191
4242
  OWNER_NODE_ENDPOINT_SCHEMA,
4243
+ POLICY_CAPABILITY_V1_DOMAIN,
4244
+ POLICY_CAPABILITY_V1_SCHEMA,
4245
+ POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE,
4246
+ POLICY_ENFORCEMENT_DELEGATION_V2_SCHEMA,
3192
4247
  POLICY_ENGINE_RECORD_SCHEMA,
4248
+ POLICY_PRESENTATION_V3_DOMAIN,
4249
+ POLICY_PRESENTATION_V3_SCHEMA,
3193
4250
  POLICY_SCHEMA,
4251
+ POLICY_SESSION_UCAN_V1_PROFILE,
3194
4252
  POLICY_STATUS_SCHEMA,
4253
+ POLICY_V1_DOMAIN,
4254
+ POLICY_V1_SCHEMA,
4255
+ POLICY_V2_DOMAIN,
4256
+ POLICY_V2_SCHEMA,
3195
4257
  POLICY_VERSION_V0,
3196
4258
  PolicyAuthoringError,
3197
4259
  PolicyCapabilityError,
4260
+ ROOT_REVOCATION_V1_DOMAIN,
4261
+ ROOT_REVOCATION_V1_SCHEMA,
4262
+ ROOT_STATUS_CHECKPOINT_V1_SCHEMA,
4263
+ ROOT_STATUS_RENEWAL_V1_DOMAIN,
4264
+ ROOT_STATUS_V1_DOMAIN,
3198
4265
  SignatureMaterialError,
3199
4266
  SignatureVerificationError,
3200
4267
  SignedObjectCanonicalizationError,
@@ -3206,25 +4273,53 @@ export {
3206
4273
  TRANSCRIPT_SHARE_BOOTSTRAP_SCHEMA,
3207
4274
  UnsupportedSignatureSuiteError,
3208
4275
  W3C_VC_CREDENTIAL_VERIFIER,
4276
+ admitPolicyCredentialV3,
4277
+ buildPolicyCredentialPresentationV3,
3209
4278
  canonicalizePolicyCapability,
3210
4279
  canonicalizeSignedObjectUnsigned,
4280
+ canonicalizeUnifiedPolicyCapability,
4281
+ compactAttenuationContains,
3211
4282
  composeTranscriptShareBootstrap,
4283
+ contentSourceDigestHex,
3212
4284
  createAndSignPolicy,
3213
4285
  createAndSignPolicyEngineRecord,
3214
4286
  createAndSignPolicyStatus,
3215
4287
  createAndSignRequesterPolicyEngineRecord,
3216
4288
  createAndSignSignedObject,
3217
4289
  createAndSignTranscriptSharePolicy,
4290
+ createCompactPolicyDescendant,
4291
+ createCompactPolicyInvocation,
3218
4292
  createUnsignedPolicyEngineRecord,
3219
4293
  deriveSignedObjectMaterial,
4294
+ getPolicyRootStatusV3,
3220
4295
  jcsCanonicalize,
4296
+ mintPolicySessionV3,
3221
4297
  normalizeJson,
3222
4298
  normalizePolicyCapability,
4299
+ normalizeUnifiedPolicyCapability,
4300
+ parseCompactUcanAuthorization,
4301
+ parsePolicySessionUcan,
3223
4302
  policyCapabilityContains,
3224
4303
  policyCapabilityDigestHex,
4304
+ policyCidFromCanonicalBytes,
4305
+ policyDigestHex,
4306
+ policyIdForDigestHex,
4307
+ policyV2DigestHex,
4308
+ projectUnifiedPolicyCapabilities,
4309
+ projectUnifiedPolicyCapability,
4310
+ renewPolicyRootStatusV3,
4311
+ requestPolicyChallengeV3,
4312
+ revokePolicyRootV3,
3225
4313
  serialize as serializeJcsJson,
4314
+ signCompactUcanAuthorization,
4315
+ signCompactUcanRootAuthorization,
3226
4316
  signedObjectIdFor,
3227
4317
  toSignedObjectError,
4318
+ unifiedNativeProjectionHashHex,
4319
+ unifiedPolicyCapabilityContains,
4320
+ unifiedPolicyCapabilityDigestHex,
4321
+ unifiedPolicyCapabilityFromNative,
4322
+ validatePolicyCredentialRequirementV1,
3228
4323
  validatePolicyEngineRecordSigned,
3229
4324
  validatePolicyEngineRecordSignedShape,
3230
4325
  validatePolicyEngineRecordUnsigned,
@@ -3234,9 +4329,12 @@ export {
3234
4329
  validatePolicyStatusSignedShape,
3235
4330
  validatePolicyStatusUnsigned,
3236
4331
  validatePolicyUnsigned,
4332
+ validateUnifiedPolicyV2,
3237
4333
  verifyPolicy,
3238
4334
  verifyPolicyEngineRecord,
3239
4335
  verifyPolicyEngineRecordForRequester,
4336
+ verifyPolicyRootRevocationV3,
4337
+ verifyPolicyRootStatusCheckpointV3,
3240
4338
  verifyPolicyStatus,
3241
4339
  verifySignedObject
3242
4340
  };