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

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.
@@ -46,6 +46,7 @@ __export(delegations_exports, {
46
46
  MemoryShareCache: () => MemoryShareCache,
47
47
  ReceiveOptionsSchema: () => ReceiveOptionsSchema,
48
48
  SHARE_DELIVERY_AUTHORIZATION_DOMAIN: () => SHARE_DELIVERY_AUTHORIZATION_DOMAIN,
49
+ SHARE_DELIVERY_AUTHORIZATION_V3_DOMAIN: () => SHARE_DELIVERY_AUTHORIZATION_V3_DOMAIN,
49
50
  SenderShareStore: () => SenderShareStore,
50
51
  ShareAccessError: () => ShareAccessError,
51
52
  ShareActionSchema: () => ShareActionSchema,
@@ -114,6 +115,7 @@ __export(delegations_exports, {
114
115
  validateOwnerSharePolicyRegistrationBytes: () => validateOwnerSharePolicyRegistrationBytes,
115
116
  validateReceiveOptions: () => validateReceiveOptions,
116
117
  validateShareDeliveryAuthorizationBytes: () => validateShareDeliveryAuthorizationBytes,
118
+ validateShareDeliveryAuthorizationV3Bytes: () => validateShareDeliveryAuthorizationV3Bytes,
117
119
  validateSharingServiceConfig: () => validateSharingServiceConfig,
118
120
  verifyBearerEnvelope: () => import_share_sdk2.verifyBearerEnvelope,
119
121
  verifyShareCid: () => verifyShareCid,
@@ -1493,13 +1495,13 @@ function canonicalizeRecapCaveats(caveats) {
1493
1495
  }
1494
1496
  if (Array.isArray(value)) return `[${value.map(canonicalize).join(",")}]`;
1495
1497
  if (typeof value === "object") {
1496
- const object = value;
1497
- const prototype = Object.getPrototypeOf(object);
1498
+ const object2 = value;
1499
+ const prototype = Object.getPrototypeOf(object2);
1498
1500
  if (prototype !== Object.prototype && prototype !== null) {
1499
1501
  throw new Error("ReCap caveats must contain only JSON values.");
1500
1502
  }
1501
- return `{${Object.keys(object).sort().map(
1502
- (key) => `${JSON.stringify(key)}:${canonicalize(object[key])}`
1503
+ return `{${Object.keys(object2).sort().map(
1504
+ (key) => `${JSON.stringify(key)}:${canonicalize(object2[key])}`
1503
1505
  ).join(",")}}`;
1504
1506
  }
1505
1507
  throw new Error("ReCap caveats must contain only JSON values.");
@@ -2740,8 +2742,8 @@ function canonicalJson(value) {
2740
2742
  }
2741
2743
  if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
2742
2744
  if (typeof value === "object") {
2743
- const object = value;
2744
- return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(object[key])}`).join(",")}}`;
2745
+ const object2 = value;
2746
+ return `{${Object.keys(object2).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(object2[key])}`).join(",")}}`;
2745
2747
  }
2746
2748
  throw new ShareEnvelopeError("invalid-envelope", "unsupported JSON value");
2747
2749
  }
@@ -4336,8 +4338,8 @@ function canonicalJsonForProof(value) {
4336
4338
  }
4337
4339
  if (Array.isArray(value)) return `[${value.map(canonicalJsonForProof).join(",")}]`;
4338
4340
  if (typeof value === "object") {
4339
- const object = value;
4340
- return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${canonicalJsonForProof(object[key])}`).join(",")}}`;
4341
+ const object2 = value;
4342
+ return `{${Object.keys(object2).sort().map((key) => `${JSON.stringify(key)}:${canonicalJsonForProof(object2[key])}`).join(",")}}`;
4341
4343
  }
4342
4344
  throw new ShareAccessError("SHARE_SESSION_INVALID");
4343
4345
  }
@@ -5046,12 +5048,12 @@ var ShareRecipientClient = class {
5046
5048
  this.assertDetachedProof(request.proof);
5047
5049
  }
5048
5050
  parseSessionCapability(value) {
5049
- const object = this.requireObject(value, "session capability");
5050
- if (typeof object.spaceId !== "string") throw new ShareAccessError("SHARE_SESSION_INVALID", "session capability space is invalid");
5051
- if (!Array.isArray(object.actions) || object.actions.some((action) => !["read", "list", "edit"].includes(action))) throw new ShareAccessError("SHARE_SESSION_INVALID", "session capability actions are invalid");
5052
- const resource = this.requireObject(object.resource, "session capability resource");
5051
+ const object2 = this.requireObject(value, "session capability");
5052
+ if (typeof object2.spaceId !== "string") throw new ShareAccessError("SHARE_SESSION_INVALID", "session capability space is invalid");
5053
+ if (!Array.isArray(object2.actions) || object2.actions.some((action) => !["read", "list", "edit"].includes(action))) throw new ShareAccessError("SHARE_SESSION_INVALID", "session capability actions are invalid");
5054
+ const resource = this.requireObject(object2.resource, "session capability resource");
5053
5055
  if (resource.kind !== "exact" && resource.kind !== "prefix" || typeof resource.path !== "string") throw new ShareAccessError("SHARE_SESSION_INVALID", "session capability resource is invalid");
5054
- return { spaceId: object.spaceId, actions: [...new Set(object.actions)], resource: { kind: resource.kind, path: resource.path } };
5056
+ return { spaceId: object2.spaceId, actions: [...new Set(object2.actions)], resource: { kind: resource.kind, path: resource.path } };
5055
5057
  }
5056
5058
  assertProvidedPolicySession(session, envelope) {
5057
5059
  const sessionExpiry = dateValue(session.expiresAt);
@@ -6805,6 +6807,97 @@ function shareDeliveryTrustedKid(publicKey) {
6805
6807
  return `${did}#${did.slice("did:key:".length)}`;
6806
6808
  }
6807
6809
 
6810
+ // src/delegations/share-delivery-v3.ts
6811
+ var import_ed255198 = require("@noble/curves/ed25519");
6812
+ var SHARE_DELIVERY_AUTHORIZATION_V3_DOMAIN = "xyz.tinycloud.share/delivery-authorization/v3\0";
6813
+ var AUTHORIZATION_KEYS2 = [
6814
+ "type",
6815
+ "version",
6816
+ "jti",
6817
+ "shareCid",
6818
+ "shareId",
6819
+ "policyCid",
6820
+ "policyRootCid",
6821
+ "enforcementRootCid",
6822
+ "nodeAudience",
6823
+ "enforcerDid",
6824
+ "targetOrigin",
6825
+ "openCredentialsAudience",
6826
+ "holder",
6827
+ "recipientMatcher",
6828
+ "deliveryEmail",
6829
+ "shareUrl",
6830
+ "returnOrigin",
6831
+ "documentName",
6832
+ "senderDid",
6833
+ "senderTrust",
6834
+ "contentSource",
6835
+ "contentSourceDigestHex",
6836
+ "shareExpiresAt",
6837
+ "issuedAt",
6838
+ "reportAbuseToken",
6839
+ "actions",
6840
+ "resource",
6841
+ "requestBodyDigest",
6842
+ "idempotencyKey",
6843
+ "expiresAt",
6844
+ "dataAuthority"
6845
+ ];
6846
+ function exactObject(value, keys, label) {
6847
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${label} is invalid`);
6848
+ const record = value;
6849
+ 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`);
6850
+ return record;
6851
+ }
6852
+ function decodeBase64Url2(value) {
6853
+ if (typeof value !== "string" || !/^[A-Za-z0-9_-]+$/.test(value)) throw new Error("share delivery value is not canonical base64url");
6854
+ if (typeof atob === "function") {
6855
+ const padded = value.replace(/-/g, "+").replace(/_/g, "/") + "=".repeat((4 - value.length % 4) % 4);
6856
+ return Uint8Array.from(atob(padded), (character) => character.charCodeAt(0));
6857
+ }
6858
+ if (typeof Buffer !== "undefined") return new Uint8Array(Buffer.from(value, "base64url"));
6859
+ throw new Error("base64url decoding is unavailable");
6860
+ }
6861
+ function object(value, label) {
6862
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${label} is invalid`);
6863
+ return value;
6864
+ }
6865
+ function validateShareDeliveryAuthorizationV3Bytes(bytes2, expected) {
6866
+ let parsed;
6867
+ try {
6868
+ parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes2));
6869
+ } catch {
6870
+ throw new Error("v3 share delivery response is not valid UTF-8 JSON");
6871
+ }
6872
+ const root = exactObject(parsed, ["authorization", "proof"], "v3 share delivery response");
6873
+ const authorization = exactObject(root.authorization, AUTHORIZATION_KEYS2, "v3 share delivery authorization");
6874
+ const proof = exactObject(root.proof, ["alg", "kid", "signature"], "v3 share delivery proof");
6875
+ const envelope = object(expected.request.envelope, "v3 share envelope");
6876
+ const policyRoot = object(envelope.policyRoot, "v3 policy root");
6877
+ const enforcementRoot = object(envelope.enforcementRoot, "v3 enforcement root");
6878
+ const target = object(envelope.target, "v3 target");
6879
+ const display = object(envelope.display, "v3 display");
6880
+ const resource = object(envelope.resource, "v3 resource");
6881
+ const envelopeSignature = object(envelope.signature, "v3 envelope signature");
6882
+ const shareUrl = new URL(expected.request.shareUrl);
6883
+ const targetOrigin = String(target.origin);
6884
+ const targetUrl = new URL(targetOrigin);
6885
+ const targetHost = targetUrl.hostname;
6886
+ const expectedNodeAudience = `did:web:${targetHost}`;
6887
+ 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");
6888
+ 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");
6889
+ if (proof.alg !== "EdDSA" || proof.kid !== expected.nodeProof.kid || typeof proof.signature !== "string") throw new Error("v3 share delivery proof is invalid");
6890
+ const issuedAt = Date.parse(String(authorization.issuedAt));
6891
+ const expiresAt = Date.parse(String(authorization.expiresAt));
6892
+ const shareExpiresAt = Date.parse(String(authorization.shareExpiresAt));
6893
+ 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");
6894
+ const publicKey = expected.nodeProof.publicKey.length === 34 ? expected.nodeProof.publicKey.slice(2) : expected.nodeProof.publicKey;
6895
+ const signature = decodeBase64Url2(proof.signature);
6896
+ const signed = new TextEncoder().encode(`${SHARE_DELIVERY_AUTHORIZATION_V3_DOMAIN}${canonicalizeSignedObjectUnsigned(authorization)}`);
6897
+ if (publicKey.length !== 32 || signature.length !== 64 || !import_ed255198.ed25519.verify(signature, signed, publicKey)) throw new Error("v3 share delivery proof signature is invalid");
6898
+ return { authorization, proof };
6899
+ }
6900
+
6808
6901
  // src/delegations/sender-share-store.ts
6809
6902
  var MemorySenderShareRecordStorage = class {
6810
6903
  constructor() {