@tinycloud/sdk-core 3.0.0-beta.2 → 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.
- package/dist/delegations/index.cjs +106 -13
- package/dist/delegations/index.cjs.map +1 -1
- package/dist/delegations/index.d.cts +2 -2
- package/dist/delegations/index.d.ts +2 -2
- package/dist/delegations/index.js +106 -13
- package/dist/delegations/index.js.map +1 -1
- package/dist/index.cjs +278 -185
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +278 -185
- package/dist/index.js.map +1 -1
- package/dist/{recipient-types.schema-G8NEKRoo.d.cts → recipient-types.schema-BdCeDExl.d.cts} +64 -1
- package/dist/{recipient-types.schema-G8NEKRoo.d.ts → recipient-types.schema-BdCeDExl.d.ts} +64 -1
- package/package.json +3 -3
|
@@ -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
|
|
1497
|
-
const prototype = Object.getPrototypeOf(
|
|
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(
|
|
1502
|
-
(key) => `${JSON.stringify(key)}:${canonicalize(
|
|
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
|
|
2744
|
-
return `{${Object.keys(
|
|
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
|
|
4340
|
-
return `{${Object.keys(
|
|
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
|
|
5050
|
-
if (typeof
|
|
5051
|
-
if (!Array.isArray(
|
|
5052
|
-
const resource = this.requireObject(
|
|
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:
|
|
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() {
|