@tinycloud/cli 1.3.0-beta.33 → 1.3.0-beta.34
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 +220 -132
- package/dist/index.js.map +1 -1
- package/dist/legacy-entry.js +212 -145
- package/dist/legacy-entry.js.map +1 -1
- package/package.json +1 -1
- package/skills/tc-cli/REFERENCE.md +4 -0
package/dist/index.js
CHANGED
|
@@ -303,20 +303,20 @@ var init_formatter = __esm({
|
|
|
303
303
|
function storageRejection(error) {
|
|
304
304
|
let node = error;
|
|
305
305
|
for (let depth = 0; depth < MAX_CAUSE_DEPTH && typeof node === "object" && node !== null; depth += 1) {
|
|
306
|
-
const
|
|
306
|
+
const record2 = node;
|
|
307
307
|
let code4;
|
|
308
|
-
if (
|
|
309
|
-
code4 =
|
|
310
|
-
} else if (
|
|
308
|
+
if (record2.code === "STORAGE_QUOTA_EXCEEDED" || record2.code === "STORAGE_LIMIT_REACHED") {
|
|
309
|
+
code4 = record2.code;
|
|
310
|
+
} else if (record2.code !== void 0) {
|
|
311
311
|
return void 0;
|
|
312
|
-
} else if (isStorageStatus(
|
|
313
|
-
code4 = storageCodeFromText(
|
|
312
|
+
} else if (isStorageStatus(record2)) {
|
|
313
|
+
code4 = storageCodeFromText(record2.message);
|
|
314
314
|
}
|
|
315
315
|
if (code4) {
|
|
316
|
-
const account = accountTotals(
|
|
316
|
+
const account = accountTotals(record2) ?? accountTotals(record2.meta) ?? accountTotals(record2.metadata);
|
|
317
317
|
return account ? { code: code4, account } : { code: code4 };
|
|
318
318
|
}
|
|
319
|
-
node =
|
|
319
|
+
node = record2.cause;
|
|
320
320
|
}
|
|
321
321
|
return void 0;
|
|
322
322
|
}
|
|
@@ -350,11 +350,11 @@ function storageCodeFromText(message) {
|
|
|
350
350
|
}
|
|
351
351
|
return void 0;
|
|
352
352
|
}
|
|
353
|
-
function isStorageStatus(
|
|
354
|
-
const meta = "meta" in
|
|
353
|
+
function isStorageStatus(record2) {
|
|
354
|
+
const meta = "meta" in record2 && typeof record2.meta === "object" && record2.meta !== null ? record2.meta : {};
|
|
355
355
|
const statuses = [
|
|
356
|
-
"status" in
|
|
357
|
-
"statusCode" in
|
|
356
|
+
"status" in record2 ? record2.status : void 0,
|
|
357
|
+
"statusCode" in record2 ? record2.statusCode : void 0,
|
|
358
358
|
"status" in meta ? meta.status : void 0
|
|
359
359
|
];
|
|
360
360
|
return statuses.some((value) => value === 402 || value === 413);
|
|
@@ -3834,30 +3834,30 @@ function parseState(text) {
|
|
|
3834
3834
|
throw gateRefusal("gate_unavailable", "The replica gate file is not valid JSON.");
|
|
3835
3835
|
}
|
|
3836
3836
|
if (typeof raw !== "object" || raw === null) throw gateRefusal("gate_unavailable", "The replica gate file is malformed.");
|
|
3837
|
-
const
|
|
3838
|
-
if (
|
|
3839
|
-
if (typeof
|
|
3837
|
+
const record2 = raw;
|
|
3838
|
+
if (record2.v !== GATE_FILE_VERSION) throw gateRefusal("gate_unavailable", "The replica gate file has an unknown version.");
|
|
3839
|
+
if (typeof record2.incarnation !== "string" || record2.incarnation.length === 0) {
|
|
3840
3840
|
throw gateRefusal("gate_unavailable", "The replica gate file has no incarnation.");
|
|
3841
3841
|
}
|
|
3842
|
-
if (typeof
|
|
3842
|
+
if (typeof record2.salt !== "string" || Buffer.from(record2.salt, "base64url").toString("base64url") !== record2.salt || Buffer.from(record2.salt, "base64url").length < 32) {
|
|
3843
3843
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid salt.");
|
|
3844
3844
|
}
|
|
3845
|
-
if (
|
|
3845
|
+
if (record2.principalHash !== null && (typeof record2.principalHash !== "string" || !/^[0-9a-f]{64}$/.test(record2.principalHash))) {
|
|
3846
3846
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid principal hash.");
|
|
3847
3847
|
}
|
|
3848
|
-
if (typeof
|
|
3848
|
+
if (typeof record2.lifecycleEpoch !== "number" || !Number.isSafeInteger(record2.lifecycleEpoch) || record2.lifecycleEpoch < 0) {
|
|
3849
3849
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid lifecycle epoch.");
|
|
3850
3850
|
}
|
|
3851
|
-
if (
|
|
3851
|
+
if (record2.deniedAt !== null && (typeof record2.deniedAt !== "number" || !Number.isSafeInteger(record2.deniedAt) || record2.deniedAt < 0)) {
|
|
3852
3852
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid deniedAt.");
|
|
3853
3853
|
}
|
|
3854
|
-
if (!Array.isArray(
|
|
3855
|
-
for (const intent of
|
|
3854
|
+
if (!Array.isArray(record2.intents)) throw gateRefusal("gate_unavailable", "The replica gate file has no intents list.");
|
|
3855
|
+
for (const intent of record2.intents) {
|
|
3856
3856
|
if (typeof intent !== "object" || intent === null || typeof intent.id !== "string" || !/^[0-9a-f]{64}$/.test(intent.principalHash) || !Number.isSafeInteger(intent.recordedAt) || intent.recordedAt < 0 || (intent.kind === "pending" ? !/^[0-9a-f]{64}$/.test(intent.identityKeyHash) || intent.id !== `pending:${intent.identityKeyHash}` : intent.kind !== "partition" || typeof intent.partitionId !== "string" || intent.partitionId.length === 0 || intent.id !== intent.partitionId)) {
|
|
3857
3857
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid purge intent.");
|
|
3858
3858
|
}
|
|
3859
3859
|
}
|
|
3860
|
-
const firstInstall =
|
|
3860
|
+
const firstInstall = record2.firstInstall;
|
|
3861
3861
|
if (typeof firstInstall !== "object" || firstInstall === null || Array.isArray(firstInstall)) {
|
|
3862
3862
|
throw gateRefusal("gate_unavailable", "The replica gate file has no valid firstInstall map.");
|
|
3863
3863
|
}
|
|
@@ -3866,7 +3866,7 @@ function parseState(text) {
|
|
|
3866
3866
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid firstInstall entry.");
|
|
3867
3867
|
}
|
|
3868
3868
|
}
|
|
3869
|
-
const grantInstall = Object.prototype.hasOwnProperty.call(
|
|
3869
|
+
const grantInstall = Object.prototype.hasOwnProperty.call(record2, "grantInstall") ? record2.grantInstall : {};
|
|
3870
3870
|
if (typeof grantInstall !== "object" || grantInstall === null || Array.isArray(grantInstall)) {
|
|
3871
3871
|
throw gateRefusal("gate_unavailable", "The replica gate has an invalid grantInstall map.");
|
|
3872
3872
|
}
|
|
@@ -3875,7 +3875,7 @@ function parseState(text) {
|
|
|
3875
3875
|
throw gateRefusal("gate_unavailable", "The replica gate has an invalid grant install time.");
|
|
3876
3876
|
}
|
|
3877
3877
|
}
|
|
3878
|
-
const pendingGenerations =
|
|
3878
|
+
const pendingGenerations = record2.pendingGenerations;
|
|
3879
3879
|
if (typeof pendingGenerations !== "object" || pendingGenerations === null || Array.isArray(pendingGenerations)) {
|
|
3880
3880
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid pending generation map.");
|
|
3881
3881
|
}
|
|
@@ -3884,18 +3884,18 @@ function parseState(text) {
|
|
|
3884
3884
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid pending generation.");
|
|
3885
3885
|
}
|
|
3886
3886
|
}
|
|
3887
|
-
const eraseDeferred = Object.prototype.hasOwnProperty.call(
|
|
3888
|
-
const deferredPrincipalHash = Object.prototype.hasOwnProperty.call(
|
|
3889
|
-
if (typeof eraseDeferred !== "boolean" || deferredPrincipalHash !== null && (typeof deferredPrincipalHash !== "string" || !/^[0-9a-f]{64}$/.test(deferredPrincipalHash)) || eraseDeferred && (
|
|
3887
|
+
const eraseDeferred = Object.prototype.hasOwnProperty.call(record2, "eraseDeferred") ? record2.eraseDeferred : false;
|
|
3888
|
+
const deferredPrincipalHash = Object.prototype.hasOwnProperty.call(record2, "deferredPrincipalHash") ? record2.deferredPrincipalHash : null;
|
|
3889
|
+
if (typeof eraseDeferred !== "boolean" || deferredPrincipalHash !== null && (typeof deferredPrincipalHash !== "string" || !/^[0-9a-f]{64}$/.test(deferredPrincipalHash)) || eraseDeferred && (record2.principalHash !== null || deferredPrincipalHash === null)) {
|
|
3890
3890
|
throw gateRefusal("gate_unavailable", "The replica gate has an invalid deferred erase state.");
|
|
3891
3891
|
}
|
|
3892
3892
|
return {
|
|
3893
|
-
incarnation:
|
|
3894
|
-
salt:
|
|
3895
|
-
principalHash:
|
|
3896
|
-
lifecycleEpoch:
|
|
3897
|
-
deniedAt:
|
|
3898
|
-
intents:
|
|
3893
|
+
incarnation: record2.incarnation,
|
|
3894
|
+
salt: record2.salt,
|
|
3895
|
+
principalHash: record2.principalHash,
|
|
3896
|
+
lifecycleEpoch: record2.lifecycleEpoch,
|
|
3897
|
+
deniedAt: record2.deniedAt,
|
|
3898
|
+
intents: record2.intents,
|
|
3899
3899
|
firstInstall,
|
|
3900
3900
|
grantInstall,
|
|
3901
3901
|
pendingGenerations,
|
|
@@ -3917,17 +3917,17 @@ async function readStoredState(profileDir) {
|
|
|
3917
3917
|
return parseState(text);
|
|
3918
3918
|
}
|
|
3919
3919
|
async function readDenyFloor(profileDir) {
|
|
3920
|
-
let
|
|
3920
|
+
let record2;
|
|
3921
3921
|
try {
|
|
3922
|
-
|
|
3922
|
+
record2 = JSON.parse(await readFile3(join6(profileDir, DENY_FLOOR_FILE), "utf8"));
|
|
3923
3923
|
} catch (error) {
|
|
3924
3924
|
if (isNotFound(error)) return void 0;
|
|
3925
3925
|
throw gateRefusal("gate_unavailable", "The replica deny floor cannot be read.");
|
|
3926
3926
|
}
|
|
3927
|
-
if (typeof
|
|
3927
|
+
if (typeof record2 !== "object" || record2 === null || Array.isArray(record2) || Object.keys(record2).length !== 2 || !("epoch" in record2) || !("deniedAt" in record2) || !Number.isSafeInteger(record2.epoch) || record2.epoch < 1 || !Number.isSafeInteger(record2.deniedAt) || record2.deniedAt < 0) {
|
|
3928
3928
|
throw gateRefusal("gate_unavailable", "The replica deny floor is malformed.");
|
|
3929
3929
|
}
|
|
3930
|
-
return { epoch:
|
|
3930
|
+
return { epoch: record2.epoch, deniedAt: record2.deniedAt };
|
|
3931
3931
|
}
|
|
3932
3932
|
function behindFloor(state2, floor) {
|
|
3933
3933
|
return state2.lifecycleEpoch < floor.epoch || state2.deniedAt === null || state2.deniedAt < floor.deniedAt;
|
|
@@ -13204,15 +13204,15 @@ function parseArtifactManifest(bytes) {
|
|
|
13204
13204
|
throw new ArtifactError("corrupt", "artifact manifest is malformed");
|
|
13205
13205
|
};
|
|
13206
13206
|
if (value === null || typeof value !== "object" || Array.isArray(value)) return fail();
|
|
13207
|
-
const
|
|
13207
|
+
const record2 = value;
|
|
13208
13208
|
const allowed = ["v", "files", "createdAt", "parent", "note"];
|
|
13209
|
-
if (Object.keys(
|
|
13210
|
-
if (!Array.isArray(
|
|
13211
|
-
if (typeof
|
|
13212
|
-
if (
|
|
13213
|
-
if (
|
|
13209
|
+
if (Object.keys(record2).some((key) => !allowed.includes(key)) || record2.v !== ARTIFACT_MANIFEST_VERSION) return fail();
|
|
13210
|
+
if (!Array.isArray(record2.files) || record2.files.length === 0) return fail();
|
|
13211
|
+
if (typeof record2.createdAt !== "string" || Number.isNaN(Date.parse(record2.createdAt))) return fail();
|
|
13212
|
+
if (record2.parent !== null && (typeof record2.parent !== "number" || !Number.isSafeInteger(record2.parent) || record2.parent < 1)) return fail();
|
|
13213
|
+
if (record2.note !== void 0 && (typeof record2.note !== "string" || record2.note.length > 1024)) return fail();
|
|
13214
13214
|
const seen = /* @__PURE__ */ new Set();
|
|
13215
|
-
const files =
|
|
13215
|
+
const files = record2.files.map((entry) => {
|
|
13216
13216
|
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) return fail();
|
|
13217
13217
|
const file = entry;
|
|
13218
13218
|
if (Object.keys(file).some((key) => !["path", "sha256", "bytes"].includes(key))) return fail();
|
|
@@ -13230,9 +13230,9 @@ function parseArtifactManifest(bytes) {
|
|
|
13230
13230
|
return {
|
|
13231
13231
|
v: ARTIFACT_MANIFEST_VERSION,
|
|
13232
13232
|
files,
|
|
13233
|
-
createdAt:
|
|
13234
|
-
parent:
|
|
13235
|
-
...
|
|
13233
|
+
createdAt: record2.createdAt,
|
|
13234
|
+
parent: record2.parent,
|
|
13235
|
+
...record2.note === void 0 ? {} : { note: record2.note }
|
|
13236
13236
|
};
|
|
13237
13237
|
}
|
|
13238
13238
|
async function listArtifactVersions(store, artifactId) {
|
|
@@ -19054,21 +19054,21 @@ async function parseSealedInlineShareUrl(url, options = {}) {
|
|
|
19054
19054
|
throw new TypeError("sealed inline payload is not valid JSON");
|
|
19055
19055
|
}
|
|
19056
19056
|
if (typeof value !== "object" || value === null || Array.isArray(value) || canonicalize2(value) !== payloadText) throw new TypeError("sealed inline payload is not canonical JSON");
|
|
19057
|
-
const
|
|
19058
|
-
if (Object.keys(
|
|
19057
|
+
const record2 = value;
|
|
19058
|
+
if (Object.keys(record2).length !== 4 || record2.v !== 2 || typeof record2.c !== "string" || typeof record2.cid !== "string" || typeof record2.k !== "string") throw new TypeError("sealed inline payload has invalid fields");
|
|
19059
19059
|
let ciphertext;
|
|
19060
19060
|
let key32;
|
|
19061
19061
|
try {
|
|
19062
|
-
ciphertext = fromBase64Url2(
|
|
19063
|
-
key32 = fromBase64Url2(
|
|
19062
|
+
ciphertext = fromBase64Url2(record2.c);
|
|
19063
|
+
key32 = fromBase64Url2(record2.k);
|
|
19064
19064
|
} catch {
|
|
19065
19065
|
throw new TypeError("sealed inline payload has invalid base64url material");
|
|
19066
19066
|
}
|
|
19067
19067
|
if (ciphertext.byteLength === 0 || ciphertext.byteLength > MAX_INLINE_BYTES2) throw new TypeError("sealed inline ciphertext is outside the allowed size");
|
|
19068
19068
|
if (key32.byteLength !== KEY_LENGTH2) throw new TypeError("sealed inline key must be 32 bytes");
|
|
19069
|
-
assertCanonicalCid(
|
|
19070
|
-
if (await computeCid(ciphertext) !==
|
|
19071
|
-
return { kind: "inline", ciphertextCid:
|
|
19069
|
+
assertCanonicalCid(record2.cid);
|
|
19070
|
+
if (await computeCid(ciphertext) !== record2.cid) throw new TypeError("sealed inline ciphertext does not match its CID");
|
|
19071
|
+
return { kind: "inline", ciphertextCid: record2.cid, ciphertext, key32 };
|
|
19072
19072
|
}
|
|
19073
19073
|
var ARTIFACT_ROOT2 = "artifacts";
|
|
19074
19074
|
function parseArtifactVersionPath2(path) {
|
|
@@ -20539,16 +20539,16 @@ var ShareNotifyError = class extends Error {
|
|
|
20539
20539
|
}
|
|
20540
20540
|
code = "delivery-failed";
|
|
20541
20541
|
};
|
|
20542
|
-
function recipientMatchesShareRecord(
|
|
20543
|
-
const matcher =
|
|
20542
|
+
function recipientMatchesShareRecord(record2, recipient) {
|
|
20543
|
+
const matcher = record2.recipientMatcher;
|
|
20544
20544
|
const mailbox = canonicalMailbox(recipient);
|
|
20545
20545
|
if (mailbox === void 0) return false;
|
|
20546
20546
|
if (matcher.kind === "exactEmail") return canonicalMailbox(matcher.value)?.email === mailbox.email;
|
|
20547
20547
|
if (matcher.kind === "emailDomain") return mailbox.domain === matcher.value;
|
|
20548
20548
|
return false;
|
|
20549
20549
|
}
|
|
20550
|
-
function shareDeliveryWindowExpiresAt(
|
|
20551
|
-
const expiresAt = Math.min(Date.parse(
|
|
20550
|
+
function shareDeliveryWindowExpiresAt(record2) {
|
|
20551
|
+
const expiresAt = Math.min(Date.parse(record2.expiresAt), Date.parse(record2.registeredAt) + 5 * 60 * 1e3);
|
|
20552
20552
|
if (!Number.isFinite(expiresAt)) throw new ShareNotifyError("share delivery history has invalid timestamps");
|
|
20553
20553
|
return expiresAt;
|
|
20554
20554
|
}
|
|
@@ -20736,17 +20736,17 @@ async function deliverCredentialInvitation(input) {
|
|
|
20736
20736
|
}
|
|
20737
20737
|
return { status: "accepted" };
|
|
20738
20738
|
}
|
|
20739
|
-
function targetKind2(
|
|
20740
|
-
if (
|
|
20741
|
-
return
|
|
20739
|
+
function targetKind2(record2) {
|
|
20740
|
+
if (record2.targetKind !== void 0) return record2.targetKind;
|
|
20741
|
+
return record2.recipientMatcher.kind === "exactEmail" ? "email" : record2.recipientMatcher.kind === "emailDomain" ? "emailDomain" : record2.recipientMatcher.kind === "recipientDid" ? "recipientDid" : "bearer";
|
|
20742
20742
|
}
|
|
20743
|
-
function policyNodeAudience(
|
|
20744
|
-
const envelope =
|
|
20745
|
-
if (typeof envelope !== "object" || envelope === null || Array.isArray(envelope)) return
|
|
20743
|
+
function policyNodeAudience(record2) {
|
|
20744
|
+
const envelope = record2.deliveryMaterial?.envelope;
|
|
20745
|
+
if (typeof envelope !== "object" || envelope === null || Array.isArray(envelope)) return record2.target.nodeAudience;
|
|
20746
20746
|
const binding = envelope.attestedEnforcerBinding;
|
|
20747
|
-
if (typeof binding !== "object" || binding === null || Array.isArray(binding)) return
|
|
20747
|
+
if (typeof binding !== "object" || binding === null || Array.isArray(binding)) return record2.target.nodeAudience;
|
|
20748
20748
|
const nodeAudience = binding.nodeAudience;
|
|
20749
|
-
return typeof nodeAudience === "string" ? nodeAudience :
|
|
20749
|
+
return typeof nodeAudience === "string" ? nodeAudience : record2.target.nodeAudience;
|
|
20750
20750
|
}
|
|
20751
20751
|
async function revokeShare(input) {
|
|
20752
20752
|
const target = targetKind2(input.record);
|
|
@@ -20770,7 +20770,7 @@ async function revokeShare(input) {
|
|
|
20770
20770
|
}
|
|
20771
20771
|
let revokedAt = input.record.revokedAt ?? (input.now?.() ?? /* @__PURE__ */ new Date()).toISOString();
|
|
20772
20772
|
if (input.records?.update !== void 0) {
|
|
20773
|
-
const updated = await input.records.update(input.record.shareId, (
|
|
20773
|
+
const updated = await input.records.update(input.record.shareId, (record2) => ({ ...record2, revokedAt: record2.revokedAt ?? revokedAt }));
|
|
20774
20774
|
revokedAt = updated?.revokedAt ?? revokedAt;
|
|
20775
20775
|
} else if (input.records !== void 0) {
|
|
20776
20776
|
const latest = await input.records.get(input.record.shareId);
|
|
@@ -20779,26 +20779,26 @@ async function revokeShare(input) {
|
|
|
20779
20779
|
}
|
|
20780
20780
|
return { state: "revoked", target, delegationCid, revokedAt };
|
|
20781
20781
|
}
|
|
20782
|
-
function redactRecord(
|
|
20783
|
-
const matcher =
|
|
20784
|
-
const revealedLink = revealLink ? link3 ??
|
|
20782
|
+
function redactRecord(record2, revealLink, link3) {
|
|
20783
|
+
const matcher = record2.recipientMatcher;
|
|
20784
|
+
const revealedLink = revealLink ? link3 ?? record2.link : void 0;
|
|
20785
20785
|
return {
|
|
20786
|
-
shareId:
|
|
20786
|
+
shareId: record2.shareId,
|
|
20787
20787
|
target: matcher.kind === "exactEmail" ? "email" : matcher.kind === "emailDomain" ? "email-domain" : matcher.kind === "recipientDid" ? "recipient-did" : "bearer",
|
|
20788
20788
|
...matcher.kind === "exactEmail" ? { recipient: matcher.value } : matcher.kind === "emailDomain" ? { recipient: `*@${matcher.value}` } : matcher.kind === "recipientDid" ? { recipient: matcher.value } : {},
|
|
20789
|
-
expiresAt:
|
|
20790
|
-
revoked:
|
|
20789
|
+
expiresAt: record2.expiresAt,
|
|
20790
|
+
revoked: record2.revokedAt !== void 0,
|
|
20791
20791
|
...revealedLink === void 0 ? {} : { link: revealedLink }
|
|
20792
20792
|
};
|
|
20793
20793
|
}
|
|
20794
20794
|
async function listShares(storage) {
|
|
20795
20795
|
const records = await storage.list();
|
|
20796
|
-
return records.map((
|
|
20796
|
+
return records.map((record2) => redactRecord(record2, false));
|
|
20797
20797
|
}
|
|
20798
20798
|
async function showShare(input) {
|
|
20799
|
-
const
|
|
20800
|
-
if (
|
|
20801
|
-
return redactRecord(
|
|
20799
|
+
const record2 = await input.storage.get(input.shareId);
|
|
20800
|
+
if (record2 === void 0) throw new Error("share not found");
|
|
20801
|
+
return redactRecord(record2, input.revealLink === true, input.link);
|
|
20802
20802
|
}
|
|
20803
20803
|
var SHARE_V2_PROTOCOL = Object.freeze({
|
|
20804
20804
|
challengeDomain: "xyz.tinycloud.share/policy-challenge/v2\0",
|
|
@@ -26306,6 +26306,60 @@ function parseDuration(input) {
|
|
|
26306
26306
|
// src/commands/share.ts
|
|
26307
26307
|
init_errors();
|
|
26308
26308
|
|
|
26309
|
+
// src/share/failure-class.ts
|
|
26310
|
+
init_constants();
|
|
26311
|
+
import { authorizationVerdictOf as authorizationVerdictOf2 } from "@tinycloud/sdk-core";
|
|
26312
|
+
var NETWORK_FAILURE = /\b(?:fetch failed|ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|UND_ERR_[A-Z_]+)\b|network ?error|failed to fetch/i;
|
|
26313
|
+
function record(value) {
|
|
26314
|
+
return typeof value === "object" && value !== null ? value : void 0;
|
|
26315
|
+
}
|
|
26316
|
+
function httpStatus(value) {
|
|
26317
|
+
const status = typeof value === "number" && Number.isInteger(value) && value >= 400 && value <= 599 ? value : void 0;
|
|
26318
|
+
return status;
|
|
26319
|
+
}
|
|
26320
|
+
function statusOf(error, depth = 0) {
|
|
26321
|
+
const fields = record(error);
|
|
26322
|
+
if (fields === void 0) return void 0;
|
|
26323
|
+
const direct = httpStatus(fields.status) ?? httpStatus(fields.statusCode) ?? httpStatus(record(fields.meta)?.status);
|
|
26324
|
+
return direct ?? (depth === 0 ? statusOf(fields.cause, 1) : void 0);
|
|
26325
|
+
}
|
|
26326
|
+
function codeOf(error) {
|
|
26327
|
+
const code4 = record(error)?.code;
|
|
26328
|
+
return typeof code4 === "string" && /^[A-Z][A-Z0-9_]{2,63}$/.test(code4) ? code4 : void 0;
|
|
26329
|
+
}
|
|
26330
|
+
function classifyShareFailure(error, loginHint) {
|
|
26331
|
+
const status = statusOf(error);
|
|
26332
|
+
const verdict = authorizationVerdictOf2(error);
|
|
26333
|
+
const message = error instanceof Error ? error.message : "";
|
|
26334
|
+
const code4 = codeOf(error);
|
|
26335
|
+
const detail = (text) => {
|
|
26336
|
+
const parts = [status === void 0 ? void 0 : `HTTP ${status}`, code4].filter((part) => part !== void 0);
|
|
26337
|
+
return parts.length === 0 ? text : `${text} (${parts.join(", ")})`;
|
|
26338
|
+
};
|
|
26339
|
+
if (verdict === "unauthenticated" || status === 401) {
|
|
26340
|
+
return { code: "AUTH_REQUIRED", exitCode: ExitCode.AUTH_REQUIRED, reason: detail(`the node did not accept this session; sign in again with ${loginHint}`) };
|
|
26341
|
+
}
|
|
26342
|
+
if (verdict === "forbidden" || status === 403) {
|
|
26343
|
+
return { code: "PERMISSION_DENIED", exitCode: ExitCode.PERMISSION_DENIED, reason: detail("the node refused this session's authority for the request") };
|
|
26344
|
+
}
|
|
26345
|
+
if (status === 404) {
|
|
26346
|
+
return { code: "NOT_FOUND", exitCode: ExitCode.NOT_FOUND, reason: detail("the node could not find what the request names") };
|
|
26347
|
+
}
|
|
26348
|
+
if (status !== void 0 && (status >= 500 || status === 408 || status === 429)) {
|
|
26349
|
+
return { code: "NODE_UNAVAILABLE", exitCode: ExitCode.NODE_ERROR, reason: detail("the node could not complete the request; try again shortly") };
|
|
26350
|
+
}
|
|
26351
|
+
if (status === 400 || status === 422) {
|
|
26352
|
+
return { code: "INVALID_ARGUMENT", exitCode: ExitCode.USAGE_ERROR, reason: detail("the node rejected the request as invalid") };
|
|
26353
|
+
}
|
|
26354
|
+
if (status !== void 0) {
|
|
26355
|
+
return { code: "NODE_REJECTED", exitCode: ExitCode.ERROR, reason: detail("the node rejected the request") };
|
|
26356
|
+
}
|
|
26357
|
+
if (NETWORK_FAILURE.test(message) || typeof record(error)?.code === "string" && NETWORK_FAILURE.test(String(record(error)?.code))) {
|
|
26358
|
+
return { code: "NETWORK_ERROR", exitCode: ExitCode.NETWORK_ERROR, reason: "the TinyCloud node could not be reached; check the connection and retry" };
|
|
26359
|
+
}
|
|
26360
|
+
return void 0;
|
|
26361
|
+
}
|
|
26362
|
+
|
|
26309
26363
|
// src/share/output.ts
|
|
26310
26364
|
function writeJson2(value) {
|
|
26311
26365
|
process.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
@@ -26473,8 +26527,8 @@ async function writeShareOutput(directory, filename, bytes, force) {
|
|
|
26473
26527
|
|
|
26474
26528
|
// src/share/errors.ts
|
|
26475
26529
|
var SharePublishAuthorityError = class extends Error {
|
|
26476
|
-
constructor(failure) {
|
|
26477
|
-
super(failure.kind);
|
|
26530
|
+
constructor(failure, options) {
|
|
26531
|
+
super(failure.kind, options);
|
|
26478
26532
|
this.failure = failure;
|
|
26479
26533
|
this.name = "SharePublishAuthorityError";
|
|
26480
26534
|
}
|
|
@@ -26592,6 +26646,17 @@ function shareCliError(error, operation = "publish") {
|
|
|
26592
26646
|
if (failure.kind === "storage-full") {
|
|
26593
26647
|
return storageFullError(failure);
|
|
26594
26648
|
}
|
|
26649
|
+
if (failure.kind === "space-not-ready") {
|
|
26650
|
+
return Object.assign(
|
|
26651
|
+
new CLIError(
|
|
26652
|
+
"SPACE_NOT_READY",
|
|
26653
|
+
"Your TinyCloud space isn't ready for this yet (SPACE_NOT_READY). This is a known node problem being fixed: retry after the node update; contact support with this code if it persists.",
|
|
26654
|
+
4,
|
|
26655
|
+
{ hint: "Nothing was shared, and repeating the command is safe. Retries keep failing until the node is updated." }
|
|
26656
|
+
),
|
|
26657
|
+
{ cause: error.cause }
|
|
26658
|
+
);
|
|
26659
|
+
}
|
|
26595
26660
|
if (failure.kind === "upload-failed") {
|
|
26596
26661
|
return new CLIError("UPLOAD_FAILED", "share source upload failed; nothing was shared", 4);
|
|
26597
26662
|
}
|
|
@@ -26625,8 +26690,10 @@ function shareCliError(error, operation = "publish") {
|
|
|
26625
26690
|
};
|
|
26626
26691
|
if (nodeCode === "ENOENT") return new CLIError("INVALID_ARGUMENT", "share input was not found", 2);
|
|
26627
26692
|
if (nodeCode === "EISDIR") return new CLIError("INVALID_ARGUMENT", "share input must be a Markdown file", 2);
|
|
26628
|
-
if (error instanceof TypeError) return new CLIError("INVALID_ARGUMENT", "share input is invalid", 2);
|
|
26629
26693
|
const mapped = typeof nodeCode === "string" && known[nodeCode] !== void 0 ? known[nodeCode] : known[message];
|
|
26694
|
+
const classified = mapped === void 0 ? classifyShareFailure(error, `\`${CLI_NAME12} auth login\``) : void 0;
|
|
26695
|
+
if (classified !== void 0) return Object.assign(new CLIError(classified.code, classified.reason, classified.exitCode), { cause: error });
|
|
26696
|
+
if (error instanceof TypeError) return new CLIError("INVALID_ARGUMENT", "share input is invalid", 2);
|
|
26630
26697
|
return new CLIError(mapped?.code ?? "INVALID_ARGUMENT", mapped ? mapped.code : "share operation failed", mapped?.exit ?? 2);
|
|
26631
26698
|
}
|
|
26632
26699
|
function inputUrl(value, stdin) {
|
|
@@ -26654,24 +26721,24 @@ function expires(value) {
|
|
|
26654
26721
|
}
|
|
26655
26722
|
}
|
|
26656
26723
|
async function rememberPublishedShare(result) {
|
|
26657
|
-
const
|
|
26658
|
-
if (shareServices.records === void 0) return { record, recorded: false };
|
|
26724
|
+
const record2 = historyRecordForPublishedShare(result);
|
|
26725
|
+
if (shareServices.records === void 0) return { record: record2, recorded: false };
|
|
26659
26726
|
try {
|
|
26660
|
-
await shareServices.records.put(
|
|
26661
|
-
return { record, recorded: true };
|
|
26727
|
+
await shareServices.records.put(record2);
|
|
26728
|
+
return { record: record2, recorded: true };
|
|
26662
26729
|
} catch {
|
|
26663
26730
|
process.stderr.write("Warning: share was published but not recorded in sender history; future share list, share notify, and share revoke by ID will not find it.\n");
|
|
26664
|
-
return { record, recorded: false };
|
|
26731
|
+
return { record: record2, recorded: false };
|
|
26665
26732
|
}
|
|
26666
26733
|
}
|
|
26667
|
-
async function notifyRecordedShare(
|
|
26668
|
-
const result = await notifyShare({ shareId:
|
|
26734
|
+
async function notifyRecordedShare(record2, recipient, adapter, storage) {
|
|
26735
|
+
const result = await notifyShare({ shareId: record2.shareId, recipient, record: record2, adapter, checkDeliveryWindow: true });
|
|
26669
26736
|
if (result.state !== "partial-failure" && storage !== void 0) {
|
|
26670
26737
|
const mailbox = canonicalMailbox2(recipient).email;
|
|
26671
|
-
if (!
|
|
26738
|
+
if (!record2.deliveredRecipients?.includes(mailbox)) {
|
|
26672
26739
|
try {
|
|
26673
26740
|
if (storage.update === void 0) throw new Error("atomic sender history update is unavailable");
|
|
26674
|
-
const updated = await storage.update(
|
|
26741
|
+
const updated = await storage.update(record2.shareId, (current) => ({
|
|
26675
26742
|
...current,
|
|
26676
26743
|
deliveredRecipients: current.deliveredRecipients?.includes(mailbox) ? current.deliveredRecipients : [...current.deliveredRecipients ?? [], mailbox]
|
|
26677
26744
|
}));
|
|
@@ -26766,11 +26833,11 @@ function registerShareCommand(program2) {
|
|
|
26766
26833
|
}
|
|
26767
26834
|
throw new CLIError(result.method === "openkey-device" ? "DEVICE_AUTH_REQUIRED" : "CLAIM_REQUIRED", "recipient authorization is required; continue through the configured authority adapter", 6);
|
|
26768
26835
|
}
|
|
26769
|
-
const { record, recorded } = await rememberPublishedShare(result);
|
|
26836
|
+
const { record: record2, recorded } = await rememberPublishedShare(result);
|
|
26770
26837
|
let notification;
|
|
26771
26838
|
if (notifyRecipient !== void 0) {
|
|
26772
26839
|
if (shareServices.delivery === void 0) throw new CLIError("AUTH_REQUIRED", "delivery authority is not configured", 3);
|
|
26773
|
-
notification = await notifyRecordedShare(
|
|
26840
|
+
notification = await notifyRecordedShare(record2, notifyRecipient, shareServices.delivery, recorded ? shareServices.records : void 0);
|
|
26774
26841
|
if (notification.state === "partial-failure") process.exitCode = 9;
|
|
26775
26842
|
if (notification.reason === "delivery-window-expired") process.stderr.write(NOTIFY_WINDOW_MESSAGE);
|
|
26776
26843
|
}
|
|
@@ -26803,11 +26870,11 @@ function registerShareCommand(program2) {
|
|
|
26803
26870
|
if (shareServices.artifactStore === void 0) throw new CLIError("AUTH_REQUIRED", "artifact storage is not configured", 3);
|
|
26804
26871
|
const versions = await listArtifactVersions(await shareServices.artifactStore(), id);
|
|
26805
26872
|
const pinned = /* @__PURE__ */ new Map();
|
|
26806
|
-
for (const
|
|
26807
|
-
const path = parseArtifactVersionPath(
|
|
26873
|
+
for (const record2 of await shareServices.records?.list() ?? []) {
|
|
26874
|
+
const path = parseArtifactVersionPath(record2.resource.path);
|
|
26808
26875
|
if (path === void 0 || path.artifactId !== id) continue;
|
|
26809
26876
|
const shares = pinned.get(path.version) ?? [];
|
|
26810
|
-
shares.push({ shareId:
|
|
26877
|
+
shares.push({ shareId: record2.shareId, target: record2.targetKind ?? record2.recipientMatcher.kind, expiresAt: record2.expiresAt, ...record2.revokedAt === void 0 ? {} : { revokedAt: record2.revokedAt } });
|
|
26811
26878
|
pinned.set(path.version, shares);
|
|
26812
26879
|
}
|
|
26813
26880
|
const view = versions.map((version2) => ({
|
|
@@ -26907,19 +26974,19 @@ function registerShareCommand(program2) {
|
|
|
26907
26974
|
const json = jsonOutput(options, command);
|
|
26908
26975
|
if (shareServices.delivery === void 0) throw new CLIError("AUTH_REQUIRED", "delivery authority is not configured", 3);
|
|
26909
26976
|
if (shareServices.records === void 0) throw new CLIError("AUTH_REQUIRED", "sender history storage is not configured", 3);
|
|
26910
|
-
const
|
|
26911
|
-
if (
|
|
26912
|
-
if (!
|
|
26977
|
+
const record2 = await shareServices.records.get(id);
|
|
26978
|
+
if (record2 === void 0) throw new CLIError("NOT_FOUND", "share not found", 4);
|
|
26979
|
+
if (!record2.actions.includes("tinycloud.kv/get")) {
|
|
26913
26980
|
throw new CLIError("INVALID_ARGUMENT", "share notify requires a stored share with the read action; no invitation was sent", 2);
|
|
26914
26981
|
}
|
|
26915
26982
|
const mailbox = canonicalMailbox2(options.to);
|
|
26916
26983
|
if (mailbox === void 0) throw new ShareNotifyError("recipient is invalid");
|
|
26917
|
-
if (!recipientMatchesShareRecord(
|
|
26918
|
-
if (
|
|
26984
|
+
if (!recipientMatchesShareRecord(record2, mailbox.email)) throw new ShareNotifyError("recipient does not match the stored share target");
|
|
26985
|
+
if (record2.recipientMatcher.kind === "emailDomain" && shareDeliveryWindowExpiresAt(record2) > Date.now()) {
|
|
26919
26986
|
if (shareServices.assertDomainDelivery === void 0) throw new CLIError("UNAVAILABLE", "could not verify TinyCloud node 1.17.3 domain delivery support; no invitation was sent", 4);
|
|
26920
26987
|
await shareServices.assertDomainDelivery();
|
|
26921
26988
|
}
|
|
26922
|
-
const result = await notifyRecordedShare(
|
|
26989
|
+
const result = await notifyRecordedShare(record2, options.to, shareServices.delivery, shareServices.records);
|
|
26923
26990
|
if (json) writeJson2(result);
|
|
26924
26991
|
else process.stdout.write(`${result.state}
|
|
26925
26992
|
`);
|
|
@@ -26933,9 +27000,9 @@ function registerShareCommand(program2) {
|
|
|
26933
27000
|
try {
|
|
26934
27001
|
const json = jsonOutput(options, command);
|
|
26935
27002
|
if (shareServices.records === void 0) throw new CLIError("AUTH_REQUIRED", "sender history storage is not configured", 3);
|
|
26936
|
-
const
|
|
26937
|
-
if (
|
|
26938
|
-
const result = await revokeShare({ record, records: shareServices.records, adapter: shareServices.revocation, scope: options.ancestor ? "ancestor" : "direct" });
|
|
27003
|
+
const record2 = shareServices.getRecord ? await shareServices.getRecord(id) : await shareServices.records.get(id);
|
|
27004
|
+
if (record2 === void 0) throw new CLIError("NOT_FOUND", "share not found", 4);
|
|
27005
|
+
const result = await revokeShare({ record: record2, records: shareServices.records, adapter: shareServices.revocation, scope: options.ancestor ? "ancestor" : "direct" });
|
|
26939
27006
|
if (result.state === "unsupported") {
|
|
26940
27007
|
throw new CLIError("UNSUPPORTED_TARGET", result.reason, 2);
|
|
26941
27008
|
}
|
|
@@ -26986,6 +27053,25 @@ function kvArtifactStore(kv) {
|
|
|
26986
27053
|
};
|
|
26987
27054
|
}
|
|
26988
27055
|
|
|
27056
|
+
// src/share/space-not-ready.ts
|
|
27057
|
+
function isSpaceNotFound(error) {
|
|
27058
|
+
if (typeof error !== "object" || error === null) return false;
|
|
27059
|
+
const message = "message" in error && typeof error.message === "string" ? error.message : "";
|
|
27060
|
+
if (!/space not found/i.test(message)) return false;
|
|
27061
|
+
const meta = "meta" in error && typeof error.meta === "object" && error.meta !== null ? error.meta : void 0;
|
|
27062
|
+
const status = meta !== void 0 && "status" in meta ? meta.status : void 0;
|
|
27063
|
+
return status === 404 || /\b404\b/.test(message);
|
|
27064
|
+
}
|
|
27065
|
+
function spaceNotReadyFailure(cause) {
|
|
27066
|
+
return new SharePublishAuthorityError({ kind: "space-not-ready" }, { cause });
|
|
27067
|
+
}
|
|
27068
|
+
function failIfSpaceNotReady(result) {
|
|
27069
|
+
if (!result.ok && isSpaceNotFound(result.error)) throw spaceNotReadyFailure(result.error);
|
|
27070
|
+
}
|
|
27071
|
+
function artifactSpaceNotReady(error) {
|
|
27072
|
+
return error instanceof ArtifactError && isSpaceNotFound(error.cause) ? spaceNotReadyFailure(error.cause) : error;
|
|
27073
|
+
}
|
|
27074
|
+
|
|
26989
27075
|
// src/share/adapters.ts
|
|
26990
27076
|
init_storage();
|
|
26991
27077
|
init_profiles();
|
|
@@ -27065,7 +27151,7 @@ async function storeArtifactVersion(kv, version2, authority) {
|
|
|
27065
27151
|
try {
|
|
27066
27152
|
return await publishArtifactVersion(kvArtifactStore(kv), version2);
|
|
27067
27153
|
} catch (error) {
|
|
27068
|
-
throw scopeDeniedFromArtifactError(error, "KV upload", authority) ?? error;
|
|
27154
|
+
throw scopeDeniedFromArtifactError(error, "KV upload", authority) ?? artifactSpaceNotReady(error);
|
|
27069
27155
|
}
|
|
27070
27156
|
}
|
|
27071
27157
|
function createEncryptedSessionHistory() {
|
|
@@ -27078,8 +27164,8 @@ function createEncryptedSessionHistory() {
|
|
|
27078
27164
|
};
|
|
27079
27165
|
let keyPromise;
|
|
27080
27166
|
const key = async () => keyPromise ??= crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
27081
|
-
const encode6 = async (
|
|
27082
|
-
const secret = new TextEncoder().encode(JSON.stringify(
|
|
27167
|
+
const encode6 = async (record2) => {
|
|
27168
|
+
const secret = new TextEncoder().encode(JSON.stringify(record2));
|
|
27083
27169
|
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
27084
27170
|
const encrypted = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv }, await key(), secret));
|
|
27085
27171
|
const value = new Uint8Array(iv.length + encrypted.length);
|
|
@@ -27089,9 +27175,9 @@ function createEncryptedSessionHistory() {
|
|
|
27089
27175
|
};
|
|
27090
27176
|
const decode10 = async (value) => JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await crypto.subtle.decrypt({ name: "AES-GCM", iv: value.slice(0, 12) }, await key(), value.slice(12))));
|
|
27091
27177
|
return {
|
|
27092
|
-
async put(
|
|
27178
|
+
async put(record2) {
|
|
27093
27179
|
return serial(async () => {
|
|
27094
|
-
records.set(
|
|
27180
|
+
records.set(record2.shareId, await encode6(record2));
|
|
27095
27181
|
});
|
|
27096
27182
|
},
|
|
27097
27183
|
async update(shareId, change) {
|
|
@@ -27257,19 +27343,19 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
|
|
|
27257
27343
|
throw new ShareHistoryRetryError(profile);
|
|
27258
27344
|
});
|
|
27259
27345
|
return {
|
|
27260
|
-
async put(
|
|
27346
|
+
async put(record2) {
|
|
27261
27347
|
return locked(async (profile, ready) => {
|
|
27262
27348
|
const values = await read4(profile, ready);
|
|
27263
|
-
const index = values.findIndex((value) => value.shareId ===
|
|
27264
|
-
if (index >= 0) values[index] =
|
|
27265
|
-
else values.push(
|
|
27349
|
+
const index = values.findIndex((value) => value.shareId === record2.shareId);
|
|
27350
|
+
if (index >= 0) values[index] = record2;
|
|
27351
|
+
else values.push(record2);
|
|
27266
27352
|
await write(profile, values, ready);
|
|
27267
27353
|
}, true);
|
|
27268
27354
|
},
|
|
27269
27355
|
async update(shareId, change) {
|
|
27270
27356
|
return locked(async (profile, ready) => {
|
|
27271
27357
|
const values = await read4(profile, ready);
|
|
27272
|
-
const index = values.findIndex((
|
|
27358
|
+
const index = values.findIndex((record2) => record2.shareId === shareId);
|
|
27273
27359
|
if (index < 0) return void 0;
|
|
27274
27360
|
const updated = await change(values[index]);
|
|
27275
27361
|
values[index] = updated;
|
|
@@ -27281,11 +27367,11 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
|
|
|
27281
27367
|
return locked((profile, ready) => read4(profile, ready));
|
|
27282
27368
|
},
|
|
27283
27369
|
async get(shareId) {
|
|
27284
|
-
return locked(async (profile, ready) => (await read4(profile, ready)).find((
|
|
27370
|
+
return locked(async (profile, ready) => (await read4(profile, ready)).find((record2) => record2.shareId === shareId));
|
|
27285
27371
|
},
|
|
27286
27372
|
async delete(shareId) {
|
|
27287
27373
|
return locked(async (profile, ready) => {
|
|
27288
|
-
await write(profile, (await read4(profile, ready)).filter((
|
|
27374
|
+
await write(profile, (await read4(profile, ready)).filter((record2) => record2.shareId !== shareId), ready);
|
|
27289
27375
|
}, true);
|
|
27290
27376
|
}
|
|
27291
27377
|
};
|
|
@@ -27458,6 +27544,7 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27458
27544
|
const written = await node.kvForSpace(ownerSpaceId).put(resourcePath2, file2.bytes.slice(), {
|
|
27459
27545
|
contentType: targetInput.mediaType ?? file2.mediaType ?? "application/octet-stream"
|
|
27460
27546
|
});
|
|
27547
|
+
failIfSpaceNotReady(written);
|
|
27461
27548
|
if (!written.ok) {
|
|
27462
27549
|
const code4 = typeof written.error === "object" && written.error !== null && "code" in written.error ? written.error.code : void 0;
|
|
27463
27550
|
if (code4 === "AUTH_UNAUTHORIZED" || code4 === "PERMISSION_DENIED") {
|
|
@@ -27557,6 +27644,7 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27557
27644
|
resourcePath = artifactVersionFilePath(artifact.id, artifactVersion.version, storageName);
|
|
27558
27645
|
} else {
|
|
27559
27646
|
const stored = await node.kvForSpace(ownerSpaceId).put(resourcePath, storedBytes, { contentType: "application/vnd.tinycloud.encrypted-envelope+json" });
|
|
27647
|
+
failIfSpaceNotReady(stored);
|
|
27560
27648
|
if (!stored.ok) {
|
|
27561
27649
|
const code4 = typeof stored.error === "object" && stored.error !== null && "code" in stored.error ? stored.error.code : void 0;
|
|
27562
27650
|
if (code4 === "AUTH_UNAUTHORIZED" || code4 === "PERMISSION_DENIED") {
|
|
@@ -27623,21 +27711,21 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27623
27711
|
return published;
|
|
27624
27712
|
} };
|
|
27625
27713
|
const delivery = { deliver: input.deliver ?? (async (request) => {
|
|
27626
|
-
const
|
|
27627
|
-
if (
|
|
27628
|
-
const expiry = shareDeliveryWindowExpiresAt(
|
|
27714
|
+
const record2 = request.record;
|
|
27715
|
+
if (record2 === void 0 || record2.link === void 0 || record2.deliveryMaterial === void 0 || request.idempotencyKey === void 0) throw new Error("share delivery history is incomplete");
|
|
27716
|
+
const expiry = shareDeliveryWindowExpiresAt(record2);
|
|
27629
27717
|
if (expiry <= Date.now()) throw new ShareNotifyError("share delivery authorization window has expired", "delivery-window-expired");
|
|
27630
27718
|
const authorizationExpiresAt = new Date(expiry).toISOString();
|
|
27631
27719
|
const [config, node] = await Promise.all([publicConfig(), authenticatedNode()]);
|
|
27632
27720
|
const receipt = await node.authorizeShareDeliveryV3({
|
|
27633
|
-
envelope:
|
|
27634
|
-
sealedEnvelope:
|
|
27635
|
-
envelopeKey:
|
|
27636
|
-
shareCid:
|
|
27637
|
-
resourcePath:
|
|
27721
|
+
envelope: record2.deliveryMaterial.envelope,
|
|
27722
|
+
sealedEnvelope: record2.deliveryMaterial.sealedEnvelope,
|
|
27723
|
+
envelopeKey: record2.deliveryMaterial.envelopeKey,
|
|
27724
|
+
shareCid: record2.deliveryMaterial.shareCid,
|
|
27725
|
+
resourcePath: record2.resource.path,
|
|
27638
27726
|
recipientEmail: request.recipient,
|
|
27639
|
-
shareUrl:
|
|
27640
|
-
documentName:
|
|
27727
|
+
shareUrl: record2.link,
|
|
27728
|
+
documentName: record2.filename ?? "share.md",
|
|
27641
27729
|
expiresAt: authorizationExpiresAt,
|
|
27642
27730
|
deliveryAudience: config.credentialsOrigin,
|
|
27643
27731
|
idempotencyKey: request.idempotencyKey
|
|
@@ -27645,7 +27733,7 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27645
27733
|
await deliverCredentialInvitation({
|
|
27646
27734
|
credentialsOrigin: config.credentialsOrigin,
|
|
27647
27735
|
receipt,
|
|
27648
|
-
shareUrl:
|
|
27736
|
+
shareUrl: record2.link,
|
|
27649
27737
|
fetchFn,
|
|
27650
27738
|
signal: request.signal
|
|
27651
27739
|
});
|
|
@@ -27658,15 +27746,15 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27658
27746
|
// proofless session-key revocation covers the first, and a local owner
|
|
27659
27747
|
// key covers both. Without either key (a session-only profile that signed
|
|
27660
27748
|
// in again since, for example) the link cannot be revoked here.
|
|
27661
|
-
revokeDelegation: input.revokeDelegation ?? (async ({ delegationCid, record }) => {
|
|
27749
|
+
revokeDelegation: input.revokeDelegation ?? (async ({ delegationCid, record: record2 }) => {
|
|
27662
27750
|
const node = await authenticatedNode();
|
|
27663
27751
|
const activeNode = await node.activeNodeIdentity();
|
|
27664
|
-
if (
|
|
27752
|
+
if (record2.target.origin !== activeNode.origin) throw new Error("share delegation revocation is not bound to the active owner node");
|
|
27665
27753
|
const linkUnavailable = new CLIError("SHARE_LINK_UNAVAILABLE", "this share's stored link could not be verified; nothing was revoked", ExitCode.NOT_FOUND);
|
|
27666
|
-
const resource = `${
|
|
27754
|
+
const resource = `${record2.target.spaceId}/kv/${record2.resource.path}`;
|
|
27667
27755
|
let sessionIssued;
|
|
27668
27756
|
try {
|
|
27669
|
-
const decoded = node.sharing.decodeLink(parseNativeShareUrl(
|
|
27757
|
+
const decoded = node.sharing.decodeLink(parseNativeShareUrl(record2.link ?? ""));
|
|
27670
27758
|
const linkKey = decoded.keyDid.split("#", 1)[0];
|
|
27671
27759
|
const authorization2 = withoutBearer(decoded.delegation.authHeader ?? "");
|
|
27672
27760
|
if (authorization2.split(".").length === 3) {
|
|
@@ -27675,7 +27763,7 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27675
27763
|
sessionIssued = signed.payload.iss.split("#", 1)[0] === node.credentialHolderDid;
|
|
27676
27764
|
} else {
|
|
27677
27765
|
const signed = await parseSignedSiweCacao(authorization2, delegationCid);
|
|
27678
|
-
const owner = /^tinycloud:pkh:(eip155:[1-9]\d*:0x[0-9a-fA-F]{40}):/.exec(
|
|
27766
|
+
const owner = /^tinycloud:pkh:(eip155:[1-9]\d*:0x[0-9a-fA-F]{40}):/.exec(record2.target.spaceId)?.[1];
|
|
27679
27767
|
if (owner === void 0 || signed.issuer.toLowerCase() !== `did:pkh:${owner}`.toLowerCase() || signed.audience !== linkKey || signed.attenuation[resource] === void 0) throw linkUnavailable;
|
|
27680
27768
|
sessionIssued = false;
|
|
27681
27769
|
}
|
|
@@ -27771,7 +27859,7 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27771
27859
|
try {
|
|
27772
27860
|
return await operation();
|
|
27773
27861
|
} catch (error) {
|
|
27774
|
-
throw scopeDeniedFromArtifactError(error, "artifact storage", authority) ?? error;
|
|
27862
|
+
throw scopeDeniedFromArtifactError(error, "artifact storage", authority) ?? artifactSpaceNotReady(error);
|
|
27775
27863
|
}
|
|
27776
27864
|
};
|
|
27777
27865
|
return {
|