@tinycloud/sdk-core 3.0.0-beta.1 → 3.0.0-beta.11
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-C_cO1QqB.d.cts → credential-admission-CFjUChF8.d.cts} +122 -2
- package/dist/{credential-admission-cvHe-HUC.d.ts → credential-admission-DIEPgQ0o.d.ts} +122 -2
- package/dist/delegations/index.cjs +80 -133
- package/dist/delegations/index.cjs.map +1 -1
- package/dist/delegations/index.d.cts +3 -3
- package/dist/delegations/index.d.ts +3 -3
- package/dist/delegations/index.js +81 -138
- package/dist/delegations/index.js.map +1 -1
- package/dist/index.cjs +758 -306
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +67 -8
- package/dist/index.d.ts +67 -8
- package/dist/index.js +760 -311
- package/dist/index.js.map +1 -1
- package/dist/policy/index.cjs +324 -8
- 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 +324 -8
- package/dist/policy/index.js.map +1 -1
- package/dist/{recipient-types.schema-G8NEKRoo.d.cts → recipient-types.schema-Cz5zJzED.d.cts} +50 -77
- package/dist/{recipient-types.schema-G8NEKRoo.d.ts → recipient-types.schema-Cz5zJzED.d.ts} +50 -77
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -311,6 +311,7 @@ var CREDENTIAL_ERROR_CODES = [
|
|
|
311
311
|
"ISSUER_UNREADY",
|
|
312
312
|
"OFFLINE",
|
|
313
313
|
"POPUP_BLOCKED",
|
|
314
|
+
"PROOF_REJECTED",
|
|
314
315
|
"REQUEST_EXPIRED",
|
|
315
316
|
"REQUEST_SUBSTITUTED",
|
|
316
317
|
"SIGNATURE_REJECTED",
|
|
@@ -324,6 +325,7 @@ var RECOVERABLE = /* @__PURE__ */ new Set([
|
|
|
324
325
|
"ISSUER_UNREADY",
|
|
325
326
|
"OFFLINE",
|
|
326
327
|
"POPUP_BLOCKED",
|
|
328
|
+
"PROOF_REJECTED",
|
|
327
329
|
"REQUEST_EXPIRED",
|
|
328
330
|
"SIGNATURE_REJECTED",
|
|
329
331
|
"UNSUPPORTED_PROFILE",
|
|
@@ -565,6 +567,17 @@ function isDigest(value) {
|
|
|
565
567
|
|
|
566
568
|
// src/credentials/requirement.ts
|
|
567
569
|
var ID2 = /^[a-z0-9][a-z0-9._-]{0,127}(?:\/v1)?$/;
|
|
570
|
+
var EMAIL_CREDENTIAL_MAX_AGE_SECONDS = 3600;
|
|
571
|
+
function createEmailCredentialRequirement(input) {
|
|
572
|
+
return validateCredentialRequirement({
|
|
573
|
+
type: "TinyCloudCredentialRequirement",
|
|
574
|
+
version: 1,
|
|
575
|
+
profile: input.profile,
|
|
576
|
+
credentialType: input.credentialType,
|
|
577
|
+
claims: { email: input.email },
|
|
578
|
+
maxAgeSeconds: EMAIL_CREDENTIAL_MAX_AGE_SECONDS
|
|
579
|
+
});
|
|
580
|
+
}
|
|
568
581
|
function validateCredentialRequirement(value) {
|
|
569
582
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new CredentialError("UNSUPPORTED_PROFILE", "Credential requirement is invalid");
|
|
570
583
|
const raw = value;
|
|
@@ -1779,16 +1792,16 @@ function policyCapabilityContains(authority, request) {
|
|
|
1779
1792
|
return caveatsContain(auth.caveats, req.caveats);
|
|
1780
1793
|
}
|
|
1781
1794
|
function normalizePolicyCapabilityWithOptions(input, options2) {
|
|
1782
|
-
const
|
|
1783
|
-
assertExactKeys(
|
|
1784
|
-
const service = requiredString(
|
|
1795
|
+
const object4 = expectObject(input, "$");
|
|
1796
|
+
assertExactKeys(object4, ["service", "space", "path", "actions", "caveats"], "$");
|
|
1797
|
+
const service = requiredString(object4, "service", "$", "policy-capability-malformed-service");
|
|
1785
1798
|
if (!CEILING_SERVICES.has(service)) {
|
|
1786
1799
|
throw new PolicyCapabilityError(
|
|
1787
1800
|
"policy-capability-malformed-service",
|
|
1788
1801
|
"$.service is outside the frozen permissionsCeiling vocabulary"
|
|
1789
1802
|
);
|
|
1790
1803
|
}
|
|
1791
|
-
const space = requiredString(
|
|
1804
|
+
const space = requiredString(object4, "space", "$", "policy-capability-malformed-space");
|
|
1792
1805
|
validateConcreteSpace(space);
|
|
1793
1806
|
const canonicalSpace = space.normalize("NFC");
|
|
1794
1807
|
if (options2.requireCanonical && canonicalSpace !== space) {
|
|
@@ -1797,7 +1810,7 @@ function normalizePolicyCapabilityWithOptions(input, options2) {
|
|
|
1797
1810
|
"$.space must already be canonical NFC"
|
|
1798
1811
|
);
|
|
1799
1812
|
}
|
|
1800
|
-
const rawPath = requiredString(
|
|
1813
|
+
const rawPath = requiredString(object4, "path", "$", "policy-capability-malformed-path");
|
|
1801
1814
|
validateRawPath(rawPath, options2);
|
|
1802
1815
|
const path = normalizePath(rawPath);
|
|
1803
1816
|
if (options2.requireCanonical && path !== rawPath) {
|
|
@@ -1808,7 +1821,7 @@ function normalizePolicyCapabilityWithOptions(input, options2) {
|
|
|
1808
1821
|
}
|
|
1809
1822
|
validateRawPath(path, options2);
|
|
1810
1823
|
const actions = normalizeActions(
|
|
1811
|
-
requiredArray(
|
|
1824
|
+
requiredArray(object4, "actions", "$", "policy-capability-malformed-action"),
|
|
1812
1825
|
service,
|
|
1813
1826
|
options2
|
|
1814
1827
|
);
|
|
@@ -1817,9 +1830,9 @@ function normalizePolicyCapabilityWithOptions(input, options2) {
|
|
|
1817
1830
|
output.space = canonicalSpace;
|
|
1818
1831
|
output.path = path;
|
|
1819
1832
|
output.actions = actions;
|
|
1820
|
-
if (hasOwn(
|
|
1833
|
+
if (hasOwn(object4, "caveats")) {
|
|
1821
1834
|
output.caveats = validateCaveats(
|
|
1822
|
-
requiredValue(
|
|
1835
|
+
requiredValue(object4, "caveats", "$", "policy-capability-malformed-caveats"),
|
|
1823
1836
|
output.service
|
|
1824
1837
|
);
|
|
1825
1838
|
}
|
|
@@ -1842,9 +1855,9 @@ function expectObject(input, path) {
|
|
|
1842
1855
|
);
|
|
1843
1856
|
}
|
|
1844
1857
|
}
|
|
1845
|
-
function assertExactKeys(
|
|
1858
|
+
function assertExactKeys(object4, allowed, path) {
|
|
1846
1859
|
const allowedSet = new Set(allowed);
|
|
1847
|
-
for (const key of Object.keys(
|
|
1860
|
+
for (const key of Object.keys(object4)) {
|
|
1848
1861
|
if (!allowedSet.has(key)) {
|
|
1849
1862
|
throw new PolicyCapabilityError(
|
|
1850
1863
|
key === "id" || key === "scope" ? "policy-capability-malformed" : "policy-capability-unknown-key",
|
|
@@ -1853,21 +1866,21 @@ function assertExactKeys(object3, allowed, path) {
|
|
|
1853
1866
|
}
|
|
1854
1867
|
}
|
|
1855
1868
|
}
|
|
1856
|
-
function requiredValue(
|
|
1857
|
-
if (!hasOwn(
|
|
1869
|
+
function requiredValue(object4, key, path, code3) {
|
|
1870
|
+
if (!hasOwn(object4, key)) {
|
|
1858
1871
|
throw new PolicyCapabilityError(code3, `${path}.${key} is required`);
|
|
1859
1872
|
}
|
|
1860
|
-
return
|
|
1873
|
+
return object4[key];
|
|
1861
1874
|
}
|
|
1862
|
-
function requiredString(
|
|
1863
|
-
const value = requiredValue(
|
|
1875
|
+
function requiredString(object4, key, path, code3) {
|
|
1876
|
+
const value = requiredValue(object4, key, path, code3);
|
|
1864
1877
|
if (typeof value !== "string" || value.length === 0) {
|
|
1865
1878
|
throw new PolicyCapabilityError(code3, `${path}.${key} must be a non-empty string`);
|
|
1866
1879
|
}
|
|
1867
1880
|
return value;
|
|
1868
1881
|
}
|
|
1869
|
-
function requiredArray(
|
|
1870
|
-
const value = requiredValue(
|
|
1882
|
+
function requiredArray(object4, key, path, code3) {
|
|
1883
|
+
const value = requiredValue(object4, key, path, code3);
|
|
1871
1884
|
if (!Array.isArray(value)) {
|
|
1872
1885
|
throw new PolicyCapabilityError(code3, `${path}.${key} must be an array`);
|
|
1873
1886
|
}
|
|
@@ -2012,11 +2025,11 @@ function validateSqlStatement(input, path) {
|
|
|
2012
2025
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
2013
2026
|
throw new PolicyCapabilityError("policy-capability-malformed-caveats", `${path} must be an object`);
|
|
2014
2027
|
}
|
|
2015
|
-
const
|
|
2016
|
-
assertCaveatKeys(
|
|
2017
|
-
caveatString(
|
|
2018
|
-
caveatString(
|
|
2019
|
-
const fixedParams = requiredCaveat(
|
|
2028
|
+
const object4 = input;
|
|
2029
|
+
assertCaveatKeys(object4, ["name", "sql", "fixedParams"], path);
|
|
2030
|
+
caveatString(object4, "name", path);
|
|
2031
|
+
caveatString(object4, "sql", path);
|
|
2032
|
+
const fixedParams = requiredCaveat(object4, "fixedParams", path);
|
|
2020
2033
|
if (!Array.isArray(fixedParams)) {
|
|
2021
2034
|
throw new PolicyCapabilityError(
|
|
2022
2035
|
"policy-capability-malformed-caveats",
|
|
@@ -2031,20 +2044,20 @@ function validateFixedParam(input, path) {
|
|
|
2031
2044
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
2032
2045
|
throw new PolicyCapabilityError("policy-capability-malformed-caveats", `${path} must be an object`);
|
|
2033
2046
|
}
|
|
2034
|
-
const
|
|
2035
|
-
assertCaveatKeys(
|
|
2036
|
-
const index = requiredCaveat(
|
|
2047
|
+
const object4 = input;
|
|
2048
|
+
assertCaveatKeys(object4, ["index", "value"], path);
|
|
2049
|
+
const index = requiredCaveat(object4, "index", path);
|
|
2037
2050
|
if (typeof index !== "number" || !Number.isSafeInteger(index) || index < 0) {
|
|
2038
2051
|
throw new PolicyCapabilityError(
|
|
2039
2052
|
"policy-capability-malformed-caveats",
|
|
2040
2053
|
`${path}.index must be a non-negative integer`
|
|
2041
2054
|
);
|
|
2042
2055
|
}
|
|
2043
|
-
requiredCaveat(
|
|
2056
|
+
requiredCaveat(object4, "value", path);
|
|
2044
2057
|
}
|
|
2045
|
-
function assertCaveatKeys(
|
|
2058
|
+
function assertCaveatKeys(object4, allowed, path) {
|
|
2046
2059
|
const allowedSet = new Set(allowed);
|
|
2047
|
-
for (const key of Object.keys(
|
|
2060
|
+
for (const key of Object.keys(object4)) {
|
|
2048
2061
|
if (!allowedSet.has(key)) {
|
|
2049
2062
|
throw new PolicyCapabilityError(
|
|
2050
2063
|
"policy-capability-malformed-caveats",
|
|
@@ -2053,17 +2066,17 @@ function assertCaveatKeys(object3, allowed, path) {
|
|
|
2053
2066
|
}
|
|
2054
2067
|
}
|
|
2055
2068
|
}
|
|
2056
|
-
function requiredCaveat(
|
|
2057
|
-
if (!hasOwn(
|
|
2069
|
+
function requiredCaveat(object4, key, path) {
|
|
2070
|
+
if (!hasOwn(object4, key)) {
|
|
2058
2071
|
throw new PolicyCapabilityError(
|
|
2059
2072
|
"policy-capability-malformed-caveats",
|
|
2060
2073
|
`${path}.${key} is required`
|
|
2061
2074
|
);
|
|
2062
2075
|
}
|
|
2063
|
-
return
|
|
2076
|
+
return object4[key];
|
|
2064
2077
|
}
|
|
2065
|
-
function caveatString(
|
|
2066
|
-
const value = requiredCaveat(
|
|
2078
|
+
function caveatString(object4, key, path) {
|
|
2079
|
+
const value = requiredCaveat(object4, key, path);
|
|
2067
2080
|
if (typeof value !== "string" || value.length === 0) {
|
|
2068
2081
|
throw new PolicyCapabilityError(
|
|
2069
2082
|
"policy-capability-malformed-caveats",
|
|
@@ -2094,8 +2107,8 @@ function caveatsContain(authority, request) {
|
|
|
2094
2107
|
(statement) => authorityStatements.some((candidate) => jcsCanonicalize(candidate) === jcsCanonicalize(statement))
|
|
2095
2108
|
);
|
|
2096
2109
|
}
|
|
2097
|
-
function hasOwn(
|
|
2098
|
-
return objectHasOwn2(
|
|
2110
|
+
function hasOwn(object4, key) {
|
|
2111
|
+
return objectHasOwn2(object4, key);
|
|
2099
2112
|
}
|
|
2100
2113
|
|
|
2101
2114
|
// src/policy/signed-object.ts
|
|
@@ -2423,17 +2436,17 @@ async function createAndSignSignedObject(input, signer) {
|
|
|
2423
2436
|
}
|
|
2424
2437
|
function createAndSignPolicy(input, signer) {
|
|
2425
2438
|
return createAndSignSignedObject(input, signer).then(
|
|
2426
|
-
(
|
|
2439
|
+
(object4) => validatePolicySignedShape(object4)
|
|
2427
2440
|
);
|
|
2428
2441
|
}
|
|
2429
2442
|
function createAndSignPolicyStatus(input, signer) {
|
|
2430
2443
|
return createAndSignSignedObject(input, signer).then(
|
|
2431
|
-
(
|
|
2444
|
+
(object4) => validatePolicyStatusSignedShape(object4)
|
|
2432
2445
|
);
|
|
2433
2446
|
}
|
|
2434
2447
|
function createAndSignPolicyEngineRecord(input, signer) {
|
|
2435
2448
|
return createAndSignSignedObject(input, signer).then(
|
|
2436
|
-
(
|
|
2449
|
+
(object4) => validatePolicyEngineRecordSignedShape(object4)
|
|
2437
2450
|
);
|
|
2438
2451
|
}
|
|
2439
2452
|
async function verifySignedObject(input) {
|
|
@@ -2537,9 +2550,9 @@ function validateUnsignedForDescriptor(input, descriptor) {
|
|
|
2537
2550
|
}
|
|
2538
2551
|
}
|
|
2539
2552
|
function validatePolicyShape(input, signed) {
|
|
2540
|
-
const
|
|
2553
|
+
const object4 = expectJsonObject(normalizeJson(input), "$");
|
|
2541
2554
|
assertExactKeys2(
|
|
2542
|
-
|
|
2555
|
+
object4,
|
|
2543
2556
|
signed ? [
|
|
2544
2557
|
"schema",
|
|
2545
2558
|
"policyId",
|
|
@@ -2567,30 +2580,30 @@ function validatePolicyShape(input, signed) {
|
|
|
2567
2580
|
],
|
|
2568
2581
|
"$"
|
|
2569
2582
|
);
|
|
2570
|
-
expectConst(requiredString2(
|
|
2583
|
+
expectConst(requiredString2(object4, "schema", "$"), POLICY_SCHEMA, "$.schema");
|
|
2571
2584
|
if (signed) {
|
|
2572
|
-
requiredString2(
|
|
2573
|
-
validateSignature(requiredValue2(
|
|
2585
|
+
requiredString2(object4, "policyId", "$");
|
|
2586
|
+
validateSignature(requiredValue2(object4, "signature", "$"));
|
|
2574
2587
|
}
|
|
2575
|
-
requiredString2(
|
|
2576
|
-
requiredString2(
|
|
2577
|
-
requiredDateString(
|
|
2578
|
-
optionalDateString(
|
|
2579
|
-
validatePolicyResource(requiredValue2(
|
|
2580
|
-
validateExpression(requiredValue2(
|
|
2581
|
-
validateGrant(requiredValue2(
|
|
2582
|
-
if (hasOwn2(
|
|
2583
|
-
validateDisclosure(requiredValue2(
|
|
2588
|
+
requiredString2(object4, "ownerDid", "$");
|
|
2589
|
+
requiredString2(object4, "signingKeyDid", "$");
|
|
2590
|
+
requiredDateString(object4, "createdAt", "$");
|
|
2591
|
+
optionalDateString(object4, "expiresAt", "$");
|
|
2592
|
+
validatePolicyResource(requiredValue2(object4, "resource", "$"), "$.resource");
|
|
2593
|
+
validateExpression(requiredValue2(object4, "when", "$"), "$.when");
|
|
2594
|
+
validateGrant(requiredValue2(object4, "grant", "$"), "$.grant");
|
|
2595
|
+
if (hasOwn2(object4, "disclosure")) {
|
|
2596
|
+
validateDisclosure(requiredValue2(object4, "disclosure", "$"), "$.disclosure");
|
|
2584
2597
|
}
|
|
2585
|
-
if (hasOwn2(
|
|
2586
|
-
validateAudit(requiredValue2(
|
|
2598
|
+
if (hasOwn2(object4, "audit")) {
|
|
2599
|
+
validateAudit(requiredValue2(object4, "audit", "$"), "$.audit");
|
|
2587
2600
|
}
|
|
2588
|
-
return
|
|
2601
|
+
return object4;
|
|
2589
2602
|
}
|
|
2590
2603
|
function validatePolicyStatusShape(input, signed) {
|
|
2591
|
-
const
|
|
2604
|
+
const object4 = expectJsonObject(normalizeJson(input), "$");
|
|
2592
2605
|
assertExactKeys2(
|
|
2593
|
-
|
|
2606
|
+
object4,
|
|
2594
2607
|
signed ? [
|
|
2595
2608
|
"schema",
|
|
2596
2609
|
"statusId",
|
|
@@ -2614,28 +2627,28 @@ function validatePolicyStatusShape(input, signed) {
|
|
|
2614
2627
|
],
|
|
2615
2628
|
"$"
|
|
2616
2629
|
);
|
|
2617
|
-
expectConst(requiredString2(
|
|
2630
|
+
expectConst(requiredString2(object4, "schema", "$"), POLICY_STATUS_SCHEMA, "$.schema");
|
|
2618
2631
|
if (signed) {
|
|
2619
|
-
requiredString2(
|
|
2620
|
-
validateSignature(requiredValue2(
|
|
2632
|
+
requiredString2(object4, "statusId", "$");
|
|
2633
|
+
validateSignature(requiredValue2(object4, "signature", "$"));
|
|
2621
2634
|
}
|
|
2622
|
-
requiredString2(
|
|
2623
|
-
requiredString2(
|
|
2624
|
-
requiredInteger(
|
|
2625
|
-
expectOneOf(requiredString2(
|
|
2635
|
+
requiredString2(object4, "policyId", "$");
|
|
2636
|
+
requiredString2(object4, "ownerDid", "$");
|
|
2637
|
+
requiredInteger(object4, "sequence", "$", 0);
|
|
2638
|
+
expectOneOf(requiredString2(object4, "disposition", "$"), [
|
|
2626
2639
|
"active",
|
|
2627
2640
|
"suspended",
|
|
2628
2641
|
"revoked"
|
|
2629
2642
|
], "$.disposition");
|
|
2630
|
-
requiredDateString(
|
|
2631
|
-
optionalString(
|
|
2632
|
-
requiredString2(
|
|
2633
|
-
return
|
|
2643
|
+
requiredDateString(object4, "effectiveAt", "$");
|
|
2644
|
+
optionalString(object4, "reasonCode", "$");
|
|
2645
|
+
requiredString2(object4, "signingKeyDid", "$");
|
|
2646
|
+
return object4;
|
|
2634
2647
|
}
|
|
2635
2648
|
function validatePolicyEngineRecordShape(input, signed) {
|
|
2636
|
-
const
|
|
2649
|
+
const object4 = expectJsonObject(normalizeJson(input), "$");
|
|
2637
2650
|
assertExactKeys2(
|
|
2638
|
-
|
|
2651
|
+
object4,
|
|
2639
2652
|
signed ? [
|
|
2640
2653
|
"schema",
|
|
2641
2654
|
"engineRecordId",
|
|
@@ -2660,44 +2673,44 @@ function validatePolicyEngineRecordShape(input, signed) {
|
|
|
2660
2673
|
"$"
|
|
2661
2674
|
);
|
|
2662
2675
|
expectConst(
|
|
2663
|
-
requiredString2(
|
|
2676
|
+
requiredString2(object4, "schema", "$"),
|
|
2664
2677
|
POLICY_ENGINE_RECORD_SCHEMA,
|
|
2665
2678
|
"$.schema"
|
|
2666
2679
|
);
|
|
2667
2680
|
if (signed) {
|
|
2668
|
-
requiredString2(
|
|
2669
|
-
validateSignature(requiredValue2(
|
|
2681
|
+
requiredString2(object4, "engineRecordId", "$");
|
|
2682
|
+
validateSignature(requiredValue2(object4, "signature", "$"));
|
|
2670
2683
|
}
|
|
2671
|
-
requiredString2(
|
|
2672
|
-
requiredString2(
|
|
2673
|
-
requiredString2(
|
|
2684
|
+
requiredString2(object4, "ownerDid", "$");
|
|
2685
|
+
requiredString2(object4, "endpoint", "$");
|
|
2686
|
+
requiredString2(object4, "audience", "$");
|
|
2674
2687
|
requiredStringArray(
|
|
2675
|
-
|
|
2688
|
+
object4,
|
|
2676
2689
|
"supportedPolicyVersions",
|
|
2677
2690
|
"$",
|
|
2678
2691
|
(value, path) => expectConst(value, "v0", path)
|
|
2679
2692
|
);
|
|
2680
|
-
requiredStringArray(
|
|
2681
|
-
requiredString2(
|
|
2682
|
-
requiredDateString(
|
|
2683
|
-
return
|
|
2693
|
+
requiredStringArray(object4, "supportedEvidenceVerifiers", "$");
|
|
2694
|
+
requiredString2(object4, "grantIssuerDid", "$");
|
|
2695
|
+
requiredDateString(object4, "expiresAt", "$");
|
|
2696
|
+
return object4;
|
|
2684
2697
|
}
|
|
2685
2698
|
function validateSignature(input) {
|
|
2686
|
-
const
|
|
2687
|
-
assertExactKeys2(
|
|
2688
|
-
const suite = requiredString2(
|
|
2699
|
+
const object4 = expectJsonObject(input, "$.signature");
|
|
2700
|
+
assertExactKeys2(object4, ["suite", "signerDid", "value"], "$.signature");
|
|
2701
|
+
const suite = requiredString2(object4, "suite", "$.signature");
|
|
2689
2702
|
assertSupportedSignatureSuite(suite);
|
|
2690
|
-
const signerDid = requiredString2(
|
|
2691
|
-
const value = requiredString2(
|
|
2703
|
+
const signerDid = requiredString2(object4, "signerDid", "$.signature");
|
|
2704
|
+
const value = requiredString2(object4, "value", "$.signature");
|
|
2692
2705
|
decodeSignatureValue(value, suite);
|
|
2693
2706
|
return { suite, signerDid, value };
|
|
2694
2707
|
}
|
|
2695
2708
|
function validatePolicyResource(input, path) {
|
|
2696
|
-
const
|
|
2697
|
-
assertExactKeys2(
|
|
2698
|
-
requiredString2(
|
|
2699
|
-
requiredString2(
|
|
2700
|
-
const ceiling = requiredArray2(
|
|
2709
|
+
const object4 = expectJsonObject(input, path);
|
|
2710
|
+
assertExactKeys2(object4, ["resourceType", "resourceId", "permissionsCeiling"], path);
|
|
2711
|
+
requiredString2(object4, "resourceType", path);
|
|
2712
|
+
requiredString2(object4, "resourceId", path);
|
|
2713
|
+
const ceiling = requiredArray2(object4, "permissionsCeiling", path, 1);
|
|
2701
2714
|
for (let index = 0; index < ceiling.length; index++) {
|
|
2702
2715
|
validatePolicyCapability(ceiling[index], `${path}.permissionsCeiling[${index}]`);
|
|
2703
2716
|
}
|
|
@@ -2713,10 +2726,10 @@ function validatePolicyPermissionsCeilingForSigning(input) {
|
|
|
2713
2726
|
}
|
|
2714
2727
|
}
|
|
2715
2728
|
function validatePolicyCapability(input, path) {
|
|
2716
|
-
const
|
|
2729
|
+
const object4 = expectJsonObject(input, path);
|
|
2717
2730
|
try {
|
|
2718
|
-
const canonical = canonicalizePolicyCapability(
|
|
2719
|
-
if (jcsCanonicalize(
|
|
2731
|
+
const canonical = canonicalizePolicyCapability(object4);
|
|
2732
|
+
if (jcsCanonicalize(object4) !== jcsCanonicalize(canonical)) {
|
|
2720
2733
|
throw new SignedObjectSchemaError(`${path} must be canonical PolicyCapability JSON`);
|
|
2721
2734
|
}
|
|
2722
2735
|
} catch (error) {
|
|
@@ -2729,10 +2742,10 @@ function validatePolicyCapability(input, path) {
|
|
|
2729
2742
|
}
|
|
2730
2743
|
}
|
|
2731
2744
|
function validatePolicyCapabilityForSigning(input, path) {
|
|
2732
|
-
const
|
|
2745
|
+
const object4 = expectJsonObject(input, path);
|
|
2733
2746
|
try {
|
|
2734
|
-
const canonical = normalizePolicyCapability(
|
|
2735
|
-
if (jcsCanonicalize(
|
|
2747
|
+
const canonical = normalizePolicyCapability(object4);
|
|
2748
|
+
if (jcsCanonicalize(object4) !== jcsCanonicalize(canonical)) {
|
|
2736
2749
|
throw new SignedObjectSchemaError(`${path} must be strict canonical PolicyCapability JSON`);
|
|
2737
2750
|
}
|
|
2738
2751
|
} catch (error) {
|
|
@@ -2745,43 +2758,43 @@ function validatePolicyCapabilityForSigning(input, path) {
|
|
|
2745
2758
|
}
|
|
2746
2759
|
}
|
|
2747
2760
|
function validateExpression(input, path) {
|
|
2748
|
-
const
|
|
2749
|
-
const keys = Object.keys(
|
|
2761
|
+
const object4 = expectJsonObject(input, path);
|
|
2762
|
+
const keys = Object.keys(object4);
|
|
2750
2763
|
if (keys.length !== 1) {
|
|
2751
2764
|
throw new SignedObjectSchemaError(`${path} must have exactly one expression key`);
|
|
2752
2765
|
}
|
|
2753
2766
|
const key = keys[0];
|
|
2754
2767
|
if (key === "allOf" || key === "anyOf") {
|
|
2755
|
-
const values = requiredArray2(
|
|
2768
|
+
const values = requiredArray2(object4, key, path, 1);
|
|
2756
2769
|
for (let index = 0; index < values.length; index++) {
|
|
2757
2770
|
validateExpression(values[index], `${path}.${key}[${index}]`);
|
|
2758
2771
|
}
|
|
2759
2772
|
return;
|
|
2760
2773
|
}
|
|
2761
2774
|
if (key === "subject") {
|
|
2762
|
-
const subject = expectJsonObject(requiredValue2(
|
|
2775
|
+
const subject = expectJsonObject(requiredValue2(object4, "subject", path), `${path}.subject`);
|
|
2763
2776
|
assertExactKeys2(subject, ["did"], `${path}.subject`);
|
|
2764
2777
|
requiredString2(subject, "did", `${path}.subject`);
|
|
2765
2778
|
return;
|
|
2766
2779
|
}
|
|
2767
2780
|
if (key === "evidence") {
|
|
2768
|
-
validateEvidenceRequirement(requiredValue2(
|
|
2781
|
+
validateEvidenceRequirement(requiredValue2(object4, "evidence", path), `${path}.evidence`);
|
|
2769
2782
|
return;
|
|
2770
2783
|
}
|
|
2771
2784
|
throw new SignedObjectSchemaError(`${path} has unknown expression key ${key}`);
|
|
2772
2785
|
}
|
|
2773
2786
|
function validateEvidenceRequirement(input, path) {
|
|
2774
|
-
const
|
|
2787
|
+
const object4 = expectJsonObject(input, path);
|
|
2775
2788
|
assertExactKeys2(
|
|
2776
|
-
|
|
2789
|
+
object4,
|
|
2777
2790
|
["requirementId", "verifier", "requirements", "authority", "freshness"],
|
|
2778
2791
|
path
|
|
2779
2792
|
);
|
|
2780
|
-
requiredString2(
|
|
2781
|
-
requiredString2(
|
|
2782
|
-
requiredValue2(
|
|
2783
|
-
if (hasOwn2(
|
|
2784
|
-
const authority = expectJsonObject(requiredValue2(
|
|
2793
|
+
requiredString2(object4, "requirementId", path);
|
|
2794
|
+
requiredString2(object4, "verifier", path);
|
|
2795
|
+
requiredValue2(object4, "requirements", path);
|
|
2796
|
+
if (hasOwn2(object4, "authority")) {
|
|
2797
|
+
const authority = expectJsonObject(requiredValue2(object4, "authority", path), `${path}.authority`);
|
|
2785
2798
|
assertExactKeys2(
|
|
2786
2799
|
authority,
|
|
2787
2800
|
["profile", "acceptedIssuers", "allowOwnerAuthorizedIssuer"],
|
|
@@ -2793,35 +2806,35 @@ function validateEvidenceRequirement(input, path) {
|
|
|
2793
2806
|
}
|
|
2794
2807
|
optionalBoolean(authority, "allowOwnerAuthorizedIssuer", `${path}.authority`);
|
|
2795
2808
|
}
|
|
2796
|
-
if (hasOwn2(
|
|
2797
|
-
const freshness = expectJsonObject(requiredValue2(
|
|
2809
|
+
if (hasOwn2(object4, "freshness")) {
|
|
2810
|
+
const freshness = expectJsonObject(requiredValue2(object4, "freshness", path), `${path}.freshness`);
|
|
2798
2811
|
assertExactKeys2(freshness, ["maxStatusAgeSeconds"], `${path}.freshness`);
|
|
2799
2812
|
requiredInteger(freshness, "maxStatusAgeSeconds", `${path}.freshness`, 0);
|
|
2800
2813
|
}
|
|
2801
2814
|
}
|
|
2802
2815
|
function validateGrant(input, path) {
|
|
2803
|
-
const
|
|
2804
|
-
assertExactKeys2(
|
|
2805
|
-
expectConst(requiredString2(
|
|
2806
|
-
requiredInteger(
|
|
2807
|
-
expectOneOf(requiredString2(
|
|
2816
|
+
const object4 = expectJsonObject(input, path);
|
|
2817
|
+
assertExactKeys2(object4, ["output", "maxTtlSeconds", "delegationMode", "revocation"], path);
|
|
2818
|
+
expectConst(requiredString2(object4, "output", path), "portable-delegation", `${path}.output`);
|
|
2819
|
+
requiredInteger(object4, "maxTtlSeconds", path, 1);
|
|
2820
|
+
expectOneOf(requiredString2(object4, "delegationMode", path), [
|
|
2808
2821
|
"terminal",
|
|
2809
2822
|
"attenuable"
|
|
2810
2823
|
], `${path}.delegationMode`);
|
|
2811
|
-
expectOneOf(requiredString2(
|
|
2824
|
+
expectOneOf(requiredString2(object4, "revocation", path), [
|
|
2812
2825
|
"refresh_only",
|
|
2813
2826
|
"active_cutoff"
|
|
2814
2827
|
], `${path}.revocation`);
|
|
2815
2828
|
}
|
|
2816
2829
|
function validateDisclosure(input, path) {
|
|
2817
|
-
const
|
|
2818
|
-
assertExactKeys2(
|
|
2819
|
-
expectOneOf(requiredString2(
|
|
2830
|
+
const object4 = expectJsonObject(input, path);
|
|
2831
|
+
assertExactKeys2(object4, ["denial"], path);
|
|
2832
|
+
expectOneOf(requiredString2(object4, "denial", path), ["none", "code", "debug"], `${path}.denial`);
|
|
2820
2833
|
}
|
|
2821
2834
|
function validateAudit(input, path) {
|
|
2822
|
-
const
|
|
2823
|
-
assertExactKeys2(
|
|
2824
|
-
expectOneOf(requiredString2(
|
|
2835
|
+
const object4 = expectJsonObject(input, path);
|
|
2836
|
+
assertExactKeys2(object4, ["issuance"], path);
|
|
2837
|
+
expectOneOf(requiredString2(object4, "issuance", path), ["off", "security", "full"], `${path}.issuance`);
|
|
2825
2838
|
}
|
|
2826
2839
|
function materialForUnsigned(unsigned, descriptor) {
|
|
2827
2840
|
const jcs = jcsCanonicalize(unsigned);
|
|
@@ -2970,9 +2983,9 @@ function encodeSignatureValue(value, suite) {
|
|
|
2970
2983
|
decodeSignatureValue(encoded, suite);
|
|
2971
2984
|
return encoded;
|
|
2972
2985
|
}
|
|
2973
|
-
function stripOwnIdAndSignature(
|
|
2986
|
+
function stripOwnIdAndSignature(object4, descriptor) {
|
|
2974
2987
|
const output = /* @__PURE__ */ Object.create(null);
|
|
2975
|
-
for (const [key, value] of Object.entries(
|
|
2988
|
+
for (const [key, value] of Object.entries(object4)) {
|
|
2976
2989
|
if (key === descriptor.idField || key === "signature") {
|
|
2977
2990
|
continue;
|
|
2978
2991
|
}
|
|
@@ -2981,8 +2994,8 @@ function stripOwnIdAndSignature(object3, descriptor) {
|
|
|
2981
2994
|
return output;
|
|
2982
2995
|
}
|
|
2983
2996
|
function descriptorForUnsigned(input) {
|
|
2984
|
-
const
|
|
2985
|
-
return descriptorForSchema(requiredString2(
|
|
2997
|
+
const object4 = expectJsonObject(normalizeJson(input), "$");
|
|
2998
|
+
return descriptorForSchema(requiredString2(object4, "schema", "$"));
|
|
2986
2999
|
}
|
|
2987
3000
|
function descriptorForSchema(schema) {
|
|
2988
3001
|
if (schema === POLICY_SCHEMA) return DESCRIPTORS.Policy;
|
|
@@ -2996,28 +3009,28 @@ function expectJsonObject(input, path) {
|
|
|
2996
3009
|
}
|
|
2997
3010
|
return input;
|
|
2998
3011
|
}
|
|
2999
|
-
function assertExactKeys2(
|
|
3012
|
+
function assertExactKeys2(object4, allowed, path) {
|
|
3000
3013
|
const allowedSet = new Set(allowed);
|
|
3001
|
-
for (const key of Object.keys(
|
|
3014
|
+
for (const key of Object.keys(object4)) {
|
|
3002
3015
|
if (!allowedSet.has(key)) {
|
|
3003
3016
|
throw new SignedObjectSchemaError(`${path} has unknown field ${key}`);
|
|
3004
3017
|
}
|
|
3005
3018
|
}
|
|
3006
3019
|
}
|
|
3007
|
-
function requiredValue2(
|
|
3008
|
-
if (!hasOwn2(
|
|
3020
|
+
function requiredValue2(object4, key, path) {
|
|
3021
|
+
if (!hasOwn2(object4, key)) {
|
|
3009
3022
|
throw new SignedObjectSchemaError(`${path}.${key} is required`);
|
|
3010
3023
|
}
|
|
3011
|
-
return
|
|
3024
|
+
return object4[key];
|
|
3012
3025
|
}
|
|
3013
|
-
function requiredString2(
|
|
3014
|
-
return requireStringType(requiredValue2(
|
|
3026
|
+
function requiredString2(object4, key, path) {
|
|
3027
|
+
return requireStringType(requiredValue2(object4, key, path), `${path}.${key}`);
|
|
3015
3028
|
}
|
|
3016
|
-
function optionalString(
|
|
3017
|
-
if (!hasOwn2(
|
|
3029
|
+
function optionalString(object4, key, path) {
|
|
3030
|
+
if (!hasOwn2(object4, key)) {
|
|
3018
3031
|
return;
|
|
3019
3032
|
}
|
|
3020
|
-
requireStringType(requiredValue2(
|
|
3033
|
+
requireStringType(requiredValue2(object4, key, path), `${path}.${key}`);
|
|
3021
3034
|
}
|
|
3022
3035
|
function requireStringType(value, path) {
|
|
3023
3036
|
if (typeof value !== "string" || value.length === 0) {
|
|
@@ -3025,16 +3038,16 @@ function requireStringType(value, path) {
|
|
|
3025
3038
|
}
|
|
3026
3039
|
return value;
|
|
3027
3040
|
}
|
|
3028
|
-
function optionalBoolean(
|
|
3029
|
-
if (!hasOwn2(
|
|
3041
|
+
function optionalBoolean(object4, key, path) {
|
|
3042
|
+
if (!hasOwn2(object4, key)) {
|
|
3030
3043
|
return;
|
|
3031
3044
|
}
|
|
3032
|
-
if (typeof requiredValue2(
|
|
3045
|
+
if (typeof requiredValue2(object4, key, path) !== "boolean") {
|
|
3033
3046
|
throw new SignedObjectSchemaError(`${path}.${key} must be a boolean`);
|
|
3034
3047
|
}
|
|
3035
3048
|
}
|
|
3036
|
-
function requiredInteger(
|
|
3037
|
-
const value = requiredValue2(
|
|
3049
|
+
function requiredInteger(object4, key, path, minimum) {
|
|
3050
|
+
const value = requiredValue2(object4, key, path);
|
|
3038
3051
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < minimum) {
|
|
3039
3052
|
throw new SignedObjectSchemaError(
|
|
3040
3053
|
`${path}.${key} must be an integer >= ${minimum}`
|
|
@@ -3042,8 +3055,8 @@ function requiredInteger(object3, key, path, minimum) {
|
|
|
3042
3055
|
}
|
|
3043
3056
|
return value;
|
|
3044
3057
|
}
|
|
3045
|
-
function requiredArray2(
|
|
3046
|
-
const value = requiredValue2(
|
|
3058
|
+
function requiredArray2(object4, key, path, minimum) {
|
|
3059
|
+
const value = requiredValue2(object4, key, path);
|
|
3047
3060
|
if (!Array.isArray(value) || value.length < minimum) {
|
|
3048
3061
|
throw new SignedObjectSchemaError(
|
|
3049
3062
|
`${path}.${key} must be an array with at least ${minimum} item(s)`
|
|
@@ -3051,22 +3064,22 @@ function requiredArray2(object3, key, path, minimum) {
|
|
|
3051
3064
|
}
|
|
3052
3065
|
return value;
|
|
3053
3066
|
}
|
|
3054
|
-
function requiredStringArray(
|
|
3055
|
-
const values = requiredArray2(
|
|
3067
|
+
function requiredStringArray(object4, key, path, check) {
|
|
3068
|
+
const values = requiredArray2(object4, key, path, 0);
|
|
3056
3069
|
for (let index = 0; index < values.length; index++) {
|
|
3057
3070
|
const itemPath = `${path}.${key}[${index}]`;
|
|
3058
3071
|
const value = requireStringType(values[index], itemPath);
|
|
3059
3072
|
check?.(value, itemPath);
|
|
3060
3073
|
}
|
|
3061
3074
|
}
|
|
3062
|
-
function requiredDateString(
|
|
3063
|
-
assertRfc3339(requiredString2(
|
|
3075
|
+
function requiredDateString(object4, key, path) {
|
|
3076
|
+
assertRfc3339(requiredString2(object4, key, path), `${path}.${key}`);
|
|
3064
3077
|
}
|
|
3065
|
-
function optionalDateString(
|
|
3066
|
-
if (!hasOwn2(
|
|
3078
|
+
function optionalDateString(object4, key, path) {
|
|
3079
|
+
if (!hasOwn2(object4, key)) {
|
|
3067
3080
|
return;
|
|
3068
3081
|
}
|
|
3069
|
-
assertRfc3339(requiredString2(
|
|
3082
|
+
assertRfc3339(requiredString2(object4, key, path), `${path}.${key}`);
|
|
3070
3083
|
}
|
|
3071
3084
|
function assertRfc3339(value, path) {
|
|
3072
3085
|
const match = value.match(
|
|
@@ -3098,8 +3111,8 @@ function expectOneOf(actual, allowed, path) {
|
|
|
3098
3111
|
}
|
|
3099
3112
|
throw new SignedObjectSchemaError(`${path} has unsupported value ${actual}`);
|
|
3100
3113
|
}
|
|
3101
|
-
function hasOwn2(
|
|
3102
|
-
return objectHasOwn3(
|
|
3114
|
+
function hasOwn2(object4, key) {
|
|
3115
|
+
return objectHasOwn3(object4, key);
|
|
3103
3116
|
}
|
|
3104
3117
|
function assertSupportedSignatureSuite(suite) {
|
|
3105
3118
|
if (suite !== ED25519_JCS_SIGNATURE_SUITE && suite !== EIP191_JCS_SIGNATURE_SUITE) {
|
|
@@ -3326,9 +3339,9 @@ function expectObject2(input, path, code3) {
|
|
|
3326
3339
|
);
|
|
3327
3340
|
}
|
|
3328
3341
|
}
|
|
3329
|
-
function assertExactKeys3(
|
|
3342
|
+
function assertExactKeys3(object4, allowed, path) {
|
|
3330
3343
|
const allowedSet = new Set(allowed);
|
|
3331
|
-
for (const key of Object.keys(
|
|
3344
|
+
for (const key of Object.keys(object4)) {
|
|
3332
3345
|
if (!allowedSet.has(key)) {
|
|
3333
3346
|
throw new PolicyAuthoringError(
|
|
3334
3347
|
"policy-authoring-unknown-key",
|
|
@@ -3337,17 +3350,17 @@ function assertExactKeys3(object3, allowed, path) {
|
|
|
3337
3350
|
}
|
|
3338
3351
|
}
|
|
3339
3352
|
}
|
|
3340
|
-
function requiredValue3(
|
|
3341
|
-
if (!hasOwn3(
|
|
3353
|
+
function requiredValue3(object4, key, path) {
|
|
3354
|
+
if (!hasOwn3(object4, key)) {
|
|
3342
3355
|
throw new PolicyAuthoringError(
|
|
3343
3356
|
"policy-authoring-malformed",
|
|
3344
3357
|
`${path}.${key} is required`
|
|
3345
3358
|
);
|
|
3346
3359
|
}
|
|
3347
|
-
return
|
|
3360
|
+
return object4[key];
|
|
3348
3361
|
}
|
|
3349
|
-
function requiredString3(
|
|
3350
|
-
const value = requiredValue3(
|
|
3362
|
+
function requiredString3(object4, key, path) {
|
|
3363
|
+
const value = requiredValue3(object4, key, path);
|
|
3351
3364
|
if (typeof value !== "string" || value.length === 0) {
|
|
3352
3365
|
throw new PolicyAuthoringError(
|
|
3353
3366
|
"policy-authoring-malformed",
|
|
@@ -3356,11 +3369,11 @@ function requiredString3(object3, key, path) {
|
|
|
3356
3369
|
}
|
|
3357
3370
|
return value;
|
|
3358
3371
|
}
|
|
3359
|
-
function fieldString(
|
|
3360
|
-
if (!hasOwn3(
|
|
3372
|
+
function fieldString(object4, key, path, code3) {
|
|
3373
|
+
if (!hasOwn3(object4, key)) {
|
|
3361
3374
|
throw new PolicyAuthoringError(code3, `${path}.${key} is required`);
|
|
3362
3375
|
}
|
|
3363
|
-
const value =
|
|
3376
|
+
const value = object4[key];
|
|
3364
3377
|
if (typeof value !== "string" || value.length === 0) {
|
|
3365
3378
|
throw new PolicyAuthoringError(
|
|
3366
3379
|
code3,
|
|
@@ -3398,8 +3411,8 @@ function parseStrictRfc3339(value, path) {
|
|
|
3398
3411
|
var objectHasOwn4 = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
|
|
3399
3412
|
Object.prototype.hasOwnProperty
|
|
3400
3413
|
);
|
|
3401
|
-
function hasOwn3(
|
|
3402
|
-
return objectHasOwn4(
|
|
3414
|
+
function hasOwn3(object4, key) {
|
|
3415
|
+
return objectHasOwn4(object4, key);
|
|
3403
3416
|
}
|
|
3404
3417
|
|
|
3405
3418
|
// src/policy/unified.ts
|
|
@@ -3426,9 +3439,11 @@ var MAX_LEGACY_ENVELOPE_EXPIRES_AT = "2026-12-29T00:00:00Z";
|
|
|
3426
3439
|
var LAST_V2_READ_AT = "2027-01-05T00:00:00Z";
|
|
3427
3440
|
async function requestPolicyChallengeV3(input) {
|
|
3428
3441
|
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3429
|
-
const
|
|
3442
|
+
const policyRuntimePath = policyRuntimeBasePath(input.policyRuntimePath);
|
|
3443
|
+
const response = await fetchFn(new URL(`${policyRuntimePath}/challenges`, input.nodeOrigin), {
|
|
3430
3444
|
method: "POST",
|
|
3431
3445
|
redirect: "error",
|
|
3446
|
+
signal: input.signal,
|
|
3432
3447
|
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3433
3448
|
body: JSON.stringify({ policyCid: input.policyCid, recipientDid: input.recipientDid, requestedCapabilities: input.requestedCapabilities.map(normalizeUnifiedPolicyCapability) })
|
|
3434
3449
|
});
|
|
@@ -3438,6 +3453,13 @@ async function requestPolicyChallengeV3(input) {
|
|
|
3438
3453
|
throw new Error("policy challenge binding is invalid");
|
|
3439
3454
|
return value;
|
|
3440
3455
|
}
|
|
3456
|
+
function policyRuntimeBasePath(value) {
|
|
3457
|
+
const path = value ?? "/policy/v3";
|
|
3458
|
+
if (!/^\/policy(?:\/[a-z0-9-]+)*$/.test(path)) {
|
|
3459
|
+
throw new Error("policy runtime path is invalid");
|
|
3460
|
+
}
|
|
3461
|
+
return path;
|
|
3462
|
+
}
|
|
3441
3463
|
function compactAttenuationForPolicyCapabilities(input) {
|
|
3442
3464
|
const attenuation = {};
|
|
3443
3465
|
for (const raw of input) {
|
|
@@ -3483,7 +3505,7 @@ function verifyPolicyRootStatusCheckpointV3(input) {
|
|
|
3483
3505
|
}
|
|
3484
3506
|
async function getPolicyRootStatusV3(input) {
|
|
3485
3507
|
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3486
|
-
const response = await fetchFn(new URL(`/
|
|
3508
|
+
const response = await fetchFn(new URL(`/policy/v3/status/${encodeURIComponent(input.rootCid)}`, input.nodeOrigin), {
|
|
3487
3509
|
method: "GET",
|
|
3488
3510
|
redirect: "error",
|
|
3489
3511
|
headers: { accept: "application/json" }
|
|
@@ -3542,7 +3564,7 @@ async function renewPolicyRootStatusV3(input) {
|
|
|
3542
3564
|
};
|
|
3543
3565
|
const signature = await input.sign(sha2564(new TextEncoder().encode(ROOT_STATUS_RENEWAL_V1_DOMAIN + jcsCanonicalize(unsigned))));
|
|
3544
3566
|
if (signature.length !== 64) throw new Error("policy root renewal signature must be Ed25519");
|
|
3545
|
-
const response = await fetchFn(new URL("/
|
|
3567
|
+
const response = await fetchFn(new URL("/policy/v3/status", input.nodeOrigin), {
|
|
3546
3568
|
method: "POST",
|
|
3547
3569
|
redirect: "error",
|
|
3548
3570
|
headers: { accept: "application/json", "content-type": "application/json" },
|
|
@@ -3598,6 +3620,11 @@ var POLICY_SESSION_FACT_KEYS = [
|
|
|
3598
3620
|
"issuanceAuditDigestHex",
|
|
3599
3621
|
"remainingRedelegationDepth"
|
|
3600
3622
|
];
|
|
3623
|
+
var POLICY_SESSION_V4_AUDIT_FACT_KEYS = [
|
|
3624
|
+
"credentialIdAuditDigestHex",
|
|
3625
|
+
"presentationJtiAuditDigestHex"
|
|
3626
|
+
];
|
|
3627
|
+
var LOWER_SHA256_HEX = /^[0-9a-f]{64}$/;
|
|
3601
3628
|
var KV_ACTIONS = /* @__PURE__ */ new Set([
|
|
3602
3629
|
"tinycloud.kv/get",
|
|
3603
3630
|
"tinycloud.kv/list",
|
|
@@ -3792,6 +3819,133 @@ function contentSourceDigestHex(input) {
|
|
|
3792
3819
|
)
|
|
3793
3820
|
);
|
|
3794
3821
|
}
|
|
3822
|
+
function exactObject(value, keys, label) {
|
|
3823
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
3824
|
+
throw new Error(`${label} is invalid`);
|
|
3825
|
+
}
|
|
3826
|
+
const record2 = value;
|
|
3827
|
+
if (Object.keys(record2).length !== keys.length || keys.some((key) => !Object.prototype.hasOwnProperty.call(record2, key))) {
|
|
3828
|
+
throw new Error(`${label} is invalid`);
|
|
3829
|
+
}
|
|
3830
|
+
return record2;
|
|
3831
|
+
}
|
|
3832
|
+
function didKeyEd25519PublicKey(value) {
|
|
3833
|
+
const principal = value.split("#", 1)[0];
|
|
3834
|
+
if (!principal.startsWith("did:key:")) {
|
|
3835
|
+
throw new Error("policy enforcer binding signer is invalid");
|
|
3836
|
+
}
|
|
3837
|
+
const material = base58btc.decode(principal.slice("did:key:".length));
|
|
3838
|
+
if (material.length !== 34 || material[0] !== 237 || material[1] !== 1) {
|
|
3839
|
+
throw new Error("policy enforcer binding signer is invalid");
|
|
3840
|
+
}
|
|
3841
|
+
return material.slice(2);
|
|
3842
|
+
}
|
|
3843
|
+
async function registerPolicyV3(input) {
|
|
3844
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3845
|
+
const rootExpiresAt = new Date(input.rootExpiresAt);
|
|
3846
|
+
const canonicalRootExpiresAt = new Date(
|
|
3847
|
+
Math.floor(rootExpiresAt.getTime() / 1e3) * 1e3
|
|
3848
|
+
).toISOString().replace(/\.000Z$/, "Z");
|
|
3849
|
+
if (!Number.isFinite(rootExpiresAt.getTime()) || canonicalRootExpiresAt !== input.rootExpiresAt || rootExpiresAt.getTime() <= Date.now()) {
|
|
3850
|
+
throw new Error("policy root expiry is invalid");
|
|
3851
|
+
}
|
|
3852
|
+
const bindingResponse = await fetchFn(
|
|
3853
|
+
new URL("/policy/v3/enforcer-bindings", input.nodeOrigin),
|
|
3854
|
+
{
|
|
3855
|
+
method: "POST",
|
|
3856
|
+
redirect: "error",
|
|
3857
|
+
signal: input.signal,
|
|
3858
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3859
|
+
body: JSON.stringify({
|
|
3860
|
+
rootExpiresAt: input.rootExpiresAt,
|
|
3861
|
+
enforcerDid: input.enforcerDid
|
|
3862
|
+
})
|
|
3863
|
+
}
|
|
3864
|
+
);
|
|
3865
|
+
if (!bindingResponse.ok) {
|
|
3866
|
+
throw new Error(`policy enforcer binding rejected (${bindingResponse.status})`);
|
|
3867
|
+
}
|
|
3868
|
+
const binding = exactObject(
|
|
3869
|
+
await bindingResponse.json(),
|
|
3870
|
+
[
|
|
3871
|
+
"schema",
|
|
3872
|
+
"enforcerDid",
|
|
3873
|
+
"nodeAudience",
|
|
3874
|
+
"attestationBindingDigestHex",
|
|
3875
|
+
"issuedAt",
|
|
3876
|
+
"expiresAt",
|
|
3877
|
+
"signature"
|
|
3878
|
+
],
|
|
3879
|
+
"policy enforcer binding"
|
|
3880
|
+
);
|
|
3881
|
+
const signature = exactObject(
|
|
3882
|
+
binding.signature,
|
|
3883
|
+
["suite", "signerDid", "value"],
|
|
3884
|
+
"policy enforcer binding signature"
|
|
3885
|
+
);
|
|
3886
|
+
const expectedBindingDigestHex = hex(
|
|
3887
|
+
sha2564(
|
|
3888
|
+
new TextEncoder().encode(
|
|
3889
|
+
jcsCanonicalize({
|
|
3890
|
+
enforcerDid: input.enforcerDid,
|
|
3891
|
+
nodeAudience: input.expectedNodeAudience
|
|
3892
|
+
})
|
|
3893
|
+
)
|
|
3894
|
+
)
|
|
3895
|
+
);
|
|
3896
|
+
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") {
|
|
3897
|
+
throw new Error("policy enforcer binding is invalid");
|
|
3898
|
+
}
|
|
3899
|
+
const { signature: _signature, ...unsignedBinding } = binding;
|
|
3900
|
+
const signedBinding = sha2564(
|
|
3901
|
+
new TextEncoder().encode(
|
|
3902
|
+
`xyz.tinycloud.policy/AttestedEnforcerBinding/v2\0${jcsCanonicalize(unsignedBinding)}`
|
|
3903
|
+
)
|
|
3904
|
+
);
|
|
3905
|
+
if (!ed255193.verify(
|
|
3906
|
+
decodeBase64Url2(signature.value),
|
|
3907
|
+
signedBinding,
|
|
3908
|
+
didKeyEd25519PublicKey(input.expectedNodeAudience),
|
|
3909
|
+
{ zip215: false }
|
|
3910
|
+
)) {
|
|
3911
|
+
throw new Error("policy enforcer binding signature is invalid");
|
|
3912
|
+
}
|
|
3913
|
+
const response = await fetchFn(
|
|
3914
|
+
new URL("/policy/v3/policies", input.nodeOrigin),
|
|
3915
|
+
{
|
|
3916
|
+
method: "POST",
|
|
3917
|
+
redirect: "error",
|
|
3918
|
+
signal: input.signal,
|
|
3919
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3920
|
+
body: JSON.stringify({
|
|
3921
|
+
policyCid: input.policyCid,
|
|
3922
|
+
policy: input.policy,
|
|
3923
|
+
policyRoot: input.policyRoot.authorization.replace(/^Bearer\s+/i, ""),
|
|
3924
|
+
enforcementRoot: input.enforcementRoot.authorization.replace(/^Bearer\s+/i, ""),
|
|
3925
|
+
contentSourceDigestHex: input.contentSourceDigestHex,
|
|
3926
|
+
nativeProjectionHashHex: input.nativeProjectionHashHex,
|
|
3927
|
+
attestedEnforcerBinding: binding
|
|
3928
|
+
})
|
|
3929
|
+
}
|
|
3930
|
+
);
|
|
3931
|
+
if (!response.ok) {
|
|
3932
|
+
throw new Error(`policy registration rejected (${response.status})`);
|
|
3933
|
+
}
|
|
3934
|
+
const receipt = exactObject(
|
|
3935
|
+
await response.json(),
|
|
3936
|
+
["policyCid", "policyRootCid", "enforcementRootCid"],
|
|
3937
|
+
"policy registration response"
|
|
3938
|
+
);
|
|
3939
|
+
if (receipt.policyCid !== input.policyCid || receipt.policyRootCid !== input.policyRoot.cid || receipt.enforcementRootCid !== input.enforcementRoot.cid) {
|
|
3940
|
+
throw new Error("policy registration response binding is invalid");
|
|
3941
|
+
}
|
|
3942
|
+
return {
|
|
3943
|
+
policyCid: input.policyCid,
|
|
3944
|
+
policyRootCid: input.policyRoot.cid,
|
|
3945
|
+
enforcementRootCid: input.enforcementRoot.cid,
|
|
3946
|
+
attestedEnforcerBinding: binding
|
|
3947
|
+
};
|
|
3948
|
+
}
|
|
3795
3949
|
function policyDigestHex(policy) {
|
|
3796
3950
|
const canonicalPolicy = {
|
|
3797
3951
|
...policy,
|
|
@@ -3990,9 +4144,13 @@ function parsePolicySessionUcan(authorization, expectedProofs) {
|
|
|
3990
4144
|
if (expectedProofs !== void 0 && (parsed.payload.prf[0] !== expectedProofs[0] || parsed.payload.prf[1] !== expectedProofs[1]))
|
|
3991
4145
|
throw new Error("policy session UCAN ordered proofs do not match");
|
|
3992
4146
|
const factKeys = Object.keys(fact);
|
|
3993
|
-
|
|
4147
|
+
const hasLegacyFactShape = factKeys.length === POLICY_SESSION_FACT_KEYS.length && factKeys.every((key) => POLICY_SESSION_FACT_KEYS.includes(key)) && POLICY_SESSION_FACT_KEYS.every((key) => key in fact);
|
|
4148
|
+
const hasV4AuditFactShape = factKeys.length === POLICY_SESSION_FACT_KEYS.length + POLICY_SESSION_V4_AUDIT_FACT_KEYS.length && factKeys.every((key) => POLICY_SESSION_FACT_KEYS.includes(key) || POLICY_SESSION_V4_AUDIT_FACT_KEYS.includes(key)) && POLICY_SESSION_FACT_KEYS.every((key) => key in fact) && POLICY_SESSION_V4_AUDIT_FACT_KEYS.every((key) => key in fact);
|
|
4149
|
+
if (!hasLegacyFactShape && !hasV4AuditFactShape)
|
|
3994
4150
|
throw new Error("policy session UCAN fact is incomplete");
|
|
3995
|
-
if (
|
|
4151
|
+
if (hasV4AuditFactShape && (!LOWER_SHA256_HEX.test(fact.credentialIdAuditDigestHex) || !LOWER_SHA256_HEX.test(fact.presentationJtiAuditDigestHex)))
|
|
4152
|
+
throw new Error("policy session UCAN v4 audit facts are invalid");
|
|
4153
|
+
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 > 60 || parsed.payload.iss.split("#", 1)[0] !== fact.nodeAudience || parsed.payload.aud !== fact.recipientDid)
|
|
3996
4154
|
throw new Error("policy session UCAN fact is invalid");
|
|
3997
4155
|
return {
|
|
3998
4156
|
authorization,
|
|
@@ -4051,6 +4209,8 @@ var POLICY_V2_DOMAIN = "xyz.tinycloud.policy/policy/v2\0";
|
|
|
4051
4209
|
var POLICY_CREDENTIAL_REQUIREMENT_V1_TYPE = "TinyCloudPolicyCredentialRequirement";
|
|
4052
4210
|
var POLICY_PRESENTATION_V3_SCHEMA = "xyz.tinycloud.policy/presentation/v3";
|
|
4053
4211
|
var POLICY_PRESENTATION_V3_DOMAIN = "xyz.tinycloud.policy/Presentation/v3\0";
|
|
4212
|
+
var POLICY_PRESENTATION_V4_SCHEMA = "xyz.tinycloud.policy/presentation/v4";
|
|
4213
|
+
var POLICY_PRESENTATION_V4_DOMAIN = "xyz.tinycloud.policy/Presentation/v4\0";
|
|
4054
4214
|
function record(value, label) {
|
|
4055
4215
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
4056
4216
|
throw new Error(`${label} must be an object`);
|
|
@@ -4225,6 +4385,97 @@ function envelopeFromVerified(verified) {
|
|
|
4225
4385
|
} = verified;
|
|
4226
4386
|
return envelope;
|
|
4227
4387
|
}
|
|
4388
|
+
function issuedCredentialEnvelopeFromVerified(verified) {
|
|
4389
|
+
return envelopeFromVerified(verified);
|
|
4390
|
+
}
|
|
4391
|
+
async function signPolicyCredentialPresentationV4(value, sign) {
|
|
4392
|
+
const item = record(value, "Policy presentation v4");
|
|
4393
|
+
exactKeys2(item, [
|
|
4394
|
+
"schema",
|
|
4395
|
+
"jti",
|
|
4396
|
+
"challengeId",
|
|
4397
|
+
"nonce",
|
|
4398
|
+
"policyCid",
|
|
4399
|
+
"nodeAudience",
|
|
4400
|
+
"holderDid",
|
|
4401
|
+
"subjectDid",
|
|
4402
|
+
"credentialDigest",
|
|
4403
|
+
"requirementDigest",
|
|
4404
|
+
"descriptorDigest",
|
|
4405
|
+
"requestedCapabilities",
|
|
4406
|
+
"issuedAt",
|
|
4407
|
+
"expiresAt"
|
|
4408
|
+
], "Policy presentation v4");
|
|
4409
|
+
if (item.schema !== POLICY_PRESENTATION_V4_SCHEMA || item.holderDid !== item.subjectDid || !Array.isArray(item.requestedCapabilities)) throw new Error("Policy presentation v4 is invalid");
|
|
4410
|
+
const holderDid = nonEmpty(item.holderDid, "Policy presentation v4 holder DID");
|
|
4411
|
+
didKeyBytes(holderDid);
|
|
4412
|
+
const unsigned = Object.freeze({
|
|
4413
|
+
schema: POLICY_PRESENTATION_V4_SCHEMA,
|
|
4414
|
+
jti: nonEmpty(item.jti, "Policy presentation v4 jti"),
|
|
4415
|
+
challengeId: nonEmpty(item.challengeId, "Policy presentation v4 challenge"),
|
|
4416
|
+
nonce: nonEmpty(item.nonce, "Policy presentation v4 nonce"),
|
|
4417
|
+
policyCid: nonEmpty(item.policyCid, "Policy presentation v4 policy CID"),
|
|
4418
|
+
nodeAudience: nonEmpty(item.nodeAudience, "Policy presentation v4 audience"),
|
|
4419
|
+
holderDid,
|
|
4420
|
+
subjectDid: holderDid,
|
|
4421
|
+
credentialDigest: nonEmpty(item.credentialDigest, "Policy presentation v4 credential digest"),
|
|
4422
|
+
requirementDigest: nonEmpty(item.requirementDigest, "Policy presentation v4 requirement digest"),
|
|
4423
|
+
descriptorDigest: nonEmpty(item.descriptorDigest, "Policy presentation v4 descriptor digest"),
|
|
4424
|
+
// The low-level signer preserves the frozen wire bytes exactly. The
|
|
4425
|
+
// policy-aware builder performs capability normalization and containment.
|
|
4426
|
+
requestedCapabilities: Object.freeze(item.requestedCapabilities),
|
|
4427
|
+
issuedAt: date(item.issuedAt, "Policy presentation v4 issuedAt"),
|
|
4428
|
+
expiresAt: date(item.expiresAt, "Policy presentation v4 expiresAt")
|
|
4429
|
+
});
|
|
4430
|
+
const digest4 = sha2565(new TextEncoder().encode(
|
|
4431
|
+
POLICY_PRESENTATION_V4_DOMAIN + jcsCanonicalize(unsigned)
|
|
4432
|
+
));
|
|
4433
|
+
const signature = await sign(digest4);
|
|
4434
|
+
if (signature.length !== 64 || !ed255194.verify(signature, digest4, didKeyBytes(holderDid))) throw new Error("policy presentation signature is invalid");
|
|
4435
|
+
return Object.freeze({
|
|
4436
|
+
...unsigned,
|
|
4437
|
+
signature: Object.freeze({
|
|
4438
|
+
suite: "Ed25519",
|
|
4439
|
+
signerDid: holderDid,
|
|
4440
|
+
value: encodeBase64Url(signature)
|
|
4441
|
+
})
|
|
4442
|
+
});
|
|
4443
|
+
}
|
|
4444
|
+
async function buildPolicyCredentialPresentationV4(input) {
|
|
4445
|
+
const policy = validateUnifiedPolicyV2(input.policy, input.policyCid);
|
|
4446
|
+
const requirement = validateCredentialRequirement(input.requirement);
|
|
4447
|
+
const commitment = policy.credentialRequirement;
|
|
4448
|
+
const requirementDigest = await credentialRequirementDigest(requirement);
|
|
4449
|
+
const credentialDigest = await sha256Base64Url(input.credential.credential);
|
|
4450
|
+
if (requirementDigest !== commitment.requirementDigest || input.credential.descriptorDigest !== commitment.descriptorDigest || input.credential.credentialDigest !== credentialDigest || input.credential.issuerDid !== commitment.issuerDid || input.credential.issuerKid !== commitment.issuerKid || jcsCanonicalize(input.credential.profile) !== jcsCanonicalize(commitment.profile) || jcsCanonicalize(input.credential.credentialType) !== jcsCanonicalize(commitment.credentialType)) throw new Error("credential does not match the signed Policy/v2 requirement");
|
|
4451
|
+
const requestedCapabilities = input.requestedCapabilities.map(normalizeUnifiedPolicyCapability);
|
|
4452
|
+
if (requestedCapabilities.length === 0 || requestedCapabilities.some((requested) => !policy.capabilityCeiling.some((authority) => unifiedPolicyCapabilityContains(authority, requested)))) throw new Error("requested capabilities exceed the signed Policy/v2 ceiling");
|
|
4453
|
+
const holderDid = input.credential.holderDid;
|
|
4454
|
+
if (input.challenge.policyCid !== input.policyCid || input.challenge.recipientDid !== holderDid || input.credential.subjectDid !== holderDid || typeof input.challenge.nodeAudience !== "string" || input.challenge.nodeAudience.length === 0 || typeof input.challenge.expiresAt !== "string" || !Number.isFinite(Date.parse(input.challenge.expiresAt))) throw new Error("policy challenge binding is invalid");
|
|
4455
|
+
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
4456
|
+
const expiresAtMs = Math.min(
|
|
4457
|
+
now.getTime() + 6e4,
|
|
4458
|
+
Date.parse(input.challenge.expiresAt),
|
|
4459
|
+
Date.parse(input.credential.expiresAt)
|
|
4460
|
+
);
|
|
4461
|
+
if (expiresAtMs <= now.getTime()) throw new Error("policy challenge is expired");
|
|
4462
|
+
return signPolicyCredentialPresentationV4(Object.freeze({
|
|
4463
|
+
schema: POLICY_PRESENTATION_V4_SCHEMA,
|
|
4464
|
+
jti: input.jti ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
4465
|
+
challengeId: input.challenge.challengeId,
|
|
4466
|
+
nonce: input.challenge.nonce,
|
|
4467
|
+
policyCid: input.policyCid,
|
|
4468
|
+
nodeAudience: input.challenge.nodeAudience,
|
|
4469
|
+
holderDid,
|
|
4470
|
+
subjectDid: holderDid,
|
|
4471
|
+
credentialDigest,
|
|
4472
|
+
requirementDigest,
|
|
4473
|
+
descriptorDigest: input.credential.descriptorDigest,
|
|
4474
|
+
requestedCapabilities: Object.freeze(requestedCapabilities),
|
|
4475
|
+
issuedAt: rfc3339Seconds(now),
|
|
4476
|
+
expiresAt: rfc3339Seconds(new Date(expiresAtMs))
|
|
4477
|
+
}), input.sign);
|
|
4478
|
+
}
|
|
4228
4479
|
async function buildPolicyCredentialPresentationV3(input) {
|
|
4229
4480
|
const policy = validateUnifiedPolicyV2(input.policy, input.policyCid);
|
|
4230
4481
|
const requirement = validateCredentialRequirement(input.requirement);
|
|
@@ -4311,10 +4562,12 @@ async function admitPolicyCredentialV3(input) {
|
|
|
4311
4562
|
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
4312
4563
|
const challenge = await requestPolicyChallengeV3({
|
|
4313
4564
|
nodeOrigin,
|
|
4565
|
+
policyRuntimePath: input.policyRuntimePath,
|
|
4314
4566
|
policyCid: input.policyCid,
|
|
4315
4567
|
recipientDid: input.credential.holderDid,
|
|
4316
4568
|
requestedCapabilities: input.requestedCapabilities,
|
|
4317
|
-
fetch: fetchFn
|
|
4569
|
+
fetch: fetchFn,
|
|
4570
|
+
signal: input.signal
|
|
4318
4571
|
});
|
|
4319
4572
|
const presentation = await buildPolicyCredentialPresentationV3({
|
|
4320
4573
|
...input,
|
|
@@ -4322,10 +4575,11 @@ async function admitPolicyCredentialV3(input) {
|
|
|
4322
4575
|
challenge
|
|
4323
4576
|
});
|
|
4324
4577
|
const response = await fetchFn(
|
|
4325
|
-
new URL(
|
|
4578
|
+
new URL(`${policyRuntimeBasePath2(input.policyRuntimePath)}/delegations`, nodeOrigin),
|
|
4326
4579
|
{
|
|
4327
4580
|
method: "POST",
|
|
4328
4581
|
redirect: "error",
|
|
4582
|
+
signal: input.signal,
|
|
4329
4583
|
headers: { accept: "application/json", "content-type": "application/json" },
|
|
4330
4584
|
body: JSON.stringify({
|
|
4331
4585
|
policyCid: input.policyCid,
|
|
@@ -4354,8 +4608,74 @@ async function admitPolicyCredentialV3(input) {
|
|
|
4354
4608
|
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)) {
|
|
4355
4609
|
throw new Error("policy delegation signed binding is invalid");
|
|
4356
4610
|
}
|
|
4611
|
+
input.signal?.throwIfAborted();
|
|
4357
4612
|
return Object.freeze({ challenge, presentation, session });
|
|
4358
4613
|
}
|
|
4614
|
+
function validatePolicyCredentialAdmissionV4Authority(session, expected) {
|
|
4615
|
+
if (session.iss.split("#", 1)[0] !== expected.nodeAudience || session.fact.nodeAudience !== expected.nodeAudience || session.fact.enforcerDid !== expected.enforcerDid) throw new Error("policy delegation authority binding is invalid");
|
|
4616
|
+
}
|
|
4617
|
+
async function admitPolicyCredentialV4(input) {
|
|
4618
|
+
const policy = validateUnifiedPolicyV2(input.policy, input.policyCid);
|
|
4619
|
+
const nodeOrigin = policyNodeOrigin(input.nodeOrigin);
|
|
4620
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
4621
|
+
const challenge = await requestPolicyChallengeV3({
|
|
4622
|
+
nodeOrigin,
|
|
4623
|
+
policyRuntimePath: input.policyRuntimePath,
|
|
4624
|
+
policyCid: input.policyCid,
|
|
4625
|
+
recipientDid: input.credential.holderDid,
|
|
4626
|
+
requestedCapabilities: input.requestedCapabilities,
|
|
4627
|
+
fetch: fetchFn,
|
|
4628
|
+
signal: input.signal
|
|
4629
|
+
});
|
|
4630
|
+
const presentation = await buildPolicyCredentialPresentationV4({
|
|
4631
|
+
...input,
|
|
4632
|
+
policy,
|
|
4633
|
+
challenge
|
|
4634
|
+
});
|
|
4635
|
+
const response = await fetchFn(new URL(`${policyRuntimeBasePath2(input.policyRuntimePath)}/delegations`, nodeOrigin), {
|
|
4636
|
+
method: "POST",
|
|
4637
|
+
redirect: "error",
|
|
4638
|
+
signal: input.signal,
|
|
4639
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
4640
|
+
body: JSON.stringify({
|
|
4641
|
+
policyCid: input.policyCid,
|
|
4642
|
+
challengeId: challenge.challengeId,
|
|
4643
|
+
nonce: challenge.nonce,
|
|
4644
|
+
requirement: validateCredentialRequirement(input.requirement),
|
|
4645
|
+
credential: envelopeFromVerified(input.credential),
|
|
4646
|
+
presentation
|
|
4647
|
+
})
|
|
4648
|
+
});
|
|
4649
|
+
if (!response.ok) throw new Error(`policy delegation rejected (${response.status})`);
|
|
4650
|
+
const value = record(await response.json(), "policy delegation");
|
|
4651
|
+
if (value.admitted !== true || typeof value.sessionCid !== "string" || typeof value.authorization !== "string") throw new Error("policy delegation response is invalid");
|
|
4652
|
+
const session = parsePolicySessionUcan(value.authorization, [
|
|
4653
|
+
input.policyRootCid,
|
|
4654
|
+
input.enforcementRootCid
|
|
4655
|
+
]);
|
|
4656
|
+
const expectedAttenuation = compactAttenuationForPolicyCapabilities(input.requestedCapabilities);
|
|
4657
|
+
validatePolicyCredentialAdmissionV4Authority(session, {
|
|
4658
|
+
nodeAudience: input.expectedNodeAudience,
|
|
4659
|
+
enforcerDid: input.expectedEnforcerDid
|
|
4660
|
+
});
|
|
4661
|
+
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");
|
|
4662
|
+
const importResponse = await fetchFn(new URL("/delegate", nodeOrigin), {
|
|
4663
|
+
method: "POST",
|
|
4664
|
+
redirect: "error",
|
|
4665
|
+
signal: input.signal,
|
|
4666
|
+
headers: { Authorization: session.authorization }
|
|
4667
|
+
});
|
|
4668
|
+
if (!importResponse.ok) throw new Error(`delegation import rejected (${importResponse.status})`);
|
|
4669
|
+
input.signal?.throwIfAborted();
|
|
4670
|
+
return Object.freeze({ challenge, presentation, session, delegationImported: true });
|
|
4671
|
+
}
|
|
4672
|
+
function policyRuntimeBasePath2(value) {
|
|
4673
|
+
const path = value ?? "/policy/v3";
|
|
4674
|
+
if (!/^\/policy(?:\/[a-z0-9-]+)*$/.test(path)) {
|
|
4675
|
+
throw new Error("policy runtime path is invalid");
|
|
4676
|
+
}
|
|
4677
|
+
return path;
|
|
4678
|
+
}
|
|
4359
4679
|
|
|
4360
4680
|
// src/requester/index.ts
|
|
4361
4681
|
var REQUESTER_NEAR_EXPIRY_SECONDS = 30;
|
|
@@ -7762,13 +8082,13 @@ function canonicalizeRecapCaveats(caveats) {
|
|
|
7762
8082
|
}
|
|
7763
8083
|
if (Array.isArray(value)) return `[${value.map(canonicalize).join(",")}]`;
|
|
7764
8084
|
if (typeof value === "object") {
|
|
7765
|
-
const
|
|
7766
|
-
const prototype = Object.getPrototypeOf(
|
|
8085
|
+
const object4 = value;
|
|
8086
|
+
const prototype = Object.getPrototypeOf(object4);
|
|
7767
8087
|
if (prototype !== Object.prototype && prototype !== null) {
|
|
7768
8088
|
throw new Error("ReCap caveats must contain only JSON values.");
|
|
7769
8089
|
}
|
|
7770
|
-
return `{${Object.keys(
|
|
7771
|
-
(key) => `${JSON.stringify(key)}:${canonicalize(
|
|
8090
|
+
return `{${Object.keys(object4).sort().map(
|
|
8091
|
+
(key) => `${JSON.stringify(key)}:${canonicalize(object4[key])}`
|
|
7772
8092
|
).join(",")}}`;
|
|
7773
8093
|
}
|
|
7774
8094
|
throw new Error("ReCap caveats must contain only JSON values.");
|
|
@@ -7856,7 +8176,6 @@ import { ed25519 as ed255195 } from "@noble/curves/ed25519";
|
|
|
7856
8176
|
import { blake3 as blake33 } from "@noble/hashes/blake3";
|
|
7857
8177
|
import { sha256 as sha2567 } from "@noble/hashes/sha256";
|
|
7858
8178
|
var ENVELOPE_SCHEMA = "xyz.tinycloud.share/envelope";
|
|
7859
|
-
var INLINE_PREFIX = "tc2:";
|
|
7860
8179
|
var RAW_CID_CODEC = 85;
|
|
7861
8180
|
var BLAKE3_256_CODE = 30;
|
|
7862
8181
|
var DEFAULT_MAX_INLINE_BYTES = 256 * 1024;
|
|
@@ -7903,8 +8222,8 @@ function canonicalJson(value) {
|
|
|
7903
8222
|
}
|
|
7904
8223
|
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
7905
8224
|
if (typeof value === "object") {
|
|
7906
|
-
const
|
|
7907
|
-
return `{${Object.keys(
|
|
8225
|
+
const object4 = value;
|
|
8226
|
+
return `{${Object.keys(object4).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(object4[key])}`).join(",")}}`;
|
|
7908
8227
|
}
|
|
7909
8228
|
throw new ShareEnvelopeError("invalid-envelope", "unsupported JSON value");
|
|
7910
8229
|
}
|
|
@@ -8561,25 +8880,8 @@ function parsePublishedShareLink(link, options2 = {}) {
|
|
|
8561
8880
|
}
|
|
8562
8881
|
const origin2 = normalizeOrigin(url.origin);
|
|
8563
8882
|
if (options2.trustedOrigins !== void 0 && !options2.trustedOrigins.map(normalizeOrigin).includes(origin2)) throw new ShareEnvelopeError("origin-mismatch", "share link origin is not trusted");
|
|
8564
|
-
if (url.
|
|
8565
|
-
if (url.
|
|
8566
|
-
let payload;
|
|
8567
|
-
try {
|
|
8568
|
-
const bytes2 = base64UrlToBytes(url.hash.slice("#v=2&p=".length));
|
|
8569
|
-
if (bytes2.length > (options2.maxInlineBytes ?? DEFAULT_MAX_INLINE_BYTES) * 2) throw new Error("inline payload too large");
|
|
8570
|
-
const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes2));
|
|
8571
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("inline payload shape");
|
|
8572
|
-
payload = value;
|
|
8573
|
-
} catch (error) {
|
|
8574
|
-
throw new ShareEnvelopeError("invalid-link", error instanceof Error ? error.message : "invalid inline payload");
|
|
8575
|
-
}
|
|
8576
|
-
if (payload.v !== 2 || typeof payload.c !== "string" || typeof payload.cid !== "string" || payload.k !== void 0 && typeof payload.k !== "string" || Object.keys(payload).some((key3) => !["v", "c", "cid", "k"].includes(key3))) throw new ShareEnvelopeError("invalid-link", "inline payload fields are invalid");
|
|
8577
|
-
const sealed = base64UrlToBytes(payload.c);
|
|
8578
|
-
if (!verifyPublishedShareCid(payload.cid, sealed)) throw new ShareEnvelopeError("cid-mismatch", "inline payload CID does not match");
|
|
8579
|
-
const key2 = payload.k === void 0 ? void 0 : base64UrlToBytes(payload.k);
|
|
8580
|
-
if (key2 !== void 0 && key2.length !== 32) throw new ShareEnvelopeError("invalid-link", "inline payload key is invalid");
|
|
8581
|
-
return { origin: origin2, cid: payload.cid, ...key2 === void 0 ? {} : { key: key2 }, sealed };
|
|
8582
|
-
}
|
|
8883
|
+
if (url.username !== "" || url.password !== "") throw new ShareEnvelopeError("invalid-link", "share link is not canonical");
|
|
8884
|
+
if (url.search !== "") throw new ShareEnvelopeError("invalid-link", "share link is not canonical");
|
|
8583
8885
|
const match = /^\/s\/([a-z2-7]+)$/.exec(url.pathname);
|
|
8584
8886
|
if (match === null || !url.hash.startsWith("#k=")) throw new ShareEnvelopeError("invalid-link", "published share link is invalid");
|
|
8585
8887
|
const key = base64UrlToBytes(url.hash.slice(3));
|
|
@@ -8599,13 +8901,10 @@ function parseShareUrl(link, options2 = {}) {
|
|
|
8599
8901
|
} catch {
|
|
8600
8902
|
throw new ShareEnvelopeError("invalid-link", "share link must be an absolute URL");
|
|
8601
8903
|
}
|
|
8602
|
-
if (url.search !== "") throw new ShareEnvelopeError("invalid-link", "share links must not contain query parameters");
|
|
8603
8904
|
const origin2 = normalizeOrigin(url.origin);
|
|
8604
8905
|
if (options2.trustedOrigins !== void 0 && !options2.trustedOrigins.map(normalizeOrigin).includes(origin2)) throw new ShareEnvelopeError("origin-mismatch", "share link origin is not trusted");
|
|
8605
|
-
if (url.pathname === "/
|
|
8606
|
-
|
|
8607
|
-
return { kind: "inline", origin: origin2, cid: published.cid, key: published.key, url: `${url.origin}${url.pathname}`, protocol: "share-envelope-v2" };
|
|
8608
|
-
}
|
|
8906
|
+
if (url.pathname === "/viewer") throw new ShareEnvelopeError("invalid-link", "retired viewer links are not accepted");
|
|
8907
|
+
if (url.search !== "") throw new ShareEnvelopeError("invalid-link", "share links must not contain query parameters");
|
|
8609
8908
|
const match = url.pathname.match(/^\/s\/(i\/)?([^/]+)$/);
|
|
8610
8909
|
if (!match) throw new ShareEnvelopeError("invalid-link", "share link path is invalid");
|
|
8611
8910
|
const fragmentParams = url.hash === "" ? void 0 : new URLSearchParams(url.hash.slice(1));
|
|
@@ -8628,9 +8927,10 @@ function parseShareUrl(link, options2 = {}) {
|
|
|
8628
8927
|
}
|
|
8629
8928
|
function isV2ShareLink(link) {
|
|
8630
8929
|
try {
|
|
8631
|
-
|
|
8930
|
+
const url = new URL(link);
|
|
8931
|
+
return url.search === "" && url.pathname.startsWith("/s/");
|
|
8632
8932
|
} catch {
|
|
8633
|
-
return
|
|
8933
|
+
return false;
|
|
8634
8934
|
}
|
|
8635
8935
|
}
|
|
8636
8936
|
async function encryptShareBytes(bytes2, key) {
|
|
@@ -9086,8 +9386,8 @@ function canonicalJsonForProof(value) {
|
|
|
9086
9386
|
}
|
|
9087
9387
|
if (Array.isArray(value)) return `[${value.map(canonicalJsonForProof).join(",")}]`;
|
|
9088
9388
|
if (typeof value === "object") {
|
|
9089
|
-
const
|
|
9090
|
-
return `{${Object.keys(
|
|
9389
|
+
const object4 = value;
|
|
9390
|
+
return `{${Object.keys(object4).sort().map((key) => `${JSON.stringify(key)}:${canonicalJsonForProof(object4[key])}`).join(",")}}`;
|
|
9091
9391
|
}
|
|
9092
9392
|
throw new ShareAccessError("SHARE_SESSION_INVALID");
|
|
9093
9393
|
}
|
|
@@ -9796,12 +10096,12 @@ var ShareRecipientClient = class {
|
|
|
9796
10096
|
this.assertDetachedProof(request.proof);
|
|
9797
10097
|
}
|
|
9798
10098
|
parseSessionCapability(value) {
|
|
9799
|
-
const
|
|
9800
|
-
if (typeof
|
|
9801
|
-
if (!Array.isArray(
|
|
9802
|
-
const resource = this.requireObject(
|
|
10099
|
+
const object4 = this.requireObject(value, "session capability");
|
|
10100
|
+
if (typeof object4.spaceId !== "string") throw new ShareAccessError("SHARE_SESSION_INVALID", "session capability space is invalid");
|
|
10101
|
+
if (!Array.isArray(object4.actions) || object4.actions.some((action) => !["read", "list", "edit"].includes(action))) throw new ShareAccessError("SHARE_SESSION_INVALID", "session capability actions are invalid");
|
|
10102
|
+
const resource = this.requireObject(object4.resource, "session capability resource");
|
|
9803
10103
|
if (resource.kind !== "exact" && resource.kind !== "prefix" || typeof resource.path !== "string") throw new ShareAccessError("SHARE_SESSION_INVALID", "session capability resource is invalid");
|
|
9804
|
-
return { spaceId:
|
|
10104
|
+
return { spaceId: object4.spaceId, actions: [...new Set(object4.actions)], resource: { kind: resource.kind, path: resource.path } };
|
|
9805
10105
|
}
|
|
9806
10106
|
assertProvidedPolicySession(session, envelope) {
|
|
9807
10107
|
const sessionExpiry = dateValue(session.expiresAt);
|
|
@@ -11441,62 +11741,21 @@ function validateOwnerSharePolicyRegistrationBytes(bytesValue, expected) {
|
|
|
11441
11741
|
return validateOwnerSharePolicyRegistration(value, expected);
|
|
11442
11742
|
}
|
|
11443
11743
|
|
|
11444
|
-
// src/delegations/share-delivery.ts
|
|
11744
|
+
// src/delegations/share-delivery-v3.ts
|
|
11445
11745
|
import { ed25519 as ed255199 } from "@noble/curves/ed25519";
|
|
11446
|
-
|
|
11447
|
-
|
|
11448
|
-
|
|
11449
|
-
|
|
11450
|
-
|
|
11451
|
-
|
|
11452
|
-
return false;
|
|
11453
|
-
}
|
|
11454
|
-
return url.protocol === "https:" && url.origin === value && url.pathname === "/" && url.search === "" && url.hash === "" && url.username === "" && url.password === "";
|
|
11455
|
-
}
|
|
11456
|
-
var AUTHORIZATION_KEYS = [
|
|
11457
|
-
"type",
|
|
11458
|
-
"version",
|
|
11459
|
-
"jti",
|
|
11460
|
-
"shareCid",
|
|
11461
|
-
"shareId",
|
|
11462
|
-
"registrationCid",
|
|
11463
|
-
"delegationCid",
|
|
11464
|
-
"enforcementDelegationCid",
|
|
11465
|
-
"envelopeCid",
|
|
11466
|
-
"policyCid",
|
|
11467
|
-
"nodeAudience",
|
|
11468
|
-
"targetOrigin",
|
|
11469
|
-
"openCredentialsAudience",
|
|
11470
|
-
"holder",
|
|
11471
|
-
"recipientMatcher",
|
|
11472
|
-
"deliveryEmail",
|
|
11473
|
-
"shareUrl",
|
|
11474
|
-
"returnOrigin",
|
|
11475
|
-
"documentName",
|
|
11476
|
-
"senderDid",
|
|
11477
|
-
"senderTrust",
|
|
11478
|
-
"contentSource",
|
|
11479
|
-
"contentSourceDigest",
|
|
11480
|
-
"shareExpiresAt",
|
|
11481
|
-
"issuedAt",
|
|
11482
|
-
"reportAbuseToken",
|
|
11483
|
-
"actions",
|
|
11484
|
-
"resource",
|
|
11485
|
-
"authorityMaterialHandle",
|
|
11486
|
-
"authorityMaterialDigest",
|
|
11487
|
-
"requestBodyDigest",
|
|
11488
|
-
"idempotencyKey",
|
|
11489
|
-
"expiresAt",
|
|
11490
|
-
"dataAuthority"
|
|
11491
|
-
];
|
|
11492
|
-
function assertObject2(value, keys, label) {
|
|
11746
|
+
import { sha256 as sha25611 } from "@noble/hashes/sha256";
|
|
11747
|
+
var CREDENTIAL_INVITATION_REQUEST_DOMAIN = "xyz.tinycloud.credentials/invitation-request/v1\0";
|
|
11748
|
+
var DELIVERY_ADMISSION_DOMAIN = "xyz.tinycloud.policy/delivery-admission/v0\0";
|
|
11749
|
+
var REQUEST_KEYS = ["schema", "policyId", "recipient", "resource", "credentialType", "returnLink", "envelopeRef", "label", "shareExpiresAt", "audience", "issuedAt", "expiresAt", "nonce"];
|
|
11750
|
+
var ADMISSION_KEYS = ["schema", "policyId", "ownerDid", "recipient", "resource", "actions", "credentialType", "returnLink", "envelopeRef", "label", "shareExpiresAt", "senderKeyDid", "audience", "issuedAt", "expiresAt", "nonce", "signature"];
|
|
11751
|
+
function exactObject2(value, keys, label) {
|
|
11493
11752
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${label} is invalid`);
|
|
11494
11753
|
const record2 = value;
|
|
11495
11754
|
if (Object.keys(record2).length !== keys.length || keys.some((key) => !Object.prototype.hasOwnProperty.call(record2, key))) throw new Error(`${label} has unknown or missing fields`);
|
|
11496
11755
|
return record2;
|
|
11497
11756
|
}
|
|
11498
|
-
function
|
|
11499
|
-
if (!/^[A-Za-z0-9_-]+$/.test(value)) throw new Error("share delivery value is not canonical base64url");
|
|
11757
|
+
function decodeBase64Url3(value) {
|
|
11758
|
+
if (typeof value !== "string" || !/^[A-Za-z0-9_-]+$/.test(value)) throw new Error("share delivery value is not canonical base64url");
|
|
11500
11759
|
if (typeof atob === "function") {
|
|
11501
11760
|
const padded = value.replace(/-/g, "+").replace(/_/g, "/") + "=".repeat((4 - value.length % 4) % 4);
|
|
11502
11761
|
return Uint8Array.from(atob(padded), (character) => character.charCodeAt(0));
|
|
@@ -11504,42 +11763,45 @@ function fromB642(value) {
|
|
|
11504
11763
|
if (typeof Buffer !== "undefined") return new Uint8Array(Buffer.from(value, "base64url"));
|
|
11505
11764
|
throw new Error("base64url decoding is unavailable");
|
|
11506
11765
|
}
|
|
11507
|
-
function
|
|
11508
|
-
|
|
11766
|
+
function object3(value, label) {
|
|
11767
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${label} is invalid`);
|
|
11768
|
+
return value;
|
|
11769
|
+
}
|
|
11770
|
+
function didKeyBytes2(did) {
|
|
11771
|
+
if (!did.startsWith("did:key:z") || /[#/?]/.test(did.slice("did:key:".length))) throw new Error("v3 delivery admission signer is invalid");
|
|
11772
|
+
const decoded = base58btc.decode(did.slice("did:key:".length));
|
|
11773
|
+
if (decoded.length !== 34 || decoded[0] !== 237 || decoded[1] !== 1) throw new Error("v3 delivery admission signer is invalid");
|
|
11774
|
+
return decoded.slice(2);
|
|
11775
|
+
}
|
|
11776
|
+
function validateShareDeliveryAuthorizationV3Bytes(bytes2, expected) {
|
|
11777
|
+
let parsed;
|
|
11509
11778
|
try {
|
|
11510
|
-
|
|
11779
|
+
parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes2));
|
|
11511
11780
|
} catch {
|
|
11512
|
-
throw new Error("share delivery
|
|
11513
|
-
}
|
|
11514
|
-
const root =
|
|
11515
|
-
const
|
|
11516
|
-
const
|
|
11517
|
-
const
|
|
11518
|
-
|
|
11519
|
-
|
|
11520
|
-
|
|
11521
|
-
|
|
11522
|
-
|
|
11523
|
-
|
|
11524
|
-
|
|
11525
|
-
|
|
11526
|
-
|
|
11527
|
-
if (
|
|
11528
|
-
const
|
|
11529
|
-
const
|
|
11530
|
-
if (
|
|
11531
|
-
const
|
|
11532
|
-
const
|
|
11533
|
-
|
|
11534
|
-
|
|
11535
|
-
}
|
|
11536
|
-
function shareDeliveryTrustedKid(publicKey) {
|
|
11537
|
-
if (publicKey.length !== 32) throw new Error("share delivery node key must be a raw 32-byte Ed25519 public key");
|
|
11538
|
-
const prefixed = new Uint8Array(34);
|
|
11539
|
-
prefixed.set([237, 1]);
|
|
11540
|
-
prefixed.set(publicKey, 2);
|
|
11541
|
-
const did = `did:key:${base58btc.encode(prefixed)}`;
|
|
11542
|
-
return `${did}#${did.slice("did:key:".length)}`;
|
|
11781
|
+
throw new Error("v3 share delivery response is not valid UTF-8 JSON");
|
|
11782
|
+
}
|
|
11783
|
+
const root = exactObject2(parsed, ["request", "admission"], "v3 share delivery response");
|
|
11784
|
+
const request = exactObject2(root.request, REQUEST_KEYS, "credential invitation request");
|
|
11785
|
+
const admission = exactObject2(root.admission, ADMISSION_KEYS, "delivery admission");
|
|
11786
|
+
const signature = exactObject2(admission.signature, ["suite", "signerDid", "value"], "delivery admission signature");
|
|
11787
|
+
const envelope = object3(expected.request.envelope, "v3 share envelope");
|
|
11788
|
+
const policy = object3(envelope.policy, "v3 share policy");
|
|
11789
|
+
const requirement = object3(policy.credentialRequirement, "v3 credential requirement");
|
|
11790
|
+
const credentialType = object3(requirement.credentialType, "v3 credential type");
|
|
11791
|
+
const contentSource = object3(envelope.contentSource, "v3 content source");
|
|
11792
|
+
const envelopeSignature = object3(envelope.signature, "v3 envelope signature");
|
|
11793
|
+
const target = object3(envelope.target, "v3 target");
|
|
11794
|
+
const binding = object3(envelope.attestedEnforcerBinding, "v3 attested enforcer binding");
|
|
11795
|
+
const fields = ["policyId", "recipient", "resource", "credentialType", "returnLink", "envelopeRef", "label", "shareExpiresAt", "audience", "issuedAt", "expiresAt", "nonce"];
|
|
11796
|
+
if (request.schema !== "xyz.tinycloud.credentials/invitation-request/v1" || admission.schema !== "xyz.tinycloud.policy/delivery-admission/v0" || fields.some((field) => request[field] !== admission[field]) || request.policyId !== envelope.policyCid || request.recipient !== expected.request.recipientEmail || request.resource !== contentSource.kvResource || request.credentialType !== credentialType.id || request.credentialType !== "opencredentials.email/v1" || request.returnLink !== expected.request.shareUrl || request.envelopeRef !== expected.request.shareCid || request.label !== expected.request.documentName || request.shareExpiresAt !== envelope.expiry || request.audience !== expected.deliveryAudience || request.expiresAt !== expected.request.expiresAt || request.nonce !== expected.request.jti || admission.ownerDid !== envelopeSignature.signerDid || admission.senderKeyDid !== expected.senderKeyDid || canonicalizeSignedObjectUnsigned(admission.actions) !== canonicalizeSignedObjectUnsigned(["tinycloud.kv/get"]) || signature.suite !== "eddsa-ed25519-sha256-jcs-v1" || target.nodeAudience !== binding.nodeAudience || signature.signerDid !== binding.nodeAudience) throw new Error("v3 share delivery authorization is not bound to the submitted request");
|
|
11797
|
+
const issuedAt = Date.parse(String(request.issuedAt));
|
|
11798
|
+
const expiresAt = Date.parse(String(request.expiresAt));
|
|
11799
|
+
if (!Number.isFinite(issuedAt) || !Number.isFinite(expiresAt) || expiresAt <= issuedAt || expiresAt - issuedAt > 15 * 6e4) throw new Error("v3 share delivery authorization time is invalid");
|
|
11800
|
+
const admissionSignature = decodeBase64Url3(signature.value);
|
|
11801
|
+
const { signature: _signature, ...unsignedAdmission } = admission;
|
|
11802
|
+
const digest4 = sha25611(new TextEncoder().encode(`${DELIVERY_ADMISSION_DOMAIN}${canonicalizeSignedObjectUnsigned(unsignedAdmission)}`));
|
|
11803
|
+
if (admissionSignature.length !== 64 || !ed255199.verify(admissionSignature, digest4, didKeyBytes2(String(signature.signerDid)))) throw new Error("v3 share delivery admission signature is invalid");
|
|
11804
|
+
return { request, admission };
|
|
11543
11805
|
}
|
|
11544
11806
|
|
|
11545
11807
|
// src/delegations/sender-share-store.ts
|
|
@@ -11662,9 +11924,6 @@ import {
|
|
|
11662
11924
|
publishPolicyShare,
|
|
11663
11925
|
claimShare,
|
|
11664
11926
|
resumeShareAuthorization,
|
|
11665
|
-
isLegacyShareLink,
|
|
11666
|
-
receiveLegacyShare,
|
|
11667
|
-
migrateShare,
|
|
11668
11927
|
MemoryEncryptedShareHistoryStorage,
|
|
11669
11928
|
EncryptedSenderShareHistory
|
|
11670
11929
|
} from "@tinycloud/share-sdk";
|
|
@@ -11672,8 +11931,7 @@ import {
|
|
|
11672
11931
|
inspectShare,
|
|
11673
11932
|
receiveShare,
|
|
11674
11933
|
ShareReceiveError,
|
|
11675
|
-
toShareErrorInfo
|
|
11676
|
-
verifyBearerEnvelope
|
|
11934
|
+
toShareErrorInfo
|
|
11677
11935
|
} from "@tinycloud/share-sdk";
|
|
11678
11936
|
|
|
11679
11937
|
// src/networkId.ts
|
|
@@ -14302,8 +14560,8 @@ function stableJson(value) {
|
|
|
14302
14560
|
if (Array.isArray(value)) {
|
|
14303
14561
|
return `[${value.map(stableJson).join(",")}]`;
|
|
14304
14562
|
}
|
|
14305
|
-
const
|
|
14306
|
-
return `{${Object.keys(
|
|
14563
|
+
const object4 = value;
|
|
14564
|
+
return `{${Object.keys(object4).sort().map((key) => `${JSON.stringify(key)}:${stableJson(object4[key])}`).join(",")}}`;
|
|
14307
14565
|
}
|
|
14308
14566
|
function indexedDelegationFromRow(row) {
|
|
14309
14567
|
const [
|
|
@@ -14406,6 +14664,7 @@ import {
|
|
|
14406
14664
|
SecretsService,
|
|
14407
14665
|
SECRET_NAME_RE as SECRET_NAME_RE2,
|
|
14408
14666
|
canonicalizeSecretScope,
|
|
14667
|
+
parseSecretCatalogKey,
|
|
14409
14668
|
resolveSecretListPrefix,
|
|
14410
14669
|
resolveSecretPath as resolveSecretPath2,
|
|
14411
14670
|
EncryptionService,
|
|
@@ -17316,6 +17575,7 @@ var DEFAULT_LOCAL_NODE_URL = "http://127.0.0.1:8000";
|
|
|
17316
17575
|
var LOCAL_LOOPBACK_PROBE_TIMEOUT_MS = 250;
|
|
17317
17576
|
var LOCAL_LINK_PROBE_TIMEOUT_MS = 750;
|
|
17318
17577
|
var LOCAL_LINK_HOST_SUFFIX = ".local.tinycloud.link";
|
|
17578
|
+
var OWNER_NODE_BINDING_TIMEOUT_MS = 5e3;
|
|
17319
17579
|
function createInMemoryLocalNodeIdentityStore() {
|
|
17320
17580
|
const pins = /* @__PURE__ */ new Map();
|
|
17321
17581
|
return {
|
|
@@ -17448,21 +17708,80 @@ async function verifyLocationRecord(input) {
|
|
|
17448
17708
|
}
|
|
17449
17709
|
return false;
|
|
17450
17710
|
}
|
|
17451
|
-
async function fetchLocationRecord(registryUrl, subject, fetchFn = globalThis.fetch) {
|
|
17711
|
+
async function fetchLocationRecord(registryUrl, subject, fetchFn = globalThis.fetch, signal) {
|
|
17452
17712
|
const url = `${registryUrl.replace(/\/$/, "")}/v1/locations/${encodeURIComponent(subject)}`;
|
|
17453
|
-
const response = await fetchFn(url
|
|
17713
|
+
const response = await fetchFn(url, {
|
|
17714
|
+
redirect: "error",
|
|
17715
|
+
headers: { accept: "application/json" },
|
|
17716
|
+
...signal === void 0 ? {} : { signal }
|
|
17717
|
+
});
|
|
17454
17718
|
if (response.status === 404) {
|
|
17455
17719
|
return null;
|
|
17456
17720
|
}
|
|
17457
17721
|
if (!response.ok) {
|
|
17458
17722
|
throw new Error(`location registry returned HTTP ${response.status}`);
|
|
17459
17723
|
}
|
|
17460
|
-
const
|
|
17724
|
+
const text2 = await boundedResponseText(response, "location registry", 64 * 1024);
|
|
17725
|
+
let body;
|
|
17726
|
+
try {
|
|
17727
|
+
body = JSON.parse(text2);
|
|
17728
|
+
} catch {
|
|
17729
|
+
throw new LocationRecordValidationError("registry response is not JSON");
|
|
17730
|
+
}
|
|
17461
17731
|
if (body.record === void 0) {
|
|
17462
17732
|
throw new LocationRecordValidationError("registry response missing record");
|
|
17463
17733
|
}
|
|
17464
17734
|
return validateLocationRecord(body.record);
|
|
17465
17735
|
}
|
|
17736
|
+
async function publishLocationRecord(options2) {
|
|
17737
|
+
validateSubject(options2.subject);
|
|
17738
|
+
const registryUrl = exactHttpOrigin(options2.registryUrl, "registry URL");
|
|
17739
|
+
const nodeOrigin = exactHttpOrigin(options2.nodeOrigin, "node origin");
|
|
17740
|
+
const fetchFn = options2.fetch ?? globalThis.fetch.bind(globalThis);
|
|
17741
|
+
const current = await fetchLocationRecord(registryUrl, options2.subject, fetchFn);
|
|
17742
|
+
if (current !== null) {
|
|
17743
|
+
if (current.subject !== options2.subject || !await verifyLocationRecord(current)) {
|
|
17744
|
+
throw new LocationRecordValidationError("existing location record signature is invalid");
|
|
17745
|
+
}
|
|
17746
|
+
if (publishedHttpOrigins(current).includes(nodeOrigin)) {
|
|
17747
|
+
return current;
|
|
17748
|
+
}
|
|
17749
|
+
}
|
|
17750
|
+
const record2 = await signLocationRecord({
|
|
17751
|
+
version: 1,
|
|
17752
|
+
subject: options2.subject,
|
|
17753
|
+
multiaddrs: [...current?.multiaddrs ?? [], httpUrlToMultiaddr(nodeOrigin)],
|
|
17754
|
+
updated_at: (options2.now?.() ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
17755
|
+
sequence: (current?.sequence ?? -1) + 1
|
|
17756
|
+
}, options2.signer);
|
|
17757
|
+
const response = await fetchFn(
|
|
17758
|
+
`${registryUrl}/v1/locations/${encodeURIComponent(options2.subject)}`,
|
|
17759
|
+
{
|
|
17760
|
+
method: "PUT",
|
|
17761
|
+
redirect: "error",
|
|
17762
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
17763
|
+
body: JSON.stringify(record2)
|
|
17764
|
+
}
|
|
17765
|
+
);
|
|
17766
|
+
if (!response.ok) {
|
|
17767
|
+
throw new Error(`location registry publish returned HTTP ${response.status}`);
|
|
17768
|
+
}
|
|
17769
|
+
const text2 = await boundedResponseText(response, "location registry", 64 * 1024);
|
|
17770
|
+
let body;
|
|
17771
|
+
try {
|
|
17772
|
+
body = JSON.parse(text2);
|
|
17773
|
+
} catch {
|
|
17774
|
+
throw new LocationRecordValidationError("registry publish response is not JSON");
|
|
17775
|
+
}
|
|
17776
|
+
if (body.record === void 0) {
|
|
17777
|
+
throw new LocationRecordValidationError("registry publish response missing record");
|
|
17778
|
+
}
|
|
17779
|
+
const published = validateLocationRecord(body.record);
|
|
17780
|
+
if (canonicalLocationPayload(locationPayloadForRecord(published)) !== canonicalLocationPayload(locationPayloadForRecord(record2)) || published.signature !== record2.signature || !await verifyLocationRecord(published)) {
|
|
17781
|
+
throw new LocationRecordValidationError("registry publish response does not match the signed record");
|
|
17782
|
+
}
|
|
17783
|
+
return published;
|
|
17784
|
+
}
|
|
17466
17785
|
async function resolveCloudLocation(subject, options2 = {}) {
|
|
17467
17786
|
validateSubject(subject);
|
|
17468
17787
|
const verifyRecords = options2.verifyRecords ?? true;
|
|
@@ -17713,6 +18032,123 @@ function multiaddrToHttpUrl(input) {
|
|
|
17713
18032
|
}
|
|
17714
18033
|
return uri;
|
|
17715
18034
|
}
|
|
18035
|
+
function exactHttpOrigin(value, label) {
|
|
18036
|
+
let url;
|
|
18037
|
+
try {
|
|
18038
|
+
url = new URL(value);
|
|
18039
|
+
} catch {
|
|
18040
|
+
throw new LocationRecordValidationError(`${label} must be an absolute URL origin`);
|
|
18041
|
+
}
|
|
18042
|
+
const loopback = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]";
|
|
18043
|
+
if (url.protocol !== "https:" && !(url.protocol === "http:" && loopback)) {
|
|
18044
|
+
throw new LocationRecordValidationError(`${label} must use HTTPS (or loopback HTTP)`);
|
|
18045
|
+
}
|
|
18046
|
+
if (url.username !== "" || url.password !== "" || url.pathname !== "/" || url.search !== "" || url.hash !== "") {
|
|
18047
|
+
throw new LocationRecordValidationError(`${label} must be an origin without credentials, path, query, or fragment`);
|
|
18048
|
+
}
|
|
18049
|
+
return url.origin;
|
|
18050
|
+
}
|
|
18051
|
+
function publishedHttpOrigins(record2) {
|
|
18052
|
+
const origins = [];
|
|
18053
|
+
for (const address of record2.multiaddrs) {
|
|
18054
|
+
try {
|
|
18055
|
+
origins.push(exactHttpOrigin(multiaddrToHttpUrl(address), "published node URL"));
|
|
18056
|
+
} catch {
|
|
18057
|
+
}
|
|
18058
|
+
}
|
|
18059
|
+
return origins;
|
|
18060
|
+
}
|
|
18061
|
+
async function boundedResponseText(response, label, maxBytes) {
|
|
18062
|
+
const declaredLength = response.headers.get("content-length");
|
|
18063
|
+
if (declaredLength !== null && (!/^\d+$/.test(declaredLength) || Number(declaredLength) > maxBytes)) {
|
|
18064
|
+
throw new LocationRecordValidationError(`${label} response is too large`);
|
|
18065
|
+
}
|
|
18066
|
+
if (response.body === null) return "";
|
|
18067
|
+
const reader = response.body.getReader();
|
|
18068
|
+
const chunks = [];
|
|
18069
|
+
let total = 0;
|
|
18070
|
+
try {
|
|
18071
|
+
while (true) {
|
|
18072
|
+
const { done, value } = await reader.read();
|
|
18073
|
+
if (done) break;
|
|
18074
|
+
if (value === void 0) continue;
|
|
18075
|
+
total += value.byteLength;
|
|
18076
|
+
if (total > maxBytes) {
|
|
18077
|
+
await reader.cancel().catch(() => void 0);
|
|
18078
|
+
throw new LocationRecordValidationError(`${label} response is too large`);
|
|
18079
|
+
}
|
|
18080
|
+
chunks.push(value);
|
|
18081
|
+
}
|
|
18082
|
+
} finally {
|
|
18083
|
+
reader.releaseLock();
|
|
18084
|
+
}
|
|
18085
|
+
const bytes2 = new Uint8Array(total);
|
|
18086
|
+
let offset = 0;
|
|
18087
|
+
for (const chunk of chunks) {
|
|
18088
|
+
bytes2.set(chunk, offset);
|
|
18089
|
+
offset += chunk.byteLength;
|
|
18090
|
+
}
|
|
18091
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes2);
|
|
18092
|
+
}
|
|
18093
|
+
function boundedSignal(parent, timeoutMs) {
|
|
18094
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
18095
|
+
throw new LocationRecordValidationError("owner-node binding timeout must be positive");
|
|
18096
|
+
}
|
|
18097
|
+
const controller = new AbortController();
|
|
18098
|
+
const abortFromParent = () => controller.abort(parent?.reason);
|
|
18099
|
+
if (parent?.aborted) abortFromParent();
|
|
18100
|
+
else parent?.addEventListener("abort", abortFromParent, { once: true });
|
|
18101
|
+
const timer = setTimeout(() => controller.abort(new DOMException("owner-node binding timed out", "TimeoutError")), timeoutMs);
|
|
18102
|
+
return {
|
|
18103
|
+
signal: controller.signal,
|
|
18104
|
+
dispose() {
|
|
18105
|
+
clearTimeout(timer);
|
|
18106
|
+
parent?.removeEventListener("abort", abortFromParent);
|
|
18107
|
+
}
|
|
18108
|
+
};
|
|
18109
|
+
}
|
|
18110
|
+
async function verifyOwnerNodeBinding(options2) {
|
|
18111
|
+
validateSubject(options2.ownerDid);
|
|
18112
|
+
validateSubject(options2.nodeDid);
|
|
18113
|
+
const registryUrl = exactHttpOrigin(options2.registryUrl, "registry URL");
|
|
18114
|
+
const nodeOrigin = exactHttpOrigin(options2.nodeOrigin, "node origin");
|
|
18115
|
+
const fetchFn = options2.fetch ?? globalThis.fetch.bind(globalThis);
|
|
18116
|
+
const lookup = boundedSignal(options2.signal, options2.timeoutMs ?? OWNER_NODE_BINDING_TIMEOUT_MS);
|
|
18117
|
+
try {
|
|
18118
|
+
const record2 = await fetchLocationRecord(registryUrl, options2.ownerDid, fetchFn, lookup.signal);
|
|
18119
|
+
if (record2 === null) {
|
|
18120
|
+
throw new LocationRecordValidationError("owner has no published location record");
|
|
18121
|
+
}
|
|
18122
|
+
if (record2.subject !== options2.ownerDid || !await verifyLocationRecord(record2)) {
|
|
18123
|
+
throw new LocationRecordValidationError("owner location record signature is invalid");
|
|
18124
|
+
}
|
|
18125
|
+
const publishedOrigins = publishedHttpOrigins(record2);
|
|
18126
|
+
if (!publishedOrigins.includes(nodeOrigin)) {
|
|
18127
|
+
throw new LocationRecordValidationError("share target is not in the owner's signed location record");
|
|
18128
|
+
}
|
|
18129
|
+
const response = await fetchFn(new URL("/info", nodeOrigin), {
|
|
18130
|
+
redirect: "error",
|
|
18131
|
+
headers: { accept: "application/json" },
|
|
18132
|
+
signal: lookup.signal
|
|
18133
|
+
});
|
|
18134
|
+
if (!response.ok) {
|
|
18135
|
+
throw new LocationRecordValidationError(`target node /info returned HTTP ${response.status}`);
|
|
18136
|
+
}
|
|
18137
|
+
const text2 = await boundedResponseText(response, "target node /info", 16 * 1024);
|
|
18138
|
+
let body;
|
|
18139
|
+
try {
|
|
18140
|
+
body = JSON.parse(text2);
|
|
18141
|
+
} catch {
|
|
18142
|
+
throw new LocationRecordValidationError("target node /info response is not JSON");
|
|
18143
|
+
}
|
|
18144
|
+
if (body === null || typeof body !== "object" || Array.isArray(body) || body.nodeId !== options2.nodeDid) {
|
|
18145
|
+
throw new LocationRecordValidationError("target node identity does not match the share attestation");
|
|
18146
|
+
}
|
|
18147
|
+
return Object.freeze({ record: record2, nodeOrigin, nodeDid: options2.nodeDid });
|
|
18148
|
+
} finally {
|
|
18149
|
+
lookup.dispose();
|
|
18150
|
+
}
|
|
18151
|
+
}
|
|
17716
18152
|
function httpUrlToMultiaddr(input) {
|
|
17717
18153
|
const url = new URL(input);
|
|
17718
18154
|
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
@@ -17874,7 +18310,7 @@ async function verifyPkhSignature(did, payload, signature) {
|
|
|
17874
18310
|
}
|
|
17875
18311
|
function verifyDidKeySignature(did, payload, signature) {
|
|
17876
18312
|
const publicKey = ed25519PublicKeyFromDidKey2(did);
|
|
17877
|
-
const signatureBytes =
|
|
18313
|
+
const signatureBytes = decodeBase64Url4(signature);
|
|
17878
18314
|
if (signatureBytes.length !== 64) {
|
|
17879
18315
|
throw new LocationRecordValidationError(
|
|
17880
18316
|
"did:key signature must be a base64url Ed25519 signature"
|
|
@@ -17927,7 +18363,7 @@ function base64UrlEncode3(bytes2) {
|
|
|
17927
18363
|
}
|
|
17928
18364
|
return output;
|
|
17929
18365
|
}
|
|
17930
|
-
function
|
|
18366
|
+
function decodeBase64Url4(value) {
|
|
17931
18367
|
const alphabet2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
17932
18368
|
const bytes2 = [];
|
|
17933
18369
|
let buffer = 0;
|
|
@@ -17974,6 +18410,7 @@ export {
|
|
|
17974
18410
|
CREDENTIAL_CONTRACT_VERSION,
|
|
17975
18411
|
CREDENTIAL_ERROR_CODES,
|
|
17976
18412
|
CREDENTIAL_FORMAT,
|
|
18413
|
+
CREDENTIAL_INVITATION_REQUEST_DOMAIN,
|
|
17977
18414
|
CREDENTIAL_ACQUISITION_PROTOCOL as CREDENTIAL_PROTOCOL,
|
|
17978
18415
|
CREDENTIAL_STEP_REGISTRY_VERSION,
|
|
17979
18416
|
CapabilityKeyRegistry,
|
|
@@ -17997,6 +18434,7 @@ export {
|
|
|
17997
18434
|
DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
|
|
17998
18435
|
DEFAULT_TINYCLOUD_FALLBACK_HOST,
|
|
17999
18436
|
DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL,
|
|
18437
|
+
DELIVERY_ADMISSION_DOMAIN,
|
|
18000
18438
|
DUCKDB,
|
|
18001
18439
|
DataVaultService,
|
|
18002
18440
|
DatabaseHandle,
|
|
@@ -18008,6 +18446,7 @@ export {
|
|
|
18008
18446
|
DuckDbService2 as DuckDbService,
|
|
18009
18447
|
ED25519_JCS_SIGNATURE_SUITE,
|
|
18010
18448
|
EIP191_JCS_SIGNATURE_SUITE,
|
|
18449
|
+
EMAIL_CREDENTIAL_MAX_AGE_SECONDS,
|
|
18011
18450
|
ENCRYPTION,
|
|
18012
18451
|
ENCRYPTION_MANIFEST_SPACE,
|
|
18013
18452
|
ENCRYPTION_NETWORK_URN_PREFIX,
|
|
@@ -18046,6 +18485,7 @@ export {
|
|
|
18046
18485
|
NETWORK_NAME_PATTERN,
|
|
18047
18486
|
NetworkIdError,
|
|
18048
18487
|
OPENKEY_ACTION_ID_SEPARATOR,
|
|
18488
|
+
OWNER_NODE_BINDING_TIMEOUT_MS,
|
|
18049
18489
|
OpenKeyManageKeyError,
|
|
18050
18490
|
POLICY_CAPABILITY_V1_DOMAIN,
|
|
18051
18491
|
POLICY_CAPABILITY_V1_SCHEMA,
|
|
@@ -18059,6 +18499,8 @@ export {
|
|
|
18059
18499
|
POLICY_ENGINE_RESOLVE_REQUEST_SCHEMA,
|
|
18060
18500
|
POLICY_PRESENTATION_V3_DOMAIN,
|
|
18061
18501
|
POLICY_PRESENTATION_V3_SCHEMA,
|
|
18502
|
+
POLICY_PRESENTATION_V4_DOMAIN,
|
|
18503
|
+
POLICY_PRESENTATION_V4_SCHEMA,
|
|
18062
18504
|
POLICY_SCHEMA,
|
|
18063
18505
|
POLICY_SESSION_UCAN_V1_PROFILE,
|
|
18064
18506
|
POLICY_STATUS_SCHEMA,
|
|
@@ -18083,7 +18525,6 @@ export {
|
|
|
18083
18525
|
SECRET_RECORDS_SCHEMA,
|
|
18084
18526
|
SERVICE_LONG_TO_SHORT,
|
|
18085
18527
|
SERVICE_SHORT_TO_LONG,
|
|
18086
|
-
SHARE_DELIVERY_AUTHORIZATION_DOMAIN,
|
|
18087
18528
|
SPACE,
|
|
18088
18529
|
SQL,
|
|
18089
18530
|
SQLAction,
|
|
@@ -18136,6 +18577,7 @@ export {
|
|
|
18136
18577
|
activateSessionWithHost,
|
|
18137
18578
|
addressStorageKey,
|
|
18138
18579
|
admitPolicyCredentialV3,
|
|
18580
|
+
admitPolicyCredentialV4,
|
|
18139
18581
|
applyPrefix,
|
|
18140
18582
|
bootstrapEncryptionNetworkId,
|
|
18141
18583
|
bootstrapSpaceId,
|
|
@@ -18146,6 +18588,7 @@ export {
|
|
|
18146
18588
|
buildDecryptInvocation,
|
|
18147
18589
|
buildNetworkId2 as buildNetworkId,
|
|
18148
18590
|
buildPolicyCredentialPresentationV3,
|
|
18591
|
+
buildPolicyCredentialPresentationV4,
|
|
18149
18592
|
buildSpaceUri,
|
|
18150
18593
|
canonicalDigest,
|
|
18151
18594
|
canonicalHashHex,
|
|
@@ -18176,6 +18619,7 @@ export {
|
|
|
18176
18619
|
createAndSignSignedObject,
|
|
18177
18620
|
createCapabilityKeyRegistry,
|
|
18178
18621
|
createDelegatedShareKey,
|
|
18622
|
+
createEmailCredentialRequirement,
|
|
18179
18623
|
createHolderBinding,
|
|
18180
18624
|
createInMemoryLocalNodeIdentityStore,
|
|
18181
18625
|
createLocalStorageLocalNodeIdentityStore,
|
|
@@ -18254,6 +18698,7 @@ export {
|
|
|
18254
18698
|
isNetworkId,
|
|
18255
18699
|
isPlausibleOpenKeyActionId,
|
|
18256
18700
|
isV2ShareLink,
|
|
18701
|
+
issuedCredentialEnvelopeFromVerified,
|
|
18257
18702
|
jcsCanonicalize,
|
|
18258
18703
|
loadManifest,
|
|
18259
18704
|
locationPayloadForRecord,
|
|
@@ -18282,6 +18727,7 @@ export {
|
|
|
18282
18727
|
parsePolicySessionUcan,
|
|
18283
18728
|
parsePortableDelegation,
|
|
18284
18729
|
parseRecapCapabilities,
|
|
18730
|
+
parseSecretCatalogKey,
|
|
18285
18731
|
parseShareArtifact,
|
|
18286
18732
|
parseShareUrl,
|
|
18287
18733
|
parseSpaceUri,
|
|
@@ -18294,7 +18740,9 @@ export {
|
|
|
18294
18740
|
principalDidEquals,
|
|
18295
18741
|
projectUnifiedPolicyCapabilities,
|
|
18296
18742
|
projectUnifiedPolicyCapability,
|
|
18743
|
+
publishLocationRecord,
|
|
18297
18744
|
recapCaveatsEqual,
|
|
18745
|
+
registerPolicyV3,
|
|
18298
18746
|
renewPolicyRootStatusV3,
|
|
18299
18747
|
requestTinyCloudManageKeyScope,
|
|
18300
18748
|
resolveCloudLocation,
|
|
@@ -18312,10 +18760,10 @@ export {
|
|
|
18312
18760
|
serviceError5 as serviceError,
|
|
18313
18761
|
sha256Base64Url,
|
|
18314
18762
|
shareCapabilityAllows,
|
|
18315
|
-
shareDeliveryTrustedKid,
|
|
18316
18763
|
signCompactUcanAuthorization,
|
|
18317
18764
|
signCompactUcanRootAuthorization,
|
|
18318
18765
|
signLocationRecord,
|
|
18766
|
+
signPolicyCredentialPresentationV4,
|
|
18319
18767
|
signShareEnvelope,
|
|
18320
18768
|
signedObjectIdFor,
|
|
18321
18769
|
submitHostDelegation,
|
|
@@ -18348,13 +18796,14 @@ export {
|
|
|
18348
18796
|
validatePolicyStatusSignedShape,
|
|
18349
18797
|
validatePolicyStatusUnsigned,
|
|
18350
18798
|
validatePolicyUnsigned,
|
|
18351
|
-
|
|
18799
|
+
validateShareDeliveryAuthorizationV3Bytes,
|
|
18352
18800
|
validateUnifiedPolicyV2,
|
|
18353
18801
|
verifyDecryptResponse,
|
|
18354
18802
|
verifyDidKeyEd25519Signature,
|
|
18355
18803
|
verifyEip191MessageSignature,
|
|
18356
18804
|
verifyIssuedCredential,
|
|
18357
18805
|
verifyLocationRecord,
|
|
18806
|
+
verifyOwnerNodeBinding,
|
|
18358
18807
|
verifyPolicy,
|
|
18359
18808
|
verifyPolicyEngineRecord,
|
|
18360
18809
|
verifyPolicyRootRevocationV3,
|