@tinycloud/cli 1.0.0-beta.10 → 1.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +260 -81
- package/dist/index.js.map +1 -1
- package/dist/legacy-entry.js +85 -49
- package/dist/legacy-entry.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -17579,6 +17579,68 @@ function validateV3Invariants(value, ctx) {
|
|
|
17579
17579
|
ctx.addIssue({ code: external_exports2.ZodIssueCode.custom, path: ["policy", "capabilityCeiling"], message: "policy ceiling must contain exact decrypt network" });
|
|
17580
17580
|
}
|
|
17581
17581
|
}
|
|
17582
|
+
function assertKey(key32) {
|
|
17583
|
+
if (key32.length !== KEY_LENGTH) {
|
|
17584
|
+
throw new TypeError(`key must be ${KEY_LENGTH} bytes, got ${key32.length}`);
|
|
17585
|
+
}
|
|
17586
|
+
}
|
|
17587
|
+
async function importAesKey(key32, usage) {
|
|
17588
|
+
assertKey(key32);
|
|
17589
|
+
return globalThis.crypto.subtle.importKey(
|
|
17590
|
+
"raw",
|
|
17591
|
+
key32,
|
|
17592
|
+
"AES-GCM",
|
|
17593
|
+
false,
|
|
17594
|
+
[usage]
|
|
17595
|
+
);
|
|
17596
|
+
}
|
|
17597
|
+
function generateKey() {
|
|
17598
|
+
return globalThis.crypto.getRandomValues(new Uint8Array(KEY_LENGTH));
|
|
17599
|
+
}
|
|
17600
|
+
async function seal(plaintextBytes, key32) {
|
|
17601
|
+
const { nonce, ciphertext } = await encryptEnvelope(plaintextBytes, key32);
|
|
17602
|
+
const blob = new Uint8Array(HEADER_LENGTH + nonce.length + ciphertext.length);
|
|
17603
|
+
blob[0] = SEALED_BLOB_VERSION;
|
|
17604
|
+
blob.set(nonce, HEADER_LENGTH);
|
|
17605
|
+
blob.set(ciphertext, HEADER_LENGTH + nonce.length);
|
|
17606
|
+
return { blob, cid: await computeCid(blob) };
|
|
17607
|
+
}
|
|
17608
|
+
async function open(blob, key32) {
|
|
17609
|
+
if (blob.length < HEADER_LENGTH + NONCE_LENGTH + TAG_LENGTH) {
|
|
17610
|
+
throw new TypeError(`sealed blob too short: ${blob.length} bytes`);
|
|
17611
|
+
}
|
|
17612
|
+
if (blob[0] !== SEALED_BLOB_VERSION) {
|
|
17613
|
+
throw new TypeError(`unknown sealed blob version: ${blob[0]}`);
|
|
17614
|
+
}
|
|
17615
|
+
const nonce = blob.subarray(HEADER_LENGTH, HEADER_LENGTH + NONCE_LENGTH);
|
|
17616
|
+
const ciphertext = blob.subarray(HEADER_LENGTH + NONCE_LENGTH);
|
|
17617
|
+
return decryptEnvelope(nonce, ciphertext, key32);
|
|
17618
|
+
}
|
|
17619
|
+
async function encryptEnvelope(plaintextBytes, key32) {
|
|
17620
|
+
const key = await importAesKey(key32, "encrypt");
|
|
17621
|
+
const nonce = globalThis.crypto.getRandomValues(new Uint8Array(NONCE_LENGTH));
|
|
17622
|
+
const ciphertext = new Uint8Array(
|
|
17623
|
+
await globalThis.crypto.subtle.encrypt(
|
|
17624
|
+
{ name: "AES-GCM", iv: nonce, additionalData: AAD },
|
|
17625
|
+
key,
|
|
17626
|
+
plaintextBytes
|
|
17627
|
+
)
|
|
17628
|
+
);
|
|
17629
|
+
return { nonce, ciphertext };
|
|
17630
|
+
}
|
|
17631
|
+
async function decryptEnvelope(nonce, ciphertext, key32) {
|
|
17632
|
+
if (nonce.length !== NONCE_LENGTH) {
|
|
17633
|
+
throw new TypeError(`nonce must be ${NONCE_LENGTH} bytes, got ${nonce.length}`);
|
|
17634
|
+
}
|
|
17635
|
+
const key = await importAesKey(key32, "decrypt");
|
|
17636
|
+
return new Uint8Array(
|
|
17637
|
+
await globalThis.crypto.subtle.decrypt(
|
|
17638
|
+
{ name: "AES-GCM", iv: nonce, additionalData: AAD },
|
|
17639
|
+
key,
|
|
17640
|
+
ciphertext
|
|
17641
|
+
)
|
|
17642
|
+
);
|
|
17643
|
+
}
|
|
17582
17644
|
function isPlainRecord(value) {
|
|
17583
17645
|
const proto = Object.getPrototypeOf(value);
|
|
17584
17646
|
return proto === Object.prototype || proto === null;
|
|
@@ -17778,62 +17840,61 @@ function assertCanonicalCid(cidString) {
|
|
|
17778
17840
|
throw new TypeError(`not a canonical CIDv1 raw sha2-256 base32 CID: ${cidString}`);
|
|
17779
17841
|
}
|
|
17780
17842
|
}
|
|
17781
|
-
async function
|
|
17843
|
+
async function encodeSealedInlineShareUrl(parts) {
|
|
17782
17844
|
if (!isCanonicalHttpsOrigin(parts.origin)) throw new TypeError("origin must be a canonical https origin");
|
|
17783
|
-
if (parts.
|
|
17784
|
-
|
|
17785
|
-
const
|
|
17845
|
+
if (parts.ciphertext.byteLength === 0 || parts.ciphertext.byteLength > MAX_INLINE_BYTES) throw new RangeError("inline ciphertext is outside the allowed size");
|
|
17846
|
+
if (parts.key32.byteLength !== KEY_LENGTH2) throw new TypeError("inline key must be 32 bytes");
|
|
17847
|
+
const ciphertextCid = await computeCid(parts.ciphertext);
|
|
17848
|
+
const payload = canonicalize2({
|
|
17786
17849
|
v: 2,
|
|
17787
|
-
c: toBase64Url(parts.
|
|
17788
|
-
cid: ciphertextCid
|
|
17789
|
-
|
|
17850
|
+
c: toBase64Url(parts.ciphertext),
|
|
17851
|
+
cid: ciphertextCid,
|
|
17852
|
+
k: toBase64Url(parts.key32)
|
|
17853
|
+
});
|
|
17854
|
+
const payloadBytes = new TextEncoder().encode(payload);
|
|
17790
17855
|
if (payloadBytes.byteLength > MAX_INLINE_BYTES * 2) throw new RangeError("inline URL is too large");
|
|
17791
|
-
return `${parts.origin}/
|
|
17856
|
+
return `${parts.origin}/s/inline#v=2&p=${toBase64Url(payloadBytes)}`;
|
|
17792
17857
|
}
|
|
17793
|
-
function
|
|
17858
|
+
async function parseSealedInlineShareUrl(url, options = {}) {
|
|
17794
17859
|
const parsed = new URL(url);
|
|
17795
|
-
if (parsed.protocol !== "https:" || parsed.username !== "" || parsed.password !== "") throw new TypeError("inline share URL must be canonical HTTPS without userinfo");
|
|
17796
|
-
if (!isCanonicalHttpsOrigin(parsed.origin) || options.expectedOrigin !== void 0 && parsed.origin !== options.expectedOrigin) throw new TypeError("inline share URL origin is not trusted");
|
|
17797
|
-
if (parsed.pathname !== "/
|
|
17798
|
-
|
|
17799
|
-
const
|
|
17800
|
-
if (
|
|
17801
|
-
|
|
17860
|
+
if (parsed.protocol !== "https:" || parsed.username !== "" || parsed.password !== "") throw new TypeError("sealed inline share URL must be canonical HTTPS without userinfo");
|
|
17861
|
+
if (!isCanonicalHttpsOrigin(parsed.origin) || options.expectedOrigin !== void 0 && parsed.origin !== options.expectedOrigin) throw new TypeError("sealed inline share URL origin is not trusted");
|
|
17862
|
+
if (parsed.pathname !== "/s/inline" || parsed.search !== "") throw new TypeError("not a Node sealed-inline share URL");
|
|
17863
|
+
if (url !== `${parsed.origin}/s/inline${parsed.hash}`) throw new TypeError("sealed inline share URL is not lexically canonical");
|
|
17864
|
+
const prefix = "#v=2&p=";
|
|
17865
|
+
if (!parsed.hash.startsWith(prefix)) throw new TypeError("sealed inline URL is missing its canonical fragment");
|
|
17866
|
+
const encoded = parsed.hash.slice(prefix.length);
|
|
17867
|
+
if (encoded.length === 0 || parsed.hash !== `${prefix}${encoded}`) throw new TypeError("sealed inline URL fragment is not canonical");
|
|
17802
17868
|
let payloadBytes;
|
|
17803
17869
|
try {
|
|
17804
|
-
payloadBytes = fromBase64Url(
|
|
17870
|
+
payloadBytes = fromBase64Url(encoded);
|
|
17805
17871
|
} catch {
|
|
17806
|
-
throw new TypeError("inline payload is not canonical base64url");
|
|
17872
|
+
throw new TypeError("sealed inline payload is not canonical base64url");
|
|
17807
17873
|
}
|
|
17808
|
-
if (payloadBytes.byteLength === 0 || payloadBytes.byteLength > MAX_INLINE_BYTES * 2) throw new TypeError("inline payload is too large");
|
|
17874
|
+
if (payloadBytes.byteLength === 0 || payloadBytes.byteLength > MAX_INLINE_BYTES * 2) throw new TypeError("sealed inline payload is too large");
|
|
17875
|
+
const payloadText = new TextDecoder("utf-8", { fatal: true }).decode(payloadBytes);
|
|
17809
17876
|
let value;
|
|
17810
17877
|
try {
|
|
17811
|
-
value = JSON.parse(
|
|
17878
|
+
value = JSON.parse(payloadText);
|
|
17812
17879
|
} catch {
|
|
17813
|
-
throw new TypeError("inline payload is not valid JSON");
|
|
17880
|
+
throw new TypeError("sealed inline payload is not valid JSON");
|
|
17814
17881
|
}
|
|
17815
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError("inline payload
|
|
17816
|
-
if (canonicalize2(value) !== new TextDecoder("utf-8").decode(payloadBytes)) throw new TypeError("inline payload is not canonical JSON");
|
|
17882
|
+
if (typeof value !== "object" || value === null || Array.isArray(value) || canonicalize2(value) !== payloadText) throw new TypeError("sealed inline payload is not canonical JSON");
|
|
17817
17883
|
const record = value;
|
|
17818
|
-
|
|
17819
|
-
if (!keys.every((key) => key === "v" || key === "c" || key === "cid" || key === "k") || record.v !== 2 || typeof record.c !== "string" || typeof record.cid !== "string" || publicPayload !== void 0 && (keys.length !== 3 || record.k !== void 0)) throw new TypeError("inline payload has invalid fields");
|
|
17884
|
+
if (Object.keys(record).length !== 4 || record.v !== 2 || typeof record.c !== "string" || typeof record.cid !== "string" || typeof record.k !== "string") throw new TypeError("sealed inline payload has invalid fields");
|
|
17820
17885
|
let ciphertext;
|
|
17886
|
+
let key32;
|
|
17821
17887
|
try {
|
|
17822
17888
|
ciphertext = fromBase64Url(record.c);
|
|
17889
|
+
key32 = fromBase64Url(record.k);
|
|
17823
17890
|
} catch {
|
|
17824
|
-
throw new TypeError("inline
|
|
17891
|
+
throw new TypeError("sealed inline payload has invalid base64url material");
|
|
17825
17892
|
}
|
|
17826
|
-
if (ciphertext.byteLength === 0 || ciphertext.byteLength > MAX_INLINE_BYTES) throw new TypeError("inline ciphertext is outside the allowed size");
|
|
17893
|
+
if (ciphertext.byteLength === 0 || ciphertext.byteLength > MAX_INLINE_BYTES) throw new TypeError("sealed inline ciphertext is outside the allowed size");
|
|
17894
|
+
if (key32.byteLength !== KEY_LENGTH2) throw new TypeError("sealed inline key must be 32 bytes");
|
|
17827
17895
|
assertCanonicalCid(record.cid);
|
|
17828
|
-
if (
|
|
17829
|
-
|
|
17830
|
-
try {
|
|
17831
|
-
key32 = record.k === void 0 ? void 0 : fromBase64Url(record.k);
|
|
17832
|
-
} catch {
|
|
17833
|
-
throw new TypeError("inline key is not canonical base64url");
|
|
17834
|
-
}
|
|
17835
|
-
if (key32 !== void 0 && key32.length !== KEY_LENGTH2) throw new TypeError("inline key must be 32 bytes");
|
|
17836
|
-
return { kind: "inline", ciphertextCid: record.cid, ciphertext, ...key32 === void 0 ? {} : { key32 } };
|
|
17896
|
+
if (await computeCid(ciphertext) !== record.cid) throw new TypeError("sealed inline ciphertext does not match its CID");
|
|
17897
|
+
return { kind: "inline", ciphertextCid: record.cid, ciphertext, key32 };
|
|
17837
17898
|
}
|
|
17838
17899
|
function metadataFor(envelope, origin) {
|
|
17839
17900
|
const kind = envelope.recipientMatcher.kind === "recipientDid" ? "recipientDid" : envelope.recipientMatcher.kind === "exactEmail" ? "email" : "emailDomain";
|
|
@@ -17859,19 +17920,17 @@ async function resolvePolicyShare(link2, options) {
|
|
|
17859
17920
|
let parsed;
|
|
17860
17921
|
try {
|
|
17861
17922
|
url = new URL(link2);
|
|
17862
|
-
|
|
17863
|
-
parsed = parseInlineShareUrl(link2, { ...options.expectedOrigin === void 0 ? {} : { expectedOrigin: options.expectedOrigin } });
|
|
17864
|
-
if (parsed.key32 !== void 0) throw new Error("secret inline transport is retired");
|
|
17923
|
+
parsed = await parseSealedInlineShareUrl(link2, { ...options.expectedOrigin === void 0 ? {} : { expectedOrigin: options.expectedOrigin } });
|
|
17865
17924
|
} catch {
|
|
17866
17925
|
throw new ShareReceiveError("invalid-link", "share link format is invalid");
|
|
17867
17926
|
}
|
|
17868
17927
|
const limit = options.maxSealedBlobBytes ?? DEFAULT_MAX_SEALED_BLOB_BYTES;
|
|
17869
|
-
if (!Number.isSafeInteger(limit) || limit <= 0 || parsed.ciphertext.byteLength > limit) throw new ShareReceiveError("max-bytes-exceeded", "
|
|
17870
|
-
if (await computeCid(parsed.ciphertext) !== parsed.ciphertextCid) throw new ShareReceiveError("cid-mismatch", "
|
|
17928
|
+
if (!Number.isSafeInteger(limit) || limit <= 0 || parsed.ciphertext.byteLength > limit) throw new ShareReceiveError("max-bytes-exceeded", "sealed policy envelope exceeds the configured byte limit");
|
|
17929
|
+
if (await computeCid(parsed.ciphertext) !== parsed.ciphertextCid) throw new ShareReceiveError("cid-mismatch", "sealed envelope bytes do not match the link CID");
|
|
17871
17930
|
options.signal?.throwIfAborted();
|
|
17872
17931
|
let envelope;
|
|
17873
17932
|
try {
|
|
17874
|
-
const encoded = new TextDecoder("utf-8", { fatal: true }).decode(parsed.ciphertext);
|
|
17933
|
+
const encoded = new TextDecoder("utf-8", { fatal: true }).decode(await open(parsed.ciphertext, parsed.key32));
|
|
17875
17934
|
const value = JSON.parse(encoded);
|
|
17876
17935
|
if (canonicalize2(value) !== encoded) throw new Error("non-canonical envelope");
|
|
17877
17936
|
envelope = shareEnvelopeV3Schema.parse(value);
|
|
@@ -18455,14 +18514,25 @@ async function publishAddressedShare(options) {
|
|
|
18455
18514
|
const envelope = { ...unsigned, signature: { signerDid: options.authority.ownerDid, algorithm: "Ed25519", value: toBase64Url(envelopeSignature) } };
|
|
18456
18515
|
shareEnvelopeV3Schema.parse(envelope);
|
|
18457
18516
|
const envelopeBytes = textEncoder.encode(canonicalize2(envelope));
|
|
18458
|
-
const
|
|
18459
|
-
const
|
|
18460
|
-
const
|
|
18517
|
+
const envelopeKeyBytes = generateKey();
|
|
18518
|
+
const sealed = await seal(envelopeBytes, envelopeKeyBytes);
|
|
18519
|
+
const envelopeKey = toBase64Url(envelopeKeyBytes);
|
|
18520
|
+
const url = await encodeSealedInlineShareUrl({
|
|
18521
|
+
origin: options.shareOrigin,
|
|
18522
|
+
ciphertext: sealed.blob,
|
|
18523
|
+
key32: envelopeKeyBytes
|
|
18524
|
+
});
|
|
18525
|
+
const deliveryMaterial = {
|
|
18526
|
+
envelope,
|
|
18527
|
+
shareCid: sealed.cid,
|
|
18528
|
+
sealedEnvelope: toBase64Url(sealed.blob),
|
|
18529
|
+
envelopeKey
|
|
18530
|
+
};
|
|
18461
18531
|
options.onDeliveryMaterial?.(deliveryMaterial);
|
|
18462
18532
|
return publicationResult({
|
|
18463
18533
|
options,
|
|
18464
18534
|
url,
|
|
18465
|
-
envelopeCid,
|
|
18535
|
+
envelopeCid: sealed.cid,
|
|
18466
18536
|
matcher,
|
|
18467
18537
|
policyCid: created.policyCid,
|
|
18468
18538
|
policyRootCid: policyRoot.cid,
|
|
@@ -18695,6 +18765,110 @@ async function defaultIdempotencyKey(shareId, recipient) {
|
|
|
18695
18765
|
));
|
|
18696
18766
|
return `tinycloud-share:${shareId}:${toBase64Url(digest3)}`;
|
|
18697
18767
|
}
|
|
18768
|
+
function canonicalOrigin(value) {
|
|
18769
|
+
let url;
|
|
18770
|
+
try {
|
|
18771
|
+
url = new URL(value);
|
|
18772
|
+
} catch {
|
|
18773
|
+
throw new CredentialInvitationError(
|
|
18774
|
+
"invalid-origin",
|
|
18775
|
+
"credential invitation origin is invalid"
|
|
18776
|
+
);
|
|
18777
|
+
}
|
|
18778
|
+
if (url.origin !== value || url.username !== "" || url.password !== "" || url.search !== "" || url.hash !== "" || url.protocol !== "https:")
|
|
18779
|
+
throw new CredentialInvitationError(
|
|
18780
|
+
"invalid-origin",
|
|
18781
|
+
"credential invitation origin is invalid"
|
|
18782
|
+
);
|
|
18783
|
+
return url.origin;
|
|
18784
|
+
}
|
|
18785
|
+
function object2(value) {
|
|
18786
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18787
|
+
}
|
|
18788
|
+
async function validateReceipt(receipt, shareUrl) {
|
|
18789
|
+
if (!object2(receipt) || !object2(receipt.request) || !object2(receipt.admission) || !object2(receipt.proof)) {
|
|
18790
|
+
throw new CredentialInvitationError(
|
|
18791
|
+
"invalid-receipt",
|
|
18792
|
+
"credential invitation receipt is invalid"
|
|
18793
|
+
);
|
|
18794
|
+
}
|
|
18795
|
+
if (receipt.request.returnLink !== shareUrl) {
|
|
18796
|
+
throw new CredentialInvitationError(
|
|
18797
|
+
"invalid-receipt",
|
|
18798
|
+
"credential invitation is not bound to the share link"
|
|
18799
|
+
);
|
|
18800
|
+
}
|
|
18801
|
+
let link2;
|
|
18802
|
+
try {
|
|
18803
|
+
link2 = new URL(shareUrl);
|
|
18804
|
+
} catch {
|
|
18805
|
+
throw new CredentialInvitationError(
|
|
18806
|
+
"invalid-receipt",
|
|
18807
|
+
"credential invitation share link is invalid"
|
|
18808
|
+
);
|
|
18809
|
+
}
|
|
18810
|
+
if (link2.search !== "" || link2.pathname !== "/s/inline") {
|
|
18811
|
+
throw new CredentialInvitationError(
|
|
18812
|
+
"invalid-receipt",
|
|
18813
|
+
"credential invitation share link must be sealed inline"
|
|
18814
|
+
);
|
|
18815
|
+
}
|
|
18816
|
+
try {
|
|
18817
|
+
await parseSealedInlineShareUrl(shareUrl);
|
|
18818
|
+
} catch {
|
|
18819
|
+
throw new CredentialInvitationError(
|
|
18820
|
+
"invalid-receipt",
|
|
18821
|
+
"credential invitation share link is invalid"
|
|
18822
|
+
);
|
|
18823
|
+
}
|
|
18824
|
+
}
|
|
18825
|
+
async function deliverCredentialInvitation(input) {
|
|
18826
|
+
const credentialsOrigin = canonicalOrigin(input.credentialsOrigin);
|
|
18827
|
+
await validateReceipt(input.receipt, input.shareUrl);
|
|
18828
|
+
const fetchFn = input.fetchFn ?? globalThis.fetch;
|
|
18829
|
+
let response;
|
|
18830
|
+
try {
|
|
18831
|
+
response = await fetchFn(`${credentialsOrigin}/v1/credential-invitations`, {
|
|
18832
|
+
method: "POST",
|
|
18833
|
+
credentials: "omit",
|
|
18834
|
+
redirect: "error",
|
|
18835
|
+
referrerPolicy: "no-referrer",
|
|
18836
|
+
headers: {
|
|
18837
|
+
accept: "application/json",
|
|
18838
|
+
"content-type": "application/json"
|
|
18839
|
+
},
|
|
18840
|
+
body: JSON.stringify(input.receipt),
|
|
18841
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
18842
|
+
});
|
|
18843
|
+
} catch {
|
|
18844
|
+
throw new CredentialInvitationError(
|
|
18845
|
+
"transport",
|
|
18846
|
+
"credential invitation delivery is unavailable"
|
|
18847
|
+
);
|
|
18848
|
+
}
|
|
18849
|
+
if (response.status !== 202) {
|
|
18850
|
+
throw new CredentialInvitationError(
|
|
18851
|
+
"rejected",
|
|
18852
|
+
"credential invitation delivery was not accepted"
|
|
18853
|
+
);
|
|
18854
|
+
}
|
|
18855
|
+
let body;
|
|
18856
|
+
try {
|
|
18857
|
+
body = await response.json();
|
|
18858
|
+
} catch {
|
|
18859
|
+
throw new CredentialInvitationError(
|
|
18860
|
+
"invalid-response",
|
|
18861
|
+
"credential invitation response is invalid"
|
|
18862
|
+
);
|
|
18863
|
+
}
|
|
18864
|
+
if (!object2(body) || Object.keys(body).length !== 1 || body.status !== "accepted") {
|
|
18865
|
+
throw new CredentialInvitationError(
|
|
18866
|
+
"invalid-response",
|
|
18867
|
+
"credential invitation response is invalid"
|
|
18868
|
+
);
|
|
18869
|
+
}
|
|
18870
|
+
return { status: "accepted" };
|
|
18871
|
+
}
|
|
18698
18872
|
function targetKind2(record) {
|
|
18699
18873
|
if (record.targetKind !== void 0) return record.targetKind;
|
|
18700
18874
|
return record.recipientMatcher.kind === "exactEmail" ? "email" : record.recipientMatcher.kind === "emailDomain" ? "emailDomain" : record.recipientMatcher.kind === "recipientDid" ? "recipientDid" : "bearer";
|
|
@@ -18777,7 +18951,7 @@ function parseNativeShareUrl(value) {
|
|
|
18777
18951
|
if (!token || fragment.size !== 1) throw new TypeError("missing native share fragment");
|
|
18778
18952
|
return token;
|
|
18779
18953
|
}
|
|
18780
|
-
var __defProp2, __export2, external_exports2, util2, objectUtil2, ZodParsedType2, getParsedType2, ZodIssueCode2, quotelessJson2, ZodError2, errorMap2, en_default2, overrideErrorMap2, makeIssue2, EMPTY_PATH2, ParseStatus2, INVALID2, DIRTY2, OK2, isAborted2, isDirty2, isValid2, isAsync2, errorUtil2, ParseInputLazyPath2, handleResult2, ZodType2, cuidRegex2, cuid2Regex2, ulidRegex2, uuidRegex2, nanoidRegex2, jwtRegex2, durationRegex2, emailRegex2, _emojiRegex2, emojiRegex2, ipv4Regex2, ipv4CidrRegex2, ipv6Regex2, ipv6CidrRegex2, base64Regex2, base64urlRegex2, dateRegexSource2, dateRegex2, ZodString2, ZodNumber2, ZodBigInt2, ZodBoolean2, ZodDate2, ZodSymbol2, ZodUndefined2, ZodNull2, ZodAny2, ZodUnknown2, ZodNever2, ZodVoid2, ZodArray2, ZodObject2, ZodUnion2, getDiscriminator2, ZodDiscriminatedUnion2, ZodIntersection2, ZodTuple2, ZodRecord2, ZodMap2, ZodSet2, ZodFunction2, ZodLazy2, ZodLiteral2, ZodEnum2, ZodNativeEnum2, ZodPromise2, ZodEffects2, ZodOptional2, ZodNullable2, ZodDefault2, ZodCatch2, ZodNaN2, BRAND2, ZodBranded2, ZodPipeline2, ZodReadonly2, late2, ZodFirstPartyTypeKind2, instanceOfType2, stringType2, numberType2, nanType2, bigIntType2, booleanType2, dateType2, symbolType2, undefinedType2, nullType2, anyType2, unknownType2, neverType2, voidType2, arrayType2, objectType2, strictObjectType2, unionType2, discriminatedUnionType2, intersectionType2, tupleType2, recordType2, mapType2, setType2, functionType2, lazyType2, literalType2, enumType2, nativeEnumType2, promiseType2, effectsType2, optionalType2, nullableType2, preprocessType2, pipelineType2, ostring2, onumber2, oboolean2, coerce2, NEVER2, empty, src, _brrp__multiformats_scope_baseX, base_x_default, Encoder, Decoder, ComposedDecoder, Codec, base32, base32upper, base32pad, base32padupper, base32hex, base32hexupper, base32hexpad, base32hexpadupper, base32z, base36, base36upper, base58btc, base58flickr, encode_1, MSB, REST, MSBALL, INT, decode2, MSB$1, REST$1, N1, N2, N3, N4, N5, N6, N7, N8, N9, length, varint, _brrp_varint, varint_default, Digest, cache, CID, DAG_PB_CODE, SHA_256_CODE, cidSymbol, code, SHA256_CODE, base64, base64pad, base64url, base64urlpad, ED25519_MULTICODEC_PREFIX, PUBLIC_KEY_LENGTH, base64UrlString, sessionJwkCommonFields, okpPrivateJwkSchema, ecPrivateJwkSchema, sessionJwkSchema, policyTargetSchema, bearerKeyTargetSchema, recipientDidTargetSchema, authorizationTargetSchema, resourceSelectorSchema, targetSchema, displaySchema, contentPointerSchema, signatureSchema, unsignedShareEnvelopeSchema, shareEnvelopeSchema, recipientMatcherSchema, shareActionSchema, kvContentSourceSchema, sqlContentSourceSchema, contentSourceSchema, v2TargetSchema, shareDecryptionSchema, ownerAuthoritySchema, contentMetadataSchema, unsignedShareEnvelopeV2BaseSchema, unsignedShareEnvelopeV2Schema, shareEnvelopeV2Schema, unifiedResourceSchema, unifiedEncryptionNetworkSchema, unifiedKvCapabilitySchema, unifiedEncryptionCapabilitySchema, unifiedCapabilitySchema, unifiedContentSourceSchema, unifiedPolicyV1Schema, policyCredentialRequirementV1Schema, unifiedPolicyV2Schema, unifiedPolicySchema, unifiedRootSchema, attestedEnforcerBindingV2Schema, v3TargetSchema, unsignedShareEnvelopeV3BaseSchema, unsignedShareEnvelopeV3Schema, shareEnvelopeV3Schema, ENVELOPE_AAD_LABEL, AAD, ED25519_VERIFY_OPTS2, ENVELOPE_V3_SIGNATURE_DOMAIN, POLICY_V1_SIGNATURE_DOMAIN, POLICY_V2_SIGNATURE_DOMAIN, CONTENT_SOURCE_V1_DOMAIN, POLICY_CAPABILITY_V1_DOMAIN, NATIVE_PROJECTION_V1_DOMAIN, ATTESTED_ENFORCER_V2_DOMAIN, KEY_LENGTH2,
|
|
18954
|
+
var __defProp2, __export2, external_exports2, util2, objectUtil2, ZodParsedType2, getParsedType2, ZodIssueCode2, quotelessJson2, ZodError2, errorMap2, en_default2, overrideErrorMap2, makeIssue2, EMPTY_PATH2, ParseStatus2, INVALID2, DIRTY2, OK2, isAborted2, isDirty2, isValid2, isAsync2, errorUtil2, ParseInputLazyPath2, handleResult2, ZodType2, cuidRegex2, cuid2Regex2, ulidRegex2, uuidRegex2, nanoidRegex2, jwtRegex2, durationRegex2, emailRegex2, _emojiRegex2, emojiRegex2, ipv4Regex2, ipv4CidrRegex2, ipv6Regex2, ipv6CidrRegex2, base64Regex2, base64urlRegex2, dateRegexSource2, dateRegex2, ZodString2, ZodNumber2, ZodBigInt2, ZodBoolean2, ZodDate2, ZodSymbol2, ZodUndefined2, ZodNull2, ZodAny2, ZodUnknown2, ZodNever2, ZodVoid2, ZodArray2, ZodObject2, ZodUnion2, getDiscriminator2, ZodDiscriminatedUnion2, ZodIntersection2, ZodTuple2, ZodRecord2, ZodMap2, ZodSet2, ZodFunction2, ZodLazy2, ZodLiteral2, ZodEnum2, ZodNativeEnum2, ZodPromise2, ZodEffects2, ZodOptional2, ZodNullable2, ZodDefault2, ZodCatch2, ZodNaN2, BRAND2, ZodBranded2, ZodPipeline2, ZodReadonly2, late2, ZodFirstPartyTypeKind2, instanceOfType2, stringType2, numberType2, nanType2, bigIntType2, booleanType2, dateType2, symbolType2, undefinedType2, nullType2, anyType2, unknownType2, neverType2, voidType2, arrayType2, objectType2, strictObjectType2, unionType2, discriminatedUnionType2, intersectionType2, tupleType2, recordType2, mapType2, setType2, functionType2, lazyType2, literalType2, enumType2, nativeEnumType2, promiseType2, effectsType2, optionalType2, nullableType2, preprocessType2, pipelineType2, ostring2, onumber2, oboolean2, coerce2, NEVER2, empty, src, _brrp__multiformats_scope_baseX, base_x_default, Encoder, Decoder, ComposedDecoder, Codec, base32, base32upper, base32pad, base32padupper, base32hex, base32hexupper, base32hexpad, base32hexpadupper, base32z, base36, base36upper, base58btc, base58flickr, encode_1, MSB, REST, MSBALL, INT, decode2, MSB$1, REST$1, N1, N2, N3, N4, N5, N6, N7, N8, N9, length, varint, _brrp_varint, varint_default, Digest, cache, CID, DAG_PB_CODE, SHA_256_CODE, cidSymbol, code, SHA256_CODE, base64, base64pad, base64url, base64urlpad, ED25519_MULTICODEC_PREFIX, PUBLIC_KEY_LENGTH, base64UrlString, sessionJwkCommonFields, okpPrivateJwkSchema, ecPrivateJwkSchema, sessionJwkSchema, policyTargetSchema, bearerKeyTargetSchema, recipientDidTargetSchema, authorizationTargetSchema, resourceSelectorSchema, targetSchema, displaySchema, contentPointerSchema, signatureSchema, unsignedShareEnvelopeSchema, shareEnvelopeSchema, recipientMatcherSchema, shareActionSchema, kvContentSourceSchema, sqlContentSourceSchema, contentSourceSchema, v2TargetSchema, shareDecryptionSchema, ownerAuthoritySchema, contentMetadataSchema, unsignedShareEnvelopeV2BaseSchema, unsignedShareEnvelopeV2Schema, shareEnvelopeV2Schema, unifiedResourceSchema, unifiedEncryptionNetworkSchema, unifiedKvCapabilitySchema, unifiedEncryptionCapabilitySchema, unifiedCapabilitySchema, unifiedContentSourceSchema, unifiedPolicyV1Schema, policyCredentialRequirementV1Schema, unifiedPolicyV2Schema, unifiedPolicySchema, unifiedRootSchema, attestedEnforcerBindingV2Schema, v3TargetSchema, unsignedShareEnvelopeV3BaseSchema, unsignedShareEnvelopeV3Schema, shareEnvelopeV3Schema, ENVELOPE_AAD_LABEL, SEALED_BLOB_VERSION, AAD, KEY_LENGTH, NONCE_LENGTH, TAG_LENGTH, HEADER_LENGTH, ED25519_VERIFY_OPTS2, ENVELOPE_V3_SIGNATURE_DOMAIN, POLICY_V1_SIGNATURE_DOMAIN, POLICY_V2_SIGNATURE_DOMAIN, CONTENT_SOURCE_V1_DOMAIN, POLICY_CAPABILITY_V1_DOMAIN, NATIVE_PROJECTION_V1_DOMAIN, ATTESTED_ENFORCER_V2_DOMAIN, KEY_LENGTH2, MAX_INLINE_BYTES, SHARE_RESULT_VERSION, DEFAULT_MAX_SEALED_BLOB_BYTES, ShareReceiveError, SHARE_CONTENT_LIMIT, SHARE_PUBLISH_RESULT_VERSION, DEFAULT_SHARE_LIFETIME_MS, SharePublishError, empty2, src2, _brrp__multiformats_scope_baseX2, base_x_default2, Encoder2, Decoder2, ComposedDecoder2, Codec2, base58btc2, base58flickr2, POLICY_V1_DOMAIN, POLICY_V2_DOMAIN, POLICY_CAPABILITY_V1_DOMAIN2, CONTENT_SOURCE_V1_DOMAIN2, NATIVE_PROJECTION_V1_DOMAIN2, ENVELOPE_V3_DOMAIN, textEncoder, base322, base32upper2, base32pad2, base32padupper2, base32hex2, base32hexupper2, base32hexpad2, base32hexpadupper2, base32z2, base362, base36upper2, encode_12, MSB2, REST2, MSBALL2, INT2, decode6, MSB$12, REST$12, N12, N22, N32, N42, N52, N62, N72, N82, N92, length2, varint2, _brrp_varint2, varint_default2, Digest2, cache2, CID2, DAG_PB_CODE2, SHA_256_CODE2, cidSymbol2, MAX_CONTENT_BYTES, ShareNotifyError, CredentialInvitationError, SHARE_V2_PROTOCOL, DOMAIN, PRESENTATION_DOMAIN, SESSION_DOMAIN, INVOCATION_DOMAIN, NATIVE_SHARE_FRAGMENT_PARAMETER;
|
|
18781
18955
|
var init_dist3 = __esm({
|
|
18782
18956
|
"../share-sdk/dist/index.js"() {
|
|
18783
18957
|
"use strict";
|
|
@@ -18932,10 +19106,10 @@ var init_dist3 = __esm({
|
|
|
18932
19106
|
return obj[e];
|
|
18933
19107
|
});
|
|
18934
19108
|
};
|
|
18935
|
-
util22.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (
|
|
19109
|
+
util22.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object4) => {
|
|
18936
19110
|
const keys = [];
|
|
18937
|
-
for (const key in
|
|
18938
|
-
if (Object.prototype.hasOwnProperty.call(
|
|
19111
|
+
for (const key in object4) {
|
|
19112
|
+
if (Object.prototype.hasOwnProperty.call(object4, key)) {
|
|
18939
19113
|
keys.push(key);
|
|
18940
19114
|
}
|
|
18941
19115
|
}
|
|
@@ -23394,7 +23568,12 @@ var init_dist3 = __esm({
|
|
|
23394
23568
|
unsignedShareEnvelopeV3Schema = unsignedShareEnvelopeV3BaseSchema.superRefine(validateV3Invariants);
|
|
23395
23569
|
shareEnvelopeV3Schema = unsignedShareEnvelopeV3BaseSchema.extend({ signature: signatureSchema }).strict().superRefine(validateV3Invariants);
|
|
23396
23570
|
ENVELOPE_AAD_LABEL = "tinycloud-share-envelope-v1";
|
|
23571
|
+
SEALED_BLOB_VERSION = 1;
|
|
23397
23572
|
AAD = utf8Bytes(ENVELOPE_AAD_LABEL);
|
|
23573
|
+
KEY_LENGTH = 32;
|
|
23574
|
+
NONCE_LENGTH = 12;
|
|
23575
|
+
TAG_LENGTH = 16;
|
|
23576
|
+
HEADER_LENGTH = 1;
|
|
23398
23577
|
ED25519_VERIFY_OPTS2 = { zip215: false };
|
|
23399
23578
|
ENVELOPE_V3_SIGNATURE_DOMAIN = "xyz.tinycloud.share/envelope/v3\0";
|
|
23400
23579
|
POLICY_V1_SIGNATURE_DOMAIN = "xyz.tinycloud.policy/policy/v1\0";
|
|
@@ -23404,8 +23583,6 @@ var init_dist3 = __esm({
|
|
|
23404
23583
|
NATIVE_PROJECTION_V1_DOMAIN = "xyz.tinycloud.policy/NativeProjection/v1\0";
|
|
23405
23584
|
ATTESTED_ENFORCER_V2_DOMAIN = "xyz.tinycloud.policy/AttestedEnforcerBinding/v2\0";
|
|
23406
23585
|
KEY_LENGTH2 = 32;
|
|
23407
|
-
INLINE_PREFIX = "#tc2=";
|
|
23408
|
-
PUBLIC_INLINE_PARAMETER = "tc2";
|
|
23409
23586
|
MAX_INLINE_BYTES = 256 * 1024;
|
|
23410
23587
|
SHARE_RESULT_VERSION = 1;
|
|
23411
23588
|
DEFAULT_MAX_SEALED_BLOB_BYTES = 100 * 1024 * 1024 + 29;
|
|
@@ -23906,6 +24083,13 @@ var init_dist3 = __esm({
|
|
|
23906
24083
|
this.name = "ShareNotifyError";
|
|
23907
24084
|
}
|
|
23908
24085
|
};
|
|
24086
|
+
CredentialInvitationError = class extends Error {
|
|
24087
|
+
constructor(code32, message) {
|
|
24088
|
+
super(message);
|
|
24089
|
+
this.code = code32;
|
|
24090
|
+
this.name = "CredentialInvitationError";
|
|
24091
|
+
}
|
|
24092
|
+
};
|
|
23909
24093
|
SHARE_V2_PROTOCOL = Object.freeze({
|
|
23910
24094
|
challengeDomain: "xyz.tinycloud.share/policy-challenge/v2\0",
|
|
23911
24095
|
sessionDomain: "xyz.tinycloud.share/policy-session/v2\0",
|
|
@@ -24571,9 +24755,9 @@ async function revokePolicyRootV3(input) {
|
|
|
24571
24755
|
body: JSON.stringify({ revocation: { ...unsigned, signature: { suite: "Ed25519", signerDid: input.issuerDid, value: encodeBase64Url2(signature) } } })
|
|
24572
24756
|
});
|
|
24573
24757
|
if (!response.ok) throw new Error(`policy root revocation rejected (${response.status})`);
|
|
24574
|
-
return
|
|
24758
|
+
return object22(await response.json(), "policy root revocation");
|
|
24575
24759
|
}
|
|
24576
|
-
function
|
|
24760
|
+
function object22(value, label) {
|
|
24577
24761
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
24578
24762
|
throw new Error(`${label} must be an object`);
|
|
24579
24763
|
}
|
|
@@ -29076,7 +29260,7 @@ function receiveJson(result, path) {
|
|
|
29076
29260
|
|
|
29077
29261
|
// src/share/io.ts
|
|
29078
29262
|
import { constants } from "fs";
|
|
29079
|
-
import { lstat, mkdir as mkdir2, mkdtemp, open, readFile as readFile2, realpath, stat as stat2, link, rename as rename2, rm as rm2, unlink } from "fs/promises";
|
|
29263
|
+
import { lstat, mkdir as mkdir2, mkdtemp, open as open2, readFile as readFile2, realpath, stat as stat2, link, rename as rename2, rm as rm2, unlink } from "fs/promises";
|
|
29080
29264
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
29081
29265
|
import { basename as basename2, join as join4, resolve, sep } from "path";
|
|
29082
29266
|
var MAX_SHARE_STDIN_BYTES = 100 * 1024 * 1024;
|
|
@@ -29144,7 +29328,7 @@ async function writeShareOutput(directory, filename, bytes, force) {
|
|
|
29144
29328
|
const outputDirectory = resolve(directory);
|
|
29145
29329
|
await assertDirectory(outputDirectory);
|
|
29146
29330
|
const safeName = safeFilename(filename);
|
|
29147
|
-
const directoryHandle = await
|
|
29331
|
+
const directoryHandle = await open2(outputDirectory, constants.O_RDONLY | (constants.O_DIRECTORY ?? 0) | (constants.O_NOFOLLOW ?? 0));
|
|
29148
29332
|
const stableDirectory = await realpath(outputDirectory);
|
|
29149
29333
|
const outputPath = join4(stableDirectory, safeName);
|
|
29150
29334
|
const directoryIdentity = await directoryHandle.stat();
|
|
@@ -29168,7 +29352,7 @@ async function writeShareOutput(directory, filename, bytes, force) {
|
|
|
29168
29352
|
if (error.code !== "ENOENT") throw error;
|
|
29169
29353
|
}
|
|
29170
29354
|
temporaryPath = stagingPath;
|
|
29171
|
-
handle = await
|
|
29355
|
+
handle = await open2(temporaryPath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0), 384);
|
|
29172
29356
|
await handle.writeFile(bytes);
|
|
29173
29357
|
await handle.close();
|
|
29174
29358
|
handle = void 0;
|
|
@@ -30819,18 +31003,6 @@ var MAX_INLINE_BYTES2 = 256 * 1024;
|
|
|
30819
31003
|
// src/share/adapters.ts
|
|
30820
31004
|
init_dist4();
|
|
30821
31005
|
var DEFAULT_SHARE_ORIGIN = "https://share.tinycloud.xyz";
|
|
30822
|
-
async function postAddressedShareDelivery(input) {
|
|
30823
|
-
if (input.receipt.request.returnLink !== input.shareUrl) throw new Error("credential invitation is not bound to the share link");
|
|
30824
|
-
return input.fetchFn(`${input.emailOrigin}/v1/email`, {
|
|
30825
|
-
method: "POST",
|
|
30826
|
-
credentials: "omit",
|
|
30827
|
-
redirect: "error",
|
|
30828
|
-
referrerPolicy: "no-referrer",
|
|
30829
|
-
headers: { accept: "application/json", "content-type": "application/json" },
|
|
30830
|
-
body: JSON.stringify(input.receipt),
|
|
30831
|
-
signal: input.signal
|
|
30832
|
-
});
|
|
30833
|
-
}
|
|
30834
31006
|
function createEncryptedSessionHistory() {
|
|
30835
31007
|
const records = /* @__PURE__ */ new Map();
|
|
30836
31008
|
let keyPromise;
|
|
@@ -30958,7 +31130,7 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
|
|
|
30958
31130
|
function createShareAuthorityAdapters(input = {}) {
|
|
30959
31131
|
const origin = input.origin ?? DEFAULT_SHARE_ORIGIN;
|
|
30960
31132
|
const fetchFn = input.fetchFn ?? globalThis.fetch;
|
|
30961
|
-
const
|
|
31133
|
+
const canonicalOrigin2 = (value, label) => {
|
|
30962
31134
|
if (typeof value !== "string") throw new Error(`share ${label} is unavailable`);
|
|
30963
31135
|
const parsed = new URL(value);
|
|
30964
31136
|
const loopback = parsed.hostname === "127.0.0.1" || parsed.hostname === "localhost";
|
|
@@ -30979,9 +31151,9 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
30979
31151
|
const object3 = value;
|
|
30980
31152
|
if (object3.version !== "tinycloud.share/config-v2") throw new Error("share public config version is unsupported");
|
|
30981
31153
|
return {
|
|
30982
|
-
shareOrigin:
|
|
30983
|
-
registryOrigin:
|
|
30984
|
-
|
|
31154
|
+
shareOrigin: canonicalOrigin2(object3.shareOrigin, "origin"),
|
|
31155
|
+
registryOrigin: canonicalOrigin2(object3.registryOrigin, "registry origin"),
|
|
31156
|
+
credentialsOrigin: canonicalOrigin2(input.credentialsOrigin ?? object3.credentialsOrigin, "credentials origin")
|
|
30985
31157
|
};
|
|
30986
31158
|
})();
|
|
30987
31159
|
let nodePromise;
|
|
@@ -31088,27 +31260,34 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
31088
31260
|
} };
|
|
31089
31261
|
const delivery = { deliver: input.deliver ?? (async (request) => {
|
|
31090
31262
|
const record = request.record;
|
|
31091
|
-
if (record === void 0 || record.link === void 0 || record.deliveryMaterial === void 0) throw new Error("share delivery history is incomplete");
|
|
31263
|
+
if (record === void 0 || record.link === void 0 || record.deliveryMaterial === void 0 || request.idempotencyKey === void 0) throw new Error("share delivery history is incomplete");
|
|
31092
31264
|
const [config, node] = await Promise.all([publicConfig(), authenticatedNode()]);
|
|
31265
|
+
const authorizationExpiresAt = new Date(Math.min(
|
|
31266
|
+
Date.parse(record.expiresAt),
|
|
31267
|
+
Date.parse(record.registeredAt) + 5 * 60 * 1e3
|
|
31268
|
+
)).toISOString();
|
|
31269
|
+
if (Date.parse(authorizationExpiresAt) <= Date.now()) throw new Error("share delivery authorization retry window has expired");
|
|
31093
31270
|
const receipt = await node.authorizeShareDeliveryV3({
|
|
31094
31271
|
envelope: record.deliveryMaterial.envelope,
|
|
31272
|
+
sealedEnvelope: record.deliveryMaterial.sealedEnvelope,
|
|
31273
|
+
envelopeKey: record.deliveryMaterial.envelopeKey,
|
|
31095
31274
|
shareCid: record.deliveryMaterial.shareCid,
|
|
31096
31275
|
resourcePath: record.resource.path,
|
|
31097
31276
|
recipientEmail: request.recipient,
|
|
31098
31277
|
shareUrl: record.link,
|
|
31099
31278
|
documentName: record.filename ?? "share.md",
|
|
31100
|
-
expiresAt:
|
|
31101
|
-
deliveryAudience: config.
|
|
31279
|
+
expiresAt: authorizationExpiresAt,
|
|
31280
|
+
deliveryAudience: config.credentialsOrigin,
|
|
31281
|
+
idempotencyKey: request.idempotencyKey
|
|
31102
31282
|
});
|
|
31103
|
-
|
|
31104
|
-
|
|
31283
|
+
await deliverCredentialInvitation({
|
|
31284
|
+
credentialsOrigin: config.credentialsOrigin,
|
|
31105
31285
|
receipt,
|
|
31106
31286
|
shareUrl: record.link,
|
|
31107
31287
|
fetchFn,
|
|
31108
31288
|
signal: request.signal
|
|
31109
31289
|
});
|
|
31110
|
-
|
|
31111
|
-
return response.status === 208 ? "already-delivered" : "delivered";
|
|
31290
|
+
return "delivered";
|
|
31112
31291
|
}) };
|
|
31113
31292
|
const revocation = {
|
|
31114
31293
|
revokeDelegation: input.revokeDelegation ?? (async (request) => {
|
|
@@ -31139,7 +31318,7 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
31139
31318
|
const decoder = new TinyCloudNode2({ autoDiscoverLocalNode: false });
|
|
31140
31319
|
const decoded = decoder.sharing.decodeLink(token);
|
|
31141
31320
|
if (typeof decoded.host !== "string") throw new Error("native share has no owner Node");
|
|
31142
|
-
const client = new TinyCloudNode2({ host:
|
|
31321
|
+
const client = new TinyCloudNode2({ host: canonicalOrigin2(decoded.host, "owner node origin"), autoDiscoverLocalNode: false });
|
|
31143
31322
|
const received = await client.sharing.receive(token, { autoSubdelegate: false, useSessionKey: false });
|
|
31144
31323
|
if (!received.ok) throw new Error("native share could not be verified");
|
|
31145
31324
|
const value = await received.data.kv.get("", { binary: true });
|