@tinycloud/sdk-core 2.11.0-beta.9 → 2.11.1-beta.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.
Files changed (32) hide show
  1. package/dist/{capability-BA49Uboq.d.cts → capability-BjzXwtNw.d.cts} +1 -1
  2. package/dist/{capability-BA49Uboq.d.ts → capability-BjzXwtNw.d.ts} +1 -1
  3. package/dist/credential-admission-C_cO1QqB.d.cts +781 -0
  4. package/dist/credential-admission-cvHe-HUC.d.ts +781 -0
  5. package/dist/delegations/index.cjs +620 -221
  6. package/dist/delegations/index.cjs.map +1 -1
  7. package/dist/delegations/index.d.cts +32 -32
  8. package/dist/delegations/index.d.ts +32 -32
  9. package/dist/delegations/index.js +622 -223
  10. package/dist/delegations/index.js.map +1 -1
  11. package/dist/index.cjs +3162 -1255
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +348 -18
  14. package/dist/index.d.ts +348 -18
  15. package/dist/index.js +3959 -2050
  16. package/dist/index.js.map +1 -1
  17. package/dist/policy/index.cjs +1273 -175
  18. package/dist/policy/index.cjs.map +1 -1
  19. package/dist/policy/index.d.cts +5 -4
  20. package/dist/policy/index.d.ts +5 -4
  21. package/dist/policy/index.js +1274 -176
  22. package/dist/policy/index.js.map +1 -1
  23. package/dist/{recipient-types.schema-D5pDlIqn.d.cts → recipient-types.schema-G8NEKRoo.d.cts} +240 -183
  24. package/dist/{recipient-types.schema-D5pDlIqn.d.ts → recipient-types.schema-G8NEKRoo.d.ts} +240 -183
  25. package/dist/requester/index.cjs.map +1 -1
  26. package/dist/requester/index.d.cts +1 -1
  27. package/dist/requester/index.d.ts +1 -1
  28. package/dist/requester/index.js +1 -1
  29. package/dist/requester/index.js.map +1 -1
  30. package/package.json +5 -5
  31. package/dist/signed-object-B3dMzh8O.d.ts +0 -149
  32. package/dist/signed-object-DwPZl6kV.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",
@@ -2676,12 +2681,12 @@ var bases = { ...identity_exports, ...base2_exports, ...base8_exports, ...base10
2676
2681
  var hashes = { ...sha2_browser_exports, ...identity_exports2 };
2677
2682
 
2678
2683
  // src/delegations/SharingService.ts
2679
- var import_ed255193 = require("@noble/curves/ed25519");
2684
+ var import_ed255194 = require("@noble/curves/ed25519");
2680
2685
 
2681
2686
  // src/delegations/ShareRecipientClient.ts
2682
2687
  var import_sdk_services2 = require("@tinycloud/sdk-services");
2683
- var import_ed255192 = require("@noble/curves/ed25519");
2684
- var import_sha2563 = require("@noble/hashes/sha256");
2688
+ var import_ed255193 = require("@noble/curves/ed25519");
2689
+ var import_sha2564 = require("@noble/hashes/sha256");
2685
2690
 
2686
2691
  // src/delegations/share-envelope.ts
2687
2692
  var import_ed25519 = require("@noble/curves/ed25519");
@@ -3772,6 +3777,506 @@ var ShareNativeResponseSchema = import_zod3.z.discriminatedUnion("action", [
3772
3777
  }).strict()
3773
3778
  ]);
3774
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 atob === "function" ? atob(normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "=")) : Buffer.from(normalized, "base64").toString("binary");
4173
+ const bytes2 = Uint8Array.from(binary, (character) => character.charCodeAt(0));
4174
+ const encoded = typeof btoa === "function" ? btoa(String.fromCharCode(...bytes2)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_") : Buffer.from(bytes2).toString("base64url");
4175
+ if (encoded !== value) throw new Error("value is not canonical base64url");
4176
+ return bytes2;
4177
+ }
4178
+ function encodeBase64Url(value) {
4179
+ return typeof btoa === "function" ? btoa(String.fromCharCode(...value)).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_") : Buffer.from(value).toString("base64url");
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
+
3775
4280
  // src/delegations/ShareRecipientClient.ts
3776
4281
  var DEFAULT_MAX_ARTIFACT_BYTES2 = MAX_SHARE_ARTIFACT_BYTES;
3777
4282
  var DEFAULT_MAX_CONTENT_BYTES = MAX_SHARE_CONTENT_BYTES;
@@ -3847,7 +4352,7 @@ function randomJti() {
3847
4352
  return bytesToBase64Url2(bytes2);
3848
4353
  }
3849
4354
  function digestCanonical(value) {
3850
- return bytesToBase64Url2((0, import_sha2563.sha256)(new TextEncoder().encode(canonicalJsonForProof(value))));
4355
+ return bytesToBase64Url2((0, import_sha2564.sha256)(new TextEncoder().encode(canonicalJsonForProof(value))));
3851
4356
  }
3852
4357
  function actionWire(action) {
3853
4358
  return action === "get" ? "tinycloud.kv/get" : action === "metadata" ? "tinycloud.kv/metadata" : action === "list" ? "tinycloud.kv/list" : "tinycloud.kv/put";
@@ -3959,9 +4464,31 @@ var ShareRecipientClient = class {
3959
4464
  if (policy && this.options.bearerSession !== void 0) throw new ShareAccessError("SHARE_POLICY_BEARER_MISMATCH");
3960
4465
  if (bearer && this.options.presentation !== void 0) throw new ShareAccessError("SHARE_BEARER_PRESENTATION_MISMATCH");
3961
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;
3962
- const kv = bearer || legacyBearer ? session === void 0 ? void 0 : this.createKV(envelope.origin, session) : void 0;
3963
4467
  const policySession = policy ? session : void 0;
3964
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;
3965
4492
  const advertisedCapability = { spaceId: envelope.spaceId, resource: envelope.resource, actions: envelope.actions };
3966
4493
  const capability = policySession?.capability === void 0 ? advertisedCapability : intersectShareCapabilities(advertisedCapability, policySession.capability);
3967
4494
  if (capability === void 0) throw new ShareAccessError("SHARE_CAPABILITY_EMPTY");
@@ -3986,6 +4513,11 @@ var ShareRecipientClient = class {
3986
4513
  const scope = normalizePath(input.path ?? envelope.resource.path);
3987
4514
  this.assertAllowed(capability, "list", scope);
3988
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
+ }
3989
4521
  if (policySession !== void 0) return this.nativeList(envelope, policySession, scope, input.limit, input.cursor);
3990
4522
  const result = await kv.list({ path: scope, limit: input.limit, cursor: input.cursor });
3991
4523
  if (!result.ok) throw result.error;
@@ -3999,6 +4531,14 @@ var ShareRecipientClient = class {
3999
4531
  const resolvedPath = normalizePath(path);
4000
4532
  this.assertAllowed(capability, "save", resolvedPath);
4001
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
+ }
4002
4542
  if (policySession !== void 0) return this.nativeSave(envelope, policySession, resolvedPath, bytes2, input);
4003
4543
  const result = await kv.put(resolvedPath, bytes2, { contentType: input.contentType ?? envelope.content.mimeType, ifMatch: input.etag });
4004
4544
  if (!result.ok) {
@@ -4014,22 +4554,79 @@ var ShareRecipientClient = class {
4014
4554
  const metadata = async (path = envelope.resource.kind === "exact" ? envelope.resource.path : "") => {
4015
4555
  const resolvedPath = normalizePath(path);
4016
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
+ }
4017
4562
  if (policySession !== void 0) return this.nativeMetadata(envelope, policySession, resolvedPath);
4018
4563
  if (kv === void 0) throw new ShareAccessError("SHARE_SESSION_REQUIRED");
4019
4564
  const result = await kv.head(resolvedPath);
4020
4565
  if (!result.ok) throw result.error;
4021
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 };
4022
4567
  };
4023
- 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 };
4024
4569
  } catch (error) {
4025
4570
  throw asError(error);
4026
4571
  }
4027
4572
  }
4028
- createKV(origin, session) {
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 marker = parentResource.indexOf("/kv/");
4592
+ if (marker < 1) return false;
4593
+ const parentPath = parentResource.slice(marker + 4);
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) => resource.indexOf("/kv/") > 0);
4620
+ const marker = kvResource?.indexOf("/kv/") ?? -1;
4621
+ if (kvResource === void 0 || marker < 1) throw new ShareAccessError("SHARE_SESSION_INVALID");
4622
+ return { spaceId: kvResource.slice(0, marker) };
4623
+ }
4624
+ createKV(origin, session, invokeOverride) {
4625
+ const invoke = invokeOverride ?? this.options.invoke ?? nativeInvoke;
4029
4626
  if (this.options.createKVService !== void 0) {
4030
- return this.options.createKVService({ hosts: [origin], session, invoke: this.options.invoke ?? nativeInvoke, fetch: this.fetchFn });
4627
+ return this.options.createKVService({ hosts: [origin], session, invoke, fetch: this.fetchFn });
4031
4628
  }
4032
- const context = new import_sdk_services2.ServiceContext({ hosts: [origin], session, invoke: this.options.invoke ?? nativeInvoke, fetch: this.fetchFn });
4629
+ const context = new import_sdk_services2.ServiceContext({ hosts: [origin], session, invoke, fetch: this.fetchFn });
4033
4630
  const service = new import_sdk_services2.KVService({ prefix: "" });
4034
4631
  context.registerService("kv", service);
4035
4632
  service.initialize(context);
@@ -4072,7 +4669,7 @@ var ShareRecipientClient = class {
4072
4669
  if (bytes2.byteLength > (this.options.maxContentBytes ?? DEFAULT_MAX_CONTENT_BYTES)) throw new ShareAccessError("SHARE_TOO_LARGE");
4073
4670
  const contentType = input.contentType ?? envelope.content.mimeType;
4074
4671
  if (contentType !== envelope.content.mimeType && !/^text\/(?:plain|markdown)(?:;|$)/i.test(contentType)) throw new ShareAccessError("SHARE_CONTENT_TYPE_INVALID");
4075
- const result = await this.invokeNative({ envelope, session, action: "put", resource: path, body: bytes2, bodyDigest: bytesToBase64Url2((0, import_sha2563.sha256)(bytes2)), contentType, ifMatch: input.etag, mediaType: "application/vnd.tinycloud.share+json" });
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" });
4076
4673
  if (result.status === 412 || result.status === 409) throw new ShareConflict(path, result.headers?.etag);
4077
4674
  if (result.status === 401 || result.status === 403) throw new ShareAccessError("SHARE_DENIED");
4078
4675
  if (result.status < 200 || result.status >= 300) throw new ShareAccessError("SHARE_WRITE_FAILED");
@@ -4194,7 +4791,7 @@ var ShareRecipientClient = class {
4194
4791
  };
4195
4792
  const signed = this.options.signNativeInvoke === void 0 ? void 0 : await this.options.signNativeInvoke({ envelope: input.envelope, session: input.session, request: body });
4196
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;
4197
- const response = await this.fetchFn(v2 ? `${base3}/share/v2/invoke` : `${base3}/invoke`, {
4794
+ const response = await this.fetchFn(`${base3}/invoke`, {
4198
4795
  method: "POST",
4199
4796
  headers: { ...headersRecord(transport), ...headersRecord(signed), "content-type": input.mediaType, accept: input.mediaType },
4200
4797
  body: JSON.stringify(body),
@@ -4318,7 +4915,7 @@ var ShareRecipientClient = class {
4318
4915
  }]);
4319
4916
  }
4320
4917
  digestMatches(value, bytes2) {
4321
- const digest4 = bytesToBase64Url2((0, import_sha2563.sha256)(bytes2));
4918
+ const digest4 = bytesToBase64Url2((0, import_sha2564.sha256)(bytes2));
4322
4919
  return value === digest4 || value === `sha-256=:${digest4}:`;
4323
4920
  }
4324
4921
  assertNativeRequestBounds(envelope, session, operation, path, limit, cursor) {
@@ -4536,7 +5133,7 @@ var ShareRecipientClient = class {
4536
5133
  nodeAudience: binding.nodeAudience,
4537
5134
  ...isV2 ? {
4538
5135
  enforcerDid: challenge.enforcerDid,
4539
- credentialDigest: typeof presentation.credentialDigest === "string" ? presentation.credentialDigest : bytesToBase64Url2((0, import_sha2563.sha256)(new TextEncoder().encode(credential)))
5136
+ credentialDigest: typeof presentation.credentialDigest === "string" ? presentation.credentialDigest : bytesToBase64Url2((0, import_sha2564.sha256)(new TextEncoder().encode(credential)))
4540
5137
  } : {},
4541
5138
  action,
4542
5139
  ...binding.actions === void 0 ? {} : { actions: [...binding.actions] },
@@ -4602,7 +5199,7 @@ var ShareRecipientClient = class {
4602
5199
  }
4603
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");
4604
5201
  const bytes2 = new TextEncoder().encode(`${domain}${canonicalJsonForProof(message)}`);
4605
- if (!import_ed255192.ed25519.verify(signature, bytes2, key)) throw new ShareAccessError("SHARE_SESSION_INVALID", "Node proof signature is invalid");
5202
+ if (!import_ed255193.ed25519.verify(signature, bytes2, key)) throw new ShareAccessError("SHARE_SESSION_INVALID", "Node proof signature is invalid");
4606
5203
  }
4607
5204
  assertChallengeRequestBinding(request, challenge) {
4608
5205
  const source = isRecord(request.body) ? request.body : request;
@@ -5806,7 +6403,7 @@ function shareKeyMatchesDid(key, didUrl) {
5806
6403
  if (!publicKey) return false;
5807
6404
  const jwkBytes = decodeBase64UrlBytes(key.x);
5808
6405
  const privateKey = decodeBase64UrlBytes(key.d);
5809
- const derivedPublicKey = import_ed255193.ed25519.getPublicKey(privateKey);
6406
+ const derivedPublicKey = import_ed255194.ed25519.getPublicKey(privateKey);
5810
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]);
5811
6408
  } catch {
5812
6409
  return false;
@@ -5856,210 +6453,12 @@ function verifySignedChild(result, expected, computeCid) {
5856
6453
  }
5857
6454
 
5858
6455
  // src/delegations/owner-policy.ts
5859
- var import_ed255195 = require("@noble/curves/ed25519");
5860
- var import_sha2564 = require("@noble/hashes/sha256");
6456
+ var import_ed255196 = require("@noble/curves/ed25519");
6457
+ var import_sha2565 = require("@noble/hashes/sha256");
5861
6458
 
5862
6459
  // src/policy/signed-object.ts
5863
- var import_ed255194 = require("@noble/curves/ed25519");
6460
+ var import_ed255195 = require("@noble/curves/ed25519");
5864
6461
  var import_viem2 = require("viem");
5865
-
5866
- // src/policy/errors.ts
5867
- var SignedObjectProfileError = class extends Error {
5868
- constructor(code3, message) {
5869
- super(message);
5870
- this.name = "SignedObjectProfileError";
5871
- this.code = code3;
5872
- }
5873
- };
5874
- var SignedObjectCanonicalizationError = class extends SignedObjectProfileError {
5875
- constructor(message) {
5876
- super("canonicalization-mismatch", message);
5877
- this.name = "SignedObjectCanonicalizationError";
5878
- }
5879
- };
5880
-
5881
- // src/policy/jcs.ts
5882
- var objectHasOwn = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
5883
- Object.prototype.hasOwnProperty
5884
- );
5885
- function jcsCanonicalize(input) {
5886
- return serialize(normalizeJson(input, "$"));
5887
- }
5888
- function normalizeJson(input, path = "$") {
5889
- if (input === null) {
5890
- return null;
5891
- }
5892
- switch (typeof input) {
5893
- case "boolean":
5894
- return input;
5895
- case "number":
5896
- if (!Number.isFinite(input)) {
5897
- throw new SignedObjectCanonicalizationError(
5898
- `${path} must be a finite JSON number`
5899
- );
5900
- }
5901
- return input;
5902
- case "string":
5903
- assertUnicodeScalarString(input, path);
5904
- return input;
5905
- case "object":
5906
- return normalizeJsonObjectOrArray(input, path);
5907
- case "bigint":
5908
- case "function":
5909
- case "symbol":
5910
- case "undefined":
5911
- default:
5912
- throw new SignedObjectCanonicalizationError(
5913
- `${path} is not a JSON value`
5914
- );
5915
- }
5916
- }
5917
- function serialize(value) {
5918
- if (value === null) {
5919
- return "null";
5920
- }
5921
- switch (typeof value) {
5922
- case "boolean":
5923
- return value ? "true" : "false";
5924
- case "number": {
5925
- const encoded = JSON.stringify(value);
5926
- if (encoded === void 0) {
5927
- throw new SignedObjectCanonicalizationError(
5928
- "number could not be serialized as JSON"
5929
- );
5930
- }
5931
- return encoded;
5932
- }
5933
- case "string":
5934
- return JSON.stringify(value);
5935
- case "object":
5936
- if (Array.isArray(value)) {
5937
- return `[${value.map((item) => serialize(item)).join(",")}]`;
5938
- }
5939
- return serializeObject(value);
5940
- default:
5941
- throw new SignedObjectCanonicalizationError(
5942
- `unsupported JSON value type ${typeof value}`
5943
- );
5944
- }
5945
- }
5946
- function normalizeJsonObjectOrArray(input, path) {
5947
- assertNoSymbolKeys(input, path);
5948
- if (Array.isArray(input)) {
5949
- for (const key of Object.getOwnPropertyNames(input)) {
5950
- if (key === "length") {
5951
- continue;
5952
- }
5953
- if (!isArrayIndexKey(key, input.length)) {
5954
- throw new SignedObjectCanonicalizationError(
5955
- `${path}.${key} is not allowed on a JSON array`
5956
- );
5957
- }
5958
- const descriptor = Object.getOwnPropertyDescriptor(input, key);
5959
- if (descriptor?.enumerable !== true) {
5960
- throw new SignedObjectCanonicalizationError(
5961
- `${path}[${key}] must be an enumerable JSON array item`
5962
- );
5963
- }
5964
- if (!("value" in descriptor)) {
5965
- throw new SignedObjectCanonicalizationError(
5966
- `${path}[${key}] must be a JSON data property`
5967
- );
5968
- }
5969
- }
5970
- const output2 = [];
5971
- for (let index = 0; index < input.length; index++) {
5972
- if (!objectHasOwn(input, index)) {
5973
- throw new SignedObjectCanonicalizationError(
5974
- `${path}[${index}] must not be a sparse array hole`
5975
- );
5976
- }
5977
- output2.push(normalizeJson(input[index], `${path}[${index}]`));
5978
- }
5979
- return output2;
5980
- }
5981
- const proto = Object.getPrototypeOf(input);
5982
- if (proto !== Object.prototype && proto !== null) {
5983
- throw new SignedObjectCanonicalizationError(
5984
- `${path} must be a plain JSON object`
5985
- );
5986
- }
5987
- const output = /* @__PURE__ */ Object.create(null);
5988
- for (const key of Object.getOwnPropertyNames(input)) {
5989
- assertUnicodeScalarString(key, `${path} key`);
5990
- if (key === "__proto__" || key === "constructor") {
5991
- throw new SignedObjectCanonicalizationError(
5992
- `${path}.${key} is not allowed`
5993
- );
5994
- }
5995
- const descriptor = Object.getOwnPropertyDescriptor(input, key);
5996
- if (descriptor?.enumerable !== true) {
5997
- throw new SignedObjectCanonicalizationError(
5998
- `${path}.${key} must be an enumerable JSON object property`
5999
- );
6000
- }
6001
- if (!("value" in descriptor)) {
6002
- throw new SignedObjectCanonicalizationError(
6003
- `${path}.${key} must be a JSON data property`
6004
- );
6005
- }
6006
- const value = descriptor.value;
6007
- output[key] = normalizeJson(value, `${path}.${key}`);
6008
- }
6009
- return output;
6010
- }
6011
- function assertNoSymbolKeys(input, path) {
6012
- if (Object.getOwnPropertySymbols(input).length > 0) {
6013
- throw new SignedObjectCanonicalizationError(
6014
- `${path} must not have symbol properties`
6015
- );
6016
- }
6017
- }
6018
- function isArrayIndexKey(key, length2) {
6019
- if (!/^(0|[1-9]\d*)$/.test(key)) {
6020
- return false;
6021
- }
6022
- const index = Number(key);
6023
- return Number.isSafeInteger(index) && index >= 0 && index < length2;
6024
- }
6025
- function serializeObject(value) {
6026
- const keys = Object.keys(value).sort(compareUtf16CodeUnits);
6027
- const parts = keys.map((key) => `${JSON.stringify(key)}:${serialize(value[key])}`);
6028
- return `{${parts.join(",")}}`;
6029
- }
6030
- function compareUtf16CodeUnits(a, b) {
6031
- const max = Math.min(a.length, b.length);
6032
- for (let index = 0; index < max; index++) {
6033
- const leftCodeUnit = a.charCodeAt(index);
6034
- const rightCodeUnit = b.charCodeAt(index);
6035
- if (leftCodeUnit !== rightCodeUnit) {
6036
- return leftCodeUnit - rightCodeUnit;
6037
- }
6038
- }
6039
- return a.length - b.length;
6040
- }
6041
- function assertUnicodeScalarString(value, path) {
6042
- for (let index = 0; index < value.length; index++) {
6043
- const code3 = value.charCodeAt(index);
6044
- if (code3 >= 55296 && code3 <= 56319) {
6045
- const next = value.charCodeAt(index + 1);
6046
- if (Number.isNaN(next) || next < 56320 || next > 57343) {
6047
- throw new SignedObjectCanonicalizationError(
6048
- `${path} contains a lone high surrogate`
6049
- );
6050
- }
6051
- index++;
6052
- continue;
6053
- }
6054
- if (code3 >= 56320 && code3 <= 57343) {
6055
- throw new SignedObjectCanonicalizationError(
6056
- `${path} contains a lone low surrogate`
6057
- );
6058
- }
6059
- }
6060
- }
6061
-
6062
- // src/policy/signed-object.ts
6063
6462
  var textEncoder2 = new TextEncoder();
6064
6463
  var objectHasOwn2 = Object.hasOwn ?? Object.prototype.hasOwnProperty.call.bind(
6065
6464
  Object.prototype.hasOwnProperty
@@ -6095,10 +6494,10 @@ function fromB64(value) {
6095
6494
  throw new Error("base64url decoding is unavailable");
6096
6495
  }
6097
6496
  function cid(bytesValue) {
6098
- return CID.createV1(code, create(sha256.code, (0, import_sha2564.sha256)(bytesValue))).toString(base32.encoder);
6497
+ return CID.createV1(code, create(sha256.code, (0, import_sha2565.sha256)(bytesValue))).toString(base32.encoder);
6099
6498
  }
6100
6499
  function digest3(bytesValue) {
6101
- return b64((0, import_sha2564.sha256)(bytesValue));
6500
+ return b64((0, import_sha2565.sha256)(bytesValue));
6102
6501
  }
6103
6502
  function didKeyFromEd25519PublicKey(publicKey) {
6104
6503
  if (publicKey.length !== 32) throw new Error("share key public key must be 32 bytes");
@@ -6283,7 +6682,7 @@ function validateOwnerSharePolicyRegistration(value, expected) {
6283
6682
  const publicKey = encodedKid.length === 34 ? encodedKid.slice(2) : encodedKid;
6284
6683
  const signatureBytes = fromB64(proof.signature);
6285
6684
  const signedBytes = new TextEncoder().encode(`${OWNER_SHARE_REGISTRATION_DOMAIN}${canonicalizeSignedObjectUnsigned(registrationCore)}`);
6286
- if (signatureBytes.length !== 64 || !import_ed255195.ed25519.verify(signatureBytes, signedBytes, publicKey)) throw new Error("owner-share registration proof signature is invalid");
6685
+ if (signatureBytes.length !== 64 || !import_ed255196.ed25519.verify(signatureBytes, signedBytes, publicKey)) throw new Error("owner-share registration proof signature is invalid");
6287
6686
  return { registration, proof };
6288
6687
  }
6289
6688
  function validateOwnerSharePolicyRegistrationBytes(bytesValue, expected) {
@@ -6297,7 +6696,7 @@ function validateOwnerSharePolicyRegistrationBytes(bytesValue, expected) {
6297
6696
  }
6298
6697
 
6299
6698
  // src/delegations/share-delivery.ts
6300
- var import_ed255196 = require("@noble/curves/ed25519");
6699
+ var import_ed255197 = require("@noble/curves/ed25519");
6301
6700
  var SHARE_DELIVERY_AUTHORIZATION_DOMAIN = "xyz.tinycloud.share/delivery-authorization/v2\0";
6302
6701
  function isCanonicalHttpsOrigin(value) {
6303
6702
  let url;
@@ -6385,7 +6784,7 @@ function validateShareDeliveryAuthorizationBytes(bytesValue, expected) {
6385
6784
  if (publicKey.length !== 32) throw new Error("share delivery authorization proof key is invalid");
6386
6785
  const signatureBytes = fromB642(proof.signature);
6387
6786
  const signedBytes = new TextEncoder().encode(`${SHARE_DELIVERY_AUTHORIZATION_DOMAIN}${canonicalizeSignedObjectUnsigned(authorization)}`);
6388
- if (signatureBytes.length !== 64 || !import_ed255196.ed25519.verify(signatureBytes, signedBytes, publicKey)) throw new Error("share delivery authorization proof signature is invalid");
6787
+ if (signatureBytes.length !== 64 || !import_ed255197.ed25519.verify(signatureBytes, signedBytes, publicKey)) throw new Error("share delivery authorization proof signature is invalid");
6389
6788
  return { authorization, proof };
6390
6789
  }
6391
6790
  function shareDeliveryTrustedKid(publicKey) {