@tinycloud/sdk-core 2.11.0-beta.5 → 2.11.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
@@ -6996,6 +6996,10 @@ function normalizeRecipient(recipient) {
6996
6996
  }
6997
6997
  return { kind: recipient.kind, value: domain };
6998
6998
  }
6999
+ if (recipient.kind === "recipientDid") {
7000
+ if (!isCanonicalRecipientDid(recipient.value)) throw new ShareEnvelopeError("invalid-envelope", "recipient DID is invalid");
7001
+ return { kind: recipient.kind, value: recipient.value };
7002
+ }
6999
7003
  const exact = recipient.value.trim();
7000
7004
  const at = exact.lastIndexOf("@");
7001
7005
  const normalizedExact = at > 0 ? `${exact.slice(0, at)}@${exact.slice(at + 1).toLowerCase()}` : exact;
@@ -7004,6 +7008,28 @@ function normalizeRecipient(recipient) {
7004
7008
  }
7005
7009
  return { kind: recipient.kind, value: normalizedExact };
7006
7010
  }
7011
+ function isCanonicalRecipientDid(value) {
7012
+ if (value.length === 0 || value.length > 2048 || /[\u0000-\u0020\u007f]/.test(value)) return false;
7013
+ const parts = value.split(":");
7014
+ if (parts.length < 3 || parts[0] !== "did" || !/^[a-z0-9]+$/.test(parts[1] ?? "")) return false;
7015
+ const identifier = parts.slice(2);
7016
+ if (identifier.some((part) => part.length === 0)) return false;
7017
+ if (parts[1] === "web") {
7018
+ const host = identifier[0] ?? "";
7019
+ if (host.length > 253 || host.split(".").some((label) => !label || label.length > 63 || !/^[A-Za-z0-9-]+$/.test(label) || label.startsWith("-") || label.endsWith("-"))) return false;
7020
+ return identifier.slice(1).every((part) => /^[A-Za-z0-9._%-]+$/.test(part));
7021
+ }
7022
+ if (parts[1] === "pkh") return identifier.length >= 3 && identifier.every((part) => /^[A-Za-z0-9._%-]+$/.test(part));
7023
+ if (parts[1] === "key") {
7024
+ try {
7025
+ const bytes2 = base58btc.decode(identifier.join(":"));
7026
+ return bytes2.length === 34 && bytes2[0] === 237 && bytes2[1] === 1;
7027
+ } catch {
7028
+ return false;
7029
+ }
7030
+ }
7031
+ return false;
7032
+ }
7007
7033
  function normalizeShareRecipientTarget(recipient) {
7008
7034
  const normalized = normalizeRecipient(recipient);
7009
7035
  if (normalized === void 0) throw new ShareEnvelopeError("invalid-envelope", "recipient matcher is required");
@@ -7090,9 +7116,9 @@ function verifyShareEnvelope(envelope, options2 = {}) {
7090
7116
  const recipient = normalizeRecipient(envelope.recipient);
7091
7117
  if (recipient !== void 0 && JSON.stringify(recipient) !== JSON.stringify(envelope.recipient)) throw new ShareEnvelopeError("invalid-envelope", "recipient is not canonical");
7092
7118
  if (recipient?.kind === "exactEmail" || recipient?.kind === "emailDomain") throw new ShareEnvelopeError("unsafe-plaintext", "recipient matchers are not public envelope fields");
7093
- if (envelope.recipientKind !== void 0 && !["exactEmail", "emailDomain", "bearer"].includes(envelope.recipientKind)) throw new ShareEnvelopeError("invalid-envelope", "recipient mode is invalid");
7119
+ if (envelope.recipientKind !== void 0 && !["exactEmail", "emailDomain", "recipientDid", "bearer"].includes(envelope.recipientKind)) throw new ShareEnvelopeError("invalid-envelope", "recipient mode is invalid");
7094
7120
  if (envelope.recipientKind === "bearer" && recipient?.kind !== void 0 && recipient.kind !== "bearer") throw new ShareEnvelopeError("invalid-envelope", "recipient mode does not match recipient");
7095
- if ((envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain") && !envelope.encrypted) throw new ShareEnvelopeError("unsafe-plaintext", "policy shares require encryption");
7121
+ if ((envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain" || envelope.recipientKind === "recipientDid") && !envelope.encrypted) throw new ShareEnvelopeError("unsafe-plaintext", "addressed shares require encryption");
7096
7122
  if (typeof envelope.spaceId !== "string" || envelope.spaceId.length === 0 || typeof envelope.content.mimeType !== "string" || envelope.content.mimeType.length === 0 || typeof envelope.content.digest !== "string" || !/^[A-Za-z0-9_-]+$/.test(envelope.content.digest)) throw new ShareEnvelopeError("invalid-envelope", "content metadata is invalid");
7097
7123
  const maxContentBytes = envelope.encrypted ? options2.maxSealedContentBytes ?? MAX_SEALED_SHARE_CONTENT_BYTES : options2.maxContentBytes ?? MAX_SHARE_CONTENT_BYTES;
7098
7124
  if (!Number.isInteger(envelope.content.size) || envelope.content.size < 0 || envelope.content.size > maxContentBytes) throw new ShareEnvelopeError("content-too-large", "share content exceeds the configured limit");
@@ -7231,7 +7257,7 @@ function parsePolicyMetadata(policyBytes, target, expectedExpiry) {
7231
7257
  assertKeys(policy, ["type", "version", "issuerDid", "recipientMatcher", "target", "delegation", "authority", "actions", "resource", "content-source", "expiresAt"], "published canonical policy material");
7232
7258
  if (typeof policy.issuerDid !== "string" || typeof policy.expiresAt !== "string" || policy.expiresAt !== expectedExpiry) throw new ShareEnvelopeError("invalid-envelope", "policy expiry is not bound to the envelope");
7233
7259
  const matcherValue = policy.recipientMatcher;
7234
- if (!isPlainObject(matcherValue) || matcherValue.kind !== "exactEmail" && matcherValue.kind !== "emailDomain" || typeof matcherValue.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "policy matcher is invalid");
7260
+ if (!isPlainObject(matcherValue) || matcherValue.kind !== "exactEmail" && matcherValue.kind !== "emailDomain" && matcherValue.kind !== "recipientDid" || typeof matcherValue.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "policy matcher is invalid");
7235
7261
  const matcher2 = normalizeRecipient(matcherValue);
7236
7262
  if (matcher2 === void 0 || matcher2.kind === "bearer") throw new ShareEnvelopeError("invalid-envelope", "policy matcher is invalid");
7237
7263
  if (!isPlainObject(policy.target)) throw new ShareEnvelopeError("invalid-envelope", "policy target is invalid");
@@ -7318,7 +7344,7 @@ function parseCanonicalPublishedV2(value, options2) {
7318
7344
  if (!Number.isFinite(expiry) || expiry <= (options2.now ?? /* @__PURE__ */ new Date()).getTime() || new Date(expiry).toISOString() !== value.expiry) throw new ShareEnvelopeError("expired", "published share envelope has expired");
7319
7345
  if (typeof delegation.cid !== "string" || typeof delegation.issuerDid !== "string" || typeof delegation.audience !== "string" || typeof delegation.expiresAt !== "string" || Date.parse(delegation.expiresAt) > expiry) throw new ShareEnvelopeError("invalid-envelope", "published v2 delegation is invalid");
7320
7346
  const matcher = value.recipientMatcher;
7321
- if (!isPlainObject(matcher) || matcher.kind !== "exactEmail" && matcher.kind !== "emailDomain" || typeof matcher.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "published v2 recipient matcher is invalid");
7347
+ if (!isPlainObject(matcher) || matcher.kind !== "exactEmail" && matcher.kind !== "emailDomain" && matcher.kind !== "recipientDid" || typeof matcher.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "published v2 recipient matcher is invalid");
7322
7348
  const normalizedMatcher = normalizeRecipient(matcher);
7323
7349
  if (normalizedMatcher === void 0 || normalizedMatcher.kind === "bearer") throw new ShareEnvelopeError("invalid-envelope", "published v2 recipient matcher is invalid");
7324
7350
  if (!Array.isArray(value.actions)) throw new ShareEnvelopeError("invalid-envelope", "published v2 actions are invalid");
@@ -7759,10 +7785,11 @@ var ShareConflict = class extends Error {
7759
7785
  }
7760
7786
  };
7761
7787
  var ShareAccessError = class extends Error {
7762
- constructor(code3, message) {
7788
+ constructor(code3, message, details) {
7763
7789
  super(message ?? "shared access could not be completed");
7764
7790
  this.name = "ShareAccessError";
7765
7791
  this.code = code3;
7792
+ this.details = details;
7766
7793
  }
7767
7794
  };
7768
7795
 
@@ -7771,6 +7798,7 @@ var import_zod5 = require("zod");
7771
7798
  var ShareRecipientTargetSchema = import_zod5.z.discriminatedUnion("kind", [
7772
7799
  import_zod5.z.object({ kind: import_zod5.z.literal("exactEmail"), value: import_zod5.z.string().min(1) }).strict(),
7773
7800
  import_zod5.z.object({ kind: import_zod5.z.literal("emailDomain"), value: import_zod5.z.string().min(1) }).strict(),
7801
+ import_zod5.z.object({ kind: import_zod5.z.literal("recipientDid"), value: import_zod5.z.string().regex(/^did:[a-z0-9]+:.+$/) }).strict(),
7774
7802
  import_zod5.z.object({ kind: import_zod5.z.literal("bearer") }).strict()
7775
7803
  ]);
7776
7804
  var ShareResourceSchema = import_zod5.z.discriminatedUnion("kind", [
@@ -7814,7 +7842,8 @@ var ShareContentSourceSchema = import_zod5.z.discriminatedUnion("kind", [
7814
7842
  ]);
7815
7843
  var ShareAddressedRecipientSchema = import_zod5.z.discriminatedUnion("kind", [
7816
7844
  import_zod5.z.object({ kind: import_zod5.z.literal("exactEmail"), value: import_zod5.z.string().min(1) }).strict(),
7817
- import_zod5.z.object({ kind: import_zod5.z.literal("emailDomain"), value: import_zod5.z.string().min(1) }).strict()
7845
+ import_zod5.z.object({ kind: import_zod5.z.literal("emailDomain"), value: import_zod5.z.string().min(1) }).strict(),
7846
+ import_zod5.z.object({ kind: import_zod5.z.literal("recipientDid"), value: import_zod5.z.string().regex(/^did:[a-z0-9]+:.+$/) }).strict()
7818
7847
  ]);
7819
7848
  var ShareAddressedDelegationRequestV2Schema = import_zod5.z.object({
7820
7849
  version: import_zod5.z.literal(2),
@@ -8069,12 +8098,21 @@ var ShareRecipientClient = class {
8069
8098
  const { envelope } = resolved.artifact;
8070
8099
  const { location } = resolved;
8071
8100
  const bearer = isBearerEnvelope(envelope);
8072
- const policy = envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain";
8101
+ const policy = envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain" || envelope.authorizationTargetKind === "recipientDid";
8073
8102
  const legacyBearer = !policy && envelope.recipientKind === void 0;
8074
- if (envelope.authorizationTargetKind === "recipientDid") throw new ShareAccessError("SHARE_RECIPIENT_DID_UNSUPPORTED");
8103
+ let recipientDidSession;
8104
+ if (envelope.authorizationTargetKind === "recipientDid") {
8105
+ if (this.options.establishRecipientDidSession === void 0) throw new ShareAccessError("SHARE_DEVICE_AUTH_REQUIRED", "an OpenKey device authorization is required");
8106
+ const authorization = await this.options.establishRecipientDidSession({ envelope, recipientDid: envelope.recipient?.kind === "recipientDid" ? envelope.recipient.value : "" });
8107
+ if ("state" in authorization) {
8108
+ if (authorization.state === "authorization-required") throw new ShareAccessError("SHARE_DEVICE_AUTH_REQUIRED", "an OpenKey device authorization is required", authorization);
8109
+ throw new ShareAccessError("SHARE_DENIED", "recipient DID authorization was denied", authorization);
8110
+ }
8111
+ recipientDidSession = authorization;
8112
+ }
8075
8113
  if (policy && this.options.bearerSession !== void 0) throw new ShareAccessError("SHARE_POLICY_BEARER_MISMATCH");
8076
8114
  if (bearer && this.options.presentation !== void 0) throw new ShareAccessError("SHARE_BEARER_PRESENTATION_MISMATCH");
8077
- const session = bearer || legacyBearer ? this.options.bearerSession : policy && this.options.establishPolicySession !== void 0 ? await this.options.establishPolicySession({ envelope, presentation: this.options.presentation }) : policy ? await this.establishPolicySession(envelope) : void 0;
8115
+ const session = bearer || legacyBearer ? this.options.bearerSession : recipientDidSession ? recipientDidSession : policy && this.options.establishPolicySession !== void 0 ? await this.options.establishPolicySession({ envelope, presentation: this.options.presentation }) : policy ? await this.establishPolicySession(envelope) : void 0;
8078
8116
  const kv = bearer || legacyBearer ? session === void 0 ? void 0 : this.createKV(envelope.origin, session) : void 0;
8079
8117
  const policySession = policy ? session : void 0;
8080
8118
  if (policySession !== void 0) this.assertProvidedPolicySession(policySession, envelope);
@@ -10275,7 +10313,7 @@ function validateShareDeliveryAuthorizationBytes(bytesValue, expected) {
10275
10313
  const authorization = assertObject2(root.authorization, AUTHORIZATION_KEYS, "share delivery authorization");
10276
10314
  const proof = assertObject2(root.proof, ["alg", "kid", "signature"], "share delivery authorization proof");
10277
10315
  const request = expected.request;
10278
- if (authorization.type !== "TinyCloudShareDeliveryAuthorization" || authorization.version !== 2 || authorization.dataAuthority !== false || authorization.jti !== request.jti || authorization.shareCid !== request.shareCid || authorization.shareId !== request.shareId || authorization.registrationCid !== request.registrationCid || authorization.delegationCid !== request.delegationCid || authorization.enforcementDelegationCid !== request.enforcementDelegationCid || authorization.envelopeCid !== request.envelopeCid || authorization.policyCid !== request.policyCid || authorization.deliveryEmail !== request.recipientEmail || authorization.shareUrl !== request.shareUrl || authorization.documentName !== request.documentName || authorization.requestBodyDigest !== request.requestBodyDigest || authorization.expiresAt !== request.expiresAt || authorization.idempotencyKey !== request.jti || authorization.reportAbuseToken !== request.jti || authorization.authorityMaterialHandle !== request.registrationCid) {
10316
+ if (authorization.type !== "TinyCloudShareDeliveryAuthorization" || authorization.version !== 2 || authorization.dataAuthority !== false || authorization.jti !== request.jti || authorization.shareCid !== request.shareCid || authorization.shareId !== request.shareId || authorization.registrationCid !== request.registrationCid || authorization.delegationCid !== request.delegationCid || authorization.enforcementDelegationCid !== request.enforcementDelegationCid || authorization.envelopeCid !== request.envelopeCid || authorization.policyCid !== request.policyCid || authorization.deliveryEmail !== request.recipientEmail || authorization.shareUrl !== request.shareUrl || authorization.documentName !== request.documentName || authorization.requestBodyDigest !== request.requestBodyDigest || authorization.expiresAt !== request.expiresAt || authorization.idempotencyKey !== request.idempotencyKey || authorization.reportAbuseToken !== request.jti || authorization.authorityMaterialHandle !== request.registrationCid) {
10279
10317
  throw new Error("share delivery authorization is not bound to the submitted request");
10280
10318
  }
10281
10319
  if (typeof authorization.issuedAt !== "string" || Date.parse(authorization.issuedAt) > Date.now() + 6e4) throw new Error("share delivery authorization issuedAt is invalid");
@@ -10410,6 +10448,10 @@ var SenderShareStore = class {
10410
10448
  }
10411
10449
  };
10412
10450
 
10451
+ // src/delegations/index.ts
10452
+ var import_share_sdk = require("@tinycloud/share-sdk");
10453
+ var import_share_sdk2 = require("@tinycloud/share-sdk");
10454
+
10413
10455
  // src/networkId.ts
10414
10456
  var import_sdk_services3 = require("@tinycloud/sdk-services");
10415
10457
  function canonicalizeNetworkId(networkId) {