@tinycloud/sdk-core 2.11.0-beta.1 → 2.11.0-beta.11

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.
@@ -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
@@ -1383,13 +1383,12 @@ function digest(input, options) {
1383
1383
  }
1384
1384
  var identity2 = { code, name, encode: encode4, digest };
1385
1385
 
1386
- // ../../node_modules/multiformats/dist/src/hashes/sha2.js
1387
- var sha2_exports = {};
1388
- __export(sha2_exports, {
1386
+ // ../../node_modules/multiformats/dist/src/hashes/sha2-browser.js
1387
+ var sha2_browser_exports = {};
1388
+ __export(sha2_browser_exports, {
1389
1389
  sha256: () => sha2562,
1390
1390
  sha512: () => sha512
1391
1391
  });
1392
- import crypto from "crypto";
1393
1392
 
1394
1393
  // ../../node_modules/multiformats/dist/src/hashes/hasher.js
1395
1394
  var DEFAULT_MIN_DIGEST_LENGTH = 20;
@@ -1439,16 +1438,19 @@ function createDigest(digest2, code2, truncate) {
1439
1438
  return create(code2, digest2);
1440
1439
  }
1441
1440
 
1442
- // ../../node_modules/multiformats/dist/src/hashes/sha2.js
1441
+ // ../../node_modules/multiformats/dist/src/hashes/sha2-browser.js
1442
+ function sha(name2) {
1443
+ return async (data) => new Uint8Array(await crypto.subtle.digest(name2, data));
1444
+ }
1443
1445
  var sha2562 = from2({
1444
1446
  name: "sha2-256",
1445
1447
  code: 18,
1446
- encode: (input) => coerce(crypto.createHash("sha256").update(input).digest())
1448
+ encode: sha("SHA-256")
1447
1449
  });
1448
1450
  var sha512 = from2({
1449
1451
  name: "sha2-512",
1450
1452
  code: 19,
1451
- encode: (input) => coerce(crypto.createHash("sha512").update(input).digest())
1453
+ encode: sha("SHA-512")
1452
1454
  });
1453
1455
 
1454
1456
  // ../../node_modules/multiformats/dist/src/cid.js
@@ -1790,7 +1792,7 @@ var cidSymbol = /* @__PURE__ */ Symbol.for("@ipld/js-cid/CID");
1790
1792
 
1791
1793
  // ../../node_modules/multiformats/dist/src/basics.js
1792
1794
  var bases = { ...identity_exports, ...base2_exports, ...base8_exports, ...base10_exports, ...base16_exports, ...base32_exports, ...base36_exports, ...base58_exports, ...base64_exports, ...base256emoji_exports };
1793
- var hashes = { ...sha2_exports, ...identity_exports2 };
1795
+ var hashes = { ...sha2_browser_exports, ...identity_exports2 };
1794
1796
 
1795
1797
  // src/policy/signed-object.ts
1796
1798
  import { bytesToHex as bytesToHex2, sha256 as sha2563, verifyMessage } from "viem";
@@ -1907,17 +1909,17 @@ async function createAndSignSignedObject(input, signer) {
1907
1909
  }
1908
1910
  function createAndSignPolicy(input, signer) {
1909
1911
  return createAndSignSignedObject(input, signer).then(
1910
- (object) => validatePolicySignedShape(object)
1912
+ (object2) => validatePolicySignedShape(object2)
1911
1913
  );
1912
1914
  }
1913
1915
  function createAndSignPolicyStatus(input, signer) {
1914
1916
  return createAndSignSignedObject(input, signer).then(
1915
- (object) => validatePolicyStatusSignedShape(object)
1917
+ (object2) => validatePolicyStatusSignedShape(object2)
1916
1918
  );
1917
1919
  }
1918
1920
  function createAndSignPolicyEngineRecord(input, signer) {
1919
1921
  return createAndSignSignedObject(input, signer).then(
1920
- (object) => validatePolicyEngineRecordSignedShape(object)
1922
+ (object2) => validatePolicyEngineRecordSignedShape(object2)
1921
1923
  );
1922
1924
  }
1923
1925
  async function verifySignedObject(input) {
@@ -2021,9 +2023,9 @@ function validateUnsignedForDescriptor(input, descriptor) {
2021
2023
  }
2022
2024
  }
2023
2025
  function validatePolicyShape(input, signed) {
2024
- const object = expectJsonObject(normalizeJson(input), "$");
2026
+ const object2 = expectJsonObject(normalizeJson(input), "$");
2025
2027
  assertExactKeys2(
2026
- object,
2028
+ object2,
2027
2029
  signed ? [
2028
2030
  "schema",
2029
2031
  "policyId",
@@ -2051,30 +2053,30 @@ function validatePolicyShape(input, signed) {
2051
2053
  ],
2052
2054
  "$"
2053
2055
  );
2054
- expectConst(requiredString2(object, "schema", "$"), POLICY_SCHEMA, "$.schema");
2056
+ expectConst(requiredString2(object2, "schema", "$"), POLICY_SCHEMA, "$.schema");
2055
2057
  if (signed) {
2056
- requiredString2(object, "policyId", "$");
2057
- validateSignature(requiredValue2(object, "signature", "$"));
2058
+ requiredString2(object2, "policyId", "$");
2059
+ validateSignature(requiredValue2(object2, "signature", "$"));
2058
2060
  }
2059
- requiredString2(object, "ownerDid", "$");
2060
- requiredString2(object, "signingKeyDid", "$");
2061
- requiredDateString(object, "createdAt", "$");
2062
- optionalDateString(object, "expiresAt", "$");
2063
- validatePolicyResource(requiredValue2(object, "resource", "$"), "$.resource");
2064
- validateExpression(requiredValue2(object, "when", "$"), "$.when");
2065
- validateGrant(requiredValue2(object, "grant", "$"), "$.grant");
2066
- if (hasOwn2(object, "disclosure")) {
2067
- 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");
2068
2070
  }
2069
- if (hasOwn2(object, "audit")) {
2070
- validateAudit(requiredValue2(object, "audit", "$"), "$.audit");
2071
+ if (hasOwn2(object2, "audit")) {
2072
+ validateAudit(requiredValue2(object2, "audit", "$"), "$.audit");
2071
2073
  }
2072
- return object;
2074
+ return object2;
2073
2075
  }
2074
2076
  function validatePolicyStatusShape(input, signed) {
2075
- const object = expectJsonObject(normalizeJson(input), "$");
2077
+ const object2 = expectJsonObject(normalizeJson(input), "$");
2076
2078
  assertExactKeys2(
2077
- object,
2079
+ object2,
2078
2080
  signed ? [
2079
2081
  "schema",
2080
2082
  "statusId",
@@ -2098,28 +2100,28 @@ function validatePolicyStatusShape(input, signed) {
2098
2100
  ],
2099
2101
  "$"
2100
2102
  );
2101
- expectConst(requiredString2(object, "schema", "$"), POLICY_STATUS_SCHEMA, "$.schema");
2103
+ expectConst(requiredString2(object2, "schema", "$"), POLICY_STATUS_SCHEMA, "$.schema");
2102
2104
  if (signed) {
2103
- requiredString2(object, "statusId", "$");
2104
- validateSignature(requiredValue2(object, "signature", "$"));
2105
+ requiredString2(object2, "statusId", "$");
2106
+ validateSignature(requiredValue2(object2, "signature", "$"));
2105
2107
  }
2106
- requiredString2(object, "policyId", "$");
2107
- requiredString2(object, "ownerDid", "$");
2108
- requiredInteger(object, "sequence", "$", 0);
2109
- expectOneOf(requiredString2(object, "disposition", "$"), [
2108
+ requiredString2(object2, "policyId", "$");
2109
+ requiredString2(object2, "ownerDid", "$");
2110
+ requiredInteger(object2, "sequence", "$", 0);
2111
+ expectOneOf(requiredString2(object2, "disposition", "$"), [
2110
2112
  "active",
2111
2113
  "suspended",
2112
2114
  "revoked"
2113
2115
  ], "$.disposition");
2114
- requiredDateString(object, "effectiveAt", "$");
2115
- optionalString(object, "reasonCode", "$");
2116
- requiredString2(object, "signingKeyDid", "$");
2117
- return object;
2116
+ requiredDateString(object2, "effectiveAt", "$");
2117
+ optionalString(object2, "reasonCode", "$");
2118
+ requiredString2(object2, "signingKeyDid", "$");
2119
+ return object2;
2118
2120
  }
2119
2121
  function validatePolicyEngineRecordShape(input, signed) {
2120
- const object = expectJsonObject(normalizeJson(input), "$");
2122
+ const object2 = expectJsonObject(normalizeJson(input), "$");
2121
2123
  assertExactKeys2(
2122
- object,
2124
+ object2,
2123
2125
  signed ? [
2124
2126
  "schema",
2125
2127
  "engineRecordId",
@@ -2144,44 +2146,44 @@ function validatePolicyEngineRecordShape(input, signed) {
2144
2146
  "$"
2145
2147
  );
2146
2148
  expectConst(
2147
- requiredString2(object, "schema", "$"),
2149
+ requiredString2(object2, "schema", "$"),
2148
2150
  POLICY_ENGINE_RECORD_SCHEMA,
2149
2151
  "$.schema"
2150
2152
  );
2151
2153
  if (signed) {
2152
- requiredString2(object, "engineRecordId", "$");
2153
- validateSignature(requiredValue2(object, "signature", "$"));
2154
+ requiredString2(object2, "engineRecordId", "$");
2155
+ validateSignature(requiredValue2(object2, "signature", "$"));
2154
2156
  }
2155
- requiredString2(object, "ownerDid", "$");
2156
- requiredString2(object, "endpoint", "$");
2157
- requiredString2(object, "audience", "$");
2157
+ requiredString2(object2, "ownerDid", "$");
2158
+ requiredString2(object2, "endpoint", "$");
2159
+ requiredString2(object2, "audience", "$");
2158
2160
  requiredStringArray(
2159
- object,
2161
+ object2,
2160
2162
  "supportedPolicyVersions",
2161
2163
  "$",
2162
2164
  (value, path) => expectConst(value, "v0", path)
2163
2165
  );
2164
- requiredStringArray(object, "supportedEvidenceVerifiers", "$");
2165
- requiredString2(object, "grantIssuerDid", "$");
2166
- requiredDateString(object, "expiresAt", "$");
2167
- return object;
2166
+ requiredStringArray(object2, "supportedEvidenceVerifiers", "$");
2167
+ requiredString2(object2, "grantIssuerDid", "$");
2168
+ requiredDateString(object2, "expiresAt", "$");
2169
+ return object2;
2168
2170
  }
2169
2171
  function validateSignature(input) {
2170
- const object = expectJsonObject(input, "$.signature");
2171
- assertExactKeys2(object, ["suite", "signerDid", "value"], "$.signature");
2172
- 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");
2173
2175
  assertSupportedSignatureSuite(suite);
2174
- const signerDid = requiredString2(object, "signerDid", "$.signature");
2175
- const value = requiredString2(object, "value", "$.signature");
2176
+ const signerDid = requiredString2(object2, "signerDid", "$.signature");
2177
+ const value = requiredString2(object2, "value", "$.signature");
2176
2178
  decodeSignatureValue(value, suite);
2177
2179
  return { suite, signerDid, value };
2178
2180
  }
2179
2181
  function validatePolicyResource(input, path) {
2180
- const object = expectJsonObject(input, path);
2181
- assertExactKeys2(object, ["resourceType", "resourceId", "permissionsCeiling"], path);
2182
- requiredString2(object, "resourceType", path);
2183
- requiredString2(object, "resourceId", path);
2184
- 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);
2185
2187
  for (let index = 0; index < ceiling.length; index++) {
2186
2188
  validatePolicyCapability(ceiling[index], `${path}.permissionsCeiling[${index}]`);
2187
2189
  }
@@ -2197,10 +2199,10 @@ function validatePolicyPermissionsCeilingForSigning(input) {
2197
2199
  }
2198
2200
  }
2199
2201
  function validatePolicyCapability(input, path) {
2200
- const object = expectJsonObject(input, path);
2202
+ const object2 = expectJsonObject(input, path);
2201
2203
  try {
2202
- const canonical = canonicalizePolicyCapability(object);
2203
- if (jcsCanonicalize(object) !== jcsCanonicalize(canonical)) {
2204
+ const canonical = canonicalizePolicyCapability(object2);
2205
+ if (jcsCanonicalize(object2) !== jcsCanonicalize(canonical)) {
2204
2206
  throw new SignedObjectSchemaError(`${path} must be canonical PolicyCapability JSON`);
2205
2207
  }
2206
2208
  } catch (error) {
@@ -2213,10 +2215,10 @@ function validatePolicyCapability(input, path) {
2213
2215
  }
2214
2216
  }
2215
2217
  function validatePolicyCapabilityForSigning(input, path) {
2216
- const object = expectJsonObject(input, path);
2218
+ const object2 = expectJsonObject(input, path);
2217
2219
  try {
2218
- const canonical = normalizePolicyCapability(object);
2219
- if (jcsCanonicalize(object) !== jcsCanonicalize(canonical)) {
2220
+ const canonical = normalizePolicyCapability(object2);
2221
+ if (jcsCanonicalize(object2) !== jcsCanonicalize(canonical)) {
2220
2222
  throw new SignedObjectSchemaError(`${path} must be strict canonical PolicyCapability JSON`);
2221
2223
  }
2222
2224
  } catch (error) {
@@ -2229,43 +2231,43 @@ function validatePolicyCapabilityForSigning(input, path) {
2229
2231
  }
2230
2232
  }
2231
2233
  function validateExpression(input, path) {
2232
- const object = expectJsonObject(input, path);
2233
- const keys = Object.keys(object);
2234
+ const object2 = expectJsonObject(input, path);
2235
+ const keys = Object.keys(object2);
2234
2236
  if (keys.length !== 1) {
2235
2237
  throw new SignedObjectSchemaError(`${path} must have exactly one expression key`);
2236
2238
  }
2237
2239
  const key = keys[0];
2238
2240
  if (key === "allOf" || key === "anyOf") {
2239
- const values = requiredArray2(object, key, path, 1);
2241
+ const values = requiredArray2(object2, key, path, 1);
2240
2242
  for (let index = 0; index < values.length; index++) {
2241
2243
  validateExpression(values[index], `${path}.${key}[${index}]`);
2242
2244
  }
2243
2245
  return;
2244
2246
  }
2245
2247
  if (key === "subject") {
2246
- const subject = expectJsonObject(requiredValue2(object, "subject", path), `${path}.subject`);
2248
+ const subject = expectJsonObject(requiredValue2(object2, "subject", path), `${path}.subject`);
2247
2249
  assertExactKeys2(subject, ["did"], `${path}.subject`);
2248
2250
  requiredString2(subject, "did", `${path}.subject`);
2249
2251
  return;
2250
2252
  }
2251
2253
  if (key === "evidence") {
2252
- validateEvidenceRequirement(requiredValue2(object, "evidence", path), `${path}.evidence`);
2254
+ validateEvidenceRequirement(requiredValue2(object2, "evidence", path), `${path}.evidence`);
2253
2255
  return;
2254
2256
  }
2255
2257
  throw new SignedObjectSchemaError(`${path} has unknown expression key ${key}`);
2256
2258
  }
2257
2259
  function validateEvidenceRequirement(input, path) {
2258
- const object = expectJsonObject(input, path);
2260
+ const object2 = expectJsonObject(input, path);
2259
2261
  assertExactKeys2(
2260
- object,
2262
+ object2,
2261
2263
  ["requirementId", "verifier", "requirements", "authority", "freshness"],
2262
2264
  path
2263
2265
  );
2264
- requiredString2(object, "requirementId", path);
2265
- requiredString2(object, "verifier", path);
2266
- requiredValue2(object, "requirements", path);
2267
- if (hasOwn2(object, "authority")) {
2268
- 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`);
2269
2271
  assertExactKeys2(
2270
2272
  authority,
2271
2273
  ["profile", "acceptedIssuers", "allowOwnerAuthorizedIssuer"],
@@ -2277,35 +2279,35 @@ function validateEvidenceRequirement(input, path) {
2277
2279
  }
2278
2280
  optionalBoolean(authority, "allowOwnerAuthorizedIssuer", `${path}.authority`);
2279
2281
  }
2280
- if (hasOwn2(object, "freshness")) {
2281
- const freshness = expectJsonObject(requiredValue2(object, "freshness", path), `${path}.freshness`);
2282
+ if (hasOwn2(object2, "freshness")) {
2283
+ const freshness = expectJsonObject(requiredValue2(object2, "freshness", path), `${path}.freshness`);
2282
2284
  assertExactKeys2(freshness, ["maxStatusAgeSeconds"], `${path}.freshness`);
2283
2285
  requiredInteger(freshness, "maxStatusAgeSeconds", `${path}.freshness`, 0);
2284
2286
  }
2285
2287
  }
2286
2288
  function validateGrant(input, path) {
2287
- const object = expectJsonObject(input, path);
2288
- assertExactKeys2(object, ["output", "maxTtlSeconds", "delegationMode", "revocation"], path);
2289
- expectConst(requiredString2(object, "output", path), "portable-delegation", `${path}.output`);
2290
- requiredInteger(object, "maxTtlSeconds", path, 1);
2291
- 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), [
2292
2294
  "terminal",
2293
2295
  "attenuable"
2294
2296
  ], `${path}.delegationMode`);
2295
- expectOneOf(requiredString2(object, "revocation", path), [
2297
+ expectOneOf(requiredString2(object2, "revocation", path), [
2296
2298
  "refresh_only",
2297
2299
  "active_cutoff"
2298
2300
  ], `${path}.revocation`);
2299
2301
  }
2300
2302
  function validateDisclosure(input, path) {
2301
- const object = expectJsonObject(input, path);
2302
- assertExactKeys2(object, ["denial"], path);
2303
- 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`);
2304
2306
  }
2305
2307
  function validateAudit(input, path) {
2306
- const object = expectJsonObject(input, path);
2307
- assertExactKeys2(object, ["issuance"], path);
2308
- 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`);
2309
2311
  }
2310
2312
  function materialForUnsigned(unsigned, descriptor) {
2311
2313
  const jcs = jcsCanonicalize(unsigned);
@@ -2454,9 +2456,9 @@ function encodeSignatureValue(value, suite) {
2454
2456
  decodeSignatureValue(encoded, suite);
2455
2457
  return encoded;
2456
2458
  }
2457
- function stripOwnIdAndSignature(object, descriptor) {
2459
+ function stripOwnIdAndSignature(object2, descriptor) {
2458
2460
  const output = /* @__PURE__ */ Object.create(null);
2459
- for (const [key, value] of Object.entries(object)) {
2461
+ for (const [key, value] of Object.entries(object2)) {
2460
2462
  if (key === descriptor.idField || key === "signature") {
2461
2463
  continue;
2462
2464
  }
@@ -2465,8 +2467,8 @@ function stripOwnIdAndSignature(object, descriptor) {
2465
2467
  return output;
2466
2468
  }
2467
2469
  function descriptorForUnsigned(input) {
2468
- const object = expectJsonObject(normalizeJson(input), "$");
2469
- return descriptorForSchema(requiredString2(object, "schema", "$"));
2470
+ const object2 = expectJsonObject(normalizeJson(input), "$");
2471
+ return descriptorForSchema(requiredString2(object2, "schema", "$"));
2470
2472
  }
2471
2473
  function descriptorForSchema(schema) {
2472
2474
  if (schema === POLICY_SCHEMA) return DESCRIPTORS.Policy;
@@ -2480,28 +2482,28 @@ function expectJsonObject(input, path) {
2480
2482
  }
2481
2483
  return input;
2482
2484
  }
2483
- function assertExactKeys2(object, allowed, path) {
2485
+ function assertExactKeys2(object2, allowed, path) {
2484
2486
  const allowedSet = new Set(allowed);
2485
- for (const key of Object.keys(object)) {
2487
+ for (const key of Object.keys(object2)) {
2486
2488
  if (!allowedSet.has(key)) {
2487
2489
  throw new SignedObjectSchemaError(`${path} has unknown field ${key}`);
2488
2490
  }
2489
2491
  }
2490
2492
  }
2491
- function requiredValue2(object, key, path) {
2492
- if (!hasOwn2(object, key)) {
2493
+ function requiredValue2(object2, key, path) {
2494
+ if (!hasOwn2(object2, key)) {
2493
2495
  throw new SignedObjectSchemaError(`${path}.${key} is required`);
2494
2496
  }
2495
- return object[key];
2497
+ return object2[key];
2496
2498
  }
2497
- function requiredString2(object, key, path) {
2498
- return requireStringType(requiredValue2(object, key, path), `${path}.${key}`);
2499
+ function requiredString2(object2, key, path) {
2500
+ return requireStringType(requiredValue2(object2, key, path), `${path}.${key}`);
2499
2501
  }
2500
- function optionalString(object, key, path) {
2501
- if (!hasOwn2(object, key)) {
2502
+ function optionalString(object2, key, path) {
2503
+ if (!hasOwn2(object2, key)) {
2502
2504
  return;
2503
2505
  }
2504
- requireStringType(requiredValue2(object, key, path), `${path}.${key}`);
2506
+ requireStringType(requiredValue2(object2, key, path), `${path}.${key}`);
2505
2507
  }
2506
2508
  function requireStringType(value, path) {
2507
2509
  if (typeof value !== "string" || value.length === 0) {
@@ -2509,16 +2511,16 @@ function requireStringType(value, path) {
2509
2511
  }
2510
2512
  return value;
2511
2513
  }
2512
- function optionalBoolean(object, key, path) {
2513
- if (!hasOwn2(object, key)) {
2514
+ function optionalBoolean(object2, key, path) {
2515
+ if (!hasOwn2(object2, key)) {
2514
2516
  return;
2515
2517
  }
2516
- if (typeof requiredValue2(object, key, path) !== "boolean") {
2518
+ if (typeof requiredValue2(object2, key, path) !== "boolean") {
2517
2519
  throw new SignedObjectSchemaError(`${path}.${key} must be a boolean`);
2518
2520
  }
2519
2521
  }
2520
- function requiredInteger(object, key, path, minimum) {
2521
- const value = requiredValue2(object, key, path);
2522
+ function requiredInteger(object2, key, path, minimum) {
2523
+ const value = requiredValue2(object2, key, path);
2522
2524
  if (typeof value !== "number" || !Number.isSafeInteger(value) || value < minimum) {
2523
2525
  throw new SignedObjectSchemaError(
2524
2526
  `${path}.${key} must be an integer >= ${minimum}`
@@ -2526,8 +2528,8 @@ function requiredInteger(object, key, path, minimum) {
2526
2528
  }
2527
2529
  return value;
2528
2530
  }
2529
- function requiredArray2(object, key, path, minimum) {
2530
- const value = requiredValue2(object, key, path);
2531
+ function requiredArray2(object2, key, path, minimum) {
2532
+ const value = requiredValue2(object2, key, path);
2531
2533
  if (!Array.isArray(value) || value.length < minimum) {
2532
2534
  throw new SignedObjectSchemaError(
2533
2535
  `${path}.${key} must be an array with at least ${minimum} item(s)`
@@ -2535,22 +2537,22 @@ function requiredArray2(object, key, path, minimum) {
2535
2537
  }
2536
2538
  return value;
2537
2539
  }
2538
- function requiredStringArray(object, key, path, check) {
2539
- const values = requiredArray2(object, key, path, 0);
2540
+ function requiredStringArray(object2, key, path, check) {
2541
+ const values = requiredArray2(object2, key, path, 0);
2540
2542
  for (let index = 0; index < values.length; index++) {
2541
2543
  const itemPath = `${path}.${key}[${index}]`;
2542
2544
  const value = requireStringType(values[index], itemPath);
2543
2545
  check?.(value, itemPath);
2544
2546
  }
2545
2547
  }
2546
- function requiredDateString(object, key, path) {
2547
- assertRfc3339(requiredString2(object, key, path), `${path}.${key}`);
2548
+ function requiredDateString(object2, key, path) {
2549
+ assertRfc3339(requiredString2(object2, key, path), `${path}.${key}`);
2548
2550
  }
2549
- function optionalDateString(object, key, path) {
2550
- if (!hasOwn2(object, key)) {
2551
+ function optionalDateString(object2, key, path) {
2552
+ if (!hasOwn2(object2, key)) {
2551
2553
  return;
2552
2554
  }
2553
- assertRfc3339(requiredString2(object, key, path), `${path}.${key}`);
2555
+ assertRfc3339(requiredString2(object2, key, path), `${path}.${key}`);
2554
2556
  }
2555
2557
  function assertRfc3339(value, path) {
2556
2558
  const match = value.match(
@@ -2582,8 +2584,8 @@ function expectOneOf(actual, allowed, path) {
2582
2584
  }
2583
2585
  throw new SignedObjectSchemaError(`${path} has unsupported value ${actual}`);
2584
2586
  }
2585
- function hasOwn2(object, key) {
2586
- return objectHasOwn3(object, key);
2587
+ function hasOwn2(object2, key) {
2588
+ return objectHasOwn3(object2, key);
2587
2589
  }
2588
2590
  function assertSupportedSignatureSuite(suite) {
2589
2591
  if (suite !== ED25519_JCS_SIGNATURE_SUITE && suite !== EIP191_JCS_SIGNATURE_SUITE) {
@@ -2662,13 +2664,13 @@ function base64UrlDecode(value) {
2662
2664
  return decoded;
2663
2665
  }
2664
2666
  function hexToBytes(value) {
2665
- const hex = value.slice(2);
2666
- if (hex.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex)) {
2667
+ const hex2 = value.slice(2);
2668
+ if (hex2.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex2)) {
2667
2669
  throw new SignatureMaterialError("hex signature must have even length");
2668
2670
  }
2669
- const output = new Uint8Array(hex.length / 2);
2671
+ const output = new Uint8Array(hex2.length / 2);
2670
2672
  for (let index = 0; index < output.length; index++) {
2671
- output[index] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);
2673
+ output[index] = Number.parseInt(hex2.slice(index * 2, index * 2 + 2), 16);
2672
2674
  }
2673
2675
  return output;
2674
2676
  }
@@ -3019,9 +3021,9 @@ function expectPolicyEngineRecord(input) {
3019
3021
  );
3020
3022
  }
3021
3023
  }
3022
- function assertExactKeys3(object, allowed, path) {
3024
+ function assertExactKeys3(object2, allowed, path) {
3023
3025
  const allowedSet = new Set(allowed);
3024
- for (const key of Object.keys(object)) {
3026
+ for (const key of Object.keys(object2)) {
3025
3027
  if (!allowedSet.has(key)) {
3026
3028
  throw new PolicyAuthoringError(
3027
3029
  "policy-authoring-unknown-key",
@@ -3030,17 +3032,17 @@ function assertExactKeys3(object, allowed, path) {
3030
3032
  }
3031
3033
  }
3032
3034
  }
3033
- function requiredValue3(object, key, path) {
3034
- if (!hasOwn3(object, key)) {
3035
+ function requiredValue3(object2, key, path) {
3036
+ if (!hasOwn3(object2, key)) {
3035
3037
  throw new PolicyAuthoringError(
3036
3038
  "policy-authoring-malformed",
3037
3039
  `${path}.${key} is required`
3038
3040
  );
3039
3041
  }
3040
- return object[key];
3042
+ return object2[key];
3041
3043
  }
3042
- function requiredString3(object, key, path) {
3043
- const value = requiredValue3(object, key, path);
3044
+ function requiredString3(object2, key, path) {
3045
+ const value = requiredValue3(object2, key, path);
3044
3046
  if (typeof value !== "string" || value.length === 0) {
3045
3047
  throw new PolicyAuthoringError(
3046
3048
  "policy-authoring-malformed",
@@ -3049,11 +3051,11 @@ function requiredString3(object, key, path) {
3049
3051
  }
3050
3052
  return value;
3051
3053
  }
3052
- function fieldString(object, key, path, code2) {
3053
- if (!hasOwn3(object, key)) {
3054
+ function fieldString(object2, key, path, code2) {
3055
+ if (!hasOwn3(object2, key)) {
3054
3056
  throw new PolicyAuthoringError(code2, `${path}.${key} is required`);
3055
3057
  }
3056
- const value = object[key];
3058
+ const value = object2[key];
3057
3059
  if (typeof value !== "string" || value.length === 0) {
3058
3060
  throw new PolicyAuthoringError(
3059
3061
  code2,
@@ -3062,8 +3064,8 @@ function fieldString(object, key, path, code2) {
3062
3064
  }
3063
3065
  return value;
3064
3066
  }
3065
- function requiredObject(object, key, path) {
3066
- const value = requiredValue3(object, key, path);
3067
+ function requiredObject(object2, key, path) {
3068
+ const value = requiredValue3(object2, key, path);
3067
3069
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
3068
3070
  throw new PolicyAuthoringError(
3069
3071
  "policy-authoring-malformed",
@@ -3072,8 +3074,8 @@ function requiredObject(object, key, path) {
3072
3074
  }
3073
3075
  return value;
3074
3076
  }
3075
- function requiredArray3(object, key, path) {
3076
- const value = requiredValue3(object, key, path);
3077
+ function requiredArray3(object2, key, path) {
3078
+ const value = requiredValue3(object2, key, path);
3077
3079
  if (!Array.isArray(value)) {
3078
3080
  throw new PolicyAuthoringError(
3079
3081
  "policy-authoring-malformed",
@@ -3082,8 +3084,8 @@ function requiredArray3(object, key, path) {
3082
3084
  }
3083
3085
  return value;
3084
3086
  }
3085
- function requiredStringArray2(object, key, path) {
3086
- const values = requiredArray3(object, key, path);
3087
+ function requiredStringArray2(object2, key, path) {
3088
+ const values = requiredArray3(object2, key, path);
3087
3089
  return values.map((value, index) => {
3088
3090
  if (typeof value !== "string" || value.length === 0) {
3089
3091
  throw new PolicyAuthoringError(
@@ -3180,19 +3182,686 @@ function parseStrictRfc3339(value, path) {
3180
3182
  var objectHasOwn4 = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
3181
3183
  Object.prototype.hasOwnProperty
3182
3184
  );
3183
- function hasOwn3(object, key) {
3184
- 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 match = /^tinycloud:\/\/([^/]+)\/kv\/(.+)$/.exec(resource);
3430
+ if (!match || match[1].includes(":") || match[1].includes("?") || match[1].includes("#") || match[1].includes("%") || match[2].startsWith("/") || match[2].endsWith("/") || match[2].includes("//") || match[2].split("/").some((part) => part === "." || part === ".." || part.length === 0)) {
3431
+ throw new Error("KV resource is not canonical");
3432
+ }
3433
+ return { space: match[1], path: match[2] };
3434
+ }
3435
+ function parseEncryptionResource(resource) {
3436
+ if (!resource.startsWith("urn:tinycloud:encryption:")) throw new Error("encryption capability is invalid");
3437
+ const rest = resource.slice("urn:tinycloud:encryption:".length);
3438
+ const separator = rest.lastIndexOf(":");
3439
+ const ownerDid = separator < 0 ? "" : rest.slice(0, separator);
3440
+ const network = separator < 0 ? "" : rest.slice(separator + 1);
3441
+ if (!ownerDid.startsWith("did:") || network.length === 0 || network.includes(":") || network.includes("/") || network.includes("%") || network.includes("?") || network.includes("#")) {
3442
+ throw new Error("encryption capability is invalid");
3443
+ }
3444
+ }
3445
+ function normalizeUnifiedPolicyCapability(input) {
3446
+ const value = object(input, "capability");
3447
+ const kind = nonEmptyString(value.kind, "capability.kind");
3448
+ if (kind === "kv") {
3449
+ exactKeys(
3450
+ value,
3451
+ ["kind", "resource", "selector", "actions"],
3452
+ "KV capability"
3453
+ );
3454
+ const resource = nonEmptyString(value.resource, "capability.resource");
3455
+ parseKvResource(resource);
3456
+ if (value.selector !== "exact" && value.selector !== "prefix")
3457
+ throw new Error("capability.selector is invalid");
3458
+ if (!Array.isArray(value.actions) || value.actions.length === 0)
3459
+ throw new Error("capability.actions is invalid");
3460
+ const actions = value.actions.map(
3461
+ (action) => nonEmptyString(action, "capability.actions[]")
3462
+ );
3463
+ if (new Set(actions).size !== actions.length || actions.some((action) => !KV_ACTIONS.has(action)))
3464
+ throw new Error("capability.actions is invalid");
3465
+ return {
3466
+ kind: "kv",
3467
+ resource,
3468
+ selector: value.selector,
3469
+ actions: [...actions].sort()
3470
+ };
3471
+ }
3472
+ if (kind === "encryption") {
3473
+ exactKeys(value, ["kind", "resource", "action"], "encryption capability");
3474
+ const resource = nonEmptyString(value.resource, "capability.resource");
3475
+ if (value.action !== "tinycloud.encryption/decrypt")
3476
+ throw new Error("encryption capability is invalid");
3477
+ parseEncryptionResource(resource);
3478
+ return {
3479
+ kind: "encryption",
3480
+ resource,
3481
+ action: "tinycloud.encryption/decrypt"
3482
+ };
3483
+ }
3484
+ throw new Error("capability.kind is invalid");
3485
+ }
3486
+ function canonicalizeUnifiedPolicyCapability(input) {
3487
+ return normalizeUnifiedPolicyCapability(input);
3488
+ }
3489
+ function unifiedPolicyCapabilityDigestHex(input) {
3490
+ return hex(
3491
+ sha2564(
3492
+ new TextEncoder().encode(
3493
+ POLICY_CAPABILITY_V1_DOMAIN + jcsCanonicalize(normalizeUnifiedPolicyCapability(input))
3494
+ )
3495
+ )
3496
+ );
3497
+ }
3498
+ function unifiedPolicyCapabilityContains(authorityInput, requestedInput) {
3499
+ try {
3500
+ const authority = normalizeUnifiedPolicyCapability(authorityInput);
3501
+ const requested = normalizeUnifiedPolicyCapability(requestedInput);
3502
+ if (authority.kind !== requested.kind) return false;
3503
+ if (authority.kind === "encryption" && requested.kind === "encryption")
3504
+ return authority.resource === requested.resource && authority.action === requested.action;
3505
+ if (authority.kind !== "kv" || requested.kind !== "kv") return false;
3506
+ const { resource: authorized } = authority;
3507
+ const { resource: requestedResource } = requested;
3508
+ const pathContained = authority.selector === "exact" ? authorized === requestedResource : authorized === requestedResource || requestedResource.startsWith(`${authorized}/`);
3509
+ if (!pathContained || authority.selector === "exact" && requested.selector === "prefix")
3510
+ return false;
3511
+ return requested.actions.every(
3512
+ (action) => authority.actions.includes(action)
3513
+ );
3514
+ } catch {
3515
+ return false;
3516
+ }
3517
+ }
3518
+ function projectUnifiedPolicyCapability(input) {
3519
+ const capability = normalizeUnifiedPolicyCapability(input);
3520
+ if (capability.kind === "encryption") {
3521
+ return {
3522
+ service: "tinycloud.encryption",
3523
+ space: capability.resource,
3524
+ path: capability.resource,
3525
+ actions: [capability.action]
3526
+ };
3527
+ }
3528
+ const { space, path } = parseKvResource(capability.resource);
3529
+ return {
3530
+ service: "tinycloud.kv",
3531
+ space,
3532
+ path,
3533
+ actions: [...capability.actions],
3534
+ caveat: {
3535
+ type: "xyz.tinycloud.resource/selector",
3536
+ kind: capability.selector,
3537
+ value: capability.resource
3538
+ }
3539
+ };
3540
+ }
3541
+ function projectUnifiedPolicyCapabilities(input) {
3542
+ return input.map(projectUnifiedPolicyCapability).sort((left, right) => {
3543
+ const a = jcsCanonicalize(left);
3544
+ const b = jcsCanonicalize(right);
3545
+ return a < b ? -1 : a > b ? 1 : 0;
3546
+ });
3547
+ }
3548
+ function unifiedNativeProjectionHashHex(input) {
3549
+ return hex(
3550
+ sha2564(
3551
+ new TextEncoder().encode(
3552
+ NATIVE_PROJECTION_V1_DOMAIN + jcsCanonicalize(projectUnifiedPolicyCapabilities(input))
3553
+ )
3554
+ )
3555
+ );
3556
+ }
3557
+ function unifiedPolicyCapabilityFromNative(input) {
3558
+ const value = object(input, "native capability");
3559
+ exactKeys(
3560
+ value,
3561
+ ["service", "space", "path", "actions", "caveat"],
3562
+ "native capability"
3563
+ );
3564
+ const service = nonEmptyString(value.service, "native.service");
3565
+ const actions = value.actions;
3566
+ if (!Array.isArray(actions)) throw new Error("native.actions is invalid");
3567
+ if (service === "tinycloud.encryption" && value.caveat === void 0 && value.space === value.path && actions.length === 1 && actions[0] === "tinycloud.encryption/decrypt") {
3568
+ return normalizeUnifiedPolicyCapability({
3569
+ kind: "encryption",
3570
+ resource: value.space,
3571
+ action: actions[0]
3572
+ });
3573
+ }
3574
+ if (service !== "tinycloud.kv" || typeof value.space !== "string" || typeof value.path !== "string")
3575
+ throw new Error("native capability is not supported");
3576
+ const caveat = object(value.caveat, "native.caveat");
3577
+ exactKeys(caveat, ["type", "kind", "value"], "native selector caveat");
3578
+ if (caveat.type !== "xyz.tinycloud.resource/selector" || caveat.kind !== "exact" && caveat.kind !== "prefix" || caveat.value !== `tinycloud://${value.space}/kv/${value.path}`)
3579
+ throw new Error("native selector caveat does not match capability");
3580
+ return normalizeUnifiedPolicyCapability({
3581
+ kind: "kv",
3582
+ resource: caveat.value,
3583
+ selector: caveat.kind,
3584
+ actions
3585
+ });
3586
+ }
3587
+ function contentSourceDigestHex(input) {
3588
+ return hex(
3589
+ sha2564(
3590
+ new TextEncoder().encode(
3591
+ CONTENT_SOURCE_V1_DOMAIN + jcsCanonicalize(input)
3592
+ )
3593
+ )
3594
+ );
3595
+ }
3596
+ function policyDigestHex(policy) {
3597
+ const canonicalPolicy = {
3598
+ ...policy,
3599
+ capabilityCeiling: policy.capabilityCeiling.map(
3600
+ normalizeUnifiedPolicyCapability
3601
+ )
3602
+ };
3603
+ return hex(
3604
+ sha2564(
3605
+ new TextEncoder().encode(
3606
+ POLICY_V1_DOMAIN + jcsCanonicalize(canonicalPolicy)
3607
+ )
3608
+ )
3609
+ );
3610
+ }
3611
+ function policyIdForDigestHex(digestHex) {
3612
+ const digest2 = Uint8Array.from(
3613
+ (digestHex.match(/.{2}/g) ?? []).map((byte) => Number.parseInt(byte, 16))
3614
+ );
3615
+ if (digest2.length !== 32) throw new Error("policy digest must be 32 bytes");
3616
+ return `pol_${base32Lower(digest2)}`;
3617
+ }
3618
+ function policyCidFromCanonicalBytes(bytes) {
3619
+ return CID.createV1(85, create(18, sha2564(bytes))).toString();
3620
+ }
3621
+ var CompactHeaderSchema = z.object({
3622
+ alg: z.literal("EdDSA"),
3623
+ jwk: z.object({ alg: z.literal("EdDSA"), crv: z.literal("Ed25519"), kty: z.literal("OKP"), x: z.string().min(1) }).strict(),
3624
+ typ: z.literal("JWT"),
3625
+ ucv: z.literal("0.10.0")
3626
+ }).strict();
3627
+ var CompactPayloadSchema = z.object({
3628
+ att: z.record(z.record(z.array(z.unknown()).min(1))),
3629
+ aud: z.string().min(1),
3630
+ exp: z.number().int(),
3631
+ fct: z.array(z.record(z.unknown())).length(1),
3632
+ iss: z.string().min(1),
3633
+ nbf: z.number().int(),
3634
+ nnc: z.string().min(1),
3635
+ prf: z.array(z.string().min(1))
3636
+ }).strict();
3637
+ async function signCompactUcanAuthorization(input) {
3638
+ if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > 60)
3639
+ throw new Error("compact invocation lifetime must be between one and 60 seconds");
3640
+ const principal = input.issuerDid.split("#", 1)[0];
3641
+ const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
3642
+ if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
3643
+ throw new Error("compact UCAN signer must be did:key Ed25519");
3644
+ const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(didMaterial.slice(2)) }, typ: "JWT", ucv: "0.10.0" };
3645
+ const payload = {
3646
+ att: input.attenuation,
3647
+ aud: input.audienceDid,
3648
+ exp: input.expiresAt,
3649
+ fct: input.facts,
3650
+ iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
3651
+ nbf: input.notBefore,
3652
+ nnc: input.nonce,
3653
+ prf: input.proofs
3654
+ };
3655
+ const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
3656
+ const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
3657
+ const signature = await input.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`));
3658
+ if (signature.length !== 64) throw new Error("compact Authorization signature must be Ed25519");
3659
+ return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
3660
+ }
3661
+ function createCompactPolicyInvocation(input) {
3662
+ const session = parsePolicySessionUcan(input.sessionAuthorization);
3663
+ if (session.cid !== input.sessionCid || session.aud !== input.recipientDid)
3664
+ throw new Error("policy session does not bind the recipient signer");
3665
+ const principal = input.recipientDid.split("#", 1)[0];
3666
+ const didMaterial = base58btc.decode(principal.slice("did:key:".length));
3667
+ if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
3668
+ throw new Error("policy invocation signer must be did:key Ed25519");
3669
+ const publicKey = ed255192.getPublicKey(input.privateKey);
3670
+ if (!equalBytes(publicKey, didMaterial.slice(2)))
3671
+ throw new Error("policy invocation private key does not bind recipient DID");
3672
+ const now = input.now ?? Math.floor(Date.now() / 1e3);
3673
+ const exp = Math.min(now + 60, session.exp);
3674
+ if (exp <= now) throw new Error("policy session has expired");
3675
+ const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
3676
+ const payload = {
3677
+ att: { [input.resource]: { [input.action]: [input.caveat ?? {}] } },
3678
+ aud: input.audienceDid,
3679
+ exp,
3680
+ fct: [input.facts ?? { type: "tinycloud.policy.invocation/v1", policyCid: session.fact.policyCid, sessionCid: session.cid }],
3681
+ iss: input.recipientDid.includes("#") ? input.recipientDid : `${principal}#${principal.slice("did:key:".length)}`,
3682
+ nbf: now,
3683
+ nnc: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
3684
+ prf: [session.cid]
3685
+ };
3686
+ const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
3687
+ const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
3688
+ const signingInput = new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`);
3689
+ const signature = ed255192.sign(signingInput, input.privateKey);
3690
+ return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
3691
+ }
3692
+ function createCompactPolicyDescendant(input) {
3693
+ const parent = parseCompactUcanAuthorization(input.parentAuthorization, input.parentCid);
3694
+ if (parent.payload.aud !== input.issuerDid) throw new Error("policy descendant issuer is not the parent audience");
3695
+ const parentFact = parent.payload.fct[0];
3696
+ const depth = parentFact.remainingRedelegationDepth;
3697
+ if (!Number.isInteger(depth) || depth <= 0) throw new Error("policy descendant depth is exhausted");
3698
+ if (!compactAttenuationContains(parent.payload.att, input.attenuation))
3699
+ throw new Error("policy descendant exceeds the parent attenuation");
3700
+ const principal = input.issuerDid.split("#", 1)[0];
3701
+ const didMaterial = base58btc.decode(principal.slice("did:key:".length));
3702
+ const publicKey = ed255192.getPublicKey(input.privateKey);
3703
+ if (didMaterial.length !== 34 || !equalBytes(publicKey, didMaterial.slice(2))) throw new Error("policy descendant signer does not bind issuer DID");
3704
+ const now = Math.max(input.now ?? Math.floor(Date.now() / 1e3), parent.payload.nbf + 1);
3705
+ const exp = Math.min(input.expiresAt ?? now + 60, now + 60, parent.payload.exp - 1);
3706
+ if (exp <= now) throw new Error("policy parent has no strictly narrower validity window");
3707
+ const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
3708
+ const payload = {
3709
+ att: input.attenuation,
3710
+ aud: input.audienceDid,
3711
+ exp,
3712
+ fct: [{ ...parentFact, remainingRedelegationDepth: depth - 1 }],
3713
+ iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
3714
+ nbf: now,
3715
+ nnc: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
3716
+ prf: [parent.cid]
3717
+ };
3718
+ const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
3719
+ const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
3720
+ const signature = ed255192.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`), input.privateKey);
3721
+ return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
3722
+ }
3723
+ function compactAttenuationContains(parent, child) {
3724
+ const selector = (value) => {
3725
+ if (value.length !== 1 || !isRecordValue(value[0])) return void 0;
3726
+ const caveat = value[0];
3727
+ 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;
3728
+ return { kind: caveat.kind, value: caveat.value };
3729
+ };
3730
+ const equal = (left, right) => jcsCanonicalize(left) === jcsCanonicalize(right);
3731
+ return Object.entries(child).every(
3732
+ ([childResource, childActions]) => Object.entries(childActions).every(
3733
+ ([action, childCaveats]) => Object.entries(parent).some(([parentResource, parentActions]) => {
3734
+ const parentCaveats = parentActions[action];
3735
+ if (parentCaveats === void 0) return false;
3736
+ if (parentResource === childResource && equal(parentCaveats, childCaveats)) return true;
3737
+ const parentSelector = selector(parentCaveats);
3738
+ const childSelector = selector(childCaveats);
3739
+ return parentSelector?.kind === "prefix" && childSelector !== void 0 && parentSelector.value === parentResource && childSelector.value === childResource && (childResource === parentResource || childResource.startsWith(`${parentResource}/`));
3740
+ })
3741
+ )
3742
+ );
3743
+ }
3744
+ function isRecordValue(value) {
3745
+ return value !== null && typeof value === "object" && !Array.isArray(value);
3746
+ }
3747
+ function parseCompactUcanAuthorization(input, expectedCid) {
3748
+ if (typeof input !== "string" || /\s/.test(input))
3749
+ throw new Error("Authorization must be compact UCAN bytes");
3750
+ const segments = input.split(".");
3751
+ if (segments.length !== 3 || segments.some((segment) => segment.length === 0))
3752
+ throw new Error("Authorization must have three compact segments");
3753
+ const [headerSegment, payloadSegment, signatureSegment] = segments;
3754
+ const headerBytes = decodeBase64Url(headerSegment);
3755
+ const payloadBytes = decodeBase64Url(payloadSegment);
3756
+ const signature = decodeBase64Url(signatureSegment);
3757
+ const headerValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(headerBytes));
3758
+ const payloadValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(payloadBytes));
3759
+ if (jcsCanonicalize(headerValue) !== new TextDecoder().decode(headerBytes) || jcsCanonicalize(payloadValue) !== new TextDecoder().decode(payloadBytes))
3760
+ throw new Error("compact UCAN segments are not canonical JCS");
3761
+ const header = CompactHeaderSchema.parse(headerValue);
3762
+ const payload = CompactPayloadSchema.parse(payloadValue);
3763
+ if (payload.nbf >= payload.exp) throw new Error("compact UCAN validity is empty");
3764
+ const principal = payload.iss.split("#", 1)[0];
3765
+ const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
3766
+ if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
3767
+ throw new Error("compact UCAN issuer must be did:key Ed25519");
3768
+ const publicKey = didMaterial.slice(2);
3769
+ if (!equalBytes(publicKey, decodeBase64Url(header.jwk.x)))
3770
+ throw new Error("compact UCAN JWK does not bind issuer");
3771
+ if (!ed255192.verify(signature, new TextEncoder().encode(`${headerSegment}.${payloadSegment}`), publicKey))
3772
+ throw new Error("compact UCAN signature is invalid");
3773
+ const cid = CID.createV1(85, create(30, blake3(new TextEncoder().encode(input)))).toString();
3774
+ if (expectedCid !== void 0 && cid !== expectedCid)
3775
+ throw new Error("compact UCAN CID does not match exact Authorization bytes");
3776
+ return { authorization: input, cid, header, payload };
3777
+ }
3778
+ function parsePolicySessionUcan(authorization, expectedProofs) {
3779
+ const parsed = parseCompactUcanAuthorization(authorization);
3780
+ const fact = parsed.payload.fct[0];
3781
+ if (parsed.payload.prf.length !== 2 || parsed.payload.prf[0] === parsed.payload.prf[1])
3782
+ throw new Error("policy session UCAN requires two distinct ordered proofs");
3783
+ if (expectedProofs !== void 0 && (parsed.payload.prf[0] !== expectedProofs[0] || parsed.payload.prf[1] !== expectedProofs[1]))
3784
+ throw new Error("policy session UCAN ordered proofs do not match");
3785
+ const factKeys = Object.keys(fact);
3786
+ 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)))
3787
+ throw new Error("policy session UCAN fact is incomplete");
3788
+ 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)
3789
+ throw new Error("policy session UCAN fact is invalid");
3790
+ return {
3791
+ authorization,
3792
+ cid: parsed.cid,
3793
+ iss: parsed.payload.iss,
3794
+ aud: parsed.payload.aud,
3795
+ prf: parsed.payload.prf,
3796
+ att: parsed.payload.att,
3797
+ nbf: parsed.payload.nbf,
3798
+ exp: parsed.payload.exp,
3799
+ nnc: parsed.payload.nnc,
3800
+ fact
3801
+ };
3802
+ }
3803
+ function decodeBase64Url(value) {
3804
+ if (!/^[A-Za-z0-9_-]+$/.test(value) || value.length % 4 === 1)
3805
+ throw new Error("value is not canonical base64url");
3806
+ const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
3807
+ const binary = typeof Buffer !== "undefined" ? Buffer.from(normalized, "base64").toString("binary") : atob(normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "="));
3808
+ const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
3809
+ const encoded = typeof Buffer !== "undefined" ? Buffer.from(bytes).toString("base64url") : btoa(String.fromCharCode(...bytes)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
3810
+ if (encoded !== value) throw new Error("value is not canonical base64url");
3811
+ return bytes;
3812
+ }
3813
+ function encodeBase64Url(value) {
3814
+ return typeof Buffer !== "undefined" ? Buffer.from(value).toString("base64url") : btoa(String.fromCharCode(...value)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
3815
+ }
3816
+ function equalBytes(left, right) {
3817
+ return left.length === right.length && left.every((byte, index) => byte === right[index]);
3818
+ }
3819
+ function hex(bytes) {
3820
+ return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
3821
+ }
3822
+ function base32Lower(bytes) {
3823
+ const alphabet2 = "abcdefghijklmnopqrstuvwxyz234567";
3824
+ let output = "";
3825
+ let buffer = 0;
3826
+ let bits = 0;
3827
+ for (const byte of bytes) {
3828
+ buffer = buffer << 8 | byte;
3829
+ bits += 8;
3830
+ while (bits >= 5) {
3831
+ output += alphabet2[buffer >>> bits - 5 & 31];
3832
+ bits -= 5;
3833
+ }
3834
+ }
3835
+ if (bits > 0) output += alphabet2[buffer << 5 - bits & 31];
3836
+ return output;
3185
3837
  }
3186
3838
  export {
3839
+ ATTESTED_ENFORCER_BINDING_V2_SCHEMA,
3840
+ CONTENT_SOURCE_V1_DOMAIN,
3187
3841
  ED25519_JCS_SIGNATURE_SUITE,
3188
3842
  EIP191_JCS_SIGNATURE_SUITE,
3843
+ LAST_V2_CREATE_AT,
3844
+ LAST_V2_READ_AT,
3845
+ MAX_LEGACY_ENVELOPE_EXPIRES_AT,
3846
+ NATIVE_PROJECTION_V1_DOMAIN,
3189
3847
  OWNER_NODE_ENDPOINT_SCHEMA,
3848
+ POLICY_CAPABILITY_V1_DOMAIN,
3849
+ POLICY_CAPABILITY_V1_SCHEMA,
3850
+ POLICY_ENFORCEMENT_DELEGATION_V2_SCHEMA,
3190
3851
  POLICY_ENGINE_RECORD_SCHEMA,
3191
3852
  POLICY_SCHEMA,
3853
+ POLICY_SESSION_UCAN_V1_PROFILE,
3192
3854
  POLICY_STATUS_SCHEMA,
3855
+ POLICY_V1_DOMAIN,
3856
+ POLICY_V1_SCHEMA,
3193
3857
  POLICY_VERSION_V0,
3194
3858
  PolicyAuthoringError,
3195
3859
  PolicyCapabilityError,
3860
+ ROOT_REVOCATION_V1_DOMAIN,
3861
+ ROOT_REVOCATION_V1_SCHEMA,
3862
+ ROOT_STATUS_CHECKPOINT_V1_SCHEMA,
3863
+ ROOT_STATUS_RENEWAL_V1_DOMAIN,
3864
+ ROOT_STATUS_V1_DOMAIN,
3196
3865
  SignatureMaterialError,
3197
3866
  SignatureVerificationError,
3198
3867
  SignedObjectCanonicalizationError,
@@ -3206,23 +3875,46 @@ export {
3206
3875
  W3C_VC_CREDENTIAL_VERIFIER,
3207
3876
  canonicalizePolicyCapability,
3208
3877
  canonicalizeSignedObjectUnsigned,
3878
+ canonicalizeUnifiedPolicyCapability,
3879
+ compactAttenuationContains,
3209
3880
  composeTranscriptShareBootstrap,
3881
+ contentSourceDigestHex,
3210
3882
  createAndSignPolicy,
3211
3883
  createAndSignPolicyEngineRecord,
3212
3884
  createAndSignPolicyStatus,
3213
3885
  createAndSignRequesterPolicyEngineRecord,
3214
3886
  createAndSignSignedObject,
3215
3887
  createAndSignTranscriptSharePolicy,
3888
+ createCompactPolicyDescendant,
3889
+ createCompactPolicyInvocation,
3216
3890
  createUnsignedPolicyEngineRecord,
3217
3891
  deriveSignedObjectMaterial,
3892
+ getPolicyRootStatusV3,
3218
3893
  jcsCanonicalize,
3894
+ mintPolicySessionV3,
3219
3895
  normalizeJson,
3220
3896
  normalizePolicyCapability,
3897
+ normalizeUnifiedPolicyCapability,
3898
+ parseCompactUcanAuthorization,
3899
+ parsePolicySessionUcan,
3221
3900
  policyCapabilityContains,
3222
3901
  policyCapabilityDigestHex,
3902
+ policyCidFromCanonicalBytes,
3903
+ policyDigestHex,
3904
+ policyIdForDigestHex,
3905
+ projectUnifiedPolicyCapabilities,
3906
+ projectUnifiedPolicyCapability,
3907
+ renewPolicyRootStatusV3,
3908
+ requestPolicyChallengeV3,
3909
+ revokePolicyRootV3,
3223
3910
  serialize as serializeJcsJson,
3911
+ signCompactUcanAuthorization,
3224
3912
  signedObjectIdFor,
3225
3913
  toSignedObjectError,
3914
+ unifiedNativeProjectionHashHex,
3915
+ unifiedPolicyCapabilityContains,
3916
+ unifiedPolicyCapabilityDigestHex,
3917
+ unifiedPolicyCapabilityFromNative,
3226
3918
  validatePolicyEngineRecordSigned,
3227
3919
  validatePolicyEngineRecordSignedShape,
3228
3920
  validatePolicyEngineRecordUnsigned,
@@ -3235,6 +3927,8 @@ export {
3235
3927
  verifyPolicy,
3236
3928
  verifyPolicyEngineRecord,
3237
3929
  verifyPolicyEngineRecordForRequester,
3930
+ verifyPolicyRootRevocationV3,
3931
+ verifyPolicyRootStatusCheckpointV3,
3238
3932
  verifyPolicyStatus,
3239
3933
  verifySignedObject
3240
3934
  };