@tinycloud/sdk-core 2.11.0-beta.8 → 2.11.0
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 +630 -314
- package/dist/delegations/index.cjs.map +1 -1
- package/dist/delegations/index.d.cts +32 -32
- package/dist/delegations/index.d.ts +32 -32
- package/dist/delegations/index.js +632 -231
- package/dist/delegations/index.js.map +1 -1
- package/dist/index.cjs +2923 -1500
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +583 -17
- package/dist/index.d.ts +583 -17
- package/dist/index.js +2892 -1151
- 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 +878 -184
- package/dist/policy/index.js.map +1 -1
- package/dist/{recipient-types.schema-D5pDlIqn.d.cts → recipient-types.schema-CieclU3Z.d.cts} +232 -175
- package/dist/{recipient-types.schema-D5pDlIqn.d.ts → recipient-types.schema-CieclU3Z.d.ts} +232 -175
- package/dist/requester/index.cjs +10 -38
- package/dist/requester/index.cjs.map +1 -1
- package/dist/requester/index.js +11 -9
- package/dist/requester/index.js.map +1 -1
- package/dist/unified-BlXXf3l7.d.cts +429 -0
- package/dist/unified-HWqC-h7O.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
|
@@ -76,11 +76,13 @@ __export(delegations_exports, {
|
|
|
76
76
|
createSharePolicy: () => createSharePolicy,
|
|
77
77
|
createSharingService: () => createSharingService,
|
|
78
78
|
decryptShareBytesAsync: () => decryptShareBytesAsync,
|
|
79
|
+
delegatePortablePolicySession: () => delegatePortablePolicySession,
|
|
79
80
|
encodeInlineShareUrl: () => encodeInlineShareUrl,
|
|
80
81
|
encodeShareArtifact: () => encodeShareArtifact,
|
|
81
82
|
encodeShareUrl: () => encodeShareUrl,
|
|
82
83
|
encryptShareBytes: () => encryptShareBytes,
|
|
83
84
|
encryptShareBytesAsync: () => encryptShareBytesAsync,
|
|
85
|
+
importPortableDelegation: () => importPortableDelegation,
|
|
84
86
|
inspectShare: () => import_share_sdk2.inspectShare,
|
|
85
87
|
intersectShareCapabilities: () => intersectShareCapabilities,
|
|
86
88
|
isLegacyShareLink: () => import_share_sdk.isLegacyShareLink,
|
|
@@ -91,6 +93,7 @@ __export(delegations_exports, {
|
|
|
91
93
|
normalizeShareRecipientTarget: () => normalizeShareRecipientTarget,
|
|
92
94
|
normalizeShareResource: () => normalizeShareResource,
|
|
93
95
|
notifyShare: () => import_share_sdk.notifyShare,
|
|
96
|
+
parsePortableDelegation: () => parsePortableDelegation,
|
|
94
97
|
parseShareArtifact: () => parseShareArtifact,
|
|
95
98
|
parseShareUrl: () => parseShareUrl,
|
|
96
99
|
publishPolicyShare: () => import_share_sdk.publishPolicyShare,
|
|
@@ -100,6 +103,7 @@ __export(delegations_exports, {
|
|
|
100
103
|
restoreDelegatedShareKey: () => restoreDelegatedShareKey,
|
|
101
104
|
resumeShareAuthorization: () => import_share_sdk.resumeShareAuthorization,
|
|
102
105
|
revokeShare: () => import_share_sdk.revokeShare,
|
|
106
|
+
serializePortableDelegation: () => serializePortableDelegation,
|
|
103
107
|
shareCapabilityAllows: () => shareCapabilityAllows,
|
|
104
108
|
shareDeliveryTrustedKid: () => shareDeliveryTrustedKid,
|
|
105
109
|
showShare: () => import_share_sdk.showShare,
|
|
@@ -1382,6 +1386,7 @@ function validateSharingServiceConfig(data) {
|
|
|
1382
1386
|
|
|
1383
1387
|
// src/manifest.ts
|
|
1384
1388
|
var import_ms = __toESM(require("ms"), 1);
|
|
1389
|
+
var import_bootstrap = require("@tinycloud/bootstrap");
|
|
1385
1390
|
var import_sdk_services = require("@tinycloud/sdk-services");
|
|
1386
1391
|
var SERVICE_SHORT_TO_LONG = Object.freeze({
|
|
1387
1392
|
kv: "tinycloud.kv",
|
|
@@ -2264,13 +2269,12 @@ function digest(input, options) {
|
|
|
2264
2269
|
}
|
|
2265
2270
|
var identity2 = { code: code2, name, encode: encode4, digest };
|
|
2266
2271
|
|
|
2267
|
-
// ../../node_modules/multiformats/dist/src/hashes/sha2.js
|
|
2268
|
-
var
|
|
2269
|
-
__export(
|
|
2272
|
+
// ../../node_modules/multiformats/dist/src/hashes/sha2-browser.js
|
|
2273
|
+
var sha2_browser_exports = {};
|
|
2274
|
+
__export(sha2_browser_exports, {
|
|
2270
2275
|
sha256: () => sha256,
|
|
2271
2276
|
sha512: () => sha512
|
|
2272
2277
|
});
|
|
2273
|
-
var import_crypto = __toESM(require("crypto"), 1);
|
|
2274
2278
|
|
|
2275
2279
|
// ../../node_modules/multiformats/dist/src/hashes/hasher.js
|
|
2276
2280
|
var DEFAULT_MIN_DIGEST_LENGTH = 20;
|
|
@@ -2320,16 +2324,19 @@ function createDigest(digest4, code3, truncate) {
|
|
|
2320
2324
|
return create(code3, digest4);
|
|
2321
2325
|
}
|
|
2322
2326
|
|
|
2323
|
-
// ../../node_modules/multiformats/dist/src/hashes/sha2.js
|
|
2327
|
+
// ../../node_modules/multiformats/dist/src/hashes/sha2-browser.js
|
|
2328
|
+
function sha(name2) {
|
|
2329
|
+
return async (data) => new Uint8Array(await crypto.subtle.digest(name2, data));
|
|
2330
|
+
}
|
|
2324
2331
|
var sha256 = from2({
|
|
2325
2332
|
name: "sha2-256",
|
|
2326
2333
|
code: 18,
|
|
2327
|
-
encode: (
|
|
2334
|
+
encode: sha("SHA-256")
|
|
2328
2335
|
});
|
|
2329
2336
|
var sha512 = from2({
|
|
2330
2337
|
name: "sha2-512",
|
|
2331
2338
|
code: 19,
|
|
2332
|
-
encode: (
|
|
2339
|
+
encode: sha("SHA-512")
|
|
2333
2340
|
});
|
|
2334
2341
|
|
|
2335
2342
|
// ../../node_modules/multiformats/dist/src/cid.js
|
|
@@ -2671,15 +2678,15 @@ var cidSymbol = /* @__PURE__ */ Symbol.for("@ipld/js-cid/CID");
|
|
|
2671
2678
|
|
|
2672
2679
|
// ../../node_modules/multiformats/dist/src/basics.js
|
|
2673
2680
|
var bases = { ...identity_exports, ...base2_exports, ...base8_exports, ...base10_exports, ...base16_exports, ...base32_exports, ...base36_exports, ...base58_exports, ...base64_exports, ...base256emoji_exports };
|
|
2674
|
-
var hashes = { ...
|
|
2681
|
+
var hashes = { ...sha2_browser_exports, ...identity_exports2 };
|
|
2675
2682
|
|
|
2676
2683
|
// src/delegations/SharingService.ts
|
|
2677
|
-
var
|
|
2684
|
+
var import_ed255194 = require("@noble/curves/ed25519");
|
|
2678
2685
|
|
|
2679
2686
|
// src/delegations/ShareRecipientClient.ts
|
|
2680
2687
|
var import_sdk_services2 = require("@tinycloud/sdk-services");
|
|
2681
|
-
var
|
|
2682
|
-
var
|
|
2688
|
+
var import_ed255193 = require("@noble/curves/ed25519");
|
|
2689
|
+
var import_sha2564 = require("@noble/hashes/sha256");
|
|
2683
2690
|
|
|
2684
2691
|
// src/delegations/share-envelope.ts
|
|
2685
2692
|
var import_ed25519 = require("@noble/curves/ed25519");
|
|
@@ -3770,6 +3777,506 @@ var ShareNativeResponseSchema = import_zod3.z.discriminatedUnion("action", [
|
|
|
3770
3777
|
}).strict()
|
|
3771
3778
|
]);
|
|
3772
3779
|
|
|
3780
|
+
// src/delegations/portable.ts
|
|
3781
|
+
var import_zod5 = require("zod");
|
|
3782
|
+
|
|
3783
|
+
// src/policy/unified.ts
|
|
3784
|
+
var import_sha2563 = require("@noble/hashes/sha256");
|
|
3785
|
+
var import_blake32 = require("@noble/hashes/blake3");
|
|
3786
|
+
var import_ed255192 = require("@noble/curves/ed25519");
|
|
3787
|
+
var import_zod4 = require("zod");
|
|
3788
|
+
|
|
3789
|
+
// src/policy/errors.ts
|
|
3790
|
+
var SignedObjectProfileError = class extends Error {
|
|
3791
|
+
constructor(code3, message) {
|
|
3792
|
+
super(message);
|
|
3793
|
+
this.name = "SignedObjectProfileError";
|
|
3794
|
+
this.code = code3;
|
|
3795
|
+
}
|
|
3796
|
+
};
|
|
3797
|
+
var SignedObjectCanonicalizationError = class extends SignedObjectProfileError {
|
|
3798
|
+
constructor(message) {
|
|
3799
|
+
super("canonicalization-mismatch", message);
|
|
3800
|
+
this.name = "SignedObjectCanonicalizationError";
|
|
3801
|
+
}
|
|
3802
|
+
};
|
|
3803
|
+
|
|
3804
|
+
// src/policy/jcs.ts
|
|
3805
|
+
var objectHasOwn = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
|
|
3806
|
+
Object.prototype.hasOwnProperty
|
|
3807
|
+
);
|
|
3808
|
+
function jcsCanonicalize(input) {
|
|
3809
|
+
return serialize(normalizeJson(input, "$"));
|
|
3810
|
+
}
|
|
3811
|
+
function normalizeJson(input, path = "$") {
|
|
3812
|
+
if (input === null) {
|
|
3813
|
+
return null;
|
|
3814
|
+
}
|
|
3815
|
+
switch (typeof input) {
|
|
3816
|
+
case "boolean":
|
|
3817
|
+
return input;
|
|
3818
|
+
case "number":
|
|
3819
|
+
if (!Number.isFinite(input)) {
|
|
3820
|
+
throw new SignedObjectCanonicalizationError(
|
|
3821
|
+
`${path} must be a finite JSON number`
|
|
3822
|
+
);
|
|
3823
|
+
}
|
|
3824
|
+
return input;
|
|
3825
|
+
case "string":
|
|
3826
|
+
assertUnicodeScalarString(input, path);
|
|
3827
|
+
return input;
|
|
3828
|
+
case "object":
|
|
3829
|
+
return normalizeJsonObjectOrArray(input, path);
|
|
3830
|
+
case "bigint":
|
|
3831
|
+
case "function":
|
|
3832
|
+
case "symbol":
|
|
3833
|
+
case "undefined":
|
|
3834
|
+
default:
|
|
3835
|
+
throw new SignedObjectCanonicalizationError(
|
|
3836
|
+
`${path} is not a JSON value`
|
|
3837
|
+
);
|
|
3838
|
+
}
|
|
3839
|
+
}
|
|
3840
|
+
function serialize(value) {
|
|
3841
|
+
if (value === null) {
|
|
3842
|
+
return "null";
|
|
3843
|
+
}
|
|
3844
|
+
switch (typeof value) {
|
|
3845
|
+
case "boolean":
|
|
3846
|
+
return value ? "true" : "false";
|
|
3847
|
+
case "number": {
|
|
3848
|
+
const encoded = JSON.stringify(value);
|
|
3849
|
+
if (encoded === void 0) {
|
|
3850
|
+
throw new SignedObjectCanonicalizationError(
|
|
3851
|
+
"number could not be serialized as JSON"
|
|
3852
|
+
);
|
|
3853
|
+
}
|
|
3854
|
+
return encoded;
|
|
3855
|
+
}
|
|
3856
|
+
case "string":
|
|
3857
|
+
return JSON.stringify(value);
|
|
3858
|
+
case "object":
|
|
3859
|
+
if (Array.isArray(value)) {
|
|
3860
|
+
return `[${value.map((item) => serialize(item)).join(",")}]`;
|
|
3861
|
+
}
|
|
3862
|
+
return serializeObject(value);
|
|
3863
|
+
default:
|
|
3864
|
+
throw new SignedObjectCanonicalizationError(
|
|
3865
|
+
`unsupported JSON value type ${typeof value}`
|
|
3866
|
+
);
|
|
3867
|
+
}
|
|
3868
|
+
}
|
|
3869
|
+
function normalizeJsonObjectOrArray(input, path) {
|
|
3870
|
+
assertNoSymbolKeys(input, path);
|
|
3871
|
+
if (Array.isArray(input)) {
|
|
3872
|
+
for (const key of Object.getOwnPropertyNames(input)) {
|
|
3873
|
+
if (key === "length") {
|
|
3874
|
+
continue;
|
|
3875
|
+
}
|
|
3876
|
+
if (!isArrayIndexKey(key, input.length)) {
|
|
3877
|
+
throw new SignedObjectCanonicalizationError(
|
|
3878
|
+
`${path}.${key} is not allowed on a JSON array`
|
|
3879
|
+
);
|
|
3880
|
+
}
|
|
3881
|
+
const descriptor = Object.getOwnPropertyDescriptor(input, key);
|
|
3882
|
+
if (descriptor?.enumerable !== true) {
|
|
3883
|
+
throw new SignedObjectCanonicalizationError(
|
|
3884
|
+
`${path}[${key}] must be an enumerable JSON array item`
|
|
3885
|
+
);
|
|
3886
|
+
}
|
|
3887
|
+
if (!("value" in descriptor)) {
|
|
3888
|
+
throw new SignedObjectCanonicalizationError(
|
|
3889
|
+
`${path}[${key}] must be a JSON data property`
|
|
3890
|
+
);
|
|
3891
|
+
}
|
|
3892
|
+
}
|
|
3893
|
+
const output2 = [];
|
|
3894
|
+
for (let index = 0; index < input.length; index++) {
|
|
3895
|
+
if (!objectHasOwn(input, index)) {
|
|
3896
|
+
throw new SignedObjectCanonicalizationError(
|
|
3897
|
+
`${path}[${index}] must not be a sparse array hole`
|
|
3898
|
+
);
|
|
3899
|
+
}
|
|
3900
|
+
output2.push(normalizeJson(input[index], `${path}[${index}]`));
|
|
3901
|
+
}
|
|
3902
|
+
return output2;
|
|
3903
|
+
}
|
|
3904
|
+
const proto = Object.getPrototypeOf(input);
|
|
3905
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
3906
|
+
throw new SignedObjectCanonicalizationError(
|
|
3907
|
+
`${path} must be a plain JSON object`
|
|
3908
|
+
);
|
|
3909
|
+
}
|
|
3910
|
+
const output = /* @__PURE__ */ Object.create(null);
|
|
3911
|
+
for (const key of Object.getOwnPropertyNames(input)) {
|
|
3912
|
+
assertUnicodeScalarString(key, `${path} key`);
|
|
3913
|
+
if (key === "__proto__" || key === "constructor") {
|
|
3914
|
+
throw new SignedObjectCanonicalizationError(
|
|
3915
|
+
`${path}.${key} is not allowed`
|
|
3916
|
+
);
|
|
3917
|
+
}
|
|
3918
|
+
const descriptor = Object.getOwnPropertyDescriptor(input, key);
|
|
3919
|
+
if (descriptor?.enumerable !== true) {
|
|
3920
|
+
throw new SignedObjectCanonicalizationError(
|
|
3921
|
+
`${path}.${key} must be an enumerable JSON object property`
|
|
3922
|
+
);
|
|
3923
|
+
}
|
|
3924
|
+
if (!("value" in descriptor)) {
|
|
3925
|
+
throw new SignedObjectCanonicalizationError(
|
|
3926
|
+
`${path}.${key} must be a JSON data property`
|
|
3927
|
+
);
|
|
3928
|
+
}
|
|
3929
|
+
const value = descriptor.value;
|
|
3930
|
+
output[key] = normalizeJson(value, `${path}.${key}`);
|
|
3931
|
+
}
|
|
3932
|
+
return output;
|
|
3933
|
+
}
|
|
3934
|
+
function assertNoSymbolKeys(input, path) {
|
|
3935
|
+
if (Object.getOwnPropertySymbols(input).length > 0) {
|
|
3936
|
+
throw new SignedObjectCanonicalizationError(
|
|
3937
|
+
`${path} must not have symbol properties`
|
|
3938
|
+
);
|
|
3939
|
+
}
|
|
3940
|
+
}
|
|
3941
|
+
function isArrayIndexKey(key, length2) {
|
|
3942
|
+
if (!/^(0|[1-9]\d*)$/.test(key)) {
|
|
3943
|
+
return false;
|
|
3944
|
+
}
|
|
3945
|
+
const index = Number(key);
|
|
3946
|
+
return Number.isSafeInteger(index) && index >= 0 && index < length2;
|
|
3947
|
+
}
|
|
3948
|
+
function serializeObject(value) {
|
|
3949
|
+
const keys = Object.keys(value).sort(compareUtf16CodeUnits);
|
|
3950
|
+
const parts = keys.map((key) => `${JSON.stringify(key)}:${serialize(value[key])}`);
|
|
3951
|
+
return `{${parts.join(",")}}`;
|
|
3952
|
+
}
|
|
3953
|
+
function compareUtf16CodeUnits(a, b) {
|
|
3954
|
+
const max = Math.min(a.length, b.length);
|
|
3955
|
+
for (let index = 0; index < max; index++) {
|
|
3956
|
+
const leftCodeUnit = a.charCodeAt(index);
|
|
3957
|
+
const rightCodeUnit = b.charCodeAt(index);
|
|
3958
|
+
if (leftCodeUnit !== rightCodeUnit) {
|
|
3959
|
+
return leftCodeUnit - rightCodeUnit;
|
|
3960
|
+
}
|
|
3961
|
+
}
|
|
3962
|
+
return a.length - b.length;
|
|
3963
|
+
}
|
|
3964
|
+
function assertUnicodeScalarString(value, path) {
|
|
3965
|
+
for (let index = 0; index < value.length; index++) {
|
|
3966
|
+
const code3 = value.charCodeAt(index);
|
|
3967
|
+
if (code3 >= 55296 && code3 <= 56319) {
|
|
3968
|
+
const next = value.charCodeAt(index + 1);
|
|
3969
|
+
if (Number.isNaN(next) || next < 56320 || next > 57343) {
|
|
3970
|
+
throw new SignedObjectCanonicalizationError(
|
|
3971
|
+
`${path} contains a lone high surrogate`
|
|
3972
|
+
);
|
|
3973
|
+
}
|
|
3974
|
+
index++;
|
|
3975
|
+
continue;
|
|
3976
|
+
}
|
|
3977
|
+
if (code3 >= 56320 && code3 <= 57343) {
|
|
3978
|
+
throw new SignedObjectCanonicalizationError(
|
|
3979
|
+
`${path} contains a lone low surrogate`
|
|
3980
|
+
);
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3983
|
+
}
|
|
3984
|
+
|
|
3985
|
+
// src/policy/unified.ts
|
|
3986
|
+
var POLICY_SESSION_UCAN_V1_PROFILE = "policy-session-ucan/v1";
|
|
3987
|
+
var POLICY_SESSION_FACT_KEYS = [
|
|
3988
|
+
"profile",
|
|
3989
|
+
"ownerDid",
|
|
3990
|
+
"policyId",
|
|
3991
|
+
"policyDigestHex",
|
|
3992
|
+
"policyCid",
|
|
3993
|
+
"policyDelegationCid",
|
|
3994
|
+
"enforcementDelegationCid",
|
|
3995
|
+
"contentSourceDigestHex",
|
|
3996
|
+
"capabilityCeilingHashHex",
|
|
3997
|
+
"nativeProjectionHashHex",
|
|
3998
|
+
"enforcerDid",
|
|
3999
|
+
"nodeAudience",
|
|
4000
|
+
"recipientDid",
|
|
4001
|
+
"challengeId",
|
|
4002
|
+
"claimDigestHex",
|
|
4003
|
+
"claimJti",
|
|
4004
|
+
"vpDigestHex",
|
|
4005
|
+
"credentialEvidenceDigestHex",
|
|
4006
|
+
"decisionContextDigestHex",
|
|
4007
|
+
"issuanceAuditDigestHex",
|
|
4008
|
+
"remainingRedelegationDepth"
|
|
4009
|
+
];
|
|
4010
|
+
var CompactHeaderSchema = import_zod4.z.object({
|
|
4011
|
+
alg: import_zod4.z.literal("EdDSA"),
|
|
4012
|
+
jwk: import_zod4.z.object({ alg: import_zod4.z.literal("EdDSA"), crv: import_zod4.z.literal("Ed25519"), kty: import_zod4.z.literal("OKP"), x: import_zod4.z.string().min(1) }).strict(),
|
|
4013
|
+
typ: import_zod4.z.literal("JWT"),
|
|
4014
|
+
ucv: import_zod4.z.literal("0.10.0")
|
|
4015
|
+
}).strict();
|
|
4016
|
+
var CompactPayloadSchema = import_zod4.z.object({
|
|
4017
|
+
att: import_zod4.z.record(import_zod4.z.record(import_zod4.z.array(import_zod4.z.unknown()).min(1))),
|
|
4018
|
+
aud: import_zod4.z.string().min(1),
|
|
4019
|
+
exp: import_zod4.z.number().int(),
|
|
4020
|
+
fct: import_zod4.z.array(import_zod4.z.record(import_zod4.z.unknown())).length(1),
|
|
4021
|
+
iss: import_zod4.z.string().min(1),
|
|
4022
|
+
nbf: import_zod4.z.number().int(),
|
|
4023
|
+
nnc: import_zod4.z.string().min(1),
|
|
4024
|
+
prf: import_zod4.z.array(import_zod4.z.string().min(1))
|
|
4025
|
+
}).strict();
|
|
4026
|
+
function createCompactPolicyInvocation(input) {
|
|
4027
|
+
const session = parsePolicySessionUcan(input.sessionAuthorization);
|
|
4028
|
+
if (session.cid !== input.sessionCid || session.aud !== input.recipientDid)
|
|
4029
|
+
throw new Error("policy session does not bind the recipient signer");
|
|
4030
|
+
const principal = input.recipientDid.split("#", 1)[0];
|
|
4031
|
+
const didMaterial = base58btc.decode(principal.slice("did:key:".length));
|
|
4032
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
|
|
4033
|
+
throw new Error("policy invocation signer must be did:key Ed25519");
|
|
4034
|
+
const publicKey = import_ed255192.ed25519.getPublicKey(input.privateKey);
|
|
4035
|
+
if (!equalBytes2(publicKey, didMaterial.slice(2)))
|
|
4036
|
+
throw new Error("policy invocation private key does not bind recipient DID");
|
|
4037
|
+
const now = input.now ?? Math.floor(Date.now() / 1e3);
|
|
4038
|
+
const exp = Math.min(now + 60, session.exp);
|
|
4039
|
+
if (exp <= now) throw new Error("policy session has expired");
|
|
4040
|
+
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
|
|
4041
|
+
const payload = {
|
|
4042
|
+
att: { [input.resource]: { [input.action]: [input.caveat ?? {}] } },
|
|
4043
|
+
aud: input.audienceDid,
|
|
4044
|
+
exp,
|
|
4045
|
+
fct: [input.facts ?? { type: "tinycloud.policy.invocation/v1", policyCid: session.fact.policyCid, sessionCid: session.cid }],
|
|
4046
|
+
iss: input.recipientDid.includes("#") ? input.recipientDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
4047
|
+
nbf: now,
|
|
4048
|
+
nnc: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
4049
|
+
prf: [session.cid]
|
|
4050
|
+
};
|
|
4051
|
+
const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
4052
|
+
const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
4053
|
+
const signingInput = new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`);
|
|
4054
|
+
const signature = import_ed255192.ed25519.sign(signingInput, input.privateKey);
|
|
4055
|
+
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
4056
|
+
}
|
|
4057
|
+
function createCompactPolicyDescendant(input) {
|
|
4058
|
+
const parent = parseCompactUcanAuthorization(input.parentAuthorization, input.parentCid);
|
|
4059
|
+
if (parent.payload.aud !== input.issuerDid) throw new Error("policy descendant issuer is not the parent audience");
|
|
4060
|
+
const parentFact = parent.payload.fct[0];
|
|
4061
|
+
const depth = parentFact.remainingRedelegationDepth;
|
|
4062
|
+
if (!Number.isInteger(depth) || depth <= 0) throw new Error("policy descendant depth is exhausted");
|
|
4063
|
+
if (!compactAttenuationContains(parent.payload.att, input.attenuation))
|
|
4064
|
+
throw new Error("policy descendant exceeds the parent attenuation");
|
|
4065
|
+
const principal = input.issuerDid.split("#", 1)[0];
|
|
4066
|
+
const didMaterial = base58btc.decode(principal.slice("did:key:".length));
|
|
4067
|
+
const publicKey = import_ed255192.ed25519.getPublicKey(input.privateKey);
|
|
4068
|
+
if (didMaterial.length !== 34 || !equalBytes2(publicKey, didMaterial.slice(2))) throw new Error("policy descendant signer does not bind issuer DID");
|
|
4069
|
+
const now = Math.max(input.now ?? Math.floor(Date.now() / 1e3), parent.payload.nbf + 1);
|
|
4070
|
+
const exp = Math.min(input.expiresAt ?? now + 60, now + 60, parent.payload.exp - 1);
|
|
4071
|
+
if (exp <= now) throw new Error("policy parent has no strictly narrower validity window");
|
|
4072
|
+
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
|
|
4073
|
+
const payload = {
|
|
4074
|
+
att: input.attenuation,
|
|
4075
|
+
aud: input.audienceDid,
|
|
4076
|
+
exp,
|
|
4077
|
+
fct: [{ ...parentFact, remainingRedelegationDepth: depth - 1 }],
|
|
4078
|
+
iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
4079
|
+
nbf: now,
|
|
4080
|
+
nnc: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
4081
|
+
prf: [parent.cid]
|
|
4082
|
+
};
|
|
4083
|
+
const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
4084
|
+
const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
4085
|
+
const signature = import_ed255192.ed25519.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`), input.privateKey);
|
|
4086
|
+
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
4087
|
+
}
|
|
4088
|
+
function compactAttenuationContains(parent, child) {
|
|
4089
|
+
const selector = (value) => {
|
|
4090
|
+
if (value.length !== 1 || !isRecordValue(value[0])) return void 0;
|
|
4091
|
+
const caveat = value[0];
|
|
4092
|
+
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;
|
|
4093
|
+
return { kind: caveat.kind, value: caveat.value };
|
|
4094
|
+
};
|
|
4095
|
+
const equal = (left, right) => jcsCanonicalize(left) === jcsCanonicalize(right);
|
|
4096
|
+
return Object.entries(child).every(
|
|
4097
|
+
([childResource, childActions]) => Object.entries(childActions).every(
|
|
4098
|
+
([action, childCaveats]) => Object.entries(parent).some(([parentResource, parentActions]) => {
|
|
4099
|
+
const parentCaveats = parentActions[action];
|
|
4100
|
+
if (parentCaveats === void 0) return false;
|
|
4101
|
+
if (parentResource === childResource && equal(parentCaveats, childCaveats)) return true;
|
|
4102
|
+
const parentSelector = selector(parentCaveats);
|
|
4103
|
+
const childSelector = selector(childCaveats);
|
|
4104
|
+
return parentSelector?.kind === "prefix" && childSelector !== void 0 && parentSelector.value === parentResource && childSelector.value === childResource && (childResource === parentResource || childResource.startsWith(`${parentResource}/`));
|
|
4105
|
+
})
|
|
4106
|
+
)
|
|
4107
|
+
);
|
|
4108
|
+
}
|
|
4109
|
+
function isRecordValue(value) {
|
|
4110
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4111
|
+
}
|
|
4112
|
+
function parseCompactUcanAuthorization(input, expectedCid) {
|
|
4113
|
+
if (typeof input !== "string" || /\s/.test(input))
|
|
4114
|
+
throw new Error("Authorization must be compact UCAN bytes");
|
|
4115
|
+
const segments = input.split(".");
|
|
4116
|
+
if (segments.length !== 3 || segments.some((segment) => segment.length === 0))
|
|
4117
|
+
throw new Error("Authorization must have three compact segments");
|
|
4118
|
+
const [headerSegment, payloadSegment, signatureSegment] = segments;
|
|
4119
|
+
const headerBytes = decodeBase64Url(headerSegment);
|
|
4120
|
+
const payloadBytes = decodeBase64Url(payloadSegment);
|
|
4121
|
+
const signature = decodeBase64Url(signatureSegment);
|
|
4122
|
+
const headerValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(headerBytes));
|
|
4123
|
+
const payloadValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(payloadBytes));
|
|
4124
|
+
if (jcsCanonicalize(headerValue) !== new TextDecoder().decode(headerBytes) || jcsCanonicalize(payloadValue) !== new TextDecoder().decode(payloadBytes))
|
|
4125
|
+
throw new Error("compact UCAN segments are not canonical JCS");
|
|
4126
|
+
const header = CompactHeaderSchema.parse(headerValue);
|
|
4127
|
+
const payload = CompactPayloadSchema.parse(payloadValue);
|
|
4128
|
+
if (payload.nbf >= payload.exp) throw new Error("compact UCAN validity is empty");
|
|
4129
|
+
const principal = payload.iss.split("#", 1)[0];
|
|
4130
|
+
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
4131
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
|
|
4132
|
+
throw new Error("compact UCAN issuer must be did:key Ed25519");
|
|
4133
|
+
const publicKey = didMaterial.slice(2);
|
|
4134
|
+
if (!equalBytes2(publicKey, decodeBase64Url(header.jwk.x)))
|
|
4135
|
+
throw new Error("compact UCAN JWK does not bind issuer");
|
|
4136
|
+
if (!import_ed255192.ed25519.verify(signature, new TextEncoder().encode(`${headerSegment}.${payloadSegment}`), publicKey))
|
|
4137
|
+
throw new Error("compact UCAN signature is invalid");
|
|
4138
|
+
const cid2 = CID.createV1(85, create(30, (0, import_blake32.blake3)(new TextEncoder().encode(input)))).toString();
|
|
4139
|
+
if (expectedCid !== void 0 && cid2 !== expectedCid)
|
|
4140
|
+
throw new Error("compact UCAN CID does not match exact Authorization bytes");
|
|
4141
|
+
return { authorization: input, cid: cid2, header, payload };
|
|
4142
|
+
}
|
|
4143
|
+
function parsePolicySessionUcan(authorization, expectedProofs) {
|
|
4144
|
+
const parsed = parseCompactUcanAuthorization(authorization);
|
|
4145
|
+
const fact = parsed.payload.fct[0];
|
|
4146
|
+
if (parsed.payload.prf.length !== 2 || parsed.payload.prf[0] === parsed.payload.prf[1])
|
|
4147
|
+
throw new Error("policy session UCAN requires two distinct ordered proofs");
|
|
4148
|
+
if (expectedProofs !== void 0 && (parsed.payload.prf[0] !== expectedProofs[0] || parsed.payload.prf[1] !== expectedProofs[1]))
|
|
4149
|
+
throw new Error("policy session UCAN ordered proofs do not match");
|
|
4150
|
+
const factKeys = Object.keys(fact);
|
|
4151
|
+
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)))
|
|
4152
|
+
throw new Error("policy session UCAN fact is incomplete");
|
|
4153
|
+
if (fact.profile !== POLICY_SESSION_UCAN_V1_PROFILE || typeof fact.remainingRedelegationDepth !== "number" || !Number.isInteger(fact.remainingRedelegationDepth) || fact.remainingRedelegationDepth < 0 || fact.remainingRedelegationDepth > 8 || parsed.payload.exp - parsed.payload.nbf > 60 || parsed.payload.iss.split("#", 1)[0] !== fact.enforcerDid || parsed.payload.aud !== fact.recipientDid)
|
|
4154
|
+
throw new Error("policy session UCAN fact is invalid");
|
|
4155
|
+
return {
|
|
4156
|
+
authorization,
|
|
4157
|
+
cid: parsed.cid,
|
|
4158
|
+
iss: parsed.payload.iss,
|
|
4159
|
+
aud: parsed.payload.aud,
|
|
4160
|
+
prf: parsed.payload.prf,
|
|
4161
|
+
att: parsed.payload.att,
|
|
4162
|
+
nbf: parsed.payload.nbf,
|
|
4163
|
+
exp: parsed.payload.exp,
|
|
4164
|
+
nnc: parsed.payload.nnc,
|
|
4165
|
+
fact
|
|
4166
|
+
};
|
|
4167
|
+
}
|
|
4168
|
+
function decodeBase64Url(value) {
|
|
4169
|
+
if (!/^[A-Za-z0-9_-]+$/.test(value) || value.length % 4 === 1)
|
|
4170
|
+
throw new Error("value is not canonical base64url");
|
|
4171
|
+
const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
4172
|
+
const binary = typeof Buffer !== "undefined" ? Buffer.from(normalized, "base64").toString("binary") : atob(normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "="));
|
|
4173
|
+
const bytes2 = Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
4174
|
+
const encoded = typeof Buffer !== "undefined" ? Buffer.from(bytes2).toString("base64url") : btoa(String.fromCharCode(...bytes2)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
4175
|
+
if (encoded !== value) throw new Error("value is not canonical base64url");
|
|
4176
|
+
return bytes2;
|
|
4177
|
+
}
|
|
4178
|
+
function encodeBase64Url(value) {
|
|
4179
|
+
return typeof Buffer !== "undefined" ? Buffer.from(value).toString("base64url") : btoa(String.fromCharCode(...value)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
4180
|
+
}
|
|
4181
|
+
function equalBytes2(left, right) {
|
|
4182
|
+
return left.length === right.length && left.every((byte, index) => byte === right[index]);
|
|
4183
|
+
}
|
|
4184
|
+
|
|
4185
|
+
// src/delegations/portable.ts
|
|
4186
|
+
var ResourceSchema = import_zod5.z.object({
|
|
4187
|
+
service: import_zod5.z.string().min(1),
|
|
4188
|
+
space: import_zod5.z.string().min(1),
|
|
4189
|
+
path: import_zod5.z.string(),
|
|
4190
|
+
actions: import_zod5.z.array(import_zod5.z.string().min(1)).min(1),
|
|
4191
|
+
caveats: import_zod5.z.array(import_zod5.z.record(import_zod5.z.unknown())).optional()
|
|
4192
|
+
}).strict();
|
|
4193
|
+
var PortableDelegationSchema = import_zod5.z.object({
|
|
4194
|
+
cid: import_zod5.z.string().min(1),
|
|
4195
|
+
delegationHeader: import_zod5.z.object({ Authorization: import_zod5.z.string().min(1) }).strict(),
|
|
4196
|
+
ownerAddress: import_zod5.z.string().min(1),
|
|
4197
|
+
chainId: import_zod5.z.number().int().nonnegative(),
|
|
4198
|
+
host: import_zod5.z.string().url().optional(),
|
|
4199
|
+
spaceId: import_zod5.z.string().min(1),
|
|
4200
|
+
path: import_zod5.z.string(),
|
|
4201
|
+
actions: import_zod5.z.array(import_zod5.z.string().min(1)).min(1),
|
|
4202
|
+
caveats: import_zod5.z.array(import_zod5.z.record(import_zod5.z.unknown())).optional(),
|
|
4203
|
+
expiry: import_zod5.z.coerce.date(),
|
|
4204
|
+
delegateDID: import_zod5.z.string().min(1),
|
|
4205
|
+
delegatorDID: import_zod5.z.string().min(1).optional(),
|
|
4206
|
+
parentCid: import_zod5.z.string().min(1).optional(),
|
|
4207
|
+
disableSubDelegation: import_zod5.z.boolean().optional(),
|
|
4208
|
+
resources: import_zod5.z.array(ResourceSchema).min(1).optional()
|
|
4209
|
+
}).strict();
|
|
4210
|
+
function parsePortableDelegation(input) {
|
|
4211
|
+
const parsed = PortableDelegationSchema.parse(input);
|
|
4212
|
+
if (parsed.resources !== void 0 && parsed.resources.length === 0)
|
|
4213
|
+
throw new Error("portable delegation resources must not be empty");
|
|
4214
|
+
return parsed;
|
|
4215
|
+
}
|
|
4216
|
+
function serializePortableDelegation(delegation) {
|
|
4217
|
+
return JSON.stringify({
|
|
4218
|
+
...delegation,
|
|
4219
|
+
expiry: delegation.expiry.toISOString()
|
|
4220
|
+
});
|
|
4221
|
+
}
|
|
4222
|
+
async function importPortableDelegation(fetchFn, host, delegation) {
|
|
4223
|
+
const parsed = parsePortableDelegation(delegation);
|
|
4224
|
+
const response = await fetchFn(`${host.replace(/\/+$/, "")}/delegate`, {
|
|
4225
|
+
method: "POST",
|
|
4226
|
+
headers: { Authorization: parsed.delegationHeader.Authorization }
|
|
4227
|
+
});
|
|
4228
|
+
if (!response.ok)
|
|
4229
|
+
throw new Error(`node rejected delegation import (${response.status})`);
|
|
4230
|
+
const body = await response.json().catch(() => ({}));
|
|
4231
|
+
if (body === null || typeof body !== "object" || Array.isArray(body))
|
|
4232
|
+
return {};
|
|
4233
|
+
return body;
|
|
4234
|
+
}
|
|
4235
|
+
async function delegatePortablePolicySession(input) {
|
|
4236
|
+
const parent = parsePortableDelegation(input.parent);
|
|
4237
|
+
const descendant = createCompactPolicyDescendant({
|
|
4238
|
+
parentAuthorization: parent.delegationHeader.Authorization.replace(/^Bearer\s+/i, ""),
|
|
4239
|
+
parentCid: parent.cid,
|
|
4240
|
+
issuerDid: parent.delegateDID,
|
|
4241
|
+
audienceDid: input.delegateDID,
|
|
4242
|
+
attenuation: input.attenuation,
|
|
4243
|
+
privateKey: input.issuerPrivateKey,
|
|
4244
|
+
...input.now === void 0 ? {} : { now: input.now },
|
|
4245
|
+
...input.expiresAt === void 0 ? {} : { expiresAt: input.expiresAt },
|
|
4246
|
+
...input.nonce === void 0 ? {} : { nonce: input.nonce }
|
|
4247
|
+
});
|
|
4248
|
+
const resources = Object.entries(descendant.payload.att).map(([resource, abilities]) => {
|
|
4249
|
+
const actions = Object.keys(abilities);
|
|
4250
|
+
if (resource.startsWith("urn:tinycloud:encryption:")) {
|
|
4251
|
+
return { service: "encryption", space: "encryption", path: resource, actions };
|
|
4252
|
+
}
|
|
4253
|
+
const match = /^tinycloud:\/\/([^/]+)\/kv\/(.+)$/.exec(resource);
|
|
4254
|
+
if (match === null) throw new Error("policy descendant resource is invalid");
|
|
4255
|
+
const caveats = Object.values(abilities).flat().filter((value) => value !== null && typeof value === "object" && !Array.isArray(value));
|
|
4256
|
+
return { service: "kv", space: match[1], path: match[2], actions, ...caveats.length === 0 ? {} : { caveats } };
|
|
4257
|
+
});
|
|
4258
|
+
const primary = resources.find((resource) => resource.service === "kv") ?? resources[0];
|
|
4259
|
+
if (primary === void 0) throw new Error("policy descendant attenuation is empty");
|
|
4260
|
+
const portable = {
|
|
4261
|
+
cid: descendant.cid,
|
|
4262
|
+
delegationHeader: { Authorization: descendant.authorization },
|
|
4263
|
+
ownerAddress: parent.ownerAddress,
|
|
4264
|
+
chainId: parent.chainId,
|
|
4265
|
+
host: input.host,
|
|
4266
|
+
spaceId: primary.space,
|
|
4267
|
+
path: primary.path,
|
|
4268
|
+
actions: primary.actions,
|
|
4269
|
+
expiry: new Date(descendant.payload.exp * 1e3),
|
|
4270
|
+
delegateDID: input.delegateDID,
|
|
4271
|
+
delegatorDID: parent.delegateDID,
|
|
4272
|
+
parentCid: parent.cid,
|
|
4273
|
+
disableSubDelegation: descendant.payload.fct[0]?.remainingRedelegationDepth === 0,
|
|
4274
|
+
resources
|
|
4275
|
+
};
|
|
4276
|
+
await importPortableDelegation(input.fetch, input.host, portable);
|
|
4277
|
+
return portable;
|
|
4278
|
+
}
|
|
4279
|
+
|
|
3773
4280
|
// src/delegations/ShareRecipientClient.ts
|
|
3774
4281
|
var DEFAULT_MAX_ARTIFACT_BYTES2 = MAX_SHARE_ARTIFACT_BYTES;
|
|
3775
4282
|
var DEFAULT_MAX_CONTENT_BYTES = MAX_SHARE_CONTENT_BYTES;
|
|
@@ -3845,7 +4352,7 @@ function randomJti() {
|
|
|
3845
4352
|
return bytesToBase64Url2(bytes2);
|
|
3846
4353
|
}
|
|
3847
4354
|
function digestCanonical(value) {
|
|
3848
|
-
return bytesToBase64Url2((0,
|
|
4355
|
+
return bytesToBase64Url2((0, import_sha2564.sha256)(new TextEncoder().encode(canonicalJsonForProof(value))));
|
|
3849
4356
|
}
|
|
3850
4357
|
function actionWire(action) {
|
|
3851
4358
|
return action === "get" ? "tinycloud.kv/get" : action === "metadata" ? "tinycloud.kv/metadata" : action === "list" ? "tinycloud.kv/list" : "tinycloud.kv/put";
|
|
@@ -3957,9 +4464,31 @@ var ShareRecipientClient = class {
|
|
|
3957
4464
|
if (policy && this.options.bearerSession !== void 0) throw new ShareAccessError("SHARE_POLICY_BEARER_MISMATCH");
|
|
3958
4465
|
if (bearer && this.options.presentation !== void 0) throw new ShareAccessError("SHARE_BEARER_PRESENTATION_MISMATCH");
|
|
3959
4466
|
const session = bearer || legacyBearer ? this.options.bearerSession : recipientDidSession ? recipientDidSession : policy && this.options.establishPolicySession !== void 0 ? await this.options.establishPolicySession({ envelope, presentation: this.options.presentation }) : policy ? await this.establishPolicySession(envelope) : void 0;
|
|
3960
|
-
const kv = bearer || legacyBearer ? session === void 0 ? void 0 : this.createKV(envelope.origin, session) : void 0;
|
|
3961
4467
|
const policySession = policy ? session : void 0;
|
|
3962
4468
|
if (policySession !== void 0) this.assertProvidedPolicySession(policySession, envelope);
|
|
4469
|
+
const portableDelegation = policySession === void 0 ? void 0 : this.policySessionDelegation(policySession, envelope.origin);
|
|
4470
|
+
const portableInvoke = portableDelegation === void 0 ? void 0 : this.policyInvocationSigner(portableDelegation);
|
|
4471
|
+
if (portableDelegation !== void 0) {
|
|
4472
|
+
if (this.options.importDelegation === void 0) {
|
|
4473
|
+
await importPortableDelegation(this.fetchFn, envelope.origin, portableDelegation);
|
|
4474
|
+
} else {
|
|
4475
|
+
const imported = await this.options.importDelegation(portableDelegation);
|
|
4476
|
+
if (imported !== void 0) {
|
|
4477
|
+
const normalized = parsePortableDelegation(imported);
|
|
4478
|
+
if (normalized.delegationHeader.Authorization !== portableDelegation.delegationHeader.Authorization) {
|
|
4479
|
+
throw new ShareAccessError("SHARE_SESSION_INVALID", "delegation importer changed authorization bytes");
|
|
4480
|
+
}
|
|
4481
|
+
}
|
|
4482
|
+
}
|
|
4483
|
+
}
|
|
4484
|
+
const ordinarySession = portableDelegation === void 0 ? void 0 : {
|
|
4485
|
+
delegationHeader: portableDelegation.delegationHeader,
|
|
4486
|
+
delegationCid: portableDelegation.cid,
|
|
4487
|
+
spaceId: this.policySessionProjection(portableDelegation).spaceId,
|
|
4488
|
+
verificationMethod: portableDelegation.delegateDID,
|
|
4489
|
+
jwk: this.options.bearerSession?.jwk ?? {}
|
|
4490
|
+
};
|
|
4491
|
+
const kv = bearer || legacyBearer || ordinarySession !== void 0 ? session === void 0 && ordinarySession === void 0 ? void 0 : this.createKV(envelope.origin, ordinarySession ?? session, portableInvoke) : void 0;
|
|
3963
4492
|
const advertisedCapability = { spaceId: envelope.spaceId, resource: envelope.resource, actions: envelope.actions };
|
|
3964
4493
|
const capability = policySession?.capability === void 0 ? advertisedCapability : intersectShareCapabilities(advertisedCapability, policySession.capability);
|
|
3965
4494
|
if (capability === void 0) throw new ShareAccessError("SHARE_CAPABILITY_EMPTY");
|
|
@@ -3984,6 +4513,11 @@ var ShareRecipientClient = class {
|
|
|
3984
4513
|
const scope = normalizePath(input.path ?? envelope.resource.path);
|
|
3985
4514
|
this.assertAllowed(capability, "list", scope);
|
|
3986
4515
|
if (kv === void 0 && policySession === void 0) throw new ShareAccessError("SHARE_SESSION_REQUIRED");
|
|
4516
|
+
if (portableDelegation !== void 0 && kv !== void 0) {
|
|
4517
|
+
const result2 = await kv.list({ path: scope, limit: input.limit, cursor: input.cursor });
|
|
4518
|
+
if (!result2.ok) throw result2.error;
|
|
4519
|
+
return { keys: result2.data.keys, truncated: result2.data.truncated, nextCursor: result2.data.nextCursor };
|
|
4520
|
+
}
|
|
3987
4521
|
if (policySession !== void 0) return this.nativeList(envelope, policySession, scope, input.limit, input.cursor);
|
|
3988
4522
|
const result = await kv.list({ path: scope, limit: input.limit, cursor: input.cursor });
|
|
3989
4523
|
if (!result.ok) throw result.error;
|
|
@@ -3997,6 +4531,14 @@ var ShareRecipientClient = class {
|
|
|
3997
4531
|
const resolvedPath = normalizePath(path);
|
|
3998
4532
|
this.assertAllowed(capability, "save", resolvedPath);
|
|
3999
4533
|
if (kv === void 0 && policySession === void 0) throw new ShareAccessError("SHARE_SESSION_REQUIRED");
|
|
4534
|
+
if (portableDelegation !== void 0 && kv !== void 0) {
|
|
4535
|
+
const result2 = await kv.put(resolvedPath, bytes2, { contentType: input.contentType ?? envelope.content.mimeType, ifMatch: input.etag });
|
|
4536
|
+
if (!result2.ok) {
|
|
4537
|
+
if (result2.error.code === import_sdk_services2.ErrorCodes.KV_PRECONDITION_FAILED || result2.error.code === import_sdk_services2.ErrorCodes.KV_CONFLICT) throw new ShareConflict(resolvedPath, result2.error.meta?.etag);
|
|
4538
|
+
throw result2.error;
|
|
4539
|
+
}
|
|
4540
|
+
return { etag: result2.data.headers.etag };
|
|
4541
|
+
}
|
|
4000
4542
|
if (policySession !== void 0) return this.nativeSave(envelope, policySession, resolvedPath, bytes2, input);
|
|
4001
4543
|
const result = await kv.put(resolvedPath, bytes2, { contentType: input.contentType ?? envelope.content.mimeType, ifMatch: input.etag });
|
|
4002
4544
|
if (!result.ok) {
|
|
@@ -4012,22 +4554,79 @@ var ShareRecipientClient = class {
|
|
|
4012
4554
|
const metadata = async (path = envelope.resource.kind === "exact" ? envelope.resource.path : "") => {
|
|
4013
4555
|
const resolvedPath = normalizePath(path);
|
|
4014
4556
|
this.assertAllowed(capability, "metadata", resolvedPath);
|
|
4557
|
+
if (portableDelegation !== void 0 && kv !== void 0) {
|
|
4558
|
+
const result2 = await kv.head(resolvedPath);
|
|
4559
|
+
if (!result2.ok) throw result2.error;
|
|
4560
|
+
return { metadata: { "content-type": result2.data.headers.contentType ?? "application/octet-stream", "content-length": String(result2.data.headers.contentLength ?? ""), ...result2.data.headers.lastModified === void 0 ? {} : { "last-modified": result2.data.headers.lastModified } }, etag: result2.data.headers.etag, contentType: result2.data.headers.contentType, size: result2.data.headers.contentLength };
|
|
4561
|
+
}
|
|
4015
4562
|
if (policySession !== void 0) return this.nativeMetadata(envelope, policySession, resolvedPath);
|
|
4016
4563
|
if (kv === void 0) throw new ShareAccessError("SHARE_SESSION_REQUIRED");
|
|
4017
4564
|
const result = await kv.head(resolvedPath);
|
|
4018
4565
|
if (!result.ok) throw result.error;
|
|
4019
4566
|
return { metadata: { "content-type": result.data.headers.contentType ?? "application/octet-stream", "content-length": String(result.data.headers.contentLength ?? ""), ...result.data.headers.lastModified === void 0 ? {} : { "last-modified": result.data.headers.lastModified } }, etag: result.data.headers.etag, contentType: result.data.headers.contentType, size: result.data.headers.contentLength };
|
|
4020
4567
|
};
|
|
4021
|
-
return { kind: "share-v2", envelope, location: { ...location, key: void 0 }, resource: envelope.resource, actions: envelope.actions, expiresAt: new Date(envelope.expiresAt), kv, get, listChildren, save, metadata };
|
|
4568
|
+
return { kind: "share-v2", envelope, location: { ...location, key: void 0 }, resource: envelope.resource, actions: envelope.actions, expiresAt: new Date(envelope.expiresAt), kv, portableDelegation, get, listChildren, save, metadata };
|
|
4022
4569
|
} catch (error) {
|
|
4023
4570
|
throw asError(error);
|
|
4024
4571
|
}
|
|
4025
4572
|
}
|
|
4026
|
-
|
|
4573
|
+
policySessionDelegation(session, origin) {
|
|
4574
|
+
if (session.runtimeDelegation === void 0) return void 0;
|
|
4575
|
+
const delegation = parsePortableDelegation(session.runtimeDelegation);
|
|
4576
|
+
if (delegation.host !== void 0 && delegation.host.replace(/\/+$/, "") !== origin.replace(/\/+$/, "")) throw new ShareAccessError("SHARE_ORIGIN_MISMATCH", "delegation host does not match the trusted share origin");
|
|
4577
|
+
return delegation;
|
|
4578
|
+
}
|
|
4579
|
+
policyInvocationSigner(delegation) {
|
|
4580
|
+
const privateKey = this.options.policySessionPrivateKey;
|
|
4581
|
+
if (privateKey === void 0) throw new ShareAccessError("SHARE_SESSION_SIGNER_REQUIRED");
|
|
4582
|
+
const session = parsePolicySessionUcan(delegation.delegationHeader.Authorization);
|
|
4583
|
+
if (session.cid !== delegation.cid || session.aud !== delegation.delegateDID)
|
|
4584
|
+
throw new ShareAccessError("SHARE_SESSION_INVALID");
|
|
4585
|
+
return (_serviceSession, service, path, action, facts) => {
|
|
4586
|
+
const serviceName = service.replace(/^tinycloud\./, "");
|
|
4587
|
+
const cleanPath = path.replace(/^\//, "").replace(/\/$/, "");
|
|
4588
|
+
const authority = Object.entries(session.att).find(([parentResource, abilities]) => {
|
|
4589
|
+
if (!(action in abilities)) return false;
|
|
4590
|
+
if (serviceName === "encryption") return parentResource.startsWith("urn:tinycloud:encryption:") && parentResource === cleanPath;
|
|
4591
|
+
const match = /^tinycloud:\/\/[^/]+\/kv\/(.+)$/.exec(parentResource);
|
|
4592
|
+
if (match === null) return false;
|
|
4593
|
+
const parentPath = match[1];
|
|
4594
|
+
const caveats = abilities[action] ?? [];
|
|
4595
|
+
const prefix = caveats.some((value) => isRecord(value) && value.kind === "prefix");
|
|
4596
|
+
return cleanPath === parentPath || prefix && cleanPath.startsWith(`${parentPath}/`);
|
|
4597
|
+
});
|
|
4598
|
+
if (authority === void 0) throw new ShareAccessError("SHARE_OUT_OF_SCOPE");
|
|
4599
|
+
const resource = serviceName === "encryption" ? authority[0] : `${authority[0].slice(0, authority[0].indexOf("/kv/") + 4)}${cleanPath}`;
|
|
4600
|
+
const caveat = serviceName === "encryption" ? {} : { type: "xyz.tinycloud.resource/selector", kind: "exact", value: resource };
|
|
4601
|
+
const invocation = createCompactPolicyInvocation({
|
|
4602
|
+
sessionAuthorization: delegation.delegationHeader.Authorization,
|
|
4603
|
+
sessionCid: delegation.cid,
|
|
4604
|
+
recipientDid: delegation.delegateDID,
|
|
4605
|
+
audienceDid: String(session.fact.nodeAudience),
|
|
4606
|
+
resource,
|
|
4607
|
+
action,
|
|
4608
|
+
caveat,
|
|
4609
|
+
...facts?.length === 1 ? { facts: facts[0] } : {},
|
|
4610
|
+
privateKey,
|
|
4611
|
+
now: Math.floor(this.now().getTime() / 1e3)
|
|
4612
|
+
});
|
|
4613
|
+
return { Authorization: invocation.authorization };
|
|
4614
|
+
};
|
|
4615
|
+
}
|
|
4616
|
+
policySessionProjection(delegation) {
|
|
4617
|
+
const session = parsePolicySessionUcan(delegation.delegationHeader.Authorization);
|
|
4618
|
+
if (session.cid !== delegation.cid || session.aud !== delegation.delegateDID) throw new ShareAccessError("SHARE_SESSION_INVALID");
|
|
4619
|
+
const kvResource = Object.keys(session.att).find((resource) => /^tinycloud:\/\/[^/]+\/kv\/.+$/.test(resource));
|
|
4620
|
+
const match = kvResource === void 0 ? void 0 : /^tinycloud:\/\/([^/]+)\/kv\/(.+)$/.exec(kvResource);
|
|
4621
|
+
if (match === void 0 || match === null) throw new ShareAccessError("SHARE_SESSION_INVALID");
|
|
4622
|
+
return { spaceId: match[1] };
|
|
4623
|
+
}
|
|
4624
|
+
createKV(origin, session, invokeOverride) {
|
|
4625
|
+
const invoke = invokeOverride ?? this.options.invoke ?? nativeInvoke;
|
|
4027
4626
|
if (this.options.createKVService !== void 0) {
|
|
4028
|
-
return this.options.createKVService({ hosts: [origin], session, invoke
|
|
4627
|
+
return this.options.createKVService({ hosts: [origin], session, invoke, fetch: this.fetchFn });
|
|
4029
4628
|
}
|
|
4030
|
-
const context = new import_sdk_services2.ServiceContext({ hosts: [origin], session, invoke
|
|
4629
|
+
const context = new import_sdk_services2.ServiceContext({ hosts: [origin], session, invoke, fetch: this.fetchFn });
|
|
4031
4630
|
const service = new import_sdk_services2.KVService({ prefix: "" });
|
|
4032
4631
|
context.registerService("kv", service);
|
|
4033
4632
|
service.initialize(context);
|
|
@@ -4070,7 +4669,7 @@ var ShareRecipientClient = class {
|
|
|
4070
4669
|
if (bytes2.byteLength > (this.options.maxContentBytes ?? DEFAULT_MAX_CONTENT_BYTES)) throw new ShareAccessError("SHARE_TOO_LARGE");
|
|
4071
4670
|
const contentType = input.contentType ?? envelope.content.mimeType;
|
|
4072
4671
|
if (contentType !== envelope.content.mimeType && !/^text\/(?:plain|markdown)(?:;|$)/i.test(contentType)) throw new ShareAccessError("SHARE_CONTENT_TYPE_INVALID");
|
|
4073
|
-
const result = await this.invokeNative({ envelope, session, action: "put", resource: path, body: bytes2, bodyDigest: bytesToBase64Url2((0,
|
|
4672
|
+
const result = await this.invokeNative({ envelope, session, action: "put", resource: path, body: bytes2, bodyDigest: bytesToBase64Url2((0, import_sha2564.sha256)(bytes2)), contentType, ifMatch: input.etag, mediaType: "application/vnd.tinycloud.share+json" });
|
|
4074
4673
|
if (result.status === 412 || result.status === 409) throw new ShareConflict(path, result.headers?.etag);
|
|
4075
4674
|
if (result.status === 401 || result.status === 403) throw new ShareAccessError("SHARE_DENIED");
|
|
4076
4675
|
if (result.status < 200 || result.status >= 300) throw new ShareAccessError("SHARE_WRITE_FAILED");
|
|
@@ -4192,7 +4791,7 @@ var ShareRecipientClient = class {
|
|
|
4192
4791
|
};
|
|
4193
4792
|
const signed = this.options.signNativeInvoke === void 0 ? void 0 : await this.options.signNativeInvoke({ envelope: input.envelope, session: input.session, request: body });
|
|
4194
4793
|
const transport = this.options.invoke !== void 0 || session.authorization !== void 0 || session.delegationHeader !== void 0 ? this.defaultNativeHeaders(session, input.action, input.resource, body) : void 0;
|
|
4195
|
-
const response = await this.fetchFn(
|
|
4794
|
+
const response = await this.fetchFn(`${base3}/invoke`, {
|
|
4196
4795
|
method: "POST",
|
|
4197
4796
|
headers: { ...headersRecord(transport), ...headersRecord(signed), "content-type": input.mediaType, accept: input.mediaType },
|
|
4198
4797
|
body: JSON.stringify(body),
|
|
@@ -4316,7 +4915,7 @@ var ShareRecipientClient = class {
|
|
|
4316
4915
|
}]);
|
|
4317
4916
|
}
|
|
4318
4917
|
digestMatches(value, bytes2) {
|
|
4319
|
-
const digest4 = bytesToBase64Url2((0,
|
|
4918
|
+
const digest4 = bytesToBase64Url2((0, import_sha2564.sha256)(bytes2));
|
|
4320
4919
|
return value === digest4 || value === `sha-256=:${digest4}:`;
|
|
4321
4920
|
}
|
|
4322
4921
|
assertNativeRequestBounds(envelope, session, operation, path, limit, cursor) {
|
|
@@ -4534,7 +5133,7 @@ var ShareRecipientClient = class {
|
|
|
4534
5133
|
nodeAudience: binding.nodeAudience,
|
|
4535
5134
|
...isV2 ? {
|
|
4536
5135
|
enforcerDid: challenge.enforcerDid,
|
|
4537
|
-
credentialDigest: typeof presentation.credentialDigest === "string" ? presentation.credentialDigest : bytesToBase64Url2((0,
|
|
5136
|
+
credentialDigest: typeof presentation.credentialDigest === "string" ? presentation.credentialDigest : bytesToBase64Url2((0, import_sha2564.sha256)(new TextEncoder().encode(credential)))
|
|
4538
5137
|
} : {},
|
|
4539
5138
|
action,
|
|
4540
5139
|
...binding.actions === void 0 ? {} : { actions: [...binding.actions] },
|
|
@@ -4600,7 +5199,7 @@ var ShareRecipientClient = class {
|
|
|
4600
5199
|
}
|
|
4601
5200
|
if (isJwsProof && detached.kid !== `${signerDid}#${encoded}` || isEd25519Proof && detached.signerDid !== signerDid || signature.length !== 64) throw new ShareAccessError("SHARE_SESSION_INVALID", "Node proof binding is invalid");
|
|
4602
5201
|
const bytes2 = new TextEncoder().encode(`${domain}${canonicalJsonForProof(message)}`);
|
|
4603
|
-
if (!
|
|
5202
|
+
if (!import_ed255193.ed25519.verify(signature, bytes2, key)) throw new ShareAccessError("SHARE_SESSION_INVALID", "Node proof signature is invalid");
|
|
4604
5203
|
}
|
|
4605
5204
|
assertChallengeRequestBinding(request, challenge) {
|
|
4606
5205
|
const source = isRecord(request.body) ? request.body : request;
|
|
@@ -5804,7 +6403,7 @@ function shareKeyMatchesDid(key, didUrl) {
|
|
|
5804
6403
|
if (!publicKey) return false;
|
|
5805
6404
|
const jwkBytes = decodeBase64UrlBytes(key.x);
|
|
5806
6405
|
const privateKey = decodeBase64UrlBytes(key.d);
|
|
5807
|
-
const derivedPublicKey =
|
|
6406
|
+
const derivedPublicKey = import_ed255194.ed25519.getPublicKey(privateKey);
|
|
5808
6407
|
return privateKey.length === 32 && publicKey.length === jwkBytes.length && publicKey.every((byte, index) => byte === jwkBytes[index]) && derivedPublicKey.length === jwkBytes.length && derivedPublicKey.every((byte, index) => byte === jwkBytes[index]);
|
|
5809
6408
|
} catch {
|
|
5810
6409
|
return false;
|
|
@@ -5854,210 +6453,12 @@ function verifySignedChild(result, expected, computeCid) {
|
|
|
5854
6453
|
}
|
|
5855
6454
|
|
|
5856
6455
|
// src/delegations/owner-policy.ts
|
|
5857
|
-
var
|
|
5858
|
-
var
|
|
6456
|
+
var import_ed255196 = require("@noble/curves/ed25519");
|
|
6457
|
+
var import_sha2565 = require("@noble/hashes/sha256");
|
|
5859
6458
|
|
|
5860
6459
|
// src/policy/signed-object.ts
|
|
5861
|
-
var
|
|
6460
|
+
var import_ed255195 = require("@noble/curves/ed25519");
|
|
5862
6461
|
var import_viem2 = require("viem");
|
|
5863
|
-
|
|
5864
|
-
// src/policy/errors.ts
|
|
5865
|
-
var SignedObjectProfileError = class extends Error {
|
|
5866
|
-
constructor(code3, message) {
|
|
5867
|
-
super(message);
|
|
5868
|
-
this.name = "SignedObjectProfileError";
|
|
5869
|
-
this.code = code3;
|
|
5870
|
-
}
|
|
5871
|
-
};
|
|
5872
|
-
var SignedObjectCanonicalizationError = class extends SignedObjectProfileError {
|
|
5873
|
-
constructor(message) {
|
|
5874
|
-
super("canonicalization-mismatch", message);
|
|
5875
|
-
this.name = "SignedObjectCanonicalizationError";
|
|
5876
|
-
}
|
|
5877
|
-
};
|
|
5878
|
-
|
|
5879
|
-
// src/policy/jcs.ts
|
|
5880
|
-
var objectHasOwn = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
|
|
5881
|
-
Object.prototype.hasOwnProperty
|
|
5882
|
-
);
|
|
5883
|
-
function jcsCanonicalize(input) {
|
|
5884
|
-
return serialize(normalizeJson(input, "$"));
|
|
5885
|
-
}
|
|
5886
|
-
function normalizeJson(input, path = "$") {
|
|
5887
|
-
if (input === null) {
|
|
5888
|
-
return null;
|
|
5889
|
-
}
|
|
5890
|
-
switch (typeof input) {
|
|
5891
|
-
case "boolean":
|
|
5892
|
-
return input;
|
|
5893
|
-
case "number":
|
|
5894
|
-
if (!Number.isFinite(input)) {
|
|
5895
|
-
throw new SignedObjectCanonicalizationError(
|
|
5896
|
-
`${path} must be a finite JSON number`
|
|
5897
|
-
);
|
|
5898
|
-
}
|
|
5899
|
-
return input;
|
|
5900
|
-
case "string":
|
|
5901
|
-
assertUnicodeScalarString(input, path);
|
|
5902
|
-
return input;
|
|
5903
|
-
case "object":
|
|
5904
|
-
return normalizeJsonObjectOrArray(input, path);
|
|
5905
|
-
case "bigint":
|
|
5906
|
-
case "function":
|
|
5907
|
-
case "symbol":
|
|
5908
|
-
case "undefined":
|
|
5909
|
-
default:
|
|
5910
|
-
throw new SignedObjectCanonicalizationError(
|
|
5911
|
-
`${path} is not a JSON value`
|
|
5912
|
-
);
|
|
5913
|
-
}
|
|
5914
|
-
}
|
|
5915
|
-
function serialize(value) {
|
|
5916
|
-
if (value === null) {
|
|
5917
|
-
return "null";
|
|
5918
|
-
}
|
|
5919
|
-
switch (typeof value) {
|
|
5920
|
-
case "boolean":
|
|
5921
|
-
return value ? "true" : "false";
|
|
5922
|
-
case "number": {
|
|
5923
|
-
const encoded = JSON.stringify(value);
|
|
5924
|
-
if (encoded === void 0) {
|
|
5925
|
-
throw new SignedObjectCanonicalizationError(
|
|
5926
|
-
"number could not be serialized as JSON"
|
|
5927
|
-
);
|
|
5928
|
-
}
|
|
5929
|
-
return encoded;
|
|
5930
|
-
}
|
|
5931
|
-
case "string":
|
|
5932
|
-
return JSON.stringify(value);
|
|
5933
|
-
case "object":
|
|
5934
|
-
if (Array.isArray(value)) {
|
|
5935
|
-
return `[${value.map((item) => serialize(item)).join(",")}]`;
|
|
5936
|
-
}
|
|
5937
|
-
return serializeObject(value);
|
|
5938
|
-
default:
|
|
5939
|
-
throw new SignedObjectCanonicalizationError(
|
|
5940
|
-
`unsupported JSON value type ${typeof value}`
|
|
5941
|
-
);
|
|
5942
|
-
}
|
|
5943
|
-
}
|
|
5944
|
-
function normalizeJsonObjectOrArray(input, path) {
|
|
5945
|
-
assertNoSymbolKeys(input, path);
|
|
5946
|
-
if (Array.isArray(input)) {
|
|
5947
|
-
for (const key of Object.getOwnPropertyNames(input)) {
|
|
5948
|
-
if (key === "length") {
|
|
5949
|
-
continue;
|
|
5950
|
-
}
|
|
5951
|
-
if (!isArrayIndexKey(key, input.length)) {
|
|
5952
|
-
throw new SignedObjectCanonicalizationError(
|
|
5953
|
-
`${path}.${key} is not allowed on a JSON array`
|
|
5954
|
-
);
|
|
5955
|
-
}
|
|
5956
|
-
const descriptor = Object.getOwnPropertyDescriptor(input, key);
|
|
5957
|
-
if (descriptor?.enumerable !== true) {
|
|
5958
|
-
throw new SignedObjectCanonicalizationError(
|
|
5959
|
-
`${path}[${key}] must be an enumerable JSON array item`
|
|
5960
|
-
);
|
|
5961
|
-
}
|
|
5962
|
-
if (!("value" in descriptor)) {
|
|
5963
|
-
throw new SignedObjectCanonicalizationError(
|
|
5964
|
-
`${path}[${key}] must be a JSON data property`
|
|
5965
|
-
);
|
|
5966
|
-
}
|
|
5967
|
-
}
|
|
5968
|
-
const output2 = [];
|
|
5969
|
-
for (let index = 0; index < input.length; index++) {
|
|
5970
|
-
if (!objectHasOwn(input, index)) {
|
|
5971
|
-
throw new SignedObjectCanonicalizationError(
|
|
5972
|
-
`${path}[${index}] must not be a sparse array hole`
|
|
5973
|
-
);
|
|
5974
|
-
}
|
|
5975
|
-
output2.push(normalizeJson(input[index], `${path}[${index}]`));
|
|
5976
|
-
}
|
|
5977
|
-
return output2;
|
|
5978
|
-
}
|
|
5979
|
-
const proto = Object.getPrototypeOf(input);
|
|
5980
|
-
if (proto !== Object.prototype && proto !== null) {
|
|
5981
|
-
throw new SignedObjectCanonicalizationError(
|
|
5982
|
-
`${path} must be a plain JSON object`
|
|
5983
|
-
);
|
|
5984
|
-
}
|
|
5985
|
-
const output = /* @__PURE__ */ Object.create(null);
|
|
5986
|
-
for (const key of Object.getOwnPropertyNames(input)) {
|
|
5987
|
-
assertUnicodeScalarString(key, `${path} key`);
|
|
5988
|
-
if (key === "__proto__" || key === "constructor") {
|
|
5989
|
-
throw new SignedObjectCanonicalizationError(
|
|
5990
|
-
`${path}.${key} is not allowed`
|
|
5991
|
-
);
|
|
5992
|
-
}
|
|
5993
|
-
const descriptor = Object.getOwnPropertyDescriptor(input, key);
|
|
5994
|
-
if (descriptor?.enumerable !== true) {
|
|
5995
|
-
throw new SignedObjectCanonicalizationError(
|
|
5996
|
-
`${path}.${key} must be an enumerable JSON object property`
|
|
5997
|
-
);
|
|
5998
|
-
}
|
|
5999
|
-
if (!("value" in descriptor)) {
|
|
6000
|
-
throw new SignedObjectCanonicalizationError(
|
|
6001
|
-
`${path}.${key} must be a JSON data property`
|
|
6002
|
-
);
|
|
6003
|
-
}
|
|
6004
|
-
const value = descriptor.value;
|
|
6005
|
-
output[key] = normalizeJson(value, `${path}.${key}`);
|
|
6006
|
-
}
|
|
6007
|
-
return output;
|
|
6008
|
-
}
|
|
6009
|
-
function assertNoSymbolKeys(input, path) {
|
|
6010
|
-
if (Object.getOwnPropertySymbols(input).length > 0) {
|
|
6011
|
-
throw new SignedObjectCanonicalizationError(
|
|
6012
|
-
`${path} must not have symbol properties`
|
|
6013
|
-
);
|
|
6014
|
-
}
|
|
6015
|
-
}
|
|
6016
|
-
function isArrayIndexKey(key, length2) {
|
|
6017
|
-
if (!/^(0|[1-9]\d*)$/.test(key)) {
|
|
6018
|
-
return false;
|
|
6019
|
-
}
|
|
6020
|
-
const index = Number(key);
|
|
6021
|
-
return Number.isSafeInteger(index) && index >= 0 && index < length2;
|
|
6022
|
-
}
|
|
6023
|
-
function serializeObject(value) {
|
|
6024
|
-
const keys = Object.keys(value).sort(compareUtf16CodeUnits);
|
|
6025
|
-
const parts = keys.map((key) => `${JSON.stringify(key)}:${serialize(value[key])}`);
|
|
6026
|
-
return `{${parts.join(",")}}`;
|
|
6027
|
-
}
|
|
6028
|
-
function compareUtf16CodeUnits(a, b) {
|
|
6029
|
-
const max = Math.min(a.length, b.length);
|
|
6030
|
-
for (let index = 0; index < max; index++) {
|
|
6031
|
-
const leftCodeUnit = a.charCodeAt(index);
|
|
6032
|
-
const rightCodeUnit = b.charCodeAt(index);
|
|
6033
|
-
if (leftCodeUnit !== rightCodeUnit) {
|
|
6034
|
-
return leftCodeUnit - rightCodeUnit;
|
|
6035
|
-
}
|
|
6036
|
-
}
|
|
6037
|
-
return a.length - b.length;
|
|
6038
|
-
}
|
|
6039
|
-
function assertUnicodeScalarString(value, path) {
|
|
6040
|
-
for (let index = 0; index < value.length; index++) {
|
|
6041
|
-
const code3 = value.charCodeAt(index);
|
|
6042
|
-
if (code3 >= 55296 && code3 <= 56319) {
|
|
6043
|
-
const next = value.charCodeAt(index + 1);
|
|
6044
|
-
if (Number.isNaN(next) || next < 56320 || next > 57343) {
|
|
6045
|
-
throw new SignedObjectCanonicalizationError(
|
|
6046
|
-
`${path} contains a lone high surrogate`
|
|
6047
|
-
);
|
|
6048
|
-
}
|
|
6049
|
-
index++;
|
|
6050
|
-
continue;
|
|
6051
|
-
}
|
|
6052
|
-
if (code3 >= 56320 && code3 <= 57343) {
|
|
6053
|
-
throw new SignedObjectCanonicalizationError(
|
|
6054
|
-
`${path} contains a lone low surrogate`
|
|
6055
|
-
);
|
|
6056
|
-
}
|
|
6057
|
-
}
|
|
6058
|
-
}
|
|
6059
|
-
|
|
6060
|
-
// src/policy/signed-object.ts
|
|
6061
6462
|
var textEncoder2 = new TextEncoder();
|
|
6062
6463
|
var objectHasOwn2 = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
|
|
6063
6464
|
Object.prototype.hasOwnProperty
|
|
@@ -6093,10 +6494,10 @@ function fromB64(value) {
|
|
|
6093
6494
|
throw new Error("base64url decoding is unavailable");
|
|
6094
6495
|
}
|
|
6095
6496
|
function cid(bytesValue) {
|
|
6096
|
-
return CID.createV1(code, create(sha256.code, (0,
|
|
6497
|
+
return CID.createV1(code, create(sha256.code, (0, import_sha2565.sha256)(bytesValue))).toString(base32.encoder);
|
|
6097
6498
|
}
|
|
6098
6499
|
function digest3(bytesValue) {
|
|
6099
|
-
return b64((0,
|
|
6500
|
+
return b64((0, import_sha2565.sha256)(bytesValue));
|
|
6100
6501
|
}
|
|
6101
6502
|
function didKeyFromEd25519PublicKey(publicKey) {
|
|
6102
6503
|
if (publicKey.length !== 32) throw new Error("share key public key must be 32 bytes");
|
|
@@ -6281,7 +6682,7 @@ function validateOwnerSharePolicyRegistration(value, expected) {
|
|
|
6281
6682
|
const publicKey = encodedKid.length === 34 ? encodedKid.slice(2) : encodedKid;
|
|
6282
6683
|
const signatureBytes = fromB64(proof.signature);
|
|
6283
6684
|
const signedBytes = new TextEncoder().encode(`${OWNER_SHARE_REGISTRATION_DOMAIN}${canonicalizeSignedObjectUnsigned(registrationCore)}`);
|
|
6284
|
-
if (signatureBytes.length !== 64 || !
|
|
6685
|
+
if (signatureBytes.length !== 64 || !import_ed255196.ed25519.verify(signatureBytes, signedBytes, publicKey)) throw new Error("owner-share registration proof signature is invalid");
|
|
6285
6686
|
return { registration, proof };
|
|
6286
6687
|
}
|
|
6287
6688
|
function validateOwnerSharePolicyRegistrationBytes(bytesValue, expected) {
|
|
@@ -6295,7 +6696,7 @@ function validateOwnerSharePolicyRegistrationBytes(bytesValue, expected) {
|
|
|
6295
6696
|
}
|
|
6296
6697
|
|
|
6297
6698
|
// src/delegations/share-delivery.ts
|
|
6298
|
-
var
|
|
6699
|
+
var import_ed255197 = require("@noble/curves/ed25519");
|
|
6299
6700
|
var SHARE_DELIVERY_AUTHORIZATION_DOMAIN = "xyz.tinycloud.share/delivery-authorization/v2\0";
|
|
6300
6701
|
function isCanonicalHttpsOrigin(value) {
|
|
6301
6702
|
let url;
|
|
@@ -6383,7 +6784,7 @@ function validateShareDeliveryAuthorizationBytes(bytesValue, expected) {
|
|
|
6383
6784
|
if (publicKey.length !== 32) throw new Error("share delivery authorization proof key is invalid");
|
|
6384
6785
|
const signatureBytes = fromB642(proof.signature);
|
|
6385
6786
|
const signedBytes = new TextEncoder().encode(`${SHARE_DELIVERY_AUTHORIZATION_DOMAIN}${canonicalizeSignedObjectUnsigned(authorization)}`);
|
|
6386
|
-
if (signatureBytes.length !== 64 || !
|
|
6787
|
+
if (signatureBytes.length !== 64 || !import_ed255197.ed25519.verify(signatureBytes, signedBytes, publicKey)) throw new Error("share delivery authorization proof signature is invalid");
|
|
6387
6788
|
return { authorization, proof };
|
|
6388
6789
|
}
|
|
6389
6790
|
function shareDeliveryTrustedKid(publicKey) {
|
|
@@ -6506,89 +6907,4 @@ var SenderShareStore = class {
|
|
|
6506
6907
|
// src/delegations/index.ts
|
|
6507
6908
|
var import_share_sdk = require("@tinycloud/share-sdk");
|
|
6508
6909
|
var import_share_sdk2 = require("@tinycloud/share-sdk");
|
|
6509
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
6510
|
-
0 && (module.exports = {
|
|
6511
|
-
DelegationErrorCodes,
|
|
6512
|
-
DelegationManager,
|
|
6513
|
-
EncodedShareDataSchema,
|
|
6514
|
-
EncryptedSenderShareHistory,
|
|
6515
|
-
MAX_CONTENT_BYTES,
|
|
6516
|
-
MAX_SEALED_SHARE_CONTENT_BYTES,
|
|
6517
|
-
MAX_SHARE_ARTIFACT_BYTES,
|
|
6518
|
-
MAX_SHARE_CONTENT_BYTES,
|
|
6519
|
-
MemoryEncryptedShareHistoryStorage,
|
|
6520
|
-
MemorySenderShareKeyStorage,
|
|
6521
|
-
MemorySenderShareRecordStorage,
|
|
6522
|
-
MemoryShareCache,
|
|
6523
|
-
ReceiveOptionsSchema,
|
|
6524
|
-
SHARE_DELIVERY_AUTHORIZATION_DOMAIN,
|
|
6525
|
-
SenderShareStore,
|
|
6526
|
-
ShareAccessError,
|
|
6527
|
-
ShareActionSchema,
|
|
6528
|
-
ShareAddressedDelegationEnvelopeV2Schema,
|
|
6529
|
-
ShareAddressedDelegationRequestV2Schema,
|
|
6530
|
-
ShareAddressedDelegationResponseV2Schema,
|
|
6531
|
-
ShareConflict,
|
|
6532
|
-
ShareEnvelopeError,
|
|
6533
|
-
ShareNativeResponseSchema,
|
|
6534
|
-
ShareReceiveError,
|
|
6535
|
-
ShareRecipientClient,
|
|
6536
|
-
ShareRecipientClientOptionsSchema,
|
|
6537
|
-
ShareRecipientPolicySchema,
|
|
6538
|
-
ShareRecipientTargetSchema,
|
|
6539
|
-
ShareResourceSchema,
|
|
6540
|
-
SharingService,
|
|
6541
|
-
SharingServiceConfigSchema,
|
|
6542
|
-
authorizationMethodForTarget,
|
|
6543
|
-
authorizeShare,
|
|
6544
|
-
canonicalOwnerSharePolicy,
|
|
6545
|
-
claimShare,
|
|
6546
|
-
computeOwnerShareRegistrationCid,
|
|
6547
|
-
computeShareCid,
|
|
6548
|
-
createDelegatedShareKey,
|
|
6549
|
-
createPolicyEnforcementDelegation,
|
|
6550
|
-
createShareArtifact,
|
|
6551
|
-
createShareArtifactAsync,
|
|
6552
|
-
createSharePolicy,
|
|
6553
|
-
createSharingService,
|
|
6554
|
-
decryptShareBytesAsync,
|
|
6555
|
-
encodeInlineShareUrl,
|
|
6556
|
-
encodeShareArtifact,
|
|
6557
|
-
encodeShareUrl,
|
|
6558
|
-
encryptShareBytes,
|
|
6559
|
-
encryptShareBytesAsync,
|
|
6560
|
-
inspectShare,
|
|
6561
|
-
intersectShareCapabilities,
|
|
6562
|
-
isLegacyShareLink,
|
|
6563
|
-
isV2ShareLink,
|
|
6564
|
-
listShares,
|
|
6565
|
-
migrateShare,
|
|
6566
|
-
normalizeShareActions,
|
|
6567
|
-
normalizeShareRecipientTarget,
|
|
6568
|
-
normalizeShareResource,
|
|
6569
|
-
notifyShare,
|
|
6570
|
-
parseShareArtifact,
|
|
6571
|
-
parseShareUrl,
|
|
6572
|
-
publishPolicyShare,
|
|
6573
|
-
publishTargetShare,
|
|
6574
|
-
receiveLegacyShare,
|
|
6575
|
-
receiveShare,
|
|
6576
|
-
restoreDelegatedShareKey,
|
|
6577
|
-
resumeShareAuthorization,
|
|
6578
|
-
revokeShare,
|
|
6579
|
-
shareCapabilityAllows,
|
|
6580
|
-
shareDeliveryTrustedKid,
|
|
6581
|
-
showShare,
|
|
6582
|
-
signShareEnvelope,
|
|
6583
|
-
toShareErrorInfo,
|
|
6584
|
-
validateEncodedShareData,
|
|
6585
|
-
validateOwnerSharePolicyRegistration,
|
|
6586
|
-
validateOwnerSharePolicyRegistrationBytes,
|
|
6587
|
-
validateReceiveOptions,
|
|
6588
|
-
validateShareDeliveryAuthorizationBytes,
|
|
6589
|
-
validateSharingServiceConfig,
|
|
6590
|
-
verifyBearerEnvelope,
|
|
6591
|
-
verifyShareCid,
|
|
6592
|
-
verifyShareEnvelope
|
|
6593
|
-
});
|
|
6594
6910
|
//# sourceMappingURL=index.cjs.map
|