@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
|
@@ -1271,6 +1271,7 @@ function validateSharingServiceConfig(data) {
|
|
|
1271
1271
|
|
|
1272
1272
|
// src/manifest.ts
|
|
1273
1273
|
import ms from "ms";
|
|
1274
|
+
import { ACCOUNT_MANIFEST_PERMISSIONS } from "@tinycloud/bootstrap";
|
|
1274
1275
|
import { resolveSecretPath, SECRET_NAME_RE } from "@tinycloud/sdk-services";
|
|
1275
1276
|
var SERVICE_SHORT_TO_LONG = Object.freeze({
|
|
1276
1277
|
kv: "tinycloud.kv",
|
|
@@ -2153,13 +2154,12 @@ function digest(input, options) {
|
|
|
2153
2154
|
}
|
|
2154
2155
|
var identity2 = { code: code2, name, encode: encode4, digest };
|
|
2155
2156
|
|
|
2156
|
-
// ../../node_modules/multiformats/dist/src/hashes/sha2.js
|
|
2157
|
-
var
|
|
2158
|
-
__export(
|
|
2157
|
+
// ../../node_modules/multiformats/dist/src/hashes/sha2-browser.js
|
|
2158
|
+
var sha2_browser_exports = {};
|
|
2159
|
+
__export(sha2_browser_exports, {
|
|
2159
2160
|
sha256: () => sha256,
|
|
2160
2161
|
sha512: () => sha512
|
|
2161
2162
|
});
|
|
2162
|
-
import crypto2 from "crypto";
|
|
2163
2163
|
|
|
2164
2164
|
// ../../node_modules/multiformats/dist/src/hashes/hasher.js
|
|
2165
2165
|
var DEFAULT_MIN_DIGEST_LENGTH = 20;
|
|
@@ -2209,16 +2209,19 @@ function createDigest(digest4, code3, truncate) {
|
|
|
2209
2209
|
return create(code3, digest4);
|
|
2210
2210
|
}
|
|
2211
2211
|
|
|
2212
|
-
// ../../node_modules/multiformats/dist/src/hashes/sha2.js
|
|
2212
|
+
// ../../node_modules/multiformats/dist/src/hashes/sha2-browser.js
|
|
2213
|
+
function sha(name2) {
|
|
2214
|
+
return async (data) => new Uint8Array(await crypto.subtle.digest(name2, data));
|
|
2215
|
+
}
|
|
2213
2216
|
var sha256 = from2({
|
|
2214
2217
|
name: "sha2-256",
|
|
2215
2218
|
code: 18,
|
|
2216
|
-
encode: (
|
|
2219
|
+
encode: sha("SHA-256")
|
|
2217
2220
|
});
|
|
2218
2221
|
var sha512 = from2({
|
|
2219
2222
|
name: "sha2-512",
|
|
2220
2223
|
code: 19,
|
|
2221
|
-
encode: (
|
|
2224
|
+
encode: sha("SHA-512")
|
|
2222
2225
|
});
|
|
2223
2226
|
|
|
2224
2227
|
// ../../node_modules/multiformats/dist/src/cid.js
|
|
@@ -2560,10 +2563,10 @@ var cidSymbol = /* @__PURE__ */ Symbol.for("@ipld/js-cid/CID");
|
|
|
2560
2563
|
|
|
2561
2564
|
// ../../node_modules/multiformats/dist/src/basics.js
|
|
2562
2565
|
var bases = { ...identity_exports, ...base2_exports, ...base8_exports, ...base10_exports, ...base16_exports, ...base32_exports, ...base36_exports, ...base58_exports, ...base64_exports, ...base256emoji_exports };
|
|
2563
|
-
var hashes = { ...
|
|
2566
|
+
var hashes = { ...sha2_browser_exports, ...identity_exports2 };
|
|
2564
2567
|
|
|
2565
2568
|
// src/delegations/SharingService.ts
|
|
2566
|
-
import { ed25519 as
|
|
2569
|
+
import { ed25519 as ed255194 } from "@noble/curves/ed25519";
|
|
2567
2570
|
|
|
2568
2571
|
// src/delegations/ShareRecipientClient.ts
|
|
2569
2572
|
import {
|
|
@@ -2571,8 +2574,8 @@ import {
|
|
|
2571
2574
|
KVService,
|
|
2572
2575
|
ServiceContext
|
|
2573
2576
|
} from "@tinycloud/sdk-services";
|
|
2574
|
-
import { ed25519 as
|
|
2575
|
-
import { sha256 as
|
|
2577
|
+
import { ed25519 as ed255193 } from "@noble/curves/ed25519";
|
|
2578
|
+
import { sha256 as sha2565 } from "@noble/hashes/sha256";
|
|
2576
2579
|
|
|
2577
2580
|
// src/delegations/share-envelope.ts
|
|
2578
2581
|
import { ed25519 } from "@noble/curves/ed25519";
|
|
@@ -2733,6 +2736,10 @@ function normalizeRecipient(recipient) {
|
|
|
2733
2736
|
}
|
|
2734
2737
|
return { kind: recipient.kind, value: domain };
|
|
2735
2738
|
}
|
|
2739
|
+
if (recipient.kind === "recipientDid") {
|
|
2740
|
+
if (!isCanonicalRecipientDid(recipient.value)) throw new ShareEnvelopeError("invalid-envelope", "recipient DID is invalid");
|
|
2741
|
+
return { kind: recipient.kind, value: recipient.value };
|
|
2742
|
+
}
|
|
2736
2743
|
const exact = recipient.value.trim();
|
|
2737
2744
|
const at = exact.lastIndexOf("@");
|
|
2738
2745
|
const normalizedExact = at > 0 ? `${exact.slice(0, at)}@${exact.slice(at + 1).toLowerCase()}` : exact;
|
|
@@ -2741,6 +2748,28 @@ function normalizeRecipient(recipient) {
|
|
|
2741
2748
|
}
|
|
2742
2749
|
return { kind: recipient.kind, value: normalizedExact };
|
|
2743
2750
|
}
|
|
2751
|
+
function isCanonicalRecipientDid(value) {
|
|
2752
|
+
if (value.length === 0 || value.length > 2048 || /[\u0000-\u0020\u007f]/.test(value)) return false;
|
|
2753
|
+
const parts = value.split(":");
|
|
2754
|
+
if (parts.length < 3 || parts[0] !== "did" || !/^[a-z0-9]+$/.test(parts[1] ?? "")) return false;
|
|
2755
|
+
const identifier = parts.slice(2);
|
|
2756
|
+
if (identifier.some((part) => part.length === 0)) return false;
|
|
2757
|
+
if (parts[1] === "web") {
|
|
2758
|
+
const host = identifier[0] ?? "";
|
|
2759
|
+
if (host.length > 253 || host.split(".").some((label) => !label || label.length > 63 || !/^[A-Za-z0-9-]+$/.test(label) || label.startsWith("-") || label.endsWith("-"))) return false;
|
|
2760
|
+
return identifier.slice(1).every((part) => /^[A-Za-z0-9._%-]+$/.test(part));
|
|
2761
|
+
}
|
|
2762
|
+
if (parts[1] === "pkh") return identifier.length >= 3 && identifier.every((part) => /^[A-Za-z0-9._%-]+$/.test(part));
|
|
2763
|
+
if (parts[1] === "key") {
|
|
2764
|
+
try {
|
|
2765
|
+
const bytes2 = base58btc.decode(identifier.join(":"));
|
|
2766
|
+
return bytes2.length === 34 && bytes2[0] === 237 && bytes2[1] === 1;
|
|
2767
|
+
} catch {
|
|
2768
|
+
return false;
|
|
2769
|
+
}
|
|
2770
|
+
}
|
|
2771
|
+
return false;
|
|
2772
|
+
}
|
|
2744
2773
|
function normalizeShareRecipientTarget(recipient) {
|
|
2745
2774
|
const normalized = normalizeRecipient(recipient);
|
|
2746
2775
|
if (normalized === void 0) throw new ShareEnvelopeError("invalid-envelope", "recipient matcher is required");
|
|
@@ -2827,9 +2856,9 @@ function verifyShareEnvelope(envelope, options = {}) {
|
|
|
2827
2856
|
const recipient = normalizeRecipient(envelope.recipient);
|
|
2828
2857
|
if (recipient !== void 0 && JSON.stringify(recipient) !== JSON.stringify(envelope.recipient)) throw new ShareEnvelopeError("invalid-envelope", "recipient is not canonical");
|
|
2829
2858
|
if (recipient?.kind === "exactEmail" || recipient?.kind === "emailDomain") throw new ShareEnvelopeError("unsafe-plaintext", "recipient matchers are not public envelope fields");
|
|
2830
|
-
if (envelope.recipientKind !== void 0 && !["exactEmail", "emailDomain", "bearer"].includes(envelope.recipientKind)) throw new ShareEnvelopeError("invalid-envelope", "recipient mode is invalid");
|
|
2859
|
+
if (envelope.recipientKind !== void 0 && !["exactEmail", "emailDomain", "recipientDid", "bearer"].includes(envelope.recipientKind)) throw new ShareEnvelopeError("invalid-envelope", "recipient mode is invalid");
|
|
2831
2860
|
if (envelope.recipientKind === "bearer" && recipient?.kind !== void 0 && recipient.kind !== "bearer") throw new ShareEnvelopeError("invalid-envelope", "recipient mode does not match recipient");
|
|
2832
|
-
if ((envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain") && !envelope.encrypted) throw new ShareEnvelopeError("unsafe-plaintext", "
|
|
2861
|
+
if ((envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain" || envelope.recipientKind === "recipientDid") && !envelope.encrypted) throw new ShareEnvelopeError("unsafe-plaintext", "addressed shares require encryption");
|
|
2833
2862
|
if (typeof envelope.spaceId !== "string" || envelope.spaceId.length === 0 || typeof envelope.content.mimeType !== "string" || envelope.content.mimeType.length === 0 || typeof envelope.content.digest !== "string" || !/^[A-Za-z0-9_-]+$/.test(envelope.content.digest)) throw new ShareEnvelopeError("invalid-envelope", "content metadata is invalid");
|
|
2834
2863
|
const maxContentBytes = envelope.encrypted ? options.maxSealedContentBytes ?? MAX_SEALED_SHARE_CONTENT_BYTES : options.maxContentBytes ?? MAX_SHARE_CONTENT_BYTES;
|
|
2835
2864
|
if (!Number.isInteger(envelope.content.size) || envelope.content.size < 0 || envelope.content.size > maxContentBytes) throw new ShareEnvelopeError("content-too-large", "share content exceeds the configured limit");
|
|
@@ -2968,7 +2997,7 @@ function parsePolicyMetadata(policyBytes, target, expectedExpiry) {
|
|
|
2968
2997
|
assertKeys(policy, ["type", "version", "issuerDid", "recipientMatcher", "target", "delegation", "authority", "actions", "resource", "content-source", "expiresAt"], "published canonical policy material");
|
|
2969
2998
|
if (typeof policy.issuerDid !== "string" || typeof policy.expiresAt !== "string" || policy.expiresAt !== expectedExpiry) throw new ShareEnvelopeError("invalid-envelope", "policy expiry is not bound to the envelope");
|
|
2970
2999
|
const matcherValue = policy.recipientMatcher;
|
|
2971
|
-
if (!isPlainObject(matcherValue) || matcherValue.kind !== "exactEmail" && matcherValue.kind !== "emailDomain" || typeof matcherValue.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "policy matcher is invalid");
|
|
3000
|
+
if (!isPlainObject(matcherValue) || matcherValue.kind !== "exactEmail" && matcherValue.kind !== "emailDomain" && matcherValue.kind !== "recipientDid" || typeof matcherValue.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "policy matcher is invalid");
|
|
2972
3001
|
const matcher2 = normalizeRecipient(matcherValue);
|
|
2973
3002
|
if (matcher2 === void 0 || matcher2.kind === "bearer") throw new ShareEnvelopeError("invalid-envelope", "policy matcher is invalid");
|
|
2974
3003
|
if (!isPlainObject(policy.target)) throw new ShareEnvelopeError("invalid-envelope", "policy target is invalid");
|
|
@@ -3055,7 +3084,7 @@ function parseCanonicalPublishedV2(value, options) {
|
|
|
3055
3084
|
if (!Number.isFinite(expiry) || expiry <= (options.now ?? /* @__PURE__ */ new Date()).getTime() || new Date(expiry).toISOString() !== value.expiry) throw new ShareEnvelopeError("expired", "published share envelope has expired");
|
|
3056
3085
|
if (typeof delegation.cid !== "string" || typeof delegation.issuerDid !== "string" || typeof delegation.audience !== "string" || typeof delegation.expiresAt !== "string" || Date.parse(delegation.expiresAt) > expiry) throw new ShareEnvelopeError("invalid-envelope", "published v2 delegation is invalid");
|
|
3057
3086
|
const matcher = value.recipientMatcher;
|
|
3058
|
-
if (!isPlainObject(matcher) || matcher.kind !== "exactEmail" && matcher.kind !== "emailDomain" || typeof matcher.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "published v2 recipient matcher is invalid");
|
|
3087
|
+
if (!isPlainObject(matcher) || matcher.kind !== "exactEmail" && matcher.kind !== "emailDomain" && matcher.kind !== "recipientDid" || typeof matcher.value !== "string") throw new ShareEnvelopeError("invalid-envelope", "published v2 recipient matcher is invalid");
|
|
3059
3088
|
const normalizedMatcher = normalizeRecipient(matcher);
|
|
3060
3089
|
if (normalizedMatcher === void 0 || normalizedMatcher.kind === "bearer") throw new ShareEnvelopeError("invalid-envelope", "published v2 recipient matcher is invalid");
|
|
3061
3090
|
if (!Array.isArray(value.actions)) throw new ShareEnvelopeError("invalid-envelope", "published v2 actions are invalid");
|
|
@@ -3496,10 +3525,11 @@ var ShareConflict = class extends Error {
|
|
|
3496
3525
|
}
|
|
3497
3526
|
};
|
|
3498
3527
|
var ShareAccessError = class extends Error {
|
|
3499
|
-
constructor(code3, message) {
|
|
3528
|
+
constructor(code3, message, details) {
|
|
3500
3529
|
super(message ?? "shared access could not be completed");
|
|
3501
3530
|
this.name = "ShareAccessError";
|
|
3502
3531
|
this.code = code3;
|
|
3532
|
+
this.details = details;
|
|
3503
3533
|
}
|
|
3504
3534
|
};
|
|
3505
3535
|
|
|
@@ -3508,6 +3538,7 @@ import { z as z3 } from "zod";
|
|
|
3508
3538
|
var ShareRecipientTargetSchema = z3.discriminatedUnion("kind", [
|
|
3509
3539
|
z3.object({ kind: z3.literal("exactEmail"), value: z3.string().min(1) }).strict(),
|
|
3510
3540
|
z3.object({ kind: z3.literal("emailDomain"), value: z3.string().min(1) }).strict(),
|
|
3541
|
+
z3.object({ kind: z3.literal("recipientDid"), value: z3.string().regex(/^did:[a-z0-9]+:.+$/) }).strict(),
|
|
3511
3542
|
z3.object({ kind: z3.literal("bearer") }).strict()
|
|
3512
3543
|
]);
|
|
3513
3544
|
var ShareResourceSchema = z3.discriminatedUnion("kind", [
|
|
@@ -3551,7 +3582,8 @@ var ShareContentSourceSchema = z3.discriminatedUnion("kind", [
|
|
|
3551
3582
|
]);
|
|
3552
3583
|
var ShareAddressedRecipientSchema = z3.discriminatedUnion("kind", [
|
|
3553
3584
|
z3.object({ kind: z3.literal("exactEmail"), value: z3.string().min(1) }).strict(),
|
|
3554
|
-
z3.object({ kind: z3.literal("emailDomain"), value: z3.string().min(1) }).strict()
|
|
3585
|
+
z3.object({ kind: z3.literal("emailDomain"), value: z3.string().min(1) }).strict(),
|
|
3586
|
+
z3.object({ kind: z3.literal("recipientDid"), value: z3.string().regex(/^did:[a-z0-9]+:.+$/) }).strict()
|
|
3555
3587
|
]);
|
|
3556
3588
|
var ShareAddressedDelegationRequestV2Schema = z3.object({
|
|
3557
3589
|
version: z3.literal(2),
|
|
@@ -3634,6 +3666,506 @@ var ShareNativeResponseSchema = z3.discriminatedUnion("action", [
|
|
|
3634
3666
|
}).strict()
|
|
3635
3667
|
]);
|
|
3636
3668
|
|
|
3669
|
+
// src/delegations/portable.ts
|
|
3670
|
+
import { z as z5 } from "zod";
|
|
3671
|
+
|
|
3672
|
+
// src/policy/unified.ts
|
|
3673
|
+
import { sha256 as sha2564 } from "@noble/hashes/sha256";
|
|
3674
|
+
import { blake3 as blake32 } from "@noble/hashes/blake3";
|
|
3675
|
+
import { ed25519 as ed255192 } from "@noble/curves/ed25519";
|
|
3676
|
+
import { z as z4 } from "zod";
|
|
3677
|
+
|
|
3678
|
+
// src/policy/errors.ts
|
|
3679
|
+
var SignedObjectProfileError = class extends Error {
|
|
3680
|
+
constructor(code3, message) {
|
|
3681
|
+
super(message);
|
|
3682
|
+
this.name = "SignedObjectProfileError";
|
|
3683
|
+
this.code = code3;
|
|
3684
|
+
}
|
|
3685
|
+
};
|
|
3686
|
+
var SignedObjectCanonicalizationError = class extends SignedObjectProfileError {
|
|
3687
|
+
constructor(message) {
|
|
3688
|
+
super("canonicalization-mismatch", message);
|
|
3689
|
+
this.name = "SignedObjectCanonicalizationError";
|
|
3690
|
+
}
|
|
3691
|
+
};
|
|
3692
|
+
|
|
3693
|
+
// src/policy/jcs.ts
|
|
3694
|
+
var objectHasOwn = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
|
|
3695
|
+
Object.prototype.hasOwnProperty
|
|
3696
|
+
);
|
|
3697
|
+
function jcsCanonicalize(input) {
|
|
3698
|
+
return serialize(normalizeJson(input, "$"));
|
|
3699
|
+
}
|
|
3700
|
+
function normalizeJson(input, path = "$") {
|
|
3701
|
+
if (input === null) {
|
|
3702
|
+
return null;
|
|
3703
|
+
}
|
|
3704
|
+
switch (typeof input) {
|
|
3705
|
+
case "boolean":
|
|
3706
|
+
return input;
|
|
3707
|
+
case "number":
|
|
3708
|
+
if (!Number.isFinite(input)) {
|
|
3709
|
+
throw new SignedObjectCanonicalizationError(
|
|
3710
|
+
`${path} must be a finite JSON number`
|
|
3711
|
+
);
|
|
3712
|
+
}
|
|
3713
|
+
return input;
|
|
3714
|
+
case "string":
|
|
3715
|
+
assertUnicodeScalarString(input, path);
|
|
3716
|
+
return input;
|
|
3717
|
+
case "object":
|
|
3718
|
+
return normalizeJsonObjectOrArray(input, path);
|
|
3719
|
+
case "bigint":
|
|
3720
|
+
case "function":
|
|
3721
|
+
case "symbol":
|
|
3722
|
+
case "undefined":
|
|
3723
|
+
default:
|
|
3724
|
+
throw new SignedObjectCanonicalizationError(
|
|
3725
|
+
`${path} is not a JSON value`
|
|
3726
|
+
);
|
|
3727
|
+
}
|
|
3728
|
+
}
|
|
3729
|
+
function serialize(value) {
|
|
3730
|
+
if (value === null) {
|
|
3731
|
+
return "null";
|
|
3732
|
+
}
|
|
3733
|
+
switch (typeof value) {
|
|
3734
|
+
case "boolean":
|
|
3735
|
+
return value ? "true" : "false";
|
|
3736
|
+
case "number": {
|
|
3737
|
+
const encoded = JSON.stringify(value);
|
|
3738
|
+
if (encoded === void 0) {
|
|
3739
|
+
throw new SignedObjectCanonicalizationError(
|
|
3740
|
+
"number could not be serialized as JSON"
|
|
3741
|
+
);
|
|
3742
|
+
}
|
|
3743
|
+
return encoded;
|
|
3744
|
+
}
|
|
3745
|
+
case "string":
|
|
3746
|
+
return JSON.stringify(value);
|
|
3747
|
+
case "object":
|
|
3748
|
+
if (Array.isArray(value)) {
|
|
3749
|
+
return `[${value.map((item) => serialize(item)).join(",")}]`;
|
|
3750
|
+
}
|
|
3751
|
+
return serializeObject(value);
|
|
3752
|
+
default:
|
|
3753
|
+
throw new SignedObjectCanonicalizationError(
|
|
3754
|
+
`unsupported JSON value type ${typeof value}`
|
|
3755
|
+
);
|
|
3756
|
+
}
|
|
3757
|
+
}
|
|
3758
|
+
function normalizeJsonObjectOrArray(input, path) {
|
|
3759
|
+
assertNoSymbolKeys(input, path);
|
|
3760
|
+
if (Array.isArray(input)) {
|
|
3761
|
+
for (const key of Object.getOwnPropertyNames(input)) {
|
|
3762
|
+
if (key === "length") {
|
|
3763
|
+
continue;
|
|
3764
|
+
}
|
|
3765
|
+
if (!isArrayIndexKey(key, input.length)) {
|
|
3766
|
+
throw new SignedObjectCanonicalizationError(
|
|
3767
|
+
`${path}.${key} is not allowed on a JSON array`
|
|
3768
|
+
);
|
|
3769
|
+
}
|
|
3770
|
+
const descriptor = Object.getOwnPropertyDescriptor(input, key);
|
|
3771
|
+
if (descriptor?.enumerable !== true) {
|
|
3772
|
+
throw new SignedObjectCanonicalizationError(
|
|
3773
|
+
`${path}[${key}] must be an enumerable JSON array item`
|
|
3774
|
+
);
|
|
3775
|
+
}
|
|
3776
|
+
if (!("value" in descriptor)) {
|
|
3777
|
+
throw new SignedObjectCanonicalizationError(
|
|
3778
|
+
`${path}[${key}] must be a JSON data property`
|
|
3779
|
+
);
|
|
3780
|
+
}
|
|
3781
|
+
}
|
|
3782
|
+
const output2 = [];
|
|
3783
|
+
for (let index = 0; index < input.length; index++) {
|
|
3784
|
+
if (!objectHasOwn(input, index)) {
|
|
3785
|
+
throw new SignedObjectCanonicalizationError(
|
|
3786
|
+
`${path}[${index}] must not be a sparse array hole`
|
|
3787
|
+
);
|
|
3788
|
+
}
|
|
3789
|
+
output2.push(normalizeJson(input[index], `${path}[${index}]`));
|
|
3790
|
+
}
|
|
3791
|
+
return output2;
|
|
3792
|
+
}
|
|
3793
|
+
const proto = Object.getPrototypeOf(input);
|
|
3794
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
3795
|
+
throw new SignedObjectCanonicalizationError(
|
|
3796
|
+
`${path} must be a plain JSON object`
|
|
3797
|
+
);
|
|
3798
|
+
}
|
|
3799
|
+
const output = /* @__PURE__ */ Object.create(null);
|
|
3800
|
+
for (const key of Object.getOwnPropertyNames(input)) {
|
|
3801
|
+
assertUnicodeScalarString(key, `${path} key`);
|
|
3802
|
+
if (key === "__proto__" || key === "constructor") {
|
|
3803
|
+
throw new SignedObjectCanonicalizationError(
|
|
3804
|
+
`${path}.${key} is not allowed`
|
|
3805
|
+
);
|
|
3806
|
+
}
|
|
3807
|
+
const descriptor = Object.getOwnPropertyDescriptor(input, key);
|
|
3808
|
+
if (descriptor?.enumerable !== true) {
|
|
3809
|
+
throw new SignedObjectCanonicalizationError(
|
|
3810
|
+
`${path}.${key} must be an enumerable JSON object property`
|
|
3811
|
+
);
|
|
3812
|
+
}
|
|
3813
|
+
if (!("value" in descriptor)) {
|
|
3814
|
+
throw new SignedObjectCanonicalizationError(
|
|
3815
|
+
`${path}.${key} must be a JSON data property`
|
|
3816
|
+
);
|
|
3817
|
+
}
|
|
3818
|
+
const value = descriptor.value;
|
|
3819
|
+
output[key] = normalizeJson(value, `${path}.${key}`);
|
|
3820
|
+
}
|
|
3821
|
+
return output;
|
|
3822
|
+
}
|
|
3823
|
+
function assertNoSymbolKeys(input, path) {
|
|
3824
|
+
if (Object.getOwnPropertySymbols(input).length > 0) {
|
|
3825
|
+
throw new SignedObjectCanonicalizationError(
|
|
3826
|
+
`${path} must not have symbol properties`
|
|
3827
|
+
);
|
|
3828
|
+
}
|
|
3829
|
+
}
|
|
3830
|
+
function isArrayIndexKey(key, length2) {
|
|
3831
|
+
if (!/^(0|[1-9]\d*)$/.test(key)) {
|
|
3832
|
+
return false;
|
|
3833
|
+
}
|
|
3834
|
+
const index = Number(key);
|
|
3835
|
+
return Number.isSafeInteger(index) && index >= 0 && index < length2;
|
|
3836
|
+
}
|
|
3837
|
+
function serializeObject(value) {
|
|
3838
|
+
const keys = Object.keys(value).sort(compareUtf16CodeUnits);
|
|
3839
|
+
const parts = keys.map((key) => `${JSON.stringify(key)}:${serialize(value[key])}`);
|
|
3840
|
+
return `{${parts.join(",")}}`;
|
|
3841
|
+
}
|
|
3842
|
+
function compareUtf16CodeUnits(a, b) {
|
|
3843
|
+
const max = Math.min(a.length, b.length);
|
|
3844
|
+
for (let index = 0; index < max; index++) {
|
|
3845
|
+
const leftCodeUnit = a.charCodeAt(index);
|
|
3846
|
+
const rightCodeUnit = b.charCodeAt(index);
|
|
3847
|
+
if (leftCodeUnit !== rightCodeUnit) {
|
|
3848
|
+
return leftCodeUnit - rightCodeUnit;
|
|
3849
|
+
}
|
|
3850
|
+
}
|
|
3851
|
+
return a.length - b.length;
|
|
3852
|
+
}
|
|
3853
|
+
function assertUnicodeScalarString(value, path) {
|
|
3854
|
+
for (let index = 0; index < value.length; index++) {
|
|
3855
|
+
const code3 = value.charCodeAt(index);
|
|
3856
|
+
if (code3 >= 55296 && code3 <= 56319) {
|
|
3857
|
+
const next = value.charCodeAt(index + 1);
|
|
3858
|
+
if (Number.isNaN(next) || next < 56320 || next > 57343) {
|
|
3859
|
+
throw new SignedObjectCanonicalizationError(
|
|
3860
|
+
`${path} contains a lone high surrogate`
|
|
3861
|
+
);
|
|
3862
|
+
}
|
|
3863
|
+
index++;
|
|
3864
|
+
continue;
|
|
3865
|
+
}
|
|
3866
|
+
if (code3 >= 56320 && code3 <= 57343) {
|
|
3867
|
+
throw new SignedObjectCanonicalizationError(
|
|
3868
|
+
`${path} contains a lone low surrogate`
|
|
3869
|
+
);
|
|
3870
|
+
}
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3873
|
+
|
|
3874
|
+
// src/policy/unified.ts
|
|
3875
|
+
var POLICY_SESSION_UCAN_V1_PROFILE = "policy-session-ucan/v1";
|
|
3876
|
+
var POLICY_SESSION_FACT_KEYS = [
|
|
3877
|
+
"profile",
|
|
3878
|
+
"ownerDid",
|
|
3879
|
+
"policyId",
|
|
3880
|
+
"policyDigestHex",
|
|
3881
|
+
"policyCid",
|
|
3882
|
+
"policyDelegationCid",
|
|
3883
|
+
"enforcementDelegationCid",
|
|
3884
|
+
"contentSourceDigestHex",
|
|
3885
|
+
"capabilityCeilingHashHex",
|
|
3886
|
+
"nativeProjectionHashHex",
|
|
3887
|
+
"enforcerDid",
|
|
3888
|
+
"nodeAudience",
|
|
3889
|
+
"recipientDid",
|
|
3890
|
+
"challengeId",
|
|
3891
|
+
"claimDigestHex",
|
|
3892
|
+
"claimJti",
|
|
3893
|
+
"vpDigestHex",
|
|
3894
|
+
"credentialEvidenceDigestHex",
|
|
3895
|
+
"decisionContextDigestHex",
|
|
3896
|
+
"issuanceAuditDigestHex",
|
|
3897
|
+
"remainingRedelegationDepth"
|
|
3898
|
+
];
|
|
3899
|
+
var CompactHeaderSchema = z4.object({
|
|
3900
|
+
alg: z4.literal("EdDSA"),
|
|
3901
|
+
jwk: z4.object({ alg: z4.literal("EdDSA"), crv: z4.literal("Ed25519"), kty: z4.literal("OKP"), x: z4.string().min(1) }).strict(),
|
|
3902
|
+
typ: z4.literal("JWT"),
|
|
3903
|
+
ucv: z4.literal("0.10.0")
|
|
3904
|
+
}).strict();
|
|
3905
|
+
var CompactPayloadSchema = z4.object({
|
|
3906
|
+
att: z4.record(z4.record(z4.array(z4.unknown()).min(1))),
|
|
3907
|
+
aud: z4.string().min(1),
|
|
3908
|
+
exp: z4.number().int(),
|
|
3909
|
+
fct: z4.array(z4.record(z4.unknown())).length(1),
|
|
3910
|
+
iss: z4.string().min(1),
|
|
3911
|
+
nbf: z4.number().int(),
|
|
3912
|
+
nnc: z4.string().min(1),
|
|
3913
|
+
prf: z4.array(z4.string().min(1))
|
|
3914
|
+
}).strict();
|
|
3915
|
+
function createCompactPolicyInvocation(input) {
|
|
3916
|
+
const session = parsePolicySessionUcan(input.sessionAuthorization);
|
|
3917
|
+
if (session.cid !== input.sessionCid || session.aud !== input.recipientDid)
|
|
3918
|
+
throw new Error("policy session does not bind the recipient signer");
|
|
3919
|
+
const principal = input.recipientDid.split("#", 1)[0];
|
|
3920
|
+
const didMaterial = base58btc.decode(principal.slice("did:key:".length));
|
|
3921
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
|
|
3922
|
+
throw new Error("policy invocation signer must be did:key Ed25519");
|
|
3923
|
+
const publicKey = ed255192.getPublicKey(input.privateKey);
|
|
3924
|
+
if (!equalBytes2(publicKey, didMaterial.slice(2)))
|
|
3925
|
+
throw new Error("policy invocation private key does not bind recipient DID");
|
|
3926
|
+
const now = input.now ?? Math.floor(Date.now() / 1e3);
|
|
3927
|
+
const exp = Math.min(now + 60, session.exp);
|
|
3928
|
+
if (exp <= now) throw new Error("policy session has expired");
|
|
3929
|
+
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
|
|
3930
|
+
const payload = {
|
|
3931
|
+
att: { [input.resource]: { [input.action]: [input.caveat ?? {}] } },
|
|
3932
|
+
aud: input.audienceDid,
|
|
3933
|
+
exp,
|
|
3934
|
+
fct: [input.facts ?? { type: "tinycloud.policy.invocation/v1", policyCid: session.fact.policyCid, sessionCid: session.cid }],
|
|
3935
|
+
iss: input.recipientDid.includes("#") ? input.recipientDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
3936
|
+
nbf: now,
|
|
3937
|
+
nnc: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
3938
|
+
prf: [session.cid]
|
|
3939
|
+
};
|
|
3940
|
+
const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
3941
|
+
const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
3942
|
+
const signingInput = new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`);
|
|
3943
|
+
const signature = ed255192.sign(signingInput, input.privateKey);
|
|
3944
|
+
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
3945
|
+
}
|
|
3946
|
+
function createCompactPolicyDescendant(input) {
|
|
3947
|
+
const parent = parseCompactUcanAuthorization(input.parentAuthorization, input.parentCid);
|
|
3948
|
+
if (parent.payload.aud !== input.issuerDid) throw new Error("policy descendant issuer is not the parent audience");
|
|
3949
|
+
const parentFact = parent.payload.fct[0];
|
|
3950
|
+
const depth = parentFact.remainingRedelegationDepth;
|
|
3951
|
+
if (!Number.isInteger(depth) || depth <= 0) throw new Error("policy descendant depth is exhausted");
|
|
3952
|
+
if (!compactAttenuationContains(parent.payload.att, input.attenuation))
|
|
3953
|
+
throw new Error("policy descendant exceeds the parent attenuation");
|
|
3954
|
+
const principal = input.issuerDid.split("#", 1)[0];
|
|
3955
|
+
const didMaterial = base58btc.decode(principal.slice("did:key:".length));
|
|
3956
|
+
const publicKey = ed255192.getPublicKey(input.privateKey);
|
|
3957
|
+
if (didMaterial.length !== 34 || !equalBytes2(publicKey, didMaterial.slice(2))) throw new Error("policy descendant signer does not bind issuer DID");
|
|
3958
|
+
const now = Math.max(input.now ?? Math.floor(Date.now() / 1e3), parent.payload.nbf + 1);
|
|
3959
|
+
const exp = Math.min(input.expiresAt ?? now + 60, now + 60, parent.payload.exp - 1);
|
|
3960
|
+
if (exp <= now) throw new Error("policy parent has no strictly narrower validity window");
|
|
3961
|
+
const header = { alg: "EdDSA", jwk: { alg: "EdDSA", crv: "Ed25519", kty: "OKP", x: encodeBase64Url(publicKey) }, typ: "JWT", ucv: "0.10.0" };
|
|
3962
|
+
const payload = {
|
|
3963
|
+
att: input.attenuation,
|
|
3964
|
+
aud: input.audienceDid,
|
|
3965
|
+
exp,
|
|
3966
|
+
fct: [{ ...parentFact, remainingRedelegationDepth: depth - 1 }],
|
|
3967
|
+
iss: input.issuerDid.includes("#") ? input.issuerDid : `${principal}#${principal.slice("did:key:".length)}`,
|
|
3968
|
+
nbf: now,
|
|
3969
|
+
nnc: input.nonce ?? encodeBase64Url(crypto.getRandomValues(new Uint8Array(16))),
|
|
3970
|
+
prf: [parent.cid]
|
|
3971
|
+
};
|
|
3972
|
+
const protectedSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(header)));
|
|
3973
|
+
const payloadSegment = encodeBase64Url(new TextEncoder().encode(jcsCanonicalize(payload)));
|
|
3974
|
+
const signature = ed255192.sign(new TextEncoder().encode(`${protectedSegment}.${payloadSegment}`), input.privateKey);
|
|
3975
|
+
return parseCompactUcanAuthorization(`${protectedSegment}.${payloadSegment}.${encodeBase64Url(signature)}`);
|
|
3976
|
+
}
|
|
3977
|
+
function compactAttenuationContains(parent, child) {
|
|
3978
|
+
const selector = (value) => {
|
|
3979
|
+
if (value.length !== 1 || !isRecordValue(value[0])) return void 0;
|
|
3980
|
+
const caveat = value[0];
|
|
3981
|
+
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;
|
|
3982
|
+
return { kind: caveat.kind, value: caveat.value };
|
|
3983
|
+
};
|
|
3984
|
+
const equal = (left, right) => jcsCanonicalize(left) === jcsCanonicalize(right);
|
|
3985
|
+
return Object.entries(child).every(
|
|
3986
|
+
([childResource, childActions]) => Object.entries(childActions).every(
|
|
3987
|
+
([action, childCaveats]) => Object.entries(parent).some(([parentResource, parentActions]) => {
|
|
3988
|
+
const parentCaveats = parentActions[action];
|
|
3989
|
+
if (parentCaveats === void 0) return false;
|
|
3990
|
+
if (parentResource === childResource && equal(parentCaveats, childCaveats)) return true;
|
|
3991
|
+
const parentSelector = selector(parentCaveats);
|
|
3992
|
+
const childSelector = selector(childCaveats);
|
|
3993
|
+
return parentSelector?.kind === "prefix" && childSelector !== void 0 && parentSelector.value === parentResource && childSelector.value === childResource && (childResource === parentResource || childResource.startsWith(`${parentResource}/`));
|
|
3994
|
+
})
|
|
3995
|
+
)
|
|
3996
|
+
);
|
|
3997
|
+
}
|
|
3998
|
+
function isRecordValue(value) {
|
|
3999
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
4000
|
+
}
|
|
4001
|
+
function parseCompactUcanAuthorization(input, expectedCid) {
|
|
4002
|
+
if (typeof input !== "string" || /\s/.test(input))
|
|
4003
|
+
throw new Error("Authorization must be compact UCAN bytes");
|
|
4004
|
+
const segments = input.split(".");
|
|
4005
|
+
if (segments.length !== 3 || segments.some((segment) => segment.length === 0))
|
|
4006
|
+
throw new Error("Authorization must have three compact segments");
|
|
4007
|
+
const [headerSegment, payloadSegment, signatureSegment] = segments;
|
|
4008
|
+
const headerBytes = decodeBase64Url(headerSegment);
|
|
4009
|
+
const payloadBytes = decodeBase64Url(payloadSegment);
|
|
4010
|
+
const signature = decodeBase64Url(signatureSegment);
|
|
4011
|
+
const headerValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(headerBytes));
|
|
4012
|
+
const payloadValue = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(payloadBytes));
|
|
4013
|
+
if (jcsCanonicalize(headerValue) !== new TextDecoder().decode(headerBytes) || jcsCanonicalize(payloadValue) !== new TextDecoder().decode(payloadBytes))
|
|
4014
|
+
throw new Error("compact UCAN segments are not canonical JCS");
|
|
4015
|
+
const header = CompactHeaderSchema.parse(headerValue);
|
|
4016
|
+
const payload = CompactPayloadSchema.parse(payloadValue);
|
|
4017
|
+
if (payload.nbf >= payload.exp) throw new Error("compact UCAN validity is empty");
|
|
4018
|
+
const principal = payload.iss.split("#", 1)[0];
|
|
4019
|
+
const didMaterial = principal.startsWith("did:key:") ? base58btc.decode(principal.slice("did:key:".length)) : new Uint8Array();
|
|
4020
|
+
if (didMaterial.length !== 34 || didMaterial[0] !== 237 || didMaterial[1] !== 1)
|
|
4021
|
+
throw new Error("compact UCAN issuer must be did:key Ed25519");
|
|
4022
|
+
const publicKey = didMaterial.slice(2);
|
|
4023
|
+
if (!equalBytes2(publicKey, decodeBase64Url(header.jwk.x)))
|
|
4024
|
+
throw new Error("compact UCAN JWK does not bind issuer");
|
|
4025
|
+
if (!ed255192.verify(signature, new TextEncoder().encode(`${headerSegment}.${payloadSegment}`), publicKey))
|
|
4026
|
+
throw new Error("compact UCAN signature is invalid");
|
|
4027
|
+
const cid2 = CID.createV1(85, create(30, blake32(new TextEncoder().encode(input)))).toString();
|
|
4028
|
+
if (expectedCid !== void 0 && cid2 !== expectedCid)
|
|
4029
|
+
throw new Error("compact UCAN CID does not match exact Authorization bytes");
|
|
4030
|
+
return { authorization: input, cid: cid2, header, payload };
|
|
4031
|
+
}
|
|
4032
|
+
function parsePolicySessionUcan(authorization, expectedProofs) {
|
|
4033
|
+
const parsed = parseCompactUcanAuthorization(authorization);
|
|
4034
|
+
const fact = parsed.payload.fct[0];
|
|
4035
|
+
if (parsed.payload.prf.length !== 2 || parsed.payload.prf[0] === parsed.payload.prf[1])
|
|
4036
|
+
throw new Error("policy session UCAN requires two distinct ordered proofs");
|
|
4037
|
+
if (expectedProofs !== void 0 && (parsed.payload.prf[0] !== expectedProofs[0] || parsed.payload.prf[1] !== expectedProofs[1]))
|
|
4038
|
+
throw new Error("policy session UCAN ordered proofs do not match");
|
|
4039
|
+
const factKeys = Object.keys(fact);
|
|
4040
|
+
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)))
|
|
4041
|
+
throw new Error("policy session UCAN fact is incomplete");
|
|
4042
|
+
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)
|
|
4043
|
+
throw new Error("policy session UCAN fact is invalid");
|
|
4044
|
+
return {
|
|
4045
|
+
authorization,
|
|
4046
|
+
cid: parsed.cid,
|
|
4047
|
+
iss: parsed.payload.iss,
|
|
4048
|
+
aud: parsed.payload.aud,
|
|
4049
|
+
prf: parsed.payload.prf,
|
|
4050
|
+
att: parsed.payload.att,
|
|
4051
|
+
nbf: parsed.payload.nbf,
|
|
4052
|
+
exp: parsed.payload.exp,
|
|
4053
|
+
nnc: parsed.payload.nnc,
|
|
4054
|
+
fact
|
|
4055
|
+
};
|
|
4056
|
+
}
|
|
4057
|
+
function decodeBase64Url(value) {
|
|
4058
|
+
if (!/^[A-Za-z0-9_-]+$/.test(value) || value.length % 4 === 1)
|
|
4059
|
+
throw new Error("value is not canonical base64url");
|
|
4060
|
+
const normalized = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
4061
|
+
const binary = typeof Buffer !== "undefined" ? Buffer.from(normalized, "base64").toString("binary") : atob(normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "="));
|
|
4062
|
+
const bytes2 = Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
4063
|
+
const encoded = typeof Buffer !== "undefined" ? Buffer.from(bytes2).toString("base64url") : btoa(String.fromCharCode(...bytes2)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
4064
|
+
if (encoded !== value) throw new Error("value is not canonical base64url");
|
|
4065
|
+
return bytes2;
|
|
4066
|
+
}
|
|
4067
|
+
function encodeBase64Url(value) {
|
|
4068
|
+
return typeof Buffer !== "undefined" ? Buffer.from(value).toString("base64url") : btoa(String.fromCharCode(...value)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
4069
|
+
}
|
|
4070
|
+
function equalBytes2(left, right) {
|
|
4071
|
+
return left.length === right.length && left.every((byte, index) => byte === right[index]);
|
|
4072
|
+
}
|
|
4073
|
+
|
|
4074
|
+
// src/delegations/portable.ts
|
|
4075
|
+
var ResourceSchema = z5.object({
|
|
4076
|
+
service: z5.string().min(1),
|
|
4077
|
+
space: z5.string().min(1),
|
|
4078
|
+
path: z5.string(),
|
|
4079
|
+
actions: z5.array(z5.string().min(1)).min(1),
|
|
4080
|
+
caveats: z5.array(z5.record(z5.unknown())).optional()
|
|
4081
|
+
}).strict();
|
|
4082
|
+
var PortableDelegationSchema = z5.object({
|
|
4083
|
+
cid: z5.string().min(1),
|
|
4084
|
+
delegationHeader: z5.object({ Authorization: z5.string().min(1) }).strict(),
|
|
4085
|
+
ownerAddress: z5.string().min(1),
|
|
4086
|
+
chainId: z5.number().int().nonnegative(),
|
|
4087
|
+
host: z5.string().url().optional(),
|
|
4088
|
+
spaceId: z5.string().min(1),
|
|
4089
|
+
path: z5.string(),
|
|
4090
|
+
actions: z5.array(z5.string().min(1)).min(1),
|
|
4091
|
+
caveats: z5.array(z5.record(z5.unknown())).optional(),
|
|
4092
|
+
expiry: z5.coerce.date(),
|
|
4093
|
+
delegateDID: z5.string().min(1),
|
|
4094
|
+
delegatorDID: z5.string().min(1).optional(),
|
|
4095
|
+
parentCid: z5.string().min(1).optional(),
|
|
4096
|
+
disableSubDelegation: z5.boolean().optional(),
|
|
4097
|
+
resources: z5.array(ResourceSchema).min(1).optional()
|
|
4098
|
+
}).strict();
|
|
4099
|
+
function parsePortableDelegation(input) {
|
|
4100
|
+
const parsed = PortableDelegationSchema.parse(input);
|
|
4101
|
+
if (parsed.resources !== void 0 && parsed.resources.length === 0)
|
|
4102
|
+
throw new Error("portable delegation resources must not be empty");
|
|
4103
|
+
return parsed;
|
|
4104
|
+
}
|
|
4105
|
+
function serializePortableDelegation(delegation) {
|
|
4106
|
+
return JSON.stringify({
|
|
4107
|
+
...delegation,
|
|
4108
|
+
expiry: delegation.expiry.toISOString()
|
|
4109
|
+
});
|
|
4110
|
+
}
|
|
4111
|
+
async function importPortableDelegation(fetchFn, host, delegation) {
|
|
4112
|
+
const parsed = parsePortableDelegation(delegation);
|
|
4113
|
+
const response = await fetchFn(`${host.replace(/\/+$/, "")}/delegate`, {
|
|
4114
|
+
method: "POST",
|
|
4115
|
+
headers: { Authorization: parsed.delegationHeader.Authorization }
|
|
4116
|
+
});
|
|
4117
|
+
if (!response.ok)
|
|
4118
|
+
throw new Error(`node rejected delegation import (${response.status})`);
|
|
4119
|
+
const body = await response.json().catch(() => ({}));
|
|
4120
|
+
if (body === null || typeof body !== "object" || Array.isArray(body))
|
|
4121
|
+
return {};
|
|
4122
|
+
return body;
|
|
4123
|
+
}
|
|
4124
|
+
async function delegatePortablePolicySession(input) {
|
|
4125
|
+
const parent = parsePortableDelegation(input.parent);
|
|
4126
|
+
const descendant = createCompactPolicyDescendant({
|
|
4127
|
+
parentAuthorization: parent.delegationHeader.Authorization.replace(/^Bearer\s+/i, ""),
|
|
4128
|
+
parentCid: parent.cid,
|
|
4129
|
+
issuerDid: parent.delegateDID,
|
|
4130
|
+
audienceDid: input.delegateDID,
|
|
4131
|
+
attenuation: input.attenuation,
|
|
4132
|
+
privateKey: input.issuerPrivateKey,
|
|
4133
|
+
...input.now === void 0 ? {} : { now: input.now },
|
|
4134
|
+
...input.expiresAt === void 0 ? {} : { expiresAt: input.expiresAt },
|
|
4135
|
+
...input.nonce === void 0 ? {} : { nonce: input.nonce }
|
|
4136
|
+
});
|
|
4137
|
+
const resources = Object.entries(descendant.payload.att).map(([resource, abilities]) => {
|
|
4138
|
+
const actions = Object.keys(abilities);
|
|
4139
|
+
if (resource.startsWith("urn:tinycloud:encryption:")) {
|
|
4140
|
+
return { service: "encryption", space: "encryption", path: resource, actions };
|
|
4141
|
+
}
|
|
4142
|
+
const match = /^tinycloud:\/\/([^/]+)\/kv\/(.+)$/.exec(resource);
|
|
4143
|
+
if (match === null) throw new Error("policy descendant resource is invalid");
|
|
4144
|
+
const caveats = Object.values(abilities).flat().filter((value) => value !== null && typeof value === "object" && !Array.isArray(value));
|
|
4145
|
+
return { service: "kv", space: match[1], path: match[2], actions, ...caveats.length === 0 ? {} : { caveats } };
|
|
4146
|
+
});
|
|
4147
|
+
const primary = resources.find((resource) => resource.service === "kv") ?? resources[0];
|
|
4148
|
+
if (primary === void 0) throw new Error("policy descendant attenuation is empty");
|
|
4149
|
+
const portable = {
|
|
4150
|
+
cid: descendant.cid,
|
|
4151
|
+
delegationHeader: { Authorization: descendant.authorization },
|
|
4152
|
+
ownerAddress: parent.ownerAddress,
|
|
4153
|
+
chainId: parent.chainId,
|
|
4154
|
+
host: input.host,
|
|
4155
|
+
spaceId: primary.space,
|
|
4156
|
+
path: primary.path,
|
|
4157
|
+
actions: primary.actions,
|
|
4158
|
+
expiry: new Date(descendant.payload.exp * 1e3),
|
|
4159
|
+
delegateDID: input.delegateDID,
|
|
4160
|
+
delegatorDID: parent.delegateDID,
|
|
4161
|
+
parentCid: parent.cid,
|
|
4162
|
+
disableSubDelegation: descendant.payload.fct[0]?.remainingRedelegationDepth === 0,
|
|
4163
|
+
resources
|
|
4164
|
+
};
|
|
4165
|
+
await importPortableDelegation(input.fetch, input.host, portable);
|
|
4166
|
+
return portable;
|
|
4167
|
+
}
|
|
4168
|
+
|
|
3637
4169
|
// src/delegations/ShareRecipientClient.ts
|
|
3638
4170
|
var DEFAULT_MAX_ARTIFACT_BYTES2 = MAX_SHARE_ARTIFACT_BYTES;
|
|
3639
4171
|
var DEFAULT_MAX_CONTENT_BYTES = MAX_SHARE_CONTENT_BYTES;
|
|
@@ -3709,7 +4241,7 @@ function randomJti() {
|
|
|
3709
4241
|
return bytesToBase64Url2(bytes2);
|
|
3710
4242
|
}
|
|
3711
4243
|
function digestCanonical(value) {
|
|
3712
|
-
return bytesToBase64Url2(
|
|
4244
|
+
return bytesToBase64Url2(sha2565(new TextEncoder().encode(canonicalJsonForProof(value))));
|
|
3713
4245
|
}
|
|
3714
4246
|
function actionWire(action) {
|
|
3715
4247
|
return action === "get" ? "tinycloud.kv/get" : action === "metadata" ? "tinycloud.kv/metadata" : action === "list" ? "tinycloud.kv/list" : "tinycloud.kv/put";
|
|
@@ -3806,15 +4338,46 @@ var ShareRecipientClient = class {
|
|
|
3806
4338
|
const { envelope } = resolved.artifact;
|
|
3807
4339
|
const { location } = resolved;
|
|
3808
4340
|
const bearer = isBearerEnvelope(envelope);
|
|
3809
|
-
const policy = envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain";
|
|
4341
|
+
const policy = envelope.recipientKind === "exactEmail" || envelope.recipientKind === "emailDomain" || envelope.authorizationTargetKind === "recipientDid";
|
|
3810
4342
|
const legacyBearer = !policy && envelope.recipientKind === void 0;
|
|
3811
|
-
|
|
4343
|
+
let recipientDidSession;
|
|
4344
|
+
if (envelope.authorizationTargetKind === "recipientDid") {
|
|
4345
|
+
if (this.options.establishRecipientDidSession === void 0) throw new ShareAccessError("SHARE_DEVICE_AUTH_REQUIRED", "an OpenKey device authorization is required");
|
|
4346
|
+
const authorization = await this.options.establishRecipientDidSession({ envelope, recipientDid: envelope.recipient?.kind === "recipientDid" ? envelope.recipient.value : "" });
|
|
4347
|
+
if ("state" in authorization) {
|
|
4348
|
+
if (authorization.state === "authorization-required") throw new ShareAccessError("SHARE_DEVICE_AUTH_REQUIRED", "an OpenKey device authorization is required", authorization);
|
|
4349
|
+
throw new ShareAccessError("SHARE_DENIED", "recipient DID authorization was denied", authorization);
|
|
4350
|
+
}
|
|
4351
|
+
recipientDidSession = authorization;
|
|
4352
|
+
}
|
|
3812
4353
|
if (policy && this.options.bearerSession !== void 0) throw new ShareAccessError("SHARE_POLICY_BEARER_MISMATCH");
|
|
3813
4354
|
if (bearer && this.options.presentation !== void 0) throw new ShareAccessError("SHARE_BEARER_PRESENTATION_MISMATCH");
|
|
3814
|
-
const session = bearer || legacyBearer ? this.options.bearerSession : policy && this.options.establishPolicySession !== void 0 ? await this.options.establishPolicySession({ envelope, presentation: this.options.presentation }) : policy ? await this.establishPolicySession(envelope) : void 0;
|
|
3815
|
-
const kv = bearer || legacyBearer ? session === void 0 ? void 0 : this.createKV(envelope.origin, session) : void 0;
|
|
4355
|
+
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;
|
|
3816
4356
|
const policySession = policy ? session : void 0;
|
|
3817
4357
|
if (policySession !== void 0) this.assertProvidedPolicySession(policySession, envelope);
|
|
4358
|
+
const portableDelegation = policySession === void 0 ? void 0 : this.policySessionDelegation(policySession, envelope.origin);
|
|
4359
|
+
const portableInvoke = portableDelegation === void 0 ? void 0 : this.policyInvocationSigner(portableDelegation);
|
|
4360
|
+
if (portableDelegation !== void 0) {
|
|
4361
|
+
if (this.options.importDelegation === void 0) {
|
|
4362
|
+
await importPortableDelegation(this.fetchFn, envelope.origin, portableDelegation);
|
|
4363
|
+
} else {
|
|
4364
|
+
const imported = await this.options.importDelegation(portableDelegation);
|
|
4365
|
+
if (imported !== void 0) {
|
|
4366
|
+
const normalized = parsePortableDelegation(imported);
|
|
4367
|
+
if (normalized.delegationHeader.Authorization !== portableDelegation.delegationHeader.Authorization) {
|
|
4368
|
+
throw new ShareAccessError("SHARE_SESSION_INVALID", "delegation importer changed authorization bytes");
|
|
4369
|
+
}
|
|
4370
|
+
}
|
|
4371
|
+
}
|
|
4372
|
+
}
|
|
4373
|
+
const ordinarySession = portableDelegation === void 0 ? void 0 : {
|
|
4374
|
+
delegationHeader: portableDelegation.delegationHeader,
|
|
4375
|
+
delegationCid: portableDelegation.cid,
|
|
4376
|
+
spaceId: this.policySessionProjection(portableDelegation).spaceId,
|
|
4377
|
+
verificationMethod: portableDelegation.delegateDID,
|
|
4378
|
+
jwk: this.options.bearerSession?.jwk ?? {}
|
|
4379
|
+
};
|
|
4380
|
+
const kv = bearer || legacyBearer || ordinarySession !== void 0 ? session === void 0 && ordinarySession === void 0 ? void 0 : this.createKV(envelope.origin, ordinarySession ?? session, portableInvoke) : void 0;
|
|
3818
4381
|
const advertisedCapability = { spaceId: envelope.spaceId, resource: envelope.resource, actions: envelope.actions };
|
|
3819
4382
|
const capability = policySession?.capability === void 0 ? advertisedCapability : intersectShareCapabilities(advertisedCapability, policySession.capability);
|
|
3820
4383
|
if (capability === void 0) throw new ShareAccessError("SHARE_CAPABILITY_EMPTY");
|
|
@@ -3839,6 +4402,11 @@ var ShareRecipientClient = class {
|
|
|
3839
4402
|
const scope = normalizePath(input.path ?? envelope.resource.path);
|
|
3840
4403
|
this.assertAllowed(capability, "list", scope);
|
|
3841
4404
|
if (kv === void 0 && policySession === void 0) throw new ShareAccessError("SHARE_SESSION_REQUIRED");
|
|
4405
|
+
if (portableDelegation !== void 0 && kv !== void 0) {
|
|
4406
|
+
const result2 = await kv.list({ path: scope, limit: input.limit, cursor: input.cursor });
|
|
4407
|
+
if (!result2.ok) throw result2.error;
|
|
4408
|
+
return { keys: result2.data.keys, truncated: result2.data.truncated, nextCursor: result2.data.nextCursor };
|
|
4409
|
+
}
|
|
3842
4410
|
if (policySession !== void 0) return this.nativeList(envelope, policySession, scope, input.limit, input.cursor);
|
|
3843
4411
|
const result = await kv.list({ path: scope, limit: input.limit, cursor: input.cursor });
|
|
3844
4412
|
if (!result.ok) throw result.error;
|
|
@@ -3852,6 +4420,14 @@ var ShareRecipientClient = class {
|
|
|
3852
4420
|
const resolvedPath = normalizePath(path);
|
|
3853
4421
|
this.assertAllowed(capability, "save", resolvedPath);
|
|
3854
4422
|
if (kv === void 0 && policySession === void 0) throw new ShareAccessError("SHARE_SESSION_REQUIRED");
|
|
4423
|
+
if (portableDelegation !== void 0 && kv !== void 0) {
|
|
4424
|
+
const result2 = await kv.put(resolvedPath, bytes2, { contentType: input.contentType ?? envelope.content.mimeType, ifMatch: input.etag });
|
|
4425
|
+
if (!result2.ok) {
|
|
4426
|
+
if (result2.error.code === ErrorCodes.KV_PRECONDITION_FAILED || result2.error.code === ErrorCodes.KV_CONFLICT) throw new ShareConflict(resolvedPath, result2.error.meta?.etag);
|
|
4427
|
+
throw result2.error;
|
|
4428
|
+
}
|
|
4429
|
+
return { etag: result2.data.headers.etag };
|
|
4430
|
+
}
|
|
3855
4431
|
if (policySession !== void 0) return this.nativeSave(envelope, policySession, resolvedPath, bytes2, input);
|
|
3856
4432
|
const result = await kv.put(resolvedPath, bytes2, { contentType: input.contentType ?? envelope.content.mimeType, ifMatch: input.etag });
|
|
3857
4433
|
if (!result.ok) {
|
|
@@ -3867,22 +4443,79 @@ var ShareRecipientClient = class {
|
|
|
3867
4443
|
const metadata = async (path = envelope.resource.kind === "exact" ? envelope.resource.path : "") => {
|
|
3868
4444
|
const resolvedPath = normalizePath(path);
|
|
3869
4445
|
this.assertAllowed(capability, "metadata", resolvedPath);
|
|
4446
|
+
if (portableDelegation !== void 0 && kv !== void 0) {
|
|
4447
|
+
const result2 = await kv.head(resolvedPath);
|
|
4448
|
+
if (!result2.ok) throw result2.error;
|
|
4449
|
+
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 };
|
|
4450
|
+
}
|
|
3870
4451
|
if (policySession !== void 0) return this.nativeMetadata(envelope, policySession, resolvedPath);
|
|
3871
4452
|
if (kv === void 0) throw new ShareAccessError("SHARE_SESSION_REQUIRED");
|
|
3872
4453
|
const result = await kv.head(resolvedPath);
|
|
3873
4454
|
if (!result.ok) throw result.error;
|
|
3874
4455
|
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 };
|
|
3875
4456
|
};
|
|
3876
|
-
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 };
|
|
4457
|
+
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 };
|
|
3877
4458
|
} catch (error) {
|
|
3878
4459
|
throw asError(error);
|
|
3879
4460
|
}
|
|
3880
4461
|
}
|
|
3881
|
-
|
|
4462
|
+
policySessionDelegation(session, origin) {
|
|
4463
|
+
if (session.runtimeDelegation === void 0) return void 0;
|
|
4464
|
+
const delegation = parsePortableDelegation(session.runtimeDelegation);
|
|
4465
|
+
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");
|
|
4466
|
+
return delegation;
|
|
4467
|
+
}
|
|
4468
|
+
policyInvocationSigner(delegation) {
|
|
4469
|
+
const privateKey = this.options.policySessionPrivateKey;
|
|
4470
|
+
if (privateKey === void 0) throw new ShareAccessError("SHARE_SESSION_SIGNER_REQUIRED");
|
|
4471
|
+
const session = parsePolicySessionUcan(delegation.delegationHeader.Authorization);
|
|
4472
|
+
if (session.cid !== delegation.cid || session.aud !== delegation.delegateDID)
|
|
4473
|
+
throw new ShareAccessError("SHARE_SESSION_INVALID");
|
|
4474
|
+
return (_serviceSession, service, path, action, facts) => {
|
|
4475
|
+
const serviceName = service.replace(/^tinycloud\./, "");
|
|
4476
|
+
const cleanPath = path.replace(/^\//, "").replace(/\/$/, "");
|
|
4477
|
+
const authority = Object.entries(session.att).find(([parentResource, abilities]) => {
|
|
4478
|
+
if (!(action in abilities)) return false;
|
|
4479
|
+
if (serviceName === "encryption") return parentResource.startsWith("urn:tinycloud:encryption:") && parentResource === cleanPath;
|
|
4480
|
+
const match = /^tinycloud:\/\/[^/]+\/kv\/(.+)$/.exec(parentResource);
|
|
4481
|
+
if (match === null) return false;
|
|
4482
|
+
const parentPath = match[1];
|
|
4483
|
+
const caveats = abilities[action] ?? [];
|
|
4484
|
+
const prefix = caveats.some((value) => isRecord(value) && value.kind === "prefix");
|
|
4485
|
+
return cleanPath === parentPath || prefix && cleanPath.startsWith(`${parentPath}/`);
|
|
4486
|
+
});
|
|
4487
|
+
if (authority === void 0) throw new ShareAccessError("SHARE_OUT_OF_SCOPE");
|
|
4488
|
+
const resource = serviceName === "encryption" ? authority[0] : `${authority[0].slice(0, authority[0].indexOf("/kv/") + 4)}${cleanPath}`;
|
|
4489
|
+
const caveat = serviceName === "encryption" ? {} : { type: "xyz.tinycloud.resource/selector", kind: "exact", value: resource };
|
|
4490
|
+
const invocation = createCompactPolicyInvocation({
|
|
4491
|
+
sessionAuthorization: delegation.delegationHeader.Authorization,
|
|
4492
|
+
sessionCid: delegation.cid,
|
|
4493
|
+
recipientDid: delegation.delegateDID,
|
|
4494
|
+
audienceDid: String(session.fact.nodeAudience),
|
|
4495
|
+
resource,
|
|
4496
|
+
action,
|
|
4497
|
+
caveat,
|
|
4498
|
+
...facts?.length === 1 ? { facts: facts[0] } : {},
|
|
4499
|
+
privateKey,
|
|
4500
|
+
now: Math.floor(this.now().getTime() / 1e3)
|
|
4501
|
+
});
|
|
4502
|
+
return { Authorization: invocation.authorization };
|
|
4503
|
+
};
|
|
4504
|
+
}
|
|
4505
|
+
policySessionProjection(delegation) {
|
|
4506
|
+
const session = parsePolicySessionUcan(delegation.delegationHeader.Authorization);
|
|
4507
|
+
if (session.cid !== delegation.cid || session.aud !== delegation.delegateDID) throw new ShareAccessError("SHARE_SESSION_INVALID");
|
|
4508
|
+
const kvResource = Object.keys(session.att).find((resource) => /^tinycloud:\/\/[^/]+\/kv\/.+$/.test(resource));
|
|
4509
|
+
const match = kvResource === void 0 ? void 0 : /^tinycloud:\/\/([^/]+)\/kv\/(.+)$/.exec(kvResource);
|
|
4510
|
+
if (match === void 0 || match === null) throw new ShareAccessError("SHARE_SESSION_INVALID");
|
|
4511
|
+
return { spaceId: match[1] };
|
|
4512
|
+
}
|
|
4513
|
+
createKV(origin, session, invokeOverride) {
|
|
4514
|
+
const invoke = invokeOverride ?? this.options.invoke ?? nativeInvoke;
|
|
3882
4515
|
if (this.options.createKVService !== void 0) {
|
|
3883
|
-
return this.options.createKVService({ hosts: [origin], session, invoke
|
|
4516
|
+
return this.options.createKVService({ hosts: [origin], session, invoke, fetch: this.fetchFn });
|
|
3884
4517
|
}
|
|
3885
|
-
const context = new ServiceContext({ hosts: [origin], session, invoke
|
|
4518
|
+
const context = new ServiceContext({ hosts: [origin], session, invoke, fetch: this.fetchFn });
|
|
3886
4519
|
const service = new KVService({ prefix: "" });
|
|
3887
4520
|
context.registerService("kv", service);
|
|
3888
4521
|
service.initialize(context);
|
|
@@ -3925,7 +4558,7 @@ var ShareRecipientClient = class {
|
|
|
3925
4558
|
if (bytes2.byteLength > (this.options.maxContentBytes ?? DEFAULT_MAX_CONTENT_BYTES)) throw new ShareAccessError("SHARE_TOO_LARGE");
|
|
3926
4559
|
const contentType = input.contentType ?? envelope.content.mimeType;
|
|
3927
4560
|
if (contentType !== envelope.content.mimeType && !/^text\/(?:plain|markdown)(?:;|$)/i.test(contentType)) throw new ShareAccessError("SHARE_CONTENT_TYPE_INVALID");
|
|
3928
|
-
const result = await this.invokeNative({ envelope, session, action: "put", resource: path, body: bytes2, bodyDigest: bytesToBase64Url2(
|
|
4561
|
+
const result = await this.invokeNative({ envelope, session, action: "put", resource: path, body: bytes2, bodyDigest: bytesToBase64Url2(sha2565(bytes2)), contentType, ifMatch: input.etag, mediaType: "application/vnd.tinycloud.share+json" });
|
|
3929
4562
|
if (result.status === 412 || result.status === 409) throw new ShareConflict(path, result.headers?.etag);
|
|
3930
4563
|
if (result.status === 401 || result.status === 403) throw new ShareAccessError("SHARE_DENIED");
|
|
3931
4564
|
if (result.status < 200 || result.status >= 300) throw new ShareAccessError("SHARE_WRITE_FAILED");
|
|
@@ -4047,7 +4680,7 @@ var ShareRecipientClient = class {
|
|
|
4047
4680
|
};
|
|
4048
4681
|
const signed = this.options.signNativeInvoke === void 0 ? void 0 : await this.options.signNativeInvoke({ envelope: input.envelope, session: input.session, request: body });
|
|
4049
4682
|
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;
|
|
4050
|
-
const response = await this.fetchFn(
|
|
4683
|
+
const response = await this.fetchFn(`${base3}/invoke`, {
|
|
4051
4684
|
method: "POST",
|
|
4052
4685
|
headers: { ...headersRecord(transport), ...headersRecord(signed), "content-type": input.mediaType, accept: input.mediaType },
|
|
4053
4686
|
body: JSON.stringify(body),
|
|
@@ -4171,7 +4804,7 @@ var ShareRecipientClient = class {
|
|
|
4171
4804
|
}]);
|
|
4172
4805
|
}
|
|
4173
4806
|
digestMatches(value, bytes2) {
|
|
4174
|
-
const digest4 = bytesToBase64Url2(
|
|
4807
|
+
const digest4 = bytesToBase64Url2(sha2565(bytes2));
|
|
4175
4808
|
return value === digest4 || value === `sha-256=:${digest4}:`;
|
|
4176
4809
|
}
|
|
4177
4810
|
assertNativeRequestBounds(envelope, session, operation, path, limit, cursor) {
|
|
@@ -4389,7 +5022,7 @@ var ShareRecipientClient = class {
|
|
|
4389
5022
|
nodeAudience: binding.nodeAudience,
|
|
4390
5023
|
...isV2 ? {
|
|
4391
5024
|
enforcerDid: challenge.enforcerDid,
|
|
4392
|
-
credentialDigest: typeof presentation.credentialDigest === "string" ? presentation.credentialDigest : bytesToBase64Url2(
|
|
5025
|
+
credentialDigest: typeof presentation.credentialDigest === "string" ? presentation.credentialDigest : bytesToBase64Url2(sha2565(new TextEncoder().encode(credential)))
|
|
4393
5026
|
} : {},
|
|
4394
5027
|
action,
|
|
4395
5028
|
...binding.actions === void 0 ? {} : { actions: [...binding.actions] },
|
|
@@ -4455,7 +5088,7 @@ var ShareRecipientClient = class {
|
|
|
4455
5088
|
}
|
|
4456
5089
|
if (isJwsProof && detached.kid !== `${signerDid}#${encoded}` || isEd25519Proof && detached.signerDid !== signerDid || signature.length !== 64) throw new ShareAccessError("SHARE_SESSION_INVALID", "Node proof binding is invalid");
|
|
4457
5090
|
const bytes2 = new TextEncoder().encode(`${domain}${canonicalJsonForProof(message)}`);
|
|
4458
|
-
if (!
|
|
5091
|
+
if (!ed255193.verify(signature, bytes2, key)) throw new ShareAccessError("SHARE_SESSION_INVALID", "Node proof signature is invalid");
|
|
4459
5092
|
}
|
|
4460
5093
|
assertChallengeRequestBinding(request, challenge) {
|
|
4461
5094
|
const source = isRecord(request.body) ? request.body : request;
|
|
@@ -5659,7 +6292,7 @@ function shareKeyMatchesDid(key, didUrl) {
|
|
|
5659
6292
|
if (!publicKey) return false;
|
|
5660
6293
|
const jwkBytes = decodeBase64UrlBytes(key.x);
|
|
5661
6294
|
const privateKey = decodeBase64UrlBytes(key.d);
|
|
5662
|
-
const derivedPublicKey =
|
|
6295
|
+
const derivedPublicKey = ed255194.getPublicKey(privateKey);
|
|
5663
6296
|
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]);
|
|
5664
6297
|
} catch {
|
|
5665
6298
|
return false;
|
|
@@ -5709,240 +6342,16 @@ function verifySignedChild(result, expected, computeCid) {
|
|
|
5709
6342
|
}
|
|
5710
6343
|
|
|
5711
6344
|
// src/delegations/owner-policy.ts
|
|
5712
|
-
import { ed25519 as
|
|
6345
|
+
import { ed25519 as ed255196 } from "@noble/curves/ed25519";
|
|
5713
6346
|
import { sha256 as sha2567 } from "@noble/hashes/sha256";
|
|
5714
6347
|
|
|
5715
6348
|
// src/policy/signed-object.ts
|
|
5716
|
-
import { ed25519 as
|
|
5717
|
-
import { bytesToHex
|
|
5718
|
-
|
|
5719
|
-
// src/policy/capability.ts
|
|
5720
|
-
import { CAPABILITY_REGISTRY } from "@tinycloud/bootstrap";
|
|
5721
|
-
import { bytesToHex, sha256 as sha2565 } from "viem";
|
|
5722
|
-
|
|
5723
|
-
// src/policy/errors.ts
|
|
5724
|
-
var SignedObjectProfileError = class extends Error {
|
|
5725
|
-
constructor(code3, message) {
|
|
5726
|
-
super(message);
|
|
5727
|
-
this.name = "SignedObjectProfileError";
|
|
5728
|
-
this.code = code3;
|
|
5729
|
-
}
|
|
5730
|
-
};
|
|
5731
|
-
var SignedObjectCanonicalizationError = class extends SignedObjectProfileError {
|
|
5732
|
-
constructor(message) {
|
|
5733
|
-
super("canonicalization-mismatch", message);
|
|
5734
|
-
this.name = "SignedObjectCanonicalizationError";
|
|
5735
|
-
}
|
|
5736
|
-
};
|
|
5737
|
-
|
|
5738
|
-
// src/policy/jcs.ts
|
|
5739
|
-
var objectHasOwn = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
|
|
5740
|
-
Object.prototype.hasOwnProperty
|
|
5741
|
-
);
|
|
5742
|
-
function jcsCanonicalize(input) {
|
|
5743
|
-
return serialize(normalizeJson(input, "$"));
|
|
5744
|
-
}
|
|
5745
|
-
function normalizeJson(input, path = "$") {
|
|
5746
|
-
if (input === null) {
|
|
5747
|
-
return null;
|
|
5748
|
-
}
|
|
5749
|
-
switch (typeof input) {
|
|
5750
|
-
case "boolean":
|
|
5751
|
-
return input;
|
|
5752
|
-
case "number":
|
|
5753
|
-
if (!Number.isFinite(input)) {
|
|
5754
|
-
throw new SignedObjectCanonicalizationError(
|
|
5755
|
-
`${path} must be a finite JSON number`
|
|
5756
|
-
);
|
|
5757
|
-
}
|
|
5758
|
-
return input;
|
|
5759
|
-
case "string":
|
|
5760
|
-
assertUnicodeScalarString(input, path);
|
|
5761
|
-
return input;
|
|
5762
|
-
case "object":
|
|
5763
|
-
return normalizeJsonObjectOrArray(input, path);
|
|
5764
|
-
case "bigint":
|
|
5765
|
-
case "function":
|
|
5766
|
-
case "symbol":
|
|
5767
|
-
case "undefined":
|
|
5768
|
-
default:
|
|
5769
|
-
throw new SignedObjectCanonicalizationError(
|
|
5770
|
-
`${path} is not a JSON value`
|
|
5771
|
-
);
|
|
5772
|
-
}
|
|
5773
|
-
}
|
|
5774
|
-
function serialize(value) {
|
|
5775
|
-
if (value === null) {
|
|
5776
|
-
return "null";
|
|
5777
|
-
}
|
|
5778
|
-
switch (typeof value) {
|
|
5779
|
-
case "boolean":
|
|
5780
|
-
return value ? "true" : "false";
|
|
5781
|
-
case "number": {
|
|
5782
|
-
const encoded = JSON.stringify(value);
|
|
5783
|
-
if (encoded === void 0) {
|
|
5784
|
-
throw new SignedObjectCanonicalizationError(
|
|
5785
|
-
"number could not be serialized as JSON"
|
|
5786
|
-
);
|
|
5787
|
-
}
|
|
5788
|
-
return encoded;
|
|
5789
|
-
}
|
|
5790
|
-
case "string":
|
|
5791
|
-
return JSON.stringify(value);
|
|
5792
|
-
case "object":
|
|
5793
|
-
if (Array.isArray(value)) {
|
|
5794
|
-
return `[${value.map((item) => serialize(item)).join(",")}]`;
|
|
5795
|
-
}
|
|
5796
|
-
return serializeObject(value);
|
|
5797
|
-
default:
|
|
5798
|
-
throw new SignedObjectCanonicalizationError(
|
|
5799
|
-
`unsupported JSON value type ${typeof value}`
|
|
5800
|
-
);
|
|
5801
|
-
}
|
|
5802
|
-
}
|
|
5803
|
-
function normalizeJsonObjectOrArray(input, path) {
|
|
5804
|
-
assertNoSymbolKeys(input, path);
|
|
5805
|
-
if (Array.isArray(input)) {
|
|
5806
|
-
for (const key of Object.getOwnPropertyNames(input)) {
|
|
5807
|
-
if (key === "length") {
|
|
5808
|
-
continue;
|
|
5809
|
-
}
|
|
5810
|
-
if (!isArrayIndexKey(key, input.length)) {
|
|
5811
|
-
throw new SignedObjectCanonicalizationError(
|
|
5812
|
-
`${path}.${key} is not allowed on a JSON array`
|
|
5813
|
-
);
|
|
5814
|
-
}
|
|
5815
|
-
const descriptor = Object.getOwnPropertyDescriptor(input, key);
|
|
5816
|
-
if (descriptor?.enumerable !== true) {
|
|
5817
|
-
throw new SignedObjectCanonicalizationError(
|
|
5818
|
-
`${path}[${key}] must be an enumerable JSON array item`
|
|
5819
|
-
);
|
|
5820
|
-
}
|
|
5821
|
-
if (!("value" in descriptor)) {
|
|
5822
|
-
throw new SignedObjectCanonicalizationError(
|
|
5823
|
-
`${path}[${key}] must be a JSON data property`
|
|
5824
|
-
);
|
|
5825
|
-
}
|
|
5826
|
-
}
|
|
5827
|
-
const output2 = [];
|
|
5828
|
-
for (let index = 0; index < input.length; index++) {
|
|
5829
|
-
if (!objectHasOwn(input, index)) {
|
|
5830
|
-
throw new SignedObjectCanonicalizationError(
|
|
5831
|
-
`${path}[${index}] must not be a sparse array hole`
|
|
5832
|
-
);
|
|
5833
|
-
}
|
|
5834
|
-
output2.push(normalizeJson(input[index], `${path}[${index}]`));
|
|
5835
|
-
}
|
|
5836
|
-
return output2;
|
|
5837
|
-
}
|
|
5838
|
-
const proto = Object.getPrototypeOf(input);
|
|
5839
|
-
if (proto !== Object.prototype && proto !== null) {
|
|
5840
|
-
throw new SignedObjectCanonicalizationError(
|
|
5841
|
-
`${path} must be a plain JSON object`
|
|
5842
|
-
);
|
|
5843
|
-
}
|
|
5844
|
-
const output = /* @__PURE__ */ Object.create(null);
|
|
5845
|
-
for (const key of Object.getOwnPropertyNames(input)) {
|
|
5846
|
-
assertUnicodeScalarString(key, `${path} key`);
|
|
5847
|
-
if (key === "__proto__" || key === "constructor") {
|
|
5848
|
-
throw new SignedObjectCanonicalizationError(
|
|
5849
|
-
`${path}.${key} is not allowed`
|
|
5850
|
-
);
|
|
5851
|
-
}
|
|
5852
|
-
const descriptor = Object.getOwnPropertyDescriptor(input, key);
|
|
5853
|
-
if (descriptor?.enumerable !== true) {
|
|
5854
|
-
throw new SignedObjectCanonicalizationError(
|
|
5855
|
-
`${path}.${key} must be an enumerable JSON object property`
|
|
5856
|
-
);
|
|
5857
|
-
}
|
|
5858
|
-
if (!("value" in descriptor)) {
|
|
5859
|
-
throw new SignedObjectCanonicalizationError(
|
|
5860
|
-
`${path}.${key} must be a JSON data property`
|
|
5861
|
-
);
|
|
5862
|
-
}
|
|
5863
|
-
const value = descriptor.value;
|
|
5864
|
-
output[key] = normalizeJson(value, `${path}.${key}`);
|
|
5865
|
-
}
|
|
5866
|
-
return output;
|
|
5867
|
-
}
|
|
5868
|
-
function assertNoSymbolKeys(input, path) {
|
|
5869
|
-
if (Object.getOwnPropertySymbols(input).length > 0) {
|
|
5870
|
-
throw new SignedObjectCanonicalizationError(
|
|
5871
|
-
`${path} must not have symbol properties`
|
|
5872
|
-
);
|
|
5873
|
-
}
|
|
5874
|
-
}
|
|
5875
|
-
function isArrayIndexKey(key, length2) {
|
|
5876
|
-
if (!/^(0|[1-9]\d*)$/.test(key)) {
|
|
5877
|
-
return false;
|
|
5878
|
-
}
|
|
5879
|
-
const index = Number(key);
|
|
5880
|
-
return Number.isSafeInteger(index) && index >= 0 && index < length2;
|
|
5881
|
-
}
|
|
5882
|
-
function serializeObject(value) {
|
|
5883
|
-
const keys = Object.keys(value).sort(compareUtf16CodeUnits);
|
|
5884
|
-
const parts = keys.map((key) => `${JSON.stringify(key)}:${serialize(value[key])}`);
|
|
5885
|
-
return `{${parts.join(",")}}`;
|
|
5886
|
-
}
|
|
5887
|
-
function compareUtf16CodeUnits(a, b) {
|
|
5888
|
-
const max = Math.min(a.length, b.length);
|
|
5889
|
-
for (let index = 0; index < max; index++) {
|
|
5890
|
-
const leftCodeUnit = a.charCodeAt(index);
|
|
5891
|
-
const rightCodeUnit = b.charCodeAt(index);
|
|
5892
|
-
if (leftCodeUnit !== rightCodeUnit) {
|
|
5893
|
-
return leftCodeUnit - rightCodeUnit;
|
|
5894
|
-
}
|
|
5895
|
-
}
|
|
5896
|
-
return a.length - b.length;
|
|
5897
|
-
}
|
|
5898
|
-
function assertUnicodeScalarString(value, path) {
|
|
5899
|
-
for (let index = 0; index < value.length; index++) {
|
|
5900
|
-
const code3 = value.charCodeAt(index);
|
|
5901
|
-
if (code3 >= 55296 && code3 <= 56319) {
|
|
5902
|
-
const next = value.charCodeAt(index + 1);
|
|
5903
|
-
if (Number.isNaN(next) || next < 56320 || next > 57343) {
|
|
5904
|
-
throw new SignedObjectCanonicalizationError(
|
|
5905
|
-
`${path} contains a lone high surrogate`
|
|
5906
|
-
);
|
|
5907
|
-
}
|
|
5908
|
-
index++;
|
|
5909
|
-
continue;
|
|
5910
|
-
}
|
|
5911
|
-
if (code3 >= 56320 && code3 <= 57343) {
|
|
5912
|
-
throw new SignedObjectCanonicalizationError(
|
|
5913
|
-
`${path} contains a lone low surrogate`
|
|
5914
|
-
);
|
|
5915
|
-
}
|
|
5916
|
-
}
|
|
5917
|
-
}
|
|
5918
|
-
|
|
5919
|
-
// src/policy/capability.ts
|
|
6349
|
+
import { ed25519 as ed255195 } from "@noble/curves/ed25519";
|
|
6350
|
+
import { bytesToHex, sha256 as sha2566, verifyMessage } from "viem";
|
|
5920
6351
|
var textEncoder2 = new TextEncoder();
|
|
5921
6352
|
var objectHasOwn2 = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
|
|
5922
6353
|
Object.prototype.hasOwnProperty
|
|
5923
6354
|
);
|
|
5924
|
-
var CEILING_SERVICES = /* @__PURE__ */ new Set(["tinycloud.kv", "tinycloud.sql", "tinycloud.vfs"]);
|
|
5925
|
-
var GRANTABLE_ACTIONS = /* @__PURE__ */ new Map();
|
|
5926
|
-
for (const entry of CAPABILITY_REGISTRY) {
|
|
5927
|
-
if (!CEILING_SERVICES.has(entry.service)) {
|
|
5928
|
-
continue;
|
|
5929
|
-
}
|
|
5930
|
-
if (entry.aliasOf !== void 0 || entry.implies !== void 0 || entry.urn.endsWith("/*")) {
|
|
5931
|
-
continue;
|
|
5932
|
-
}
|
|
5933
|
-
const existing = GRANTABLE_ACTIONS.get(entry.service);
|
|
5934
|
-
if (existing === void 0) {
|
|
5935
|
-
GRANTABLE_ACTIONS.set(entry.service, /* @__PURE__ */ new Set([entry.urn]));
|
|
5936
|
-
continue;
|
|
5937
|
-
}
|
|
5938
|
-
existing.add(entry.urn);
|
|
5939
|
-
}
|
|
5940
|
-
|
|
5941
|
-
// src/policy/signed-object.ts
|
|
5942
|
-
var textEncoder3 = new TextEncoder();
|
|
5943
|
-
var objectHasOwn3 = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
|
|
5944
|
-
Object.prototype.hasOwnProperty
|
|
5945
|
-
);
|
|
5946
6355
|
function canonicalizeSignedObjectUnsigned(input) {
|
|
5947
6356
|
return jcsCanonicalize(input);
|
|
5948
6357
|
}
|
|
@@ -6162,7 +6571,7 @@ function validateOwnerSharePolicyRegistration(value, expected) {
|
|
|
6162
6571
|
const publicKey = encodedKid.length === 34 ? encodedKid.slice(2) : encodedKid;
|
|
6163
6572
|
const signatureBytes = fromB64(proof.signature);
|
|
6164
6573
|
const signedBytes = new TextEncoder().encode(`${OWNER_SHARE_REGISTRATION_DOMAIN}${canonicalizeSignedObjectUnsigned(registrationCore)}`);
|
|
6165
|
-
if (signatureBytes.length !== 64 || !
|
|
6574
|
+
if (signatureBytes.length !== 64 || !ed255196.verify(signatureBytes, signedBytes, publicKey)) throw new Error("owner-share registration proof signature is invalid");
|
|
6166
6575
|
return { registration, proof };
|
|
6167
6576
|
}
|
|
6168
6577
|
function validateOwnerSharePolicyRegistrationBytes(bytesValue, expected) {
|
|
@@ -6176,7 +6585,7 @@ function validateOwnerSharePolicyRegistrationBytes(bytesValue, expected) {
|
|
|
6176
6585
|
}
|
|
6177
6586
|
|
|
6178
6587
|
// src/delegations/share-delivery.ts
|
|
6179
|
-
import { ed25519 as
|
|
6588
|
+
import { ed25519 as ed255197 } from "@noble/curves/ed25519";
|
|
6180
6589
|
var SHARE_DELIVERY_AUTHORIZATION_DOMAIN = "xyz.tinycloud.share/delivery-authorization/v2\0";
|
|
6181
6590
|
function isCanonicalHttpsOrigin(value) {
|
|
6182
6591
|
let url;
|
|
@@ -6249,7 +6658,7 @@ function validateShareDeliveryAuthorizationBytes(bytesValue, expected) {
|
|
|
6249
6658
|
const authorization = assertObject2(root.authorization, AUTHORIZATION_KEYS, "share delivery authorization");
|
|
6250
6659
|
const proof = assertObject2(root.proof, ["alg", "kid", "signature"], "share delivery authorization proof");
|
|
6251
6660
|
const request = expected.request;
|
|
6252
|
-
if (authorization.type !== "TinyCloudShareDeliveryAuthorization" || authorization.version !== 2 || authorization.dataAuthority !== false || authorization.jti !== request.jti || authorization.shareCid !== request.shareCid || authorization.shareId !== request.shareId || authorization.registrationCid !== request.registrationCid || authorization.delegationCid !== request.delegationCid || authorization.enforcementDelegationCid !== request.enforcementDelegationCid || authorization.envelopeCid !== request.envelopeCid || authorization.policyCid !== request.policyCid || authorization.deliveryEmail !== request.recipientEmail || authorization.shareUrl !== request.shareUrl || authorization.documentName !== request.documentName || authorization.requestBodyDigest !== request.requestBodyDigest || authorization.expiresAt !== request.expiresAt || authorization.idempotencyKey !== request.
|
|
6661
|
+
if (authorization.type !== "TinyCloudShareDeliveryAuthorization" || authorization.version !== 2 || authorization.dataAuthority !== false || authorization.jti !== request.jti || authorization.shareCid !== request.shareCid || authorization.shareId !== request.shareId || authorization.registrationCid !== request.registrationCid || authorization.delegationCid !== request.delegationCid || authorization.enforcementDelegationCid !== request.enforcementDelegationCid || authorization.envelopeCid !== request.envelopeCid || authorization.policyCid !== request.policyCid || authorization.deliveryEmail !== request.recipientEmail || authorization.shareUrl !== request.shareUrl || authorization.documentName !== request.documentName || authorization.requestBodyDigest !== request.requestBodyDigest || authorization.expiresAt !== request.expiresAt || authorization.idempotencyKey !== request.idempotencyKey || authorization.reportAbuseToken !== request.jti || authorization.authorityMaterialHandle !== request.registrationCid) {
|
|
6253
6662
|
throw new Error("share delivery authorization is not bound to the submitted request");
|
|
6254
6663
|
}
|
|
6255
6664
|
if (typeof authorization.issuedAt !== "string" || Date.parse(authorization.issuedAt) > Date.now() + 6e4) throw new Error("share delivery authorization issuedAt is invalid");
|
|
@@ -6264,7 +6673,7 @@ function validateShareDeliveryAuthorizationBytes(bytesValue, expected) {
|
|
|
6264
6673
|
if (publicKey.length !== 32) throw new Error("share delivery authorization proof key is invalid");
|
|
6265
6674
|
const signatureBytes = fromB642(proof.signature);
|
|
6266
6675
|
const signedBytes = new TextEncoder().encode(`${SHARE_DELIVERY_AUTHORIZATION_DOMAIN}${canonicalizeSignedObjectUnsigned(authorization)}`);
|
|
6267
|
-
if (signatureBytes.length !== 64 || !
|
|
6676
|
+
if (signatureBytes.length !== 64 || !ed255197.verify(signatureBytes, signedBytes, publicKey)) throw new Error("share delivery authorization proof signature is invalid");
|
|
6268
6677
|
return { authorization, proof };
|
|
6269
6678
|
}
|
|
6270
6679
|
function shareDeliveryTrustedKid(publicKey) {
|
|
@@ -6383,14 +6792,42 @@ var SenderShareStore = class {
|
|
|
6383
6792
|
await this.keys.delete(shareId);
|
|
6384
6793
|
}
|
|
6385
6794
|
};
|
|
6795
|
+
|
|
6796
|
+
// src/delegations/index.ts
|
|
6797
|
+
import {
|
|
6798
|
+
authorizeShare,
|
|
6799
|
+
authorizationMethodForTarget,
|
|
6800
|
+
notifyShare,
|
|
6801
|
+
revokeShare,
|
|
6802
|
+
listShares,
|
|
6803
|
+
showShare,
|
|
6804
|
+
publishTargetShare,
|
|
6805
|
+
publishPolicyShare,
|
|
6806
|
+
claimShare,
|
|
6807
|
+
resumeShareAuthorization,
|
|
6808
|
+
isLegacyShareLink,
|
|
6809
|
+
receiveLegacyShare,
|
|
6810
|
+
migrateShare,
|
|
6811
|
+
MemoryEncryptedShareHistoryStorage,
|
|
6812
|
+
EncryptedSenderShareHistory
|
|
6813
|
+
} from "@tinycloud/share-sdk";
|
|
6814
|
+
import {
|
|
6815
|
+
inspectShare,
|
|
6816
|
+
receiveShare,
|
|
6817
|
+
ShareReceiveError,
|
|
6818
|
+
toShareErrorInfo,
|
|
6819
|
+
verifyBearerEnvelope
|
|
6820
|
+
} from "@tinycloud/share-sdk";
|
|
6386
6821
|
export {
|
|
6387
6822
|
DelegationErrorCodes,
|
|
6388
6823
|
DelegationManager,
|
|
6389
6824
|
EncodedShareDataSchema,
|
|
6825
|
+
EncryptedSenderShareHistory,
|
|
6390
6826
|
MAX_CONTENT_BYTES,
|
|
6391
6827
|
MAX_SEALED_SHARE_CONTENT_BYTES,
|
|
6392
6828
|
MAX_SHARE_ARTIFACT_BYTES,
|
|
6393
6829
|
MAX_SHARE_CONTENT_BYTES,
|
|
6830
|
+
MemoryEncryptedShareHistoryStorage,
|
|
6394
6831
|
MemorySenderShareKeyStorage,
|
|
6395
6832
|
MemorySenderShareRecordStorage,
|
|
6396
6833
|
MemoryShareCache,
|
|
@@ -6405,6 +6842,7 @@ export {
|
|
|
6405
6842
|
ShareConflict,
|
|
6406
6843
|
ShareEnvelopeError,
|
|
6407
6844
|
ShareNativeResponseSchema,
|
|
6845
|
+
ShareReceiveError,
|
|
6408
6846
|
ShareRecipientClient,
|
|
6409
6847
|
ShareRecipientClientOptionsSchema,
|
|
6410
6848
|
ShareRecipientPolicySchema,
|
|
@@ -6412,7 +6850,10 @@ export {
|
|
|
6412
6850
|
ShareResourceSchema,
|
|
6413
6851
|
SharingService,
|
|
6414
6852
|
SharingServiceConfigSchema,
|
|
6853
|
+
authorizationMethodForTarget,
|
|
6854
|
+
authorizeShare,
|
|
6415
6855
|
canonicalOwnerSharePolicy,
|
|
6856
|
+
claimShare,
|
|
6416
6857
|
computeOwnerShareRegistrationCid,
|
|
6417
6858
|
computeShareCid,
|
|
6418
6859
|
createDelegatedShareKey,
|
|
@@ -6422,28 +6863,46 @@ export {
|
|
|
6422
6863
|
createSharePolicy,
|
|
6423
6864
|
createSharingService,
|
|
6424
6865
|
decryptShareBytesAsync,
|
|
6866
|
+
delegatePortablePolicySession,
|
|
6425
6867
|
encodeInlineShareUrl,
|
|
6426
6868
|
encodeShareArtifact,
|
|
6427
6869
|
encodeShareUrl,
|
|
6428
6870
|
encryptShareBytes,
|
|
6429
6871
|
encryptShareBytesAsync,
|
|
6872
|
+
importPortableDelegation,
|
|
6873
|
+
inspectShare,
|
|
6430
6874
|
intersectShareCapabilities,
|
|
6875
|
+
isLegacyShareLink,
|
|
6431
6876
|
isV2ShareLink,
|
|
6877
|
+
listShares,
|
|
6878
|
+
migrateShare,
|
|
6432
6879
|
normalizeShareActions,
|
|
6433
6880
|
normalizeShareRecipientTarget,
|
|
6434
6881
|
normalizeShareResource,
|
|
6882
|
+
notifyShare,
|
|
6883
|
+
parsePortableDelegation,
|
|
6435
6884
|
parseShareArtifact,
|
|
6436
6885
|
parseShareUrl,
|
|
6886
|
+
publishPolicyShare,
|
|
6887
|
+
publishTargetShare,
|
|
6888
|
+
receiveLegacyShare,
|
|
6889
|
+
receiveShare,
|
|
6437
6890
|
restoreDelegatedShareKey,
|
|
6891
|
+
resumeShareAuthorization,
|
|
6892
|
+
revokeShare,
|
|
6893
|
+
serializePortableDelegation,
|
|
6438
6894
|
shareCapabilityAllows,
|
|
6439
6895
|
shareDeliveryTrustedKid,
|
|
6896
|
+
showShare,
|
|
6440
6897
|
signShareEnvelope,
|
|
6898
|
+
toShareErrorInfo,
|
|
6441
6899
|
validateEncodedShareData,
|
|
6442
6900
|
validateOwnerSharePolicyRegistration,
|
|
6443
6901
|
validateOwnerSharePolicyRegistrationBytes,
|
|
6444
6902
|
validateReceiveOptions,
|
|
6445
6903
|
validateShareDeliveryAuthorizationBytes,
|
|
6446
6904
|
validateSharingServiceConfig,
|
|
6905
|
+
verifyBearerEnvelope,
|
|
6447
6906
|
verifyShareCid,
|
|
6448
6907
|
verifyShareEnvelope
|
|
6449
6908
|
};
|