@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/policy/index.cjs
CHANGED
|
@@ -108,6 +108,7 @@ __export(policy_exports, {
|
|
|
108
108
|
requestPolicyChallengeV3: () => requestPolicyChallengeV3,
|
|
109
109
|
revokePolicyRootV3: () => revokePolicyRootV3,
|
|
110
110
|
serializeJcsJson: () => serialize,
|
|
111
|
+
signCompactPolicyDescendant: () => signCompactPolicyDescendant,
|
|
111
112
|
signCompactUcanAuthorization: () => signCompactUcanAuthorization,
|
|
112
113
|
signCompactUcanRootAuthorization: () => signCompactUcanRootAuthorization,
|
|
113
114
|
signPolicyCredentialPresentationV4: () => signPolicyCredentialPresentationV4,
|
|
@@ -3939,8 +3940,9 @@ async function signCompactUcanAuthorization(input) {
|
|
|
3939
3940
|
throw new Error("compact invocation lifetime must be between one and 60 seconds");
|
|
3940
3941
|
return signCompactUcan(input);
|
|
3941
3942
|
}
|
|
3943
|
+
var MAX_POLICY_ROOT_SECONDS = 31 * 24 * 60 * 60;
|
|
3942
3944
|
async function signCompactUcanRootAuthorization(input) {
|
|
3943
|
-
if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore >
|
|
3945
|
+
if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > MAX_POLICY_ROOT_SECONDS)
|
|
3944
3946
|
throw new Error("compact policy root lifetime must be between one second and 31 days");
|
|
3945
3947
|
return signCompactUcan({ ...input, proofs: [] });
|
|
3946
3948
|
}
|
|
@@ -3975,7 +3977,7 @@ function createCompactPolicyInvocation(input) {
|
|
|
3975
3977
|
const signature = import_ed255192.ed25519.sign(signingInput, input.privateKey);
|
|
3976
3978
|
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
3977
3979
|
}
|
|
3978
|
-
function
|
|
3980
|
+
function compactPolicyDescendantClaims(input) {
|
|
3979
3981
|
const parent = parseCompactUcanAuthorization(input.parentAuthorization, input.parentCid);
|
|
3980
3982
|
if (parent.payload.aud !== input.issuerDid) throw new Error("policy descendant issuer is not the parent audience");
|
|
3981
3983
|
const parentFact = parent.payload.fct[0];
|
|
@@ -3983,29 +3985,53 @@ function createCompactPolicyDescendant(input) {
|
|
|
3983
3985
|
if (!Number.isInteger(depth) || depth <= 0) throw new Error("policy descendant depth is exhausted");
|
|
3984
3986
|
if (!compactAttenuationContains(parent.payload.att, input.attenuation))
|
|
3985
3987
|
throw new Error("policy descendant exceeds the parent attenuation");
|
|
3988
|
+
const now = Math.max(input.now ?? parent.payload.nbf + 1, parent.payload.nbf + 1);
|
|
3989
|
+
const exp = Math.min(input.expiresAt ?? parent.payload.exp - 1, parent.payload.exp - 1);
|
|
3990
|
+
if (exp <= now) throw new Error("policy parent has no strictly narrower validity window");
|
|
3991
|
+
return {
|
|
3992
|
+
parentCid: parent.cid,
|
|
3993
|
+
fact: { ...parentFact, remainingRedelegationDepth: depth - 1 },
|
|
3994
|
+
notBefore: now,
|
|
3995
|
+
expiresAt: exp,
|
|
3996
|
+
nonce: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16)))
|
|
3997
|
+
};
|
|
3998
|
+
}
|
|
3999
|
+
function createCompactPolicyDescendant(input) {
|
|
4000
|
+
const claims = compactPolicyDescendantClaims(input);
|
|
3986
4001
|
const principal = input.issuerDid.split("#", 1)[0];
|
|
3987
4002
|
const didMaterial = base58btc.decode(principal.slice("did:key:".length));
|
|
3988
4003
|
const publicKey = import_ed255192.ed25519.getPublicKey(input.privateKey);
|
|
3989
4004
|
if (didMaterial.length !== 34 || !equalBytes(publicKey, didMaterial.slice(2))) throw new Error("policy descendant signer does not bind issuer DID");
|
|
3990
|
-
const now = Math.max(input.now ?? Math.floor(Date.now() / 1e3), parent.payload.nbf + 1);
|
|
3991
|
-
const exp = Math.min(input.expiresAt ?? now + 60, now + 60, parent.payload.exp - 1);
|
|
3992
|
-
if (exp <= now) throw new Error("policy parent has no strictly narrower validity window");
|
|
3993
4005
|
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
|
|
3994
4006
|
const payload = {
|
|
3995
4007
|
att: input.attenuation,
|
|
3996
4008
|
aud: input.audienceDid,
|
|
3997
|
-
exp,
|
|
3998
|
-
fct: [
|
|
4009
|
+
exp: claims.expiresAt,
|
|
4010
|
+
fct: [claims.fact],
|
|
3999
4011
|
iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
4000
|
-
nbf:
|
|
4001
|
-
nnc:
|
|
4002
|
-
prf: [
|
|
4012
|
+
nbf: claims.notBefore,
|
|
4013
|
+
nnc: claims.nonce,
|
|
4014
|
+
prf: [claims.parentCid]
|
|
4003
4015
|
};
|
|
4004
4016
|
const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
4005
4017
|
const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
4006
4018
|
const signature = import_ed255192.ed25519.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`), input.privateKey);
|
|
4007
4019
|
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
4008
4020
|
}
|
|
4021
|
+
async function signCompactPolicyDescendant(input) {
|
|
4022
|
+
const claims = compactPolicyDescendantClaims(input);
|
|
4023
|
+
return signCompactUcan({
|
|
4024
|
+
issuerDid: input.issuerDid,
|
|
4025
|
+
audienceDid: input.audienceDid,
|
|
4026
|
+
attenuation: input.attenuation,
|
|
4027
|
+
facts: [claims.fact],
|
|
4028
|
+
proofs: [claims.parentCid],
|
|
4029
|
+
notBefore: claims.notBefore,
|
|
4030
|
+
expiresAt: claims.expiresAt,
|
|
4031
|
+
nonce: claims.nonce,
|
|
4032
|
+
sign: input.sign
|
|
4033
|
+
});
|
|
4034
|
+
}
|
|
4009
4035
|
function compactAttenuationContains(parent, child) {
|
|
4010
4036
|
const selector = (value) => {
|
|
4011
4037
|
if (value.length !== 1 || !isRecordValue(value[0])) return void 0;
|
|
@@ -4075,7 +4101,7 @@ function parsePolicySessionUcan(authorization, expectedProofs) {
|
|
|
4075
4101
|
throw new Error("policy session UCAN fact is incomplete");
|
|
4076
4102
|
if (hasV4AuditFactShape && (!LOWER_SHA256_HEX.test(fact.credentialIdAuditDigestHex) || !LOWER_SHA256_HEX.test(fact.presentationJtiAuditDigestHex)))
|
|
4077
4103
|
throw new Error("policy session UCAN v4 audit facts are invalid");
|
|
4078
|
-
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 >
|
|
4104
|
+
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)
|
|
4079
4105
|
throw new Error("policy session UCAN fact is invalid");
|
|
4080
4106
|
return {
|
|
4081
4107
|
authorization,
|
|
@@ -4570,24 +4596,21 @@ async function admitPolicyCredentialV3(input) {
|
|
|
4570
4596
|
policy,
|
|
4571
4597
|
challenge
|
|
4572
4598
|
});
|
|
4573
|
-
const response = await
|
|
4599
|
+
const response = await postPolicyDelegation(
|
|
4600
|
+
fetchFn,
|
|
4574
4601
|
new URL(`${policyRuntimeBasePath2(input.policyRuntimePath)}/delegations`, nodeOrigin),
|
|
4575
4602
|
{
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
credentialSpaceId,
|
|
4588
|
-
presentation
|
|
4589
|
-
})
|
|
4590
|
-
}
|
|
4603
|
+
policyCid: input.policyCid,
|
|
4604
|
+
challengeId: challenge.challengeId,
|
|
4605
|
+
nonce: challenge.nonce,
|
|
4606
|
+
requirement: validateCredentialRequirement(input.requirement),
|
|
4607
|
+
credential: envelopeFromVerified(input.credential),
|
|
4608
|
+
accountAuthorizationCid,
|
|
4609
|
+
credentialSpaceId,
|
|
4610
|
+
presentation
|
|
4611
|
+
},
|
|
4612
|
+
requestedSessionExpiry(input.requestedExpiresAt, policy),
|
|
4613
|
+
input.signal
|
|
4591
4614
|
);
|
|
4592
4615
|
if (!response.ok) throw new Error(`policy delegation rejected (${response.status})`);
|
|
4593
4616
|
const value = record(await response.json(), "policy delegation");
|
|
@@ -4628,20 +4651,20 @@ async function admitPolicyCredentialV4(input) {
|
|
|
4628
4651
|
policy,
|
|
4629
4652
|
challenge
|
|
4630
4653
|
});
|
|
4631
|
-
const response = await
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
headers: { accept: "application/json", "content-type": "application/json" },
|
|
4636
|
-
body: JSON.stringify({
|
|
4654
|
+
const response = await postPolicyDelegation(
|
|
4655
|
+
fetchFn,
|
|
4656
|
+
new URL(`${policyRuntimeBasePath2(input.policyRuntimePath)}/delegations`, nodeOrigin),
|
|
4657
|
+
{
|
|
4637
4658
|
policyCid: input.policyCid,
|
|
4638
4659
|
challengeId: challenge.challengeId,
|
|
4639
4660
|
nonce: challenge.nonce,
|
|
4640
4661
|
requirement: validateCredentialRequirement(input.requirement),
|
|
4641
4662
|
credential: envelopeFromVerified(input.credential),
|
|
4642
4663
|
presentation
|
|
4643
|
-
}
|
|
4644
|
-
|
|
4664
|
+
},
|
|
4665
|
+
requestedSessionExpiry(input.requestedExpiresAt, policy),
|
|
4666
|
+
input.signal
|
|
4667
|
+
);
|
|
4645
4668
|
if (!response.ok) throw new Error(`policy delegation rejected (${response.status})`);
|
|
4646
4669
|
const value = record(await response.json(), "policy delegation");
|
|
4647
4670
|
if (value.admitted !== true || typeof value.sessionCid !== "string" || typeof value.authorization !== "string") throw new Error("policy delegation response is invalid");
|
|
@@ -4665,6 +4688,27 @@ async function admitPolicyCredentialV4(input) {
|
|
|
4665
4688
|
input.signal?.throwIfAborted();
|
|
4666
4689
|
return Object.freeze({ challenge, presentation, session, delegationImported: true });
|
|
4667
4690
|
}
|
|
4691
|
+
function requestedSessionExpiry(requested, policy) {
|
|
4692
|
+
const value = requested === void 0 ? policy.expiresAt : requested;
|
|
4693
|
+
if (value === null || value === void 0) return void 0;
|
|
4694
|
+
const seconds = Math.floor(Date.parse(value) / 1e3);
|
|
4695
|
+
if (!Number.isFinite(seconds) || seconds <= Math.floor(Date.now() / 1e3) + 60) return void 0;
|
|
4696
|
+
return new Date(seconds * 1e3).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
4697
|
+
}
|
|
4698
|
+
async function postPolicyDelegation(fetchFn, url, body, requestedExpiresAt, signal) {
|
|
4699
|
+
const send = (payload) => fetchFn(url, {
|
|
4700
|
+
method: "POST",
|
|
4701
|
+
redirect: "error",
|
|
4702
|
+
signal,
|
|
4703
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
4704
|
+
body: JSON.stringify(payload)
|
|
4705
|
+
});
|
|
4706
|
+
if (requestedExpiresAt === void 0) return send(body);
|
|
4707
|
+
const response = await send({ ...body, requestedExpiresAt });
|
|
4708
|
+
if (response.status !== 422) return response;
|
|
4709
|
+
await response.body?.cancel().catch(() => void 0);
|
|
4710
|
+
return send(body);
|
|
4711
|
+
}
|
|
4668
4712
|
function policyRuntimeBasePath2(value) {
|
|
4669
4713
|
const path = value ?? "/policy/v3";
|
|
4670
4714
|
if (!/^\/policy(?:\/[a-z0-9-]+)*$/.test(path)) {
|