@tinycloud/share-sdk 1.4.0 → 1.4.1-beta.1
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/{addressed-publish-BP6nsgRq.d.cts → addressed-publish-BcvisG4a.d.cts} +7 -0
- package/dist/{addressed-publish-CpkwV-Au.d.ts → addressed-publish-CwTTn9Jn.d.ts} +7 -0
- package/dist/artifact.cjs +27 -4
- package/dist/artifact.cjs.map +1 -1
- package/dist/artifact.js +27 -4
- package/dist/artifact.js.map +1 -1
- package/dist/index.cjs +283 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +283 -13
- package/dist/index.js.map +1 -1
- package/dist/share-index.cjs +27 -4
- package/dist/share-index.cjs.map +1 -1
- package/dist/share-index.js +27 -4
- package/dist/share-index.js.map +1 -1
- package/dist/share-root.cjs +27 -4
- package/dist/share-root.cjs.map +1 -1
- package/dist/share-root.d.cts +1 -1
- package/dist/share-root.d.ts +1 -1
- package/dist/share-root.js +27 -4
- package/dist/share-root.js.map +1 -1
- package/dist/{web-recipient-entry-DVyTQBl0.d.ts → web-recipient-entry-CPntAP0H.d.ts} +46 -5
- package/dist/{web-recipient-entry-CiUzdSQs.d.cts → web-recipient-entry-Cy1fXl_5.d.cts} +46 -5
- package/dist/web-recipient.cjs +258 -11
- package/dist/web-recipient.cjs.map +1 -1
- package/dist/web-recipient.d.cts +1 -1
- package/dist/web-recipient.d.ts +1 -1
- package/dist/web-recipient.js +258 -11
- package/dist/web-recipient.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { ShareEnvelopeV2, ShareEnvelopeV3 } from '@tinycloud/share-envelope';
|
|
2
|
+
import { c as ShareAuthorizationAdapter, f as ShareAuthorizedContent, a as ShareAuthorizationMethod } from './authorization-CmP1skO8.js';
|
|
3
3
|
|
|
4
4
|
type ShareErrorCode = "invalid-link" | "fetch-failed" | "max-bytes-exceeded" | "cid-mismatch" | "decrypt-failed" | "envelope-invalid" | "origin-mismatch" | "signature-invalid" | "capability-invalid" | "expired" | "unsupported-target" | "authorization-denied" | "content-integrity-failed";
|
|
5
5
|
declare const SHARE_RESULT_VERSION: 1;
|
|
@@ -42,7 +42,19 @@ interface ShareFetchOptions {
|
|
|
42
42
|
readonly now?: () => number;
|
|
43
43
|
readonly maxSealedBlobBytes?: number;
|
|
44
44
|
readonly maxContentBlobBytes?: number;
|
|
45
|
-
readonly onResolvedAddressedEnvelope?: (envelope: ShareEnvelopeV3, cid: string) => void;
|
|
45
|
+
readonly onResolvedAddressedEnvelope?: (envelope: ShareEnvelopeV2 | ShareEnvelopeV3, cid: string) => void;
|
|
46
|
+
/** Legacy V2 registry transport; used only for existing compact V2 links. */
|
|
47
|
+
readonly registryBaseUrl?: string;
|
|
48
|
+
readonly fetchBlob?: (input: {
|
|
49
|
+
readonly origin: string;
|
|
50
|
+
readonly cid: string;
|
|
51
|
+
readonly signal?: AbortSignal;
|
|
52
|
+
}) => Promise<Uint8Array>;
|
|
53
|
+
readonly trustedSignerDid?: string;
|
|
54
|
+
readonly trustedPolicyAuthority?: SharePolicyAuthority;
|
|
55
|
+
readonly authorization?: ShareAuthorizationAdapter<ShareAuthorizedContent>;
|
|
56
|
+
readonly authorizationResumeToken?: string;
|
|
57
|
+
readonly authorizationProof?: unknown;
|
|
46
58
|
}
|
|
47
59
|
interface ShareMetadata {
|
|
48
60
|
readonly protocol: "tinycloud-share";
|
|
@@ -77,8 +89,37 @@ interface ShareInspection {
|
|
|
77
89
|
readonly link: {
|
|
78
90
|
readonly origin: string;
|
|
79
91
|
readonly cid: string;
|
|
80
|
-
readonly kind: "policy";
|
|
92
|
+
readonly kind: "policy" | "compact";
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
interface SharePolicyEvidence {
|
|
96
|
+
readonly policyCid: string;
|
|
97
|
+
readonly signerDid: string;
|
|
98
|
+
readonly registrationCid: string;
|
|
99
|
+
readonly shareId: string;
|
|
100
|
+
readonly recipientMatcher: unknown;
|
|
101
|
+
readonly target: {
|
|
102
|
+
readonly origin: string;
|
|
103
|
+
readonly nodeAudience: string;
|
|
104
|
+
readonly spaceId: string;
|
|
81
105
|
};
|
|
106
|
+
readonly resource: {
|
|
107
|
+
readonly kind: "exact" | "prefix";
|
|
108
|
+
readonly path: string;
|
|
109
|
+
};
|
|
110
|
+
readonly actions: readonly string[];
|
|
111
|
+
readonly contentSource: unknown;
|
|
112
|
+
readonly contentSourceDigest: string;
|
|
113
|
+
readonly delegationCid: string;
|
|
114
|
+
readonly authorityMaterialHandle: string;
|
|
115
|
+
readonly authorityMaterialDigest: string;
|
|
116
|
+
readonly expiresAt: string;
|
|
117
|
+
}
|
|
118
|
+
interface SharePolicyAuthority {
|
|
119
|
+
resolve(input: {
|
|
120
|
+
readonly policyCid: string;
|
|
121
|
+
readonly envelope: ShareEnvelopeV2;
|
|
122
|
+
}): Promise<SharePolicyEvidence | undefined>;
|
|
82
123
|
}
|
|
83
124
|
interface ShareReceiveAuthorizationRequired {
|
|
84
125
|
readonly state: "authorization-required";
|
|
@@ -211,4 +252,4 @@ declare function createAddressedAuthorization(input: Omit<ShareRecipientClientOp
|
|
|
211
252
|
}) => Promise<SharePresentationMaterial>;
|
|
212
253
|
}): ShareAuthorizationAdapter<ShareAuthorizedContent>;
|
|
213
254
|
|
|
214
|
-
export { DEFAULT_MAX_CONTENT_BLOB_BYTES as D, SHARE_RESULT_VERSION as S, DEFAULT_MAX_SEALED_BLOB_BYTES as a, type ShareErrorCode as b, type ShareErrorInfo as c, type ShareFetchOptions as d, type ShareInspection as e, type ShareMetadata as f, type ShareNodeTrust as g, type
|
|
255
|
+
export { DEFAULT_MAX_CONTENT_BLOB_BYTES as D, SHARE_RESULT_VERSION as S, DEFAULT_MAX_SEALED_BLOB_BYTES as a, type ShareErrorCode as b, type ShareErrorInfo as c, type ShareFetchOptions as d, type ShareInspection as e, type ShareMetadata as f, type ShareNodeTrust as g, type SharePolicyAuthority as h, type SharePolicyChallenge as i, type SharePolicyDelegationLink as j, type SharePolicyEvidence as k, type SharePolicySession as l, type SharePresentationMaterial as m, type ShareReceiveAuthorizationRequired as n, ShareReceiveError as o, type ShareReceiveOutcome as p, type ShareReceiveResult as q, ShareRecipientClient as r, type ShareRecipientClientOptions as s, createAddressedAuthorization as t, inspectShare as u, receiveShare as v, toShareErrorInfo as w };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { ShareEnvelopeV2, ShareEnvelopeV3 } from '@tinycloud/share-envelope';
|
|
2
|
+
import { c as ShareAuthorizationAdapter, f as ShareAuthorizedContent, a as ShareAuthorizationMethod } from './authorization-CmP1skO8.cjs';
|
|
3
3
|
|
|
4
4
|
type ShareErrorCode = "invalid-link" | "fetch-failed" | "max-bytes-exceeded" | "cid-mismatch" | "decrypt-failed" | "envelope-invalid" | "origin-mismatch" | "signature-invalid" | "capability-invalid" | "expired" | "unsupported-target" | "authorization-denied" | "content-integrity-failed";
|
|
5
5
|
declare const SHARE_RESULT_VERSION: 1;
|
|
@@ -42,7 +42,19 @@ interface ShareFetchOptions {
|
|
|
42
42
|
readonly now?: () => number;
|
|
43
43
|
readonly maxSealedBlobBytes?: number;
|
|
44
44
|
readonly maxContentBlobBytes?: number;
|
|
45
|
-
readonly onResolvedAddressedEnvelope?: (envelope: ShareEnvelopeV3, cid: string) => void;
|
|
45
|
+
readonly onResolvedAddressedEnvelope?: (envelope: ShareEnvelopeV2 | ShareEnvelopeV3, cid: string) => void;
|
|
46
|
+
/** Legacy V2 registry transport; used only for existing compact V2 links. */
|
|
47
|
+
readonly registryBaseUrl?: string;
|
|
48
|
+
readonly fetchBlob?: (input: {
|
|
49
|
+
readonly origin: string;
|
|
50
|
+
readonly cid: string;
|
|
51
|
+
readonly signal?: AbortSignal;
|
|
52
|
+
}) => Promise<Uint8Array>;
|
|
53
|
+
readonly trustedSignerDid?: string;
|
|
54
|
+
readonly trustedPolicyAuthority?: SharePolicyAuthority;
|
|
55
|
+
readonly authorization?: ShareAuthorizationAdapter<ShareAuthorizedContent>;
|
|
56
|
+
readonly authorizationResumeToken?: string;
|
|
57
|
+
readonly authorizationProof?: unknown;
|
|
46
58
|
}
|
|
47
59
|
interface ShareMetadata {
|
|
48
60
|
readonly protocol: "tinycloud-share";
|
|
@@ -77,8 +89,37 @@ interface ShareInspection {
|
|
|
77
89
|
readonly link: {
|
|
78
90
|
readonly origin: string;
|
|
79
91
|
readonly cid: string;
|
|
80
|
-
readonly kind: "policy";
|
|
92
|
+
readonly kind: "policy" | "compact";
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
interface SharePolicyEvidence {
|
|
96
|
+
readonly policyCid: string;
|
|
97
|
+
readonly signerDid: string;
|
|
98
|
+
readonly registrationCid: string;
|
|
99
|
+
readonly shareId: string;
|
|
100
|
+
readonly recipientMatcher: unknown;
|
|
101
|
+
readonly target: {
|
|
102
|
+
readonly origin: string;
|
|
103
|
+
readonly nodeAudience: string;
|
|
104
|
+
readonly spaceId: string;
|
|
81
105
|
};
|
|
106
|
+
readonly resource: {
|
|
107
|
+
readonly kind: "exact" | "prefix";
|
|
108
|
+
readonly path: string;
|
|
109
|
+
};
|
|
110
|
+
readonly actions: readonly string[];
|
|
111
|
+
readonly contentSource: unknown;
|
|
112
|
+
readonly contentSourceDigest: string;
|
|
113
|
+
readonly delegationCid: string;
|
|
114
|
+
readonly authorityMaterialHandle: string;
|
|
115
|
+
readonly authorityMaterialDigest: string;
|
|
116
|
+
readonly expiresAt: string;
|
|
117
|
+
}
|
|
118
|
+
interface SharePolicyAuthority {
|
|
119
|
+
resolve(input: {
|
|
120
|
+
readonly policyCid: string;
|
|
121
|
+
readonly envelope: ShareEnvelopeV2;
|
|
122
|
+
}): Promise<SharePolicyEvidence | undefined>;
|
|
82
123
|
}
|
|
83
124
|
interface ShareReceiveAuthorizationRequired {
|
|
84
125
|
readonly state: "authorization-required";
|
|
@@ -211,4 +252,4 @@ declare function createAddressedAuthorization(input: Omit<ShareRecipientClientOp
|
|
|
211
252
|
}) => Promise<SharePresentationMaterial>;
|
|
212
253
|
}): ShareAuthorizationAdapter<ShareAuthorizedContent>;
|
|
213
254
|
|
|
214
|
-
export { DEFAULT_MAX_CONTENT_BLOB_BYTES as D, SHARE_RESULT_VERSION as S, DEFAULT_MAX_SEALED_BLOB_BYTES as a, type ShareErrorCode as b, type ShareErrorInfo as c, type ShareFetchOptions as d, type ShareInspection as e, type ShareMetadata as f, type ShareNodeTrust as g, type
|
|
255
|
+
export { DEFAULT_MAX_CONTENT_BLOB_BYTES as D, SHARE_RESULT_VERSION as S, DEFAULT_MAX_SEALED_BLOB_BYTES as a, type ShareErrorCode as b, type ShareErrorInfo as c, type ShareFetchOptions as d, type ShareInspection as e, type ShareMetadata as f, type ShareNodeTrust as g, type SharePolicyAuthority as h, type SharePolicyChallenge as i, type SharePolicyDelegationLink as j, type SharePolicyEvidence as k, type SharePolicySession as l, type SharePresentationMaterial as m, type ShareReceiveAuthorizationRequired as n, ShareReceiveError as o, type ShareReceiveOutcome as p, type ShareReceiveResult as q, ShareRecipientClient as r, type ShareRecipientClientOptions as s, createAddressedAuthorization as t, inspectShare as u, receiveShare as v, toShareErrorInfo as w };
|
package/dist/web-recipient.cjs
CHANGED
|
@@ -5256,6 +5256,23 @@ var unifiedEncryptionNetworkSchema = external_exports.string().refine((value) =>
|
|
|
5256
5256
|
const network = separator < 0 ? "" : rest.slice(separator + 1);
|
|
5257
5257
|
return owner.startsWith("did:") && owner.length > 4 && network.length > 0 && !/[:/%?#\s]/.test(network);
|
|
5258
5258
|
}, { message: "expected canonical TinyCloud encryption network" });
|
|
5259
|
+
var unifiedEncryptionResourceSchema = external_exports.string().refine((value) => {
|
|
5260
|
+
const prefix = "urn:tinycloud:encryption:";
|
|
5261
|
+
if (!value.startsWith(prefix)) return false;
|
|
5262
|
+
const match = /^(did:.+):([^/:?#\s]+)(?:\/(.+))?$/.exec(value.slice(prefix.length));
|
|
5263
|
+
if (match === null) return false;
|
|
5264
|
+
const path = match[3];
|
|
5265
|
+
return path === void 0 || path.split("/").every(
|
|
5266
|
+
(segment) => segment.length > 0 && segment !== "." && segment !== ".." && !/[\\:%?#\s]/.test(segment)
|
|
5267
|
+
);
|
|
5268
|
+
}, { message: "expected a canonical TinyCloud encryption resource" });
|
|
5269
|
+
var unifiedEncryptionKeyPathSchema = external_exports.string().regex(/^share\/[^/]+$/).refine(
|
|
5270
|
+
(value) => {
|
|
5271
|
+
const segment = value.slice("share/".length);
|
|
5272
|
+
return segment !== "." && segment !== ".." && !/[\\:%?#\s]/.test(segment);
|
|
5273
|
+
},
|
|
5274
|
+
{ message: "expected an exact share key path" }
|
|
5275
|
+
);
|
|
5259
5276
|
var unifiedKvCapabilitySchema = external_exports.object({
|
|
5260
5277
|
kind: external_exports.literal("kv"),
|
|
5261
5278
|
resource: unifiedResourceSchema,
|
|
@@ -5269,7 +5286,7 @@ var unifiedKvCapabilitySchema = external_exports.object({
|
|
|
5269
5286
|
}).strict();
|
|
5270
5287
|
var unifiedEncryptionCapabilitySchema = external_exports.object({
|
|
5271
5288
|
kind: external_exports.literal("encryption"),
|
|
5272
|
-
resource:
|
|
5289
|
+
resource: unifiedEncryptionResourceSchema,
|
|
5273
5290
|
action: external_exports.literal("tinycloud.encryption/decrypt")
|
|
5274
5291
|
}).strict();
|
|
5275
5292
|
var unifiedCapabilitySchema = external_exports.union([unifiedKvCapabilitySchema, unifiedEncryptionCapabilitySchema]);
|
|
@@ -5278,6 +5295,7 @@ var unifiedContentSourceSchema = external_exports.object({
|
|
|
5278
5295
|
kvResource: unifiedResourceSchema,
|
|
5279
5296
|
selector: external_exports.union([external_exports.literal("exact"), external_exports.literal("prefix")]),
|
|
5280
5297
|
encryptionNetwork: unifiedEncryptionNetworkSchema,
|
|
5298
|
+
encryptionKeyPath: unifiedEncryptionKeyPathSchema.optional(),
|
|
5281
5299
|
encryptedSymmetricKeyDigestHex: external_exports.string().regex(/^[0-9a-f]{64}$/),
|
|
5282
5300
|
keyVersion: external_exports.number().int().positive(),
|
|
5283
5301
|
mode: external_exports.union([external_exports.literal("mutable"), external_exports.literal("immutable")]),
|
|
@@ -5395,22 +5413,71 @@ function validateV3Invariants(value, ctx) {
|
|
|
5395
5413
|
if (value.attestedEnforcerBinding.nodeAudience !== value.target.nodeAudience || value.attestedEnforcerBinding.signature.signerDid !== value.attestedEnforcerBinding.nodeAudience || Date.parse(value.attestedEnforcerBinding.expiresAt) < Date.parse(value.expiry)) {
|
|
5396
5414
|
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["attestedEnforcerBinding"], message: "enforcer binding does not cover the target and share lifetime" });
|
|
5397
5415
|
}
|
|
5398
|
-
|
|
5416
|
+
const encryptionKeyPath = value.contentSource.encryptionKeyPath;
|
|
5417
|
+
if (encryptionKeyPath !== void 0 && encryptionKeyPath !== `share/${value.contentSource.shareId}`) {
|
|
5418
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["contentSource", "encryptionKeyPath"], message: "share key path must name this share" });
|
|
5419
|
+
}
|
|
5420
|
+
if (value.policy.contentSource.shareId !== value.contentSource.shareId || value.policy.contentSource.kvResource !== value.contentSource.kvResource || value.policy.contentSource.selector !== value.contentSource.selector || value.policy.contentSource.encryptionNetwork !== value.encryptionNetwork || value.policy.contentSource.encryptionKeyPath !== encryptionKeyPath || value.policy.contentSource.encryptedSymmetricKeyDigestHex !== value.contentSource.encryptedSymmetricKeyDigestHex || value.policy.contentSource.keyVersion !== value.contentSource.keyVersion || value.policy.contentSource.mode !== value.contentSource.mode || value.policy.contentSource.initialCiphertextDigestHex !== value.contentSource.initialCiphertextDigestHex) {
|
|
5399
5421
|
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["contentSource"], message: "content source is not bound to policy" });
|
|
5400
5422
|
}
|
|
5401
5423
|
if (value.policy.signature.suite !== "Ed25519" || value.policy.signature.signerDid !== value.policy.ownerDid) {
|
|
5402
5424
|
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["policy", "signature"], message: "policy must be signed by its owner" });
|
|
5403
5425
|
}
|
|
5404
5426
|
const kvCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "kv");
|
|
5405
|
-
const
|
|
5427
|
+
const expectedEncryptionResource = encryptionKeyPath === void 0 ? value.encryptionNetwork : `${value.encryptionNetwork}/${encryptionKeyPath}`;
|
|
5428
|
+
const decryptCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "encryption" && capability.resource === expectedEncryptionResource && capability.action === "tinycloud.encryption/decrypt");
|
|
5406
5429
|
if (value.policy.capabilityCeiling.length !== 2 || kvCapabilities.length !== 1 || decryptCapabilities.length !== 1 || kvCapabilities[0]?.resource !== value.contentSource.kvResource || kvCapabilities[0]?.selector !== value.contentSource.selector) {
|
|
5407
|
-
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["policy", "capabilityCeiling"], message: "policy ceiling must contain exact decrypt
|
|
5430
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["policy", "capabilityCeiling"], message: "policy ceiling must contain the exact decrypt resource" });
|
|
5408
5431
|
}
|
|
5409
5432
|
}
|
|
5410
5433
|
var unsignedShareEnvelopeV3Schema = unsignedShareEnvelopeV3BaseSchema.superRefine(validateV3Invariants);
|
|
5411
5434
|
var shareEnvelopeV3Schema = unsignedShareEnvelopeV3BaseSchema.extend({ signature: signatureSchema }).strict().superRefine(validateV3Invariants);
|
|
5412
5435
|
var ENVELOPE_AAD_LABEL = "tinycloud-share-envelope-v1";
|
|
5436
|
+
var SEALED_BLOB_VERSION = 1;
|
|
5413
5437
|
var AAD = utf8Bytes(ENVELOPE_AAD_LABEL);
|
|
5438
|
+
var KEY_LENGTH = 32;
|
|
5439
|
+
var NONCE_LENGTH = 12;
|
|
5440
|
+
var TAG_LENGTH = 16;
|
|
5441
|
+
var HEADER_LENGTH = 1;
|
|
5442
|
+
function assertKey(key32) {
|
|
5443
|
+
if (key32.length !== KEY_LENGTH) {
|
|
5444
|
+
throw new TypeError(`key must be ${KEY_LENGTH} bytes, got ${key32.length}`);
|
|
5445
|
+
}
|
|
5446
|
+
}
|
|
5447
|
+
async function importAesKey(key32, usage) {
|
|
5448
|
+
assertKey(key32);
|
|
5449
|
+
return globalThis.crypto.subtle.importKey(
|
|
5450
|
+
"raw",
|
|
5451
|
+
key32,
|
|
5452
|
+
"AES-GCM",
|
|
5453
|
+
false,
|
|
5454
|
+
[usage]
|
|
5455
|
+
);
|
|
5456
|
+
}
|
|
5457
|
+
async function open(blob, key32) {
|
|
5458
|
+
if (blob.length < HEADER_LENGTH + NONCE_LENGTH + TAG_LENGTH) {
|
|
5459
|
+
throw new TypeError(`sealed blob too short: ${blob.length} bytes`);
|
|
5460
|
+
}
|
|
5461
|
+
if (blob[0] !== SEALED_BLOB_VERSION) {
|
|
5462
|
+
throw new TypeError(`unknown sealed blob version: ${blob[0]}`);
|
|
5463
|
+
}
|
|
5464
|
+
const nonce = blob.subarray(HEADER_LENGTH, HEADER_LENGTH + NONCE_LENGTH);
|
|
5465
|
+
const ciphertext = blob.subarray(HEADER_LENGTH + NONCE_LENGTH);
|
|
5466
|
+
return decryptEnvelope(nonce, ciphertext, key32);
|
|
5467
|
+
}
|
|
5468
|
+
async function decryptEnvelope(nonce, ciphertext, key32) {
|
|
5469
|
+
if (nonce.length !== NONCE_LENGTH) {
|
|
5470
|
+
throw new TypeError(`nonce must be ${NONCE_LENGTH} bytes, got ${nonce.length}`);
|
|
5471
|
+
}
|
|
5472
|
+
const key = await importAesKey(key32, "decrypt");
|
|
5473
|
+
return new Uint8Array(
|
|
5474
|
+
await globalThis.crypto.subtle.decrypt(
|
|
5475
|
+
{ name: "AES-GCM", iv: nonce, additionalData: AAD },
|
|
5476
|
+
key,
|
|
5477
|
+
ciphertext
|
|
5478
|
+
)
|
|
5479
|
+
);
|
|
5480
|
+
}
|
|
5414
5481
|
function isPlainRecord(value) {
|
|
5415
5482
|
const proto = Object.getPrototypeOf(value);
|
|
5416
5483
|
return proto === Object.prototype || proto === null;
|
|
@@ -5541,6 +5608,7 @@ function equal(left, right) {
|
|
|
5541
5608
|
return left.length === right.length && left.every((byte, index) => byte === right[index]);
|
|
5542
5609
|
}
|
|
5543
5610
|
var ED25519_VERIFY_OPTS2 = { zip215: false };
|
|
5611
|
+
var ENVELOPE_V2_SIGNATURE_DOMAIN = "xyz.tinycloud.share/envelope/v2\0";
|
|
5544
5612
|
var ENVELOPE_V3_SIGNATURE_DOMAIN = "xyz.tinycloud.share/envelope/v3\0";
|
|
5545
5613
|
var POLICY_V1_SIGNATURE_DOMAIN = "xyz.tinycloud.policy/policy/v1\0";
|
|
5546
5614
|
var POLICY_V2_SIGNATURE_DOMAIN = "xyz.tinycloud.policy/policy/v2\0";
|
|
@@ -5548,6 +5616,14 @@ var CONTENT_SOURCE_V1_DOMAIN = "xyz.tinycloud.policy/ContentSource/v1\0";
|
|
|
5548
5616
|
var POLICY_CAPABILITY_V1_DOMAIN = "xyz.tinycloud.policy/PolicyCapability/v1\0";
|
|
5549
5617
|
var NATIVE_PROJECTION_V1_DOMAIN = "xyz.tinycloud.policy/NativeProjection/v1\0";
|
|
5550
5618
|
var ATTESTED_ENFORCER_V2_DOMAIN = "xyz.tinycloud.policy/AttestedEnforcerBinding/v2\0";
|
|
5619
|
+
function signingBytesV2(unsigned) {
|
|
5620
|
+
const domain = utf8Bytes(ENVELOPE_V2_SIGNATURE_DOMAIN);
|
|
5621
|
+
const body = utf8Bytes(canonicalize(unsigned));
|
|
5622
|
+
const bytes = new Uint8Array(domain.length + body.length);
|
|
5623
|
+
bytes.set(domain);
|
|
5624
|
+
bytes.set(body, domain.length);
|
|
5625
|
+
return bytes;
|
|
5626
|
+
}
|
|
5551
5627
|
function signingBytesV3(unsigned) {
|
|
5552
5628
|
const domain = utf8Bytes(ENVELOPE_V3_SIGNATURE_DOMAIN);
|
|
5553
5629
|
const body = utf8Bytes(canonicalize(unsigned));
|
|
@@ -5556,6 +5632,17 @@ function signingBytesV3(unsigned) {
|
|
|
5556
5632
|
bytes.set(body, domain.length);
|
|
5557
5633
|
return bytes;
|
|
5558
5634
|
}
|
|
5635
|
+
function verifyEnvelopeV2SignatureOnly(envelope) {
|
|
5636
|
+
const parsed = shareEnvelopeV2Schema.parse(envelope);
|
|
5637
|
+
const { signature, ...unsigned } = parsed;
|
|
5638
|
+
return import_ed255193.ed25519.verify(fromBase64Url(signature.value), signingBytesV2(unsigned), ed25519PublicKeyFromDidKey(signature.signerDid), ED25519_VERIFY_OPTS2);
|
|
5639
|
+
}
|
|
5640
|
+
async function verifyEnvelopeV2(envelope, options) {
|
|
5641
|
+
const parsed = shareEnvelopeV2Schema.parse(envelope);
|
|
5642
|
+
if (parsed.signature.signerDid !== options.expectedSignerDid || !verifyEnvelopeV2SignatureOnly(parsed)) return false;
|
|
5643
|
+
if (parsed.authorizationTarget.kind === "policy") return await computeCid(fromBase64Url(parsed.authorizationTarget.policyBytes)) === parsed.authorizationTarget.policyCid;
|
|
5644
|
+
return true;
|
|
5645
|
+
}
|
|
5559
5646
|
function verifyEnvelopeV3SignatureOnly(envelope) {
|
|
5560
5647
|
const parsed = shareEnvelopeV3Schema.parse(envelope);
|
|
5561
5648
|
const { signature, ...unsigned } = parsed;
|
|
@@ -5642,6 +5729,52 @@ function base32Lower(bytes) {
|
|
|
5642
5729
|
if (bits > 0) output += alphabet[buffer << 5 - bits & 31];
|
|
5643
5730
|
return output;
|
|
5644
5731
|
}
|
|
5732
|
+
var KEY_LENGTH2 = 32;
|
|
5733
|
+
function assertCanonicalCid(cidString) {
|
|
5734
|
+
const cid = CID.parse(cidString);
|
|
5735
|
+
if (cid.version !== 1 || cid.code !== code || cid.multihash.code !== 18 || // sha2-256 (0x12) only, at the link layer too
|
|
5736
|
+
cid.toString() !== cidString) {
|
|
5737
|
+
throw new TypeError(`not a canonical CIDv1 raw sha2-256 base32 CID: ${cidString}`);
|
|
5738
|
+
}
|
|
5739
|
+
}
|
|
5740
|
+
function parseShareUrl(url, options = {}) {
|
|
5741
|
+
const parsed = new URL(url);
|
|
5742
|
+
if (parsed.protocol !== "https:") {
|
|
5743
|
+
throw new TypeError(`share URL must be https, got ${parsed.protocol}`);
|
|
5744
|
+
}
|
|
5745
|
+
if (parsed.username !== "" || parsed.password !== "") {
|
|
5746
|
+
throw new TypeError("share URL must not carry userinfo");
|
|
5747
|
+
}
|
|
5748
|
+
if (parsed.search !== "") {
|
|
5749
|
+
throw new TypeError("share URL must not have a query string");
|
|
5750
|
+
}
|
|
5751
|
+
if (options.expectedOrigin !== void 0) {
|
|
5752
|
+
if (!isCanonicalHttpsOrigin(options.expectedOrigin)) {
|
|
5753
|
+
throw new TypeError(
|
|
5754
|
+
`expectedOrigin must be a canonical https origin, got ${options.expectedOrigin}`
|
|
5755
|
+
);
|
|
5756
|
+
}
|
|
5757
|
+
if (parsed.origin !== options.expectedOrigin) {
|
|
5758
|
+
throw new TypeError(
|
|
5759
|
+
`share URL origin ${parsed.origin} does not match expected ${options.expectedOrigin}`
|
|
5760
|
+
);
|
|
5761
|
+
}
|
|
5762
|
+
}
|
|
5763
|
+
const match = /^\/s\/([a-z2-7]+)$/.exec(parsed.pathname);
|
|
5764
|
+
if (!match || match[1] === void 0) {
|
|
5765
|
+
throw new TypeError(`not a share URL path: ${parsed.pathname}`);
|
|
5766
|
+
}
|
|
5767
|
+
const ciphertextCid = match[1];
|
|
5768
|
+
assertCanonicalCid(ciphertextCid);
|
|
5769
|
+
if (!parsed.hash.startsWith("#k=")) {
|
|
5770
|
+
throw new TypeError("share URL is missing the #k= key fragment");
|
|
5771
|
+
}
|
|
5772
|
+
const key32 = fromBase64Url(parsed.hash.slice("#k=".length));
|
|
5773
|
+
if (key32.length !== KEY_LENGTH2) {
|
|
5774
|
+
throw new TypeError(`fragment key must be ${KEY_LENGTH2} bytes, got ${key32.length}`);
|
|
5775
|
+
}
|
|
5776
|
+
return { ciphertextCid, key32 };
|
|
5777
|
+
}
|
|
5645
5778
|
|
|
5646
5779
|
// src/artifact-core.ts
|
|
5647
5780
|
var ARTIFACT_ROOT = "artifacts";
|
|
@@ -5738,7 +5871,7 @@ var ShareReceiveError = class extends Error {
|
|
|
5738
5871
|
}
|
|
5739
5872
|
};
|
|
5740
5873
|
function metadataFor(envelope, origin) {
|
|
5741
|
-
const kind = envelope.recipientMatcher.kind === "recipientDid" ? "recipientDid" : envelope.recipientMatcher.kind === "exactEmail" ? "email" : "emailDomain";
|
|
5874
|
+
const kind = envelope.recipientMatcher.kind === "recipientDid" ? "recipientDid" : envelope.recipientMatcher.kind === "exactEmail" ? "email" : envelope.recipientMatcher.kind === "emailDomain" ? "emailDomain" : "bearer";
|
|
5742
5875
|
return {
|
|
5743
5876
|
protocol: "tinycloud-share",
|
|
5744
5877
|
version: 1,
|
|
@@ -5753,7 +5886,7 @@ function metadataFor(envelope, origin) {
|
|
|
5753
5886
|
...envelope.display.filename === void 0 ? {} : { filename: envelope.display.filename },
|
|
5754
5887
|
...envelope.display.mode === void 0 ? {} : { mode: envelope.display.mode }
|
|
5755
5888
|
},
|
|
5756
|
-
...envelope.
|
|
5889
|
+
...envelope.version === 3 && envelope.artifactPin !== void 0 ? { artifact: { id: envelope.artifactPin.artifactId, version: envelope.artifactPin.version } } : {}
|
|
5757
5890
|
};
|
|
5758
5891
|
}
|
|
5759
5892
|
function receiveErrorFor(error) {
|
|
@@ -5851,10 +5984,123 @@ async function resolvePolicyShare(link, options) {
|
|
|
5851
5984
|
options.onResolvedAddressedEnvelope?.(envelope, cid);
|
|
5852
5985
|
return { envelope, origin: url.origin, cid };
|
|
5853
5986
|
}
|
|
5987
|
+
async function resolveLegacyV2(link, options) {
|
|
5988
|
+
let parsed;
|
|
5989
|
+
try {
|
|
5990
|
+
parsed = parseShareUrl(link, { ...options.expectedOrigin === void 0 ? {} : { expectedOrigin: options.expectedOrigin } });
|
|
5991
|
+
} catch {
|
|
5992
|
+
throw new ShareReceiveError("invalid-link", "legacy share link format is invalid");
|
|
5993
|
+
}
|
|
5994
|
+
try {
|
|
5995
|
+
options.signal?.throwIfAborted();
|
|
5996
|
+
const origin = new URL(link).origin;
|
|
5997
|
+
const limit = options.maxSealedBlobBytes ?? DEFAULT_MAX_SEALED_BLOB_BYTES;
|
|
5998
|
+
if (!Number.isSafeInteger(limit) || limit <= 0) throw new ShareReceiveError("max-bytes-exceeded", "sealed envelope limit is invalid");
|
|
5999
|
+
let sealed;
|
|
6000
|
+
if (options.fetchBlob !== void 0) {
|
|
6001
|
+
try {
|
|
6002
|
+
sealed = await options.fetchBlob({ origin, cid: parsed.ciphertextCid, ...options.signal === void 0 ? {} : { signal: options.signal } });
|
|
6003
|
+
} catch {
|
|
6004
|
+
throw new ShareReceiveError("fetch-failed", "legacy registry unavailable");
|
|
6005
|
+
}
|
|
6006
|
+
} else {
|
|
6007
|
+
if (options.registryBaseUrl === void 0) throw new ShareReceiveError("fetch-failed", "legacy registry is required");
|
|
6008
|
+
const response = await (options.fetch ?? globalThis.fetch)(`${options.registryBaseUrl.replace(/\/+$/, "")}/ipfs/${parsed.ciphertextCid}?format=raw`, {
|
|
6009
|
+
headers: { accept: "application/vnd.ipld.raw" },
|
|
6010
|
+
redirect: "error",
|
|
6011
|
+
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
6012
|
+
});
|
|
6013
|
+
if (!response.ok) throw new ShareReceiveError("fetch-failed", "legacy registry unavailable");
|
|
6014
|
+
if (Number(response.headers.get("content-length")) > limit) throw new ShareReceiveError("max-bytes-exceeded", "sealed envelope exceeds the size limit");
|
|
6015
|
+
const reader = response.body?.getReader();
|
|
6016
|
+
if (reader === void 0) throw new ShareReceiveError("fetch-failed", "legacy registry returned no body");
|
|
6017
|
+
const chunks = [];
|
|
6018
|
+
let length2 = 0;
|
|
6019
|
+
for (; ; ) {
|
|
6020
|
+
const part = await reader.read();
|
|
6021
|
+
if (part.done) break;
|
|
6022
|
+
length2 += part.value.length;
|
|
6023
|
+
if (length2 > limit) {
|
|
6024
|
+
await reader.cancel();
|
|
6025
|
+
throw new ShareReceiveError("max-bytes-exceeded", "sealed envelope exceeds the size limit");
|
|
6026
|
+
}
|
|
6027
|
+
chunks.push(part.value);
|
|
6028
|
+
}
|
|
6029
|
+
sealed = new Uint8Array(length2);
|
|
6030
|
+
let offset = 0;
|
|
6031
|
+
for (const chunk of chunks) {
|
|
6032
|
+
sealed.set(chunk, offset);
|
|
6033
|
+
offset += chunk.length;
|
|
6034
|
+
}
|
|
6035
|
+
}
|
|
6036
|
+
options.signal?.throwIfAborted();
|
|
6037
|
+
if (!(sealed instanceof Uint8Array) || sealed.length > limit) throw new ShareReceiveError("max-bytes-exceeded", "sealed envelope exceeds the size limit");
|
|
6038
|
+
if (await computeCid(sealed) !== parsed.ciphertextCid) throw new ShareReceiveError("cid-mismatch", "legacy envelope CID does not match");
|
|
6039
|
+
let plaintext;
|
|
6040
|
+
try {
|
|
6041
|
+
plaintext = await open(sealed, parsed.key32);
|
|
6042
|
+
} catch {
|
|
6043
|
+
throw new ShareReceiveError("decrypt-failed", "legacy envelope could not be opened");
|
|
6044
|
+
}
|
|
6045
|
+
let envelope;
|
|
6046
|
+
try {
|
|
6047
|
+
const encoded = new TextDecoder("utf-8", { fatal: true }).decode(plaintext);
|
|
6048
|
+
const value = JSON.parse(encoded);
|
|
6049
|
+
if (canonicalize(value) !== encoded) throw new Error("non-canonical envelope");
|
|
6050
|
+
envelope = shareEnvelopeV2Schema.parse(value);
|
|
6051
|
+
} catch {
|
|
6052
|
+
throw new ShareReceiveError("envelope-invalid", "legacy envelope is invalid");
|
|
6053
|
+
}
|
|
6054
|
+
return { envelope, origin, cid: parsed.ciphertextCid };
|
|
6055
|
+
} finally {
|
|
6056
|
+
parsed.key32.fill(0);
|
|
6057
|
+
}
|
|
6058
|
+
}
|
|
6059
|
+
function evidenceMatchesV2(envelope, evidence) {
|
|
6060
|
+
const actions = new Set(evidence.actions.map((action) => action === "read" ? "tinycloud.kv/get" : action === "list" ? "tinycloud.kv/list" : action === "edit" ? "tinycloud.kv/put" : action));
|
|
6061
|
+
const resourceCovers = evidence.resource.kind === "exact" ? envelope.resource.kind === "exact" && evidence.resource.path === envelope.resource.path : envelope.resource.path === evidence.resource.path || envelope.resource.path.startsWith(evidence.resource.path.endsWith("/") ? evidence.resource.path : `${evidence.resource.path}/`);
|
|
6062
|
+
return envelope.authorizationTarget.kind === "policy" && evidence.policyCid === envelope.authorizationTarget.policyCid && evidence.signerDid === envelope.signature.signerDid && evidence.registrationCid.length > 0 && evidence.shareId === envelope.shareId && canonicalize(evidence.recipientMatcher) === canonicalize(envelope.recipientMatcher) && canonicalize(evidence.target) === canonicalize(envelope.target) && resourceCovers && envelope.actions.every((action) => actions.has(action === "read" ? "tinycloud.kv/get" : action === "list" ? "tinycloud.kv/list" : "tinycloud.kv/put")) && canonicalize(evidence.contentSource) === canonicalize(envelope.contentSource) && evidence.contentSourceDigest === envelope.contentSourceDigest && evidence.delegationCid === envelope.delegationCid && evidence.authorityMaterialHandle === envelope.authorityMaterialHandle && evidence.authorityMaterialDigest === envelope.authorityMaterialDigest && evidence.expiresAt === envelope.expiry && Number.isFinite(Date.parse(evidence.expiresAt)) && Date.parse(evidence.expiresAt) === Date.parse(envelope.expiry);
|
|
6063
|
+
}
|
|
6064
|
+
async function verifyLegacyV2(envelope, options) {
|
|
6065
|
+
try {
|
|
6066
|
+
if (!await verifyEnvelopeV2(envelope, { expectedSignerDid: envelope.signature.signerDid })) throw new Error("signature");
|
|
6067
|
+
} catch {
|
|
6068
|
+
throw new ShareReceiveError("signature-invalid", "legacy envelope signature is invalid");
|
|
6069
|
+
}
|
|
6070
|
+
const expiry = Date.parse(envelope.expiry);
|
|
6071
|
+
if (!Number.isFinite(expiry)) throw new ShareReceiveError("envelope-invalid", "legacy share expiry is invalid");
|
|
6072
|
+
if (expiry <= (options.now?.() ?? Date.now())) throw new ShareReceiveError("expired", "legacy share has expired", { expiresAt: envelope.expiry });
|
|
6073
|
+
if (envelope.authorizationTarget.kind === "policy") {
|
|
6074
|
+
if (options.trustedPolicyAuthority === void 0) throw new ShareReceiveError("envelope-invalid", "a legacy policy authority is required");
|
|
6075
|
+
let evidence;
|
|
6076
|
+
try {
|
|
6077
|
+
evidence = await options.trustedPolicyAuthority.resolve({ policyCid: envelope.authorizationTarget.policyCid, envelope });
|
|
6078
|
+
} catch {
|
|
6079
|
+
}
|
|
6080
|
+
if (evidence === void 0 || !evidenceMatchesV2(envelope, evidence)) throw new ShareReceiveError("capability-invalid", "legacy policy evidence does not match");
|
|
6081
|
+
if (options.trustedSignerDid !== void 0 && options.trustedSignerDid !== evidence.signerDid) throw new ShareReceiveError("signature-invalid", "legacy signer is not trusted");
|
|
6082
|
+
} else if (options.trustedSignerDid === void 0 || options.trustedSignerDid !== envelope.signature.signerDid || envelope.authorizationTarget.kind === "recipientDid" && envelope.recipientMatcher.kind === "recipientDid" && envelope.authorizationTarget.did !== envelope.recipientMatcher.value) {
|
|
6083
|
+
throw new ShareReceiveError("capability-invalid", "legacy recipient authority does not match");
|
|
6084
|
+
}
|
|
6085
|
+
}
|
|
5854
6086
|
async function inspectShare(link, options = {}) {
|
|
6087
|
+
if (isLegacyV2Link(link)) {
|
|
6088
|
+
const legacy = await resolveLegacyV2(link, options);
|
|
6089
|
+
await verifyLegacyV2(legacy.envelope, options);
|
|
6090
|
+
options.onResolvedAddressedEnvelope?.(legacy.envelope, legacy.cid);
|
|
6091
|
+
return { metadata: metadataFor(legacy.envelope, legacy.origin), link: { origin: legacy.origin, cid: legacy.cid, kind: "compact" } };
|
|
6092
|
+
}
|
|
5855
6093
|
const resolved = await resolvePolicyShare(link, options);
|
|
5856
6094
|
return { metadata: metadataFor(resolved.envelope, resolved.origin), link: { origin: resolved.origin, cid: resolved.cid, kind: "policy" } };
|
|
5857
6095
|
}
|
|
6096
|
+
function isLegacyV2Link(link) {
|
|
6097
|
+
try {
|
|
6098
|
+
const url = new URL(link);
|
|
6099
|
+
return /^\/s\/bafkrei[a-z2-7]{52}$/.test(url.pathname) && url.hash.startsWith("#k=");
|
|
6100
|
+
} catch {
|
|
6101
|
+
return false;
|
|
6102
|
+
}
|
|
6103
|
+
}
|
|
5858
6104
|
|
|
5859
6105
|
// src/recipient.ts
|
|
5860
6106
|
var import_ed255194 = require("@noble/curves/ed25519");
|
|
@@ -6050,8 +6296,8 @@ function parseV3InlineEncryptedEnvelope(bytes, expected) {
|
|
|
6050
6296
|
}
|
|
6051
6297
|
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("encrypted content envelope is malformed");
|
|
6052
6298
|
const record = value;
|
|
6053
|
-
const allowed = ["v", "networkId", "alg", "keyVersion", "encryptedSymmetricKey", "encryptedSymmetricKeyHash", "ciphertext", "metadata"];
|
|
6054
|
-
if (Object.keys(record).some((key) => !allowed.includes(key)) || record.v !== 1 || record.networkId !== expected.encryptionNetwork || record.alg !== "x25519-aes256gcm/v1" || record.keyVersion !== expected.contentSource.keyVersion || typeof record.encryptedSymmetricKey !== "string" || typeof record.encryptedSymmetricKeyHash !== "string" || record.encryptedSymmetricKeyHash !== expected.contentSource.encryptedSymmetricKeyDigestHex || record.encryptedSymmetricKeyHash !== canonicalHashHex(record.encryptedSymmetricKey) || typeof record.ciphertext !== "string" || record.metadata !== void 0 && (record.metadata === null || typeof record.metadata !== "object" || Array.isArray(record.metadata) || Object.values(record.metadata).some((entry) => typeof entry !== "string"))) {
|
|
6299
|
+
const allowed = ["v", "networkId", "keyPath", "alg", "keyVersion", "encryptedSymmetricKey", "encryptedSymmetricKeyHash", "ciphertext", "metadata"];
|
|
6300
|
+
if (Object.keys(record).some((key) => !allowed.includes(key)) || record.v !== 1 || record.networkId !== expected.encryptionNetwork || record.keyPath !== expected.contentSource.encryptionKeyPath || record.keyPath !== void 0 && record.keyPath !== `share/${expected.shareId}` || record.alg !== "x25519-aes256gcm/v1" || record.keyVersion !== expected.contentSource.keyVersion || typeof record.encryptedSymmetricKey !== "string" || typeof record.encryptedSymmetricKeyHash !== "string" || record.encryptedSymmetricKeyHash !== expected.contentSource.encryptedSymmetricKeyDigestHex || record.encryptedSymmetricKeyHash !== canonicalHashHex(record.encryptedSymmetricKey) || typeof record.ciphertext !== "string" || record.metadata !== void 0 && (record.metadata === null || typeof record.metadata !== "object" || Array.isArray(record.metadata) || Object.values(record.metadata).some((entry) => typeof entry !== "string"))) {
|
|
6055
6301
|
throw new Error("encrypted content envelope binding is invalid");
|
|
6056
6302
|
}
|
|
6057
6303
|
return record;
|
|
@@ -6183,15 +6429,16 @@ var ShareRecipientClient = class {
|
|
|
6183
6429
|
const receiverPrivateKey = crypto.getRandomValues(new Uint8Array(32));
|
|
6184
6430
|
const receiverPublicKey = toBase64(import_ed255194.x25519.getPublicKey(receiverPrivateKey));
|
|
6185
6431
|
const receiverPublicKeyHash = canonicalHashHex(receiverPublicKey);
|
|
6186
|
-
const body = { type: "tinycloud.encryption.decrypt/v1", targetNode: this.v3NodeAudience, networkId: encrypted.networkId, alg: encrypted.alg, keyVersion: encrypted.keyVersion, encryptedSymmetricKey: encrypted.encryptedSymmetricKey, encryptedSymmetricKeyHash: encrypted.encryptedSymmetricKeyHash, receiverPublicKey, receiverPublicKeyHash };
|
|
6432
|
+
const body = { type: "tinycloud.encryption.decrypt/v1", targetNode: this.v3NodeAudience, networkId: encrypted.networkId, ...encrypted.keyPath === void 0 ? {} : { keyPath: encrypted.keyPath }, alg: encrypted.alg, keyVersion: encrypted.keyVersion, encryptedSymmetricKey: encrypted.encryptedSymmetricKey, encryptedSymmetricKeyHash: encrypted.encryptedSymmetricKeyHash, receiverPublicKey, receiverPublicKeyHash };
|
|
6187
6433
|
const bodyHash = hex2((0, import_sha2562.sha256)(new TextEncoder().encode(canonicalize(body))));
|
|
6188
6434
|
const session = verifyCompactUcanAuthorization(this.v3Authorization, this.session.sessionId);
|
|
6189
6435
|
const now = Math.floor(Date.now() / 1e3);
|
|
6436
|
+
const decryptResource = encrypted.keyPath === void 0 ? encrypted.networkId : `${encrypted.networkId}/${encrypted.keyPath}`;
|
|
6190
6437
|
const invocation = await signCompactUcanAuthorization({
|
|
6191
6438
|
issuerDid: this.options.holderDid,
|
|
6192
6439
|
audienceDid: this.v3NodeAudience,
|
|
6193
|
-
attenuation: { [
|
|
6194
|
-
facts: [{ type: body.type, targetNode: body.targetNode, networkId: body.networkId, bodyHash, encryptedSymmetricKeyHash: body.encryptedSymmetricKeyHash, receiverPublicKeyHash, alg: body.alg, keyVersion: body.keyVersion }],
|
|
6440
|
+
attenuation: { [decryptResource]: { "tinycloud.encryption/decrypt": [{}] } },
|
|
6441
|
+
facts: [{ type: body.type, targetNode: body.targetNode, networkId: body.networkId, ...encrypted.keyPath === void 0 ? {} : { keyPath: encrypted.keyPath }, bodyHash, encryptedSymmetricKeyHash: body.encryptedSymmetricKeyHash, receiverPublicKeyHash, alg: body.alg, keyVersion: body.keyVersion }],
|
|
6195
6442
|
proofs: [session.cid],
|
|
6196
6443
|
notBefore: now,
|
|
6197
6444
|
expiresAt: Math.min(now + 60, session.payload.exp),
|