@tinycloud/sdk-core 3.0.0-beta.18 → 3.0.0-beta.19
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/{credential-admission-CFjUChF8.d.cts → credential-admission-BxpkckU0.d.cts} +23 -3
- package/dist/{credential-admission-DIEPgQ0o.d.ts → credential-admission-CO9WMtGs.d.ts} +23 -3
- package/dist/delegations/index.cjs +21 -10
- package/dist/delegations/index.cjs.map +1 -1
- package/dist/delegations/index.js +21 -10
- package/dist/delegations/index.js.map +1 -1
- package/dist/index.cjs +79 -35
- 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 +79 -35
- package/dist/index.js.map +1 -1
- package/dist/policy/index.cjs +79 -35
- package/dist/policy/index.cjs.map +1 -1
- package/dist/policy/index.d.cts +2 -2
- package/dist/policy/index.d.ts +2 -2
- package/dist/policy/index.js +79 -35
- package/dist/policy/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -421,6 +421,7 @@ __export(index_exports, {
|
|
|
421
421
|
serviceError: () => import_sdk_services8.serviceError,
|
|
422
422
|
sha256Base64Url: () => sha256Base64Url,
|
|
423
423
|
shareCapabilityAllows: () => shareCapabilityAllows,
|
|
424
|
+
signCompactPolicyDescendant: () => signCompactPolicyDescendant,
|
|
424
425
|
signCompactUcanAuthorization: () => signCompactUcanAuthorization,
|
|
425
426
|
signCompactUcanRootAuthorization: () => signCompactUcanRootAuthorization,
|
|
426
427
|
signLocationRecord: () => signLocationRecord,
|
|
@@ -4495,8 +4496,9 @@ async function signCompactUcanAuthorization(input) {
|
|
|
4495
4496
|
throw new Error("compact invocation lifetime must be between one and 60 seconds");
|
|
4496
4497
|
return signCompactUcan(input);
|
|
4497
4498
|
}
|
|
4499
|
+
var MAX_POLICY_ROOT_SECONDS = 31 * 24 * 60 * 60;
|
|
4498
4500
|
async function signCompactUcanRootAuthorization(input) {
|
|
4499
|
-
if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore >
|
|
4501
|
+
if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > MAX_POLICY_ROOT_SECONDS)
|
|
4500
4502
|
throw new Error("compact policy root lifetime must be between one second and 31 days");
|
|
4501
4503
|
return signCompactUcan({ ...input, proofs: [] });
|
|
4502
4504
|
}
|
|
@@ -4531,7 +4533,7 @@ function createCompactPolicyInvocation(input) {
|
|
|
4531
4533
|
const signature = import_ed255193.ed25519.sign(signingInput, input.privateKey);
|
|
4532
4534
|
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url2(signature)}`);
|
|
4533
4535
|
}
|
|
4534
|
-
function
|
|
4536
|
+
function compactPolicyDescendantClaims(input) {
|
|
4535
4537
|
const parent = parseCompactUcanAuthorization(input.parentAuthorization, input.parentCid);
|
|
4536
4538
|
if (parent.payload.aud !== input.issuerDid) throw new Error("policy descendant issuer is not the parent audience");
|
|
4537
4539
|
const parentFact = parent.payload.fct[0];
|
|
@@ -4539,29 +4541,53 @@ function createCompactPolicyDescendant(input) {
|
|
|
4539
4541
|
if (!Number.isInteger(depth) || depth <= 0) throw new Error("policy descendant depth is exhausted");
|
|
4540
4542
|
if (!compactAttenuationContains(parent.payload.att, input.attenuation))
|
|
4541
4543
|
throw new Error("policy descendant exceeds the parent attenuation");
|
|
4544
|
+
const now = Math.max(input.now ?? parent.payload.nbf + 1, parent.payload.nbf + 1);
|
|
4545
|
+
const exp = Math.min(input.expiresAt ?? parent.payload.exp - 1, parent.payload.exp - 1);
|
|
4546
|
+
if (exp <= now) throw new Error("policy parent has no strictly narrower validity window");
|
|
4547
|
+
return {
|
|
4548
|
+
parentCid: parent.cid,
|
|
4549
|
+
fact: { ...parentFact, remainingRedelegationDepth: depth - 1 },
|
|
4550
|
+
notBefore: now,
|
|
4551
|
+
expiresAt: exp,
|
|
4552
|
+
nonce: input.nonce ?? encodeBase64Url2(crypto.getRandomValues(new Uint8Array(16)))
|
|
4553
|
+
};
|
|
4554
|
+
}
|
|
4555
|
+
function createCompactPolicyDescendant(input) {
|
|
4556
|
+
const claims = compactPolicyDescendantClaims(input);
|
|
4542
4557
|
const principal = input.issuerDid.split("#", 1)[0];
|
|
4543
4558
|
const didMaterial = base58btc.decode(principal.slice("did:key:".length));
|
|
4544
4559
|
const publicKey = import_ed255193.ed25519.getPublicKey(input.privateKey);
|
|
4545
4560
|
if (didMaterial.length !== 34 || !equalBytes(publicKey, didMaterial.slice(2))) throw new Error("policy descendant signer does not bind issuer DID");
|
|
4546
|
-
const now = Math.max(input.now ?? Math.floor(Date.now() / 1e3), parent.payload.nbf + 1);
|
|
4547
|
-
const exp = Math.min(input.expiresAt ?? now + 60, now + 60, parent.payload.exp - 1);
|
|
4548
|
-
if (exp <= now) throw new Error("policy parent has no strictly narrower validity window");
|
|
4549
4561
|
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url2(publicKey) }, typ: "JWT", ucv: "0.10.0" };
|
|
4550
4562
|
const payload = {
|
|
4551
4563
|
att: input.attenuation,
|
|
4552
4564
|
aud: input.audienceDid,
|
|
4553
|
-
exp,
|
|
4554
|
-
fct: [
|
|
4565
|
+
exp: claims.expiresAt,
|
|
4566
|
+
fct: [claims.fact],
|
|
4555
4567
|
iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
4556
|
-
nbf:
|
|
4557
|
-
nnc:
|
|
4558
|
-
prf: [
|
|
4568
|
+
nbf: claims.notBefore,
|
|
4569
|
+
nnc: claims.nonce,
|
|
4570
|
+
prf: [claims.parentCid]
|
|
4559
4571
|
};
|
|
4560
4572
|
const protectedSegment = encodeBase64Url2(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
4561
4573
|
const payloadSegment = encodeBase64Url2(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
4562
4574
|
const signature = import_ed255193.ed25519.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`), input.privateKey);
|
|
4563
4575
|
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url2(signature)}`);
|
|
4564
4576
|
}
|
|
4577
|
+
async function signCompactPolicyDescendant(input) {
|
|
4578
|
+
const claims = compactPolicyDescendantClaims(input);
|
|
4579
|
+
return signCompactUcan({
|
|
4580
|
+
issuerDid: input.issuerDid,
|
|
4581
|
+
audienceDid: input.audienceDid,
|
|
4582
|
+
attenuation: input.attenuation,
|
|
4583
|
+
facts: [claims.fact],
|
|
4584
|
+
proofs: [claims.parentCid],
|
|
4585
|
+
notBefore: claims.notBefore,
|
|
4586
|
+
expiresAt: claims.expiresAt,
|
|
4587
|
+
nonce: claims.nonce,
|
|
4588
|
+
sign: input.sign
|
|
4589
|
+
});
|
|
4590
|
+
}
|
|
4565
4591
|
function compactAttenuationContains(parent, child) {
|
|
4566
4592
|
const selector = (value) => {
|
|
4567
4593
|
if (value.length !== 1 || !isRecordValue(value[0])) return void 0;
|
|
@@ -4631,7 +4657,7 @@ function parsePolicySessionUcan(authorization, expectedProofs) {
|
|
|
4631
4657
|
throw new Error("policy session UCAN fact is incomplete");
|
|
4632
4658
|
if (hasV4AuditFactShape && (!LOWER_SHA256_HEX.test(fact.credentialIdAuditDigestHex) || !LOWER_SHA256_HEX.test(fact.presentationJtiAuditDigestHex)))
|
|
4633
4659
|
throw new Error("policy session UCAN v4 audit facts are invalid");
|
|
4634
|
-
if (fact.profile !== POLICY_SESSION_UCAN_V1_PROFILE || typeof fact.remainingRedelegationDepth !== "number" || !Number.isInteger(fact.remainingRedelegationDepth) || fact.remainingRedelegationDepth < 0 || fact.remainingRedelegationDepth > 8 || parsed.payload.exp - parsed.payload.nbf >
|
|
4660
|
+
if (fact.profile !== POLICY_SESSION_UCAN_V1_PROFILE || typeof fact.remainingRedelegationDepth !== "number" || !Number.isInteger(fact.remainingRedelegationDepth) || fact.remainingRedelegationDepth < 0 || fact.remainingRedelegationDepth > 8 || parsed.payload.exp - parsed.payload.nbf > MAX_POLICY_ROOT_SECONDS || parsed.payload.iss.split("#", 1)[0] !== fact.nodeAudience || parsed.payload.aud !== fact.recipientDid)
|
|
4635
4661
|
throw new Error("policy session UCAN fact is invalid");
|
|
4636
4662
|
return {
|
|
4637
4663
|
authorization,
|
|
@@ -5055,24 +5081,21 @@ async function admitPolicyCredentialV3(input) {
|
|
|
5055
5081
|
policy,
|
|
5056
5082
|
challenge
|
|
5057
5083
|
});
|
|
5058
|
-
const response = await
|
|
5084
|
+
const response = await postPolicyDelegation(
|
|
5085
|
+
fetchFn,
|
|
5059
5086
|
new URL(`${policyRuntimeBasePath2(input.policyRuntimePath)}/delegations`, nodeOrigin),
|
|
5060
5087
|
{
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
credentialSpaceId,
|
|
5073
|
-
presentation
|
|
5074
|
-
})
|
|
5075
|
-
}
|
|
5088
|
+
policyCid: input.policyCid,
|
|
5089
|
+
challengeId: challenge.challengeId,
|
|
5090
|
+
nonce: challenge.nonce,
|
|
5091
|
+
requirement: validateCredentialRequirement(input.requirement),
|
|
5092
|
+
credential: envelopeFromVerified(input.credential),
|
|
5093
|
+
accountAuthorizationCid,
|
|
5094
|
+
credentialSpaceId,
|
|
5095
|
+
presentation
|
|
5096
|
+
},
|
|
5097
|
+
requestedSessionExpiry(input.requestedExpiresAt, policy),
|
|
5098
|
+
input.signal
|
|
5076
5099
|
);
|
|
5077
5100
|
if (!response.ok) throw new Error(`policy delegation rejected (${response.status})`);
|
|
5078
5101
|
const value = record(await response.json(), "policy delegation");
|
|
@@ -5113,20 +5136,20 @@ async function admitPolicyCredentialV4(input) {
|
|
|
5113
5136
|
policy,
|
|
5114
5137
|
challenge
|
|
5115
5138
|
});
|
|
5116
|
-
const response = await
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
headers: { accept: "application/json", "content-type": "application/json" },
|
|
5121
|
-
body: JSON.stringify({
|
|
5139
|
+
const response = await postPolicyDelegation(
|
|
5140
|
+
fetchFn,
|
|
5141
|
+
new URL(`${policyRuntimeBasePath2(input.policyRuntimePath)}/delegations`, nodeOrigin),
|
|
5142
|
+
{
|
|
5122
5143
|
policyCid: input.policyCid,
|
|
5123
5144
|
challengeId: challenge.challengeId,
|
|
5124
5145
|
nonce: challenge.nonce,
|
|
5125
5146
|
requirement: validateCredentialRequirement(input.requirement),
|
|
5126
5147
|
credential: envelopeFromVerified(input.credential),
|
|
5127
5148
|
presentation
|
|
5128
|
-
}
|
|
5129
|
-
|
|
5149
|
+
},
|
|
5150
|
+
requestedSessionExpiry(input.requestedExpiresAt, policy),
|
|
5151
|
+
input.signal
|
|
5152
|
+
);
|
|
5130
5153
|
if (!response.ok) throw new Error(`policy delegation rejected (${response.status})`);
|
|
5131
5154
|
const value = record(await response.json(), "policy delegation");
|
|
5132
5155
|
if (value.admitted !== true || typeof value.sessionCid !== "string" || typeof value.authorization !== "string") throw new Error("policy delegation response is invalid");
|
|
@@ -5150,6 +5173,27 @@ async function admitPolicyCredentialV4(input) {
|
|
|
5150
5173
|
input.signal?.throwIfAborted();
|
|
5151
5174
|
return Object.freeze({ challenge, presentation, session, delegationImported: true });
|
|
5152
5175
|
}
|
|
5176
|
+
function requestedSessionExpiry(requested, policy) {
|
|
5177
|
+
const value = requested === void 0 ? policy.expiresAt : requested;
|
|
5178
|
+
if (value === null || value === void 0) return void 0;
|
|
5179
|
+
const seconds = Math.floor(Date.parse(value) / 1e3);
|
|
5180
|
+
if (!Number.isFinite(seconds) || seconds <= Math.floor(Date.now() / 1e3) + 60) return void 0;
|
|
5181
|
+
return new Date(seconds * 1e3).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
5182
|
+
}
|
|
5183
|
+
async function postPolicyDelegation(fetchFn, url, body, requestedExpiresAt, signal) {
|
|
5184
|
+
const send = (payload) => fetchFn(url, {
|
|
5185
|
+
method: "POST",
|
|
5186
|
+
redirect: "error",
|
|
5187
|
+
signal,
|
|
5188
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
5189
|
+
body: JSON.stringify(payload)
|
|
5190
|
+
});
|
|
5191
|
+
if (requestedExpiresAt === void 0) return send(body);
|
|
5192
|
+
const response = await send({ ...body, requestedExpiresAt });
|
|
5193
|
+
if (response.status !== 422) return response;
|
|
5194
|
+
await response.body?.cancel().catch(() => void 0);
|
|
5195
|
+
return send(body);
|
|
5196
|
+
}
|
|
5153
5197
|
function policyRuntimeBasePath2(value) {
|
|
5154
5198
|
const path = value ?? "/policy/v3";
|
|
5155
5199
|
if (!/^\/policy(?:\/[a-z0-9-]+)*$/.test(path)) {
|