@tinycloud/sdk-core 2.11.0 → 3.0.0-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.
package/dist/index.cjs CHANGED
@@ -138,6 +138,7 @@ __export(index_exports, {
138
138
  OPENKEY_ACTION_ID_SEPARATOR: () => OPENKEY_ACTION_ID_SEPARATOR,
139
139
  POLICY_CAPABILITY_V1_DOMAIN: () => POLICY_CAPABILITY_V1_DOMAIN,
140
140
  POLICY_CAPABILITY_V1_SCHEMA: () => POLICY_CAPABILITY_V1_SCHEMA,
141
+ POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE: () => POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE,
141
142
  POLICY_ENFORCEMENT_DELEGATION_V2_SCHEMA: () => POLICY_ENFORCEMENT_DELEGATION_V2_SCHEMA,
142
143
  POLICY_ENGINE_CHALLENGE_REQUEST_SCHEMA: () => POLICY_ENGINE_CHALLENGE_REQUEST_SCHEMA,
143
144
  POLICY_ENGINE_CHALLENGE_RESPONSE_SCHEMA: () => POLICY_ENGINE_CHALLENGE_RESPONSE_SCHEMA,
@@ -145,11 +146,15 @@ __export(index_exports, {
145
146
  POLICY_ENGINE_GRANT_PRESENTATION_DENIAL_CODES: () => POLICY_ENGINE_GRANT_PRESENTATION_DENIAL_CODES,
146
147
  POLICY_ENGINE_RECORD_SCHEMA: () => POLICY_ENGINE_RECORD_SCHEMA,
147
148
  POLICY_ENGINE_RESOLVE_REQUEST_SCHEMA: () => POLICY_ENGINE_RESOLVE_REQUEST_SCHEMA,
149
+ POLICY_PRESENTATION_V3_DOMAIN: () => POLICY_PRESENTATION_V3_DOMAIN,
150
+ POLICY_PRESENTATION_V3_SCHEMA: () => POLICY_PRESENTATION_V3_SCHEMA,
148
151
  POLICY_SCHEMA: () => POLICY_SCHEMA,
149
152
  POLICY_SESSION_UCAN_V1_PROFILE: () => POLICY_SESSION_UCAN_V1_PROFILE,
150
153
  POLICY_STATUS_SCHEMA: () => POLICY_STATUS_SCHEMA,
151
154
  POLICY_V1_DOMAIN: () => POLICY_V1_DOMAIN,
152
155
  POLICY_V1_SCHEMA: () => POLICY_V1_SCHEMA,
156
+ POLICY_V2_DOMAIN: () => POLICY_V2_DOMAIN,
157
+ POLICY_V2_SCHEMA: () => POLICY_V2_SCHEMA,
153
158
  PORTABLE_DELEGATION_SCHEMA: () => PORTABLE_DELEGATION_SCHEMA,
154
159
  PermissionNotInManifestError: () => PermissionNotInManifestError,
155
160
  PrefixedKVService: () => import_sdk_services8.PrefixedKVService,
@@ -217,6 +222,7 @@ __export(index_exports, {
217
222
  actionContains: () => actionContains,
218
223
  activateSessionWithHost: () => activateSessionWithHost,
219
224
  addressStorageKey: () => addressStorageKey,
225
+ admitPolicyCredentialV3: () => admitPolicyCredentialV3,
220
226
  applyPrefix: () => applyPrefix,
221
227
  bootstrapEncryptionNetworkId: () => import_bootstrap4.bootstrapEncryptionNetworkId,
222
228
  bootstrapSpaceId: () => import_bootstrap4.bootstrapSpaceId,
@@ -226,6 +232,7 @@ __export(index_exports, {
226
232
  buildDecryptFacts: () => import_sdk_services8.buildDecryptFacts,
227
233
  buildDecryptInvocation: () => import_sdk_services8.buildDecryptInvocation,
228
234
  buildNetworkId: () => import_sdk_services8.buildNetworkId,
235
+ buildPolicyCredentialPresentationV3: () => buildPolicyCredentialPresentationV3,
229
236
  buildSpaceUri: () => buildSpaceUri,
230
237
  canonicalDigest: () => canonicalDigest,
231
238
  canonicalHashHex: () => import_sdk_services8.canonicalHashHex,
@@ -365,6 +372,7 @@ __export(index_exports, {
365
372
  policyCidFromCanonicalBytes: () => policyCidFromCanonicalBytes,
366
373
  policyDigestHex: () => policyDigestHex,
367
374
  policyIdForDigestHex: () => policyIdForDigestHex,
375
+ policyV2DigestHex: () => policyV2DigestHex,
368
376
  principalDid: () => principalDid,
369
377
  principalDidEquals: () => principalDidEquals,
370
378
  projectUnifiedPolicyCapabilities: () => projectUnifiedPolicyCapabilities,
@@ -388,6 +396,7 @@ __export(index_exports, {
388
396
  shareCapabilityAllows: () => shareCapabilityAllows,
389
397
  shareDeliveryTrustedKid: () => shareDeliveryTrustedKid,
390
398
  signCompactUcanAuthorization: () => signCompactUcanAuthorization,
399
+ signCompactUcanRootAuthorization: () => signCompactUcanRootAuthorization,
391
400
  signLocationRecord: () => signLocationRecord,
392
401
  signShareEnvelope: () => signShareEnvelope,
393
402
  signedObjectIdFor: () => signedObjectIdFor,
@@ -411,6 +420,7 @@ __export(index_exports, {
411
420
  validateOwnerSharePolicyRegistration: () => validateOwnerSharePolicyRegistration,
412
421
  validateOwnerSharePolicyRegistrationBytes: () => validateOwnerSharePolicyRegistrationBytes,
413
422
  validatePersistedSessionData: () => validatePersistedSessionData,
423
+ validatePolicyCredentialRequirementV1: () => validatePolicyCredentialRequirementV1,
414
424
  validatePolicyEngineRecordSigned: () => validatePolicyEngineRecordSigned,
415
425
  validatePolicyEngineRecordSignedShape: () => validatePolicyEngineRecordSignedShape,
416
426
  validatePolicyEngineRecordUnsigned: () => validatePolicyEngineRecordUnsigned,
@@ -421,6 +431,7 @@ __export(index_exports, {
421
431
  validatePolicyStatusUnsigned: () => validatePolicyStatusUnsigned,
422
432
  validatePolicyUnsigned: () => validatePolicyUnsigned,
423
433
  validateShareDeliveryAuthorizationBytes: () => validateShareDeliveryAuthorizationBytes,
434
+ validateUnifiedPolicyV2: () => validateUnifiedPolicyV2,
424
435
  verifyDecryptResponse: () => import_sdk_services8.verifyDecryptResponse,
425
436
  verifyDidKeyEd25519Signature: () => verifyDidKeyEd25519Signature,
426
437
  verifyEip191MessageSignature: () => verifyEip191MessageSignature,
@@ -740,6 +751,7 @@ var CREDENTIAL_ERROR_CODES = [
740
751
  "REQUEST_SUBSTITUTED",
741
752
  "SIGNATURE_REJECTED",
742
753
  "UNSUPPORTED_PROFILE",
754
+ "UNSUPPORTED_VERSION",
743
755
  "VERIFICATION_FAILED",
744
756
  "VERIFIED_NOT_SAVED"
745
757
  ];
@@ -751,6 +763,7 @@ var RECOVERABLE = /* @__PURE__ */ new Set([
751
763
  "REQUEST_EXPIRED",
752
764
  "SIGNATURE_REJECTED",
753
765
  "UNSUPPORTED_PROFILE",
766
+ "UNSUPPORTED_VERSION",
754
767
  "VERIFIED_NOT_SAVED"
755
768
  ]);
756
769
  var CredentialError = class extends Error {
@@ -1038,11 +1051,11 @@ async function createStoredCredentialRecord(input) {
1038
1051
  const recordId = await canonicalDigest({ credentialDigest: input.verified.credentialDigest, holderDid: input.ownerDid });
1039
1052
  return Object.freeze({ type: "TinyCloudStoredCredential", version: 1, ownerDid: input.ownerDid, recordId, requirementDigest: input.requirementDigest, descriptorDigest: input.verified.descriptorDigest, profile: input.verified.profile, credentialType: input.verified.credentialType, issuerDid: input.verified.issuerDid, issuerKid: input.verified.issuerKid, holderDid: input.verified.holderDid, claims: input.verified.claims, claimsDigest: input.verified.claimsDigest, credentialDigest: input.verified.credentialDigest, credential: input.verified.credential, schema: input.verified.schema, credentialId: input.verified.credentialId, issuedAt: input.verified.issuedAt, notBefore: input.verified.notBefore, expiresAt: input.verified.expiresAt, status: input.verified.status, verifiedAt: input.verified.verifiedAt, storedAt });
1040
1053
  }
1041
- async function createStorageReceipt(record, etag) {
1042
- return Object.freeze({ type: "TinyCloudCredentialStorageReceipt", version: 1, ownerDid: record.ownerDid, recordId: record.recordId, recordDigest: await canonicalDigest(record), storedAt: record.storedAt, ...etag === void 0 ? {} : { etag } });
1054
+ async function createStorageReceipt(record2, etag) {
1055
+ return Object.freeze({ type: "TinyCloudCredentialStorageReceipt", version: 1, ownerDid: record2.ownerDid, recordId: record2.recordId, recordDigest: await canonicalDigest(record2), storedAt: record2.storedAt, ...etag === void 0 ? {} : { etag } });
1043
1056
  }
1044
- async function verifyStorageReceipt(record, receipt, activeOwnerDid, activeHolderDid) {
1045
- return receipt.type === "TinyCloudCredentialStorageReceipt" && receipt.version === 1 && receipt.ownerDid === activeOwnerDid && record.ownerDid === activeOwnerDid && record.holderDid === activeHolderDid && receipt.recordId === record.recordId && receipt.storedAt === record.storedAt && receipt.recordDigest === await canonicalDigest(record);
1057
+ async function verifyStorageReceipt(record2, receipt, activeOwnerDid, activeHolderDid) {
1058
+ return receipt.type === "TinyCloudCredentialStorageReceipt" && receipt.version === 1 && receipt.ownerDid === activeOwnerDid && record2.ownerDid === activeOwnerDid && record2.holderDid === activeHolderDid && receipt.recordId === record2.recordId && receipt.storedAt === record2.storedAt && receipt.recordDigest === await canonicalDigest(record2);
1046
1059
  }
1047
1060
 
1048
1061
  // src/credentials/verification.ts
@@ -3601,13 +3614,13 @@ function base64UrlDecode(value) {
3601
3614
  return decoded;
3602
3615
  }
3603
3616
  function hexToBytes(value) {
3604
- const hex2 = value.slice(2);
3605
- if (hex2.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex2)) {
3617
+ const hex3 = value.slice(2);
3618
+ if (hex3.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex3)) {
3606
3619
  throw new SignatureMaterialError("hex signature must have even length");
3607
3620
  }
3608
- const output = new Uint8Array(hex2.length / 2);
3621
+ const output = new Uint8Array(hex3.length / 2);
3609
3622
  for (let index = 0; index < output.length; index++) {
3610
- output[index] = Number.parseInt(hex2.slice(index * 2, index * 2 + 2), 16);
3623
+ output[index] = Number.parseInt(hex3.slice(index * 2, index * 2 + 2), 16);
3611
3624
  }
3612
3625
  return output;
3613
3626
  }
@@ -3847,6 +3860,34 @@ var ROOT_REVOCATION_V1_DOMAIN = "xyz.tinycloud.policy/RootRevocation/v1\0";
3847
3860
  var LAST_V2_CREATE_AT = "2026-09-30T00:00:00Z";
3848
3861
  var MAX_LEGACY_ENVELOPE_EXPIRES_AT = "2026-12-29T00:00:00Z";
3849
3862
  var LAST_V2_READ_AT = "2027-01-05T00:00:00Z";
3863
+ async function requestPolicyChallengeV3(input) {
3864
+ const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
3865
+ const response = await fetchFn(new URL("/share/v3/policy/challenges", input.nodeOrigin), {
3866
+ method: "POST",
3867
+ redirect: "error",
3868
+ headers: { accept: "application/json", "content-type": "application/json" },
3869
+ body: JSON.stringify({ policyCid: input.policyCid, recipientDid: input.recipientDid, requestedCapabilities: input.requestedCapabilities.map(normalizeUnifiedPolicyCapability) })
3870
+ });
3871
+ if (!response.ok) throw new Error(`policy challenge rejected (${response.status})`);
3872
+ const value = object2(await response.json(), "policy challenge");
3873
+ if (typeof value.challengeId !== "string" || typeof value.nonce !== "string" || value.policyCid !== input.policyCid || value.recipientDid !== input.recipientDid)
3874
+ throw new Error("policy challenge binding is invalid");
3875
+ return value;
3876
+ }
3877
+ function compactAttenuationForPolicyCapabilities(input) {
3878
+ const attenuation = {};
3879
+ for (const raw of input) {
3880
+ const capability = normalizeUnifiedPolicyCapability(raw);
3881
+ if (attenuation[capability.resource] !== void 0)
3882
+ throw new Error("policy capabilities contain a duplicate resource");
3883
+ attenuation[capability.resource] = capability.kind === "encryption" ? { [capability.action]: [{}] } : Object.fromEntries(capability.actions.map((action) => [action, [{
3884
+ type: "xyz.tinycloud.resource/selector",
3885
+ kind: capability.selector,
3886
+ value: capability.resource
3887
+ }]]));
3888
+ }
3889
+ return attenuation;
3890
+ }
3850
3891
  function verifyPolicyRootStatusCheckpointV3(input) {
3851
3892
  const checkpoint = input.checkpoint;
3852
3893
  const allowed = /* @__PURE__ */ new Set(["schema", "targetCid", "targetRole", "ownerDid", "nodeAudience", "state", "sequence", "checkedAt", "freshUntil", "revokedAt", "revocationCid", "previousCheckpointDigestHex", "issuerDid", "signature"]);
@@ -4016,11 +4057,15 @@ function nonEmptyString(value, label) {
4016
4057
  return value;
4017
4058
  }
4018
4059
  function parseKvResource(resource) {
4019
- const match = /^tinycloud:\/\/([^/]+)\/kv\/(.+)$/.exec(resource);
4020
- 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)) {
4060
+ const marker = resource.indexOf("/kv/");
4061
+ const encodedSpace = marker < 1 ? "" : resource.slice(0, marker);
4062
+ const legacy = encodedSpace.startsWith("tinycloud://");
4063
+ const space = legacy ? encodedSpace.slice("tinycloud://".length) : encodedSpace;
4064
+ const path = marker < 1 ? "" : resource.slice(marker + 4);
4065
+ 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)) {
4021
4066
  throw new Error("KV resource is not canonical");
4022
4067
  }
4023
- return { space: match[1], path: match[2] };
4068
+ return { space, path };
4024
4069
  }
4025
4070
  function parseEncryptionResource(resource) {
4026
4071
  if (!resource.startsWith("urn:tinycloud:encryption:")) throw new Error("encryption capability is invalid");
@@ -4165,7 +4210,7 @@ function unifiedPolicyCapabilityFromNative(input) {
4165
4210
  throw new Error("native capability is not supported");
4166
4211
  const caveat = object2(value.caveat, "native.caveat");
4167
4212
  exactKeys(caveat, ["type", "kind", "value"], "native selector caveat");
4168
- if (caveat.type !== "xyz.tinycloud.resource/selector" || caveat.kind !== "exact" && caveat.kind !== "prefix" || caveat.value !== `tinycloud://${value.space}/kv/${value.path}`)
4213
+ 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}`)
4169
4214
  throw new Error("native selector caveat does not match capability");
4170
4215
  return normalizeUnifiedPolicyCapability({
4171
4216
  kind: "kv",
@@ -4224,9 +4269,7 @@ var CompactPayloadSchema = import_zod2.z.object({
4224
4269
  nnc: import_zod2.z.string().min(1),
4225
4270
  prf: import_zod2.z.array(import_zod2.z.string().min(1))
4226
4271
  }).strict();
4227
- async function signCompactUcanAuthorization(input) {
4228
- if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > 60)
4229
- throw new Error("compact invocation lifetime must be between one and 60 seconds");
4272
+ async function signCompactUcan(input) {
4230
4273
  const principal = input.issuerDid.split("#", 1)[0];
4231
4274
  const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
4232
4275
  if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
@@ -4248,6 +4291,16 @@ async function signCompactUcanAuthorization(input) {
4248
4291
  if (signature.length !== 64) throw new Error("compact Authorization signature must be Ed25519");
4249
4292
  return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url2(signature)}`);
4250
4293
  }
4294
+ async function signCompactUcanAuthorization(input) {
4295
+ if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > 60)
4296
+ throw new Error("compact invocation lifetime must be between one and 60 seconds");
4297
+ return signCompactUcan(input);
4298
+ }
4299
+ async function signCompactUcanRootAuthorization(input) {
4300
+ if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > 31 * 24 * 60 * 60)
4301
+ throw new Error("compact policy root lifetime must be between one second and 31 days");
4302
+ return signCompactUcan({ ...input, proofs: [] });
4303
+ }
4251
4304
  function createCompactPolicyInvocation(input) {
4252
4305
  const session = parsePolicySessionUcan(input.sessionAuthorization);
4253
4306
  if (session.cid !== input.sessionCid || session.aud !== input.recipientDid)
@@ -4394,14 +4447,14 @@ function decodeBase64Url2(value) {
4394
4447
  if (!/^[A-Za-z0-9_-]+$/.test(value) || value.length % 4 === 1)
4395
4448
  throw new Error("value is not canonical base64url");
4396
4449
  const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
4397
- const binary = typeof Buffer !== "undefined" ? Buffer.from(normalized, "base64").toString("binary") : atob(normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "="));
4450
+ const binary = typeof atob === "function" ? atob(normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "=")) : Buffer.from(normalized, "base64").toString("binary");
4398
4451
  const bytes2 = Uint8Array.from(binary, (character) => character.charCodeAt(0));
4399
- const encoded = typeof Buffer !== "undefined" ? Buffer.from(bytes2).toString("base64url") : btoa(String.fromCharCode(...bytes2)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
4452
+ const encoded = typeof btoa === "function" ? btoa(String.fromCharCode(...bytes2)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_") : Buffer.from(bytes2).toString("base64url");
4400
4453
  if (encoded !== value) throw new Error("value is not canonical base64url");
4401
4454
  return bytes2;
4402
4455
  }
4403
4456
  function encodeBase64Url2(value) {
4404
- return typeof Buffer !== "undefined" ? Buffer.from(value).toString("base64url") : btoa(String.fromCharCode(...value)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
4457
+ return typeof btoa === "function" ? btoa(String.fromCharCode(...value)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_") : Buffer.from(value).toString("base64url");
4405
4458
  }
4406
4459
  function equalBytes(left, right) {
4407
4460
  return left.length === right.length && left.every((byte, index) => byte === right[index]);
@@ -4426,6 +4479,320 @@ function base32Lower(bytes2) {
4426
4479
  return output;
4427
4480
  }
4428
4481
 
4482
+ // src/policy/credential-admission.ts
4483
+ var import_ed255194 = require("@noble/curves/ed25519");
4484
+ var import_sha2562 = require("@noble/hashes/sha256");
4485
+ var POLICY_V2_SCHEMA = "xyz.tinycloud.policy/policy/v2";
4486
+ var POLICY_V2_DOMAIN = "xyz.tinycloud.policy/policy/v2\0";
4487
+ var POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE = "TinyCloudPolicyCredentialRequirement";
4488
+ var POLICY_PRESENTATION_V3_SCHEMA = "xyz.tinycloud.policy/presentation/v3";
4489
+ var POLICY_PRESENTATION_V3_DOMAIN = "xyz.tinycloud.policy/Presentation/v3\0";
4490
+ function record(value, label) {
4491
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
4492
+ throw new Error(`${label} must be an object`);
4493
+ }
4494
+ return value;
4495
+ }
4496
+ function exactKeys2(value, keys, label) {
4497
+ const expected = [...keys].sort();
4498
+ const actual = Object.keys(value).sort();
4499
+ if (actual.length !== expected.length || actual.some((key, index) => key !== expected[index])) {
4500
+ throw new Error(`${label} contains an unknown or missing field`);
4501
+ }
4502
+ }
4503
+ function nonEmpty(value, label) {
4504
+ if (typeof value !== "string" || value.length === 0) {
4505
+ throw new Error(`${label} must be a non-empty string`);
4506
+ }
4507
+ return value;
4508
+ }
4509
+ function policyNodeOrigin(value) {
4510
+ let url;
4511
+ try {
4512
+ url = new URL(value);
4513
+ } catch {
4514
+ throw new Error("policy node origin is invalid");
4515
+ }
4516
+ if (url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.pathname !== "/" || url.search !== "" || url.hash !== "") {
4517
+ throw new Error("policy node origin is invalid");
4518
+ }
4519
+ return url.origin;
4520
+ }
4521
+ function versionPair(value, label) {
4522
+ const item = record(value, label);
4523
+ exactKeys2(item, ["id", "version"], label);
4524
+ if (item.version !== 1) throw new Error(`${label} version is unsupported`);
4525
+ return Object.freeze({ id: nonEmpty(item.id, `${label}.id`), version: 1 });
4526
+ }
4527
+ function validatePolicyCredentialRequirementV1(value) {
4528
+ const item = record(value, "policy credential requirement");
4529
+ exactKeys2(
4530
+ item,
4531
+ [
4532
+ "type",
4533
+ "version",
4534
+ "requirementDigest",
4535
+ "descriptorDigest",
4536
+ "issuerDid",
4537
+ "issuerKid",
4538
+ "profile",
4539
+ "credentialType"
4540
+ ],
4541
+ "policy credential requirement"
4542
+ );
4543
+ if (item.type !== POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE || item.version !== 1 || !isDigest(item.requirementDigest) || !isDigest(item.descriptorDigest)) {
4544
+ throw new Error("policy credential requirement is invalid");
4545
+ }
4546
+ return Object.freeze({
4547
+ type: POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE,
4548
+ version: 1,
4549
+ requirementDigest: item.requirementDigest,
4550
+ descriptorDigest: item.descriptorDigest,
4551
+ issuerDid: nonEmpty(item.issuerDid, "policy credential issuer"),
4552
+ issuerKid: nonEmpty(item.issuerKid, "policy credential issuer key"),
4553
+ profile: versionPair(item.profile, "policy credential profile"),
4554
+ credentialType: versionPair(
4555
+ item.credentialType,
4556
+ "policy credential type"
4557
+ )
4558
+ });
4559
+ }
4560
+ function hex2(bytes2) {
4561
+ return [...bytes2].map((byte) => byte.toString(16).padStart(2, "0")).join("");
4562
+ }
4563
+ function policyV2DigestHex(input) {
4564
+ const canonicalPolicy = {
4565
+ ...input,
4566
+ credentialRequirement: validatePolicyCredentialRequirementV1(
4567
+ input.credentialRequirement
4568
+ ),
4569
+ capabilityCeiling: input.capabilityCeiling.map(
4570
+ normalizeUnifiedPolicyCapability
4571
+ )
4572
+ };
4573
+ return hex2(
4574
+ (0, import_sha2562.sha256)(
4575
+ new TextEncoder().encode(
4576
+ POLICY_V2_DOMAIN + jcsCanonicalize(canonicalPolicy)
4577
+ )
4578
+ )
4579
+ );
4580
+ }
4581
+ function date(value, label) {
4582
+ const text2 = nonEmpty(value, label);
4583
+ if (!Number.isFinite(Date.parse(text2))) throw new Error(`${label} is invalid`);
4584
+ return text2;
4585
+ }
4586
+ function rfc3339Seconds(value) {
4587
+ return new Date(Math.floor(value.getTime() / 1e3) * 1e3).toISOString().replace(/\.000Z$/, "Z");
4588
+ }
4589
+ function validateUnifiedPolicyV2(value, expectedPolicyCid) {
4590
+ const item = record(value, "Policy/v2");
4591
+ const allowed = [
4592
+ "schema",
4593
+ "policyId",
4594
+ "ownerDid",
4595
+ "createdAt",
4596
+ "contentSource",
4597
+ "capabilityCeiling",
4598
+ "credentialRequirement",
4599
+ "signature",
4600
+ ...item.expiresAt === void 0 ? [] : ["expiresAt"]
4601
+ ];
4602
+ exactKeys2(item, allowed, "Policy/v2");
4603
+ if (item.schema !== POLICY_V2_SCHEMA || !Array.isArray(item.capabilityCeiling)) {
4604
+ throw new Error("Policy/v2 is invalid");
4605
+ }
4606
+ const ownerDid = nonEmpty(item.ownerDid, "Policy/v2 ownerDid");
4607
+ const signature = record(item.signature, "Policy/v2 signature");
4608
+ exactKeys2(signature, ["suite", "signerDid", "value"], "Policy/v2 signature");
4609
+ if (signature.suite !== "Ed25519" || signature.signerDid !== ownerDid || typeof signature.value !== "string" || signature.value.length === 0) {
4610
+ throw new Error("Policy/v2 signature binding is invalid");
4611
+ }
4612
+ const policy = Object.freeze({
4613
+ schema: POLICY_V2_SCHEMA,
4614
+ policyId: nonEmpty(item.policyId, "Policy/v2 policyId"),
4615
+ ownerDid,
4616
+ createdAt: date(item.createdAt, "Policy/v2 createdAt"),
4617
+ ...item.expiresAt === void 0 ? {} : { expiresAt: date(item.expiresAt, "Policy/v2 expiresAt") },
4618
+ contentSource: item.contentSource,
4619
+ capabilityCeiling: Object.freeze(
4620
+ item.capabilityCeiling.map(normalizeUnifiedPolicyCapability)
4621
+ ),
4622
+ credentialRequirement: validatePolicyCredentialRequirementV1(
4623
+ item.credentialRequirement
4624
+ ),
4625
+ signature: Object.freeze({
4626
+ suite: "Ed25519",
4627
+ signerDid: ownerDid,
4628
+ value: signature.value
4629
+ })
4630
+ });
4631
+ const unsigned = { ...policy };
4632
+ delete unsigned.policyId;
4633
+ delete unsigned.signature;
4634
+ const digestHex = policyV2DigestHex(unsigned);
4635
+ if (policy.policyId !== policyIdForDigestHex(digestHex)) {
4636
+ throw new Error("Policy/v2 policyId binding is invalid");
4637
+ }
4638
+ if (expectedPolicyCid !== void 0) {
4639
+ const cid2 = policyCidFromCanonicalBytes(
4640
+ new TextEncoder().encode(jcsCanonicalize(policy))
4641
+ );
4642
+ if (cid2 !== expectedPolicyCid) throw new Error("Policy/v2 CID binding is invalid");
4643
+ }
4644
+ return policy;
4645
+ }
4646
+ function didKeyBytes(did) {
4647
+ const principal = did.split("#", 1)[0];
4648
+ if (!principal.startsWith("did:key:")) throw new Error("holder DID must be did:key");
4649
+ const material = base58btc.decode(principal.slice("did:key:".length));
4650
+ if (material.length !== 34 || material[0] !== 237 || material[1] !== 1) {
4651
+ throw new Error("holder DID must contain an Ed25519 key");
4652
+ }
4653
+ return material.slice(2);
4654
+ }
4655
+ function envelopeFromVerified(verified) {
4656
+ const {
4657
+ verifiedAt: _verifiedAt,
4658
+ credentialDigest: _credentialDigest,
4659
+ statusCheckedAt: _statusCheckedAt,
4660
+ ...envelope
4661
+ } = verified;
4662
+ return envelope;
4663
+ }
4664
+ async function buildPolicyCredentialPresentationV3(input) {
4665
+ const policy = validateUnifiedPolicyV2(input.policy, input.policyCid);
4666
+ const requirement = validateCredentialRequirement(input.requirement);
4667
+ const commitment = policy.credentialRequirement;
4668
+ const requirementDigest = await credentialRequirementDigest(requirement);
4669
+ const credentialDigest = await sha256Base64Url(input.credential.credential);
4670
+ 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)) {
4671
+ throw new Error("credential does not match the signed Policy/v2 requirement");
4672
+ }
4673
+ const requestedCapabilities = input.requestedCapabilities.map(
4674
+ normalizeUnifiedPolicyCapability
4675
+ );
4676
+ if (requestedCapabilities.length === 0 || requestedCapabilities.some(
4677
+ (requested) => !policy.capabilityCeiling.some(
4678
+ (authority) => unifiedPolicyCapabilityContains(authority, requested)
4679
+ )
4680
+ )) {
4681
+ throw new Error("requested capabilities exceed the signed Policy/v2 ceiling");
4682
+ }
4683
+ const challenge = input.challenge;
4684
+ const holderDid = input.credential.holderDid;
4685
+ 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))) {
4686
+ throw new Error("policy challenge binding is invalid");
4687
+ }
4688
+ didKeyBytes(holderDid);
4689
+ const now = input.now ?? /* @__PURE__ */ new Date();
4690
+ const challengeExpiry = Date.parse(challenge.expiresAt);
4691
+ const credentialExpiry = Date.parse(input.credential.expiresAt);
4692
+ const expiresAtMs = Math.min(
4693
+ now.getTime() + 6e4,
4694
+ challengeExpiry,
4695
+ credentialExpiry
4696
+ );
4697
+ if (expiresAtMs <= now.getTime()) throw new Error("policy challenge is expired");
4698
+ const unsigned = Object.freeze({
4699
+ schema: POLICY_PRESENTATION_V3_SCHEMA,
4700
+ jti: input.jti ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
4701
+ challengeId: challenge.challengeId,
4702
+ nonce: challenge.nonce,
4703
+ policyCid: input.policyCid,
4704
+ nodeAudience: challenge.nodeAudience,
4705
+ holderDid,
4706
+ subjectDid: input.credential.subjectDid,
4707
+ credentialSpaceOwnerDid: nonEmpty(
4708
+ input.credentialSpaceOwnerDid,
4709
+ "credential space owner DID"
4710
+ ),
4711
+ credentialDigest,
4712
+ requirementDigest,
4713
+ descriptorDigest: input.credential.descriptorDigest,
4714
+ requestedCapabilities: Object.freeze(requestedCapabilities),
4715
+ issuedAt: rfc3339Seconds(now),
4716
+ expiresAt: rfc3339Seconds(new Date(expiresAtMs))
4717
+ });
4718
+ const digest4 = (0, import_sha2562.sha256)(
4719
+ new TextEncoder().encode(
4720
+ POLICY_PRESENTATION_V3_DOMAIN + jcsCanonicalize(unsigned)
4721
+ )
4722
+ );
4723
+ const signature = await input.sign(digest4);
4724
+ if (signature.length !== 64 || !import_ed255194.ed25519.verify(signature, digest4, didKeyBytes(holderDid))) {
4725
+ throw new Error("policy presentation signature is invalid");
4726
+ }
4727
+ return Object.freeze({
4728
+ ...unsigned,
4729
+ signature: Object.freeze({
4730
+ suite: "Ed25519",
4731
+ signerDid: holderDid,
4732
+ value: encodeBase64Url(signature)
4733
+ })
4734
+ });
4735
+ }
4736
+ async function admitPolicyCredentialV3(input) {
4737
+ const policy = validateUnifiedPolicyV2(input.policy, input.policyCid);
4738
+ const nodeOrigin = policyNodeOrigin(input.nodeOrigin);
4739
+ const accountAuthorizationCid = nonEmpty(
4740
+ input.accountAuthorizationCid,
4741
+ "account authorization CID"
4742
+ );
4743
+ const credentialSpaceId = nonEmpty(
4744
+ input.credentialSpaceId,
4745
+ "credential space ID"
4746
+ );
4747
+ const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
4748
+ const challenge = await requestPolicyChallengeV3({
4749
+ nodeOrigin,
4750
+ policyCid: input.policyCid,
4751
+ recipientDid: input.credential.holderDid,
4752
+ requestedCapabilities: input.requestedCapabilities,
4753
+ fetch: fetchFn
4754
+ });
4755
+ const presentation = await buildPolicyCredentialPresentationV3({
4756
+ ...input,
4757
+ policy,
4758
+ challenge
4759
+ });
4760
+ const response = await fetchFn(
4761
+ new URL("/share/v3/policy/delegations", nodeOrigin),
4762
+ {
4763
+ method: "POST",
4764
+ redirect: "error",
4765
+ headers: { accept: "application/json", "content-type": "application/json" },
4766
+ body: JSON.stringify({
4767
+ policyCid: input.policyCid,
4768
+ challengeId: challenge.challengeId,
4769
+ nonce: challenge.nonce,
4770
+ requirement: validateCredentialRequirement(input.requirement),
4771
+ credential: envelopeFromVerified(input.credential),
4772
+ accountAuthorizationCid,
4773
+ credentialSpaceId,
4774
+ presentation
4775
+ })
4776
+ }
4777
+ );
4778
+ if (!response.ok) throw new Error(`policy delegation rejected (${response.status})`);
4779
+ const value = record(await response.json(), "policy delegation");
4780
+ if (value.admitted !== true || typeof value.sessionCid !== "string" || typeof value.authorization !== "string") {
4781
+ throw new Error("policy delegation response is invalid");
4782
+ }
4783
+ const session = parsePolicySessionUcan(value.authorization, [
4784
+ input.policyRootCid,
4785
+ input.enforcementRootCid
4786
+ ]);
4787
+ const expectedAttenuation = compactAttenuationForPolicyCapabilities(
4788
+ input.requestedCapabilities
4789
+ );
4790
+ 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)) {
4791
+ throw new Error("policy delegation signed binding is invalid");
4792
+ }
4793
+ return Object.freeze({ challenge, presentation, session });
4794
+ }
4795
+
4429
4796
  // src/requester/index.ts
4430
4797
  var REQUESTER_NEAR_EXPIRY_SECONDS = 30;
4431
4798
  var REQUESTER_ENGINE_RETRY_ATTEMPTS = 3;
@@ -4677,15 +5044,15 @@ var TranscriptRequester = class _TranscriptRequester {
4677
5044
  "bootstrap owner-node binding does not match trusted discovery/config"
4678
5045
  );
4679
5046
  }
4680
- const record = await verifyRecordBeforeEgress(bootstrap, options2);
4681
- if (record.endpoint !== bootstrap.policyEngine.endpoint) {
5047
+ const record2 = await verifyRecordBeforeEgress(bootstrap, options2);
5048
+ if (record2.endpoint !== bootstrap.policyEngine.endpoint) {
4682
5049
  throw new TranscriptRequesterError(
4683
5050
  "requester-engine-record-endpoint-mismatch",
4684
5051
  "policy engine record endpoint does not match bootstrap endpoint",
4685
5052
  "bootstrap-invalid"
4686
5053
  );
4687
5054
  }
4688
- if (record.audience !== bootstrap.policyEngine.audience) {
5055
+ if (record2.audience !== bootstrap.policyEngine.audience) {
4689
5056
  throw new TranscriptRequesterError(
4690
5057
  "requester-engine-record-audience-mismatch",
4691
5058
  "policy engine record audience does not match bootstrap audience",
@@ -4716,7 +5083,7 @@ var TranscriptRequester = class _TranscriptRequester {
4716
5083
  requestedCapabilities,
4717
5084
  nativeAuthorityCeiling,
4718
5085
  requestedCapabilitiesHash(requestedCapabilities),
4719
- parseStrictRfc33392(record.expiresAt),
5086
+ parseStrictRfc33392(record2.expiresAt),
4720
5087
  policyEngineAddresses,
4721
5088
  ownerNodeAddresses,
4722
5089
  options2
@@ -5585,9 +5952,9 @@ function parseNodeDataResponse(response, schema, label) {
5585
5952
  function nodeErrorMessage(body) {
5586
5953
  if (typeof body === "string") return body;
5587
5954
  if (body !== null && typeof body === "object") {
5588
- const record = body;
5589
- const code3 = typeof record.code === "string" ? record.code : void 0;
5590
- const message = typeof record.message === "string" ? record.message : void 0;
5955
+ const record2 = body;
5956
+ const code3 = typeof record2.code === "string" ? record2.code : void 0;
5957
+ const message = typeof record2.message === "string" ? record2.message : void 0;
5591
5958
  if (code3 !== void 0)
5592
5959
  return message === void 0 ? code3 : `${code3}: ${message}`;
5593
5960
  }
@@ -7909,17 +8276,17 @@ function parseRecapCapabilities(parseWasm, siwe) {
7909
8276
  }
7910
8277
 
7911
8278
  // src/delegations/SharingService.ts
7912
- var import_ed255196 = require("@noble/curves/ed25519");
8279
+ var import_ed255197 = require("@noble/curves/ed25519");
7913
8280
 
7914
8281
  // src/delegations/ShareRecipientClient.ts
7915
8282
  var import_sdk_services2 = require("@tinycloud/sdk-services");
7916
- var import_ed255195 = require("@noble/curves/ed25519");
7917
- var import_sha2564 = require("@noble/hashes/sha256");
8283
+ var import_ed255196 = require("@noble/curves/ed25519");
8284
+ var import_sha2565 = require("@noble/hashes/sha256");
7918
8285
 
7919
8286
  // src/delegations/share-envelope.ts
7920
- var import_ed255194 = require("@noble/curves/ed25519");
8287
+ var import_ed255195 = require("@noble/curves/ed25519");
7921
8288
  var import_blake33 = require("@noble/hashes/blake3");
7922
- var import_sha2562 = require("@noble/hashes/sha256");
8289
+ var import_sha2563 = require("@noble/hashes/sha256");
7923
8290
  var ENVELOPE_SCHEMA = "xyz.tinycloud.share/envelope";
7924
8291
  var INLINE_PREFIX = "tc2:";
7925
8292
  var RAW_CID_CODEC = 85;
@@ -8138,7 +8505,7 @@ function createSharePolicy(input) {
8138
8505
  };
8139
8506
  }
8140
8507
  function contentDigest(bytes2) {
8141
- return bytesToBase64Url((0, import_sha2562.sha256)(bytes2));
8508
+ return bytesToBase64Url((0, import_sha2563.sha256)(bytes2));
8142
8509
  }
8143
8510
  function computeShareCid(bytes2) {
8144
8511
  const digest4 = create(BLAKE3_256_CODE, (0, import_blake33.blake3)(bytes2));
@@ -8158,7 +8525,7 @@ function envelopeSigningBytes(envelope) {
8158
8525
  }
8159
8526
  function signShareEnvelope(input) {
8160
8527
  if (input.signerPrivateKey.length !== 32) throw new ShareEnvelopeError("invalid-envelope", "Ed25519 private key must be 32 bytes");
8161
- const publicKey = import_ed255194.ed25519.getPublicKey(input.signerPrivateKey);
8528
+ const publicKey = import_ed255195.ed25519.getPublicKey(input.signerPrivateKey);
8162
8529
  const unsigned = {
8163
8530
  schema: ENVELOPE_SCHEMA,
8164
8531
  version: 2,
@@ -8173,7 +8540,7 @@ function signShareEnvelope(input) {
8173
8540
  expiresAt: new Date(input.expiresAt).toISOString(),
8174
8541
  signer: { did: input.signerDid, publicKey: bytesToBase64Url(publicKey) }
8175
8542
  };
8176
- return { ...unsigned, signature: bytesToBase64Url(import_ed255194.ed25519.sign(envelopeSigningBytes(unsigned), input.signerPrivateKey)) };
8543
+ return { ...unsigned, signature: bytesToBase64Url(import_ed255195.ed25519.sign(envelopeSigningBytes(unsigned), input.signerPrivateKey)) };
8177
8544
  }
8178
8545
  function verifyShareEnvelope(envelope, options2 = {}) {
8179
8546
  try {
@@ -8205,7 +8572,7 @@ function verifyShareEnvelope(envelope, options2 = {}) {
8205
8572
  const signature = base64UrlToBytes(envelope.signature);
8206
8573
  const unsigned = { ...envelope };
8207
8574
  delete unsigned.signature;
8208
- if (publicKey.length !== 32 || signature.length !== 64 || !import_ed255194.ed25519.verify(signature, envelopeSigningBytes(unsigned), publicKey)) throw new ShareEnvelopeError("signature-invalid", "share envelope signature is invalid");
8575
+ if (publicKey.length !== 32 || signature.length !== 64 || !import_ed255195.ed25519.verify(signature, envelopeSigningBytes(unsigned), publicKey)) throw new ShareEnvelopeError("signature-invalid", "share envelope signature is invalid");
8209
8576
  if (options2.trustedSignerDids !== void 0 && envelope.recipientKind !== void 0 && !options2.trustedSignerDids.includes(envelope.signer.did)) throw new ShareEnvelopeError("signature-invalid", "share signer is not trusted");
8210
8577
  return envelope;
8211
8578
  } catch (error) {
@@ -8253,7 +8620,7 @@ function encodeInlineShareUrl(input) {
8253
8620
  }
8254
8621
  var PUBLISHED_AAD = new TextEncoder().encode("tinycloud-share-envelope-v1");
8255
8622
  function publishedCid(bytes2) {
8256
- return CID.create(1, code, create(sha2562.code, (0, import_sha2562.sha256)(bytes2))).toString();
8623
+ return CID.create(1, code, create(sha2562.code, (0, import_sha2563.sha256)(bytes2))).toString();
8257
8624
  }
8258
8625
  function isPublishedCid(value) {
8259
8626
  try {
@@ -8293,7 +8660,7 @@ function publishedArtifact(envelope, plaintext, policy) {
8293
8660
  content: {
8294
8661
  mimeType: "application/octet-stream",
8295
8662
  size: plaintext.byteLength,
8296
- digest: bytesToBase64Url((0, import_sha2562.sha256)(plaintext))
8663
+ digest: bytesToBase64Url((0, import_sha2563.sha256)(plaintext))
8297
8664
  },
8298
8665
  // Addressed policy metadata is confidential even though this function
8299
8666
  // is called after the outer envelope has been opened. Keep the
@@ -8397,9 +8764,9 @@ function parsePolicyMetadata(policyBytes, target, expectedExpiry) {
8397
8764
  assertKeys(source, ["kind", "space", "database", "path", "statement", "arguments", "argumentsDigest", "action"], "published SQL content source");
8398
8765
  if (typeof source.space !== "string" || typeof source.database !== "string" || typeof source.path !== "string" || typeof source.statement !== "string" || !source.arguments || typeof source.arguments !== "object" || Array.isArray(source.arguments) || typeof source.argumentsDigest !== "string" || source.action !== "tinycloud.sql/read") throw new ShareEnvelopeError("invalid-envelope", "published SQL content source is invalid");
8399
8766
  for (const argument of Object.values(source.arguments)) if (!Number.isSafeInteger(argument)) throw new ShareEnvelopeError("invalid-envelope", "published SQL arguments are invalid");
8400
- if (bytesToBase64Url((0, import_sha2562.sha256)(new TextEncoder().encode(canonicalJson(source.arguments)))) !== source.argumentsDigest) throw new ShareEnvelopeError("invalid-envelope", "published SQL argument digest is invalid");
8767
+ if (bytesToBase64Url((0, import_sha2563.sha256)(new TextEncoder().encode(canonicalJson(source.arguments)))) !== source.argumentsDigest) throw new ShareEnvelopeError("invalid-envelope", "published SQL argument digest is invalid");
8401
8768
  } else throw new ShareEnvelopeError("invalid-envelope", "policy content source kind is invalid");
8402
- if (typeof policy.contentSourceDigest !== "string" || bytesToBase64Url((0, import_sha2562.sha256)(new TextEncoder().encode(canonicalJson(source)))) !== policy.contentSourceDigest) throw new ShareEnvelopeError("invalid-envelope", "policy content source digest is invalid");
8769
+ if (typeof policy.contentSourceDigest !== "string" || bytesToBase64Url((0, import_sha2563.sha256)(new TextEncoder().encode(canonicalJson(source)))) !== policy.contentSourceDigest) throw new ShareEnvelopeError("invalid-envelope", "policy content source digest is invalid");
8403
8770
  return { recipientKind, actions, resource };
8404
8771
  }
8405
8772
  function parseCanonicalPublishedV2(value, options2) {
@@ -8447,7 +8814,7 @@ function parseCanonicalPublishedV2(value, options2) {
8447
8814
  const signingBytes = new Uint8Array(domain.length + body.length);
8448
8815
  signingBytes.set(domain);
8449
8816
  signingBytes.set(body, domain.length);
8450
- if (signatureBytes.length !== 64 || !import_ed255194.ed25519.verify(signatureBytes, signingBytes, signerKey)) throw new ShareEnvelopeError("signature-invalid", "published v2 envelope signature is invalid");
8817
+ if (signatureBytes.length !== 64 || !import_ed255195.ed25519.verify(signatureBytes, signingBytes, signerKey)) throw new ShareEnvelopeError("signature-invalid", "published v2 envelope signature is invalid");
8451
8818
  const content = options2.plaintext ?? new Uint8Array();
8452
8819
  const normalized = {
8453
8820
  schema: ENVELOPE_SCHEMA,
@@ -8457,7 +8824,7 @@ function parseCanonicalPublishedV2(value, options2) {
8457
8824
  recipientKind: normalizedMatcher.kind,
8458
8825
  resource,
8459
8826
  actions,
8460
- content: { mimeType: typeof contentSource.mimeType === "string" ? contentSource.mimeType : "application/octet-stream", size: content.byteLength, digest: bytesToBase64Url((0, import_sha2562.sha256)(content)) },
8827
+ content: { mimeType: typeof contentSource.mimeType === "string" ? contentSource.mimeType : "application/octet-stream", size: content.byteLength, digest: bytesToBase64Url((0, import_sha2563.sha256)(content)) },
8461
8828
  encrypted: true,
8462
8829
  expiresAt: value.expiry,
8463
8830
  signer: { did: signature.signerDid, publicKey: bytesToBase64Url(signerKey) },
@@ -8556,7 +8923,7 @@ function parsePublishedShareEnvelope(bytes2, options2 = {}) {
8556
8923
  if (envelope.authorizationTarget.kind !== "bearerKey" && (options2.trustedSignerDids === void 0 || !options2.trustedSignerDids.includes(envelope.signature.signerDid))) throw new ShareEnvelopeError("signature-invalid", "a trusted authority is required for addressed shares");
8557
8924
  const signature = base64UrlToBytes(envelope.signature.value);
8558
8925
  const publicKey = publishedPublicKey(envelope.signature.signerDid);
8559
- if (signature.length !== 64 || !import_ed255194.ed25519.verify(signature, publishedEnvelopeSigningBytes(envelope), publicKey)) throw new ShareEnvelopeError("signature-invalid", "published envelope signature is invalid");
8926
+ if (signature.length !== 64 || !import_ed255195.ed25519.verify(signature, publishedEnvelopeSigningBytes(envelope), publicKey)) throw new ShareEnvelopeError("signature-invalid", "published envelope signature is invalid");
8560
8927
  return { envelope, artifact: publishedArtifact(envelope, options2.plaintext ?? new Uint8Array(), policy) };
8561
8928
  }
8562
8929
  function parseLegacyPublishedShareEnvelope(bytes2, options2 = {}) {
@@ -8595,7 +8962,7 @@ function parseLegacyPublishedShareEnvelope(bytes2, options2 = {}) {
8595
8962
  const signingBytes = new Uint8Array(domain.length + body.length);
8596
8963
  signingBytes.set(domain);
8597
8964
  signingBytes.set(body, domain.length);
8598
- if (signatureBytes.length !== 64 || !import_ed255194.ed25519.verify(signatureBytes, signingBytes, signerKey)) throw new ShareEnvelopeError("signature-invalid", "published v1 envelope signature is invalid");
8965
+ if (signatureBytes.length !== 64 || !import_ed255195.ed25519.verify(signatureBytes, signingBytes, signerKey)) throw new ShareEnvelopeError("signature-invalid", "published v1 envelope signature is invalid");
8599
8966
  const content = options2.plaintext ?? new Uint8Array();
8600
8967
  const artifact = {
8601
8968
  envelope: {
@@ -8606,7 +8973,7 @@ function parseLegacyPublishedShareEnvelope(bytes2, options2 = {}) {
8606
8973
  resource: { kind: resource.kind, path: resource.path },
8607
8974
  recipientKind: authorizationTarget.kind === "bearer" ? "bearer" : authorizationTarget.kind === "exact-email" ? "exactEmail" : authorizationTarget.kind === "email-domain" ? "emailDomain" : void 0,
8608
8975
  actions: ["read"],
8609
- content: { mimeType: "application/octet-stream", size: content.byteLength, digest: bytesToBase64Url((0, import_sha2562.sha256)(content)) },
8976
+ content: { mimeType: "application/octet-stream", size: content.byteLength, digest: bytesToBase64Url((0, import_sha2563.sha256)(content)) },
8610
8977
  encrypted: true,
8611
8978
  expiresAt: envelope.expiry,
8612
8979
  signer: { did: signature.signerDid, publicKey: bytesToBase64Url(signerKey) },
@@ -8793,13 +9160,13 @@ function shareCapabilityAllows(capability, action, path) {
8793
9160
  }
8794
9161
 
8795
9162
  // src/delegations/ShareCache.ts
8796
- var import_sha2563 = require("@noble/hashes/sha256");
9163
+ var import_sha2564 = require("@noble/hashes/sha256");
8797
9164
  function cacheKey(key) {
8798
9165
  if (!key.cid || !key.expiresAt) throw new Error("share cache keys require CID and expiry");
8799
9166
  return `${key.cid}\0${key.expiresAt}`;
8800
9167
  }
8801
9168
  function digest2(bytes2) {
8802
- return (0, import_sha2563.sha256)(bytes2);
9169
+ return (0, import_sha2564.sha256)(bytes2);
8803
9170
  }
8804
9171
  function equalBytes2(left, right) {
8805
9172
  if (left.byteLength !== right.byteLength) return false;
@@ -9176,7 +9543,7 @@ function randomJti() {
9176
9543
  return bytesToBase64Url2(bytes2);
9177
9544
  }
9178
9545
  function digestCanonical(value) {
9179
- return bytesToBase64Url2((0, import_sha2564.sha256)(new TextEncoder().encode(canonicalJsonForProof(value))));
9546
+ return bytesToBase64Url2((0, import_sha2565.sha256)(new TextEncoder().encode(canonicalJsonForProof(value))));
9180
9547
  }
9181
9548
  function actionWire(action) {
9182
9549
  return action === "get" ? "tinycloud.kv/get" : action === "metadata" ? "tinycloud.kv/metadata" : action === "list" ? "tinycloud.kv/list" : "tinycloud.kv/put";
@@ -9412,9 +9779,9 @@ var ShareRecipientClient = class {
9412
9779
  const authority = Object.entries(session.att).find(([parentResource, abilities]) => {
9413
9780
  if (!(action in abilities)) return false;
9414
9781
  if (serviceName === "encryption") return parentResource.startsWith("urn:tinycloud:encryption:") && parentResource === cleanPath;
9415
- const match = /^tinycloud:\/\/[^/]+\/kv\/(.+)$/.exec(parentResource);
9416
- if (match === null) return false;
9417
- const parentPath = match[1];
9782
+ const marker = parentResource.indexOf("/kv/");
9783
+ if (marker < 1) return false;
9784
+ const parentPath = parentResource.slice(marker + 4);
9418
9785
  const caveats = abilities[action] ?? [];
9419
9786
  const prefix = caveats.some((value) => isRecord(value) && value.kind === "prefix");
9420
9787
  return cleanPath === parentPath || prefix && cleanPath.startsWith(`${parentPath}/`);
@@ -9440,10 +9807,10 @@ var ShareRecipientClient = class {
9440
9807
  policySessionProjection(delegation) {
9441
9808
  const session = parsePolicySessionUcan(delegation.delegationHeader.Authorization);
9442
9809
  if (session.cid !== delegation.cid || session.aud !== delegation.delegateDID) throw new ShareAccessError("SHARE_SESSION_INVALID");
9443
- const kvResource = Object.keys(session.att).find((resource) => /^tinycloud:\/\/[^/]+\/kv\/.+$/.test(resource));
9444
- const match = kvResource === void 0 ? void 0 : /^tinycloud:\/\/([^/]+)\/kv\/(.+)$/.exec(kvResource);
9445
- if (match === void 0 || match === null) throw new ShareAccessError("SHARE_SESSION_INVALID");
9446
- return { spaceId: match[1] };
9810
+ const kvResource = Object.keys(session.att).find((resource) => resource.indexOf("/kv/") > 0);
9811
+ const marker = kvResource?.indexOf("/kv/") ?? -1;
9812
+ if (kvResource === void 0 || marker < 1) throw new ShareAccessError("SHARE_SESSION_INVALID");
9813
+ return { spaceId: kvResource.slice(0, marker) };
9447
9814
  }
9448
9815
  createKV(origin2, session, invokeOverride) {
9449
9816
  const invoke = invokeOverride ?? this.options.invoke ?? nativeInvoke;
@@ -9493,7 +9860,7 @@ var ShareRecipientClient = class {
9493
9860
  if (bytes2.byteLength > (this.options.maxContentBytes ?? DEFAULT_MAX_CONTENT_BYTES)) throw new ShareAccessError("SHARE_TOO_LARGE");
9494
9861
  const contentType = input.contentType ?? envelope.content.mimeType;
9495
9862
  if (contentType !== envelope.content.mimeType && !/^text\/(?:plain|markdown)(?:;|$)/i.test(contentType)) throw new ShareAccessError("SHARE_CONTENT_TYPE_INVALID");
9496
- const result = await this.invokeNative({ envelope, session, action: "put", resource: path, body: bytes2, bodyDigest: bytesToBase64Url2((0, import_sha2564.sha256)(bytes2)), contentType, ifMatch: input.etag, mediaType: "application/vnd.tinycloud.share+json" });
9863
+ const result = await this.invokeNative({ envelope, session, action: "put", resource: path, body: bytes2, bodyDigest: bytesToBase64Url2((0, import_sha2565.sha256)(bytes2)), contentType, ifMatch: input.etag, mediaType: "application/vnd.tinycloud.share+json" });
9497
9864
  if (result.status === 412 || result.status === 409) throw new ShareConflict(path, result.headers?.etag);
9498
9865
  if (result.status === 401 || result.status === 403) throw new ShareAccessError("SHARE_DENIED");
9499
9866
  if (result.status < 200 || result.status >= 300) throw new ShareAccessError("SHARE_WRITE_FAILED");
@@ -9645,44 +10012,44 @@ var ShareRecipientClient = class {
9645
10012
  }
9646
10013
  const parsed = ShareNativeResponseSchema.safeParse(value);
9647
10014
  if (!parsed.success) throw new ShareAccessError("SHARE_RESPONSE_INVALID");
9648
- const record = parsed.data;
10015
+ const record2 = parsed.data;
9649
10016
  const expectedAction = actionWire(input.action);
9650
- if (record.action !== expectedAction || record.version !== 2 || record.resource !== input.resource) {
10017
+ if (record2.action !== expectedAction || record2.version !== 2 || record2.resource !== input.resource) {
9651
10018
  throw new ShareAccessError("SHARE_RESPONSE_MISMATCH");
9652
10019
  }
9653
- if (record.etag !== void 0 && record.etag !== null && headers.etag !== void 0 && record.etag !== headers.etag) throw new ShareAccessError("SHARE_RESPONSE_INTEGRITY");
9654
- if (record.etag !== void 0 && record.etag !== null) headers.etag = record.etag;
10020
+ if (record2.etag !== void 0 && record2.etag !== null && headers.etag !== void 0 && record2.etag !== headers.etag) throw new ShareAccessError("SHARE_RESPONSE_INTEGRITY");
10021
+ if (record2.etag !== void 0 && record2.etag !== null) headers.etag = record2.etag;
9655
10022
  if (input.action === "list") {
9656
- if (record.entries === void 0) throw new ShareAccessError("SHARE_RESPONSE_INVALID");
9657
- const rawEntries = record.entries;
10023
+ if (record2.entries === void 0) throw new ShareAccessError("SHARE_RESPONSE_INVALID");
10024
+ const rawEntries = record2.entries;
9658
10025
  if (rawEntries.length > MAX_NATIVE_ENTRIES) throw new ShareAccessError("SHARE_TOO_LARGE");
9659
10026
  const entries = [...rawEntries];
9660
10027
  const headerCursor = response.headers.get("x-tinycloud-next-cursor");
9661
- if (record.nextCursor !== void 0 && record.nextCursor !== null && headerCursor !== null && record.nextCursor !== headerCursor) throw new ShareAccessError("SHARE_RESPONSE_INTEGRITY");
9662
- const nextCursor = record.nextCursor ?? headerCursor ?? void 0;
10028
+ if (record2.nextCursor !== void 0 && record2.nextCursor !== null && headerCursor !== null && record2.nextCursor !== headerCursor) throw new ShareAccessError("SHARE_RESPONSE_INTEGRITY");
10029
+ const nextCursor = record2.nextCursor ?? headerCursor ?? void 0;
9663
10030
  if (nextCursor !== void 0 && new TextEncoder().encode(nextCursor).byteLength > MAX_NATIVE_CURSOR_BYTES) throw new ShareAccessError("SHARE_TOO_LARGE");
9664
- return { status: response.status, headers, type: record.type, version: record.version, action: record.action, resource: record.resource, keys: entries.map((entry) => entry.path), entries, truncated: nextCursor !== void 0, nextCursor };
10031
+ return { status: response.status, headers, type: record2.type, version: record2.version, action: record2.action, resource: record2.resource, keys: entries.map((entry) => entry.path), entries, truncated: nextCursor !== void 0, nextCursor };
9665
10032
  }
9666
10033
  if (input.action === "get") {
9667
- if (record.content === void 0 || record.bodyDigest === void 0) throw new ShareAccessError("SHARE_RESPONSE_INVALID");
10034
+ if (record2.content === void 0 || record2.bodyDigest === void 0) throw new ShareAccessError("SHARE_RESPONSE_INVALID");
9668
10035
  let bytes2;
9669
10036
  try {
9670
- bytes2 = base64UrlToBytes2(record.content);
10037
+ bytes2 = base64UrlToBytes2(record2.content);
9671
10038
  } catch {
9672
10039
  throw new ShareAccessError("SHARE_RESPONSE_INVALID");
9673
10040
  }
9674
- if (bytes2.byteLength > (this.options.maxContentBytes ?? DEFAULT_MAX_CONTENT_BYTES) || !this.digestMatches(record.bodyDigest, bytes2)) throw new ShareAccessError("SHARE_RESPONSE_INTEGRITY");
9675
- return { status: response.status, headers, bytes: bytes2, bodyDigest: record.bodyDigest, type: record.type, version: record.version, action: record.action, resource: record.resource };
10041
+ if (bytes2.byteLength > (this.options.maxContentBytes ?? DEFAULT_MAX_CONTENT_BYTES) || !this.digestMatches(record2.bodyDigest, bytes2)) throw new ShareAccessError("SHARE_RESPONSE_INTEGRITY");
10042
+ return { status: response.status, headers, bytes: bytes2, bodyDigest: record2.bodyDigest, type: record2.type, version: record2.version, action: record2.action, resource: record2.resource };
9676
10043
  }
9677
10044
  if (input.action === "metadata") {
9678
- if (record.metadata === void 0) throw new ShareAccessError("SHARE_RESPONSE_INVALID");
9679
- return { status: response.status, headers, metadata: record.metadata, etag: record.etag ?? void 0, type: record.type, version: record.version, action: record.action, resource: record.resource };
10045
+ if (record2.metadata === void 0) throw new ShareAccessError("SHARE_RESPONSE_INVALID");
10046
+ return { status: response.status, headers, metadata: record2.metadata, etag: record2.etag ?? void 0, type: record2.type, version: record2.version, action: record2.action, resource: record2.resource };
9680
10047
  }
9681
- const responseEtag = record.etag;
9682
- const responseBodyDigest = record.bodyDigest;
10048
+ const responseEtag = record2.etag;
10049
+ const responseBodyDigest = record2.bodyDigest;
9683
10050
  if (responseEtag === void 0 || responseEtag === null || responseEtag.length === 0 || headers.etag !== void 0 && responseEtag !== headers.etag) throw new ShareAccessError("SHARE_RESPONSE_INVALID");
9684
10051
  if (input.bodyDigest === void 0 || responseBodyDigest === void 0 || responseBodyDigest !== input.bodyDigest || !this.digestMatches(responseBodyDigest, input.body ?? new Uint8Array())) throw new ShareAccessError("SHARE_RESPONSE_INTEGRITY");
9685
- return { status: response.status, headers, bodyDigest: responseBodyDigest, type: record.type, version: record.version, action: record.action, resource: record.resource };
10052
+ return { status: response.status, headers, bodyDigest: responseBodyDigest, type: record2.type, version: record2.version, action: record2.action, resource: record2.resource };
9686
10053
  }
9687
10054
  validateNativeResult(input, result) {
9688
10055
  if (!isNativeSuccess(result)) throw new ShareAccessError("SHARE_RESPONSE_MISMATCH");
@@ -9739,7 +10106,7 @@ var ShareRecipientClient = class {
9739
10106
  }]);
9740
10107
  }
9741
10108
  digestMatches(value, bytes2) {
9742
- const digest4 = bytesToBase64Url2((0, import_sha2564.sha256)(bytes2));
10109
+ const digest4 = bytesToBase64Url2((0, import_sha2565.sha256)(bytes2));
9743
10110
  return value === digest4 || value === `sha-256=:${digest4}:`;
9744
10111
  }
9745
10112
  assertNativeRequestBounds(envelope, session, operation, path, limit, cursor) {
@@ -9957,7 +10324,7 @@ var ShareRecipientClient = class {
9957
10324
  nodeAudience: binding.nodeAudience,
9958
10325
  ...isV2 ? {
9959
10326
  enforcerDid: challenge.enforcerDid,
9960
- credentialDigest: typeof presentation.credentialDigest === "string" ? presentation.credentialDigest : bytesToBase64Url2((0, import_sha2564.sha256)(new TextEncoder().encode(credential)))
10327
+ credentialDigest: typeof presentation.credentialDigest === "string" ? presentation.credentialDigest : bytesToBase64Url2((0, import_sha2565.sha256)(new TextEncoder().encode(credential)))
9961
10328
  } : {},
9962
10329
  action,
9963
10330
  ...binding.actions === void 0 ? {} : { actions: [...binding.actions] },
@@ -10023,7 +10390,7 @@ var ShareRecipientClient = class {
10023
10390
  }
10024
10391
  if (isJwsProof && detached.kid !== `${signerDid}#${encoded}` || isEd25519Proof && detached.signerDid !== signerDid || signature.length !== 64) throw new ShareAccessError("SHARE_SESSION_INVALID", "Node proof binding is invalid");
10025
10392
  const bytes2 = new TextEncoder().encode(`${domain}${canonicalJsonForProof(message)}`);
10026
- if (!import_ed255195.ed25519.verify(signature, bytes2, key)) throw new ShareAccessError("SHARE_SESSION_INVALID", "Node proof signature is invalid");
10393
+ if (!import_ed255196.ed25519.verify(signature, bytes2, key)) throw new ShareAccessError("SHARE_SESSION_INVALID", "Node proof signature is invalid");
10027
10394
  }
10028
10395
  assertChallengeRequestBinding(request, challenge) {
10029
10396
  const source = isRecord(request.body) ? request.body : request;
@@ -11227,7 +11594,7 @@ function shareKeyMatchesDid(key, didUrl) {
11227
11594
  if (!publicKey) return false;
11228
11595
  const jwkBytes = decodeBase64UrlBytes(key.x);
11229
11596
  const privateKey = decodeBase64UrlBytes(key.d);
11230
- const derivedPublicKey = import_ed255196.ed25519.getPublicKey(privateKey);
11597
+ const derivedPublicKey = import_ed255197.ed25519.getPublicKey(privateKey);
11231
11598
  return privateKey.length === 32 && publicKey.length === jwkBytes.length && publicKey.every((byte, index) => byte === jwkBytes[index]) && derivedPublicKey.length === jwkBytes.length && derivedPublicKey.every((byte, index) => byte === jwkBytes[index]);
11232
11599
  } catch {
11233
11600
  return false;
@@ -11277,8 +11644,8 @@ function verifySignedChild(result, expected, computeCid) {
11277
11644
  }
11278
11645
 
11279
11646
  // src/delegations/owner-policy.ts
11280
- var import_ed255197 = require("@noble/curves/ed25519");
11281
- var import_sha2565 = require("@noble/hashes/sha256");
11647
+ var import_ed255198 = require("@noble/curves/ed25519");
11648
+ var import_sha2566 = require("@noble/hashes/sha256");
11282
11649
  var MAX_CONTENT_BYTES = 100 * 1024 * 1024;
11283
11650
  var ENFORCEMENT_DOMAIN = "xyz.tinycloud.share/policy-enforcement/v2\0";
11284
11651
  var POLICY_DOMAIN = "xyz.tinycloud.share/policy/v2\0";
@@ -11305,10 +11672,10 @@ function fromB64(value) {
11305
11672
  throw new Error("base64url decoding is unavailable");
11306
11673
  }
11307
11674
  function cid(bytesValue) {
11308
- return CID.createV1(code, create(sha2562.code, (0, import_sha2565.sha256)(bytesValue))).toString(base32.encoder);
11675
+ return CID.createV1(code, create(sha2562.code, (0, import_sha2566.sha256)(bytesValue))).toString(base32.encoder);
11309
11676
  }
11310
11677
  function digest3(bytesValue) {
11311
- return b64((0, import_sha2565.sha256)(bytesValue));
11678
+ return b64((0, import_sha2566.sha256)(bytesValue));
11312
11679
  }
11313
11680
  function didKeyFromEd25519PublicKey(publicKey) {
11314
11681
  if (publicKey.length !== 32) throw new Error("share key public key must be 32 bytes");
@@ -11380,9 +11747,9 @@ function dagCborEncode(value) {
11380
11747
  }
11381
11748
  function assertObject(value, keys, label) {
11382
11749
  if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${label} is invalid`);
11383
- const record = value;
11384
- if (Object.keys(record).length !== keys.length || keys.some((key) => !Object.prototype.hasOwnProperty.call(record, key))) throw new Error(`${label} has unknown or missing fields`);
11385
- return record;
11750
+ const record2 = value;
11751
+ if (Object.keys(record2).length !== keys.length || keys.some((key) => !Object.prototype.hasOwnProperty.call(record2, key))) throw new Error(`${label} has unknown or missing fields`);
11752
+ return record2;
11386
11753
  }
11387
11754
  async function createDelegatedShareKey(options2) {
11388
11755
  if (!globalThis.crypto?.subtle) throw new Error("WebCrypto Ed25519 is required for delegated share keys");
@@ -11493,7 +11860,7 @@ function validateOwnerSharePolicyRegistration(value, expected) {
11493
11860
  const publicKey = encodedKid.length === 34 ? encodedKid.slice(2) : encodedKid;
11494
11861
  const signatureBytes = fromB64(proof.signature);
11495
11862
  const signedBytes = new TextEncoder().encode(`${OWNER_SHARE_REGISTRATION_DOMAIN}${canonicalizeSignedObjectUnsigned(registrationCore)}`);
11496
- if (signatureBytes.length !== 64 || !import_ed255197.ed25519.verify(signatureBytes, signedBytes, publicKey)) throw new Error("owner-share registration proof signature is invalid");
11863
+ if (signatureBytes.length !== 64 || !import_ed255198.ed25519.verify(signatureBytes, signedBytes, publicKey)) throw new Error("owner-share registration proof signature is invalid");
11497
11864
  return { registration, proof };
11498
11865
  }
11499
11866
  function validateOwnerSharePolicyRegistrationBytes(bytesValue, expected) {
@@ -11507,7 +11874,7 @@ function validateOwnerSharePolicyRegistrationBytes(bytesValue, expected) {
11507
11874
  }
11508
11875
 
11509
11876
  // src/delegations/share-delivery.ts
11510
- var import_ed255198 = require("@noble/curves/ed25519");
11877
+ var import_ed255199 = require("@noble/curves/ed25519");
11511
11878
  var SHARE_DELIVERY_AUTHORIZATION_DOMAIN = "xyz.tinycloud.share/delivery-authorization/v2\0";
11512
11879
  function isCanonicalHttpsOrigin(value) {
11513
11880
  let url;
@@ -11556,9 +11923,9 @@ var AUTHORIZATION_KEYS = [
11556
11923
  ];
11557
11924
  function assertObject2(value, keys, label) {
11558
11925
  if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${label} is invalid`);
11559
- const record = value;
11560
- if (Object.keys(record).length !== keys.length || keys.some((key) => !Object.prototype.hasOwnProperty.call(record, key))) throw new Error(`${label} has unknown or missing fields`);
11561
- return record;
11926
+ const record2 = value;
11927
+ if (Object.keys(record2).length !== keys.length || keys.some((key) => !Object.prototype.hasOwnProperty.call(record2, key))) throw new Error(`${label} has unknown or missing fields`);
11928
+ return record2;
11562
11929
  }
11563
11930
  function fromB642(value) {
11564
11931
  if (!/^[A-Za-z0-9_-]+$/.test(value)) throw new Error("share delivery value is not canonical base64url");
@@ -11595,7 +11962,7 @@ function validateShareDeliveryAuthorizationBytes(bytesValue, expected) {
11595
11962
  if (publicKey.length !== 32) throw new Error("share delivery authorization proof key is invalid");
11596
11963
  const signatureBytes = fromB642(proof.signature);
11597
11964
  const signedBytes = new TextEncoder().encode(`${SHARE_DELIVERY_AUTHORIZATION_DOMAIN}${canonicalizeSignedObjectUnsigned(authorization)}`);
11598
- if (signatureBytes.length !== 64 || !import_ed255198.ed25519.verify(signatureBytes, signedBytes, publicKey)) throw new Error("share delivery authorization proof signature is invalid");
11965
+ if (signatureBytes.length !== 64 || !import_ed255199.ed25519.verify(signatureBytes, signedBytes, publicKey)) throw new Error("share delivery authorization proof signature is invalid");
11599
11966
  return { authorization, proof };
11600
11967
  }
11601
11968
  function shareDeliveryTrustedKid(publicKey) {
@@ -11612,8 +11979,8 @@ var MemorySenderShareRecordStorage = class {
11612
11979
  constructor() {
11613
11980
  this.records = /* @__PURE__ */ new Map();
11614
11981
  }
11615
- async put(record) {
11616
- this.records.set(record.shareId, record);
11982
+ async put(record2) {
11983
+ this.records.set(record2.shareId, record2);
11617
11984
  }
11618
11985
  async list() {
11619
11986
  return [...this.records.values()];
@@ -11649,7 +12016,7 @@ var SenderShareStore = class {
11649
12016
  async save(receipt, key) {
11650
12017
  const registration = receipt.registration;
11651
12018
  if (registration.shareKeyDid !== key.did) throw new Error("share key does not match the registered receipt");
11652
- const record = {
12019
+ const record2 = {
11653
12020
  shareId: registration.shareId,
11654
12021
  registrationCid: registration.registrationCid,
11655
12022
  policyCid: registration.policyCid,
@@ -11665,15 +12032,15 @@ var SenderShareStore = class {
11665
12032
  registeredAt: registration.registeredAt,
11666
12033
  expiresAt: registration.expiresAt
11667
12034
  };
11668
- await this.records.put(record);
11669
- await this.keys.put(record.shareId, { cryptoKey: key.cryptoKey, publicKey: key.publicKey, extractable: key.extractable });
11670
- return record;
12035
+ await this.records.put(record2);
12036
+ await this.keys.put(record2.shareId, { cryptoKey: key.cryptoKey, publicKey: key.publicKey, extractable: key.extractable });
12037
+ return record2;
11671
12038
  }
11672
12039
  /** List shares created in any session, most recent first. */
11673
12040
  async list(options2) {
11674
12041
  const now = this.now().getTime();
11675
12042
  const records = await this.records.list();
11676
- return records.filter((record) => (options2?.includeRevoked ?? false) || record.revokedAt === void 0).filter((record) => (options2?.includeExpired ?? false) || Date.parse(record.expiresAt) > now).sort((left, right) => Date.parse(right.registeredAt) - Date.parse(left.registeredAt));
12043
+ return records.filter((record2) => (options2?.includeRevoked ?? false) || record2.revokedAt === void 0).filter((record2) => (options2?.includeExpired ?? false) || Date.parse(record2.expiresAt) > now).sort((left, right) => Date.parse(right.registeredAt) - Date.parse(left.registeredAt));
11677
12044
  }
11678
12045
  async get(shareId) {
11679
12046
  return this.records.get(shareId);
@@ -11696,15 +12063,15 @@ var SenderShareStore = class {
11696
12063
  * returned CID, then call {@link markRevoked} once that succeeds.
11697
12064
  */
11698
12065
  async revocationTarget(shareId, scope) {
11699
- const record = await this.records.get(shareId);
11700
- if (record === void 0) throw new Error(`Unknown share: ${shareId}`);
11701
- return scope === "direct" ? record.enforcementDelegationCid : record.ownerDelegationCid;
12066
+ const record2 = await this.records.get(shareId);
12067
+ if (record2 === void 0) throw new Error(`Unknown share: ${shareId}`);
12068
+ return scope === "direct" ? record2.enforcementDelegationCid : record2.ownerDelegationCid;
11702
12069
  }
11703
12070
  /** Mark a share revoked locally after the caller's node-side revoke call succeeds. */
11704
12071
  async markRevoked(shareId, revokedAt = this.now().toISOString()) {
11705
- const record = await this.records.get(shareId);
11706
- if (record === void 0) throw new Error(`Unknown share: ${shareId}`);
11707
- const revoked = { ...record, revokedAt };
12072
+ const record2 = await this.records.get(shareId);
12073
+ if (record2 === void 0) throw new Error(`Unknown share: ${shareId}`);
12074
+ const revoked = { ...record2, revokedAt };
11708
12075
  await this.records.put(revoked);
11709
12076
  return revoked;
11710
12077
  }
@@ -13498,27 +13865,27 @@ var AccountService = class {
13498
13865
  const kvResult = this.accountKV();
13499
13866
  if (!kvResult.ok) return kvResult;
13500
13867
  let registered;
13501
- for (const record of request.registryRecords) {
13502
- const manifestHash = hashJson(record.manifests);
13503
- if (!options2.assumeUnregistered && await this.indexHasApplicationHash(record.app_id, manifestHash)) {
13868
+ for (const record2 of request.registryRecords) {
13869
+ const manifestHash = hashJson(record2.manifests);
13870
+ if (!options2.assumeUnregistered && await this.indexHasApplicationHash(record2.app_id, manifestHash)) {
13504
13871
  registered = {
13505
- appId: record.app_id,
13506
- manifests: record.manifests,
13872
+ appId: record2.app_id,
13873
+ manifests: record2.manifests,
13507
13874
  manifestHash,
13508
- name: record.manifests[0]?.name,
13509
- description: record.manifests[0]?.description
13875
+ name: record2.manifests[0]?.name,
13876
+ description: record2.manifests[0]?.description
13510
13877
  };
13511
13878
  continue;
13512
13879
  }
13513
13880
  const stored = {
13514
- app_id: record.app_id,
13515
- manifests: record.manifests,
13881
+ app_id: record2.app_id,
13882
+ manifests: record2.manifests,
13516
13883
  manifest_hash: manifestHash,
13517
13884
  updated_at: (/* @__PURE__ */ new Date()).toISOString()
13518
13885
  };
13519
- const written = await kvResult.data.put(record.key, stored);
13886
+ const written = await kvResult.data.put(record2.key, stored);
13520
13887
  if (!written.ok) return accountErr(written.error);
13521
- registered = applicationFromRecord(record.key, stored);
13888
+ registered = applicationFromRecord(record2.key, stored);
13522
13889
  await this.upsertApplicationIndexQuietly(registered);
13523
13890
  }
13524
13891
  return (0, import_sdk_services6.ok)(registered);
@@ -13592,11 +13959,11 @@ var AccountService = class {
13592
13959
  if (!kvResult.ok) return kvResult;
13593
13960
  const stored = spaces.map((space) => spaceRecordFromInput(space));
13594
13961
  const registered = stored.map(
13595
- (record) => spaceFromRecord(spaceKey(record.space_id), record)
13962
+ (record2) => spaceFromRecord(spaceKey(record2.space_id), record2)
13596
13963
  );
13597
- const items = stored.map((record) => ({
13598
- key: spaceKey(record.space_id),
13599
- value: record
13964
+ const items = stored.map((record2) => ({
13965
+ key: spaceKey(record2.space_id),
13966
+ value: record2
13600
13967
  }));
13601
13968
  const batchResult = await kvResult.data.batchPut(items);
13602
13969
  if (batchResult.ok) {
@@ -13607,10 +13974,10 @@ var AccountService = class {
13607
13974
  return accountErr(batchResult.error);
13608
13975
  }
13609
13976
  const reconcileFailures = [];
13610
- for (const record of stored) {
13611
- const written = await kvResult.data.put(spaceKey(record.space_id), record);
13977
+ for (const record2 of stored) {
13978
+ const written = await kvResult.data.put(spaceKey(record2.space_id), record2);
13612
13979
  if (!written.ok) {
13613
- reconcileFailures.push(`${record.space_id}: ${written.error.message}`);
13980
+ reconcileFailures.push(`${record2.space_id}: ${written.error.message}`);
13614
13981
  }
13615
13982
  }
13616
13983
  if (reconcileFailures.length > 0) {
@@ -14230,16 +14597,16 @@ function applicationKey(appId) {
14230
14597
  function appIdFromKey(key) {
14231
14598
  return key.startsWith(ACCOUNT_REGISTRY_PATH) ? key.slice(ACCOUNT_REGISTRY_PATH.length) : key;
14232
14599
  }
14233
- function applicationFromRecord(key, record) {
14234
- const manifests = Array.isArray(record.manifests) ? record.manifests : [];
14600
+ function applicationFromRecord(key, record2) {
14601
+ const manifests = Array.isArray(record2.manifests) ? record2.manifests : [];
14235
14602
  const first = manifests[0];
14236
14603
  return {
14237
- appId: record.app_id ?? record.appId ?? first?.app_id ?? appIdFromKey(key),
14604
+ appId: record2.app_id ?? record2.appId ?? first?.app_id ?? appIdFromKey(key),
14238
14605
  manifests,
14239
- updatedAt: record.updated_at ?? record.updatedAt,
14606
+ updatedAt: record2.updated_at ?? record2.updatedAt,
14240
14607
  name: first?.name,
14241
14608
  description: first?.description,
14242
- manifestHash: record.manifest_hash ?? record.manifestHash ?? hashJson(manifests)
14609
+ manifestHash: record2.manifest_hash ?? record2.manifestHash ?? hashJson(manifests)
14243
14610
  };
14244
14611
  }
14245
14612
  function indexedApplicationFromRow(row) {
@@ -14282,17 +14649,17 @@ function spaceRecordFromInput(space) {
14282
14649
  expires_at: accountSpace.expiresAt instanceof Date ? accountSpace.expiresAt.toISOString() : accountSpace.expiresAt
14283
14650
  };
14284
14651
  }
14285
- function spaceFromRecord(key, record) {
14286
- const expiresAt = record.expires_at ?? record.expiresAt;
14652
+ function spaceFromRecord(key, record2) {
14653
+ const expiresAt = record2.expires_at ?? record2.expiresAt;
14287
14654
  return {
14288
- spaceId: record.space_id ?? record.spaceId ?? spaceIdFromKey(key),
14289
- name: record.name ?? spaceIdFromKey(key).split(":").pop() ?? spaceIdFromKey(key),
14290
- ownerDid: record.owner_did ?? record.ownerDid ?? record.owner ?? "",
14291
- type: record.type ?? "discovered",
14292
- permissions: Array.isArray(record.permissions) ? record.permissions : [],
14293
- status: record.status ?? "active",
14294
- registeredAt: record.registered_at ?? record.registeredAt,
14295
- updatedAt: record.updated_at ?? record.updatedAt,
14655
+ spaceId: record2.space_id ?? record2.spaceId ?? spaceIdFromKey(key),
14656
+ name: record2.name ?? spaceIdFromKey(key).split(":").pop() ?? spaceIdFromKey(key),
14657
+ ownerDid: record2.owner_did ?? record2.ownerDid ?? record2.owner ?? "",
14658
+ type: record2.type ?? "discovered",
14659
+ permissions: Array.isArray(record2.permissions) ? record2.permissions : [],
14660
+ status: record2.status ?? "active",
14661
+ registeredAt: record2.registered_at ?? record2.registeredAt,
14662
+ updatedAt: record2.updated_at ?? record2.updatedAt,
14296
14663
  expiresAt: expiresAt ? new Date(expiresAt) : void 0
14297
14664
  };
14298
14665
  }
@@ -16998,7 +17365,7 @@ function portForProtocol(protocol) {
16998
17365
  }
16999
17366
 
17000
17367
  // src/location.ts
17001
- var import_ed255199 = require("@noble/curves/ed25519");
17368
+ var import_ed2551910 = require("@noble/curves/ed25519");
17002
17369
  var import_viem5 = require("viem");
17003
17370
  var DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL = "https://registry.tinycloud.xyz";
17004
17371
  var DEFAULT_TINYCLOUD_FALLBACK_HOST = "https://node.tinycloud.xyz";
@@ -17063,13 +17430,13 @@ var CloudLocationResolutionError = class extends Error {
17063
17430
  this.attempts = attempts;
17064
17431
  }
17065
17432
  };
17066
- function locationPayloadForRecord(record) {
17433
+ function locationPayloadForRecord(record2) {
17067
17434
  return {
17068
- version: record.version,
17069
- subject: record.subject,
17070
- multiaddrs: [...record.multiaddrs],
17071
- updated_at: record.updated_at,
17072
- sequence: record.sequence
17435
+ version: record2.version,
17436
+ subject: record2.subject,
17437
+ multiaddrs: [...record2.multiaddrs],
17438
+ updated_at: record2.updated_at,
17439
+ sequence: record2.sequence
17073
17440
  };
17074
17441
  }
17075
17442
  function canonicalLocationPayload(payload) {
@@ -17128,13 +17495,13 @@ function validateLocationRecord(input) {
17128
17495
  return { ...payload, signature };
17129
17496
  }
17130
17497
  async function verifyLocationRecord(input) {
17131
- const record = validateLocationRecord(input);
17132
- const payload = canonicalLocationPayload(locationPayloadForRecord(record));
17133
- if (record.subject.startsWith("did:pkh:")) {
17134
- return verifyPkhSignature(record.subject, payload, record.signature);
17498
+ const record2 = validateLocationRecord(input);
17499
+ const payload = canonicalLocationPayload(locationPayloadForRecord(record2));
17500
+ if (record2.subject.startsWith("did:pkh:")) {
17501
+ return verifyPkhSignature(record2.subject, payload, record2.signature);
17135
17502
  }
17136
- if (record.subject.startsWith("did:key:")) {
17137
- return verifyDidKeySignature(record.subject, payload, record.signature);
17503
+ if (record2.subject.startsWith("did:key:")) {
17504
+ return verifyDidKeySignature(record2.subject, payload, record2.signature);
17138
17505
  }
17139
17506
  return false;
17140
17507
  }
@@ -17320,18 +17687,18 @@ async function fetchRegistryLocalLinkCandidates(options2, fetchFn, existingCandi
17320
17687
  }
17321
17688
  const registryUrl = options2.registryUrl ?? DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL;
17322
17689
  try {
17323
- const record = await fetchLocationRecord(registryUrl, options2.subject, fetchFn);
17324
- if (!record) {
17690
+ const record2 = await fetchLocationRecord(registryUrl, options2.subject, fetchFn);
17691
+ if (!record2) {
17325
17692
  return [];
17326
17693
  }
17327
17694
  const shouldVerify = options2.verifyRecords ?? true;
17328
- if (shouldVerify && !await verifyLocationRecord(record)) {
17695
+ if (shouldVerify && !await verifyLocationRecord(record2)) {
17329
17696
  debugLog(
17330
17697
  `registry record signature invalid for ${options2.subject}; skipping local-link lookup`
17331
17698
  );
17332
17699
  return [];
17333
17700
  }
17334
- return extractLocalLinkUrls(record).filter((url) => !existingCandidates.some((c) => c.url === url)).map((url) => ({
17701
+ return extractLocalLinkUrls(record2).filter((url) => !existingCandidates.some((c) => c.url === url)).map((url) => ({
17335
17702
  source: "local-link",
17336
17703
  url,
17337
17704
  timeoutMs: LOCAL_LINK_PROBE_TIMEOUT_MS
@@ -17340,12 +17707,12 @@ async function fetchRegistryLocalLinkCandidates(options2, fetchFn, existingCandi
17340
17707
  return [];
17341
17708
  }
17342
17709
  }
17343
- function extractLocalLinkUrls(record) {
17344
- if (!record) {
17710
+ function extractLocalLinkUrls(record2) {
17711
+ if (!record2) {
17345
17712
  return [];
17346
17713
  }
17347
17714
  const urls = [];
17348
- for (const addr of record.multiaddrs) {
17715
+ for (const addr of record2.multiaddrs) {
17349
17716
  let url;
17350
17717
  try {
17351
17718
  url = multiaddrToHttpUrl(addr);
@@ -17444,12 +17811,12 @@ async function resolveCentralized(subject, options2, verifyRecords) {
17444
17811
  if (!options2.centralizedRegistryUrl) {
17445
17812
  return null;
17446
17813
  }
17447
- const record = await fetchLocationRecord(
17814
+ const record2 = await fetchLocationRecord(
17448
17815
  options2.centralizedRegistryUrl,
17449
17816
  subject,
17450
17817
  options2.fetch
17451
17818
  );
17452
- return toCandidate(subject, "centralized", record, verifyRecords);
17819
+ return toCandidate(subject, "centralized", record2, verifyRecords);
17453
17820
  });
17454
17821
  }
17455
17822
  async function resolveFallback(subject, multiaddrs) {
@@ -17481,18 +17848,18 @@ async function toCandidate(subject, source, input, verifyRecord) {
17481
17848
  }
17482
17849
  const maybeRecord = input;
17483
17850
  if (maybeRecord.version === 1 && maybeRecord.signature !== void 0) {
17484
- const record = validateLocationRecord(input);
17485
- if (record.subject !== subject) {
17851
+ const record2 = validateLocationRecord(input);
17852
+ if (record2.subject !== subject) {
17486
17853
  throw new LocationRecordValidationError(
17487
17854
  "location record subject does not match requested subject"
17488
17855
  );
17489
17856
  }
17490
- if (verifyRecord && !await verifyLocationRecord(record)) {
17857
+ if (verifyRecord && !await verifyLocationRecord(record2)) {
17491
17858
  throw new LocationRecordValidationError(
17492
17859
  "location record signature is invalid"
17493
17860
  );
17494
17861
  }
17495
- return { source, multiaddrs: [...record.multiaddrs], record };
17862
+ return { source, multiaddrs: [...record2.multiaddrs], record: record2 };
17496
17863
  }
17497
17864
  const candidateInput = input;
17498
17865
  if (!Array.isArray(candidateInput.multiaddrs)) {
@@ -17502,18 +17869,18 @@ async function toCandidate(subject, source, input, verifyRecord) {
17502
17869
  }
17503
17870
  validateMultiaddrs(candidateInput.multiaddrs);
17504
17871
  if (candidateInput.record !== void 0) {
17505
- const record = validateLocationRecord(candidateInput.record);
17506
- if (record.subject !== subject) {
17872
+ const record2 = validateLocationRecord(candidateInput.record);
17873
+ if (record2.subject !== subject) {
17507
17874
  throw new LocationRecordValidationError(
17508
17875
  "location record subject does not match requested subject"
17509
17876
  );
17510
17877
  }
17511
- if (verifyRecord && !await verifyLocationRecord(record)) {
17878
+ if (verifyRecord && !await verifyLocationRecord(record2)) {
17512
17879
  throw new LocationRecordValidationError(
17513
17880
  "location record signature is invalid"
17514
17881
  );
17515
17882
  }
17516
- return { source, multiaddrs: [...candidateInput.multiaddrs], record };
17883
+ return { source, multiaddrs: [...candidateInput.multiaddrs], record: record2 };
17517
17884
  }
17518
17885
  return { source, multiaddrs: [...candidateInput.multiaddrs] };
17519
17886
  }
@@ -17570,7 +17937,7 @@ function verifyDidKeySignature(did, payload, signature) {
17570
17937
  "did:key signature must be a base64url Ed25519 signature"
17571
17938
  );
17572
17939
  }
17573
- return import_ed255199.ed25519.verify(
17940
+ return import_ed2551910.ed25519.verify(
17574
17941
  signatureBytes,
17575
17942
  new TextEncoder().encode(payload),
17576
17943
  publicKey
@@ -17578,7 +17945,7 @@ function verifyDidKeySignature(did, payload, signature) {
17578
17945
  }
17579
17946
  function verifyDidKeyEd25519Signature(did, payload, signature) {
17580
17947
  const publicKey = ed25519PublicKeyFromDidKey2(did);
17581
- return import_ed255199.ed25519.verify(signature, payload, publicKey);
17948
+ return import_ed2551910.ed25519.verify(signature, payload, publicKey);
17582
17949
  }
17583
17950
  function ed25519PublicKeyFromDidKey2(did) {
17584
17951
  const identifier = did.slice("did:key:".length);