@tinycloud/sdk-core 3.0.0-beta.6 → 3.0.0-beta.7

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
@@ -64,6 +64,7 @@ __export(index_exports, {
64
64
  CREDENTIAL_CONTRACT_VERSION: () => CREDENTIAL_CONTRACT_VERSION,
65
65
  CREDENTIAL_ERROR_CODES: () => CREDENTIAL_ERROR_CODES,
66
66
  CREDENTIAL_FORMAT: () => CREDENTIAL_FORMAT,
67
+ CREDENTIAL_INVITATION_REQUEST_DOMAIN: () => CREDENTIAL_INVITATION_REQUEST_DOMAIN,
67
68
  CREDENTIAL_PROTOCOL: () => CREDENTIAL_ACQUISITION_PROTOCOL,
68
69
  CREDENTIAL_STEP_REGISTRY_VERSION: () => CREDENTIAL_STEP_REGISTRY_VERSION,
69
70
  CapabilityKeyRegistry: () => CapabilityKeyRegistry,
@@ -87,6 +88,7 @@ __export(index_exports, {
87
88
  DEFAULT_SIGNED_READ_URL_EXPIRY_MS: () => DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
88
89
  DEFAULT_TINYCLOUD_FALLBACK_HOST: () => DEFAULT_TINYCLOUD_FALLBACK_HOST,
89
90
  DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL: () => DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL,
91
+ DELIVERY_ADMISSION_DOMAIN: () => DELIVERY_ADMISSION_DOMAIN,
90
92
  DUCKDB: () => import_bootstrap4.DUCKDB,
91
93
  DataVaultService: () => import_sdk_services8.DataVaultService,
92
94
  DatabaseHandle: () => import_sdk_services8.DatabaseHandle,
@@ -177,7 +179,6 @@ __export(index_exports, {
177
179
  SERVICE_LONG_TO_SHORT: () => SERVICE_LONG_TO_SHORT,
178
180
  SERVICE_SHORT_TO_LONG: () => SERVICE_SHORT_TO_LONG,
179
181
  SHARE_DELIVERY_AUTHORIZATION_DOMAIN: () => SHARE_DELIVERY_AUTHORIZATION_DOMAIN,
180
- SHARE_DELIVERY_AUTHORIZATION_V3_DOMAIN: () => SHARE_DELIVERY_AUTHORIZATION_V3_DOMAIN,
181
182
  SPACE: () => import_bootstrap4.SPACE,
182
183
  SQL: () => import_bootstrap4.SQL,
183
184
  SQLAction: () => import_sdk_services8.SQLAction,
@@ -393,6 +394,7 @@ __export(index_exports, {
393
394
  projectUnifiedPolicyCapabilities: () => projectUnifiedPolicyCapabilities,
394
395
  projectUnifiedPolicyCapability: () => projectUnifiedPolicyCapability,
395
396
  recapCaveatsEqual: () => recapCaveatsEqual,
397
+ registerPolicyV3: () => registerPolicyV3,
396
398
  renewPolicyRootStatusV3: () => renewPolicyRootStatusV3,
397
399
  requestTinyCloudManageKeyScope: () => requestTinyCloudManageKeyScope,
398
400
  resolveCloudLocation: () => resolveCloudLocation,
@@ -3891,7 +3893,8 @@ var MAX_LEGACY_ENVELOPE_EXPIRES_AT = "2026-12-29T00:00:00Z";
3891
3893
  var LAST_V2_READ_AT = "2027-01-05T00:00:00Z";
3892
3894
  async function requestPolicyChallengeV3(input) {
3893
3895
  const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
3894
- const response = await fetchFn(new URL("/share/v3/policy/challenges", input.nodeOrigin), {
3896
+ const policyRuntimePath = policyRuntimeBasePath(input.policyRuntimePath);
3897
+ const response = await fetchFn(new URL(`${policyRuntimePath}/challenges`, input.nodeOrigin), {
3895
3898
  method: "POST",
3896
3899
  redirect: "error",
3897
3900
  signal: input.signal,
@@ -3904,6 +3907,13 @@ async function requestPolicyChallengeV3(input) {
3904
3907
  throw new Error("policy challenge binding is invalid");
3905
3908
  return value;
3906
3909
  }
3910
+ function policyRuntimeBasePath(value) {
3911
+ const path = value ?? "/policy/v3";
3912
+ if (!/^\/policy(?:\/[a-z0-9-]+)*$/.test(path)) {
3913
+ throw new Error("policy runtime path is invalid");
3914
+ }
3915
+ return path;
3916
+ }
3907
3917
  function compactAttenuationForPolicyCapabilities(input) {
3908
3918
  const attenuation = {};
3909
3919
  for (const raw of input) {
@@ -3949,7 +3959,7 @@ function verifyPolicyRootStatusCheckpointV3(input) {
3949
3959
  }
3950
3960
  async function getPolicyRootStatusV3(input) {
3951
3961
  const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
3952
- const response = await fetchFn(new URL(`/share/v3/policy/status/${encodeURIComponent(input.rootCid)}`, input.nodeOrigin), {
3962
+ const response = await fetchFn(new URL(`/policy/v3/status/${encodeURIComponent(input.rootCid)}`, input.nodeOrigin), {
3953
3963
  method: "GET",
3954
3964
  redirect: "error",
3955
3965
  headers: { accept: "application/json" }
@@ -4008,7 +4018,7 @@ async function renewPolicyRootStatusV3(input) {
4008
4018
  };
4009
4019
  const signature = await input.sign((0, import_sha256.sha256)(new TextEncoder().encode(ROOT_STATUS_RENEWAL_V1_DOMAIN + jcsCanonicalize(unsigned))));
4010
4020
  if (signature.length !== 64) throw new Error("policy root renewal signature must be Ed25519");
4011
- const response = await fetchFn(new URL("/share/v3/policy/status", input.nodeOrigin), {
4021
+ const response = await fetchFn(new URL("/policy/v3/status", input.nodeOrigin), {
4012
4022
  method: "POST",
4013
4023
  redirect: "error",
4014
4024
  headers: { accept: "application/json", "content-type": "application/json" },
@@ -4263,6 +4273,133 @@ function contentSourceDigestHex(input) {
4263
4273
  )
4264
4274
  );
4265
4275
  }
4276
+ function exactObject(value, keys, label) {
4277
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
4278
+ throw new Error(`${label} is invalid`);
4279
+ }
4280
+ const record2 = value;
4281
+ if (Object.keys(record2).length !== keys.length || keys.some((key) => !Object.prototype.hasOwnProperty.call(record2, key))) {
4282
+ throw new Error(`${label} is invalid`);
4283
+ }
4284
+ return record2;
4285
+ }
4286
+ function didKeyEd25519PublicKey(value) {
4287
+ const principal = value.split("#", 1)[0];
4288
+ if (!principal.startsWith("did:key:")) {
4289
+ throw new Error("policy enforcer binding signer is invalid");
4290
+ }
4291
+ const material = base58btc.decode(principal.slice("did:key:".length));
4292
+ if (material.length !== 34 || material[0] !== 237 || material[1] !== 1) {
4293
+ throw new Error("policy enforcer binding signer is invalid");
4294
+ }
4295
+ return material.slice(2);
4296
+ }
4297
+ async function registerPolicyV3(input) {
4298
+ const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
4299
+ const rootExpiresAt = new Date(input.rootExpiresAt);
4300
+ const canonicalRootExpiresAt = new Date(
4301
+ Math.floor(rootExpiresAt.getTime() / 1e3) * 1e3
4302
+ ).toISOString().replace(/\.000Z$/, "Z");
4303
+ if (!Number.isFinite(rootExpiresAt.getTime()) || canonicalRootExpiresAt !== input.rootExpiresAt || rootExpiresAt.getTime() <= Date.now()) {
4304
+ throw new Error("policy root expiry is invalid");
4305
+ }
4306
+ const bindingResponse = await fetchFn(
4307
+ new URL("/policy/v3/enforcer-bindings", input.nodeOrigin),
4308
+ {
4309
+ method: "POST",
4310
+ redirect: "error",
4311
+ signal: input.signal,
4312
+ headers: { accept: "application/json", "content-type": "application/json" },
4313
+ body: JSON.stringify({
4314
+ rootExpiresAt: input.rootExpiresAt,
4315
+ enforcerDid: input.enforcerDid
4316
+ })
4317
+ }
4318
+ );
4319
+ if (!bindingResponse.ok) {
4320
+ throw new Error(`policy enforcer binding rejected (${bindingResponse.status})`);
4321
+ }
4322
+ const binding = exactObject(
4323
+ await bindingResponse.json(),
4324
+ [
4325
+ "schema",
4326
+ "enforcerDid",
4327
+ "nodeAudience",
4328
+ "attestationBindingDigestHex",
4329
+ "issuedAt",
4330
+ "expiresAt",
4331
+ "signature"
4332
+ ],
4333
+ "policy enforcer binding"
4334
+ );
4335
+ const signature = exactObject(
4336
+ binding.signature,
4337
+ ["suite", "signerDid", "value"],
4338
+ "policy enforcer binding signature"
4339
+ );
4340
+ const expectedBindingDigestHex = hex(
4341
+ (0, import_sha256.sha256)(
4342
+ new TextEncoder().encode(
4343
+ jcsCanonicalize({
4344
+ enforcerDid: input.enforcerDid,
4345
+ nodeAudience: input.expectedNodeAudience
4346
+ })
4347
+ )
4348
+ )
4349
+ );
4350
+ if (binding.schema !== ATTESTED_ENFORCER_BINDING_V2_SCHEMA || binding.enforcerDid !== input.enforcerDid || binding.nodeAudience !== input.expectedNodeAudience || binding.attestationBindingDigestHex !== expectedBindingDigestHex || binding.expiresAt !== input.rootExpiresAt || typeof binding.issuedAt !== "string" || Date.parse(binding.issuedAt) > Date.now() || signature.suite !== "Ed25519" || signature.signerDid !== input.expectedNodeAudience || typeof signature.value !== "string") {
4351
+ throw new Error("policy enforcer binding is invalid");
4352
+ }
4353
+ const { signature: _signature, ...unsignedBinding } = binding;
4354
+ const signedBinding = (0, import_sha256.sha256)(
4355
+ new TextEncoder().encode(
4356
+ `xyz.tinycloud.policy/AttestedEnforcerBinding/v2\0${jcsCanonicalize(unsignedBinding)}`
4357
+ )
4358
+ );
4359
+ if (!import_ed255193.ed25519.verify(
4360
+ decodeBase64Url2(signature.value),
4361
+ signedBinding,
4362
+ didKeyEd25519PublicKey(input.expectedNodeAudience),
4363
+ { zip215: false }
4364
+ )) {
4365
+ throw new Error("policy enforcer binding signature is invalid");
4366
+ }
4367
+ const response = await fetchFn(
4368
+ new URL("/policy/v3/policies", input.nodeOrigin),
4369
+ {
4370
+ method: "POST",
4371
+ redirect: "error",
4372
+ signal: input.signal,
4373
+ headers: { accept: "application/json", "content-type": "application/json" },
4374
+ body: JSON.stringify({
4375
+ policyCid: input.policyCid,
4376
+ policy: input.policy,
4377
+ policyRoot: input.policyRoot.authorization.replace(/^Bearer\s+/i, ""),
4378
+ enforcementRoot: input.enforcementRoot.authorization.replace(/^Bearer\s+/i, ""),
4379
+ contentSourceDigestHex: input.contentSourceDigestHex,
4380
+ nativeProjectionHashHex: input.nativeProjectionHashHex,
4381
+ attestedEnforcerBinding: binding
4382
+ })
4383
+ }
4384
+ );
4385
+ if (!response.ok) {
4386
+ throw new Error(`policy registration rejected (${response.status})`);
4387
+ }
4388
+ const receipt = exactObject(
4389
+ await response.json(),
4390
+ ["policyCid", "policyRootCid", "enforcementRootCid"],
4391
+ "policy registration response"
4392
+ );
4393
+ if (receipt.policyCid !== input.policyCid || receipt.policyRootCid !== input.policyRoot.cid || receipt.enforcementRootCid !== input.enforcementRoot.cid) {
4394
+ throw new Error("policy registration response binding is invalid");
4395
+ }
4396
+ return {
4397
+ policyCid: input.policyCid,
4398
+ policyRootCid: input.policyRoot.cid,
4399
+ enforcementRootCid: input.enforcementRoot.cid,
4400
+ attestedEnforcerBinding: binding
4401
+ };
4402
+ }
4266
4403
  function policyDigestHex(policy) {
4267
4404
  const canonicalPolicy = {
4268
4405
  ...policy,
@@ -4879,6 +5016,7 @@ async function admitPolicyCredentialV3(input) {
4879
5016
  const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
4880
5017
  const challenge = await requestPolicyChallengeV3({
4881
5018
  nodeOrigin,
5019
+ policyRuntimePath: input.policyRuntimePath,
4882
5020
  policyCid: input.policyCid,
4883
5021
  recipientDid: input.credential.holderDid,
4884
5022
  requestedCapabilities: input.requestedCapabilities,
@@ -4891,7 +5029,7 @@ async function admitPolicyCredentialV3(input) {
4891
5029
  challenge
4892
5030
  });
4893
5031
  const response = await fetchFn(
4894
- new URL("/share/v3/policy/delegations", nodeOrigin),
5032
+ new URL(`${policyRuntimeBasePath2(input.policyRuntimePath)}/delegations`, nodeOrigin),
4895
5033
  {
4896
5034
  method: "POST",
4897
5035
  redirect: "error",
@@ -4936,6 +5074,7 @@ async function admitPolicyCredentialV4(input) {
4936
5074
  const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
4937
5075
  const challenge = await requestPolicyChallengeV3({
4938
5076
  nodeOrigin,
5077
+ policyRuntimePath: input.policyRuntimePath,
4939
5078
  policyCid: input.policyCid,
4940
5079
  recipientDid: input.credential.holderDid,
4941
5080
  requestedCapabilities: input.requestedCapabilities,
@@ -4947,7 +5086,7 @@ async function admitPolicyCredentialV4(input) {
4947
5086
  policy,
4948
5087
  challenge
4949
5088
  });
4950
- const response = await fetchFn(new URL("/share/v3/policy/delegations", nodeOrigin), {
5089
+ const response = await fetchFn(new URL(`${policyRuntimeBasePath2(input.policyRuntimePath)}/delegations`, nodeOrigin), {
4951
5090
  method: "POST",
4952
5091
  redirect: "error",
4953
5092
  signal: input.signal,
@@ -4974,8 +5113,22 @@ async function admitPolicyCredentialV4(input) {
4974
5113
  enforcerDid: input.expectedEnforcerDid
4975
5114
  });
4976
5115
  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)) throw new Error("policy delegation signed binding is invalid");
5116
+ const importResponse = await fetchFn(new URL("/delegate", nodeOrigin), {
5117
+ method: "POST",
5118
+ redirect: "error",
5119
+ signal: input.signal,
5120
+ headers: { Authorization: session.authorization }
5121
+ });
5122
+ if (!importResponse.ok) throw new Error(`delegation import rejected (${importResponse.status})`);
4977
5123
  input.signal?.throwIfAborted();
4978
- return Object.freeze({ challenge, presentation, session });
5124
+ return Object.freeze({ challenge, presentation, session, delegationImported: true });
5125
+ }
5126
+ function policyRuntimeBasePath2(value) {
5127
+ const path = value ?? "/policy/v3";
5128
+ if (!/^\/policy(?:\/[a-z0-9-]+)*$/.test(path)) {
5129
+ throw new Error("policy runtime path is invalid");
5130
+ }
5131
+ return path;
4979
5132
  }
4980
5133
 
4981
5134
  // src/requester/index.ts
@@ -12161,41 +12314,12 @@ function shareDeliveryTrustedKid(publicKey) {
12161
12314
 
12162
12315
  // src/delegations/share-delivery-v3.ts
12163
12316
  var import_ed2551910 = require("@noble/curves/ed25519");
12164
- var SHARE_DELIVERY_AUTHORIZATION_V3_DOMAIN = "xyz.tinycloud.share/delivery-authorization/v3\0";
12165
- var AUTHORIZATION_KEYS2 = [
12166
- "type",
12167
- "version",
12168
- "jti",
12169
- "shareCid",
12170
- "shareId",
12171
- "policyCid",
12172
- "policyRootCid",
12173
- "enforcementRootCid",
12174
- "nodeAudience",
12175
- "enforcerDid",
12176
- "targetOrigin",
12177
- "openCredentialsAudience",
12178
- "holder",
12179
- "recipientMatcher",
12180
- "deliveryEmail",
12181
- "shareUrl",
12182
- "returnOrigin",
12183
- "documentName",
12184
- "senderDid",
12185
- "senderTrust",
12186
- "contentSource",
12187
- "contentSourceDigestHex",
12188
- "shareExpiresAt",
12189
- "issuedAt",
12190
- "reportAbuseToken",
12191
- "actions",
12192
- "resource",
12193
- "requestBodyDigest",
12194
- "idempotencyKey",
12195
- "expiresAt",
12196
- "dataAuthority"
12197
- ];
12198
- function exactObject(value, keys, label) {
12317
+ var import_sha2567 = require("@noble/hashes/sha256");
12318
+ var CREDENTIAL_INVITATION_REQUEST_DOMAIN = "xyz.tinycloud.credentials/invitation-request/v1\0";
12319
+ var DELIVERY_ADMISSION_DOMAIN = "xyz.tinycloud.policy/delivery-admission/v0\0";
12320
+ var REQUEST_KEYS = ["schema", "policyId", "recipient", "resource", "credentialType", "returnLink", "envelopeRef", "audience", "issuedAt", "expiresAt", "nonce"];
12321
+ var ADMISSION_KEYS = ["schema", "policyId", "ownerDid", "recipient", "resource", "actions", "credentialType", "returnLink", "envelopeRef", "senderKeyDid", "audience", "issuedAt", "expiresAt", "nonce", "signature"];
12322
+ function exactObject2(value, keys, label) {
12199
12323
  if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${label} is invalid`);
12200
12324
  const record2 = value;
12201
12325
  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`);
@@ -12214,6 +12338,12 @@ function object3(value, label) {
12214
12338
  if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${label} is invalid`);
12215
12339
  return value;
12216
12340
  }
12341
+ function didKeyBytes2(did) {
12342
+ if (!did.startsWith("did:key:z") || /[#/?]/.test(did.slice("did:key:".length))) throw new Error("v3 delivery admission signer is invalid");
12343
+ const decoded = base58btc.decode(did.slice("did:key:".length));
12344
+ if (decoded.length !== 34 || decoded[0] !== 237 || decoded[1] !== 1) throw new Error("v3 delivery admission signer is invalid");
12345
+ return decoded.slice(2);
12346
+ }
12217
12347
  function validateShareDeliveryAuthorizationV3Bytes(bytes2, expected) {
12218
12348
  let parsed;
12219
12349
  try {
@@ -12221,33 +12351,27 @@ function validateShareDeliveryAuthorizationV3Bytes(bytes2, expected) {
12221
12351
  } catch {
12222
12352
  throw new Error("v3 share delivery response is not valid UTF-8 JSON");
12223
12353
  }
12224
- const root = exactObject(parsed, ["authorization", "proof"], "v3 share delivery response");
12225
- const authorization = exactObject(root.authorization, AUTHORIZATION_KEYS2, "v3 share delivery authorization");
12226
- const proof = exactObject(root.proof, ["alg", "kid", "signature"], "v3 share delivery proof");
12354
+ const root = exactObject2(parsed, ["request", "admission"], "v3 share delivery response");
12355
+ const request = exactObject2(root.request, REQUEST_KEYS, "credential invitation request");
12356
+ const admission = exactObject2(root.admission, ADMISSION_KEYS, "delivery admission");
12357
+ const signature = exactObject2(admission.signature, ["suite", "signerDid", "value"], "delivery admission signature");
12227
12358
  const envelope = object3(expected.request.envelope, "v3 share envelope");
12228
- const policyRoot = object3(envelope.policyRoot, "v3 policy root");
12229
- const enforcementRoot = object3(envelope.enforcementRoot, "v3 enforcement root");
12230
- const target = object3(envelope.target, "v3 target");
12231
- const display = object3(envelope.display, "v3 display");
12232
- const resource = object3(envelope.resource, "v3 resource");
12359
+ const policy = object3(envelope.policy, "v3 share policy");
12360
+ const requirement = object3(policy.credentialRequirement, "v3 credential requirement");
12361
+ const credentialType = object3(requirement.credentialType, "v3 credential type");
12362
+ const contentSource = object3(envelope.contentSource, "v3 content source");
12233
12363
  const envelopeSignature = object3(envelope.signature, "v3 envelope signature");
12234
- const shareUrl = new URL(expected.request.shareUrl);
12235
- const targetOrigin = String(target.origin);
12236
- const targetUrl = new URL(targetOrigin);
12237
- const targetHost = targetUrl.hostname;
12238
- const expectedNodeAudience = `did:web:${targetHost}`;
12239
- if (authorization.type !== "TinyCloudShareDeliveryAuthorization" || authorization.version !== 3 || authorization.dataAuthority !== false || authorization.jti !== expected.request.jti || authorization.shareCid !== expected.request.shareCid || authorization.shareId !== envelope.shareId || authorization.policyCid !== envelope.policyCid || authorization.policyRootCid !== policyRoot.cid || authorization.enforcementRootCid !== enforcementRoot.cid || authorization.enforcerDid !== target.nodeAudience || authorization.targetOrigin !== target.origin || authorization.nodeAudience !== expectedNodeAudience || expected.nodeProof.kid.split("#", 1)[0] !== expectedNodeAudience || authorization.recipientMatcher === void 0 || canonicalizeSignedObjectUnsigned(authorization.recipientMatcher) !== canonicalizeSignedObjectUnsigned(envelope.recipientMatcher) || canonicalizeSignedObjectUnsigned(authorization.contentSource) !== canonicalizeSignedObjectUnsigned(envelope.contentSource) || authorization.contentSourceDigestHex !== envelope.contentSourceDigestHex || authorization.deliveryEmail !== expected.request.recipientEmail || authorization.shareUrl !== expected.request.shareUrl || authorization.documentName !== expected.request.documentName || authorization.documentName !== display.filename || authorization.senderDid !== envelopeSignature.signerDid || authorization.senderTrust !== "verified" || canonicalizeSignedObjectUnsigned(authorization.actions) !== canonicalizeSignedObjectUnsigned(envelope.actions) || authorization.resource !== resource.path || authorization.shareExpiresAt !== envelope.expiry || authorization.requestBodyDigest !== expected.request.requestBodyDigest || authorization.expiresAt !== expected.request.expiresAt || authorization.idempotencyKey !== expected.request.jti || authorization.reportAbuseToken !== expected.request.jti || authorization.returnOrigin !== shareUrl.origin || shareUrl.pathname !== `/s/${authorization.shareCid}` || shareUrl.hash !== `#k=${expected.request.envelopeKey}` || targetUrl.protocol !== "https:" || shareUrl.protocol !== "https:") throw new Error("v3 share delivery authorization is not bound to the submitted request");
12240
- if (typeof authorization.openCredentialsAudience !== "string" || authorization.openCredentialsAudience !== expected.credentialsAudience || authorization.openCredentialsAudience === authorization.nodeAudience || authorization.openCredentialsAudience === authorization.returnOrigin) throw new Error("v3 share delivery credentials audience is untrusted");
12241
- if (proof.alg !== "EdDSA" || proof.kid !== expected.nodeProof.kid || typeof proof.signature !== "string") throw new Error("v3 share delivery proof is invalid");
12242
- const issuedAt = Date.parse(String(authorization.issuedAt));
12243
- const expiresAt = Date.parse(String(authorization.expiresAt));
12244
- const shareExpiresAt = Date.parse(String(authorization.shareExpiresAt));
12245
- if (!Number.isFinite(issuedAt) || !Number.isFinite(expiresAt) || !Number.isFinite(shareExpiresAt) || expiresAt <= issuedAt || expiresAt - issuedAt > 5 * 6e4 || shareExpiresAt <= issuedAt || typeof authorization.holder !== "string" || !authorization.holder.startsWith("did:")) throw new Error("v3 share delivery authorization time or holder is invalid");
12246
- const publicKey = expected.nodeProof.publicKey.length === 34 ? expected.nodeProof.publicKey.slice(2) : expected.nodeProof.publicKey;
12247
- const signature = decodeBase64Url3(proof.signature);
12248
- const signed = new TextEncoder().encode(`${SHARE_DELIVERY_AUTHORIZATION_V3_DOMAIN}${canonicalizeSignedObjectUnsigned(authorization)}`);
12249
- if (publicKey.length !== 32 || signature.length !== 64 || !import_ed2551910.ed25519.verify(signature, signed, publicKey)) throw new Error("v3 share delivery proof signature is invalid");
12250
- return { authorization, proof };
12364
+ const target = object3(envelope.target, "v3 target");
12365
+ const fields = ["policyId", "recipient", "resource", "credentialType", "returnLink", "envelopeRef", "audience", "issuedAt", "expiresAt", "nonce"];
12366
+ if (request.schema !== "xyz.tinycloud.credentials/invitation-request/v1" || admission.schema !== "xyz.tinycloud.policy/delivery-admission/v0" || fields.some((field) => request[field] !== admission[field]) || request.policyId !== envelope.policyCid || request.recipient !== expected.request.recipientEmail || request.resource !== contentSource.kvResource || request.credentialType !== credentialType.id || request.credentialType !== "opencredentials.email/v1" || request.returnLink !== expected.request.shareUrl || request.envelopeRef !== expected.request.shareCid || request.audience !== expected.credentialsAudience || request.expiresAt !== expected.request.expiresAt || request.nonce !== expected.request.jti || admission.ownerDid !== envelopeSignature.signerDid || admission.senderKeyDid !== expected.senderKeyDid || canonicalizeSignedObjectUnsigned(admission.actions) !== canonicalizeSignedObjectUnsigned(["tinycloud.kv/get"]) || signature.suite !== "eddsa-ed25519-sha256-jcs-v1" || signature.signerDid !== target.nodeAudience) throw new Error("v3 share delivery authorization is not bound to the submitted request");
12367
+ const issuedAt = Date.parse(String(request.issuedAt));
12368
+ const expiresAt = Date.parse(String(request.expiresAt));
12369
+ if (!Number.isFinite(issuedAt) || !Number.isFinite(expiresAt) || expiresAt <= issuedAt || expiresAt - issuedAt > 15 * 6e4) throw new Error("v3 share delivery authorization time is invalid");
12370
+ const admissionSignature = decodeBase64Url3(signature.value);
12371
+ const { signature: _signature, ...unsignedAdmission } = admission;
12372
+ const digest4 = (0, import_sha2567.sha256)(new TextEncoder().encode(`${DELIVERY_ADMISSION_DOMAIN}${canonicalizeSignedObjectUnsigned(unsignedAdmission)}`));
12373
+ if (admissionSignature.length !== 64 || !import_ed2551910.ed25519.verify(admissionSignature, digest4, didKeyBytes2(String(signature.signerDid)))) throw new Error("v3 share delivery admission signature is invalid");
12374
+ return { request, admission };
12251
12375
  }
12252
12376
 
12253
12377
  // src/delegations/sender-share-store.ts