@tinycloud/share-sdk 1.0.0-beta.8 → 1.0.0-beta.9
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 +37 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.js +37 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6667,6 +6667,7 @@ function targetMatcher(target) {
|
|
|
6667
6667
|
function targetKind(target) {
|
|
6668
6668
|
return target.kind;
|
|
6669
6669
|
}
|
|
6670
|
+
var OWNER_SHARE_ACTIONS = /* @__PURE__ */ new Set(["tinycloud.kv/get", "tinycloud.kv/list", "tinycloud.kv/metadata", "tinycloud.kv/put"]);
|
|
6670
6671
|
function assertSafeInput(input) {
|
|
6671
6672
|
if (!/^[A-Za-z0-9_-]{16,128}$/.test(input.shareId)) throw new TypeError("addressed share id is invalid");
|
|
6672
6673
|
if (!Number.isSafeInteger(input.byteLength) || input.byteLength < 0 || input.byteLength > SHARE_CONTENT_LIMIT) throw new TypeError("addressed content length is invalid");
|
|
@@ -6795,12 +6796,12 @@ function prepareAddressedShare(request) {
|
|
|
6795
6796
|
throw new TypeError("addressed filename is invalid");
|
|
6796
6797
|
}
|
|
6797
6798
|
if (request.actions.length === 0 || request.policyActions.length === 0) throw new TypeError("addressed share actions are empty");
|
|
6799
|
+
if (request.policyActions.some((action) => !OWNER_SHARE_ACTIONS.has(action))) throw new TypeError("addressed share action is not supported");
|
|
6798
6800
|
const target = normalizeShareTarget(request.target);
|
|
6799
6801
|
if (target.kind === "bearer") throw new TypeError("addressed target is required");
|
|
6800
6802
|
if (target.kind === "recipientDid") return { target };
|
|
6801
|
-
if (target.kind === "emailDomain") {
|
|
6802
|
-
|
|
6803
|
-
if (request.deliveryEmail !== void 0) throw new TypeError("email-domain shares are not emailed");
|
|
6803
|
+
if (target.kind === "emailDomain" && request.deliveryEmail !== void 0 && (request.deliveryEmail !== request.deliveryEmail.toLowerCase() || !request.deliveryEmail.endsWith(`@${target.domain}`))) {
|
|
6804
|
+
throw new TypeError("email-domain delivery address must be a lowercase mailbox at the domain");
|
|
6804
6805
|
}
|
|
6805
6806
|
return { target, credentialRequirement: mailboxCredentialCommitment(target) };
|
|
6806
6807
|
}
|
|
@@ -8309,9 +8310,28 @@ function verifyV3PolicyAuthorization(input) {
|
|
|
8309
8310
|
const binding = object3(input.envelope.attestedEnforcerBinding, "v3 attested enforcer binding");
|
|
8310
8311
|
const policy = object3(input.envelope.policy, "v3 policy");
|
|
8311
8312
|
const now = Math.floor(Date.now() / 1e3);
|
|
8312
|
-
if (!legacyShape && !v4Shape || POLICY_SESSION_DIGEST_FACT_KEYS.some((key) => !LOWER_SHA256_HEX.test(fact[key])) || v4Shape && (!LOWER_SHA256_HEX.test(fact.credentialIdAuditDigestHex) || !LOWER_SHA256_HEX.test(fact.presentationJtiAuditDigestHex)) || compact.payload.aud !== input.holderDid || compact.payload.iss.split("#", 1)[0] !== fact.nodeAudience || fact.profile !== "policy-session-ucan/v1" || fact.ownerDid !== policy.ownerDid || fact.policyId !== policy.policyId || fact.policyCid !== input.envelope.policyCid || fact.contentSourceDigestHex !== input.envelope.contentSourceDigestHex || fact.enforcerDid !== binding.enforcerDid || fact.nodeAudience !== binding.nodeAudience || fact.recipientDid !== input.holderDid || fact.policyDelegationCid !== input.envelope.policyRoot.cid || fact.enforcementDelegationCid !== input.envelope.enforcementRoot.cid || typeof fact.remainingRedelegationDepth !== "number" || !Number.isInteger(fact.remainingRedelegationDepth) || fact.remainingRedelegationDepth < 0 || fact.remainingRedelegationDepth > 8 || compact.payload.prf.length !== 2 || compact.payload.prf[0] !== input.envelope.policyRoot.cid || compact.payload.prf[1] !== input.envelope.enforcementRoot.cid || compact.payload.nbf > now || compact.payload.exp <= now || compact.payload.exp
|
|
8313
|
+
if (!legacyShape && !v4Shape || POLICY_SESSION_DIGEST_FACT_KEYS.some((key) => !LOWER_SHA256_HEX.test(fact[key])) || v4Shape && (!LOWER_SHA256_HEX.test(fact.credentialIdAuditDigestHex) || !LOWER_SHA256_HEX.test(fact.presentationJtiAuditDigestHex)) || compact.payload.aud !== input.holderDid || compact.payload.iss.split("#", 1)[0] !== fact.nodeAudience || fact.profile !== "policy-session-ucan/v1" || fact.ownerDid !== policy.ownerDid || fact.policyId !== policy.policyId || fact.policyCid !== input.envelope.policyCid || fact.contentSourceDigestHex !== input.envelope.contentSourceDigestHex || fact.enforcerDid !== binding.enforcerDid || fact.nodeAudience !== binding.nodeAudience || fact.recipientDid !== input.holderDid || fact.policyDelegationCid !== input.envelope.policyRoot.cid || fact.enforcementDelegationCid !== input.envelope.enforcementRoot.cid || typeof fact.remainingRedelegationDepth !== "number" || !Number.isInteger(fact.remainingRedelegationDepth) || fact.remainingRedelegationDepth < 0 || fact.remainingRedelegationDepth > 8 || compact.payload.prf.length !== 2 || compact.payload.prf[0] !== input.envelope.policyRoot.cid || compact.payload.prf[1] !== input.envelope.enforcementRoot.cid || compact.payload.nbf > now || compact.payload.exp <= now || !(compact.payload.exp * 1e3 <= Date.parse(input.envelope.expiry)) || canonicalize(compact.payload.att) !== canonicalize(policyAttenuationForV3(input.envelope))) throw new Error("v3 policy delegation signed binding mismatch");
|
|
8313
8314
|
return compact;
|
|
8314
8315
|
}
|
|
8316
|
+
function verifyV3PolicyDescendants(session, descendants, holderDid) {
|
|
8317
|
+
let parent = session;
|
|
8318
|
+
for (const link of descendants) {
|
|
8319
|
+
const child = verifyCompactUcanAuthorization(link.authorization, link.cid);
|
|
8320
|
+
const { remainingRedelegationDepth: parentDepth, ...parentFacts } = parent.payload.fct[0];
|
|
8321
|
+
const { remainingRedelegationDepth: depth, ...facts } = child.payload.fct[0];
|
|
8322
|
+
if (child.payload.iss.split("#", 1)[0] !== parent.payload.aud || child.payload.prf.length !== 1 || child.payload.prf[0] !== parent.cid || child.payload.nbf <= parent.payload.nbf || child.payload.exp >= parent.payload.exp || typeof parentDepth !== "number" || parentDepth <= 0 || depth !== parentDepth - 1 || canonicalize(facts) !== canonicalize(parentFacts) || canonicalize(child.payload.att) !== canonicalize(parent.payload.att)) throw new Error("v3 policy descendant does not extend its parent");
|
|
8323
|
+
parent = child;
|
|
8324
|
+
}
|
|
8325
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
8326
|
+
if (parent.payload.aud !== holderDid) throw new Error("v3 policy delegation chain does not end at this holder");
|
|
8327
|
+
if (parent.payload.nbf > now || parent.payload.exp <= now) throw new Error("v3 policy delegation chain is not currently valid");
|
|
8328
|
+
return parent;
|
|
8329
|
+
}
|
|
8330
|
+
function requestedSessionExpiry(expiry) {
|
|
8331
|
+
const seconds = Math.floor(Date.parse(expiry) / 1e3);
|
|
8332
|
+
if (!Number.isFinite(seconds) || seconds <= Math.floor(Date.now() / 1e3) + 60) return void 0;
|
|
8333
|
+
return new Date(seconds * 1e3).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
8334
|
+
}
|
|
8315
8335
|
function hex3(value) {
|
|
8316
8336
|
return [...value].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
8317
8337
|
}
|
|
@@ -8364,14 +8384,17 @@ var ShareRecipientClient = class {
|
|
|
8364
8384
|
this.signer = options.sign;
|
|
8365
8385
|
if (options.policyAuthorization !== void 0) {
|
|
8366
8386
|
if (options.envelope.version !== 3) throw new Error("policy delegation fast path requires a v3 envelope");
|
|
8367
|
-
const
|
|
8387
|
+
const { authorization, cid: cid2, descendants = [] } = options.policyAuthorization;
|
|
8388
|
+
const sessionHolder = descendants.length === 0 ? options.holderDid : verifyCompactUcanAuthorization(authorization, cid2).payload.aud;
|
|
8389
|
+
const compact = verifyV3PolicyAuthorization({ authorization, cid: cid2, envelope: options.envelope, holderDid: sessionHolder });
|
|
8390
|
+
const leaf = verifyV3PolicyDescendants(compact, descendants, options.holderDid);
|
|
8368
8391
|
const nodeAudience = compact.payload.fct[0].nodeAudience;
|
|
8369
|
-
this.v3Authorization =
|
|
8392
|
+
this.v3Authorization = leaf.authorization;
|
|
8370
8393
|
this.v3NodeAudience = nodeAudience;
|
|
8371
8394
|
this.nativeSigner = options.sign;
|
|
8372
8395
|
this.session = {
|
|
8373
|
-
sessionId:
|
|
8374
|
-
expiresAt: new Date(
|
|
8396
|
+
sessionId: leaf.cid,
|
|
8397
|
+
expiresAt: new Date(leaf.payload.exp * 1e3).toISOString(),
|
|
8375
8398
|
actions: options.envelope.actions,
|
|
8376
8399
|
resource: options.envelope.resource
|
|
8377
8400
|
};
|
|
@@ -8441,13 +8464,17 @@ var ShareRecipientClient = class {
|
|
|
8441
8464
|
throw new Error(accountless ? "v4 ceremony requires a verified credential and requirement" : "v3 ceremony requires a claim");
|
|
8442
8465
|
}
|
|
8443
8466
|
this.options.onStage?.("policy-admission");
|
|
8444
|
-
const
|
|
8467
|
+
const mintBody = accountless ? { policyCid: envelope.policyCid, challengeId: challenge.challengeId, nonce: challenge.nonce, requirement: material.requirement, credential: material.credentialEnvelope, presentation: material.presentation } : { policyCid: envelope.policyCid, challengeId: challenge.challengeId, nonce: challenge.nonce, claim: material.claim, presentation: material.presentation };
|
|
8468
|
+
const mint = (body) => this.fetchFn(new URL("/policy/v3/delegations", this.options.nodeOrigin), {
|
|
8445
8469
|
method: "POST",
|
|
8446
8470
|
redirect: "error",
|
|
8447
8471
|
headers: { accept: "application/json", "content-type": "application/json" },
|
|
8448
|
-
body: JSON.stringify(
|
|
8472
|
+
body: JSON.stringify(body),
|
|
8449
8473
|
...this.options.signal === void 0 ? {} : { signal: this.options.signal }
|
|
8450
8474
|
});
|
|
8475
|
+
const requestedExpiresAt = requestedSessionExpiry(envelope.expiry);
|
|
8476
|
+
let delegationResponse = await mint(requestedExpiresAt === void 0 ? mintBody : { ...mintBody, requestedExpiresAt });
|
|
8477
|
+
if (requestedExpiresAt !== void 0 && delegationResponse.status === 422) delegationResponse = await mint(mintBody);
|
|
8451
8478
|
if (!delegationResponse.ok) throw new Error(`v3 policy delegation rejected (${delegationResponse.status})`);
|
|
8452
8479
|
const delegation = object3(await delegationResponse.json(), "v3 policy delegation");
|
|
8453
8480
|
if (delegation.admitted !== true || typeof delegation.sessionCid !== "string" || typeof delegation.authorization !== "string") throw new Error("v3 policy delegation response is not admitted");
|