@tinycloud/sdk-core 3.0.0-beta.6 → 3.0.0-beta.8
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-BVUC6kdw.d.cts → credential-admission-CFjUChF8.d.cts} +56 -1
- package/dist/{credential-admission-BgvwOTIV.d.ts → credential-admission-DIEPgQ0o.d.ts} +56 -1
- package/dist/delegations/index.cjs +32 -60
- 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 +32 -60
- package/dist/delegations/index.js.map +1 -1
- package/dist/index.cjs +192 -67
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +193 -67
- package/dist/index.js.map +1 -1
- package/dist/policy/index.cjs +159 -7
- 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 +159 -7
- package/dist/policy/index.js.map +1 -1
- package/dist/{recipient-types.schema-BdCeDExl.d.cts → recipient-types.schema-DjmM_yJu.d.cts} +37 -37
- package/dist/{recipient-types.schema-BdCeDExl.d.ts → recipient-types.schema-DjmM_yJu.d.ts} +37 -37
- package/package.json +4 -4
package/dist/policy/index.cjs
CHANGED
|
@@ -103,6 +103,7 @@ __export(policy_exports, {
|
|
|
103
103
|
policyV2DigestHex: () => policyV2DigestHex,
|
|
104
104
|
projectUnifiedPolicyCapabilities: () => projectUnifiedPolicyCapabilities,
|
|
105
105
|
projectUnifiedPolicyCapability: () => projectUnifiedPolicyCapability,
|
|
106
|
+
registerPolicyV3: () => registerPolicyV3,
|
|
106
107
|
renewPolicyRootStatusV3: () => renewPolicyRootStatusV3,
|
|
107
108
|
requestPolicyChallengeV3: () => requestPolicyChallengeV3,
|
|
108
109
|
revokePolicyRootV3: () => revokePolicyRootV3,
|
|
@@ -3341,7 +3342,8 @@ var MAX_LEGACY_ENVELOPE_EXPIRES_AT = "2026-12-29T00:00:00Z";
|
|
|
3341
3342
|
var LAST_V2_READ_AT = "2027-01-05T00:00:00Z";
|
|
3342
3343
|
async function requestPolicyChallengeV3(input) {
|
|
3343
3344
|
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3344
|
-
const
|
|
3345
|
+
const policyRuntimePath = policyRuntimeBasePath(input.policyRuntimePath);
|
|
3346
|
+
const response = await fetchFn(new URL(`${policyRuntimePath}/challenges`, input.nodeOrigin), {
|
|
3345
3347
|
method: "POST",
|
|
3346
3348
|
redirect: "error",
|
|
3347
3349
|
signal: input.signal,
|
|
@@ -3354,12 +3356,19 @@ async function requestPolicyChallengeV3(input) {
|
|
|
3354
3356
|
throw new Error("policy challenge binding is invalid");
|
|
3355
3357
|
return value;
|
|
3356
3358
|
}
|
|
3359
|
+
function policyRuntimeBasePath(value) {
|
|
3360
|
+
const path = value ?? "/policy/v3";
|
|
3361
|
+
if (!/^\/policy(?:\/[a-z0-9-]+)*$/.test(path)) {
|
|
3362
|
+
throw new Error("policy runtime path is invalid");
|
|
3363
|
+
}
|
|
3364
|
+
return path;
|
|
3365
|
+
}
|
|
3357
3366
|
async function mintPolicySessionV3(input) {
|
|
3358
3367
|
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3359
3368
|
const challenge = input.challenge ?? await requestPolicyChallengeV3(input);
|
|
3360
3369
|
if (challenge.policyCid !== input.policyCid || challenge.recipientDid !== input.recipientDid)
|
|
3361
3370
|
throw new Error("policy challenge binding is invalid");
|
|
3362
|
-
const response = await fetchFn(new URL("/
|
|
3371
|
+
const response = await fetchFn(new URL("/policy/v3/delegations", input.nodeOrigin), {
|
|
3363
3372
|
method: "POST",
|
|
3364
3373
|
redirect: "error",
|
|
3365
3374
|
signal: input.signal,
|
|
@@ -3421,7 +3430,7 @@ function verifyPolicyRootStatusCheckpointV3(input) {
|
|
|
3421
3430
|
}
|
|
3422
3431
|
async function getPolicyRootStatusV3(input) {
|
|
3423
3432
|
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3424
|
-
const response = await fetchFn(new URL(`/
|
|
3433
|
+
const response = await fetchFn(new URL(`/policy/v3/status/${encodeURIComponent(input.rootCid)}`, input.nodeOrigin), {
|
|
3425
3434
|
method: "GET",
|
|
3426
3435
|
redirect: "error",
|
|
3427
3436
|
headers: { accept: "application/json" }
|
|
@@ -3480,7 +3489,7 @@ async function renewPolicyRootStatusV3(input) {
|
|
|
3480
3489
|
};
|
|
3481
3490
|
const signature = await input.sign((0, import_sha256.sha256)(new TextEncoder().encode(ROOT_STATUS_RENEWAL_V1_DOMAIN + jcsCanonicalize(unsigned))));
|
|
3482
3491
|
if (signature.length !== 64) throw new Error("policy root renewal signature must be Ed25519");
|
|
3483
|
-
const response = await fetchFn(new URL("/
|
|
3492
|
+
const response = await fetchFn(new URL("/policy/v3/status", input.nodeOrigin), {
|
|
3484
3493
|
method: "POST",
|
|
3485
3494
|
redirect: "error",
|
|
3486
3495
|
headers: { accept: "application/json", "content-type": "application/json" },
|
|
@@ -3735,6 +3744,133 @@ function contentSourceDigestHex(input) {
|
|
|
3735
3744
|
)
|
|
3736
3745
|
);
|
|
3737
3746
|
}
|
|
3747
|
+
function exactObject(value, keys, label) {
|
|
3748
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
3749
|
+
throw new Error(`${label} is invalid`);
|
|
3750
|
+
}
|
|
3751
|
+
const record2 = value;
|
|
3752
|
+
if (Object.keys(record2).length !== keys.length || keys.some((key) => !Object.prototype.hasOwnProperty.call(record2, key))) {
|
|
3753
|
+
throw new Error(`${label} is invalid`);
|
|
3754
|
+
}
|
|
3755
|
+
return record2;
|
|
3756
|
+
}
|
|
3757
|
+
function didKeyEd25519PublicKey(value) {
|
|
3758
|
+
const principal = value.split("#", 1)[0];
|
|
3759
|
+
if (!principal.startsWith("did:key:")) {
|
|
3760
|
+
throw new Error("policy enforcer binding signer is invalid");
|
|
3761
|
+
}
|
|
3762
|
+
const material = base58btc.decode(principal.slice("did:key:".length));
|
|
3763
|
+
if (material.length !== 34 || material[0] !== 237 || material[1] !== 1) {
|
|
3764
|
+
throw new Error("policy enforcer binding signer is invalid");
|
|
3765
|
+
}
|
|
3766
|
+
return material.slice(2);
|
|
3767
|
+
}
|
|
3768
|
+
async function registerPolicyV3(input) {
|
|
3769
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3770
|
+
const rootExpiresAt = new Date(input.rootExpiresAt);
|
|
3771
|
+
const canonicalRootExpiresAt = new Date(
|
|
3772
|
+
Math.floor(rootExpiresAt.getTime() / 1e3) * 1e3
|
|
3773
|
+
).toISOString().replace(/\.000Z$/, "Z");
|
|
3774
|
+
if (!Number.isFinite(rootExpiresAt.getTime()) || canonicalRootExpiresAt !== input.rootExpiresAt || rootExpiresAt.getTime() <= Date.now()) {
|
|
3775
|
+
throw new Error("policy root expiry is invalid");
|
|
3776
|
+
}
|
|
3777
|
+
const bindingResponse = await fetchFn(
|
|
3778
|
+
new URL("/policy/v3/enforcer-bindings", input.nodeOrigin),
|
|
3779
|
+
{
|
|
3780
|
+
method: "POST",
|
|
3781
|
+
redirect: "error",
|
|
3782
|
+
signal: input.signal,
|
|
3783
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3784
|
+
body: JSON.stringify({
|
|
3785
|
+
rootExpiresAt: input.rootExpiresAt,
|
|
3786
|
+
enforcerDid: input.enforcerDid
|
|
3787
|
+
})
|
|
3788
|
+
}
|
|
3789
|
+
);
|
|
3790
|
+
if (!bindingResponse.ok) {
|
|
3791
|
+
throw new Error(`policy enforcer binding rejected (${bindingResponse.status})`);
|
|
3792
|
+
}
|
|
3793
|
+
const binding = exactObject(
|
|
3794
|
+
await bindingResponse.json(),
|
|
3795
|
+
[
|
|
3796
|
+
"schema",
|
|
3797
|
+
"enforcerDid",
|
|
3798
|
+
"nodeAudience",
|
|
3799
|
+
"attestationBindingDigestHex",
|
|
3800
|
+
"issuedAt",
|
|
3801
|
+
"expiresAt",
|
|
3802
|
+
"signature"
|
|
3803
|
+
],
|
|
3804
|
+
"policy enforcer binding"
|
|
3805
|
+
);
|
|
3806
|
+
const signature = exactObject(
|
|
3807
|
+
binding.signature,
|
|
3808
|
+
["suite", "signerDid", "value"],
|
|
3809
|
+
"policy enforcer binding signature"
|
|
3810
|
+
);
|
|
3811
|
+
const expectedBindingDigestHex = hex(
|
|
3812
|
+
(0, import_sha256.sha256)(
|
|
3813
|
+
new TextEncoder().encode(
|
|
3814
|
+
jcsCanonicalize({
|
|
3815
|
+
enforcerDid: input.enforcerDid,
|
|
3816
|
+
nodeAudience: input.expectedNodeAudience
|
|
3817
|
+
})
|
|
3818
|
+
)
|
|
3819
|
+
)
|
|
3820
|
+
);
|
|
3821
|
+
if (binding.schema !== ATTESTED_ENFORCER_BINDING_V2_SCHEMA || binding.enforcerDid !== input.enforcerDid || binding.nodeAudience !== input.expectedNodeAudience || binding.attestationBindingDigestHex !== expectedBindingDigestHex || binding.expiresAt !== input.rootExpiresAt || typeof binding.issuedAt !== "string" || Date.parse(binding.issuedAt) > Date.now() || signature.suite !== "Ed25519" || signature.signerDid !== input.expectedNodeAudience || typeof signature.value !== "string") {
|
|
3822
|
+
throw new Error("policy enforcer binding is invalid");
|
|
3823
|
+
}
|
|
3824
|
+
const { signature: _signature, ...unsignedBinding } = binding;
|
|
3825
|
+
const signedBinding = (0, import_sha256.sha256)(
|
|
3826
|
+
new TextEncoder().encode(
|
|
3827
|
+
`xyz.tinycloud.policy/AttestedEnforcerBinding/v2\0${jcsCanonicalize(unsignedBinding)}`
|
|
3828
|
+
)
|
|
3829
|
+
);
|
|
3830
|
+
if (!import_ed255192.ed25519.verify(
|
|
3831
|
+
decodeBase64Url(signature.value),
|
|
3832
|
+
signedBinding,
|
|
3833
|
+
didKeyEd25519PublicKey(input.expectedNodeAudience),
|
|
3834
|
+
{ zip215: false }
|
|
3835
|
+
)) {
|
|
3836
|
+
throw new Error("policy enforcer binding signature is invalid");
|
|
3837
|
+
}
|
|
3838
|
+
const response = await fetchFn(
|
|
3839
|
+
new URL("/policy/v3/policies", input.nodeOrigin),
|
|
3840
|
+
{
|
|
3841
|
+
method: "POST",
|
|
3842
|
+
redirect: "error",
|
|
3843
|
+
signal: input.signal,
|
|
3844
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3845
|
+
body: JSON.stringify({
|
|
3846
|
+
policyCid: input.policyCid,
|
|
3847
|
+
policy: input.policy,
|
|
3848
|
+
policyRoot: input.policyRoot.authorization.replace(/^Bearer\s+/i, ""),
|
|
3849
|
+
enforcementRoot: input.enforcementRoot.authorization.replace(/^Bearer\s+/i, ""),
|
|
3850
|
+
contentSourceDigestHex: input.contentSourceDigestHex,
|
|
3851
|
+
nativeProjectionHashHex: input.nativeProjectionHashHex,
|
|
3852
|
+
attestedEnforcerBinding: binding
|
|
3853
|
+
})
|
|
3854
|
+
}
|
|
3855
|
+
);
|
|
3856
|
+
if (!response.ok) {
|
|
3857
|
+
throw new Error(`policy registration rejected (${response.status})`);
|
|
3858
|
+
}
|
|
3859
|
+
const receipt = exactObject(
|
|
3860
|
+
await response.json(),
|
|
3861
|
+
["policyCid", "policyRootCid", "enforcementRootCid"],
|
|
3862
|
+
"policy registration response"
|
|
3863
|
+
);
|
|
3864
|
+
if (receipt.policyCid !== input.policyCid || receipt.policyRootCid !== input.policyRoot.cid || receipt.enforcementRootCid !== input.enforcementRoot.cid) {
|
|
3865
|
+
throw new Error("policy registration response binding is invalid");
|
|
3866
|
+
}
|
|
3867
|
+
return {
|
|
3868
|
+
policyCid: input.policyCid,
|
|
3869
|
+
policyRootCid: input.policyRoot.cid,
|
|
3870
|
+
enforcementRootCid: input.enforcementRoot.cid,
|
|
3871
|
+
attestedEnforcerBinding: binding
|
|
3872
|
+
};
|
|
3873
|
+
}
|
|
3738
3874
|
function policyDigestHex(policy) {
|
|
3739
3875
|
const canonicalPolicy = {
|
|
3740
3876
|
...policy,
|
|
@@ -4420,6 +4556,7 @@ async function admitPolicyCredentialV3(input) {
|
|
|
4420
4556
|
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
4421
4557
|
const challenge = await requestPolicyChallengeV3({
|
|
4422
4558
|
nodeOrigin,
|
|
4559
|
+
policyRuntimePath: input.policyRuntimePath,
|
|
4423
4560
|
policyCid: input.policyCid,
|
|
4424
4561
|
recipientDid: input.credential.holderDid,
|
|
4425
4562
|
requestedCapabilities: input.requestedCapabilities,
|
|
@@ -4432,7 +4569,7 @@ async function admitPolicyCredentialV3(input) {
|
|
|
4432
4569
|
challenge
|
|
4433
4570
|
});
|
|
4434
4571
|
const response = await fetchFn(
|
|
4435
|
-
new URL(
|
|
4572
|
+
new URL(`${policyRuntimeBasePath2(input.policyRuntimePath)}/delegations`, nodeOrigin),
|
|
4436
4573
|
{
|
|
4437
4574
|
method: "POST",
|
|
4438
4575
|
redirect: "error",
|
|
@@ -4477,6 +4614,7 @@ async function admitPolicyCredentialV4(input) {
|
|
|
4477
4614
|
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
4478
4615
|
const challenge = await requestPolicyChallengeV3({
|
|
4479
4616
|
nodeOrigin,
|
|
4617
|
+
policyRuntimePath: input.policyRuntimePath,
|
|
4480
4618
|
policyCid: input.policyCid,
|
|
4481
4619
|
recipientDid: input.credential.holderDid,
|
|
4482
4620
|
requestedCapabilities: input.requestedCapabilities,
|
|
@@ -4488,7 +4626,7 @@ async function admitPolicyCredentialV4(input) {
|
|
|
4488
4626
|
policy,
|
|
4489
4627
|
challenge
|
|
4490
4628
|
});
|
|
4491
|
-
const response = await fetchFn(new URL(
|
|
4629
|
+
const response = await fetchFn(new URL(`${policyRuntimeBasePath2(input.policyRuntimePath)}/delegations`, nodeOrigin), {
|
|
4492
4630
|
method: "POST",
|
|
4493
4631
|
redirect: "error",
|
|
4494
4632
|
signal: input.signal,
|
|
@@ -4515,7 +4653,21 @@ async function admitPolicyCredentialV4(input) {
|
|
|
4515
4653
|
enforcerDid: input.expectedEnforcerDid
|
|
4516
4654
|
});
|
|
4517
4655
|
if (session.cid !== value.sessionCid || session.aud !== input.credential.holderDid || session.fact.policyCid !== input.policyCid || session.fact.recipientDid !== input.credential.holderDid || session.fact.policyDelegationCid !== input.policyRootCid || session.fact.enforcementDelegationCid !== input.enforcementRootCid || jcsCanonicalize(session.att) !== jcsCanonicalize(expectedAttenuation)) throw new Error("policy delegation signed binding is invalid");
|
|
4656
|
+
const importResponse = await fetchFn(new URL("/delegate", nodeOrigin), {
|
|
4657
|
+
method: "POST",
|
|
4658
|
+
redirect: "error",
|
|
4659
|
+
signal: input.signal,
|
|
4660
|
+
headers: { Authorization: session.authorization }
|
|
4661
|
+
});
|
|
4662
|
+
if (!importResponse.ok) throw new Error(`delegation import rejected (${importResponse.status})`);
|
|
4518
4663
|
input.signal?.throwIfAborted();
|
|
4519
|
-
return Object.freeze({ challenge, presentation, session });
|
|
4664
|
+
return Object.freeze({ challenge, presentation, session, delegationImported: true });
|
|
4665
|
+
}
|
|
4666
|
+
function policyRuntimeBasePath2(value) {
|
|
4667
|
+
const path = value ?? "/policy/v3";
|
|
4668
|
+
if (!/^\/policy(?:\/[a-z0-9-]+)*$/.test(path)) {
|
|
4669
|
+
throw new Error("policy runtime path is invalid");
|
|
4670
|
+
}
|
|
4671
|
+
return path;
|
|
4520
4672
|
}
|
|
4521
4673
|
//# sourceMappingURL=index.cjs.map
|