@tinycloud/cli 1.3.0-beta.32 → 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 +222 -133
- package/dist/index.js.map +1 -1
- package/dist/legacy-entry.js +214 -146
- package/dist/legacy-entry.js.map +1 -1
- package/package.json +1 -1
- package/skills/tc-cli/REFERENCE.md +41 -2
- package/skills/tc-cli/SKILL.md +2 -0
package/dist/legacy-entry.js
CHANGED
|
@@ -492,20 +492,20 @@ var init_formatter = __esm({
|
|
|
492
492
|
function storageRejection(error) {
|
|
493
493
|
let node = error;
|
|
494
494
|
for (let depth = 0; depth < MAX_CAUSE_DEPTH && typeof node === "object" && node !== null; depth += 1) {
|
|
495
|
-
const
|
|
495
|
+
const record3 = node;
|
|
496
496
|
let code4;
|
|
497
|
-
if (
|
|
498
|
-
code4 =
|
|
499
|
-
} else if (
|
|
497
|
+
if (record3.code === "STORAGE_QUOTA_EXCEEDED" || record3.code === "STORAGE_LIMIT_REACHED") {
|
|
498
|
+
code4 = record3.code;
|
|
499
|
+
} else if (record3.code !== void 0) {
|
|
500
500
|
return void 0;
|
|
501
|
-
} else if (isStorageStatus(
|
|
502
|
-
code4 = storageCodeFromText(
|
|
501
|
+
} else if (isStorageStatus(record3)) {
|
|
502
|
+
code4 = storageCodeFromText(record3.message);
|
|
503
503
|
}
|
|
504
504
|
if (code4) {
|
|
505
|
-
const account = accountTotals(
|
|
505
|
+
const account = accountTotals(record3) ?? accountTotals(record3.meta) ?? accountTotals(record3.metadata);
|
|
506
506
|
return account ? { code: code4, account } : { code: code4 };
|
|
507
507
|
}
|
|
508
|
-
node =
|
|
508
|
+
node = record3.cause;
|
|
509
509
|
}
|
|
510
510
|
return void 0;
|
|
511
511
|
}
|
|
@@ -539,11 +539,11 @@ function storageCodeFromText(message) {
|
|
|
539
539
|
}
|
|
540
540
|
return void 0;
|
|
541
541
|
}
|
|
542
|
-
function isStorageStatus(
|
|
543
|
-
const meta = "meta" in
|
|
542
|
+
function isStorageStatus(record3) {
|
|
543
|
+
const meta = "meta" in record3 && typeof record3.meta === "object" && record3.meta !== null ? record3.meta : {};
|
|
544
544
|
const statuses = [
|
|
545
|
-
"status" in
|
|
546
|
-
"statusCode" in
|
|
545
|
+
"status" in record3 ? record3.status : void 0,
|
|
546
|
+
"statusCode" in record3 ? record3.statusCode : void 0,
|
|
547
547
|
"status" in meta ? meta.status : void 0
|
|
548
548
|
];
|
|
549
549
|
return statuses.some((value) => value === 402 || value === 413);
|
|
@@ -2627,7 +2627,7 @@ async function appendLocalGrantArtifact(profile, delegation) {
|
|
|
2627
2627
|
await ProfileManager.ensureProfileDir(profile);
|
|
2628
2628
|
await refuseWriteToDeletedProfile(profile);
|
|
2629
2629
|
const records = await loadLocalGrantArtifacts(profile);
|
|
2630
|
-
if (records.some((
|
|
2630
|
+
if (records.some((record3) => record3.delegationCid === delegation.cid)) return;
|
|
2631
2631
|
await writeJsonAtomic(localGrantArtifactsPath(profile), [
|
|
2632
2632
|
...records,
|
|
2633
2633
|
{ delegationCid: delegation.cid, delegation }
|
|
@@ -6082,30 +6082,30 @@ function parseState(text) {
|
|
|
6082
6082
|
throw gateRefusal("gate_unavailable", "The replica gate file is not valid JSON.");
|
|
6083
6083
|
}
|
|
6084
6084
|
if (typeof raw !== "object" || raw === null) throw gateRefusal("gate_unavailable", "The replica gate file is malformed.");
|
|
6085
|
-
const
|
|
6086
|
-
if (
|
|
6087
|
-
if (typeof
|
|
6085
|
+
const record3 = raw;
|
|
6086
|
+
if (record3.v !== GATE_FILE_VERSION) throw gateRefusal("gate_unavailable", "The replica gate file has an unknown version.");
|
|
6087
|
+
if (typeof record3.incarnation !== "string" || record3.incarnation.length === 0) {
|
|
6088
6088
|
throw gateRefusal("gate_unavailable", "The replica gate file has no incarnation.");
|
|
6089
6089
|
}
|
|
6090
|
-
if (typeof
|
|
6090
|
+
if (typeof record3.salt !== "string" || Buffer.from(record3.salt, "base64url").toString("base64url") !== record3.salt || Buffer.from(record3.salt, "base64url").length < 32) {
|
|
6091
6091
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid salt.");
|
|
6092
6092
|
}
|
|
6093
|
-
if (
|
|
6093
|
+
if (record3.principalHash !== null && (typeof record3.principalHash !== "string" || !/^[0-9a-f]{64}$/.test(record3.principalHash))) {
|
|
6094
6094
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid principal hash.");
|
|
6095
6095
|
}
|
|
6096
|
-
if (typeof
|
|
6096
|
+
if (typeof record3.lifecycleEpoch !== "number" || !Number.isSafeInteger(record3.lifecycleEpoch) || record3.lifecycleEpoch < 0) {
|
|
6097
6097
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid lifecycle epoch.");
|
|
6098
6098
|
}
|
|
6099
|
-
if (
|
|
6099
|
+
if (record3.deniedAt !== null && (typeof record3.deniedAt !== "number" || !Number.isSafeInteger(record3.deniedAt) || record3.deniedAt < 0)) {
|
|
6100
6100
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid deniedAt.");
|
|
6101
6101
|
}
|
|
6102
|
-
if (!Array.isArray(
|
|
6103
|
-
for (const intent of
|
|
6102
|
+
if (!Array.isArray(record3.intents)) throw gateRefusal("gate_unavailable", "The replica gate file has no intents list.");
|
|
6103
|
+
for (const intent of record3.intents) {
|
|
6104
6104
|
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)) {
|
|
6105
6105
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid purge intent.");
|
|
6106
6106
|
}
|
|
6107
6107
|
}
|
|
6108
|
-
const firstInstall =
|
|
6108
|
+
const firstInstall = record3.firstInstall;
|
|
6109
6109
|
if (typeof firstInstall !== "object" || firstInstall === null || Array.isArray(firstInstall)) {
|
|
6110
6110
|
throw gateRefusal("gate_unavailable", "The replica gate file has no valid firstInstall map.");
|
|
6111
6111
|
}
|
|
@@ -6114,7 +6114,7 @@ function parseState(text) {
|
|
|
6114
6114
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid firstInstall entry.");
|
|
6115
6115
|
}
|
|
6116
6116
|
}
|
|
6117
|
-
const grantInstall = Object.prototype.hasOwnProperty.call(
|
|
6117
|
+
const grantInstall = Object.prototype.hasOwnProperty.call(record3, "grantInstall") ? record3.grantInstall : {};
|
|
6118
6118
|
if (typeof grantInstall !== "object" || grantInstall === null || Array.isArray(grantInstall)) {
|
|
6119
6119
|
throw gateRefusal("gate_unavailable", "The replica gate has an invalid grantInstall map.");
|
|
6120
6120
|
}
|
|
@@ -6123,7 +6123,7 @@ function parseState(text) {
|
|
|
6123
6123
|
throw gateRefusal("gate_unavailable", "The replica gate has an invalid grant install time.");
|
|
6124
6124
|
}
|
|
6125
6125
|
}
|
|
6126
|
-
const pendingGenerations =
|
|
6126
|
+
const pendingGenerations = record3.pendingGenerations;
|
|
6127
6127
|
if (typeof pendingGenerations !== "object" || pendingGenerations === null || Array.isArray(pendingGenerations)) {
|
|
6128
6128
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid pending generation map.");
|
|
6129
6129
|
}
|
|
@@ -6132,18 +6132,18 @@ function parseState(text) {
|
|
|
6132
6132
|
throw gateRefusal("gate_unavailable", "The replica gate file has an invalid pending generation.");
|
|
6133
6133
|
}
|
|
6134
6134
|
}
|
|
6135
|
-
const eraseDeferred = Object.prototype.hasOwnProperty.call(
|
|
6136
|
-
const deferredPrincipalHash = Object.prototype.hasOwnProperty.call(
|
|
6137
|
-
if (typeof eraseDeferred !== "boolean" || deferredPrincipalHash !== null && (typeof deferredPrincipalHash !== "string" || !/^[0-9a-f]{64}$/.test(deferredPrincipalHash)) || eraseDeferred && (
|
|
6135
|
+
const eraseDeferred = Object.prototype.hasOwnProperty.call(record3, "eraseDeferred") ? record3.eraseDeferred : false;
|
|
6136
|
+
const deferredPrincipalHash = Object.prototype.hasOwnProperty.call(record3, "deferredPrincipalHash") ? record3.deferredPrincipalHash : null;
|
|
6137
|
+
if (typeof eraseDeferred !== "boolean" || deferredPrincipalHash !== null && (typeof deferredPrincipalHash !== "string" || !/^[0-9a-f]{64}$/.test(deferredPrincipalHash)) || eraseDeferred && (record3.principalHash !== null || deferredPrincipalHash === null)) {
|
|
6138
6138
|
throw gateRefusal("gate_unavailable", "The replica gate has an invalid deferred erase state.");
|
|
6139
6139
|
}
|
|
6140
6140
|
return {
|
|
6141
|
-
incarnation:
|
|
6142
|
-
salt:
|
|
6143
|
-
principalHash:
|
|
6144
|
-
lifecycleEpoch:
|
|
6145
|
-
deniedAt:
|
|
6146
|
-
intents:
|
|
6141
|
+
incarnation: record3.incarnation,
|
|
6142
|
+
salt: record3.salt,
|
|
6143
|
+
principalHash: record3.principalHash,
|
|
6144
|
+
lifecycleEpoch: record3.lifecycleEpoch,
|
|
6145
|
+
deniedAt: record3.deniedAt,
|
|
6146
|
+
intents: record3.intents,
|
|
6147
6147
|
firstInstall,
|
|
6148
6148
|
grantInstall,
|
|
6149
6149
|
pendingGenerations,
|
|
@@ -6165,17 +6165,17 @@ async function readStoredState(profileDir) {
|
|
|
6165
6165
|
return parseState(text);
|
|
6166
6166
|
}
|
|
6167
6167
|
async function readDenyFloor(profileDir) {
|
|
6168
|
-
let
|
|
6168
|
+
let record3;
|
|
6169
6169
|
try {
|
|
6170
|
-
|
|
6170
|
+
record3 = JSON.parse(await readFile3(join6(profileDir, DENY_FLOOR_FILE), "utf8"));
|
|
6171
6171
|
} catch (error) {
|
|
6172
6172
|
if (isNotFound2(error)) return void 0;
|
|
6173
6173
|
throw gateRefusal("gate_unavailable", "The replica deny floor cannot be read.");
|
|
6174
6174
|
}
|
|
6175
|
-
if (typeof
|
|
6175
|
+
if (typeof record3 !== "object" || record3 === null || Array.isArray(record3) || Object.keys(record3).length !== 2 || !("epoch" in record3) || !("deniedAt" in record3) || !Number.isSafeInteger(record3.epoch) || record3.epoch < 1 || !Number.isSafeInteger(record3.deniedAt) || record3.deniedAt < 0) {
|
|
6176
6176
|
throw gateRefusal("gate_unavailable", "The replica deny floor is malformed.");
|
|
6177
6177
|
}
|
|
6178
|
-
return { epoch:
|
|
6178
|
+
return { epoch: record3.epoch, deniedAt: record3.deniedAt };
|
|
6179
6179
|
}
|
|
6180
6180
|
function behindFloor(state2, floor) {
|
|
6181
6181
|
return state2.lifecycleEpoch < floor.epoch || state2.deniedAt === null || state2.deniedAt < floor.deniedAt;
|
|
@@ -10456,9 +10456,9 @@ async function planLogoutRevocations(input) {
|
|
|
10456
10456
|
throw inventoryError("artifact file", "invalid JSON");
|
|
10457
10457
|
}
|
|
10458
10458
|
if (!Array.isArray(records)) throw inventoryError("artifact file", "expected an array of signed grants");
|
|
10459
|
-
for (const
|
|
10460
|
-
const cid =
|
|
10461
|
-
const delegation =
|
|
10459
|
+
for (const record3 of records) {
|
|
10460
|
+
const cid = record3 && typeof record3 === "object" && "delegationCid" in record3 && typeof record3.delegationCid === "string" ? record3.delegationCid : "artifact entry";
|
|
10461
|
+
const delegation = record3 && typeof record3 === "object" && "delegation" in record3 ? record3.delegation : void 0;
|
|
10462
10462
|
const authorization = delegation && typeof delegation === "object" && "delegationHeader" in delegation && delegation.delegationHeader && typeof delegation.delegationHeader === "object" && "Authorization" in delegation.delegationHeader ? delegation.delegationHeader.Authorization : void 0;
|
|
10463
10463
|
if (!cid || !delegation || typeof delegation !== "object" || !("cid" in delegation) || delegation.cid !== cid || typeof authorization !== "string") throw inventoryError(cid, "the issued grant record is malformed");
|
|
10464
10464
|
let owner;
|
|
@@ -10487,16 +10487,16 @@ async function planLogoutRevocations(input) {
|
|
|
10487
10487
|
const historyText = await optionalFile(join11(root, "auth-grants.jsonl"));
|
|
10488
10488
|
if (historyText !== null) {
|
|
10489
10489
|
for (const line of historyText.split("\n").filter((row) => row.trim().length > 0)) {
|
|
10490
|
-
let
|
|
10490
|
+
let record3;
|
|
10491
10491
|
try {
|
|
10492
|
-
|
|
10492
|
+
record3 = JSON.parse(line);
|
|
10493
10493
|
} catch {
|
|
10494
10494
|
throw inventoryError("history file", "invalid JSONL");
|
|
10495
10495
|
}
|
|
10496
|
-
if (!
|
|
10496
|
+
if (!record3 || typeof record3 !== "object" || !("source" in record3) || typeof record3.source !== "string") {
|
|
10497
10497
|
throw inventoryError("history file", "malformed history row");
|
|
10498
10498
|
}
|
|
10499
|
-
const cid = "delegationCid" in
|
|
10499
|
+
const cid = "delegationCid" in record3 ? record3.delegationCid : void 0;
|
|
10500
10500
|
if (cid === void 0) continue;
|
|
10501
10501
|
if (typeof cid !== "string" || !cid) throw inventoryError("history file", "invalid CID");
|
|
10502
10502
|
if (cid !== sessionCid && !included.has(cid) && !foreign.has(cid)) unresolved.add(cid);
|
|
@@ -11575,8 +11575,8 @@ function deviceAuthRateLimit(response) {
|
|
|
11575
11575
|
}
|
|
11576
11576
|
function publicSessionJwk(value) {
|
|
11577
11577
|
const publicJwk = publicJwkForDelegation(value);
|
|
11578
|
-
const
|
|
11579
|
-
if (
|
|
11578
|
+
const record3 = publicJwk;
|
|
11579
|
+
if (record3.kty !== "OKP" || record3.crv !== "Ed25519" || typeof record3.x !== "string") {
|
|
11580
11580
|
throw new Error("CLI session key is not a public Ed25519 JWK");
|
|
11581
11581
|
}
|
|
11582
11582
|
return publicJwk;
|
|
@@ -12204,8 +12204,8 @@ function ownerDidFromSpace(spaceId) {
|
|
|
12204
12204
|
if (!owner) return void 0;
|
|
12205
12205
|
return owner.startsWith("did:") ? owner : `did:${owner}`;
|
|
12206
12206
|
}
|
|
12207
|
-
async function cidBoundOwnerSpace(
|
|
12208
|
-
const { delegation } =
|
|
12207
|
+
async function cidBoundOwnerSpace(record3, ownerDid, node, host) {
|
|
12208
|
+
const { delegation } = record3;
|
|
12209
12209
|
const authorization = delegation.delegationHeader?.Authorization;
|
|
12210
12210
|
if (typeof authorization !== "string" || typeof delegation.cid !== "string") return void 0;
|
|
12211
12211
|
if (!delegation.siweProof && withoutBearer2(authorization).split(".").length === 3) {
|
|
@@ -12223,7 +12223,7 @@ async function cidBoundOwnerSpace(record2, ownerDid, node, host) {
|
|
|
12223
12223
|
return void 0;
|
|
12224
12224
|
}
|
|
12225
12225
|
if (!node || !delegation.siweProof) return void 0;
|
|
12226
|
-
const inspected = await inspectStoredDelegation(
|
|
12226
|
+
const inspected = await inspectStoredDelegation(record3, { node, host: host ?? delegation.host });
|
|
12227
12227
|
if (inspected.local !== "verified" || inspected.cid !== delegation.cid) return void 0;
|
|
12228
12228
|
for (const permission of inspected.effectivePermissions) {
|
|
12229
12229
|
const space = permission.space;
|
|
@@ -13607,9 +13607,9 @@ ${signInAgainHint(ctx.profile, posture ?? void 0)}
|
|
|
13607
13607
|
let activated = false;
|
|
13608
13608
|
let permissions = imported.permissions;
|
|
13609
13609
|
if (targetsSessionKey) {
|
|
13610
|
-
let
|
|
13610
|
+
let record3;
|
|
13611
13611
|
try {
|
|
13612
|
-
|
|
13612
|
+
record3 = await activateUnboundImport(
|
|
13613
13613
|
node,
|
|
13614
13614
|
imported.delegation,
|
|
13615
13615
|
ctx.host
|
|
@@ -13625,21 +13625,21 @@ ${signInAgainHint(ctx.profile, posture ?? void 0)}
|
|
|
13625
13625
|
if (bootstrap) await bootstrap.abandon(refusal);
|
|
13626
13626
|
throw refusal;
|
|
13627
13627
|
}
|
|
13628
|
-
await appendAdditionalDelegation(ctx.profile,
|
|
13629
|
-
importExpiry =
|
|
13630
|
-
permissions =
|
|
13628
|
+
await appendAdditionalDelegation(ctx.profile, record3);
|
|
13629
|
+
importExpiry = record3.delegation.expiry;
|
|
13630
|
+
permissions = record3.permissions;
|
|
13631
13631
|
activated = true;
|
|
13632
13632
|
} else {
|
|
13633
|
-
const
|
|
13633
|
+
const record3 = storedAdditionalDelegation(
|
|
13634
13634
|
{ ...imported.delegation, expiry: importExpiry },
|
|
13635
13635
|
imported.permissions
|
|
13636
13636
|
);
|
|
13637
13637
|
if (!targetsSessionKey && kind === "compact") {
|
|
13638
|
-
if (!await appendAdditionalDelegationIfUnexpired(ctx.profile,
|
|
13638
|
+
if (!await appendAdditionalDelegationIfUnexpired(ctx.profile, record3, signedExpiry)) {
|
|
13639
13639
|
throw delegationExpiredError();
|
|
13640
13640
|
}
|
|
13641
13641
|
} else {
|
|
13642
|
-
await appendAdditionalDelegation(ctx.profile,
|
|
13642
|
+
await appendAdditionalDelegation(ctx.profile, record3);
|
|
13643
13643
|
}
|
|
13644
13644
|
}
|
|
13645
13645
|
await appendGrantHistory(ctx.profile, {
|
|
@@ -16609,8 +16609,8 @@ async function storedGrants(profile) {
|
|
|
16609
16609
|
const records = await readAdditionalDelegations2(profile).catch(
|
|
16610
16610
|
() => []
|
|
16611
16611
|
);
|
|
16612
|
-
for (const
|
|
16613
|
-
const authorization =
|
|
16612
|
+
for (const record3 of records) {
|
|
16613
|
+
const authorization = record3.delegation?.delegationHeader?.Authorization;
|
|
16614
16614
|
if (typeof authorization === "string") authorizations.push(authorization);
|
|
16615
16615
|
}
|
|
16616
16616
|
const grants = [];
|
|
@@ -16856,7 +16856,7 @@ async function replicationPartitions(profile, root) {
|
|
|
16856
16856
|
const partition = await withPinnedLocalDirectory(profile, root, entry.name, async (pinned) => {
|
|
16857
16857
|
const identity = await readReportJson(profile, pinned, "identity.json");
|
|
16858
16858
|
const pending = await readReportJson(profile, pinned, "pending.json");
|
|
16859
|
-
const pinnedCount = pending?.records?.filter((
|
|
16859
|
+
const pinnedCount = pending?.records?.filter((record3) => record3.state === "in_flight" || record3.state === "ambiguous").length ?? 0;
|
|
16860
16860
|
return {
|
|
16861
16861
|
idHash: entry.name,
|
|
16862
16862
|
host: typeof identity?.host === "string" ? identity.host : null,
|
|
@@ -17927,9 +17927,9 @@ function shouldRequestSecretPermissions(error) {
|
|
|
17927
17927
|
return /permission|session expired|autosign|capabilit/i.test(error.message);
|
|
17928
17928
|
}
|
|
17929
17929
|
function thrownPermissionError(error) {
|
|
17930
|
-
const
|
|
17931
|
-
const message = typeof
|
|
17932
|
-
const code4 = typeof
|
|
17930
|
+
const record3 = error;
|
|
17931
|
+
const message = typeof record3?.message === "string" ? record3.message : String(error);
|
|
17932
|
+
const code4 = typeof record3?.code === "string" ? record3.code : "PERMISSION_DENIED";
|
|
17933
17933
|
if (code4 !== "PERMISSION_DENIED" && !/permission|session expired|autosign|capabilit/i.test(message)) {
|
|
17934
17934
|
return null;
|
|
17935
17935
|
}
|
|
@@ -18252,10 +18252,10 @@ async function readDelegatedSecretValue(params) {
|
|
|
18252
18252
|
return parseDecryptedSecretPayload(decrypted.data, params.secretPath);
|
|
18253
18253
|
}
|
|
18254
18254
|
function isStoredSessionExpired(session) {
|
|
18255
|
-
const
|
|
18256
|
-
const direct = parseDate(
|
|
18255
|
+
const record3 = session;
|
|
18256
|
+
const direct = parseDate(record3.expiresAt ?? record3.expiry ?? record3.expirationTime);
|
|
18257
18257
|
if (direct) return direct.getTime() <= Date.now();
|
|
18258
|
-
const signedOrSiweExpiry = sessionExpiresAt(
|
|
18258
|
+
const signedOrSiweExpiry = sessionExpiresAt(record3);
|
|
18259
18259
|
return signedOrSiweExpiry !== null && Date.parse(signedOrSiweExpiry) <= Date.now();
|
|
18260
18260
|
}
|
|
18261
18261
|
function parseDate(value) {
|
|
@@ -24197,15 +24197,15 @@ function parseArtifactManifest(bytes) {
|
|
|
24197
24197
|
throw new ArtifactError("corrupt", "artifact manifest is malformed");
|
|
24198
24198
|
};
|
|
24199
24199
|
if (value === null || typeof value !== "object" || Array.isArray(value)) return fail();
|
|
24200
|
-
const
|
|
24200
|
+
const record3 = value;
|
|
24201
24201
|
const allowed = ["v", "files", "createdAt", "parent", "note"];
|
|
24202
|
-
if (Object.keys(
|
|
24203
|
-
if (!Array.isArray(
|
|
24204
|
-
if (typeof
|
|
24205
|
-
if (
|
|
24206
|
-
if (
|
|
24202
|
+
if (Object.keys(record3).some((key) => !allowed.includes(key)) || record3.v !== ARTIFACT_MANIFEST_VERSION) return fail();
|
|
24203
|
+
if (!Array.isArray(record3.files) || record3.files.length === 0) return fail();
|
|
24204
|
+
if (typeof record3.createdAt !== "string" || Number.isNaN(Date.parse(record3.createdAt))) return fail();
|
|
24205
|
+
if (record3.parent !== null && (typeof record3.parent !== "number" || !Number.isSafeInteger(record3.parent) || record3.parent < 1)) return fail();
|
|
24206
|
+
if (record3.note !== void 0 && (typeof record3.note !== "string" || record3.note.length > 1024)) return fail();
|
|
24207
24207
|
const seen = /* @__PURE__ */ new Set();
|
|
24208
|
-
const files =
|
|
24208
|
+
const files = record3.files.map((entry) => {
|
|
24209
24209
|
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) return fail();
|
|
24210
24210
|
const file = entry;
|
|
24211
24211
|
if (Object.keys(file).some((key) => !["path", "sha256", "bytes"].includes(key))) return fail();
|
|
@@ -24223,9 +24223,9 @@ function parseArtifactManifest(bytes) {
|
|
|
24223
24223
|
return {
|
|
24224
24224
|
v: ARTIFACT_MANIFEST_VERSION,
|
|
24225
24225
|
files,
|
|
24226
|
-
createdAt:
|
|
24227
|
-
parent:
|
|
24228
|
-
...
|
|
24226
|
+
createdAt: record3.createdAt,
|
|
24227
|
+
parent: record3.parent,
|
|
24228
|
+
...record3.note === void 0 ? {} : { note: record3.note }
|
|
24229
24229
|
};
|
|
24230
24230
|
}
|
|
24231
24231
|
async function listArtifactVersions(store, artifactId) {
|
|
@@ -29924,21 +29924,21 @@ async function parseSealedInlineShareUrl(url, options = {}) {
|
|
|
29924
29924
|
throw new TypeError("sealed inline payload is not valid JSON");
|
|
29925
29925
|
}
|
|
29926
29926
|
if (typeof value !== "object" || value === null || Array.isArray(value) || canonicalize(value) !== payloadText) throw new TypeError("sealed inline payload is not canonical JSON");
|
|
29927
|
-
const
|
|
29928
|
-
if (Object.keys(
|
|
29927
|
+
const record3 = value;
|
|
29928
|
+
if (Object.keys(record3).length !== 4 || record3.v !== 2 || typeof record3.c !== "string" || typeof record3.cid !== "string" || typeof record3.k !== "string") throw new TypeError("sealed inline payload has invalid fields");
|
|
29929
29929
|
let ciphertext;
|
|
29930
29930
|
let key32;
|
|
29931
29931
|
try {
|
|
29932
|
-
ciphertext = fromBase64Url2(
|
|
29933
|
-
key32 = fromBase64Url2(
|
|
29932
|
+
ciphertext = fromBase64Url2(record3.c);
|
|
29933
|
+
key32 = fromBase64Url2(record3.k);
|
|
29934
29934
|
} catch {
|
|
29935
29935
|
throw new TypeError("sealed inline payload has invalid base64url material");
|
|
29936
29936
|
}
|
|
29937
29937
|
if (ciphertext.byteLength === 0 || ciphertext.byteLength > MAX_INLINE_BYTES2) throw new TypeError("sealed inline ciphertext is outside the allowed size");
|
|
29938
29938
|
if (key32.byteLength !== KEY_LENGTH2) throw new TypeError("sealed inline key must be 32 bytes");
|
|
29939
|
-
assertCanonicalCid(
|
|
29940
|
-
if (await computeCid(ciphertext) !==
|
|
29941
|
-
return { kind: "inline", ciphertextCid:
|
|
29939
|
+
assertCanonicalCid(record3.cid);
|
|
29940
|
+
if (await computeCid(ciphertext) !== record3.cid) throw new TypeError("sealed inline ciphertext does not match its CID");
|
|
29941
|
+
return { kind: "inline", ciphertextCid: record3.cid, ciphertext, key32 };
|
|
29942
29942
|
}
|
|
29943
29943
|
var ARTIFACT_ROOT2 = "artifacts";
|
|
29944
29944
|
function parseArtifactVersionPath2(path) {
|
|
@@ -31142,16 +31142,16 @@ var ShareNotifyError = class extends Error {
|
|
|
31142
31142
|
}
|
|
31143
31143
|
code = "delivery-failed";
|
|
31144
31144
|
};
|
|
31145
|
-
function recipientMatchesShareRecord(
|
|
31146
|
-
const matcher =
|
|
31145
|
+
function recipientMatchesShareRecord(record3, recipient) {
|
|
31146
|
+
const matcher = record3.recipientMatcher;
|
|
31147
31147
|
const mailbox = canonicalMailbox(recipient);
|
|
31148
31148
|
if (mailbox === void 0) return false;
|
|
31149
31149
|
if (matcher.kind === "exactEmail") return canonicalMailbox(matcher.value)?.email === mailbox.email;
|
|
31150
31150
|
if (matcher.kind === "emailDomain") return mailbox.domain === matcher.value;
|
|
31151
31151
|
return false;
|
|
31152
31152
|
}
|
|
31153
|
-
function shareDeliveryWindowExpiresAt(
|
|
31154
|
-
const expiresAt = Math.min(Date.parse(
|
|
31153
|
+
function shareDeliveryWindowExpiresAt(record3) {
|
|
31154
|
+
const expiresAt = Math.min(Date.parse(record3.expiresAt), Date.parse(record3.registeredAt) + 5 * 60 * 1e3);
|
|
31155
31155
|
if (!Number.isFinite(expiresAt)) throw new ShareNotifyError("share delivery history has invalid timestamps");
|
|
31156
31156
|
return expiresAt;
|
|
31157
31157
|
}
|
|
@@ -31228,17 +31228,17 @@ async function defaultIdempotencyKey(shareId, recipient) {
|
|
|
31228
31228
|
));
|
|
31229
31229
|
return `tinycloud-share:${shareId}:${toBase64Url(digest3)}`;
|
|
31230
31230
|
}
|
|
31231
|
-
function targetKind2(
|
|
31232
|
-
if (
|
|
31233
|
-
return
|
|
31231
|
+
function targetKind2(record3) {
|
|
31232
|
+
if (record3.targetKind !== void 0) return record3.targetKind;
|
|
31233
|
+
return record3.recipientMatcher.kind === "exactEmail" ? "email" : record3.recipientMatcher.kind === "emailDomain" ? "emailDomain" : record3.recipientMatcher.kind === "recipientDid" ? "recipientDid" : "bearer";
|
|
31234
31234
|
}
|
|
31235
|
-
function policyNodeAudience(
|
|
31236
|
-
const envelope =
|
|
31237
|
-
if (typeof envelope !== "object" || envelope === null || Array.isArray(envelope)) return
|
|
31235
|
+
function policyNodeAudience(record3) {
|
|
31236
|
+
const envelope = record3.deliveryMaterial?.envelope;
|
|
31237
|
+
if (typeof envelope !== "object" || envelope === null || Array.isArray(envelope)) return record3.target.nodeAudience;
|
|
31238
31238
|
const binding = envelope.attestedEnforcerBinding;
|
|
31239
|
-
if (typeof binding !== "object" || binding === null || Array.isArray(binding)) return
|
|
31239
|
+
if (typeof binding !== "object" || binding === null || Array.isArray(binding)) return record3.target.nodeAudience;
|
|
31240
31240
|
const nodeAudience = binding.nodeAudience;
|
|
31241
|
-
return typeof nodeAudience === "string" ? nodeAudience :
|
|
31241
|
+
return typeof nodeAudience === "string" ? nodeAudience : record3.target.nodeAudience;
|
|
31242
31242
|
}
|
|
31243
31243
|
async function revokeShare(input) {
|
|
31244
31244
|
const target = targetKind2(input.record);
|
|
@@ -31262,7 +31262,7 @@ async function revokeShare(input) {
|
|
|
31262
31262
|
}
|
|
31263
31263
|
let revokedAt = input.record.revokedAt ?? (input.now?.() ?? /* @__PURE__ */ new Date()).toISOString();
|
|
31264
31264
|
if (input.records?.update !== void 0) {
|
|
31265
|
-
const updated = await input.records.update(input.record.shareId, (
|
|
31265
|
+
const updated = await input.records.update(input.record.shareId, (record3) => ({ ...record3, revokedAt: record3.revokedAt ?? revokedAt }));
|
|
31266
31266
|
revokedAt = updated?.revokedAt ?? revokedAt;
|
|
31267
31267
|
} else if (input.records !== void 0) {
|
|
31268
31268
|
const latest = await input.records.get(input.record.shareId);
|
|
@@ -31271,26 +31271,26 @@ async function revokeShare(input) {
|
|
|
31271
31271
|
}
|
|
31272
31272
|
return { state: "revoked", target, delegationCid, revokedAt };
|
|
31273
31273
|
}
|
|
31274
|
-
function redactRecord(
|
|
31275
|
-
const matcher =
|
|
31276
|
-
const revealedLink = revealLink ? link3 ??
|
|
31274
|
+
function redactRecord(record3, revealLink, link3) {
|
|
31275
|
+
const matcher = record3.recipientMatcher;
|
|
31276
|
+
const revealedLink = revealLink ? link3 ?? record3.link : void 0;
|
|
31277
31277
|
return {
|
|
31278
|
-
shareId:
|
|
31278
|
+
shareId: record3.shareId,
|
|
31279
31279
|
target: matcher.kind === "exactEmail" ? "email" : matcher.kind === "emailDomain" ? "email-domain" : matcher.kind === "recipientDid" ? "recipient-did" : "bearer",
|
|
31280
31280
|
...matcher.kind === "exactEmail" ? { recipient: matcher.value } : matcher.kind === "emailDomain" ? { recipient: `*@${matcher.value}` } : matcher.kind === "recipientDid" ? { recipient: matcher.value } : {},
|
|
31281
|
-
expiresAt:
|
|
31282
|
-
revoked:
|
|
31281
|
+
expiresAt: record3.expiresAt,
|
|
31282
|
+
revoked: record3.revokedAt !== void 0,
|
|
31283
31283
|
...revealedLink === void 0 ? {} : { link: revealedLink }
|
|
31284
31284
|
};
|
|
31285
31285
|
}
|
|
31286
31286
|
async function listShares(storage) {
|
|
31287
31287
|
const records = await storage.list();
|
|
31288
|
-
return records.map((
|
|
31288
|
+
return records.map((record3) => redactRecord(record3, false));
|
|
31289
31289
|
}
|
|
31290
31290
|
async function showShare(input) {
|
|
31291
|
-
const
|
|
31292
|
-
if (
|
|
31293
|
-
return redactRecord(
|
|
31291
|
+
const record3 = await input.storage.get(input.shareId);
|
|
31292
|
+
if (record3 === void 0) throw new Error("share not found");
|
|
31293
|
+
return redactRecord(record3, input.revealLink === true, input.link);
|
|
31294
31294
|
}
|
|
31295
31295
|
var SHARE_V2_PROTOCOL = Object.freeze({
|
|
31296
31296
|
challengeDomain: "xyz.tinycloud.share/policy-challenge/v2\0",
|
|
@@ -36685,6 +36685,60 @@ var MAX_INLINE_BYTES3 = 256 * 1024;
|
|
|
36685
36685
|
import { ProfileLockTimeoutError as ProfileLockTimeoutError3 } from "@tinycloud/operations/state";
|
|
36686
36686
|
init_errors();
|
|
36687
36687
|
|
|
36688
|
+
// src/share/failure-class.ts
|
|
36689
|
+
init_constants();
|
|
36690
|
+
import { authorizationVerdictOf as authorizationVerdictOf2 } from "@tinycloud/sdk-core";
|
|
36691
|
+
var NETWORK_FAILURE = /\b(?:fetch failed|ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|UND_ERR_[A-Z_]+)\b|network ?error|failed to fetch/i;
|
|
36692
|
+
function record2(value) {
|
|
36693
|
+
return typeof value === "object" && value !== null ? value : void 0;
|
|
36694
|
+
}
|
|
36695
|
+
function httpStatus(value) {
|
|
36696
|
+
const status = typeof value === "number" && Number.isInteger(value) && value >= 400 && value <= 599 ? value : void 0;
|
|
36697
|
+
return status;
|
|
36698
|
+
}
|
|
36699
|
+
function statusOf(error, depth = 0) {
|
|
36700
|
+
const fields = record2(error);
|
|
36701
|
+
if (fields === void 0) return void 0;
|
|
36702
|
+
const direct = httpStatus(fields.status) ?? httpStatus(fields.statusCode) ?? httpStatus(record2(fields.meta)?.status);
|
|
36703
|
+
return direct ?? (depth === 0 ? statusOf(fields.cause, 1) : void 0);
|
|
36704
|
+
}
|
|
36705
|
+
function codeOf(error) {
|
|
36706
|
+
const code4 = record2(error)?.code;
|
|
36707
|
+
return typeof code4 === "string" && /^[A-Z][A-Z0-9_]{2,63}$/.test(code4) ? code4 : void 0;
|
|
36708
|
+
}
|
|
36709
|
+
function classifyShareFailure(error, loginHint) {
|
|
36710
|
+
const status = statusOf(error);
|
|
36711
|
+
const verdict = authorizationVerdictOf2(error);
|
|
36712
|
+
const message = error instanceof Error ? error.message : "";
|
|
36713
|
+
const code4 = codeOf(error);
|
|
36714
|
+
const detail = (text) => {
|
|
36715
|
+
const parts = [status === void 0 ? void 0 : `HTTP ${status}`, code4].filter((part) => part !== void 0);
|
|
36716
|
+
return parts.length === 0 ? text : `${text} (${parts.join(", ")})`;
|
|
36717
|
+
};
|
|
36718
|
+
if (verdict === "unauthenticated" || status === 401) {
|
|
36719
|
+
return { code: "AUTH_REQUIRED", exitCode: ExitCode.AUTH_REQUIRED, reason: detail(`the node did not accept this session; sign in again with ${loginHint}`) };
|
|
36720
|
+
}
|
|
36721
|
+
if (verdict === "forbidden" || status === 403) {
|
|
36722
|
+
return { code: "PERMISSION_DENIED", exitCode: ExitCode.PERMISSION_DENIED, reason: detail("the node refused this session's authority for the request") };
|
|
36723
|
+
}
|
|
36724
|
+
if (status === 404) {
|
|
36725
|
+
return { code: "NOT_FOUND", exitCode: ExitCode.NOT_FOUND, reason: detail("the node could not find what the request names") };
|
|
36726
|
+
}
|
|
36727
|
+
if (status !== void 0 && (status >= 500 || status === 408 || status === 429)) {
|
|
36728
|
+
return { code: "NODE_UNAVAILABLE", exitCode: ExitCode.NODE_ERROR, reason: detail("the node could not complete the request; try again shortly") };
|
|
36729
|
+
}
|
|
36730
|
+
if (status === 400 || status === 422) {
|
|
36731
|
+
return { code: "INVALID_ARGUMENT", exitCode: ExitCode.USAGE_ERROR, reason: detail("the node rejected the request as invalid") };
|
|
36732
|
+
}
|
|
36733
|
+
if (status !== void 0) {
|
|
36734
|
+
return { code: "NODE_REJECTED", exitCode: ExitCode.ERROR, reason: detail("the node rejected the request") };
|
|
36735
|
+
}
|
|
36736
|
+
if (NETWORK_FAILURE.test(message) || typeof record2(error)?.code === "string" && NETWORK_FAILURE.test(String(record2(error)?.code))) {
|
|
36737
|
+
return { code: "NETWORK_ERROR", exitCode: ExitCode.NETWORK_ERROR, reason: "the TinyCloud node could not be reached; check the connection and retry" };
|
|
36738
|
+
}
|
|
36739
|
+
return void 0;
|
|
36740
|
+
}
|
|
36741
|
+
|
|
36688
36742
|
// src/share/output.ts
|
|
36689
36743
|
function writeJson2(value) {
|
|
36690
36744
|
process.stdout.write(`${JSON.stringify(value, null, 2)}
|
|
@@ -36852,8 +36906,8 @@ async function writeShareOutput(directory, filename, bytes, force) {
|
|
|
36852
36906
|
|
|
36853
36907
|
// src/share/errors.ts
|
|
36854
36908
|
var SharePublishAuthorityError = class extends Error {
|
|
36855
|
-
constructor(failure) {
|
|
36856
|
-
super(failure.kind);
|
|
36909
|
+
constructor(failure, options) {
|
|
36910
|
+
super(failure.kind, options);
|
|
36857
36911
|
this.failure = failure;
|
|
36858
36912
|
this.name = "SharePublishAuthorityError";
|
|
36859
36913
|
}
|
|
@@ -36968,6 +37022,17 @@ function shareCliError(error, operation = "publish") {
|
|
|
36968
37022
|
if (failure.kind === "storage-full") {
|
|
36969
37023
|
return storageFullError(failure);
|
|
36970
37024
|
}
|
|
37025
|
+
if (failure.kind === "space-not-ready") {
|
|
37026
|
+
return Object.assign(
|
|
37027
|
+
new CLIError(
|
|
37028
|
+
"SPACE_NOT_READY",
|
|
37029
|
+
"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.",
|
|
37030
|
+
4,
|
|
37031
|
+
{ hint: "Nothing was shared, and repeating the command is safe. Retries keep failing until the node is updated." }
|
|
37032
|
+
),
|
|
37033
|
+
{ cause: error.cause }
|
|
37034
|
+
);
|
|
37035
|
+
}
|
|
36971
37036
|
if (failure.kind === "upload-failed") {
|
|
36972
37037
|
return new CLIError("UPLOAD_FAILED", "share source upload failed; nothing was shared", 4);
|
|
36973
37038
|
}
|
|
@@ -37001,8 +37066,10 @@ function shareCliError(error, operation = "publish") {
|
|
|
37001
37066
|
};
|
|
37002
37067
|
if (nodeCode === "ENOENT") return new CLIError("INVALID_ARGUMENT", "share input was not found", 2);
|
|
37003
37068
|
if (nodeCode === "EISDIR") return new CLIError("INVALID_ARGUMENT", "share input must be a Markdown file", 2);
|
|
37004
|
-
if (error instanceof TypeError) return new CLIError("INVALID_ARGUMENT", "share input is invalid", 2);
|
|
37005
37069
|
const mapped = typeof nodeCode === "string" && known[nodeCode] !== void 0 ? known[nodeCode] : known[message];
|
|
37070
|
+
const classified = mapped === void 0 ? classifyShareFailure(error, `\`${CLI_NAME27} auth login\``) : void 0;
|
|
37071
|
+
if (classified !== void 0) return Object.assign(new CLIError(classified.code, classified.reason, classified.exitCode), { cause: error });
|
|
37072
|
+
if (error instanceof TypeError) return new CLIError("INVALID_ARGUMENT", "share input is invalid", 2);
|
|
37006
37073
|
return new CLIError(mapped?.code ?? "INVALID_ARGUMENT", mapped ? mapped.code : "share operation failed", mapped?.exit ?? 2);
|
|
37007
37074
|
}
|
|
37008
37075
|
function inputUrl(value, stdin) {
|
|
@@ -37030,24 +37097,24 @@ function expires(value) {
|
|
|
37030
37097
|
}
|
|
37031
37098
|
}
|
|
37032
37099
|
async function rememberPublishedShare(result) {
|
|
37033
|
-
const
|
|
37034
|
-
if (shareServices.records === void 0) return { record:
|
|
37100
|
+
const record3 = historyRecordForPublishedShare(result);
|
|
37101
|
+
if (shareServices.records === void 0) return { record: record3, recorded: false };
|
|
37035
37102
|
try {
|
|
37036
|
-
await shareServices.records.put(
|
|
37037
|
-
return { record:
|
|
37103
|
+
await shareServices.records.put(record3);
|
|
37104
|
+
return { record: record3, recorded: true };
|
|
37038
37105
|
} catch {
|
|
37039
37106
|
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");
|
|
37040
|
-
return { record:
|
|
37107
|
+
return { record: record3, recorded: false };
|
|
37041
37108
|
}
|
|
37042
37109
|
}
|
|
37043
|
-
async function notifyRecordedShare(
|
|
37044
|
-
const result = await notifyShare({ shareId:
|
|
37110
|
+
async function notifyRecordedShare(record3, recipient, adapter, storage) {
|
|
37111
|
+
const result = await notifyShare({ shareId: record3.shareId, recipient, record: record3, adapter, checkDeliveryWindow: true });
|
|
37045
37112
|
if (result.state !== "partial-failure" && storage !== void 0) {
|
|
37046
37113
|
const mailbox = canonicalMailbox2(recipient).email;
|
|
37047
|
-
if (!
|
|
37114
|
+
if (!record3.deliveredRecipients?.includes(mailbox)) {
|
|
37048
37115
|
try {
|
|
37049
37116
|
if (storage.update === void 0) throw new Error("atomic sender history update is unavailable");
|
|
37050
|
-
const updated = await storage.update(
|
|
37117
|
+
const updated = await storage.update(record3.shareId, (current) => ({
|
|
37051
37118
|
...current,
|
|
37052
37119
|
deliveredRecipients: current.deliveredRecipients?.includes(mailbox) ? current.deliveredRecipients : [...current.deliveredRecipients ?? [], mailbox]
|
|
37053
37120
|
}));
|
|
@@ -37067,7 +37134,7 @@ function byteLimit(value) {
|
|
|
37067
37134
|
}
|
|
37068
37135
|
function mediaTypeFor(filename) {
|
|
37069
37136
|
const extension = filename.toLowerCase().split(".").at(-1);
|
|
37070
|
-
return extension === "md" || extension === "markdown" ? "text/markdown" : extension === "txt" ? "text/plain" : extension === "html" || extension === "htm" ? "text/html" : extension === "json" ? "application/json" : extension === "css" ? "text/css" : extension === "js" ? "text/javascript" : "application/octet-stream";
|
|
37137
|
+
return extension === "md" || extension === "markdown" ? "text/markdown" : extension === "txt" ? "text/plain" : extension === "html" || extension === "htm" ? "text/html" : extension === "json" ? "application/json" : extension === "css" ? "text/css" : extension === "js" ? "text/javascript" : extension === "jsx" ? "text/jsx" : extension === "tsx" ? "text/tsx" : "application/octet-stream";
|
|
37071
37138
|
}
|
|
37072
37139
|
function requestedActions(values) {
|
|
37073
37140
|
const actions = values === void 0 || values.length === 0 ? ["read"] : values;
|
|
@@ -37097,6 +37164,7 @@ function registerShareCommand(program) {
|
|
|
37097
37164
|
const target = parseShareTarget(options.to);
|
|
37098
37165
|
const actions = requestedActions(options.action);
|
|
37099
37166
|
if (options.prefix && target.kind === "bearer") throw new CLIError("INVALID_ARGUMENT", "--prefix requires an addressed target", 2);
|
|
37167
|
+
if (target.kind === "bearer" && actions.includes("edit")) throw new CLIError("INVALID_ARGUMENT", `--action edit is not available with --to ${options.to}: a link can only be read; address a recipient to allow edits`, 2);
|
|
37100
37168
|
if (inputs.length > 1 && target.kind === "bearer") throw new CLIError("UNSUPPORTED_LINK", "multiple files require an addressed target", 2);
|
|
37101
37169
|
const artifact = artifactRequest(options, actions, inputs.length);
|
|
37102
37170
|
if (inputs.length > 1 && !options.prefix) throw new CLIError("INVALID_ARGUMENT", "multiple files require --prefix", 2);
|
|
@@ -37141,11 +37209,11 @@ function registerShareCommand(program) {
|
|
|
37141
37209
|
}
|
|
37142
37210
|
throw new CLIError(result.method === "openkey-device" ? "DEVICE_AUTH_REQUIRED" : "CLAIM_REQUIRED", "recipient authorization is required; continue through the configured authority adapter", 6);
|
|
37143
37211
|
}
|
|
37144
|
-
const { record:
|
|
37212
|
+
const { record: record3, recorded } = await rememberPublishedShare(result);
|
|
37145
37213
|
let notification;
|
|
37146
37214
|
if (notifyRecipient !== void 0) {
|
|
37147
37215
|
if (shareServices.delivery === void 0) throw new CLIError("AUTH_REQUIRED", "delivery authority is not configured", 3);
|
|
37148
|
-
notification = await notifyRecordedShare(
|
|
37216
|
+
notification = await notifyRecordedShare(record3, notifyRecipient, shareServices.delivery, recorded ? shareServices.records : void 0);
|
|
37149
37217
|
if (notification.state === "partial-failure") process.exitCode = 9;
|
|
37150
37218
|
if (notification.reason === "delivery-window-expired") process.stderr.write(NOTIFY_WINDOW_MESSAGE);
|
|
37151
37219
|
}
|
|
@@ -37178,11 +37246,11 @@ function registerShareCommand(program) {
|
|
|
37178
37246
|
if (shareServices.artifactStore === void 0) throw new CLIError("AUTH_REQUIRED", "artifact storage is not configured", 3);
|
|
37179
37247
|
const versions = await listArtifactVersions(await shareServices.artifactStore(), id);
|
|
37180
37248
|
const pinned = /* @__PURE__ */ new Map();
|
|
37181
|
-
for (const
|
|
37182
|
-
const path = parseArtifactVersionPath(
|
|
37249
|
+
for (const record3 of await shareServices.records?.list() ?? []) {
|
|
37250
|
+
const path = parseArtifactVersionPath(record3.resource.path);
|
|
37183
37251
|
if (path === void 0 || path.artifactId !== id) continue;
|
|
37184
37252
|
const shares = pinned.get(path.version) ?? [];
|
|
37185
|
-
shares.push({ shareId:
|
|
37253
|
+
shares.push({ shareId: record3.shareId, target: record3.targetKind ?? record3.recipientMatcher.kind, expiresAt: record3.expiresAt, ...record3.revokedAt === void 0 ? {} : { revokedAt: record3.revokedAt } });
|
|
37186
37254
|
pinned.set(path.version, shares);
|
|
37187
37255
|
}
|
|
37188
37256
|
const view = versions.map((version) => ({
|
|
@@ -37282,19 +37350,19 @@ function registerShareCommand(program) {
|
|
|
37282
37350
|
const json = jsonOutput(options, command);
|
|
37283
37351
|
if (shareServices.delivery === void 0) throw new CLIError("AUTH_REQUIRED", "delivery authority is not configured", 3);
|
|
37284
37352
|
if (shareServices.records === void 0) throw new CLIError("AUTH_REQUIRED", "sender history storage is not configured", 3);
|
|
37285
|
-
const
|
|
37286
|
-
if (
|
|
37287
|
-
if (!
|
|
37353
|
+
const record3 = await shareServices.records.get(id);
|
|
37354
|
+
if (record3 === void 0) throw new CLIError("NOT_FOUND", "share not found", 4);
|
|
37355
|
+
if (!record3.actions.includes("tinycloud.kv/get")) {
|
|
37288
37356
|
throw new CLIError("INVALID_ARGUMENT", "share notify requires a stored share with the read action; no invitation was sent", 2);
|
|
37289
37357
|
}
|
|
37290
37358
|
const mailbox = canonicalMailbox2(options.to);
|
|
37291
37359
|
if (mailbox === void 0) throw new ShareNotifyError("recipient is invalid");
|
|
37292
|
-
if (!recipientMatchesShareRecord(
|
|
37293
|
-
if (
|
|
37360
|
+
if (!recipientMatchesShareRecord(record3, mailbox.email)) throw new ShareNotifyError("recipient does not match the stored share target");
|
|
37361
|
+
if (record3.recipientMatcher.kind === "emailDomain" && shareDeliveryWindowExpiresAt(record3) > Date.now()) {
|
|
37294
37362
|
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);
|
|
37295
37363
|
await shareServices.assertDomainDelivery();
|
|
37296
37364
|
}
|
|
37297
|
-
const result = await notifyRecordedShare(
|
|
37365
|
+
const result = await notifyRecordedShare(record3, options.to, shareServices.delivery, shareServices.records);
|
|
37298
37366
|
if (json) writeJson2(result);
|
|
37299
37367
|
else process.stdout.write(`${result.state}
|
|
37300
37368
|
`);
|
|
@@ -37308,9 +37376,9 @@ function registerShareCommand(program) {
|
|
|
37308
37376
|
try {
|
|
37309
37377
|
const json = jsonOutput(options, command);
|
|
37310
37378
|
if (shareServices.records === void 0) throw new CLIError("AUTH_REQUIRED", "sender history storage is not configured", 3);
|
|
37311
|
-
const
|
|
37312
|
-
if (
|
|
37313
|
-
const result = await revokeShare({ record:
|
|
37379
|
+
const record3 = shareServices.getRecord ? await shareServices.getRecord(id) : await shareServices.records.get(id);
|
|
37380
|
+
if (record3 === void 0) throw new CLIError("NOT_FOUND", "share not found", 4);
|
|
37381
|
+
const result = await revokeShare({ record: record3, records: shareServices.records, adapter: shareServices.revocation, scope: options.ancestor ? "ancestor" : "direct" });
|
|
37314
37382
|
if (result.state === "unsupported") {
|
|
37315
37383
|
throw new CLIError("UNSUPPORTED_TARGET", result.reason, 2);
|
|
37316
37384
|
}
|
|
@@ -37964,12 +38032,12 @@ function sessionPermissionsFromRecap(session) {
|
|
|
37964
38032
|
}
|
|
37965
38033
|
}
|
|
37966
38034
|
function permissionFromRawRecap(value) {
|
|
37967
|
-
const
|
|
37968
|
-
if (!
|
|
37969
|
-
const service = stringValue(
|
|
37970
|
-
const space = stringValue(
|
|
37971
|
-
const path = stringValue(
|
|
37972
|
-
const actions = Array.isArray(
|
|
38035
|
+
const record3 = asRecord(value);
|
|
38036
|
+
if (!record3) return null;
|
|
38037
|
+
const service = stringValue(record3.service);
|
|
38038
|
+
const space = stringValue(record3.space);
|
|
38039
|
+
const path = stringValue(record3.path);
|
|
38040
|
+
const actions = Array.isArray(record3.actions) ? record3.actions.map(String).filter(Boolean) : [];
|
|
37973
38041
|
if (!service || !space || path === null || actions.length === 0) return null;
|
|
37974
38042
|
return {
|
|
37975
38043
|
service: normalizeService2(service),
|
|
@@ -37987,12 +38055,12 @@ function normalizePermissions(entries) {
|
|
|
37987
38055
|
return uniquePermissions(permissions);
|
|
37988
38056
|
}
|
|
37989
38057
|
function permissionFromUnknown(value) {
|
|
37990
|
-
const
|
|
37991
|
-
if (!
|
|
37992
|
-
const service = stringValue(
|
|
37993
|
-
const space = stringValue(
|
|
37994
|
-
const path = stringValue(
|
|
37995
|
-
const actions = Array.isArray(
|
|
38058
|
+
const record3 = asRecord(value);
|
|
38059
|
+
if (!record3) return null;
|
|
38060
|
+
const service = stringValue(record3.service);
|
|
38061
|
+
const space = stringValue(record3.space);
|
|
38062
|
+
const path = stringValue(record3.path);
|
|
38063
|
+
const actions = Array.isArray(record3.actions) ? record3.actions.map(String).filter(Boolean) : [];
|
|
37996
38064
|
if (!service || !space || path === null || actions.length === 0) return null;
|
|
37997
38065
|
return {
|
|
37998
38066
|
service: normalizeService2(service),
|