@tinycloud/sdk-core 2.11.0-beta.10 → 2.11.0-beta.12
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/{capability-BjzXwtNw.d.cts → capability-BA49Uboq.d.cts} +1 -1
- package/dist/{capability-BjzXwtNw.d.ts → capability-BA49Uboq.d.ts} +1 -1
- package/dist/delegations/index.cjs +620 -221
- package/dist/delegations/index.cjs.map +1 -1
- package/dist/delegations/index.d.cts +8 -8
- package/dist/delegations/index.d.ts +8 -8
- package/dist/delegations/index.js +621 -222
- package/dist/delegations/index.js.map +1 -1
- package/dist/index.cjs +1576 -762
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -15
- package/dist/index.d.ts +15 -15
- package/dist/index.js +1548 -732
- package/dist/index.js.map +1 -1
- package/dist/policy/index.cjs +867 -175
- package/dist/policy/index.cjs.map +1 -1
- package/dist/policy/index.d.cts +5 -4
- package/dist/policy/index.d.ts +5 -4
- package/dist/policy/index.js +867 -175
- package/dist/policy/index.js.map +1 -1
- package/dist/{recipient-types.schema-D5pDlIqn.d.cts → recipient-types.schema-CuDpskPd.d.cts} +172 -115
- package/dist/{recipient-types.schema-D5pDlIqn.d.ts → recipient-types.schema-CuDpskPd.d.ts} +172 -115
- package/dist/requester/index.d.cts +1 -1
- package/dist/requester/index.d.ts +1 -1
- package/dist/unified-DbySI5wW.d.cts +429 -0
- package/dist/unified-tCGtc-Wx.d.ts +429 -0
- package/package.json +5 -5
- package/dist/signed-object-C6mWbTbB.d.ts +0 -149
- package/dist/signed-object-IMAm5a32.d.cts +0 -149
package/dist/policy/index.js
CHANGED
|
@@ -323,16 +323,16 @@ function policyCapabilityContains(authority, request) {
|
|
|
323
323
|
return caveatsContain(auth.caveats, req.caveats);
|
|
324
324
|
}
|
|
325
325
|
function normalizePolicyCapabilityWithOptions(input, options) {
|
|
326
|
-
const
|
|
327
|
-
assertExactKeys(
|
|
328
|
-
const service = requiredString(
|
|
326
|
+
const object2 = expectObject(input, "$");
|
|
327
|
+
assertExactKeys(object2, ["service", "space", "path", "actions", "caveats"], "$");
|
|
328
|
+
const service = requiredString(object2, "service", "$", "policy-capability-malformed-service");
|
|
329
329
|
if (!CEILING_SERVICES.has(service)) {
|
|
330
330
|
throw new PolicyCapabilityError(
|
|
331
331
|
"policy-capability-malformed-service",
|
|
332
332
|
"$.service is outside the frozen permissionsCeiling vocabulary"
|
|
333
333
|
);
|
|
334
334
|
}
|
|
335
|
-
const space = requiredString(
|
|
335
|
+
const space = requiredString(object2, "space", "$", "policy-capability-malformed-space");
|
|
336
336
|
validateConcreteSpace(space);
|
|
337
337
|
const canonicalSpace = space.normalize("NFC");
|
|
338
338
|
if (options.requireCanonical && canonicalSpace !== space) {
|
|
@@ -341,7 +341,7 @@ function normalizePolicyCapabilityWithOptions(input, options) {
|
|
|
341
341
|
"$.space must already be canonical NFC"
|
|
342
342
|
);
|
|
343
343
|
}
|
|
344
|
-
const rawPath = requiredString(
|
|
344
|
+
const rawPath = requiredString(object2, "path", "$", "policy-capability-malformed-path");
|
|
345
345
|
validateRawPath(rawPath, options);
|
|
346
346
|
const path = normalizePath(rawPath);
|
|
347
347
|
if (options.requireCanonical && path !== rawPath) {
|
|
@@ -352,7 +352,7 @@ function normalizePolicyCapabilityWithOptions(input, options) {
|
|
|
352
352
|
}
|
|
353
353
|
validateRawPath(path, options);
|
|
354
354
|
const actions = normalizeActions(
|
|
355
|
-
requiredArray(
|
|
355
|
+
requiredArray(object2, "actions", "$", "policy-capability-malformed-action"),
|
|
356
356
|
service,
|
|
357
357
|
options
|
|
358
358
|
);
|
|
@@ -361,9 +361,9 @@ function normalizePolicyCapabilityWithOptions(input, options) {
|
|
|
361
361
|
output.space = canonicalSpace;
|
|
362
362
|
output.path = path;
|
|
363
363
|
output.actions = actions;
|
|
364
|
-
if (hasOwn(
|
|
364
|
+
if (hasOwn(object2, "caveats")) {
|
|
365
365
|
output.caveats = validateCaveats(
|
|
366
|
-
requiredValue(
|
|
366
|
+
requiredValue(object2, "caveats", "$", "policy-capability-malformed-caveats"),
|
|
367
367
|
output.service
|
|
368
368
|
);
|
|
369
369
|
}
|
|
@@ -386,9 +386,9 @@ function expectObject(input, path) {
|
|
|
386
386
|
);
|
|
387
387
|
}
|
|
388
388
|
}
|
|
389
|
-
function assertExactKeys(
|
|
389
|
+
function assertExactKeys(object2, allowed, path) {
|
|
390
390
|
const allowedSet = new Set(allowed);
|
|
391
|
-
for (const key of Object.keys(
|
|
391
|
+
for (const key of Object.keys(object2)) {
|
|
392
392
|
if (!allowedSet.has(key)) {
|
|
393
393
|
throw new PolicyCapabilityError(
|
|
394
394
|
key === "id" || key === "scope" ? "policy-capability-malformed" : "policy-capability-unknown-key",
|
|
@@ -397,21 +397,21 @@ function assertExactKeys(object, allowed, path) {
|
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
399
|
}
|
|
400
|
-
function requiredValue(
|
|
401
|
-
if (!hasOwn(
|
|
400
|
+
function requiredValue(object2, key, path, code2) {
|
|
401
|
+
if (!hasOwn(object2, key)) {
|
|
402
402
|
throw new PolicyCapabilityError(code2, `${path}.${key} is required`);
|
|
403
403
|
}
|
|
404
|
-
return
|
|
404
|
+
return object2[key];
|
|
405
405
|
}
|
|
406
|
-
function requiredString(
|
|
407
|
-
const value = requiredValue(
|
|
406
|
+
function requiredString(object2, key, path, code2) {
|
|
407
|
+
const value = requiredValue(object2, key, path, code2);
|
|
408
408
|
if (typeof value !== "string" || value.length === 0) {
|
|
409
409
|
throw new PolicyCapabilityError(code2, `${path}.${key} must be a non-empty string`);
|
|
410
410
|
}
|
|
411
411
|
return value;
|
|
412
412
|
}
|
|
413
|
-
function requiredArray(
|
|
414
|
-
const value = requiredValue(
|
|
413
|
+
function requiredArray(object2, key, path, code2) {
|
|
414
|
+
const value = requiredValue(object2, key, path, code2);
|
|
415
415
|
if (!Array.isArray(value)) {
|
|
416
416
|
throw new PolicyCapabilityError(code2, `${path}.${key} must be an array`);
|
|
417
417
|
}
|
|
@@ -556,11 +556,11 @@ function validateSqlStatement(input, path) {
|
|
|
556
556
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
557
557
|
throw new PolicyCapabilityError("policy-capability-malformed-caveats", `${path} must be an object`);
|
|
558
558
|
}
|
|
559
|
-
const
|
|
560
|
-
assertCaveatKeys(
|
|
561
|
-
caveatString(
|
|
562
|
-
caveatString(
|
|
563
|
-
const fixedParams = requiredCaveat(
|
|
559
|
+
const object2 = input;
|
|
560
|
+
assertCaveatKeys(object2, ["name", "sql", "fixedParams"], path);
|
|
561
|
+
caveatString(object2, "name", path);
|
|
562
|
+
caveatString(object2, "sql", path);
|
|
563
|
+
const fixedParams = requiredCaveat(object2, "fixedParams", path);
|
|
564
564
|
if (!Array.isArray(fixedParams)) {
|
|
565
565
|
throw new PolicyCapabilityError(
|
|
566
566
|
"policy-capability-malformed-caveats",
|
|
@@ -575,20 +575,20 @@ function validateFixedParam(input, path) {
|
|
|
575
575
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
576
576
|
throw new PolicyCapabilityError("policy-capability-malformed-caveats", `${path} must be an object`);
|
|
577
577
|
}
|
|
578
|
-
const
|
|
579
|
-
assertCaveatKeys(
|
|
580
|
-
const index = requiredCaveat(
|
|
578
|
+
const object2 = input;
|
|
579
|
+
assertCaveatKeys(object2, ["index", "value"], path);
|
|
580
|
+
const index = requiredCaveat(object2, "index", path);
|
|
581
581
|
if (typeof index !== "number" || !Number.isSafeInteger(index) || index < 0) {
|
|
582
582
|
throw new PolicyCapabilityError(
|
|
583
583
|
"policy-capability-malformed-caveats",
|
|
584
584
|
`${path}.index must be a non-negative integer`
|
|
585
585
|
);
|
|
586
586
|
}
|
|
587
|
-
requiredCaveat(
|
|
587
|
+
requiredCaveat(object2, "value", path);
|
|
588
588
|
}
|
|
589
|
-
function assertCaveatKeys(
|
|
589
|
+
function assertCaveatKeys(object2, allowed, path) {
|
|
590
590
|
const allowedSet = new Set(allowed);
|
|
591
|
-
for (const key of Object.keys(
|
|
591
|
+
for (const key of Object.keys(object2)) {
|
|
592
592
|
if (!allowedSet.has(key)) {
|
|
593
593
|
throw new PolicyCapabilityError(
|
|
594
594
|
"policy-capability-malformed-caveats",
|
|
@@ -597,17 +597,17 @@ function assertCaveatKeys(object, allowed, path) {
|
|
|
597
597
|
}
|
|
598
598
|
}
|
|
599
599
|
}
|
|
600
|
-
function requiredCaveat(
|
|
601
|
-
if (!hasOwn(
|
|
600
|
+
function requiredCaveat(object2, key, path) {
|
|
601
|
+
if (!hasOwn(object2, key)) {
|
|
602
602
|
throw new PolicyCapabilityError(
|
|
603
603
|
"policy-capability-malformed-caveats",
|
|
604
604
|
`${path}.${key} is required`
|
|
605
605
|
);
|
|
606
606
|
}
|
|
607
|
-
return
|
|
607
|
+
return object2[key];
|
|
608
608
|
}
|
|
609
|
-
function caveatString(
|
|
610
|
-
const value = requiredCaveat(
|
|
609
|
+
function caveatString(object2, key, path) {
|
|
610
|
+
const value = requiredCaveat(object2, key, path);
|
|
611
611
|
if (typeof value !== "string" || value.length === 0) {
|
|
612
612
|
throw new PolicyCapabilityError(
|
|
613
613
|
"policy-capability-malformed-caveats",
|
|
@@ -638,8 +638,8 @@ function caveatsContain(authority, request) {
|
|
|
638
638
|
(statement) => authorityStatements.some((candidate) => jcsCanonicalize(candidate) === jcsCanonicalize(statement))
|
|
639
639
|
);
|
|
640
640
|
}
|
|
641
|
-
function hasOwn(
|
|
642
|
-
return objectHasOwn2(
|
|
641
|
+
function hasOwn(object2, key) {
|
|
642
|
+
return objectHasOwn2(object2, key);
|
|
643
643
|
}
|
|
644
644
|
|
|
645
645
|
// src/policy/signed-object.ts
|
|
@@ -1909,17 +1909,17 @@ async function createAndSignSignedObject(input, signer) {
|
|
|
1909
1909
|
}
|
|
1910
1910
|
function createAndSignPolicy(input, signer) {
|
|
1911
1911
|
return createAndSignSignedObject(input, signer).then(
|
|
1912
|
-
(
|
|
1912
|
+
(object2) => validatePolicySignedShape(object2)
|
|
1913
1913
|
);
|
|
1914
1914
|
}
|
|
1915
1915
|
function createAndSignPolicyStatus(input, signer) {
|
|
1916
1916
|
return createAndSignSignedObject(input, signer).then(
|
|
1917
|
-
(
|
|
1917
|
+
(object2) => validatePolicyStatusSignedShape(object2)
|
|
1918
1918
|
);
|
|
1919
1919
|
}
|
|
1920
1920
|
function createAndSignPolicyEngineRecord(input, signer) {
|
|
1921
1921
|
return createAndSignSignedObject(input, signer).then(
|
|
1922
|
-
(
|
|
1922
|
+
(object2) => validatePolicyEngineRecordSignedShape(object2)
|
|
1923
1923
|
);
|
|
1924
1924
|
}
|
|
1925
1925
|
async function verifySignedObject(input) {
|
|
@@ -2023,9 +2023,9 @@ function validateUnsignedForDescriptor(input, descriptor) {
|
|
|
2023
2023
|
}
|
|
2024
2024
|
}
|
|
2025
2025
|
function validatePolicyShape(input, signed) {
|
|
2026
|
-
const
|
|
2026
|
+
const object2 = expectJsonObject(normalizeJson(input), "$");
|
|
2027
2027
|
assertExactKeys2(
|
|
2028
|
-
|
|
2028
|
+
object2,
|
|
2029
2029
|
signed ? [
|
|
2030
2030
|
"schema",
|
|
2031
2031
|
"policyId",
|
|
@@ -2053,30 +2053,30 @@ function validatePolicyShape(input, signed) {
|
|
|
2053
2053
|
],
|
|
2054
2054
|
"$"
|
|
2055
2055
|
);
|
|
2056
|
-
expectConst(requiredString2(
|
|
2056
|
+
expectConst(requiredString2(object2, "schema", "$"), POLICY_SCHEMA, "$.schema");
|
|
2057
2057
|
if (signed) {
|
|
2058
|
-
requiredString2(
|
|
2059
|
-
validateSignature(requiredValue2(
|
|
2058
|
+
requiredString2(object2, "policyId", "$");
|
|
2059
|
+
validateSignature(requiredValue2(object2, "signature", "$"));
|
|
2060
2060
|
}
|
|
2061
|
-
requiredString2(
|
|
2062
|
-
requiredString2(
|
|
2063
|
-
requiredDateString(
|
|
2064
|
-
optionalDateString(
|
|
2065
|
-
validatePolicyResource(requiredValue2(
|
|
2066
|
-
validateExpression(requiredValue2(
|
|
2067
|
-
validateGrant(requiredValue2(
|
|
2068
|
-
if (hasOwn2(
|
|
2069
|
-
validateDisclosure(requiredValue2(
|
|
2061
|
+
requiredString2(object2, "ownerDid", "$");
|
|
2062
|
+
requiredString2(object2, "signingKeyDid", "$");
|
|
2063
|
+
requiredDateString(object2, "createdAt", "$");
|
|
2064
|
+
optionalDateString(object2, "expiresAt", "$");
|
|
2065
|
+
validatePolicyResource(requiredValue2(object2, "resource", "$"), "$.resource");
|
|
2066
|
+
validateExpression(requiredValue2(object2, "when", "$"), "$.when");
|
|
2067
|
+
validateGrant(requiredValue2(object2, "grant", "$"), "$.grant");
|
|
2068
|
+
if (hasOwn2(object2, "disclosure")) {
|
|
2069
|
+
validateDisclosure(requiredValue2(object2, "disclosure", "$"), "$.disclosure");
|
|
2070
2070
|
}
|
|
2071
|
-
if (hasOwn2(
|
|
2072
|
-
validateAudit(requiredValue2(
|
|
2071
|
+
if (hasOwn2(object2, "audit")) {
|
|
2072
|
+
validateAudit(requiredValue2(object2, "audit", "$"), "$.audit");
|
|
2073
2073
|
}
|
|
2074
|
-
return
|
|
2074
|
+
return object2;
|
|
2075
2075
|
}
|
|
2076
2076
|
function validatePolicyStatusShape(input, signed) {
|
|
2077
|
-
const
|
|
2077
|
+
const object2 = expectJsonObject(normalizeJson(input), "$");
|
|
2078
2078
|
assertExactKeys2(
|
|
2079
|
-
|
|
2079
|
+
object2,
|
|
2080
2080
|
signed ? [
|
|
2081
2081
|
"schema",
|
|
2082
2082
|
"statusId",
|
|
@@ -2100,28 +2100,28 @@ function validatePolicyStatusShape(input, signed) {
|
|
|
2100
2100
|
],
|
|
2101
2101
|
"$"
|
|
2102
2102
|
);
|
|
2103
|
-
expectConst(requiredString2(
|
|
2103
|
+
expectConst(requiredString2(object2, "schema", "$"), POLICY_STATUS_SCHEMA, "$.schema");
|
|
2104
2104
|
if (signed) {
|
|
2105
|
-
requiredString2(
|
|
2106
|
-
validateSignature(requiredValue2(
|
|
2105
|
+
requiredString2(object2, "statusId", "$");
|
|
2106
|
+
validateSignature(requiredValue2(object2, "signature", "$"));
|
|
2107
2107
|
}
|
|
2108
|
-
requiredString2(
|
|
2109
|
-
requiredString2(
|
|
2110
|
-
requiredInteger(
|
|
2111
|
-
expectOneOf(requiredString2(
|
|
2108
|
+
requiredString2(object2, "policyId", "$");
|
|
2109
|
+
requiredString2(object2, "ownerDid", "$");
|
|
2110
|
+
requiredInteger(object2, "sequence", "$", 0);
|
|
2111
|
+
expectOneOf(requiredString2(object2, "disposition", "$"), [
|
|
2112
2112
|
"active",
|
|
2113
2113
|
"suspended",
|
|
2114
2114
|
"revoked"
|
|
2115
2115
|
], "$.disposition");
|
|
2116
|
-
requiredDateString(
|
|
2117
|
-
optionalString(
|
|
2118
|
-
requiredString2(
|
|
2119
|
-
return
|
|
2116
|
+
requiredDateString(object2, "effectiveAt", "$");
|
|
2117
|
+
optionalString(object2, "reasonCode", "$");
|
|
2118
|
+
requiredString2(object2, "signingKeyDid", "$");
|
|
2119
|
+
return object2;
|
|
2120
2120
|
}
|
|
2121
2121
|
function validatePolicyEngineRecordShape(input, signed) {
|
|
2122
|
-
const
|
|
2122
|
+
const object2 = expectJsonObject(normalizeJson(input), "$");
|
|
2123
2123
|
assertExactKeys2(
|
|
2124
|
-
|
|
2124
|
+
object2,
|
|
2125
2125
|
signed ? [
|
|
2126
2126
|
"schema",
|
|
2127
2127
|
"engineRecordId",
|
|
@@ -2146,44 +2146,44 @@ function validatePolicyEngineRecordShape(input, signed) {
|
|
|
2146
2146
|
"$"
|
|
2147
2147
|
);
|
|
2148
2148
|
expectConst(
|
|
2149
|
-
requiredString2(
|
|
2149
|
+
requiredString2(object2, "schema", "$"),
|
|
2150
2150
|
POLICY_ENGINE_RECORD_SCHEMA,
|
|
2151
2151
|
"$.schema"
|
|
2152
2152
|
);
|
|
2153
2153
|
if (signed) {
|
|
2154
|
-
requiredString2(
|
|
2155
|
-
validateSignature(requiredValue2(
|
|
2154
|
+
requiredString2(object2, "engineRecordId", "$");
|
|
2155
|
+
validateSignature(requiredValue2(object2, "signature", "$"));
|
|
2156
2156
|
}
|
|
2157
|
-
requiredString2(
|
|
2158
|
-
requiredString2(
|
|
2159
|
-
requiredString2(
|
|
2157
|
+
requiredString2(object2, "ownerDid", "$");
|
|
2158
|
+
requiredString2(object2, "endpoint", "$");
|
|
2159
|
+
requiredString2(object2, "audience", "$");
|
|
2160
2160
|
requiredStringArray(
|
|
2161
|
-
|
|
2161
|
+
object2,
|
|
2162
2162
|
"supportedPolicyVersions",
|
|
2163
2163
|
"$",
|
|
2164
2164
|
(value, path) => expectConst(value, "v0", path)
|
|
2165
2165
|
);
|
|
2166
|
-
requiredStringArray(
|
|
2167
|
-
requiredString2(
|
|
2168
|
-
requiredDateString(
|
|
2169
|
-
return
|
|
2166
|
+
requiredStringArray(object2, "supportedEvidenceVerifiers", "$");
|
|
2167
|
+
requiredString2(object2, "grantIssuerDid", "$");
|
|
2168
|
+
requiredDateString(object2, "expiresAt", "$");
|
|
2169
|
+
return object2;
|
|
2170
2170
|
}
|
|
2171
2171
|
function validateSignature(input) {
|
|
2172
|
-
const
|
|
2173
|
-
assertExactKeys2(
|
|
2174
|
-
const suite = requiredString2(
|
|
2172
|
+
const object2 = expectJsonObject(input, "$.signature");
|
|
2173
|
+
assertExactKeys2(object2, ["suite", "signerDid", "value"], "$.signature");
|
|
2174
|
+
const suite = requiredString2(object2, "suite", "$.signature");
|
|
2175
2175
|
assertSupportedSignatureSuite(suite);
|
|
2176
|
-
const signerDid = requiredString2(
|
|
2177
|
-
const value = requiredString2(
|
|
2176
|
+
const signerDid = requiredString2(object2, "signerDid", "$.signature");
|
|
2177
|
+
const value = requiredString2(object2, "value", "$.signature");
|
|
2178
2178
|
decodeSignatureValue(value, suite);
|
|
2179
2179
|
return { suite, signerDid, value };
|
|
2180
2180
|
}
|
|
2181
2181
|
function validatePolicyResource(input, path) {
|
|
2182
|
-
const
|
|
2183
|
-
assertExactKeys2(
|
|
2184
|
-
requiredString2(
|
|
2185
|
-
requiredString2(
|
|
2186
|
-
const ceiling = requiredArray2(
|
|
2182
|
+
const object2 = expectJsonObject(input, path);
|
|
2183
|
+
assertExactKeys2(object2, ["resourceType", "resourceId", "permissionsCeiling"], path);
|
|
2184
|
+
requiredString2(object2, "resourceType", path);
|
|
2185
|
+
requiredString2(object2, "resourceId", path);
|
|
2186
|
+
const ceiling = requiredArray2(object2, "permissionsCeiling", path, 1);
|
|
2187
2187
|
for (let index = 0; index < ceiling.length; index++) {
|
|
2188
2188
|
validatePolicyCapability(ceiling[index], `${path}.permissionsCeiling[${index}]`);
|
|
2189
2189
|
}
|
|
@@ -2199,10 +2199,10 @@ function validatePolicyPermissionsCeilingForSigning(input) {
|
|
|
2199
2199
|
}
|
|
2200
2200
|
}
|
|
2201
2201
|
function validatePolicyCapability(input, path) {
|
|
2202
|
-
const
|
|
2202
|
+
const object2 = expectJsonObject(input, path);
|
|
2203
2203
|
try {
|
|
2204
|
-
const canonical = canonicalizePolicyCapability(
|
|
2205
|
-
if (jcsCanonicalize(
|
|
2204
|
+
const canonical = canonicalizePolicyCapability(object2);
|
|
2205
|
+
if (jcsCanonicalize(object2) !== jcsCanonicalize(canonical)) {
|
|
2206
2206
|
throw new SignedObjectSchemaError(`${path} must be canonical PolicyCapability JSON`);
|
|
2207
2207
|
}
|
|
2208
2208
|
} catch (error) {
|
|
@@ -2215,10 +2215,10 @@ function validatePolicyCapability(input, path) {
|
|
|
2215
2215
|
}
|
|
2216
2216
|
}
|
|
2217
2217
|
function validatePolicyCapabilityForSigning(input, path) {
|
|
2218
|
-
const
|
|
2218
|
+
const object2 = expectJsonObject(input, path);
|
|
2219
2219
|
try {
|
|
2220
|
-
const canonical = normalizePolicyCapability(
|
|
2221
|
-
if (jcsCanonicalize(
|
|
2220
|
+
const canonical = normalizePolicyCapability(object2);
|
|
2221
|
+
if (jcsCanonicalize(object2) !== jcsCanonicalize(canonical)) {
|
|
2222
2222
|
throw new SignedObjectSchemaError(`${path} must be strict canonical PolicyCapability JSON`);
|
|
2223
2223
|
}
|
|
2224
2224
|
} catch (error) {
|
|
@@ -2231,43 +2231,43 @@ function validatePolicyCapabilityForSigning(input, path) {
|
|
|
2231
2231
|
}
|
|
2232
2232
|
}
|
|
2233
2233
|
function validateExpression(input, path) {
|
|
2234
|
-
const
|
|
2235
|
-
const keys = Object.keys(
|
|
2234
|
+
const object2 = expectJsonObject(input, path);
|
|
2235
|
+
const keys = Object.keys(object2);
|
|
2236
2236
|
if (keys.length !== 1) {
|
|
2237
2237
|
throw new SignedObjectSchemaError(`${path} must have exactly one expression key`);
|
|
2238
2238
|
}
|
|
2239
2239
|
const key = keys[0];
|
|
2240
2240
|
if (key === "allOf" || key === "anyOf") {
|
|
2241
|
-
const values = requiredArray2(
|
|
2241
|
+
const values = requiredArray2(object2, key, path, 1);
|
|
2242
2242
|
for (let index = 0; index < values.length; index++) {
|
|
2243
2243
|
validateExpression(values[index], `${path}.${key}[${index}]`);
|
|
2244
2244
|
}
|
|
2245
2245
|
return;
|
|
2246
2246
|
}
|
|
2247
2247
|
if (key === "subject") {
|
|
2248
|
-
const subject = expectJsonObject(requiredValue2(
|
|
2248
|
+
const subject = expectJsonObject(requiredValue2(object2, "subject", path), `${path}.subject`);
|
|
2249
2249
|
assertExactKeys2(subject, ["did"], `${path}.subject`);
|
|
2250
2250
|
requiredString2(subject, "did", `${path}.subject`);
|
|
2251
2251
|
return;
|
|
2252
2252
|
}
|
|
2253
2253
|
if (key === "evidence") {
|
|
2254
|
-
validateEvidenceRequirement(requiredValue2(
|
|
2254
|
+
validateEvidenceRequirement(requiredValue2(object2, "evidence", path), `${path}.evidence`);
|
|
2255
2255
|
return;
|
|
2256
2256
|
}
|
|
2257
2257
|
throw new SignedObjectSchemaError(`${path} has unknown expression key ${key}`);
|
|
2258
2258
|
}
|
|
2259
2259
|
function validateEvidenceRequirement(input, path) {
|
|
2260
|
-
const
|
|
2260
|
+
const object2 = expectJsonObject(input, path);
|
|
2261
2261
|
assertExactKeys2(
|
|
2262
|
-
|
|
2262
|
+
object2,
|
|
2263
2263
|
["requirementId", "verifier", "requirements", "authority", "freshness"],
|
|
2264
2264
|
path
|
|
2265
2265
|
);
|
|
2266
|
-
requiredString2(
|
|
2267
|
-
requiredString2(
|
|
2268
|
-
requiredValue2(
|
|
2269
|
-
if (hasOwn2(
|
|
2270
|
-
const authority = expectJsonObject(requiredValue2(
|
|
2266
|
+
requiredString2(object2, "requirementId", path);
|
|
2267
|
+
requiredString2(object2, "verifier", path);
|
|
2268
|
+
requiredValue2(object2, "requirements", path);
|
|
2269
|
+
if (hasOwn2(object2, "authority")) {
|
|
2270
|
+
const authority = expectJsonObject(requiredValue2(object2, "authority", path), `${path}.authority`);
|
|
2271
2271
|
assertExactKeys2(
|
|
2272
2272
|
authority,
|
|
2273
2273
|
["profile", "acceptedIssuers", "allowOwnerAuthorizedIssuer"],
|
|
@@ -2279,35 +2279,35 @@ function validateEvidenceRequirement(input, path) {
|
|
|
2279
2279
|
}
|
|
2280
2280
|
optionalBoolean(authority, "allowOwnerAuthorizedIssuer", `${path}.authority`);
|
|
2281
2281
|
}
|
|
2282
|
-
if (hasOwn2(
|
|
2283
|
-
const freshness = expectJsonObject(requiredValue2(
|
|
2282
|
+
if (hasOwn2(object2, "freshness")) {
|
|
2283
|
+
const freshness = expectJsonObject(requiredValue2(object2, "freshness", path), `${path}.freshness`);
|
|
2284
2284
|
assertExactKeys2(freshness, ["maxStatusAgeSeconds"], `${path}.freshness`);
|
|
2285
2285
|
requiredInteger(freshness, "maxStatusAgeSeconds", `${path}.freshness`, 0);
|
|
2286
2286
|
}
|
|
2287
2287
|
}
|
|
2288
2288
|
function validateGrant(input, path) {
|
|
2289
|
-
const
|
|
2290
|
-
assertExactKeys2(
|
|
2291
|
-
expectConst(requiredString2(
|
|
2292
|
-
requiredInteger(
|
|
2293
|
-
expectOneOf(requiredString2(
|
|
2289
|
+
const object2 = expectJsonObject(input, path);
|
|
2290
|
+
assertExactKeys2(object2, ["output", "maxTtlSeconds", "delegationMode", "revocation"], path);
|
|
2291
|
+
expectConst(requiredString2(object2, "output", path), "portable-delegation", `${path}.output`);
|
|
2292
|
+
requiredInteger(object2, "maxTtlSeconds", path, 1);
|
|
2293
|
+
expectOneOf(requiredString2(object2, "delegationMode", path), [
|
|
2294
2294
|
"terminal",
|
|
2295
2295
|
"attenuable"
|
|
2296
2296
|
], `${path}.delegationMode`);
|
|
2297
|
-
expectOneOf(requiredString2(
|
|
2297
|
+
expectOneOf(requiredString2(object2, "revocation", path), [
|
|
2298
2298
|
"refresh_only",
|
|
2299
2299
|
"active_cutoff"
|
|
2300
2300
|
], `${path}.revocation`);
|
|
2301
2301
|
}
|
|
2302
2302
|
function validateDisclosure(input, path) {
|
|
2303
|
-
const
|
|
2304
|
-
assertExactKeys2(
|
|
2305
|
-
expectOneOf(requiredString2(
|
|
2303
|
+
const object2 = expectJsonObject(input, path);
|
|
2304
|
+
assertExactKeys2(object2, ["denial"], path);
|
|
2305
|
+
expectOneOf(requiredString2(object2, "denial", path), ["none", "code", "debug"], `${path}.denial`);
|
|
2306
2306
|
}
|
|
2307
2307
|
function validateAudit(input, path) {
|
|
2308
|
-
const
|
|
2309
|
-
assertExactKeys2(
|
|
2310
|
-
expectOneOf(requiredString2(
|
|
2308
|
+
const object2 = expectJsonObject(input, path);
|
|
2309
|
+
assertExactKeys2(object2, ["issuance"], path);
|
|
2310
|
+
expectOneOf(requiredString2(object2, "issuance", path), ["off", "security", "full"], `${path}.issuance`);
|
|
2311
2311
|
}
|
|
2312
2312
|
function materialForUnsigned(unsigned, descriptor) {
|
|
2313
2313
|
const jcs = jcsCanonicalize(unsigned);
|
|
@@ -2456,9 +2456,9 @@ function encodeSignatureValue(value, suite) {
|
|
|
2456
2456
|
decodeSignatureValue(encoded, suite);
|
|
2457
2457
|
return encoded;
|
|
2458
2458
|
}
|
|
2459
|
-
function stripOwnIdAndSignature(
|
|
2459
|
+
function stripOwnIdAndSignature(object2, descriptor) {
|
|
2460
2460
|
const output = /* @__PURE__ */ Object.create(null);
|
|
2461
|
-
for (const [key, value] of Object.entries(
|
|
2461
|
+
for (const [key, value] of Object.entries(object2)) {
|
|
2462
2462
|
if (key === descriptor.idField || key === "signature") {
|
|
2463
2463
|
continue;
|
|
2464
2464
|
}
|
|
@@ -2467,8 +2467,8 @@ function stripOwnIdAndSignature(object, descriptor) {
|
|
|
2467
2467
|
return output;
|
|
2468
2468
|
}
|
|
2469
2469
|
function descriptorForUnsigned(input) {
|
|
2470
|
-
const
|
|
2471
|
-
return descriptorForSchema(requiredString2(
|
|
2470
|
+
const object2 = expectJsonObject(normalizeJson(input), "$");
|
|
2471
|
+
return descriptorForSchema(requiredString2(object2, "schema", "$"));
|
|
2472
2472
|
}
|
|
2473
2473
|
function descriptorForSchema(schema) {
|
|
2474
2474
|
if (schema === POLICY_SCHEMA) return DESCRIPTORS.Policy;
|
|
@@ -2482,28 +2482,28 @@ function expectJsonObject(input, path) {
|
|
|
2482
2482
|
}
|
|
2483
2483
|
return input;
|
|
2484
2484
|
}
|
|
2485
|
-
function assertExactKeys2(
|
|
2485
|
+
function assertExactKeys2(object2, allowed, path) {
|
|
2486
2486
|
const allowedSet = new Set(allowed);
|
|
2487
|
-
for (const key of Object.keys(
|
|
2487
|
+
for (const key of Object.keys(object2)) {
|
|
2488
2488
|
if (!allowedSet.has(key)) {
|
|
2489
2489
|
throw new SignedObjectSchemaError(`${path} has unknown field ${key}`);
|
|
2490
2490
|
}
|
|
2491
2491
|
}
|
|
2492
2492
|
}
|
|
2493
|
-
function requiredValue2(
|
|
2494
|
-
if (!hasOwn2(
|
|
2493
|
+
function requiredValue2(object2, key, path) {
|
|
2494
|
+
if (!hasOwn2(object2, key)) {
|
|
2495
2495
|
throw new SignedObjectSchemaError(`${path}.${key} is required`);
|
|
2496
2496
|
}
|
|
2497
|
-
return
|
|
2497
|
+
return object2[key];
|
|
2498
2498
|
}
|
|
2499
|
-
function requiredString2(
|
|
2500
|
-
return requireStringType(requiredValue2(
|
|
2499
|
+
function requiredString2(object2, key, path) {
|
|
2500
|
+
return requireStringType(requiredValue2(object2, key, path), `${path}.${key}`);
|
|
2501
2501
|
}
|
|
2502
|
-
function optionalString(
|
|
2503
|
-
if (!hasOwn2(
|
|
2502
|
+
function optionalString(object2, key, path) {
|
|
2503
|
+
if (!hasOwn2(object2, key)) {
|
|
2504
2504
|
return;
|
|
2505
2505
|
}
|
|
2506
|
-
requireStringType(requiredValue2(
|
|
2506
|
+
requireStringType(requiredValue2(object2, key, path), `${path}.${key}`);
|
|
2507
2507
|
}
|
|
2508
2508
|
function requireStringType(value, path) {
|
|
2509
2509
|
if (typeof value !== "string" || value.length === 0) {
|
|
@@ -2511,16 +2511,16 @@ function requireStringType(value, path) {
|
|
|
2511
2511
|
}
|
|
2512
2512
|
return value;
|
|
2513
2513
|
}
|
|
2514
|
-
function optionalBoolean(
|
|
2515
|
-
if (!hasOwn2(
|
|
2514
|
+
function optionalBoolean(object2, key, path) {
|
|
2515
|
+
if (!hasOwn2(object2, key)) {
|
|
2516
2516
|
return;
|
|
2517
2517
|
}
|
|
2518
|
-
if (typeof requiredValue2(
|
|
2518
|
+
if (typeof requiredValue2(object2, key, path) !== "boolean") {
|
|
2519
2519
|
throw new SignedObjectSchemaError(`${path}.${key} must be a boolean`);
|
|
2520
2520
|
}
|
|
2521
2521
|
}
|
|
2522
|
-
function requiredInteger(
|
|
2523
|
-
const value = requiredValue2(
|
|
2522
|
+
function requiredInteger(object2, key, path, minimum) {
|
|
2523
|
+
const value = requiredValue2(object2, key, path);
|
|
2524
2524
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < minimum) {
|
|
2525
2525
|
throw new SignedObjectSchemaError(
|
|
2526
2526
|
`${path}.${key} must be an integer >= ${minimum}`
|
|
@@ -2528,8 +2528,8 @@ function requiredInteger(object, key, path, minimum) {
|
|
|
2528
2528
|
}
|
|
2529
2529
|
return value;
|
|
2530
2530
|
}
|
|
2531
|
-
function requiredArray2(
|
|
2532
|
-
const value = requiredValue2(
|
|
2531
|
+
function requiredArray2(object2, key, path, minimum) {
|
|
2532
|
+
const value = requiredValue2(object2, key, path);
|
|
2533
2533
|
if (!Array.isArray(value) || value.length < minimum) {
|
|
2534
2534
|
throw new SignedObjectSchemaError(
|
|
2535
2535
|
`${path}.${key} must be an array with at least ${minimum} item(s)`
|
|
@@ -2537,22 +2537,22 @@ function requiredArray2(object, key, path, minimum) {
|
|
|
2537
2537
|
}
|
|
2538
2538
|
return value;
|
|
2539
2539
|
}
|
|
2540
|
-
function requiredStringArray(
|
|
2541
|
-
const values = requiredArray2(
|
|
2540
|
+
function requiredStringArray(object2, key, path, check) {
|
|
2541
|
+
const values = requiredArray2(object2, key, path, 0);
|
|
2542
2542
|
for (let index = 0; index < values.length; index++) {
|
|
2543
2543
|
const itemPath = `${path}.${key}[${index}]`;
|
|
2544
2544
|
const value = requireStringType(values[index], itemPath);
|
|
2545
2545
|
check?.(value, itemPath);
|
|
2546
2546
|
}
|
|
2547
2547
|
}
|
|
2548
|
-
function requiredDateString(
|
|
2549
|
-
assertRfc3339(requiredString2(
|
|
2548
|
+
function requiredDateString(object2, key, path) {
|
|
2549
|
+
assertRfc3339(requiredString2(object2, key, path), `${path}.${key}`);
|
|
2550
2550
|
}
|
|
2551
|
-
function optionalDateString(
|
|
2552
|
-
if (!hasOwn2(
|
|
2551
|
+
function optionalDateString(object2, key, path) {
|
|
2552
|
+
if (!hasOwn2(object2, key)) {
|
|
2553
2553
|
return;
|
|
2554
2554
|
}
|
|
2555
|
-
assertRfc3339(requiredString2(
|
|
2555
|
+
assertRfc3339(requiredString2(object2, key, path), `${path}.${key}`);
|
|
2556
2556
|
}
|
|
2557
2557
|
function assertRfc3339(value, path) {
|
|
2558
2558
|
const match = value.match(
|
|
@@ -2584,8 +2584,8 @@ function expectOneOf(actual, allowed, path) {
|
|
|
2584
2584
|
}
|
|
2585
2585
|
throw new SignedObjectSchemaError(`${path} has unsupported value ${actual}`);
|
|
2586
2586
|
}
|
|
2587
|
-
function hasOwn2(
|
|
2588
|
-
return objectHasOwn3(
|
|
2587
|
+
function hasOwn2(object2, key) {
|
|
2588
|
+
return objectHasOwn3(object2, key);
|
|
2589
2589
|
}
|
|
2590
2590
|
function assertSupportedSignatureSuite(suite) {
|
|
2591
2591
|
if (suite !== ED25519_JCS_SIGNATURE_SUITE && suite !== EIP191_JCS_SIGNATURE_SUITE) {
|
|
@@ -2664,13 +2664,13 @@ function base64UrlDecode(value) {
|
|
|
2664
2664
|
return decoded;
|
|
2665
2665
|
}
|
|
2666
2666
|
function hexToBytes(value) {
|
|
2667
|
-
const
|
|
2668
|
-
if (
|
|
2667
|
+
const hex2 = value.slice(2);
|
|
2668
|
+
if (hex2.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex2)) {
|
|
2669
2669
|
throw new SignatureMaterialError("hex signature must have even length");
|
|
2670
2670
|
}
|
|
2671
|
-
const output = new Uint8Array(
|
|
2671
|
+
const output = new Uint8Array(hex2.length / 2);
|
|
2672
2672
|
for (let index = 0; index < output.length; index++) {
|
|
2673
|
-
output[index] = Number.parseInt(
|
|
2673
|
+
output[index] = Number.parseInt(hex2.slice(index * 2, index * 2 + 2), 16);
|
|
2674
2674
|
}
|
|
2675
2675
|
return output;
|
|
2676
2676
|
}
|
|
@@ -3021,9 +3021,9 @@ function expectPolicyEngineRecord(input) {
|
|
|
3021
3021
|
);
|
|
3022
3022
|
}
|
|
3023
3023
|
}
|
|
3024
|
-
function assertExactKeys3(
|
|
3024
|
+
function assertExactKeys3(object2, allowed, path) {
|
|
3025
3025
|
const allowedSet = new Set(allowed);
|
|
3026
|
-
for (const key of Object.keys(
|
|
3026
|
+
for (const key of Object.keys(object2)) {
|
|
3027
3027
|
if (!allowedSet.has(key)) {
|
|
3028
3028
|
throw new PolicyAuthoringError(
|
|
3029
3029
|
"policy-authoring-unknown-key",
|
|
@@ -3032,17 +3032,17 @@ function assertExactKeys3(object, allowed, path) {
|
|
|
3032
3032
|
}
|
|
3033
3033
|
}
|
|
3034
3034
|
}
|
|
3035
|
-
function requiredValue3(
|
|
3036
|
-
if (!hasOwn3(
|
|
3035
|
+
function requiredValue3(object2, key, path) {
|
|
3036
|
+
if (!hasOwn3(object2, key)) {
|
|
3037
3037
|
throw new PolicyAuthoringError(
|
|
3038
3038
|
"policy-authoring-malformed",
|
|
3039
3039
|
`${path}.${key} is required`
|
|
3040
3040
|
);
|
|
3041
3041
|
}
|
|
3042
|
-
return
|
|
3042
|
+
return object2[key];
|
|
3043
3043
|
}
|
|
3044
|
-
function requiredString3(
|
|
3045
|
-
const value = requiredValue3(
|
|
3044
|
+
function requiredString3(object2, key, path) {
|
|
3045
|
+
const value = requiredValue3(object2, key, path);
|
|
3046
3046
|
if (typeof value !== "string" || value.length === 0) {
|
|
3047
3047
|
throw new PolicyAuthoringError(
|
|
3048
3048
|
"policy-authoring-malformed",
|
|
@@ -3051,11 +3051,11 @@ function requiredString3(object, key, path) {
|
|
|
3051
3051
|
}
|
|
3052
3052
|
return value;
|
|
3053
3053
|
}
|
|
3054
|
-
function fieldString(
|
|
3055
|
-
if (!hasOwn3(
|
|
3054
|
+
function fieldString(object2, key, path, code2) {
|
|
3055
|
+
if (!hasOwn3(object2, key)) {
|
|
3056
3056
|
throw new PolicyAuthoringError(code2, `${path}.${key} is required`);
|
|
3057
3057
|
}
|
|
3058
|
-
const value =
|
|
3058
|
+
const value = object2[key];
|
|
3059
3059
|
if (typeof value !== "string" || value.length === 0) {
|
|
3060
3060
|
throw new PolicyAuthoringError(
|
|
3061
3061
|
code2,
|
|
@@ -3064,8 +3064,8 @@ function fieldString(object, key, path, code2) {
|
|
|
3064
3064
|
}
|
|
3065
3065
|
return value;
|
|
3066
3066
|
}
|
|
3067
|
-
function requiredObject(
|
|
3068
|
-
const value = requiredValue3(
|
|
3067
|
+
function requiredObject(object2, key, path) {
|
|
3068
|
+
const value = requiredValue3(object2, key, path);
|
|
3069
3069
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
3070
3070
|
throw new PolicyAuthoringError(
|
|
3071
3071
|
"policy-authoring-malformed",
|
|
@@ -3074,8 +3074,8 @@ function requiredObject(object, key, path) {
|
|
|
3074
3074
|
}
|
|
3075
3075
|
return value;
|
|
3076
3076
|
}
|
|
3077
|
-
function requiredArray3(
|
|
3078
|
-
const value = requiredValue3(
|
|
3077
|
+
function requiredArray3(object2, key, path) {
|
|
3078
|
+
const value = requiredValue3(object2, key, path);
|
|
3079
3079
|
if (!Array.isArray(value)) {
|
|
3080
3080
|
throw new PolicyAuthoringError(
|
|
3081
3081
|
"policy-authoring-malformed",
|
|
@@ -3084,8 +3084,8 @@ function requiredArray3(object, key, path) {
|
|
|
3084
3084
|
}
|
|
3085
3085
|
return value;
|
|
3086
3086
|
}
|
|
3087
|
-
function requiredStringArray2(
|
|
3088
|
-
const values = requiredArray3(
|
|
3087
|
+
function requiredStringArray2(object2, key, path) {
|
|
3088
|
+
const values = requiredArray3(object2, key, path);
|
|
3089
3089
|
return values.map((value, index) => {
|
|
3090
3090
|
if (typeof value !== "string" || value.length === 0) {
|
|
3091
3091
|
throw new PolicyAuthoringError(
|
|
@@ -3182,19 +3182,686 @@ function parseStrictRfc3339(value, path) {
|
|
|
3182
3182
|
var objectHasOwn4 = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
|
|
3183
3183
|
Object.prototype.hasOwnProperty
|
|
3184
3184
|
);
|
|
3185
|
-
function hasOwn3(
|
|
3186
|
-
return objectHasOwn4(
|
|
3185
|
+
function hasOwn3(object2, key) {
|
|
3186
|
+
return objectHasOwn4(object2, key);
|
|
3187
|
+
}
|
|
3188
|
+
|
|
3189
|
+
// src/policy/unified.ts
|
|
3190
|
+
import { sha256 as sha2564 } from "@noble/hashes/sha256";
|
|
3191
|
+
import { blake3 } from "@noble/hashes/blake3";
|
|
3192
|
+
import { ed25519 as ed255192 } from "@noble/curves/ed25519";
|
|
3193
|
+
import { z } from "zod";
|
|
3194
|
+
var POLICY_V1_SCHEMA = "xyz.tinycloud.policy/policy/v1";
|
|
3195
|
+
var POLICY_CAPABILITY_V1_SCHEMA = "xyz.tinycloud.policy/capability/v1";
|
|
3196
|
+
var POLICY_ENFORCEMENT_DELEGATION_V2_SCHEMA = "xyz.tinycloud.policy/enforcement-delegation/v2";
|
|
3197
|
+
var ATTESTED_ENFORCER_BINDING_V2_SCHEMA = "xyz.tinycloud.policy/attested-enforcer/v2";
|
|
3198
|
+
var ROOT_STATUS_CHECKPOINT_V1_SCHEMA = "xyz.tinycloud.policy/root-status/v1";
|
|
3199
|
+
var ROOT_REVOCATION_V1_SCHEMA = "xyz.tinycloud.policy/root-revocation/v1";
|
|
3200
|
+
var POLICY_SESSION_UCAN_V1_PROFILE = "policy-session-ucan/v1";
|
|
3201
|
+
var POLICY_V1_DOMAIN = "xyz.tinycloud.policy/policy/v1\0";
|
|
3202
|
+
var POLICY_CAPABILITY_V1_DOMAIN = "xyz.tinycloud.policy/PolicyCapability/v1\0";
|
|
3203
|
+
var CONTENT_SOURCE_V1_DOMAIN = "xyz.tinycloud.policy/ContentSource/v1\0";
|
|
3204
|
+
var NATIVE_PROJECTION_V1_DOMAIN = "xyz.tinycloud.policy/NativeProjection/v1\0";
|
|
3205
|
+
var ROOT_STATUS_V1_DOMAIN = "xyz.tinycloud.policy/RootStatusCheckpoint/v1\0";
|
|
3206
|
+
var ROOT_STATUS_RENEWAL_V1_DOMAIN = "xyz.tinycloud.policy/RootStatusRenewal/v1\0";
|
|
3207
|
+
var ROOT_REVOCATION_V1_DOMAIN = "xyz.tinycloud.policy/RootRevocation/v1\0";
|
|
3208
|
+
var LAST_V2_CREATE_AT = "2026-09-30T00:00:00Z";
|
|
3209
|
+
var MAX_LEGACY_ENVELOPE_EXPIRES_AT = "2026-12-29T00:00:00Z";
|
|
3210
|
+
var LAST_V2_READ_AT = "2027-01-05T00:00:00Z";
|
|
3211
|
+
async function requestPolicyChallengeV3(input) {
|
|
3212
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3213
|
+
const response = await fetchFn(new URL("/share/v3/policy/challenges", input.nodeOrigin), {
|
|
3214
|
+
method: "POST",
|
|
3215
|
+
redirect: "error",
|
|
3216
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3217
|
+
body: JSON.stringify({ policyCid: input.policyCid, recipientDid: input.recipientDid, requestedCapabilities: input.requestedCapabilities.map(normalizeUnifiedPolicyCapability) })
|
|
3218
|
+
});
|
|
3219
|
+
if (!response.ok) throw new Error(`policy challenge rejected (${response.status})`);
|
|
3220
|
+
const value = object(await response.json(), "policy challenge");
|
|
3221
|
+
if (typeof value.challengeId !== "string" || typeof value.nonce !== "string" || value.policyCid !== input.policyCid || value.recipientDid !== input.recipientDid)
|
|
3222
|
+
throw new Error("policy challenge binding is invalid");
|
|
3223
|
+
return value;
|
|
3224
|
+
}
|
|
3225
|
+
async function mintPolicySessionV3(input) {
|
|
3226
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3227
|
+
const challenge = input.challenge ?? await requestPolicyChallengeV3(input);
|
|
3228
|
+
if (challenge.policyCid !== input.policyCid || challenge.recipientDid !== input.recipientDid)
|
|
3229
|
+
throw new Error("policy challenge binding is invalid");
|
|
3230
|
+
const response = await fetchFn(new URL("/share/v3/policy/delegations", input.nodeOrigin), {
|
|
3231
|
+
method: "POST",
|
|
3232
|
+
redirect: "error",
|
|
3233
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3234
|
+
body: JSON.stringify({ policyCid: input.policyCid, challengeId: challenge.challengeId, nonce: challenge.nonce, claim: input.claim, presentation: input.presentation })
|
|
3235
|
+
});
|
|
3236
|
+
if (!response.ok) throw new Error(`policy delegation rejected (${response.status})`);
|
|
3237
|
+
const value = object(await response.json(), "policy delegation");
|
|
3238
|
+
if (value.admitted !== true || typeof value.sessionCid !== "string" || typeof value.authorization !== "string")
|
|
3239
|
+
throw new Error("policy delegation response is invalid");
|
|
3240
|
+
const session = parsePolicySessionUcan(value.authorization, [input.policyRootCid, input.enforcementRootCid]);
|
|
3241
|
+
const expectedAttenuation = compactAttenuationForPolicyCapabilities(input.requestedCapabilities);
|
|
3242
|
+
if (session.cid !== value.sessionCid || session.aud !== input.recipientDid || session.fact.policyCid !== input.policyCid || session.fact.recipientDid !== input.recipientDid || session.fact.policyDelegationCid !== input.policyRootCid || session.fact.enforcementDelegationCid !== input.enforcementRootCid || jcsCanonicalize(session.att) !== jcsCanonicalize(expectedAttenuation) || Object.entries(input.expectedFacts ?? {}).some(([key, expected]) => session.fact[key] !== expected))
|
|
3243
|
+
throw new Error("policy delegation signed binding is invalid");
|
|
3244
|
+
return session;
|
|
3245
|
+
}
|
|
3246
|
+
function compactAttenuationForPolicyCapabilities(input) {
|
|
3247
|
+
const attenuation = {};
|
|
3248
|
+
for (const raw of input) {
|
|
3249
|
+
const capability = normalizeUnifiedPolicyCapability(raw);
|
|
3250
|
+
if (attenuation[capability.resource] !== void 0)
|
|
3251
|
+
throw new Error("policy capabilities contain a duplicate resource");
|
|
3252
|
+
attenuation[capability.resource] = capability.kind === "encryption" ? { [capability.action]: [{}] } : Object.fromEntries(capability.actions.map((action) => [action, [{
|
|
3253
|
+
type: "xyz.tinycloud.resource/selector",
|
|
3254
|
+
kind: capability.selector,
|
|
3255
|
+
value: capability.resource
|
|
3256
|
+
}]]));
|
|
3257
|
+
}
|
|
3258
|
+
return attenuation;
|
|
3259
|
+
}
|
|
3260
|
+
function verifyPolicyRootStatusCheckpointV3(input) {
|
|
3261
|
+
const checkpoint = input.checkpoint;
|
|
3262
|
+
const allowed = /* @__PURE__ */ new Set(["schema", "targetCid", "targetRole", "ownerDid", "nodeAudience", "state", "sequence", "checkedAt", "freshUntil", "revokedAt", "revocationCid", "previousCheckpointDigestHex", "issuerDid", "signature"]);
|
|
3263
|
+
if (Object.keys(checkpoint).some((key) => !allowed.has(key)) || checkpoint.schema !== ROOT_STATUS_CHECKPOINT_V1_SCHEMA || checkpoint.targetCid !== input.rootCid || checkpoint.targetRole !== "policy-authority" && checkpoint.targetRole !== "policy-enforcement" || checkpoint.state !== "active" && checkpoint.state !== "revoked" || typeof checkpoint.ownerDid !== "string" || typeof checkpoint.nodeAudience !== "string" || checkpoint.issuerDid !== checkpoint.nodeAudience || input.expectedNodeAudience !== void 0 && checkpoint.nodeAudience !== input.expectedNodeAudience || !Number.isInteger(checkpoint.sequence) || checkpoint.sequence < 1 || typeof checkpoint.checkedAt !== "string" || typeof checkpoint.freshUntil !== "string") return false;
|
|
3264
|
+
const checkedAt = Date.parse(checkpoint.checkedAt);
|
|
3265
|
+
const freshUntil = Date.parse(checkpoint.freshUntil);
|
|
3266
|
+
const now = (input.now ?? /* @__PURE__ */ new Date()).getTime();
|
|
3267
|
+
if (!Number.isFinite(checkedAt) || !Number.isFinite(freshUntil) || freshUntil < now || freshUntil <= checkedAt || freshUntil - checkedAt > 3e5) return false;
|
|
3268
|
+
if (checkpoint.sequence === 1 !== (checkpoint.previousCheckpointDigestHex === void 0)) return false;
|
|
3269
|
+
if (checkpoint.sequence !== 1 && (typeof checkpoint.previousCheckpointDigestHex !== "string" || !/^[0-9a-f]{64}$/.test(checkpoint.previousCheckpointDigestHex))) return false;
|
|
3270
|
+
if (checkpoint.state === "active" && (checkpoint.revokedAt !== void 0 || checkpoint.revocationCid !== void 0)) return false;
|
|
3271
|
+
if (checkpoint.state === "revoked" && (typeof checkpoint.revokedAt !== "string" || typeof checkpoint.revocationCid !== "string")) return false;
|
|
3272
|
+
const signature = checkpoint.signature;
|
|
3273
|
+
if (!isRecordValue(signature) || Object.keys(signature).length !== 3 || signature.suite !== "Ed25519" || signature.signerDid !== checkpoint.issuerDid || typeof signature.value !== "string") return false;
|
|
3274
|
+
try {
|
|
3275
|
+
const principal = checkpoint.issuerDid.split("#", 1)[0];
|
|
3276
|
+
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
3277
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1) return false;
|
|
3278
|
+
const unsigned = { ...checkpoint };
|
|
3279
|
+
delete unsigned.signature;
|
|
3280
|
+
return ed255192.verify(
|
|
3281
|
+
decodeBase64Url(signature.value),
|
|
3282
|
+
sha2564(new TextEncoder().encode(ROOT_STATUS_V1_DOMAIN + jcsCanonicalize(unsigned))),
|
|
3283
|
+
didMaterial.slice(2)
|
|
3284
|
+
);
|
|
3285
|
+
} catch {
|
|
3286
|
+
return false;
|
|
3287
|
+
}
|
|
3288
|
+
}
|
|
3289
|
+
async function getPolicyRootStatusV3(input) {
|
|
3290
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3291
|
+
const response = await fetchFn(new URL(`/share/v3/policy/status/${encodeURIComponent(input.rootCid)}`, input.nodeOrigin), {
|
|
3292
|
+
method: "GET",
|
|
3293
|
+
redirect: "error",
|
|
3294
|
+
headers: { accept: "application/json" }
|
|
3295
|
+
});
|
|
3296
|
+
if (!response.ok) throw new Error(`policy root status rejected (${response.status})`);
|
|
3297
|
+
const value = object(await response.json(), "policy root status");
|
|
3298
|
+
const checkpoint = object(value.checkpoint, "policy root checkpoint");
|
|
3299
|
+
if (value.rootCid !== input.rootCid || value.state !== "active" && value.state !== "revoked" || value.state !== checkpoint.state || !verifyPolicyRootStatusCheckpointV3({ rootCid: input.rootCid, checkpoint, expectedNodeAudience: input.expectedNodeAudience, now: input.now }))
|
|
3300
|
+
throw new Error("policy root status binding is invalid");
|
|
3301
|
+
const revocation = value.revocation === void 0 ? void 0 : object(value.revocation, "policy root revocation");
|
|
3302
|
+
if (value.state === "revoked" !== (revocation !== void 0) || revocation !== void 0 && !verifyPolicyRootRevocationV3({
|
|
3303
|
+
rootCid: input.rootCid,
|
|
3304
|
+
checkpoint,
|
|
3305
|
+
revocation,
|
|
3306
|
+
expectedEnforcerDid: input.expectedEnforcerDid
|
|
3307
|
+
})) throw new Error("policy root status revocation evidence is invalid");
|
|
3308
|
+
return { rootCid: input.rootCid, state: value.state, checkpoint, ...revocation === void 0 ? {} : { revocation } };
|
|
3309
|
+
}
|
|
3310
|
+
function verifyPolicyRootRevocationV3(input) {
|
|
3311
|
+
const value = input.revocation;
|
|
3312
|
+
const allowed = ["schema", "targetCid", "targetRole", "ownerDid", "nodeAudience", "revokedAt", "reason", "issuerDid", "signature"];
|
|
3313
|
+
if (Object.keys(value).length !== allowed.length || Object.keys(value).some((key) => !allowed.includes(key)) || value.schema !== ROOT_REVOCATION_V1_SCHEMA || value.targetCid !== input.rootCid || value.targetRole !== input.checkpoint.targetRole || value.ownerDid !== input.checkpoint.ownerDid || value.nodeAudience !== input.checkpoint.nodeAudience || value.revokedAt !== input.checkpoint.revokedAt || typeof value.reason !== "string" || value.reason.length === 0 || typeof value.issuerDid !== "string") return false;
|
|
3314
|
+
const authorized = value.issuerDid === value.ownerDid || value.targetRole === "policy-enforcement" && value.issuerDid === input.expectedEnforcerDid;
|
|
3315
|
+
if (!authorized) return false;
|
|
3316
|
+
const signature = value.signature;
|
|
3317
|
+
if (!isRecordValue(signature) || Object.keys(signature).length !== 3 || signature.suite !== "Ed25519" || signature.signerDid !== value.issuerDid || typeof signature.value !== "string") return false;
|
|
3318
|
+
try {
|
|
3319
|
+
const principal = value.issuerDid.split("#", 1)[0];
|
|
3320
|
+
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
3321
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1) return false;
|
|
3322
|
+
const unsigned = { ...value };
|
|
3323
|
+
delete unsigned.signature;
|
|
3324
|
+
const digest2 = sha2564(new TextEncoder().encode(ROOT_REVOCATION_V1_DOMAIN + jcsCanonicalize(unsigned)));
|
|
3325
|
+
return input.checkpoint.revocationCid === hex(digest2) && ed255192.verify(decodeBase64Url(signature.value), digest2, didMaterial.slice(2));
|
|
3326
|
+
} catch {
|
|
3327
|
+
return false;
|
|
3328
|
+
}
|
|
3329
|
+
}
|
|
3330
|
+
async function renewPolicyRootStatusV3(input) {
|
|
3331
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3332
|
+
const current = await getPolicyRootStatusV3({ nodeOrigin: input.nodeOrigin, rootCid: input.rootCid, expectedNodeAudience: input.nodeAudience, now: input.now, fetch: fetchFn });
|
|
3333
|
+
if (current.state !== "active" || current.checkpoint.ownerDid !== input.ownerDid || current.checkpoint.nodeAudience !== input.nodeAudience || current.checkpoint.state !== "active" || !Number.isInteger(current.checkpoint.sequence))
|
|
3334
|
+
throw new Error("policy root status cannot be renewed");
|
|
3335
|
+
const currentUnsigned = { ...current.checkpoint };
|
|
3336
|
+
delete currentUnsigned.signature;
|
|
3337
|
+
const previousCheckpointDigestHex = hex(sha2564(new TextEncoder().encode(ROOT_STATUS_V1_DOMAIN + jcsCanonicalize(currentUnsigned))));
|
|
3338
|
+
const unsigned = {
|
|
3339
|
+
schema: "xyz.tinycloud.policy/root-status-renewal/v1",
|
|
3340
|
+
targetCid: input.rootCid,
|
|
3341
|
+
ownerDid: input.ownerDid,
|
|
3342
|
+
nodeAudience: input.nodeAudience,
|
|
3343
|
+
issuedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
3344
|
+
nonce: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
3345
|
+
sequence: current.checkpoint.sequence + 1,
|
|
3346
|
+
previousCheckpointDigestHex
|
|
3347
|
+
};
|
|
3348
|
+
const signature = await input.sign(sha2564(new TextEncoder().encode(ROOT_STATUS_RENEWAL_V1_DOMAIN + jcsCanonicalize(unsigned))));
|
|
3349
|
+
if (signature.length !== 64) throw new Error("policy root renewal signature must be Ed25519");
|
|
3350
|
+
const response = await fetchFn(new URL("/share/v3/policy/status", input.nodeOrigin), {
|
|
3351
|
+
method: "POST",
|
|
3352
|
+
redirect: "error",
|
|
3353
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3354
|
+
body: JSON.stringify({ rootCid: input.rootCid, renewal: { ...unsigned, signature: { suite: "Ed25519", signerDid: input.ownerDid, value: encodeBase64Url(signature) } } })
|
|
3355
|
+
});
|
|
3356
|
+
if (!response.ok) throw new Error(`policy root renewal rejected (${response.status})`);
|
|
3357
|
+
return object(await response.json(), "policy root renewal");
|
|
3358
|
+
}
|
|
3359
|
+
async function revokePolicyRootV3(input) {
|
|
3360
|
+
if (input.reason.length === 0) throw new Error("policy root revocation reason is required");
|
|
3361
|
+
const unsigned = {
|
|
3362
|
+
schema: ROOT_REVOCATION_V1_SCHEMA,
|
|
3363
|
+
targetCid: input.rootCid,
|
|
3364
|
+
targetRole: input.targetRole,
|
|
3365
|
+
ownerDid: input.ownerDid,
|
|
3366
|
+
nodeAudience: input.nodeAudience,
|
|
3367
|
+
revokedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
3368
|
+
reason: input.reason,
|
|
3369
|
+
issuerDid: input.issuerDid
|
|
3370
|
+
};
|
|
3371
|
+
const signature = await input.sign(sha2564(new TextEncoder().encode(ROOT_REVOCATION_V1_DOMAIN + jcsCanonicalize(unsigned))));
|
|
3372
|
+
if (signature.length !== 64) throw new Error("policy root revocation signature must be Ed25519");
|
|
3373
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3374
|
+
const response = await fetchFn(new URL("/revoke", input.nodeOrigin), {
|
|
3375
|
+
method: "POST",
|
|
3376
|
+
redirect: "error",
|
|
3377
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3378
|
+
body: JSON.stringify({ revocation: { ...unsigned, signature: { suite: "Ed25519", signerDid: input.issuerDid, value: encodeBase64Url(signature) } } })
|
|
3379
|
+
});
|
|
3380
|
+
if (!response.ok) throw new Error(`policy root revocation rejected (${response.status})`);
|
|
3381
|
+
return object(await response.json(), "policy root revocation");
|
|
3382
|
+
}
|
|
3383
|
+
var POLICY_SESSION_FACT_KEYS = [
|
|
3384
|
+
"profile",
|
|
3385
|
+
"ownerDid",
|
|
3386
|
+
"policyId",
|
|
3387
|
+
"policyDigestHex",
|
|
3388
|
+
"policyCid",
|
|
3389
|
+
"policyDelegationCid",
|
|
3390
|
+
"enforcementDelegationCid",
|
|
3391
|
+
"contentSourceDigestHex",
|
|
3392
|
+
"capabilityCeilingHashHex",
|
|
3393
|
+
"nativeProjectionHashHex",
|
|
3394
|
+
"enforcerDid",
|
|
3395
|
+
"nodeAudience",
|
|
3396
|
+
"recipientDid",
|
|
3397
|
+
"challengeId",
|
|
3398
|
+
"claimDigestHex",
|
|
3399
|
+
"claimJti",
|
|
3400
|
+
"vpDigestHex",
|
|
3401
|
+
"credentialEvidenceDigestHex",
|
|
3402
|
+
"decisionContextDigestHex",
|
|
3403
|
+
"issuanceAuditDigestHex",
|
|
3404
|
+
"remainingRedelegationDepth"
|
|
3405
|
+
];
|
|
3406
|
+
var KV_ACTIONS = /* @__PURE__ */ new Set([
|
|
3407
|
+
"tinycloud.kv/get",
|
|
3408
|
+
"tinycloud.kv/list",
|
|
3409
|
+
"tinycloud.kv/metadata",
|
|
3410
|
+
"tinycloud.kv/put"
|
|
3411
|
+
]);
|
|
3412
|
+
function object(value, label) {
|
|
3413
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
3414
|
+
throw new Error(`${label} must be an object`);
|
|
3415
|
+
}
|
|
3416
|
+
return value;
|
|
3417
|
+
}
|
|
3418
|
+
function exactKeys(value, allowed, label) {
|
|
3419
|
+
const keys = new Set(allowed);
|
|
3420
|
+
if (Object.keys(value).some((key) => !keys.has(key)))
|
|
3421
|
+
throw new Error(`${label} contains an unknown field`);
|
|
3422
|
+
}
|
|
3423
|
+
function nonEmptyString(value, label) {
|
|
3424
|
+
if (typeof value !== "string" || value.length === 0)
|
|
3425
|
+
throw new Error(`${label} must be a non-empty string`);
|
|
3426
|
+
return value;
|
|
3427
|
+
}
|
|
3428
|
+
function parseKvResource(resource) {
|
|
3429
|
+
const match = /^tinycloud:\/\/([^/]+)\/kv\/(.+)$/.exec(resource);
|
|
3430
|
+
if (!match || match[1].includes(":") || match[1].includes("?") || match[1].includes("#") || match[1].includes("%") || match[2].startsWith("/") || match[2].endsWith("/") || match[2].includes("//") || match[2].split("/").some((part) => part === "." || part === ".." || part.length === 0)) {
|
|
3431
|
+
throw new Error("KV resource is not canonical");
|
|
3432
|
+
}
|
|
3433
|
+
return { space: match[1], path: match[2] };
|
|
3434
|
+
}
|
|
3435
|
+
function parseEncryptionResource(resource) {
|
|
3436
|
+
if (!resource.startsWith("urn:tinycloud:encryption:")) throw new Error("encryption capability is invalid");
|
|
3437
|
+
const rest = resource.slice("urn:tinycloud:encryption:".length);
|
|
3438
|
+
const separator = rest.lastIndexOf(":");
|
|
3439
|
+
const ownerDid = separator < 0 ? "" : rest.slice(0, separator);
|
|
3440
|
+
const network = separator < 0 ? "" : rest.slice(separator + 1);
|
|
3441
|
+
if (!ownerDid.startsWith("did:") || network.length === 0 || network.includes(":") || network.includes("/") || network.includes("%") || network.includes("?") || network.includes("#")) {
|
|
3442
|
+
throw new Error("encryption capability is invalid");
|
|
3443
|
+
}
|
|
3444
|
+
}
|
|
3445
|
+
function normalizeUnifiedPolicyCapability(input) {
|
|
3446
|
+
const value = object(input, "capability");
|
|
3447
|
+
const kind = nonEmptyString(value.kind, "capability.kind");
|
|
3448
|
+
if (kind === "kv") {
|
|
3449
|
+
exactKeys(
|
|
3450
|
+
value,
|
|
3451
|
+
["kind", "resource", "selector", "actions"],
|
|
3452
|
+
"KV capability"
|
|
3453
|
+
);
|
|
3454
|
+
const resource = nonEmptyString(value.resource, "capability.resource");
|
|
3455
|
+
parseKvResource(resource);
|
|
3456
|
+
if (value.selector !== "exact" && value.selector !== "prefix")
|
|
3457
|
+
throw new Error("capability.selector is invalid");
|
|
3458
|
+
if (!Array.isArray(value.actions) || value.actions.length === 0)
|
|
3459
|
+
throw new Error("capability.actions is invalid");
|
|
3460
|
+
const actions = value.actions.map(
|
|
3461
|
+
(action) => nonEmptyString(action, "capability.actions[]")
|
|
3462
|
+
);
|
|
3463
|
+
if (new Set(actions).size !== actions.length || actions.some((action) => !KV_ACTIONS.has(action)))
|
|
3464
|
+
throw new Error("capability.actions is invalid");
|
|
3465
|
+
return {
|
|
3466
|
+
kind: "kv",
|
|
3467
|
+
resource,
|
|
3468
|
+
selector: value.selector,
|
|
3469
|
+
actions: [...actions].sort()
|
|
3470
|
+
};
|
|
3471
|
+
}
|
|
3472
|
+
if (kind === "encryption") {
|
|
3473
|
+
exactKeys(value, ["kind", "resource", "action"], "encryption capability");
|
|
3474
|
+
const resource = nonEmptyString(value.resource, "capability.resource");
|
|
3475
|
+
if (value.action !== "tinycloud.encryption/decrypt")
|
|
3476
|
+
throw new Error("encryption capability is invalid");
|
|
3477
|
+
parseEncryptionResource(resource);
|
|
3478
|
+
return {
|
|
3479
|
+
kind: "encryption",
|
|
3480
|
+
resource,
|
|
3481
|
+
action: "tinycloud.encryption/decrypt"
|
|
3482
|
+
};
|
|
3483
|
+
}
|
|
3484
|
+
throw new Error("capability.kind is invalid");
|
|
3485
|
+
}
|
|
3486
|
+
function canonicalizeUnifiedPolicyCapability(input) {
|
|
3487
|
+
return normalizeUnifiedPolicyCapability(input);
|
|
3488
|
+
}
|
|
3489
|
+
function unifiedPolicyCapabilityDigestHex(input) {
|
|
3490
|
+
return hex(
|
|
3491
|
+
sha2564(
|
|
3492
|
+
new TextEncoder().encode(
|
|
3493
|
+
POLICY_CAPABILITY_V1_DOMAIN + jcsCanonicalize(normalizeUnifiedPolicyCapability(input))
|
|
3494
|
+
)
|
|
3495
|
+
)
|
|
3496
|
+
);
|
|
3497
|
+
}
|
|
3498
|
+
function unifiedPolicyCapabilityContains(authorityInput, requestedInput) {
|
|
3499
|
+
try {
|
|
3500
|
+
const authority = normalizeUnifiedPolicyCapability(authorityInput);
|
|
3501
|
+
const requested = normalizeUnifiedPolicyCapability(requestedInput);
|
|
3502
|
+
if (authority.kind !== requested.kind) return false;
|
|
3503
|
+
if (authority.kind === "encryption" && requested.kind === "encryption")
|
|
3504
|
+
return authority.resource === requested.resource && authority.action === requested.action;
|
|
3505
|
+
if (authority.kind !== "kv" || requested.kind !== "kv") return false;
|
|
3506
|
+
const { resource: authorized } = authority;
|
|
3507
|
+
const { resource: requestedResource } = requested;
|
|
3508
|
+
const pathContained = authority.selector === "exact" ? authorized === requestedResource : authorized === requestedResource || requestedResource.startsWith(`${authorized}/`);
|
|
3509
|
+
if (!pathContained || authority.selector === "exact" && requested.selector === "prefix")
|
|
3510
|
+
return false;
|
|
3511
|
+
return requested.actions.every(
|
|
3512
|
+
(action) => authority.actions.includes(action)
|
|
3513
|
+
);
|
|
3514
|
+
} catch {
|
|
3515
|
+
return false;
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
3518
|
+
function projectUnifiedPolicyCapability(input) {
|
|
3519
|
+
const capability = normalizeUnifiedPolicyCapability(input);
|
|
3520
|
+
if (capability.kind === "encryption") {
|
|
3521
|
+
return {
|
|
3522
|
+
service: "tinycloud.encryption",
|
|
3523
|
+
space: capability.resource,
|
|
3524
|
+
path: capability.resource,
|
|
3525
|
+
actions: [capability.action]
|
|
3526
|
+
};
|
|
3527
|
+
}
|
|
3528
|
+
const { space, path } = parseKvResource(capability.resource);
|
|
3529
|
+
return {
|
|
3530
|
+
service: "tinycloud.kv",
|
|
3531
|
+
space,
|
|
3532
|
+
path,
|
|
3533
|
+
actions: [...capability.actions],
|
|
3534
|
+
caveat: {
|
|
3535
|
+
type: "xyz.tinycloud.resource/selector",
|
|
3536
|
+
kind: capability.selector,
|
|
3537
|
+
value: capability.resource
|
|
3538
|
+
}
|
|
3539
|
+
};
|
|
3540
|
+
}
|
|
3541
|
+
function projectUnifiedPolicyCapabilities(input) {
|
|
3542
|
+
return input.map(projectUnifiedPolicyCapability).sort((left, right) => {
|
|
3543
|
+
const a = jcsCanonicalize(left);
|
|
3544
|
+
const b = jcsCanonicalize(right);
|
|
3545
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
3546
|
+
});
|
|
3547
|
+
}
|
|
3548
|
+
function unifiedNativeProjectionHashHex(input) {
|
|
3549
|
+
return hex(
|
|
3550
|
+
sha2564(
|
|
3551
|
+
new TextEncoder().encode(
|
|
3552
|
+
NATIVE_PROJECTION_V1_DOMAIN + jcsCanonicalize(projectUnifiedPolicyCapabilities(input))
|
|
3553
|
+
)
|
|
3554
|
+
)
|
|
3555
|
+
);
|
|
3556
|
+
}
|
|
3557
|
+
function unifiedPolicyCapabilityFromNative(input) {
|
|
3558
|
+
const value = object(input, "native capability");
|
|
3559
|
+
exactKeys(
|
|
3560
|
+
value,
|
|
3561
|
+
["service", "space", "path", "actions", "caveat"],
|
|
3562
|
+
"native capability"
|
|
3563
|
+
);
|
|
3564
|
+
const service = nonEmptyString(value.service, "native.service");
|
|
3565
|
+
const actions = value.actions;
|
|
3566
|
+
if (!Array.isArray(actions)) throw new Error("native.actions is invalid");
|
|
3567
|
+
if (service === "tinycloud.encryption" && value.caveat === void 0 && value.space === value.path && actions.length === 1 && actions[0] === "tinycloud.encryption/decrypt") {
|
|
3568
|
+
return normalizeUnifiedPolicyCapability({
|
|
3569
|
+
kind: "encryption",
|
|
3570
|
+
resource: value.space,
|
|
3571
|
+
action: actions[0]
|
|
3572
|
+
});
|
|
3573
|
+
}
|
|
3574
|
+
if (service !== "tinycloud.kv" || typeof value.space !== "string" || typeof value.path !== "string")
|
|
3575
|
+
throw new Error("native capability is not supported");
|
|
3576
|
+
const caveat = object(value.caveat, "native.caveat");
|
|
3577
|
+
exactKeys(caveat, ["type", "kind", "value"], "native selector caveat");
|
|
3578
|
+
if (caveat.type !== "xyz.tinycloud.resource/selector" || caveat.kind !== "exact" && caveat.kind !== "prefix" || caveat.value !== `tinycloud://${value.space}/kv/${value.path}`)
|
|
3579
|
+
throw new Error("native selector caveat does not match capability");
|
|
3580
|
+
return normalizeUnifiedPolicyCapability({
|
|
3581
|
+
kind: "kv",
|
|
3582
|
+
resource: caveat.value,
|
|
3583
|
+
selector: caveat.kind,
|
|
3584
|
+
actions
|
|
3585
|
+
});
|
|
3586
|
+
}
|
|
3587
|
+
function contentSourceDigestHex(input) {
|
|
3588
|
+
return hex(
|
|
3589
|
+
sha2564(
|
|
3590
|
+
new TextEncoder().encode(
|
|
3591
|
+
CONTENT_SOURCE_V1_DOMAIN + jcsCanonicalize(input)
|
|
3592
|
+
)
|
|
3593
|
+
)
|
|
3594
|
+
);
|
|
3595
|
+
}
|
|
3596
|
+
function policyDigestHex(policy) {
|
|
3597
|
+
const canonicalPolicy = {
|
|
3598
|
+
...policy,
|
|
3599
|
+
capabilityCeiling: policy.capabilityCeiling.map(
|
|
3600
|
+
normalizeUnifiedPolicyCapability
|
|
3601
|
+
)
|
|
3602
|
+
};
|
|
3603
|
+
return hex(
|
|
3604
|
+
sha2564(
|
|
3605
|
+
new TextEncoder().encode(
|
|
3606
|
+
POLICY_V1_DOMAIN + jcsCanonicalize(canonicalPolicy)
|
|
3607
|
+
)
|
|
3608
|
+
)
|
|
3609
|
+
);
|
|
3610
|
+
}
|
|
3611
|
+
function policyIdForDigestHex(digestHex) {
|
|
3612
|
+
const digest2 = Uint8Array.from(
|
|
3613
|
+
(digestHex.match(/.{2}/g) ?? []).map((byte) => Number.parseInt(byte, 16))
|
|
3614
|
+
);
|
|
3615
|
+
if (digest2.length !== 32) throw new Error("policy digest must be 32 bytes");
|
|
3616
|
+
return `pol_${base32Lower(digest2)}`;
|
|
3617
|
+
}
|
|
3618
|
+
function policyCidFromCanonicalBytes(bytes) {
|
|
3619
|
+
return CID.createV1(85, create(18, sha2564(bytes))).toString();
|
|
3620
|
+
}
|
|
3621
|
+
var CompactHeaderSchema = z.object({
|
|
3622
|
+
alg: z.literal("EdDSA"),
|
|
3623
|
+
jwk: z.object({ alg: z.literal("EdDSA"), crv: z.literal("Ed25519"), kty: z.literal("OKP"), x: z.string().min(1) }).strict(),
|
|
3624
|
+
typ: z.literal("JWT"),
|
|
3625
|
+
ucv: z.literal("0.10.0")
|
|
3626
|
+
}).strict();
|
|
3627
|
+
var CompactPayloadSchema = z.object({
|
|
3628
|
+
att: z.record(z.record(z.array(z.unknown()).min(1))),
|
|
3629
|
+
aud: z.string().min(1),
|
|
3630
|
+
exp: z.number().int(),
|
|
3631
|
+
fct: z.array(z.record(z.unknown())).length(1),
|
|
3632
|
+
iss: z.string().min(1),
|
|
3633
|
+
nbf: z.number().int(),
|
|
3634
|
+
nnc: z.string().min(1),
|
|
3635
|
+
prf: z.array(z.string().min(1))
|
|
3636
|
+
}).strict();
|
|
3637
|
+
async function signCompactUcanAuthorization(input) {
|
|
3638
|
+
if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > 60)
|
|
3639
|
+
throw new Error("compact invocation lifetime must be between one and 60 seconds");
|
|
3640
|
+
const principal = input.issuerDid.split("#", 1)[0];
|
|
3641
|
+
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
3642
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
|
|
3643
|
+
throw new Error("compact UCAN signer must be did:key Ed25519");
|
|
3644
|
+
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(didMaterial.slice(2)) }, typ: "JWT", ucv: "0.10.0" };
|
|
3645
|
+
const payload = {
|
|
3646
|
+
att: input.attenuation,
|
|
3647
|
+
aud: input.audienceDid,
|
|
3648
|
+
exp: input.expiresAt,
|
|
3649
|
+
fct: input.facts,
|
|
3650
|
+
iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
3651
|
+
nbf: input.notBefore,
|
|
3652
|
+
nnc: input.nonce,
|
|
3653
|
+
prf: input.proofs
|
|
3654
|
+
};
|
|
3655
|
+
const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
3656
|
+
const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
3657
|
+
const signature = await input.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`));
|
|
3658
|
+
if (signature.length !== 64) throw new Error("compact Authorization signature must be Ed25519");
|
|
3659
|
+
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
3660
|
+
}
|
|
3661
|
+
function createCompactPolicyInvocation(input) {
|
|
3662
|
+
const session = parsePolicySessionUcan(input.sessionAuthorization);
|
|
3663
|
+
if (session.cid !== input.sessionCid || session.aud !== input.recipientDid)
|
|
3664
|
+
throw new Error("policy session does not bind the recipient signer");
|
|
3665
|
+
const principal = input.recipientDid.split("#", 1)[0];
|
|
3666
|
+
const didMaterial = base58btc.decode(principal.slice("did:key:".length));
|
|
3667
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
|
|
3668
|
+
throw new Error("policy invocation signer must be did:key Ed25519");
|
|
3669
|
+
const publicKey = ed255192.getPublicKey(input.privateKey);
|
|
3670
|
+
if (!equalBytes(publicKey, didMaterial.slice(2)))
|
|
3671
|
+
throw new Error("policy invocation private key does not bind recipient DID");
|
|
3672
|
+
const now = input.now ?? Math.floor(Date.now() / 1e3);
|
|
3673
|
+
const exp = Math.min(now + 60, session.exp);
|
|
3674
|
+
if (exp <= now) throw new Error("policy session has expired");
|
|
3675
|
+
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
|
|
3676
|
+
const payload = {
|
|
3677
|
+
att: { [input.resource]: { [input.action]: [input.caveat ?? {}] } },
|
|
3678
|
+
aud: input.audienceDid,
|
|
3679
|
+
exp,
|
|
3680
|
+
fct: [input.facts ?? { type: "tinycloud.policy.invocation/v1", policyCid: session.fact.policyCid, sessionCid: session.cid }],
|
|
3681
|
+
iss: input.recipientDid.includes("#") ? input.recipientDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
3682
|
+
nbf: now,
|
|
3683
|
+
nnc: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
3684
|
+
prf: [session.cid]
|
|
3685
|
+
};
|
|
3686
|
+
const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
3687
|
+
const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
3688
|
+
const signingInput = new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`);
|
|
3689
|
+
const signature = ed255192.sign(signingInput, input.privateKey);
|
|
3690
|
+
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
3691
|
+
}
|
|
3692
|
+
function createCompactPolicyDescendant(input) {
|
|
3693
|
+
const parent = parseCompactUcanAuthorization(input.parentAuthorization, input.parentCid);
|
|
3694
|
+
if (parent.payload.aud !== input.issuerDid) throw new Error("policy descendant issuer is not the parent audience");
|
|
3695
|
+
const parentFact = parent.payload.fct[0];
|
|
3696
|
+
const depth = parentFact.remainingRedelegationDepth;
|
|
3697
|
+
if (!Number.isInteger(depth) || depth <= 0) throw new Error("policy descendant depth is exhausted");
|
|
3698
|
+
if (!compactAttenuationContains(parent.payload.att, input.attenuation))
|
|
3699
|
+
throw new Error("policy descendant exceeds the parent attenuation");
|
|
3700
|
+
const principal = input.issuerDid.split("#", 1)[0];
|
|
3701
|
+
const didMaterial = base58btc.decode(principal.slice("did:key:".length));
|
|
3702
|
+
const publicKey = ed255192.getPublicKey(input.privateKey);
|
|
3703
|
+
if (didMaterial.length !== 34 || !equalBytes(publicKey, didMaterial.slice(2))) throw new Error("policy descendant signer does not bind issuer DID");
|
|
3704
|
+
const now = Math.max(input.now ?? Math.floor(Date.now() / 1e3), parent.payload.nbf + 1);
|
|
3705
|
+
const exp = Math.min(input.expiresAt ?? now + 60, now + 60, parent.payload.exp - 1);
|
|
3706
|
+
if (exp <= now) throw new Error("policy parent has no strictly narrower validity window");
|
|
3707
|
+
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
|
|
3708
|
+
const payload = {
|
|
3709
|
+
att: input.attenuation,
|
|
3710
|
+
aud: input.audienceDid,
|
|
3711
|
+
exp,
|
|
3712
|
+
fct: [{ ...parentFact, remainingRedelegationDepth: depth - 1 }],
|
|
3713
|
+
iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
3714
|
+
nbf: now,
|
|
3715
|
+
nnc: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
3716
|
+
prf: [parent.cid]
|
|
3717
|
+
};
|
|
3718
|
+
const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
3719
|
+
const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
3720
|
+
const signature = ed255192.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`), input.privateKey);
|
|
3721
|
+
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
3722
|
+
}
|
|
3723
|
+
function compactAttenuationContains(parent, child) {
|
|
3724
|
+
const selector = (value) => {
|
|
3725
|
+
if (value.length !== 1 || !isRecordValue(value[0])) return void 0;
|
|
3726
|
+
const caveat = value[0];
|
|
3727
|
+
if (Object.keys(caveat).length !== 3 || caveat.type !== "xyz.tinycloud.resource/selector" || caveat.kind !== "exact" && caveat.kind !== "prefix" || typeof caveat.value !== "string") return void 0;
|
|
3728
|
+
return { kind: caveat.kind, value: caveat.value };
|
|
3729
|
+
};
|
|
3730
|
+
const equal = (left, right) => jcsCanonicalize(left) === jcsCanonicalize(right);
|
|
3731
|
+
return Object.entries(child).every(
|
|
3732
|
+
([childResource, childActions]) => Object.entries(childActions).every(
|
|
3733
|
+
([action, childCaveats]) => Object.entries(parent).some(([parentResource, parentActions]) => {
|
|
3734
|
+
const parentCaveats = parentActions[action];
|
|
3735
|
+
if (parentCaveats === void 0) return false;
|
|
3736
|
+
if (parentResource === childResource && equal(parentCaveats, childCaveats)) return true;
|
|
3737
|
+
const parentSelector = selector(parentCaveats);
|
|
3738
|
+
const childSelector = selector(childCaveats);
|
|
3739
|
+
return parentSelector?.kind === "prefix" && childSelector !== void 0 && parentSelector.value === parentResource && childSelector.value === childResource && (childResource === parentResource || childResource.startsWith(`${parentResource}/`));
|
|
3740
|
+
})
|
|
3741
|
+
)
|
|
3742
|
+
);
|
|
3743
|
+
}
|
|
3744
|
+
function isRecordValue(value) {
|
|
3745
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3746
|
+
}
|
|
3747
|
+
function parseCompactUcanAuthorization(input, expectedCid) {
|
|
3748
|
+
if (typeof input !== "string" || /\s/.test(input))
|
|
3749
|
+
throw new Error("Authorization must be compact UCAN bytes");
|
|
3750
|
+
const segments = input.split(".");
|
|
3751
|
+
if (segments.length !== 3 || segments.some((segment) => segment.length === 0))
|
|
3752
|
+
throw new Error("Authorization must have three compact segments");
|
|
3753
|
+
const [headerSegment, payloadSegment, signatureSegment] = segments;
|
|
3754
|
+
const headerBytes = decodeBase64Url(headerSegment);
|
|
3755
|
+
const payloadBytes = decodeBase64Url(payloadSegment);
|
|
3756
|
+
const signature = decodeBase64Url(signatureSegment);
|
|
3757
|
+
const headerValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(headerBytes));
|
|
3758
|
+
const payloadValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(payloadBytes));
|
|
3759
|
+
if (jcsCanonicalize(headerValue) !== new TextDecoder().decode(headerBytes) || jcsCanonicalize(payloadValue) !== new TextDecoder().decode(payloadBytes))
|
|
3760
|
+
throw new Error("compact UCAN segments are not canonical JCS");
|
|
3761
|
+
const header = CompactHeaderSchema.parse(headerValue);
|
|
3762
|
+
const payload = CompactPayloadSchema.parse(payloadValue);
|
|
3763
|
+
if (payload.nbf >= payload.exp) throw new Error("compact UCAN validity is empty");
|
|
3764
|
+
const principal = payload.iss.split("#", 1)[0];
|
|
3765
|
+
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
3766
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
|
|
3767
|
+
throw new Error("compact UCAN issuer must be did:key Ed25519");
|
|
3768
|
+
const publicKey = didMaterial.slice(2);
|
|
3769
|
+
if (!equalBytes(publicKey, decodeBase64Url(header.jwk.x)))
|
|
3770
|
+
throw new Error("compact UCAN JWK does not bind issuer");
|
|
3771
|
+
if (!ed255192.verify(signature, new TextEncoder().encode(`${headerSegment}.${payloadSegment}`), publicKey))
|
|
3772
|
+
throw new Error("compact UCAN signature is invalid");
|
|
3773
|
+
const cid = CID.createV1(85, create(30, blake3(new TextEncoder().encode(input)))).toString();
|
|
3774
|
+
if (expectedCid !== void 0 && cid !== expectedCid)
|
|
3775
|
+
throw new Error("compact UCAN CID does not match exact Authorization bytes");
|
|
3776
|
+
return { authorization: input, cid, header, payload };
|
|
3777
|
+
}
|
|
3778
|
+
function parsePolicySessionUcan(authorization, expectedProofs) {
|
|
3779
|
+
const parsed = parseCompactUcanAuthorization(authorization);
|
|
3780
|
+
const fact = parsed.payload.fct[0];
|
|
3781
|
+
if (parsed.payload.prf.length !== 2 || parsed.payload.prf[0] === parsed.payload.prf[1])
|
|
3782
|
+
throw new Error("policy session UCAN requires two distinct ordered proofs");
|
|
3783
|
+
if (expectedProofs !== void 0 && (parsed.payload.prf[0] !== expectedProofs[0] || parsed.payload.prf[1] !== expectedProofs[1]))
|
|
3784
|
+
throw new Error("policy session UCAN ordered proofs do not match");
|
|
3785
|
+
const factKeys = Object.keys(fact);
|
|
3786
|
+
if (factKeys.length !== POLICY_SESSION_FACT_KEYS.length || factKeys.some((key) => !POLICY_SESSION_FACT_KEYS.includes(key)) || POLICY_SESSION_FACT_KEYS.some((key) => !(key in fact)))
|
|
3787
|
+
throw new Error("policy session UCAN fact is incomplete");
|
|
3788
|
+
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.enforcerDid || parsed.payload.aud !== fact.recipientDid)
|
|
3789
|
+
throw new Error("policy session UCAN fact is invalid");
|
|
3790
|
+
return {
|
|
3791
|
+
authorization,
|
|
3792
|
+
cid: parsed.cid,
|
|
3793
|
+
iss: parsed.payload.iss,
|
|
3794
|
+
aud: parsed.payload.aud,
|
|
3795
|
+
prf: parsed.payload.prf,
|
|
3796
|
+
att: parsed.payload.att,
|
|
3797
|
+
nbf: parsed.payload.nbf,
|
|
3798
|
+
exp: parsed.payload.exp,
|
|
3799
|
+
nnc: parsed.payload.nnc,
|
|
3800
|
+
fact
|
|
3801
|
+
};
|
|
3802
|
+
}
|
|
3803
|
+
function decodeBase64Url(value) {
|
|
3804
|
+
if (!/^[A-Za-z0-9_-]+$/.test(value) || value.length % 4 === 1)
|
|
3805
|
+
throw new Error("value is not canonical base64url");
|
|
3806
|
+
const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
3807
|
+
const binary = typeof Buffer !== "undefined" ? Buffer.from(normalized, "base64").toString("binary") : atob(normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "="));
|
|
3808
|
+
const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
3809
|
+
const encoded = typeof Buffer !== "undefined" ? Buffer.from(bytes).toString("base64url") : btoa(String.fromCharCode(...bytes)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
3810
|
+
if (encoded !== value) throw new Error("value is not canonical base64url");
|
|
3811
|
+
return bytes;
|
|
3812
|
+
}
|
|
3813
|
+
function encodeBase64Url(value) {
|
|
3814
|
+
return typeof Buffer !== "undefined" ? Buffer.from(value).toString("base64url") : btoa(String.fromCharCode(...value)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
3815
|
+
}
|
|
3816
|
+
function equalBytes(left, right) {
|
|
3817
|
+
return left.length === right.length && left.every((byte, index) => byte === right[index]);
|
|
3818
|
+
}
|
|
3819
|
+
function hex(bytes) {
|
|
3820
|
+
return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
3821
|
+
}
|
|
3822
|
+
function base32Lower(bytes) {
|
|
3823
|
+
const alphabet2 = "abcdefghijklmnopqrstuvwxyz234567";
|
|
3824
|
+
let output = "";
|
|
3825
|
+
let buffer = 0;
|
|
3826
|
+
let bits = 0;
|
|
3827
|
+
for (const byte of bytes) {
|
|
3828
|
+
buffer = buffer << 8 | byte;
|
|
3829
|
+
bits += 8;
|
|
3830
|
+
while (bits >= 5) {
|
|
3831
|
+
output += alphabet2[buffer >>> bits - 5 & 31];
|
|
3832
|
+
bits -= 5;
|
|
3833
|
+
}
|
|
3834
|
+
}
|
|
3835
|
+
if (bits > 0) output += alphabet2[buffer << 5 - bits & 31];
|
|
3836
|
+
return output;
|
|
3187
3837
|
}
|
|
3188
3838
|
export {
|
|
3839
|
+
ATTESTED_ENFORCER_BINDING_V2_SCHEMA,
|
|
3840
|
+
CONTENT_SOURCE_V1_DOMAIN,
|
|
3189
3841
|
ED25519_JCS_SIGNATURE_SUITE,
|
|
3190
3842
|
EIP191_JCS_SIGNATURE_SUITE,
|
|
3843
|
+
LAST_V2_CREATE_AT,
|
|
3844
|
+
LAST_V2_READ_AT,
|
|
3845
|
+
MAX_LEGACY_ENVELOPE_EXPIRES_AT,
|
|
3846
|
+
NATIVE_PROJECTION_V1_DOMAIN,
|
|
3191
3847
|
OWNER_NODE_ENDPOINT_SCHEMA,
|
|
3848
|
+
POLICY_CAPABILITY_V1_DOMAIN,
|
|
3849
|
+
POLICY_CAPABILITY_V1_SCHEMA,
|
|
3850
|
+
POLICY_ENFORCEMENT_DELEGATION_V2_SCHEMA,
|
|
3192
3851
|
POLICY_ENGINE_RECORD_SCHEMA,
|
|
3193
3852
|
POLICY_SCHEMA,
|
|
3853
|
+
POLICY_SESSION_UCAN_V1_PROFILE,
|
|
3194
3854
|
POLICY_STATUS_SCHEMA,
|
|
3855
|
+
POLICY_V1_DOMAIN,
|
|
3856
|
+
POLICY_V1_SCHEMA,
|
|
3195
3857
|
POLICY_VERSION_V0,
|
|
3196
3858
|
PolicyAuthoringError,
|
|
3197
3859
|
PolicyCapabilityError,
|
|
3860
|
+
ROOT_REVOCATION_V1_DOMAIN,
|
|
3861
|
+
ROOT_REVOCATION_V1_SCHEMA,
|
|
3862
|
+
ROOT_STATUS_CHECKPOINT_V1_SCHEMA,
|
|
3863
|
+
ROOT_STATUS_RENEWAL_V1_DOMAIN,
|
|
3864
|
+
ROOT_STATUS_V1_DOMAIN,
|
|
3198
3865
|
SignatureMaterialError,
|
|
3199
3866
|
SignatureVerificationError,
|
|
3200
3867
|
SignedObjectCanonicalizationError,
|
|
@@ -3208,23 +3875,46 @@ export {
|
|
|
3208
3875
|
W3C_VC_CREDENTIAL_VERIFIER,
|
|
3209
3876
|
canonicalizePolicyCapability,
|
|
3210
3877
|
canonicalizeSignedObjectUnsigned,
|
|
3878
|
+
canonicalizeUnifiedPolicyCapability,
|
|
3879
|
+
compactAttenuationContains,
|
|
3211
3880
|
composeTranscriptShareBootstrap,
|
|
3881
|
+
contentSourceDigestHex,
|
|
3212
3882
|
createAndSignPolicy,
|
|
3213
3883
|
createAndSignPolicyEngineRecord,
|
|
3214
3884
|
createAndSignPolicyStatus,
|
|
3215
3885
|
createAndSignRequesterPolicyEngineRecord,
|
|
3216
3886
|
createAndSignSignedObject,
|
|
3217
3887
|
createAndSignTranscriptSharePolicy,
|
|
3888
|
+
createCompactPolicyDescendant,
|
|
3889
|
+
createCompactPolicyInvocation,
|
|
3218
3890
|
createUnsignedPolicyEngineRecord,
|
|
3219
3891
|
deriveSignedObjectMaterial,
|
|
3892
|
+
getPolicyRootStatusV3,
|
|
3220
3893
|
jcsCanonicalize,
|
|
3894
|
+
mintPolicySessionV3,
|
|
3221
3895
|
normalizeJson,
|
|
3222
3896
|
normalizePolicyCapability,
|
|
3897
|
+
normalizeUnifiedPolicyCapability,
|
|
3898
|
+
parseCompactUcanAuthorization,
|
|
3899
|
+
parsePolicySessionUcan,
|
|
3223
3900
|
policyCapabilityContains,
|
|
3224
3901
|
policyCapabilityDigestHex,
|
|
3902
|
+
policyCidFromCanonicalBytes,
|
|
3903
|
+
policyDigestHex,
|
|
3904
|
+
policyIdForDigestHex,
|
|
3905
|
+
projectUnifiedPolicyCapabilities,
|
|
3906
|
+
projectUnifiedPolicyCapability,
|
|
3907
|
+
renewPolicyRootStatusV3,
|
|
3908
|
+
requestPolicyChallengeV3,
|
|
3909
|
+
revokePolicyRootV3,
|
|
3225
3910
|
serialize as serializeJcsJson,
|
|
3911
|
+
signCompactUcanAuthorization,
|
|
3226
3912
|
signedObjectIdFor,
|
|
3227
3913
|
toSignedObjectError,
|
|
3914
|
+
unifiedNativeProjectionHashHex,
|
|
3915
|
+
unifiedPolicyCapabilityContains,
|
|
3916
|
+
unifiedPolicyCapabilityDigestHex,
|
|
3917
|
+
unifiedPolicyCapabilityFromNative,
|
|
3228
3918
|
validatePolicyEngineRecordSigned,
|
|
3229
3919
|
validatePolicyEngineRecordSignedShape,
|
|
3230
3920
|
validatePolicyEngineRecordUnsigned,
|
|
@@ -3237,6 +3927,8 @@ export {
|
|
|
3237
3927
|
verifyPolicy,
|
|
3238
3928
|
verifyPolicyEngineRecord,
|
|
3239
3929
|
verifyPolicyEngineRecordForRequester,
|
|
3930
|
+
verifyPolicyRootRevocationV3,
|
|
3931
|
+
verifyPolicyRootStatusCheckpointV3,
|
|
3240
3932
|
verifyPolicyStatus,
|
|
3241
3933
|
verifySignedObject
|
|
3242
3934
|
};
|