@tinycloud/sdk-core 2.11.0-beta.1 → 2.11.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/bootstrap/index.cjs +0 -4
- package/dist/delegations/index.cjs +702 -330
- package/dist/delegations/index.cjs.map +1 -1
- package/dist/delegations/index.d.cts +9 -8
- package/dist/delegations/index.d.ts +9 -8
- package/dist/delegations/index.js +722 -263
- package/dist/delegations/index.js.map +1 -1
- package/dist/index.cjs +2338 -1156
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +350 -24
- package/dist/index.d.ts +350 -24
- package/dist/index.js +2333 -810
- package/dist/index.js.map +1 -1
- package/dist/policy/index.cjs +878 -250
- package/dist/policy/index.cjs.map +1 -1
- package/dist/policy/index.d.cts +3 -2
- package/dist/policy/index.d.ts +3 -2
- package/dist/policy/index.js +877 -183
- package/dist/policy/index.js.map +1 -1
- package/dist/{recipient-types.schema-CWIt63Qp.d.cts → recipient-types.schema-CuDpskPd.d.cts} +236 -98
- package/dist/{recipient-types.schema-CWIt63Qp.d.ts → recipient-types.schema-CuDpskPd.d.ts} +236 -98
- package/dist/requester/index.cjs +10 -38
- package/dist/requester/index.cjs.map +1 -1
- package/dist/requester/index.js +10 -8
- package/dist/requester/index.js.map +1 -1
- package/dist/unified-BYPfXp5S.d.ts +429 -0
- package/dist/unified-BdfNHNrx.d.cts +429 -0
- package/package.json +6 -3
- package/dist/signed-object-C6mWbTbB.d.ts +0 -149
- package/dist/signed-object-IMAm5a32.d.cts +0 -149
package/dist/policy/index.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
7
|
var __export = (target, all) => {
|
|
@@ -18,29 +16,38 @@ var __copyProps = (to, from3, except, desc) => {
|
|
|
18
16
|
}
|
|
19
17
|
return to;
|
|
20
18
|
};
|
|
21
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
-
mod
|
|
28
|
-
));
|
|
29
19
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
20
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
31
21
|
|
|
32
22
|
// src/policy/index.ts
|
|
33
23
|
var policy_exports = {};
|
|
34
24
|
__export(policy_exports, {
|
|
25
|
+
ATTESTED_ENFORCER_BINDING_V2_SCHEMA: () => ATTESTED_ENFORCER_BINDING_V2_SCHEMA,
|
|
26
|
+
CONTENT_SOURCE_V1_DOMAIN: () => CONTENT_SOURCE_V1_DOMAIN,
|
|
35
27
|
ED25519_JCS_SIGNATURE_SUITE: () => ED25519_JCS_SIGNATURE_SUITE,
|
|
36
28
|
EIP191_JCS_SIGNATURE_SUITE: () => EIP191_JCS_SIGNATURE_SUITE,
|
|
29
|
+
LAST_V2_CREATE_AT: () => LAST_V2_CREATE_AT,
|
|
30
|
+
LAST_V2_READ_AT: () => LAST_V2_READ_AT,
|
|
31
|
+
MAX_LEGACY_ENVELOPE_EXPIRES_AT: () => MAX_LEGACY_ENVELOPE_EXPIRES_AT,
|
|
32
|
+
NATIVE_PROJECTION_V1_DOMAIN: () => NATIVE_PROJECTION_V1_DOMAIN,
|
|
37
33
|
OWNER_NODE_ENDPOINT_SCHEMA: () => OWNER_NODE_ENDPOINT_SCHEMA,
|
|
34
|
+
POLICY_CAPABILITY_V1_DOMAIN: () => POLICY_CAPABILITY_V1_DOMAIN,
|
|
35
|
+
POLICY_CAPABILITY_V1_SCHEMA: () => POLICY_CAPABILITY_V1_SCHEMA,
|
|
36
|
+
POLICY_ENFORCEMENT_DELEGATION_V2_SCHEMA: () => POLICY_ENFORCEMENT_DELEGATION_V2_SCHEMA,
|
|
38
37
|
POLICY_ENGINE_RECORD_SCHEMA: () => POLICY_ENGINE_RECORD_SCHEMA,
|
|
39
38
|
POLICY_SCHEMA: () => POLICY_SCHEMA,
|
|
39
|
+
POLICY_SESSION_UCAN_V1_PROFILE: () => POLICY_SESSION_UCAN_V1_PROFILE,
|
|
40
40
|
POLICY_STATUS_SCHEMA: () => POLICY_STATUS_SCHEMA,
|
|
41
|
+
POLICY_V1_DOMAIN: () => POLICY_V1_DOMAIN,
|
|
42
|
+
POLICY_V1_SCHEMA: () => POLICY_V1_SCHEMA,
|
|
41
43
|
POLICY_VERSION_V0: () => POLICY_VERSION_V0,
|
|
42
44
|
PolicyAuthoringError: () => PolicyAuthoringError,
|
|
43
45
|
PolicyCapabilityError: () => PolicyCapabilityError,
|
|
46
|
+
ROOT_REVOCATION_V1_DOMAIN: () => ROOT_REVOCATION_V1_DOMAIN,
|
|
47
|
+
ROOT_REVOCATION_V1_SCHEMA: () => ROOT_REVOCATION_V1_SCHEMA,
|
|
48
|
+
ROOT_STATUS_CHECKPOINT_V1_SCHEMA: () => ROOT_STATUS_CHECKPOINT_V1_SCHEMA,
|
|
49
|
+
ROOT_STATUS_RENEWAL_V1_DOMAIN: () => ROOT_STATUS_RENEWAL_V1_DOMAIN,
|
|
50
|
+
ROOT_STATUS_V1_DOMAIN: () => ROOT_STATUS_V1_DOMAIN,
|
|
44
51
|
SignatureMaterialError: () => SignatureMaterialError,
|
|
45
52
|
SignatureVerificationError: () => SignatureVerificationError,
|
|
46
53
|
SignedObjectCanonicalizationError: () => SignedObjectCanonicalizationError,
|
|
@@ -54,23 +61,46 @@ __export(policy_exports, {
|
|
|
54
61
|
W3C_VC_CREDENTIAL_VERIFIER: () => W3C_VC_CREDENTIAL_VERIFIER,
|
|
55
62
|
canonicalizePolicyCapability: () => canonicalizePolicyCapability,
|
|
56
63
|
canonicalizeSignedObjectUnsigned: () => canonicalizeSignedObjectUnsigned,
|
|
64
|
+
canonicalizeUnifiedPolicyCapability: () => canonicalizeUnifiedPolicyCapability,
|
|
65
|
+
compactAttenuationContains: () => compactAttenuationContains,
|
|
57
66
|
composeTranscriptShareBootstrap: () => composeTranscriptShareBootstrap,
|
|
67
|
+
contentSourceDigestHex: () => contentSourceDigestHex,
|
|
58
68
|
createAndSignPolicy: () => createAndSignPolicy,
|
|
59
69
|
createAndSignPolicyEngineRecord: () => createAndSignPolicyEngineRecord,
|
|
60
70
|
createAndSignPolicyStatus: () => createAndSignPolicyStatus,
|
|
61
71
|
createAndSignRequesterPolicyEngineRecord: () => createAndSignRequesterPolicyEngineRecord,
|
|
62
72
|
createAndSignSignedObject: () => createAndSignSignedObject,
|
|
63
73
|
createAndSignTranscriptSharePolicy: () => createAndSignTranscriptSharePolicy,
|
|
74
|
+
createCompactPolicyDescendant: () => createCompactPolicyDescendant,
|
|
75
|
+
createCompactPolicyInvocation: () => createCompactPolicyInvocation,
|
|
64
76
|
createUnsignedPolicyEngineRecord: () => createUnsignedPolicyEngineRecord,
|
|
65
77
|
deriveSignedObjectMaterial: () => deriveSignedObjectMaterial,
|
|
78
|
+
getPolicyRootStatusV3: () => getPolicyRootStatusV3,
|
|
66
79
|
jcsCanonicalize: () => jcsCanonicalize,
|
|
80
|
+
mintPolicySessionV3: () => mintPolicySessionV3,
|
|
67
81
|
normalizeJson: () => normalizeJson,
|
|
68
82
|
normalizePolicyCapability: () => normalizePolicyCapability,
|
|
83
|
+
normalizeUnifiedPolicyCapability: () => normalizeUnifiedPolicyCapability,
|
|
84
|
+
parseCompactUcanAuthorization: () => parseCompactUcanAuthorization,
|
|
85
|
+
parsePolicySessionUcan: () => parsePolicySessionUcan,
|
|
69
86
|
policyCapabilityContains: () => policyCapabilityContains,
|
|
70
87
|
policyCapabilityDigestHex: () => policyCapabilityDigestHex,
|
|
88
|
+
policyCidFromCanonicalBytes: () => policyCidFromCanonicalBytes,
|
|
89
|
+
policyDigestHex: () => policyDigestHex,
|
|
90
|
+
policyIdForDigestHex: () => policyIdForDigestHex,
|
|
91
|
+
projectUnifiedPolicyCapabilities: () => projectUnifiedPolicyCapabilities,
|
|
92
|
+
projectUnifiedPolicyCapability: () => projectUnifiedPolicyCapability,
|
|
93
|
+
renewPolicyRootStatusV3: () => renewPolicyRootStatusV3,
|
|
94
|
+
requestPolicyChallengeV3: () => requestPolicyChallengeV3,
|
|
95
|
+
revokePolicyRootV3: () => revokePolicyRootV3,
|
|
71
96
|
serializeJcsJson: () => serialize,
|
|
97
|
+
signCompactUcanAuthorization: () => signCompactUcanAuthorization,
|
|
72
98
|
signedObjectIdFor: () => signedObjectIdFor,
|
|
73
99
|
toSignedObjectError: () => toSignedObjectError,
|
|
100
|
+
unifiedNativeProjectionHashHex: () => unifiedNativeProjectionHashHex,
|
|
101
|
+
unifiedPolicyCapabilityContains: () => unifiedPolicyCapabilityContains,
|
|
102
|
+
unifiedPolicyCapabilityDigestHex: () => unifiedPolicyCapabilityDigestHex,
|
|
103
|
+
unifiedPolicyCapabilityFromNative: () => unifiedPolicyCapabilityFromNative,
|
|
74
104
|
validatePolicyEngineRecordSigned: () => validatePolicyEngineRecordSigned,
|
|
75
105
|
validatePolicyEngineRecordSignedShape: () => validatePolicyEngineRecordSignedShape,
|
|
76
106
|
validatePolicyEngineRecordUnsigned: () => validatePolicyEngineRecordUnsigned,
|
|
@@ -83,6 +113,8 @@ __export(policy_exports, {
|
|
|
83
113
|
verifyPolicy: () => verifyPolicy,
|
|
84
114
|
verifyPolicyEngineRecord: () => verifyPolicyEngineRecord,
|
|
85
115
|
verifyPolicyEngineRecordForRequester: () => verifyPolicyEngineRecordForRequester,
|
|
116
|
+
verifyPolicyRootRevocationV3: () => verifyPolicyRootRevocationV3,
|
|
117
|
+
verifyPolicyRootStatusCheckpointV3: () => verifyPolicyRootStatusCheckpointV3,
|
|
86
118
|
verifyPolicyStatus: () => verifyPolicyStatus,
|
|
87
119
|
verifySignedObject: () => verifySignedObject
|
|
88
120
|
});
|
|
@@ -405,16 +437,16 @@ function policyCapabilityContains(authority, request) {
|
|
|
405
437
|
return caveatsContain(auth.caveats, req.caveats);
|
|
406
438
|
}
|
|
407
439
|
function normalizePolicyCapabilityWithOptions(input, options) {
|
|
408
|
-
const
|
|
409
|
-
assertExactKeys(
|
|
410
|
-
const service = requiredString(
|
|
440
|
+
const object2 = expectObject(input, "$");
|
|
441
|
+
assertExactKeys(object2, ["service", "space", "path", "actions", "caveats"], "$");
|
|
442
|
+
const service = requiredString(object2, "service", "$", "policy-capability-malformed-service");
|
|
411
443
|
if (!CEILING_SERVICES.has(service)) {
|
|
412
444
|
throw new PolicyCapabilityError(
|
|
413
445
|
"policy-capability-malformed-service",
|
|
414
446
|
"$.service is outside the frozen permissionsCeiling vocabulary"
|
|
415
447
|
);
|
|
416
448
|
}
|
|
417
|
-
const space = requiredString(
|
|
449
|
+
const space = requiredString(object2, "space", "$", "policy-capability-malformed-space");
|
|
418
450
|
validateConcreteSpace(space);
|
|
419
451
|
const canonicalSpace = space.normalize("NFC");
|
|
420
452
|
if (options.requireCanonical && canonicalSpace !== space) {
|
|
@@ -423,7 +455,7 @@ function normalizePolicyCapabilityWithOptions(input, options) {
|
|
|
423
455
|
"$.space must already be canonical NFC"
|
|
424
456
|
);
|
|
425
457
|
}
|
|
426
|
-
const rawPath = requiredString(
|
|
458
|
+
const rawPath = requiredString(object2, "path", "$", "policy-capability-malformed-path");
|
|
427
459
|
validateRawPath(rawPath, options);
|
|
428
460
|
const path = normalizePath(rawPath);
|
|
429
461
|
if (options.requireCanonical && path !== rawPath) {
|
|
@@ -434,7 +466,7 @@ function normalizePolicyCapabilityWithOptions(input, options) {
|
|
|
434
466
|
}
|
|
435
467
|
validateRawPath(path, options);
|
|
436
468
|
const actions = normalizeActions(
|
|
437
|
-
requiredArray(
|
|
469
|
+
requiredArray(object2, "actions", "$", "policy-capability-malformed-action"),
|
|
438
470
|
service,
|
|
439
471
|
options
|
|
440
472
|
);
|
|
@@ -443,9 +475,9 @@ function normalizePolicyCapabilityWithOptions(input, options) {
|
|
|
443
475
|
output.space = canonicalSpace;
|
|
444
476
|
output.path = path;
|
|
445
477
|
output.actions = actions;
|
|
446
|
-
if (hasOwn(
|
|
478
|
+
if (hasOwn(object2, "caveats")) {
|
|
447
479
|
output.caveats = validateCaveats(
|
|
448
|
-
requiredValue(
|
|
480
|
+
requiredValue(object2, "caveats", "$", "policy-capability-malformed-caveats"),
|
|
449
481
|
output.service
|
|
450
482
|
);
|
|
451
483
|
}
|
|
@@ -468,9 +500,9 @@ function expectObject(input, path) {
|
|
|
468
500
|
);
|
|
469
501
|
}
|
|
470
502
|
}
|
|
471
|
-
function assertExactKeys(
|
|
503
|
+
function assertExactKeys(object2, allowed, path) {
|
|
472
504
|
const allowedSet = new Set(allowed);
|
|
473
|
-
for (const key of Object.keys(
|
|
505
|
+
for (const key of Object.keys(object2)) {
|
|
474
506
|
if (!allowedSet.has(key)) {
|
|
475
507
|
throw new PolicyCapabilityError(
|
|
476
508
|
key === "id" || key === "scope" ? "policy-capability-malformed" : "policy-capability-unknown-key",
|
|
@@ -479,21 +511,21 @@ function assertExactKeys(object, allowed, path) {
|
|
|
479
511
|
}
|
|
480
512
|
}
|
|
481
513
|
}
|
|
482
|
-
function requiredValue(
|
|
483
|
-
if (!hasOwn(
|
|
514
|
+
function requiredValue(object2, key, path, code2) {
|
|
515
|
+
if (!hasOwn(object2, key)) {
|
|
484
516
|
throw new PolicyCapabilityError(code2, `${path}.${key} is required`);
|
|
485
517
|
}
|
|
486
|
-
return
|
|
518
|
+
return object2[key];
|
|
487
519
|
}
|
|
488
|
-
function requiredString(
|
|
489
|
-
const value = requiredValue(
|
|
520
|
+
function requiredString(object2, key, path, code2) {
|
|
521
|
+
const value = requiredValue(object2, key, path, code2);
|
|
490
522
|
if (typeof value !== "string" || value.length === 0) {
|
|
491
523
|
throw new PolicyCapabilityError(code2, `${path}.${key} must be a non-empty string`);
|
|
492
524
|
}
|
|
493
525
|
return value;
|
|
494
526
|
}
|
|
495
|
-
function requiredArray(
|
|
496
|
-
const value = requiredValue(
|
|
527
|
+
function requiredArray(object2, key, path, code2) {
|
|
528
|
+
const value = requiredValue(object2, key, path, code2);
|
|
497
529
|
if (!Array.isArray(value)) {
|
|
498
530
|
throw new PolicyCapabilityError(code2, `${path}.${key} must be an array`);
|
|
499
531
|
}
|
|
@@ -638,11 +670,11 @@ function validateSqlStatement(input, path) {
|
|
|
638
670
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
639
671
|
throw new PolicyCapabilityError("policy-capability-malformed-caveats", `${path} must be an object`);
|
|
640
672
|
}
|
|
641
|
-
const
|
|
642
|
-
assertCaveatKeys(
|
|
643
|
-
caveatString(
|
|
644
|
-
caveatString(
|
|
645
|
-
const fixedParams = requiredCaveat(
|
|
673
|
+
const object2 = input;
|
|
674
|
+
assertCaveatKeys(object2, ["name", "sql", "fixedParams"], path);
|
|
675
|
+
caveatString(object2, "name", path);
|
|
676
|
+
caveatString(object2, "sql", path);
|
|
677
|
+
const fixedParams = requiredCaveat(object2, "fixedParams", path);
|
|
646
678
|
if (!Array.isArray(fixedParams)) {
|
|
647
679
|
throw new PolicyCapabilityError(
|
|
648
680
|
"policy-capability-malformed-caveats",
|
|
@@ -657,20 +689,20 @@ function validateFixedParam(input, path) {
|
|
|
657
689
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
658
690
|
throw new PolicyCapabilityError("policy-capability-malformed-caveats", `${path} must be an object`);
|
|
659
691
|
}
|
|
660
|
-
const
|
|
661
|
-
assertCaveatKeys(
|
|
662
|
-
const index = requiredCaveat(
|
|
692
|
+
const object2 = input;
|
|
693
|
+
assertCaveatKeys(object2, ["index", "value"], path);
|
|
694
|
+
const index = requiredCaveat(object2, "index", path);
|
|
663
695
|
if (typeof index !== "number" || !Number.isSafeInteger(index) || index < 0) {
|
|
664
696
|
throw new PolicyCapabilityError(
|
|
665
697
|
"policy-capability-malformed-caveats",
|
|
666
698
|
`${path}.index must be a non-negative integer`
|
|
667
699
|
);
|
|
668
700
|
}
|
|
669
|
-
requiredCaveat(
|
|
701
|
+
requiredCaveat(object2, "value", path);
|
|
670
702
|
}
|
|
671
|
-
function assertCaveatKeys(
|
|
703
|
+
function assertCaveatKeys(object2, allowed, path) {
|
|
672
704
|
const allowedSet = new Set(allowed);
|
|
673
|
-
for (const key of Object.keys(
|
|
705
|
+
for (const key of Object.keys(object2)) {
|
|
674
706
|
if (!allowedSet.has(key)) {
|
|
675
707
|
throw new PolicyCapabilityError(
|
|
676
708
|
"policy-capability-malformed-caveats",
|
|
@@ -679,17 +711,17 @@ function assertCaveatKeys(object, allowed, path) {
|
|
|
679
711
|
}
|
|
680
712
|
}
|
|
681
713
|
}
|
|
682
|
-
function requiredCaveat(
|
|
683
|
-
if (!hasOwn(
|
|
714
|
+
function requiredCaveat(object2, key, path) {
|
|
715
|
+
if (!hasOwn(object2, key)) {
|
|
684
716
|
throw new PolicyCapabilityError(
|
|
685
717
|
"policy-capability-malformed-caveats",
|
|
686
718
|
`${path}.${key} is required`
|
|
687
719
|
);
|
|
688
720
|
}
|
|
689
|
-
return
|
|
721
|
+
return object2[key];
|
|
690
722
|
}
|
|
691
|
-
function caveatString(
|
|
692
|
-
const value = requiredCaveat(
|
|
723
|
+
function caveatString(object2, key, path) {
|
|
724
|
+
const value = requiredCaveat(object2, key, path);
|
|
693
725
|
if (typeof value !== "string" || value.length === 0) {
|
|
694
726
|
throw new PolicyCapabilityError(
|
|
695
727
|
"policy-capability-malformed-caveats",
|
|
@@ -720,8 +752,8 @@ function caveatsContain(authority, request) {
|
|
|
720
752
|
(statement) => authorityStatements.some((candidate) => jcsCanonicalize(candidate) === jcsCanonicalize(statement))
|
|
721
753
|
);
|
|
722
754
|
}
|
|
723
|
-
function hasOwn(
|
|
724
|
-
return objectHasOwn2(
|
|
755
|
+
function hasOwn(object2, key) {
|
|
756
|
+
return objectHasOwn2(object2, key);
|
|
725
757
|
}
|
|
726
758
|
|
|
727
759
|
// src/policy/signed-object.ts
|
|
@@ -1465,13 +1497,12 @@ function digest(input, options) {
|
|
|
1465
1497
|
}
|
|
1466
1498
|
var identity2 = { code, name, encode: encode4, digest };
|
|
1467
1499
|
|
|
1468
|
-
// ../../node_modules/multiformats/dist/src/hashes/sha2.js
|
|
1469
|
-
var
|
|
1470
|
-
__export(
|
|
1500
|
+
// ../../node_modules/multiformats/dist/src/hashes/sha2-browser.js
|
|
1501
|
+
var sha2_browser_exports = {};
|
|
1502
|
+
__export(sha2_browser_exports, {
|
|
1471
1503
|
sha256: () => sha2562,
|
|
1472
1504
|
sha512: () => sha512
|
|
1473
1505
|
});
|
|
1474
|
-
var import_crypto = __toESM(require("crypto"), 1);
|
|
1475
1506
|
|
|
1476
1507
|
// ../../node_modules/multiformats/dist/src/hashes/hasher.js
|
|
1477
1508
|
var DEFAULT_MIN_DIGEST_LENGTH = 20;
|
|
@@ -1521,16 +1552,19 @@ function createDigest(digest2, code2, truncate) {
|
|
|
1521
1552
|
return create(code2, digest2);
|
|
1522
1553
|
}
|
|
1523
1554
|
|
|
1524
|
-
// ../../node_modules/multiformats/dist/src/hashes/sha2.js
|
|
1555
|
+
// ../../node_modules/multiformats/dist/src/hashes/sha2-browser.js
|
|
1556
|
+
function sha(name2) {
|
|
1557
|
+
return async (data) => new Uint8Array(await crypto.subtle.digest(name2, data));
|
|
1558
|
+
}
|
|
1525
1559
|
var sha2562 = from2({
|
|
1526
1560
|
name: "sha2-256",
|
|
1527
1561
|
code: 18,
|
|
1528
|
-
encode: (
|
|
1562
|
+
encode: sha("SHA-256")
|
|
1529
1563
|
});
|
|
1530
1564
|
var sha512 = from2({
|
|
1531
1565
|
name: "sha2-512",
|
|
1532
1566
|
code: 19,
|
|
1533
|
-
encode: (
|
|
1567
|
+
encode: sha("SHA-512")
|
|
1534
1568
|
});
|
|
1535
1569
|
|
|
1536
1570
|
// ../../node_modules/multiformats/dist/src/cid.js
|
|
@@ -1872,7 +1906,7 @@ var cidSymbol = /* @__PURE__ */ Symbol.for("@ipld/js-cid/CID");
|
|
|
1872
1906
|
|
|
1873
1907
|
// ../../node_modules/multiformats/dist/src/basics.js
|
|
1874
1908
|
var bases = { ...identity_exports, ...base2_exports, ...base8_exports, ...base10_exports, ...base16_exports, ...base32_exports, ...base36_exports, ...base58_exports, ...base64_exports, ...base256emoji_exports };
|
|
1875
|
-
var hashes = { ...
|
|
1909
|
+
var hashes = { ...sha2_browser_exports, ...identity_exports2 };
|
|
1876
1910
|
|
|
1877
1911
|
// src/policy/signed-object.ts
|
|
1878
1912
|
var import_viem3 = require("viem");
|
|
@@ -1989,17 +2023,17 @@ async function createAndSignSignedObject(input, signer) {
|
|
|
1989
2023
|
}
|
|
1990
2024
|
function createAndSignPolicy(input, signer) {
|
|
1991
2025
|
return createAndSignSignedObject(input, signer).then(
|
|
1992
|
-
(
|
|
2026
|
+
(object2) => validatePolicySignedShape(object2)
|
|
1993
2027
|
);
|
|
1994
2028
|
}
|
|
1995
2029
|
function createAndSignPolicyStatus(input, signer) {
|
|
1996
2030
|
return createAndSignSignedObject(input, signer).then(
|
|
1997
|
-
(
|
|
2031
|
+
(object2) => validatePolicyStatusSignedShape(object2)
|
|
1998
2032
|
);
|
|
1999
2033
|
}
|
|
2000
2034
|
function createAndSignPolicyEngineRecord(input, signer) {
|
|
2001
2035
|
return createAndSignSignedObject(input, signer).then(
|
|
2002
|
-
(
|
|
2036
|
+
(object2) => validatePolicyEngineRecordSignedShape(object2)
|
|
2003
2037
|
);
|
|
2004
2038
|
}
|
|
2005
2039
|
async function verifySignedObject(input) {
|
|
@@ -2103,9 +2137,9 @@ function validateUnsignedForDescriptor(input, descriptor) {
|
|
|
2103
2137
|
}
|
|
2104
2138
|
}
|
|
2105
2139
|
function validatePolicyShape(input, signed) {
|
|
2106
|
-
const
|
|
2140
|
+
const object2 = expectJsonObject(normalizeJson(input), "$");
|
|
2107
2141
|
assertExactKeys2(
|
|
2108
|
-
|
|
2142
|
+
object2,
|
|
2109
2143
|
signed ? [
|
|
2110
2144
|
"schema",
|
|
2111
2145
|
"policyId",
|
|
@@ -2133,30 +2167,30 @@ function validatePolicyShape(input, signed) {
|
|
|
2133
2167
|
],
|
|
2134
2168
|
"$"
|
|
2135
2169
|
);
|
|
2136
|
-
expectConst(requiredString2(
|
|
2170
|
+
expectConst(requiredString2(object2, "schema", "$"), POLICY_SCHEMA, "$.schema");
|
|
2137
2171
|
if (signed) {
|
|
2138
|
-
requiredString2(
|
|
2139
|
-
validateSignature(requiredValue2(
|
|
2172
|
+
requiredString2(object2, "policyId", "$");
|
|
2173
|
+
validateSignature(requiredValue2(object2, "signature", "$"));
|
|
2140
2174
|
}
|
|
2141
|
-
requiredString2(
|
|
2142
|
-
requiredString2(
|
|
2143
|
-
requiredDateString(
|
|
2144
|
-
optionalDateString(
|
|
2145
|
-
validatePolicyResource(requiredValue2(
|
|
2146
|
-
validateExpression(requiredValue2(
|
|
2147
|
-
validateGrant(requiredValue2(
|
|
2148
|
-
if (hasOwn2(
|
|
2149
|
-
validateDisclosure(requiredValue2(
|
|
2175
|
+
requiredString2(object2, "ownerDid", "$");
|
|
2176
|
+
requiredString2(object2, "signingKeyDid", "$");
|
|
2177
|
+
requiredDateString(object2, "createdAt", "$");
|
|
2178
|
+
optionalDateString(object2, "expiresAt", "$");
|
|
2179
|
+
validatePolicyResource(requiredValue2(object2, "resource", "$"), "$.resource");
|
|
2180
|
+
validateExpression(requiredValue2(object2, "when", "$"), "$.when");
|
|
2181
|
+
validateGrant(requiredValue2(object2, "grant", "$"), "$.grant");
|
|
2182
|
+
if (hasOwn2(object2, "disclosure")) {
|
|
2183
|
+
validateDisclosure(requiredValue2(object2, "disclosure", "$"), "$.disclosure");
|
|
2150
2184
|
}
|
|
2151
|
-
if (hasOwn2(
|
|
2152
|
-
validateAudit(requiredValue2(
|
|
2185
|
+
if (hasOwn2(object2, "audit")) {
|
|
2186
|
+
validateAudit(requiredValue2(object2, "audit", "$"), "$.audit");
|
|
2153
2187
|
}
|
|
2154
|
-
return
|
|
2188
|
+
return object2;
|
|
2155
2189
|
}
|
|
2156
2190
|
function validatePolicyStatusShape(input, signed) {
|
|
2157
|
-
const
|
|
2191
|
+
const object2 = expectJsonObject(normalizeJson(input), "$");
|
|
2158
2192
|
assertExactKeys2(
|
|
2159
|
-
|
|
2193
|
+
object2,
|
|
2160
2194
|
signed ? [
|
|
2161
2195
|
"schema",
|
|
2162
2196
|
"statusId",
|
|
@@ -2180,28 +2214,28 @@ function validatePolicyStatusShape(input, signed) {
|
|
|
2180
2214
|
],
|
|
2181
2215
|
"$"
|
|
2182
2216
|
);
|
|
2183
|
-
expectConst(requiredString2(
|
|
2217
|
+
expectConst(requiredString2(object2, "schema", "$"), POLICY_STATUS_SCHEMA, "$.schema");
|
|
2184
2218
|
if (signed) {
|
|
2185
|
-
requiredString2(
|
|
2186
|
-
validateSignature(requiredValue2(
|
|
2219
|
+
requiredString2(object2, "statusId", "$");
|
|
2220
|
+
validateSignature(requiredValue2(object2, "signature", "$"));
|
|
2187
2221
|
}
|
|
2188
|
-
requiredString2(
|
|
2189
|
-
requiredString2(
|
|
2190
|
-
requiredInteger(
|
|
2191
|
-
expectOneOf(requiredString2(
|
|
2222
|
+
requiredString2(object2, "policyId", "$");
|
|
2223
|
+
requiredString2(object2, "ownerDid", "$");
|
|
2224
|
+
requiredInteger(object2, "sequence", "$", 0);
|
|
2225
|
+
expectOneOf(requiredString2(object2, "disposition", "$"), [
|
|
2192
2226
|
"active",
|
|
2193
2227
|
"suspended",
|
|
2194
2228
|
"revoked"
|
|
2195
2229
|
], "$.disposition");
|
|
2196
|
-
requiredDateString(
|
|
2197
|
-
optionalString(
|
|
2198
|
-
requiredString2(
|
|
2199
|
-
return
|
|
2230
|
+
requiredDateString(object2, "effectiveAt", "$");
|
|
2231
|
+
optionalString(object2, "reasonCode", "$");
|
|
2232
|
+
requiredString2(object2, "signingKeyDid", "$");
|
|
2233
|
+
return object2;
|
|
2200
2234
|
}
|
|
2201
2235
|
function validatePolicyEngineRecordShape(input, signed) {
|
|
2202
|
-
const
|
|
2236
|
+
const object2 = expectJsonObject(normalizeJson(input), "$");
|
|
2203
2237
|
assertExactKeys2(
|
|
2204
|
-
|
|
2238
|
+
object2,
|
|
2205
2239
|
signed ? [
|
|
2206
2240
|
"schema",
|
|
2207
2241
|
"engineRecordId",
|
|
@@ -2226,44 +2260,44 @@ function validatePolicyEngineRecordShape(input, signed) {
|
|
|
2226
2260
|
"$"
|
|
2227
2261
|
);
|
|
2228
2262
|
expectConst(
|
|
2229
|
-
requiredString2(
|
|
2263
|
+
requiredString2(object2, "schema", "$"),
|
|
2230
2264
|
POLICY_ENGINE_RECORD_SCHEMA,
|
|
2231
2265
|
"$.schema"
|
|
2232
2266
|
);
|
|
2233
2267
|
if (signed) {
|
|
2234
|
-
requiredString2(
|
|
2235
|
-
validateSignature(requiredValue2(
|
|
2268
|
+
requiredString2(object2, "engineRecordId", "$");
|
|
2269
|
+
validateSignature(requiredValue2(object2, "signature", "$"));
|
|
2236
2270
|
}
|
|
2237
|
-
requiredString2(
|
|
2238
|
-
requiredString2(
|
|
2239
|
-
requiredString2(
|
|
2271
|
+
requiredString2(object2, "ownerDid", "$");
|
|
2272
|
+
requiredString2(object2, "endpoint", "$");
|
|
2273
|
+
requiredString2(object2, "audience", "$");
|
|
2240
2274
|
requiredStringArray(
|
|
2241
|
-
|
|
2275
|
+
object2,
|
|
2242
2276
|
"supportedPolicyVersions",
|
|
2243
2277
|
"$",
|
|
2244
2278
|
(value, path) => expectConst(value, "v0", path)
|
|
2245
2279
|
);
|
|
2246
|
-
requiredStringArray(
|
|
2247
|
-
requiredString2(
|
|
2248
|
-
requiredDateString(
|
|
2249
|
-
return
|
|
2280
|
+
requiredStringArray(object2, "supportedEvidenceVerifiers", "$");
|
|
2281
|
+
requiredString2(object2, "grantIssuerDid", "$");
|
|
2282
|
+
requiredDateString(object2, "expiresAt", "$");
|
|
2283
|
+
return object2;
|
|
2250
2284
|
}
|
|
2251
2285
|
function validateSignature(input) {
|
|
2252
|
-
const
|
|
2253
|
-
assertExactKeys2(
|
|
2254
|
-
const suite = requiredString2(
|
|
2286
|
+
const object2 = expectJsonObject(input, "$.signature");
|
|
2287
|
+
assertExactKeys2(object2, ["suite", "signerDid", "value"], "$.signature");
|
|
2288
|
+
const suite = requiredString2(object2, "suite", "$.signature");
|
|
2255
2289
|
assertSupportedSignatureSuite(suite);
|
|
2256
|
-
const signerDid = requiredString2(
|
|
2257
|
-
const value = requiredString2(
|
|
2290
|
+
const signerDid = requiredString2(object2, "signerDid", "$.signature");
|
|
2291
|
+
const value = requiredString2(object2, "value", "$.signature");
|
|
2258
2292
|
decodeSignatureValue(value, suite);
|
|
2259
2293
|
return { suite, signerDid, value };
|
|
2260
2294
|
}
|
|
2261
2295
|
function validatePolicyResource(input, path) {
|
|
2262
|
-
const
|
|
2263
|
-
assertExactKeys2(
|
|
2264
|
-
requiredString2(
|
|
2265
|
-
requiredString2(
|
|
2266
|
-
const ceiling = requiredArray2(
|
|
2296
|
+
const object2 = expectJsonObject(input, path);
|
|
2297
|
+
assertExactKeys2(object2, ["resourceType", "resourceId", "permissionsCeiling"], path);
|
|
2298
|
+
requiredString2(object2, "resourceType", path);
|
|
2299
|
+
requiredString2(object2, "resourceId", path);
|
|
2300
|
+
const ceiling = requiredArray2(object2, "permissionsCeiling", path, 1);
|
|
2267
2301
|
for (let index = 0; index < ceiling.length; index++) {
|
|
2268
2302
|
validatePolicyCapability(ceiling[index], `${path}.permissionsCeiling[${index}]`);
|
|
2269
2303
|
}
|
|
@@ -2279,10 +2313,10 @@ function validatePolicyPermissionsCeilingForSigning(input) {
|
|
|
2279
2313
|
}
|
|
2280
2314
|
}
|
|
2281
2315
|
function validatePolicyCapability(input, path) {
|
|
2282
|
-
const
|
|
2316
|
+
const object2 = expectJsonObject(input, path);
|
|
2283
2317
|
try {
|
|
2284
|
-
const canonical = canonicalizePolicyCapability(
|
|
2285
|
-
if (jcsCanonicalize(
|
|
2318
|
+
const canonical = canonicalizePolicyCapability(object2);
|
|
2319
|
+
if (jcsCanonicalize(object2) !== jcsCanonicalize(canonical)) {
|
|
2286
2320
|
throw new SignedObjectSchemaError(`${path} must be canonical PolicyCapability JSON`);
|
|
2287
2321
|
}
|
|
2288
2322
|
} catch (error) {
|
|
@@ -2295,10 +2329,10 @@ function validatePolicyCapability(input, path) {
|
|
|
2295
2329
|
}
|
|
2296
2330
|
}
|
|
2297
2331
|
function validatePolicyCapabilityForSigning(input, path) {
|
|
2298
|
-
const
|
|
2332
|
+
const object2 = expectJsonObject(input, path);
|
|
2299
2333
|
try {
|
|
2300
|
-
const canonical = normalizePolicyCapability(
|
|
2301
|
-
if (jcsCanonicalize(
|
|
2334
|
+
const canonical = normalizePolicyCapability(object2);
|
|
2335
|
+
if (jcsCanonicalize(object2) !== jcsCanonicalize(canonical)) {
|
|
2302
2336
|
throw new SignedObjectSchemaError(`${path} must be strict canonical PolicyCapability JSON`);
|
|
2303
2337
|
}
|
|
2304
2338
|
} catch (error) {
|
|
@@ -2311,43 +2345,43 @@ function validatePolicyCapabilityForSigning(input, path) {
|
|
|
2311
2345
|
}
|
|
2312
2346
|
}
|
|
2313
2347
|
function validateExpression(input, path) {
|
|
2314
|
-
const
|
|
2315
|
-
const keys = Object.keys(
|
|
2348
|
+
const object2 = expectJsonObject(input, path);
|
|
2349
|
+
const keys = Object.keys(object2);
|
|
2316
2350
|
if (keys.length !== 1) {
|
|
2317
2351
|
throw new SignedObjectSchemaError(`${path} must have exactly one expression key`);
|
|
2318
2352
|
}
|
|
2319
2353
|
const key = keys[0];
|
|
2320
2354
|
if (key === "allOf" || key === "anyOf") {
|
|
2321
|
-
const values = requiredArray2(
|
|
2355
|
+
const values = requiredArray2(object2, key, path, 1);
|
|
2322
2356
|
for (let index = 0; index < values.length; index++) {
|
|
2323
2357
|
validateExpression(values[index], `${path}.${key}[${index}]`);
|
|
2324
2358
|
}
|
|
2325
2359
|
return;
|
|
2326
2360
|
}
|
|
2327
2361
|
if (key === "subject") {
|
|
2328
|
-
const subject = expectJsonObject(requiredValue2(
|
|
2362
|
+
const subject = expectJsonObject(requiredValue2(object2, "subject", path), `${path}.subject`);
|
|
2329
2363
|
assertExactKeys2(subject, ["did"], `${path}.subject`);
|
|
2330
2364
|
requiredString2(subject, "did", `${path}.subject`);
|
|
2331
2365
|
return;
|
|
2332
2366
|
}
|
|
2333
2367
|
if (key === "evidence") {
|
|
2334
|
-
validateEvidenceRequirement(requiredValue2(
|
|
2368
|
+
validateEvidenceRequirement(requiredValue2(object2, "evidence", path), `${path}.evidence`);
|
|
2335
2369
|
return;
|
|
2336
2370
|
}
|
|
2337
2371
|
throw new SignedObjectSchemaError(`${path} has unknown expression key ${key}`);
|
|
2338
2372
|
}
|
|
2339
2373
|
function validateEvidenceRequirement(input, path) {
|
|
2340
|
-
const
|
|
2374
|
+
const object2 = expectJsonObject(input, path);
|
|
2341
2375
|
assertExactKeys2(
|
|
2342
|
-
|
|
2376
|
+
object2,
|
|
2343
2377
|
["requirementId", "verifier", "requirements", "authority", "freshness"],
|
|
2344
2378
|
path
|
|
2345
2379
|
);
|
|
2346
|
-
requiredString2(
|
|
2347
|
-
requiredString2(
|
|
2348
|
-
requiredValue2(
|
|
2349
|
-
if (hasOwn2(
|
|
2350
|
-
const authority = expectJsonObject(requiredValue2(
|
|
2380
|
+
requiredString2(object2, "requirementId", path);
|
|
2381
|
+
requiredString2(object2, "verifier", path);
|
|
2382
|
+
requiredValue2(object2, "requirements", path);
|
|
2383
|
+
if (hasOwn2(object2, "authority")) {
|
|
2384
|
+
const authority = expectJsonObject(requiredValue2(object2, "authority", path), `${path}.authority`);
|
|
2351
2385
|
assertExactKeys2(
|
|
2352
2386
|
authority,
|
|
2353
2387
|
["profile", "acceptedIssuers", "allowOwnerAuthorizedIssuer"],
|
|
@@ -2359,35 +2393,35 @@ function validateEvidenceRequirement(input, path) {
|
|
|
2359
2393
|
}
|
|
2360
2394
|
optionalBoolean(authority, "allowOwnerAuthorizedIssuer", `${path}.authority`);
|
|
2361
2395
|
}
|
|
2362
|
-
if (hasOwn2(
|
|
2363
|
-
const freshness = expectJsonObject(requiredValue2(
|
|
2396
|
+
if (hasOwn2(object2, "freshness")) {
|
|
2397
|
+
const freshness = expectJsonObject(requiredValue2(object2, "freshness", path), `${path}.freshness`);
|
|
2364
2398
|
assertExactKeys2(freshness, ["maxStatusAgeSeconds"], `${path}.freshness`);
|
|
2365
2399
|
requiredInteger(freshness, "maxStatusAgeSeconds", `${path}.freshness`, 0);
|
|
2366
2400
|
}
|
|
2367
2401
|
}
|
|
2368
2402
|
function validateGrant(input, path) {
|
|
2369
|
-
const
|
|
2370
|
-
assertExactKeys2(
|
|
2371
|
-
expectConst(requiredString2(
|
|
2372
|
-
requiredInteger(
|
|
2373
|
-
expectOneOf(requiredString2(
|
|
2403
|
+
const object2 = expectJsonObject(input, path);
|
|
2404
|
+
assertExactKeys2(object2, ["output", "maxTtlSeconds", "delegationMode", "revocation"], path);
|
|
2405
|
+
expectConst(requiredString2(object2, "output", path), "portable-delegation", `${path}.output`);
|
|
2406
|
+
requiredInteger(object2, "maxTtlSeconds", path, 1);
|
|
2407
|
+
expectOneOf(requiredString2(object2, "delegationMode", path), [
|
|
2374
2408
|
"terminal",
|
|
2375
2409
|
"attenuable"
|
|
2376
2410
|
], `${path}.delegationMode`);
|
|
2377
|
-
expectOneOf(requiredString2(
|
|
2411
|
+
expectOneOf(requiredString2(object2, "revocation", path), [
|
|
2378
2412
|
"refresh_only",
|
|
2379
2413
|
"active_cutoff"
|
|
2380
2414
|
], `${path}.revocation`);
|
|
2381
2415
|
}
|
|
2382
2416
|
function validateDisclosure(input, path) {
|
|
2383
|
-
const
|
|
2384
|
-
assertExactKeys2(
|
|
2385
|
-
expectOneOf(requiredString2(
|
|
2417
|
+
const object2 = expectJsonObject(input, path);
|
|
2418
|
+
assertExactKeys2(object2, ["denial"], path);
|
|
2419
|
+
expectOneOf(requiredString2(object2, "denial", path), ["none", "code", "debug"], `${path}.denial`);
|
|
2386
2420
|
}
|
|
2387
2421
|
function validateAudit(input, path) {
|
|
2388
|
-
const
|
|
2389
|
-
assertExactKeys2(
|
|
2390
|
-
expectOneOf(requiredString2(
|
|
2422
|
+
const object2 = expectJsonObject(input, path);
|
|
2423
|
+
assertExactKeys2(object2, ["issuance"], path);
|
|
2424
|
+
expectOneOf(requiredString2(object2, "issuance", path), ["off", "security", "full"], `${path}.issuance`);
|
|
2391
2425
|
}
|
|
2392
2426
|
function materialForUnsigned(unsigned, descriptor) {
|
|
2393
2427
|
const jcs = jcsCanonicalize(unsigned);
|
|
@@ -2536,9 +2570,9 @@ function encodeSignatureValue(value, suite) {
|
|
|
2536
2570
|
decodeSignatureValue(encoded, suite);
|
|
2537
2571
|
return encoded;
|
|
2538
2572
|
}
|
|
2539
|
-
function stripOwnIdAndSignature(
|
|
2573
|
+
function stripOwnIdAndSignature(object2, descriptor) {
|
|
2540
2574
|
const output = /* @__PURE__ */ Object.create(null);
|
|
2541
|
-
for (const [key, value] of Object.entries(
|
|
2575
|
+
for (const [key, value] of Object.entries(object2)) {
|
|
2542
2576
|
if (key === descriptor.idField || key === "signature") {
|
|
2543
2577
|
continue;
|
|
2544
2578
|
}
|
|
@@ -2547,8 +2581,8 @@ function stripOwnIdAndSignature(object, descriptor) {
|
|
|
2547
2581
|
return output;
|
|
2548
2582
|
}
|
|
2549
2583
|
function descriptorForUnsigned(input) {
|
|
2550
|
-
const
|
|
2551
|
-
return descriptorForSchema(requiredString2(
|
|
2584
|
+
const object2 = expectJsonObject(normalizeJson(input), "$");
|
|
2585
|
+
return descriptorForSchema(requiredString2(object2, "schema", "$"));
|
|
2552
2586
|
}
|
|
2553
2587
|
function descriptorForSchema(schema) {
|
|
2554
2588
|
if (schema === POLICY_SCHEMA) return DESCRIPTORS.Policy;
|
|
@@ -2562,28 +2596,28 @@ function expectJsonObject(input, path) {
|
|
|
2562
2596
|
}
|
|
2563
2597
|
return input;
|
|
2564
2598
|
}
|
|
2565
|
-
function assertExactKeys2(
|
|
2599
|
+
function assertExactKeys2(object2, allowed, path) {
|
|
2566
2600
|
const allowedSet = new Set(allowed);
|
|
2567
|
-
for (const key of Object.keys(
|
|
2601
|
+
for (const key of Object.keys(object2)) {
|
|
2568
2602
|
if (!allowedSet.has(key)) {
|
|
2569
2603
|
throw new SignedObjectSchemaError(`${path} has unknown field ${key}`);
|
|
2570
2604
|
}
|
|
2571
2605
|
}
|
|
2572
2606
|
}
|
|
2573
|
-
function requiredValue2(
|
|
2574
|
-
if (!hasOwn2(
|
|
2607
|
+
function requiredValue2(object2, key, path) {
|
|
2608
|
+
if (!hasOwn2(object2, key)) {
|
|
2575
2609
|
throw new SignedObjectSchemaError(`${path}.${key} is required`);
|
|
2576
2610
|
}
|
|
2577
|
-
return
|
|
2611
|
+
return object2[key];
|
|
2578
2612
|
}
|
|
2579
|
-
function requiredString2(
|
|
2580
|
-
return requireStringType(requiredValue2(
|
|
2613
|
+
function requiredString2(object2, key, path) {
|
|
2614
|
+
return requireStringType(requiredValue2(object2, key, path), `${path}.${key}`);
|
|
2581
2615
|
}
|
|
2582
|
-
function optionalString(
|
|
2583
|
-
if (!hasOwn2(
|
|
2616
|
+
function optionalString(object2, key, path) {
|
|
2617
|
+
if (!hasOwn2(object2, key)) {
|
|
2584
2618
|
return;
|
|
2585
2619
|
}
|
|
2586
|
-
requireStringType(requiredValue2(
|
|
2620
|
+
requireStringType(requiredValue2(object2, key, path), `${path}.${key}`);
|
|
2587
2621
|
}
|
|
2588
2622
|
function requireStringType(value, path) {
|
|
2589
2623
|
if (typeof value !== "string" || value.length === 0) {
|
|
@@ -2591,16 +2625,16 @@ function requireStringType(value, path) {
|
|
|
2591
2625
|
}
|
|
2592
2626
|
return value;
|
|
2593
2627
|
}
|
|
2594
|
-
function optionalBoolean(
|
|
2595
|
-
if (!hasOwn2(
|
|
2628
|
+
function optionalBoolean(object2, key, path) {
|
|
2629
|
+
if (!hasOwn2(object2, key)) {
|
|
2596
2630
|
return;
|
|
2597
2631
|
}
|
|
2598
|
-
if (typeof requiredValue2(
|
|
2632
|
+
if (typeof requiredValue2(object2, key, path) !== "boolean") {
|
|
2599
2633
|
throw new SignedObjectSchemaError(`${path}.${key} must be a boolean`);
|
|
2600
2634
|
}
|
|
2601
2635
|
}
|
|
2602
|
-
function requiredInteger(
|
|
2603
|
-
const value = requiredValue2(
|
|
2636
|
+
function requiredInteger(object2, key, path, minimum) {
|
|
2637
|
+
const value = requiredValue2(object2, key, path);
|
|
2604
2638
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < minimum) {
|
|
2605
2639
|
throw new SignedObjectSchemaError(
|
|
2606
2640
|
`${path}.${key} must be an integer >= ${minimum}`
|
|
@@ -2608,8 +2642,8 @@ function requiredInteger(object, key, path, minimum) {
|
|
|
2608
2642
|
}
|
|
2609
2643
|
return value;
|
|
2610
2644
|
}
|
|
2611
|
-
function requiredArray2(
|
|
2612
|
-
const value = requiredValue2(
|
|
2645
|
+
function requiredArray2(object2, key, path, minimum) {
|
|
2646
|
+
const value = requiredValue2(object2, key, path);
|
|
2613
2647
|
if (!Array.isArray(value) || value.length < minimum) {
|
|
2614
2648
|
throw new SignedObjectSchemaError(
|
|
2615
2649
|
`${path}.${key} must be an array with at least ${minimum} item(s)`
|
|
@@ -2617,22 +2651,22 @@ function requiredArray2(object, key, path, minimum) {
|
|
|
2617
2651
|
}
|
|
2618
2652
|
return value;
|
|
2619
2653
|
}
|
|
2620
|
-
function requiredStringArray(
|
|
2621
|
-
const values = requiredArray2(
|
|
2654
|
+
function requiredStringArray(object2, key, path, check) {
|
|
2655
|
+
const values = requiredArray2(object2, key, path, 0);
|
|
2622
2656
|
for (let index = 0; index < values.length; index++) {
|
|
2623
2657
|
const itemPath = `${path}.${key}[${index}]`;
|
|
2624
2658
|
const value = requireStringType(values[index], itemPath);
|
|
2625
2659
|
check?.(value, itemPath);
|
|
2626
2660
|
}
|
|
2627
2661
|
}
|
|
2628
|
-
function requiredDateString(
|
|
2629
|
-
assertRfc3339(requiredString2(
|
|
2662
|
+
function requiredDateString(object2, key, path) {
|
|
2663
|
+
assertRfc3339(requiredString2(object2, key, path), `${path}.${key}`);
|
|
2630
2664
|
}
|
|
2631
|
-
function optionalDateString(
|
|
2632
|
-
if (!hasOwn2(
|
|
2665
|
+
function optionalDateString(object2, key, path) {
|
|
2666
|
+
if (!hasOwn2(object2, key)) {
|
|
2633
2667
|
return;
|
|
2634
2668
|
}
|
|
2635
|
-
assertRfc3339(requiredString2(
|
|
2669
|
+
assertRfc3339(requiredString2(object2, key, path), `${path}.${key}`);
|
|
2636
2670
|
}
|
|
2637
2671
|
function assertRfc3339(value, path) {
|
|
2638
2672
|
const match = value.match(
|
|
@@ -2664,8 +2698,8 @@ function expectOneOf(actual, allowed, path) {
|
|
|
2664
2698
|
}
|
|
2665
2699
|
throw new SignedObjectSchemaError(`${path} has unsupported value ${actual}`);
|
|
2666
2700
|
}
|
|
2667
|
-
function hasOwn2(
|
|
2668
|
-
return objectHasOwn3(
|
|
2701
|
+
function hasOwn2(object2, key) {
|
|
2702
|
+
return objectHasOwn3(object2, key);
|
|
2669
2703
|
}
|
|
2670
2704
|
function assertSupportedSignatureSuite(suite) {
|
|
2671
2705
|
if (suite !== ED25519_JCS_SIGNATURE_SUITE && suite !== EIP191_JCS_SIGNATURE_SUITE) {
|
|
@@ -2744,13 +2778,13 @@ function base64UrlDecode(value) {
|
|
|
2744
2778
|
return decoded;
|
|
2745
2779
|
}
|
|
2746
2780
|
function hexToBytes(value) {
|
|
2747
|
-
const
|
|
2748
|
-
if (
|
|
2781
|
+
const hex2 = value.slice(2);
|
|
2782
|
+
if (hex2.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex2)) {
|
|
2749
2783
|
throw new SignatureMaterialError("hex signature must have even length");
|
|
2750
2784
|
}
|
|
2751
|
-
const output = new Uint8Array(
|
|
2785
|
+
const output = new Uint8Array(hex2.length / 2);
|
|
2752
2786
|
for (let index = 0; index < output.length; index++) {
|
|
2753
|
-
output[index] = Number.parseInt(
|
|
2787
|
+
output[index] = Number.parseInt(hex2.slice(index * 2, index * 2 + 2), 16);
|
|
2754
2788
|
}
|
|
2755
2789
|
return output;
|
|
2756
2790
|
}
|
|
@@ -3101,9 +3135,9 @@ function expectPolicyEngineRecord(input) {
|
|
|
3101
3135
|
);
|
|
3102
3136
|
}
|
|
3103
3137
|
}
|
|
3104
|
-
function assertExactKeys3(
|
|
3138
|
+
function assertExactKeys3(object2, allowed, path) {
|
|
3105
3139
|
const allowedSet = new Set(allowed);
|
|
3106
|
-
for (const key of Object.keys(
|
|
3140
|
+
for (const key of Object.keys(object2)) {
|
|
3107
3141
|
if (!allowedSet.has(key)) {
|
|
3108
3142
|
throw new PolicyAuthoringError(
|
|
3109
3143
|
"policy-authoring-unknown-key",
|
|
@@ -3112,17 +3146,17 @@ function assertExactKeys3(object, allowed, path) {
|
|
|
3112
3146
|
}
|
|
3113
3147
|
}
|
|
3114
3148
|
}
|
|
3115
|
-
function requiredValue3(
|
|
3116
|
-
if (!hasOwn3(
|
|
3149
|
+
function requiredValue3(object2, key, path) {
|
|
3150
|
+
if (!hasOwn3(object2, key)) {
|
|
3117
3151
|
throw new PolicyAuthoringError(
|
|
3118
3152
|
"policy-authoring-malformed",
|
|
3119
3153
|
`${path}.${key} is required`
|
|
3120
3154
|
);
|
|
3121
3155
|
}
|
|
3122
|
-
return
|
|
3156
|
+
return object2[key];
|
|
3123
3157
|
}
|
|
3124
|
-
function requiredString3(
|
|
3125
|
-
const value = requiredValue3(
|
|
3158
|
+
function requiredString3(object2, key, path) {
|
|
3159
|
+
const value = requiredValue3(object2, key, path);
|
|
3126
3160
|
if (typeof value !== "string" || value.length === 0) {
|
|
3127
3161
|
throw new PolicyAuthoringError(
|
|
3128
3162
|
"policy-authoring-malformed",
|
|
@@ -3131,11 +3165,11 @@ function requiredString3(object, key, path) {
|
|
|
3131
3165
|
}
|
|
3132
3166
|
return value;
|
|
3133
3167
|
}
|
|
3134
|
-
function fieldString(
|
|
3135
|
-
if (!hasOwn3(
|
|
3168
|
+
function fieldString(object2, key, path, code2) {
|
|
3169
|
+
if (!hasOwn3(object2, key)) {
|
|
3136
3170
|
throw new PolicyAuthoringError(code2, `${path}.${key} is required`);
|
|
3137
3171
|
}
|
|
3138
|
-
const value =
|
|
3172
|
+
const value = object2[key];
|
|
3139
3173
|
if (typeof value !== "string" || value.length === 0) {
|
|
3140
3174
|
throw new PolicyAuthoringError(
|
|
3141
3175
|
code2,
|
|
@@ -3144,8 +3178,8 @@ function fieldString(object, key, path, code2) {
|
|
|
3144
3178
|
}
|
|
3145
3179
|
return value;
|
|
3146
3180
|
}
|
|
3147
|
-
function requiredObject(
|
|
3148
|
-
const value = requiredValue3(
|
|
3181
|
+
function requiredObject(object2, key, path) {
|
|
3182
|
+
const value = requiredValue3(object2, key, path);
|
|
3149
3183
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
3150
3184
|
throw new PolicyAuthoringError(
|
|
3151
3185
|
"policy-authoring-malformed",
|
|
@@ -3154,8 +3188,8 @@ function requiredObject(object, key, path) {
|
|
|
3154
3188
|
}
|
|
3155
3189
|
return value;
|
|
3156
3190
|
}
|
|
3157
|
-
function requiredArray3(
|
|
3158
|
-
const value = requiredValue3(
|
|
3191
|
+
function requiredArray3(object2, key, path) {
|
|
3192
|
+
const value = requiredValue3(object2, key, path);
|
|
3159
3193
|
if (!Array.isArray(value)) {
|
|
3160
3194
|
throw new PolicyAuthoringError(
|
|
3161
3195
|
"policy-authoring-malformed",
|
|
@@ -3164,8 +3198,8 @@ function requiredArray3(object, key, path) {
|
|
|
3164
3198
|
}
|
|
3165
3199
|
return value;
|
|
3166
3200
|
}
|
|
3167
|
-
function requiredStringArray2(
|
|
3168
|
-
const values = requiredArray3(
|
|
3201
|
+
function requiredStringArray2(object2, key, path) {
|
|
3202
|
+
const values = requiredArray3(object2, key, path);
|
|
3169
3203
|
return values.map((value, index) => {
|
|
3170
3204
|
if (typeof value !== "string" || value.length === 0) {
|
|
3171
3205
|
throw new PolicyAuthoringError(
|
|
@@ -3262,63 +3296,657 @@ function parseStrictRfc3339(value, path) {
|
|
|
3262
3296
|
var objectHasOwn4 = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
|
|
3263
3297
|
Object.prototype.hasOwnProperty
|
|
3264
3298
|
);
|
|
3265
|
-
function hasOwn3(
|
|
3266
|
-
return objectHasOwn4(
|
|
3267
|
-
}
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3299
|
+
function hasOwn3(object2, key) {
|
|
3300
|
+
return objectHasOwn4(object2, key);
|
|
3301
|
+
}
|
|
3302
|
+
|
|
3303
|
+
// src/policy/unified.ts
|
|
3304
|
+
var import_sha256 = require("@noble/hashes/sha256");
|
|
3305
|
+
var import_blake3 = require("@noble/hashes/blake3");
|
|
3306
|
+
var import_ed255192 = require("@noble/curves/ed25519");
|
|
3307
|
+
var import_zod = require("zod");
|
|
3308
|
+
var POLICY_V1_SCHEMA = "xyz.tinycloud.policy/policy/v1";
|
|
3309
|
+
var POLICY_CAPABILITY_V1_SCHEMA = "xyz.tinycloud.policy/capability/v1";
|
|
3310
|
+
var POLICY_ENFORCEMENT_DELEGATION_V2_SCHEMA = "xyz.tinycloud.policy/enforcement-delegation/v2";
|
|
3311
|
+
var ATTESTED_ENFORCER_BINDING_V2_SCHEMA = "xyz.tinycloud.policy/attested-enforcer/v2";
|
|
3312
|
+
var ROOT_STATUS_CHECKPOINT_V1_SCHEMA = "xyz.tinycloud.policy/root-status/v1";
|
|
3313
|
+
var ROOT_REVOCATION_V1_SCHEMA = "xyz.tinycloud.policy/root-revocation/v1";
|
|
3314
|
+
var POLICY_SESSION_UCAN_V1_PROFILE = "policy-session-ucan/v1";
|
|
3315
|
+
var POLICY_V1_DOMAIN = "xyz.tinycloud.policy/policy/v1\0";
|
|
3316
|
+
var POLICY_CAPABILITY_V1_DOMAIN = "xyz.tinycloud.policy/PolicyCapability/v1\0";
|
|
3317
|
+
var CONTENT_SOURCE_V1_DOMAIN = "xyz.tinycloud.policy/ContentSource/v1\0";
|
|
3318
|
+
var NATIVE_PROJECTION_V1_DOMAIN = "xyz.tinycloud.policy/NativeProjection/v1\0";
|
|
3319
|
+
var ROOT_STATUS_V1_DOMAIN = "xyz.tinycloud.policy/RootStatusCheckpoint/v1\0";
|
|
3320
|
+
var ROOT_STATUS_RENEWAL_V1_DOMAIN = "xyz.tinycloud.policy/RootStatusRenewal/v1\0";
|
|
3321
|
+
var ROOT_REVOCATION_V1_DOMAIN = "xyz.tinycloud.policy/RootRevocation/v1\0";
|
|
3322
|
+
var LAST_V2_CREATE_AT = "2026-09-30T00:00:00Z";
|
|
3323
|
+
var MAX_LEGACY_ENVELOPE_EXPIRES_AT = "2026-12-29T00:00:00Z";
|
|
3324
|
+
var LAST_V2_READ_AT = "2027-01-05T00:00:00Z";
|
|
3325
|
+
async function requestPolicyChallengeV3(input) {
|
|
3326
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3327
|
+
const response = await fetchFn(new URL("/share/v3/policy/challenges", input.nodeOrigin), {
|
|
3328
|
+
method: "POST",
|
|
3329
|
+
redirect: "error",
|
|
3330
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3331
|
+
body: JSON.stringify({ policyCid: input.policyCid, recipientDid: input.recipientDid, requestedCapabilities: input.requestedCapabilities.map(normalizeUnifiedPolicyCapability) })
|
|
3332
|
+
});
|
|
3333
|
+
if (!response.ok) throw new Error(`policy challenge rejected (${response.status})`);
|
|
3334
|
+
const value = object(await response.json(), "policy challenge");
|
|
3335
|
+
if (typeof value.challengeId !== "string" || typeof value.nonce !== "string" || value.policyCid !== input.policyCid || value.recipientDid !== input.recipientDid)
|
|
3336
|
+
throw new Error("policy challenge binding is invalid");
|
|
3337
|
+
return value;
|
|
3338
|
+
}
|
|
3339
|
+
async function mintPolicySessionV3(input) {
|
|
3340
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3341
|
+
const challenge = input.challenge ?? await requestPolicyChallengeV3(input);
|
|
3342
|
+
if (challenge.policyCid !== input.policyCid || challenge.recipientDid !== input.recipientDid)
|
|
3343
|
+
throw new Error("policy challenge binding is invalid");
|
|
3344
|
+
const response = await fetchFn(new URL("/share/v3/policy/delegations", input.nodeOrigin), {
|
|
3345
|
+
method: "POST",
|
|
3346
|
+
redirect: "error",
|
|
3347
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3348
|
+
body: JSON.stringify({ policyCid: input.policyCid, challengeId: challenge.challengeId, nonce: challenge.nonce, claim: input.claim, presentation: input.presentation })
|
|
3349
|
+
});
|
|
3350
|
+
if (!response.ok) throw new Error(`policy delegation rejected (${response.status})`);
|
|
3351
|
+
const value = object(await response.json(), "policy delegation");
|
|
3352
|
+
if (value.admitted !== true || typeof value.sessionCid !== "string" || typeof value.authorization !== "string")
|
|
3353
|
+
throw new Error("policy delegation response is invalid");
|
|
3354
|
+
const session = parsePolicySessionUcan(value.authorization, [input.policyRootCid, input.enforcementRootCid]);
|
|
3355
|
+
const expectedAttenuation = compactAttenuationForPolicyCapabilities(input.requestedCapabilities);
|
|
3356
|
+
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))
|
|
3357
|
+
throw new Error("policy delegation signed binding is invalid");
|
|
3358
|
+
return session;
|
|
3359
|
+
}
|
|
3360
|
+
function compactAttenuationForPolicyCapabilities(input) {
|
|
3361
|
+
const attenuation = {};
|
|
3362
|
+
for (const raw of input) {
|
|
3363
|
+
const capability = normalizeUnifiedPolicyCapability(raw);
|
|
3364
|
+
if (attenuation[capability.resource] !== void 0)
|
|
3365
|
+
throw new Error("policy capabilities contain a duplicate resource");
|
|
3366
|
+
attenuation[capability.resource] = capability.kind === "encryption" ? { [capability.action]: [{}] } : Object.fromEntries(capability.actions.map((action) => [action, [{
|
|
3367
|
+
type: "xyz.tinycloud.resource/selector",
|
|
3368
|
+
kind: capability.selector,
|
|
3369
|
+
value: capability.resource
|
|
3370
|
+
}]]));
|
|
3371
|
+
}
|
|
3372
|
+
return attenuation;
|
|
3373
|
+
}
|
|
3374
|
+
function verifyPolicyRootStatusCheckpointV3(input) {
|
|
3375
|
+
const checkpoint = input.checkpoint;
|
|
3376
|
+
const allowed = /* @__PURE__ */ new Set(["schema", "targetCid", "targetRole", "ownerDid", "nodeAudience", "state", "sequence", "checkedAt", "freshUntil", "revokedAt", "revocationCid", "previousCheckpointDigestHex", "issuerDid", "signature"]);
|
|
3377
|
+
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;
|
|
3378
|
+
const checkedAt = Date.parse(checkpoint.checkedAt);
|
|
3379
|
+
const freshUntil = Date.parse(checkpoint.freshUntil);
|
|
3380
|
+
const now = (input.now ?? /* @__PURE__ */ new Date()).getTime();
|
|
3381
|
+
if (!Number.isFinite(checkedAt) || !Number.isFinite(freshUntil) || freshUntil < now || freshUntil <= checkedAt || freshUntil - checkedAt > 3e5) return false;
|
|
3382
|
+
if (checkpoint.sequence === 1 !== (checkpoint.previousCheckpointDigestHex === void 0)) return false;
|
|
3383
|
+
if (checkpoint.sequence !== 1 && (typeof checkpoint.previousCheckpointDigestHex !== "string" || !/^[0-9a-f]{64}$/.test(checkpoint.previousCheckpointDigestHex))) return false;
|
|
3384
|
+
if (checkpoint.state === "active" && (checkpoint.revokedAt !== void 0 || checkpoint.revocationCid !== void 0)) return false;
|
|
3385
|
+
if (checkpoint.state === "revoked" && (typeof checkpoint.revokedAt !== "string" || typeof checkpoint.revocationCid !== "string")) return false;
|
|
3386
|
+
const signature = checkpoint.signature;
|
|
3387
|
+
if (!isRecordValue(signature) || Object.keys(signature).length !== 3 || signature.suite !== "Ed25519" || signature.signerDid !== checkpoint.issuerDid || typeof signature.value !== "string") return false;
|
|
3388
|
+
try {
|
|
3389
|
+
const principal = checkpoint.issuerDid.split("#", 1)[0];
|
|
3390
|
+
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
3391
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1) return false;
|
|
3392
|
+
const unsigned = { ...checkpoint };
|
|
3393
|
+
delete unsigned.signature;
|
|
3394
|
+
return import_ed255192.ed25519.verify(
|
|
3395
|
+
decodeBase64Url(signature.value),
|
|
3396
|
+
(0, import_sha256.sha256)(new TextEncoder().encode(ROOT_STATUS_V1_DOMAIN + jcsCanonicalize(unsigned))),
|
|
3397
|
+
didMaterial.slice(2)
|
|
3398
|
+
);
|
|
3399
|
+
} catch {
|
|
3400
|
+
return false;
|
|
3401
|
+
}
|
|
3402
|
+
}
|
|
3403
|
+
async function getPolicyRootStatusV3(input) {
|
|
3404
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3405
|
+
const response = await fetchFn(new URL(`/share/v3/policy/status/${encodeURIComponent(input.rootCid)}`, input.nodeOrigin), {
|
|
3406
|
+
method: "GET",
|
|
3407
|
+
redirect: "error",
|
|
3408
|
+
headers: { accept: "application/json" }
|
|
3409
|
+
});
|
|
3410
|
+
if (!response.ok) throw new Error(`policy root status rejected (${response.status})`);
|
|
3411
|
+
const value = object(await response.json(), "policy root status");
|
|
3412
|
+
const checkpoint = object(value.checkpoint, "policy root checkpoint");
|
|
3413
|
+
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 }))
|
|
3414
|
+
throw new Error("policy root status binding is invalid");
|
|
3415
|
+
const revocation = value.revocation === void 0 ? void 0 : object(value.revocation, "policy root revocation");
|
|
3416
|
+
if (value.state === "revoked" !== (revocation !== void 0) || revocation !== void 0 && !verifyPolicyRootRevocationV3({
|
|
3417
|
+
rootCid: input.rootCid,
|
|
3418
|
+
checkpoint,
|
|
3419
|
+
revocation,
|
|
3420
|
+
expectedEnforcerDid: input.expectedEnforcerDid
|
|
3421
|
+
})) throw new Error("policy root status revocation evidence is invalid");
|
|
3422
|
+
return { rootCid: input.rootCid, state: value.state, checkpoint, ...revocation === void 0 ? {} : { revocation } };
|
|
3423
|
+
}
|
|
3424
|
+
function verifyPolicyRootRevocationV3(input) {
|
|
3425
|
+
const value = input.revocation;
|
|
3426
|
+
const allowed = ["schema", "targetCid", "targetRole", "ownerDid", "nodeAudience", "revokedAt", "reason", "issuerDid", "signature"];
|
|
3427
|
+
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;
|
|
3428
|
+
const authorized = value.issuerDid === value.ownerDid || value.targetRole === "policy-enforcement" && value.issuerDid === input.expectedEnforcerDid;
|
|
3429
|
+
if (!authorized) return false;
|
|
3430
|
+
const signature = value.signature;
|
|
3431
|
+
if (!isRecordValue(signature) || Object.keys(signature).length !== 3 || signature.suite !== "Ed25519" || signature.signerDid !== value.issuerDid || typeof signature.value !== "string") return false;
|
|
3432
|
+
try {
|
|
3433
|
+
const principal = value.issuerDid.split("#", 1)[0];
|
|
3434
|
+
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
3435
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1) return false;
|
|
3436
|
+
const unsigned = { ...value };
|
|
3437
|
+
delete unsigned.signature;
|
|
3438
|
+
const digest2 = (0, import_sha256.sha256)(new TextEncoder().encode(ROOT_REVOCATION_V1_DOMAIN + jcsCanonicalize(unsigned)));
|
|
3439
|
+
return input.checkpoint.revocationCid === hex(digest2) && import_ed255192.ed25519.verify(decodeBase64Url(signature.value), digest2, didMaterial.slice(2));
|
|
3440
|
+
} catch {
|
|
3441
|
+
return false;
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3444
|
+
async function renewPolicyRootStatusV3(input) {
|
|
3445
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3446
|
+
const current = await getPolicyRootStatusV3({ nodeOrigin: input.nodeOrigin, rootCid: input.rootCid, expectedNodeAudience: input.nodeAudience, now: input.now, fetch: fetchFn });
|
|
3447
|
+
if (current.state !== "active" || current.checkpoint.ownerDid !== input.ownerDid || current.checkpoint.nodeAudience !== input.nodeAudience || current.checkpoint.state !== "active" || !Number.isInteger(current.checkpoint.sequence))
|
|
3448
|
+
throw new Error("policy root status cannot be renewed");
|
|
3449
|
+
const currentUnsigned = { ...current.checkpoint };
|
|
3450
|
+
delete currentUnsigned.signature;
|
|
3451
|
+
const previousCheckpointDigestHex = hex((0, import_sha256.sha256)(new TextEncoder().encode(ROOT_STATUS_V1_DOMAIN + jcsCanonicalize(currentUnsigned))));
|
|
3452
|
+
const unsigned = {
|
|
3453
|
+
schema: "xyz.tinycloud.policy/root-status-renewal/v1",
|
|
3454
|
+
targetCid: input.rootCid,
|
|
3455
|
+
ownerDid: input.ownerDid,
|
|
3456
|
+
nodeAudience: input.nodeAudience,
|
|
3457
|
+
issuedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
3458
|
+
nonce: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
3459
|
+
sequence: current.checkpoint.sequence + 1,
|
|
3460
|
+
previousCheckpointDigestHex
|
|
3461
|
+
};
|
|
3462
|
+
const signature = await input.sign((0, import_sha256.sha256)(new TextEncoder().encode(ROOT_STATUS_RENEWAL_V1_DOMAIN + jcsCanonicalize(unsigned))));
|
|
3463
|
+
if (signature.length !== 64) throw new Error("policy root renewal signature must be Ed25519");
|
|
3464
|
+
const response = await fetchFn(new URL("/share/v3/policy/status", input.nodeOrigin), {
|
|
3465
|
+
method: "POST",
|
|
3466
|
+
redirect: "error",
|
|
3467
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3468
|
+
body: JSON.stringify({ rootCid: input.rootCid, renewal: { ...unsigned, signature: { suite: "Ed25519", signerDid: input.ownerDid, value: encodeBase64Url(signature) } } })
|
|
3469
|
+
});
|
|
3470
|
+
if (!response.ok) throw new Error(`policy root renewal rejected (${response.status})`);
|
|
3471
|
+
return object(await response.json(), "policy root renewal");
|
|
3472
|
+
}
|
|
3473
|
+
async function revokePolicyRootV3(input) {
|
|
3474
|
+
if (input.reason.length === 0) throw new Error("policy root revocation reason is required");
|
|
3475
|
+
const unsigned = {
|
|
3476
|
+
schema: ROOT_REVOCATION_V1_SCHEMA,
|
|
3477
|
+
targetCid: input.rootCid,
|
|
3478
|
+
targetRole: input.targetRole,
|
|
3479
|
+
ownerDid: input.ownerDid,
|
|
3480
|
+
nodeAudience: input.nodeAudience,
|
|
3481
|
+
revokedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
3482
|
+
reason: input.reason,
|
|
3483
|
+
issuerDid: input.issuerDid
|
|
3484
|
+
};
|
|
3485
|
+
const signature = await input.sign((0, import_sha256.sha256)(new TextEncoder().encode(ROOT_REVOCATION_V1_DOMAIN + jcsCanonicalize(unsigned))));
|
|
3486
|
+
if (signature.length !== 64) throw new Error("policy root revocation signature must be Ed25519");
|
|
3487
|
+
const fetchFn = input.fetch ?? globalThis.fetch.bind(globalThis);
|
|
3488
|
+
const response = await fetchFn(new URL("/revoke", input.nodeOrigin), {
|
|
3489
|
+
method: "POST",
|
|
3490
|
+
redirect: "error",
|
|
3491
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
3492
|
+
body: JSON.stringify({ revocation: { ...unsigned, signature: { suite: "Ed25519", signerDid: input.issuerDid, value: encodeBase64Url(signature) } } })
|
|
3493
|
+
});
|
|
3494
|
+
if (!response.ok) throw new Error(`policy root revocation rejected (${response.status})`);
|
|
3495
|
+
return object(await response.json(), "policy root revocation");
|
|
3496
|
+
}
|
|
3497
|
+
var POLICY_SESSION_FACT_KEYS = [
|
|
3498
|
+
"profile",
|
|
3499
|
+
"ownerDid",
|
|
3500
|
+
"policyId",
|
|
3501
|
+
"policyDigestHex",
|
|
3502
|
+
"policyCid",
|
|
3503
|
+
"policyDelegationCid",
|
|
3504
|
+
"enforcementDelegationCid",
|
|
3505
|
+
"contentSourceDigestHex",
|
|
3506
|
+
"capabilityCeilingHashHex",
|
|
3507
|
+
"nativeProjectionHashHex",
|
|
3508
|
+
"enforcerDid",
|
|
3509
|
+
"nodeAudience",
|
|
3510
|
+
"recipientDid",
|
|
3511
|
+
"challengeId",
|
|
3512
|
+
"claimDigestHex",
|
|
3513
|
+
"claimJti",
|
|
3514
|
+
"vpDigestHex",
|
|
3515
|
+
"credentialEvidenceDigestHex",
|
|
3516
|
+
"decisionContextDigestHex",
|
|
3517
|
+
"issuanceAuditDigestHex",
|
|
3518
|
+
"remainingRedelegationDepth"
|
|
3519
|
+
];
|
|
3520
|
+
var KV_ACTIONS = /* @__PURE__ */ new Set([
|
|
3521
|
+
"tinycloud.kv/get",
|
|
3522
|
+
"tinycloud.kv/list",
|
|
3523
|
+
"tinycloud.kv/metadata",
|
|
3524
|
+
"tinycloud.kv/put"
|
|
3525
|
+
]);
|
|
3526
|
+
function object(value, label) {
|
|
3527
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
3528
|
+
throw new Error(`${label} must be an object`);
|
|
3529
|
+
}
|
|
3530
|
+
return value;
|
|
3531
|
+
}
|
|
3532
|
+
function exactKeys(value, allowed, label) {
|
|
3533
|
+
const keys = new Set(allowed);
|
|
3534
|
+
if (Object.keys(value).some((key) => !keys.has(key)))
|
|
3535
|
+
throw new Error(`${label} contains an unknown field`);
|
|
3536
|
+
}
|
|
3537
|
+
function nonEmptyString(value, label) {
|
|
3538
|
+
if (typeof value !== "string" || value.length === 0)
|
|
3539
|
+
throw new Error(`${label} must be a non-empty string`);
|
|
3540
|
+
return value;
|
|
3541
|
+
}
|
|
3542
|
+
function parseKvResource(resource) {
|
|
3543
|
+
const match = /^tinycloud:\/\/([^/]+)\/kv\/(.+)$/.exec(resource);
|
|
3544
|
+
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)) {
|
|
3545
|
+
throw new Error("KV resource is not canonical");
|
|
3546
|
+
}
|
|
3547
|
+
return { space: match[1], path: match[2] };
|
|
3548
|
+
}
|
|
3549
|
+
function parseEncryptionResource(resource) {
|
|
3550
|
+
if (!resource.startsWith("urn:tinycloud:encryption:")) throw new Error("encryption capability is invalid");
|
|
3551
|
+
const rest = resource.slice("urn:tinycloud:encryption:".length);
|
|
3552
|
+
const separator = rest.lastIndexOf(":");
|
|
3553
|
+
const ownerDid = separator < 0 ? "" : rest.slice(0, separator);
|
|
3554
|
+
const network = separator < 0 ? "" : rest.slice(separator + 1);
|
|
3555
|
+
if (!ownerDid.startsWith("did:") || network.length === 0 || network.includes(":") || network.includes("/") || network.includes("%") || network.includes("?") || network.includes("#")) {
|
|
3556
|
+
throw new Error("encryption capability is invalid");
|
|
3557
|
+
}
|
|
3558
|
+
}
|
|
3559
|
+
function normalizeUnifiedPolicyCapability(input) {
|
|
3560
|
+
const value = object(input, "capability");
|
|
3561
|
+
const kind = nonEmptyString(value.kind, "capability.kind");
|
|
3562
|
+
if (kind === "kv") {
|
|
3563
|
+
exactKeys(
|
|
3564
|
+
value,
|
|
3565
|
+
["kind", "resource", "selector", "actions"],
|
|
3566
|
+
"KV capability"
|
|
3567
|
+
);
|
|
3568
|
+
const resource = nonEmptyString(value.resource, "capability.resource");
|
|
3569
|
+
parseKvResource(resource);
|
|
3570
|
+
if (value.selector !== "exact" && value.selector !== "prefix")
|
|
3571
|
+
throw new Error("capability.selector is invalid");
|
|
3572
|
+
if (!Array.isArray(value.actions) || value.actions.length === 0)
|
|
3573
|
+
throw new Error("capability.actions is invalid");
|
|
3574
|
+
const actions = value.actions.map(
|
|
3575
|
+
(action) => nonEmptyString(action, "capability.actions[]")
|
|
3576
|
+
);
|
|
3577
|
+
if (new Set(actions).size !== actions.length || actions.some((action) => !KV_ACTIONS.has(action)))
|
|
3578
|
+
throw new Error("capability.actions is invalid");
|
|
3579
|
+
return {
|
|
3580
|
+
kind: "kv",
|
|
3581
|
+
resource,
|
|
3582
|
+
selector: value.selector,
|
|
3583
|
+
actions: [...actions].sort()
|
|
3584
|
+
};
|
|
3585
|
+
}
|
|
3586
|
+
if (kind === "encryption") {
|
|
3587
|
+
exactKeys(value, ["kind", "resource", "action"], "encryption capability");
|
|
3588
|
+
const resource = nonEmptyString(value.resource, "capability.resource");
|
|
3589
|
+
if (value.action !== "tinycloud.encryption/decrypt")
|
|
3590
|
+
throw new Error("encryption capability is invalid");
|
|
3591
|
+
parseEncryptionResource(resource);
|
|
3592
|
+
return {
|
|
3593
|
+
kind: "encryption",
|
|
3594
|
+
resource,
|
|
3595
|
+
action: "tinycloud.encryption/decrypt"
|
|
3596
|
+
};
|
|
3597
|
+
}
|
|
3598
|
+
throw new Error("capability.kind is invalid");
|
|
3599
|
+
}
|
|
3600
|
+
function canonicalizeUnifiedPolicyCapability(input) {
|
|
3601
|
+
return normalizeUnifiedPolicyCapability(input);
|
|
3602
|
+
}
|
|
3603
|
+
function unifiedPolicyCapabilityDigestHex(input) {
|
|
3604
|
+
return hex(
|
|
3605
|
+
(0, import_sha256.sha256)(
|
|
3606
|
+
new TextEncoder().encode(
|
|
3607
|
+
POLICY_CAPABILITY_V1_DOMAIN + jcsCanonicalize(normalizeUnifiedPolicyCapability(input))
|
|
3608
|
+
)
|
|
3609
|
+
)
|
|
3610
|
+
);
|
|
3611
|
+
}
|
|
3612
|
+
function unifiedPolicyCapabilityContains(authorityInput, requestedInput) {
|
|
3613
|
+
try {
|
|
3614
|
+
const authority = normalizeUnifiedPolicyCapability(authorityInput);
|
|
3615
|
+
const requested = normalizeUnifiedPolicyCapability(requestedInput);
|
|
3616
|
+
if (authority.kind !== requested.kind) return false;
|
|
3617
|
+
if (authority.kind === "encryption" && requested.kind === "encryption")
|
|
3618
|
+
return authority.resource === requested.resource && authority.action === requested.action;
|
|
3619
|
+
if (authority.kind !== "kv" || requested.kind !== "kv") return false;
|
|
3620
|
+
const { resource: authorized } = authority;
|
|
3621
|
+
const { resource: requestedResource } = requested;
|
|
3622
|
+
const pathContained = authority.selector === "exact" ? authorized === requestedResource : authorized === requestedResource || requestedResource.startsWith(`${authorized}/`);
|
|
3623
|
+
if (!pathContained || authority.selector === "exact" && requested.selector === "prefix")
|
|
3624
|
+
return false;
|
|
3625
|
+
return requested.actions.every(
|
|
3626
|
+
(action) => authority.actions.includes(action)
|
|
3627
|
+
);
|
|
3628
|
+
} catch {
|
|
3629
|
+
return false;
|
|
3630
|
+
}
|
|
3631
|
+
}
|
|
3632
|
+
function projectUnifiedPolicyCapability(input) {
|
|
3633
|
+
const capability = normalizeUnifiedPolicyCapability(input);
|
|
3634
|
+
if (capability.kind === "encryption") {
|
|
3635
|
+
return {
|
|
3636
|
+
service: "tinycloud.encryption",
|
|
3637
|
+
space: capability.resource,
|
|
3638
|
+
path: capability.resource,
|
|
3639
|
+
actions: [capability.action]
|
|
3640
|
+
};
|
|
3641
|
+
}
|
|
3642
|
+
const { space, path } = parseKvResource(capability.resource);
|
|
3643
|
+
return {
|
|
3644
|
+
service: "tinycloud.kv",
|
|
3645
|
+
space,
|
|
3646
|
+
path,
|
|
3647
|
+
actions: [...capability.actions],
|
|
3648
|
+
caveat: {
|
|
3649
|
+
type: "xyz.tinycloud.resource/selector",
|
|
3650
|
+
kind: capability.selector,
|
|
3651
|
+
value: capability.resource
|
|
3652
|
+
}
|
|
3653
|
+
};
|
|
3654
|
+
}
|
|
3655
|
+
function projectUnifiedPolicyCapabilities(input) {
|
|
3656
|
+
return input.map(projectUnifiedPolicyCapability).sort((left, right) => {
|
|
3657
|
+
const a = jcsCanonicalize(left);
|
|
3658
|
+
const b = jcsCanonicalize(right);
|
|
3659
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
3660
|
+
});
|
|
3661
|
+
}
|
|
3662
|
+
function unifiedNativeProjectionHashHex(input) {
|
|
3663
|
+
return hex(
|
|
3664
|
+
(0, import_sha256.sha256)(
|
|
3665
|
+
new TextEncoder().encode(
|
|
3666
|
+
NATIVE_PROJECTION_V1_DOMAIN + jcsCanonicalize(projectUnifiedPolicyCapabilities(input))
|
|
3667
|
+
)
|
|
3668
|
+
)
|
|
3669
|
+
);
|
|
3670
|
+
}
|
|
3671
|
+
function unifiedPolicyCapabilityFromNative(input) {
|
|
3672
|
+
const value = object(input, "native capability");
|
|
3673
|
+
exactKeys(
|
|
3674
|
+
value,
|
|
3675
|
+
["service", "space", "path", "actions", "caveat"],
|
|
3676
|
+
"native capability"
|
|
3677
|
+
);
|
|
3678
|
+
const service = nonEmptyString(value.service, "native.service");
|
|
3679
|
+
const actions = value.actions;
|
|
3680
|
+
if (!Array.isArray(actions)) throw new Error("native.actions is invalid");
|
|
3681
|
+
if (service === "tinycloud.encryption" && value.caveat === void 0 && value.space === value.path && actions.length === 1 && actions[0] === "tinycloud.encryption/decrypt") {
|
|
3682
|
+
return normalizeUnifiedPolicyCapability({
|
|
3683
|
+
kind: "encryption",
|
|
3684
|
+
resource: value.space,
|
|
3685
|
+
action: actions[0]
|
|
3686
|
+
});
|
|
3687
|
+
}
|
|
3688
|
+
if (service !== "tinycloud.kv" || typeof value.space !== "string" || typeof value.path !== "string")
|
|
3689
|
+
throw new Error("native capability is not supported");
|
|
3690
|
+
const caveat = object(value.caveat, "native.caveat");
|
|
3691
|
+
exactKeys(caveat, ["type", "kind", "value"], "native selector caveat");
|
|
3692
|
+
if (caveat.type !== "xyz.tinycloud.resource/selector" || caveat.kind !== "exact" && caveat.kind !== "prefix" || caveat.value !== `tinycloud://${value.space}/kv/${value.path}`)
|
|
3693
|
+
throw new Error("native selector caveat does not match capability");
|
|
3694
|
+
return normalizeUnifiedPolicyCapability({
|
|
3695
|
+
kind: "kv",
|
|
3696
|
+
resource: caveat.value,
|
|
3697
|
+
selector: caveat.kind,
|
|
3698
|
+
actions
|
|
3699
|
+
});
|
|
3700
|
+
}
|
|
3701
|
+
function contentSourceDigestHex(input) {
|
|
3702
|
+
return hex(
|
|
3703
|
+
(0, import_sha256.sha256)(
|
|
3704
|
+
new TextEncoder().encode(
|
|
3705
|
+
CONTENT_SOURCE_V1_DOMAIN + jcsCanonicalize(input)
|
|
3706
|
+
)
|
|
3707
|
+
)
|
|
3708
|
+
);
|
|
3709
|
+
}
|
|
3710
|
+
function policyDigestHex(policy) {
|
|
3711
|
+
const canonicalPolicy = {
|
|
3712
|
+
...policy,
|
|
3713
|
+
capabilityCeiling: policy.capabilityCeiling.map(
|
|
3714
|
+
normalizeUnifiedPolicyCapability
|
|
3715
|
+
)
|
|
3716
|
+
};
|
|
3717
|
+
return hex(
|
|
3718
|
+
(0, import_sha256.sha256)(
|
|
3719
|
+
new TextEncoder().encode(
|
|
3720
|
+
POLICY_V1_DOMAIN + jcsCanonicalize(canonicalPolicy)
|
|
3721
|
+
)
|
|
3722
|
+
)
|
|
3723
|
+
);
|
|
3724
|
+
}
|
|
3725
|
+
function policyIdForDigestHex(digestHex) {
|
|
3726
|
+
const digest2 = Uint8Array.from(
|
|
3727
|
+
(digestHex.match(/.{2}/g) ?? []).map((byte) => Number.parseInt(byte, 16))
|
|
3728
|
+
);
|
|
3729
|
+
if (digest2.length !== 32) throw new Error("policy digest must be 32 bytes");
|
|
3730
|
+
return `pol_${base32Lower(digest2)}`;
|
|
3731
|
+
}
|
|
3732
|
+
function policyCidFromCanonicalBytes(bytes) {
|
|
3733
|
+
return CID.createV1(85, create(18, (0, import_sha256.sha256)(bytes))).toString();
|
|
3734
|
+
}
|
|
3735
|
+
var CompactHeaderSchema = import_zod.z.object({
|
|
3736
|
+
alg: import_zod.z.literal("EdDSA"),
|
|
3737
|
+
jwk: import_zod.z.object({ alg: import_zod.z.literal("EdDSA"), crv: import_zod.z.literal("Ed25519"), kty: import_zod.z.literal("OKP"), x: import_zod.z.string().min(1) }).strict(),
|
|
3738
|
+
typ: import_zod.z.literal("JWT"),
|
|
3739
|
+
ucv: import_zod.z.literal("0.10.0")
|
|
3740
|
+
}).strict();
|
|
3741
|
+
var CompactPayloadSchema = import_zod.z.object({
|
|
3742
|
+
att: import_zod.z.record(import_zod.z.record(import_zod.z.array(import_zod.z.unknown()).min(1))),
|
|
3743
|
+
aud: import_zod.z.string().min(1),
|
|
3744
|
+
exp: import_zod.z.number().int(),
|
|
3745
|
+
fct: import_zod.z.array(import_zod.z.record(import_zod.z.unknown())).length(1),
|
|
3746
|
+
iss: import_zod.z.string().min(1),
|
|
3747
|
+
nbf: import_zod.z.number().int(),
|
|
3748
|
+
nnc: import_zod.z.string().min(1),
|
|
3749
|
+
prf: import_zod.z.array(import_zod.z.string().min(1))
|
|
3750
|
+
}).strict();
|
|
3751
|
+
async function signCompactUcanAuthorization(input) {
|
|
3752
|
+
if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > 60)
|
|
3753
|
+
throw new Error("compact invocation lifetime must be between one and 60 seconds");
|
|
3754
|
+
const principal = input.issuerDid.split("#", 1)[0];
|
|
3755
|
+
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
3756
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
|
|
3757
|
+
throw new Error("compact UCAN signer must be did:key Ed25519");
|
|
3758
|
+
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(didMaterial.slice(2)) }, typ: "JWT", ucv: "0.10.0" };
|
|
3759
|
+
const payload = {
|
|
3760
|
+
att: input.attenuation,
|
|
3761
|
+
aud: input.audienceDid,
|
|
3762
|
+
exp: input.expiresAt,
|
|
3763
|
+
fct: input.facts,
|
|
3764
|
+
iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
3765
|
+
nbf: input.notBefore,
|
|
3766
|
+
nnc: input.nonce,
|
|
3767
|
+
prf: input.proofs
|
|
3768
|
+
};
|
|
3769
|
+
const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
3770
|
+
const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
3771
|
+
const signature = await input.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`));
|
|
3772
|
+
if (signature.length !== 64) throw new Error("compact Authorization signature must be Ed25519");
|
|
3773
|
+
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
3774
|
+
}
|
|
3775
|
+
function createCompactPolicyInvocation(input) {
|
|
3776
|
+
const session = parsePolicySessionUcan(input.sessionAuthorization);
|
|
3777
|
+
if (session.cid !== input.sessionCid || session.aud !== input.recipientDid)
|
|
3778
|
+
throw new Error("policy session does not bind the recipient signer");
|
|
3779
|
+
const principal = input.recipientDid.split("#", 1)[0];
|
|
3780
|
+
const didMaterial = base58btc.decode(principal.slice("did:key:".length));
|
|
3781
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
|
|
3782
|
+
throw new Error("policy invocation signer must be did:key Ed25519");
|
|
3783
|
+
const publicKey = import_ed255192.ed25519.getPublicKey(input.privateKey);
|
|
3784
|
+
if (!equalBytes(publicKey, didMaterial.slice(2)))
|
|
3785
|
+
throw new Error("policy invocation private key does not bind recipient DID");
|
|
3786
|
+
const now = input.now ?? Math.floor(Date.now() / 1e3);
|
|
3787
|
+
const exp = Math.min(now + 60, session.exp);
|
|
3788
|
+
if (exp <= now) throw new Error("policy session has expired");
|
|
3789
|
+
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
|
|
3790
|
+
const payload = {
|
|
3791
|
+
att: { [input.resource]: { [input.action]: [input.caveat ?? {}] } },
|
|
3792
|
+
aud: input.audienceDid,
|
|
3793
|
+
exp,
|
|
3794
|
+
fct: [input.facts ?? { type: "tinycloud.policy.invocation/v1", policyCid: session.fact.policyCid, sessionCid: session.cid }],
|
|
3795
|
+
iss: input.recipientDid.includes("#") ? input.recipientDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
3796
|
+
nbf: now,
|
|
3797
|
+
nnc: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
3798
|
+
prf: [session.cid]
|
|
3799
|
+
};
|
|
3800
|
+
const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
3801
|
+
const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
3802
|
+
const signingInput = new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`);
|
|
3803
|
+
const signature = import_ed255192.ed25519.sign(signingInput, input.privateKey);
|
|
3804
|
+
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
3805
|
+
}
|
|
3806
|
+
function createCompactPolicyDescendant(input) {
|
|
3807
|
+
const parent = parseCompactUcanAuthorization(input.parentAuthorization, input.parentCid);
|
|
3808
|
+
if (parent.payload.aud !== input.issuerDid) throw new Error("policy descendant issuer is not the parent audience");
|
|
3809
|
+
const parentFact = parent.payload.fct[0];
|
|
3810
|
+
const depth = parentFact.remainingRedelegationDepth;
|
|
3811
|
+
if (!Number.isInteger(depth) || depth <= 0) throw new Error("policy descendant depth is exhausted");
|
|
3812
|
+
if (!compactAttenuationContains(parent.payload.att, input.attenuation))
|
|
3813
|
+
throw new Error("policy descendant exceeds the parent attenuation");
|
|
3814
|
+
const principal = input.issuerDid.split("#", 1)[0];
|
|
3815
|
+
const didMaterial = base58btc.decode(principal.slice("did:key:".length));
|
|
3816
|
+
const publicKey = import_ed255192.ed25519.getPublicKey(input.privateKey);
|
|
3817
|
+
if (didMaterial.length !== 34 || !equalBytes(publicKey, didMaterial.slice(2))) throw new Error("policy descendant signer does not bind issuer DID");
|
|
3818
|
+
const now = Math.max(input.now ?? Math.floor(Date.now() / 1e3), parent.payload.nbf + 1);
|
|
3819
|
+
const exp = Math.min(input.expiresAt ?? now + 60, now + 60, parent.payload.exp - 1);
|
|
3820
|
+
if (exp <= now) throw new Error("policy parent has no strictly narrower validity window");
|
|
3821
|
+
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
|
|
3822
|
+
const payload = {
|
|
3823
|
+
att: input.attenuation,
|
|
3824
|
+
aud: input.audienceDid,
|
|
3825
|
+
exp,
|
|
3826
|
+
fct: [{ ...parentFact, remainingRedelegationDepth: depth - 1 }],
|
|
3827
|
+
iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
3828
|
+
nbf: now,
|
|
3829
|
+
nnc: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
3830
|
+
prf: [parent.cid]
|
|
3831
|
+
};
|
|
3832
|
+
const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
3833
|
+
const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
3834
|
+
const signature = import_ed255192.ed25519.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`), input.privateKey);
|
|
3835
|
+
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
3836
|
+
}
|
|
3837
|
+
function compactAttenuationContains(parent, child) {
|
|
3838
|
+
const selector = (value) => {
|
|
3839
|
+
if (value.length !== 1 || !isRecordValue(value[0])) return void 0;
|
|
3840
|
+
const caveat = value[0];
|
|
3841
|
+
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;
|
|
3842
|
+
return { kind: caveat.kind, value: caveat.value };
|
|
3843
|
+
};
|
|
3844
|
+
const equal = (left, right) => jcsCanonicalize(left) === jcsCanonicalize(right);
|
|
3845
|
+
return Object.entries(child).every(
|
|
3846
|
+
([childResource, childActions]) => Object.entries(childActions).every(
|
|
3847
|
+
([action, childCaveats]) => Object.entries(parent).some(([parentResource, parentActions]) => {
|
|
3848
|
+
const parentCaveats = parentActions[action];
|
|
3849
|
+
if (parentCaveats === void 0) return false;
|
|
3850
|
+
if (parentResource === childResource && equal(parentCaveats, childCaveats)) return true;
|
|
3851
|
+
const parentSelector = selector(parentCaveats);
|
|
3852
|
+
const childSelector = selector(childCaveats);
|
|
3853
|
+
return parentSelector?.kind === "prefix" && childSelector !== void 0 && parentSelector.value === parentResource && childSelector.value === childResource && (childResource === parentResource || childResource.startsWith(`${parentResource}/`));
|
|
3854
|
+
})
|
|
3855
|
+
)
|
|
3856
|
+
);
|
|
3857
|
+
}
|
|
3858
|
+
function isRecordValue(value) {
|
|
3859
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3860
|
+
}
|
|
3861
|
+
function parseCompactUcanAuthorization(input, expectedCid) {
|
|
3862
|
+
if (typeof input !== "string" || /\s/.test(input))
|
|
3863
|
+
throw new Error("Authorization must be compact UCAN bytes");
|
|
3864
|
+
const segments = input.split(".");
|
|
3865
|
+
if (segments.length !== 3 || segments.some((segment) => segment.length === 0))
|
|
3866
|
+
throw new Error("Authorization must have three compact segments");
|
|
3867
|
+
const [headerSegment, payloadSegment, signatureSegment] = segments;
|
|
3868
|
+
const headerBytes = decodeBase64Url(headerSegment);
|
|
3869
|
+
const payloadBytes = decodeBase64Url(payloadSegment);
|
|
3870
|
+
const signature = decodeBase64Url(signatureSegment);
|
|
3871
|
+
const headerValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(headerBytes));
|
|
3872
|
+
const payloadValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(payloadBytes));
|
|
3873
|
+
if (jcsCanonicalize(headerValue) !== new TextDecoder().decode(headerBytes) || jcsCanonicalize(payloadValue) !== new TextDecoder().decode(payloadBytes))
|
|
3874
|
+
throw new Error("compact UCAN segments are not canonical JCS");
|
|
3875
|
+
const header = CompactHeaderSchema.parse(headerValue);
|
|
3876
|
+
const payload = CompactPayloadSchema.parse(payloadValue);
|
|
3877
|
+
if (payload.nbf >= payload.exp) throw new Error("compact UCAN validity is empty");
|
|
3878
|
+
const principal = payload.iss.split("#", 1)[0];
|
|
3879
|
+
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
3880
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
|
|
3881
|
+
throw new Error("compact UCAN issuer must be did:key Ed25519");
|
|
3882
|
+
const publicKey = didMaterial.slice(2);
|
|
3883
|
+
if (!equalBytes(publicKey, decodeBase64Url(header.jwk.x)))
|
|
3884
|
+
throw new Error("compact UCAN JWK does not bind issuer");
|
|
3885
|
+
if (!import_ed255192.ed25519.verify(signature, new TextEncoder().encode(`${headerSegment}.${payloadSegment}`), publicKey))
|
|
3886
|
+
throw new Error("compact UCAN signature is invalid");
|
|
3887
|
+
const cid = CID.createV1(85, create(30, (0, import_blake3.blake3)(new TextEncoder().encode(input)))).toString();
|
|
3888
|
+
if (expectedCid !== void 0 && cid !== expectedCid)
|
|
3889
|
+
throw new Error("compact UCAN CID does not match exact Authorization bytes");
|
|
3890
|
+
return { authorization: input, cid, header, payload };
|
|
3891
|
+
}
|
|
3892
|
+
function parsePolicySessionUcan(authorization, expectedProofs) {
|
|
3893
|
+
const parsed = parseCompactUcanAuthorization(authorization);
|
|
3894
|
+
const fact = parsed.payload.fct[0];
|
|
3895
|
+
if (parsed.payload.prf.length !== 2 || parsed.payload.prf[0] === parsed.payload.prf[1])
|
|
3896
|
+
throw new Error("policy session UCAN requires two distinct ordered proofs");
|
|
3897
|
+
if (expectedProofs !== void 0 && (parsed.payload.prf[0] !== expectedProofs[0] || parsed.payload.prf[1] !== expectedProofs[1]))
|
|
3898
|
+
throw new Error("policy session UCAN ordered proofs do not match");
|
|
3899
|
+
const factKeys = Object.keys(fact);
|
|
3900
|
+
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)))
|
|
3901
|
+
throw new Error("policy session UCAN fact is incomplete");
|
|
3902
|
+
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)
|
|
3903
|
+
throw new Error("policy session UCAN fact is invalid");
|
|
3904
|
+
return {
|
|
3905
|
+
authorization,
|
|
3906
|
+
cid: parsed.cid,
|
|
3907
|
+
iss: parsed.payload.iss,
|
|
3908
|
+
aud: parsed.payload.aud,
|
|
3909
|
+
prf: parsed.payload.prf,
|
|
3910
|
+
att: parsed.payload.att,
|
|
3911
|
+
nbf: parsed.payload.nbf,
|
|
3912
|
+
exp: parsed.payload.exp,
|
|
3913
|
+
nnc: parsed.payload.nnc,
|
|
3914
|
+
fact
|
|
3915
|
+
};
|
|
3916
|
+
}
|
|
3917
|
+
function decodeBase64Url(value) {
|
|
3918
|
+
if (!/^[A-Za-z0-9_-]+$/.test(value) || value.length % 4 === 1)
|
|
3919
|
+
throw new Error("value is not canonical base64url");
|
|
3920
|
+
const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
3921
|
+
const binary = typeof Buffer !== "undefined" ? Buffer.from(normalized, "base64").toString("binary") : atob(normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "="));
|
|
3922
|
+
const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
3923
|
+
const encoded = typeof Buffer !== "undefined" ? Buffer.from(bytes).toString("base64url") : btoa(String.fromCharCode(...bytes)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
3924
|
+
if (encoded !== value) throw new Error("value is not canonical base64url");
|
|
3925
|
+
return bytes;
|
|
3926
|
+
}
|
|
3927
|
+
function encodeBase64Url(value) {
|
|
3928
|
+
return typeof Buffer !== "undefined" ? Buffer.from(value).toString("base64url") : btoa(String.fromCharCode(...value)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
3929
|
+
}
|
|
3930
|
+
function equalBytes(left, right) {
|
|
3931
|
+
return left.length === right.length && left.every((byte, index) => byte === right[index]);
|
|
3932
|
+
}
|
|
3933
|
+
function hex(bytes) {
|
|
3934
|
+
return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
3935
|
+
}
|
|
3936
|
+
function base32Lower(bytes) {
|
|
3937
|
+
const alphabet2 = "abcdefghijklmnopqrstuvwxyz234567";
|
|
3938
|
+
let output = "";
|
|
3939
|
+
let buffer = 0;
|
|
3940
|
+
let bits = 0;
|
|
3941
|
+
for (const byte of bytes) {
|
|
3942
|
+
buffer = buffer << 8 | byte;
|
|
3943
|
+
bits += 8;
|
|
3944
|
+
while (bits >= 5) {
|
|
3945
|
+
output += alphabet2[buffer >>> bits - 5 & 31];
|
|
3946
|
+
bits -= 5;
|
|
3947
|
+
}
|
|
3948
|
+
}
|
|
3949
|
+
if (bits > 0) output += alphabet2[buffer << 5 - bits & 31];
|
|
3950
|
+
return output;
|
|
3951
|
+
}
|
|
3324
3952
|
//# sourceMappingURL=index.cjs.map
|