@tinycloud/operations 0.5.2-beta.1 → 0.5.3-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-name.cjs +32 -0
- package/dist/cli-name.cjs.map +1 -0
- package/dist/cli-name.d.cts +9 -0
- package/dist/cli-name.d.ts +9 -0
- package/dist/cli-name.js +7 -0
- package/dist/cli-name.js.map +1 -0
- package/dist/cli-runtime.cjs +83 -68
- package/dist/cli-runtime.cjs.map +1 -1
- package/dist/cli-runtime.js +28 -13
- package/dist/cli-runtime.js.map +1 -1
- package/dist/index.cjs +83 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +28 -13
- package/dist/index.js.map +1 -1
- package/dist/recovery.cjs +11 -5
- package/dist/recovery.cjs.map +1 -1
- package/dist/recovery.js +9 -5
- package/dist/recovery.js.map +1 -1
- package/dist/secret-request.cjs +7 -1
- package/dist/secret-request.cjs.map +1 -1
- package/dist/secret-request.js +7 -1
- package/dist/secret-request.js.map +1 -1
- package/package.json +10 -5
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,16 @@ var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__
|
|
|
35
35
|
var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
|
|
36
36
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
37
37
|
|
|
38
|
+
// src/cli-name.ts
|
|
39
|
+
var import_node_path, CLI_NAME;
|
|
40
|
+
var init_cli_name = __esm({
|
|
41
|
+
"src/cli-name.ts"() {
|
|
42
|
+
"use strict";
|
|
43
|
+
import_node_path = require("path");
|
|
44
|
+
CLI_NAME = (0, import_node_path.basename)(process.argv[1] ?? "") === "tinycloud" ? "tinycloud" : "tc";
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
38
48
|
// ../sdk-core/src/policy/errors.ts
|
|
39
49
|
var SignedObjectProfileError, SignedObjectCanonicalizationError;
|
|
40
50
|
var init_errors = __esm({
|
|
@@ -4302,8 +4312,8 @@ async function bindLiveness(directory) {
|
|
|
4302
4312
|
await (0, import_promises.rename)(pinned.path(`${socket}.new`), pinned.path(socket));
|
|
4303
4313
|
const stats = await (0, import_promises.lstat)(pinned.path(socket), { bigint: true });
|
|
4304
4314
|
if (!stats.isSocket()) throw new Error(`${socket} is not a socket`);
|
|
4305
|
-
await waitForTestBarrier(TEST_LOCK_LIVENESS_BARRIER_DIR, (0,
|
|
4306
|
-
return { record: { socket, dev: String(stats.dev), ino: String(stats.ino) }, path: (0,
|
|
4315
|
+
await waitForTestBarrier(TEST_LOCK_LIVENESS_BARRIER_DIR, (0, import_node_path2.basename)(directory));
|
|
4316
|
+
return { record: { socket, dev: String(stats.dev), ino: String(stats.ino) }, path: (0, import_node_path2.join)(directory, socket), server };
|
|
4307
4317
|
} catch {
|
|
4308
4318
|
if (bound) {
|
|
4309
4319
|
server.close();
|
|
@@ -4393,26 +4403,26 @@ async function sweepLiveness(acquisition) {
|
|
|
4393
4403
|
}
|
|
4394
4404
|
function tinycloudHomePath() {
|
|
4395
4405
|
const home = invocationStateRoot.getStore() ?? process.env.TC_HOME ?? process.env.HOME ?? process.env.USERPROFILE ?? (0, import_node_os.homedir)();
|
|
4396
|
-
return (0,
|
|
4406
|
+
return (0, import_node_path2.join)(home, ".tinycloud");
|
|
4397
4407
|
}
|
|
4398
4408
|
function withTinyCloudStateRoot(stateRoot, action) {
|
|
4399
4409
|
if (stateRoot === void 0) return action();
|
|
4400
|
-
if (!(0,
|
|
4410
|
+
if (!(0, import_node_path2.isAbsolute)(stateRoot) || stateRoot.includes("\0")) {
|
|
4401
4411
|
throw new TypeError("The TinyCloud state root must be an absolute path.");
|
|
4402
4412
|
}
|
|
4403
|
-
return invocationStateRoot.run((0,
|
|
4413
|
+
return invocationStateRoot.run((0, import_node_path2.resolve)(stateRoot), action);
|
|
4404
4414
|
}
|
|
4405
4415
|
function tinycloudConfigPath() {
|
|
4406
|
-
return (0,
|
|
4416
|
+
return (0, import_node_path2.join)(tinycloudHomePath(), "config.json");
|
|
4407
4417
|
}
|
|
4408
4418
|
function profilesPath() {
|
|
4409
|
-
return (0,
|
|
4419
|
+
return (0, import_node_path2.join)(tinycloudHomePath(), "profiles");
|
|
4410
4420
|
}
|
|
4411
4421
|
function profilePath(profile) {
|
|
4412
|
-
return (0,
|
|
4422
|
+
return (0, import_node_path2.join)(profilesPath(), validateProfileName(profile));
|
|
4413
4423
|
}
|
|
4414
4424
|
function profileConfigPath(profile) {
|
|
4415
|
-
return (0,
|
|
4425
|
+
return (0, import_node_path2.join)(profilePath(profile), "profile.json");
|
|
4416
4426
|
}
|
|
4417
4427
|
function sessionPath(profile) {
|
|
4418
4428
|
return profileStorePath(profile, "session");
|
|
@@ -4421,16 +4431,16 @@ function additionalDelegationsPath(profile) {
|
|
|
4421
4431
|
return profileStorePath(profile, "additional-delegations");
|
|
4422
4432
|
}
|
|
4423
4433
|
function profileStorePath(profile, store) {
|
|
4424
|
-
return (0,
|
|
4434
|
+
return (0, import_node_path2.join)(profilePath(profile), `${store}.json`);
|
|
4425
4435
|
}
|
|
4426
4436
|
function profileStoreMetadataPath(profile, store) {
|
|
4427
4437
|
return `${profileStorePath(profile, store)}.metadata.json`;
|
|
4428
4438
|
}
|
|
4429
4439
|
function profileLockPath(profile) {
|
|
4430
|
-
return (0,
|
|
4440
|
+
return (0, import_node_path2.join)(profilePath(profile), ".lock");
|
|
4431
4441
|
}
|
|
4432
4442
|
function profileTurnLockPath(profile) {
|
|
4433
|
-
return (0,
|
|
4443
|
+
return (0, import_node_path2.join)(tinycloudHomePath(), "profile-locks", validateProfileName(profile));
|
|
4434
4444
|
}
|
|
4435
4445
|
async function readJson(filePath) {
|
|
4436
4446
|
try {
|
|
@@ -4444,10 +4454,10 @@ async function writeJsonAtomic(filePath, value) {
|
|
|
4444
4454
|
await replaceJson(filePath, value, false);
|
|
4445
4455
|
}
|
|
4446
4456
|
async function replaceJson(filePath, value, durable) {
|
|
4447
|
-
const directory = (0,
|
|
4448
|
-
const temporaryPath = (0,
|
|
4457
|
+
const directory = (0, import_node_path2.dirname)(filePath);
|
|
4458
|
+
const temporaryPath = (0, import_node_path2.join)(
|
|
4449
4459
|
directory,
|
|
4450
|
-
`.${(0,
|
|
4460
|
+
`.${(0, import_node_path2.basename)(filePath)}.${process.pid}.${(0, import_node_crypto.randomUUID)()}.tmp`
|
|
4451
4461
|
);
|
|
4452
4462
|
const contents = `${JSON.stringify(value, null, 2)}
|
|
4453
4463
|
`;
|
|
@@ -4560,7 +4570,7 @@ async function acquireProfileLock(profile, options) {
|
|
|
4560
4570
|
const directory = profilePath(profile);
|
|
4561
4571
|
if (options.requireProfile && !await exists(profileConfigPath(profile))) throw new ProfileDeletedError(profile);
|
|
4562
4572
|
if (!options.requireProfile) await (0, import_promises.mkdir)(directory, { recursive: true, mode: PRIVATE_DIR_MODE });
|
|
4563
|
-
await (0, import_promises.mkdir)((0,
|
|
4573
|
+
await (0, import_promises.mkdir)((0, import_node_path2.dirname)(turnDirectory), { recursive: true, mode: PRIVATE_DIR_MODE });
|
|
4564
4574
|
for (const path of [tinycloudHomePath(), profilesPath(), directory]) {
|
|
4565
4575
|
await (0, import_promises.chmod)(path, PRIVATE_DIR_MODE).catch((error) => {
|
|
4566
4576
|
if (path !== directory || !isErrno(error, "ENOENT")) throw error;
|
|
@@ -4583,7 +4593,7 @@ async function acquireProfileLock(profile, options) {
|
|
|
4583
4593
|
await (0, import_promises.rmdir)(directory).catch(() => void 0);
|
|
4584
4594
|
throw new ProfileDeletedError(profile);
|
|
4585
4595
|
}
|
|
4586
|
-
const deletion = await readJson((0,
|
|
4596
|
+
const deletion = await readJson((0, import_node_path2.join)(turnDirectory, "deleted.json")).catch(() => null);
|
|
4587
4597
|
const deletedWhileWaiting = typeof deletion?.slot === "number" && deletion.slot >= firstWaitedTurn;
|
|
4588
4598
|
while (true) {
|
|
4589
4599
|
const token = (0, import_node_crypto.randomUUID)();
|
|
@@ -4676,10 +4686,10 @@ async function readLatestTurn(directory) {
|
|
|
4676
4686
|
return turn === "damaged" ? slot : turn;
|
|
4677
4687
|
}
|
|
4678
4688
|
async function readTurn(directory, slot) {
|
|
4679
|
-
const path = (0,
|
|
4689
|
+
const path = (0, import_node_path2.join)(directory, String(slot));
|
|
4680
4690
|
let text;
|
|
4681
4691
|
try {
|
|
4682
|
-
text = await (0, import_promises.readFile)((0,
|
|
4692
|
+
text = await (0, import_promises.readFile)((0, import_node_path2.join)(path, "owner.json"), "utf8");
|
|
4683
4693
|
} catch (error) {
|
|
4684
4694
|
if (!isErrno(error, "ENOENT") && !isErrno(error, "ENOTDIR")) throw error;
|
|
4685
4695
|
return await exists(path) ? "damaged" : null;
|
|
@@ -4693,8 +4703,8 @@ async function readTurn(directory, slot) {
|
|
|
4693
4703
|
if (owner === null || typeof owner !== "object" || typeof owner.token !== "string" || typeof owner.pid !== "number") {
|
|
4694
4704
|
return "damaged";
|
|
4695
4705
|
}
|
|
4696
|
-
const done = await exists((0,
|
|
4697
|
-
const held = await exists((0,
|
|
4706
|
+
const done = await exists((0, import_node_path2.join)(path, `${owner.token}.done`));
|
|
4707
|
+
const held = await exists((0, import_node_path2.join)(path, `${owner.token}.held`));
|
|
4698
4708
|
return {
|
|
4699
4709
|
...owner,
|
|
4700
4710
|
slot,
|
|
@@ -4713,12 +4723,12 @@ async function isFinishedTurn(directory, slot, token) {
|
|
|
4713
4723
|
async function takeTurn(profile, directory, latest, liveness) {
|
|
4714
4724
|
const token = (0, import_node_crypto.randomUUID)();
|
|
4715
4725
|
const slot = latest.slot + 1;
|
|
4716
|
-
const path = (0,
|
|
4726
|
+
const path = (0, import_node_path2.join)(directory, String(slot));
|
|
4717
4727
|
const owner = { pid: process.pid, createdAt: (/* @__PURE__ */ new Date()).toISOString(), token, after: latest.token, ...processOwner(liveness) };
|
|
4718
4728
|
let published = false;
|
|
4719
4729
|
try {
|
|
4720
4730
|
published = await publishDirectory(
|
|
4721
|
-
(0,
|
|
4731
|
+
(0, import_node_path2.join)(directory, `.stage-${process.pid}-${token}`),
|
|
4722
4732
|
path,
|
|
4723
4733
|
{ "owner.json": `${JSON.stringify(owner, null, 2)}
|
|
4724
4734
|
` },
|
|
@@ -4735,7 +4745,7 @@ async function takeTurn(profile, directory, latest, liveness) {
|
|
|
4735
4745
|
}
|
|
4736
4746
|
}
|
|
4737
4747
|
async function settleAbandonedTurn(directory, abandoned) {
|
|
4738
|
-
const path = (0,
|
|
4748
|
+
const path = (0, import_node_path2.join)(directory, String(abandoned.slot));
|
|
4739
4749
|
if (!abandoned.held && abandoned.after !== null && await isFinishedTurn(directory, abandoned.slot - 1, abandoned.after)) {
|
|
4740
4750
|
await markTurn(path, abandoned.token, "held");
|
|
4741
4751
|
}
|
|
@@ -4756,7 +4766,7 @@ function settleOwnTurn(directory, slot, token, retries = SETTLE_RETRIES) {
|
|
|
4756
4766
|
async function markTurn(path, token, kind) {
|
|
4757
4767
|
for (let attempt = 0; ; attempt++) {
|
|
4758
4768
|
try {
|
|
4759
|
-
await (0, import_promises.writeFile)((0,
|
|
4769
|
+
await (0, import_promises.writeFile)((0, import_node_path2.join)(path, `${token}.${kind}`), "", { mode: PRIVATE_FILE_MODE, flag: "wx" });
|
|
4760
4770
|
return true;
|
|
4761
4771
|
} catch (error) {
|
|
4762
4772
|
if (isErrno(error, "EEXIST")) return true;
|
|
@@ -4769,7 +4779,7 @@ async function markTurn(path, token, kind) {
|
|
|
4769
4779
|
async function createTurnDirectory(directory) {
|
|
4770
4780
|
const token = (0, import_node_crypto.randomUUID)();
|
|
4771
4781
|
const owner = { pid: process.pid, createdAt: (/* @__PURE__ */ new Date()).toISOString(), token, after: null, ...processOwner(null) };
|
|
4772
|
-
await publishDirectory((0,
|
|
4782
|
+
await publishDirectory((0, import_node_path2.join)((0, import_node_path2.dirname)(directory), `.stage-${(0, import_node_path2.basename)(directory)}-${process.pid}-${token}`), directory, {
|
|
4773
4783
|
"0/owner.json": `${JSON.stringify(owner, null, 2)}
|
|
4774
4784
|
`,
|
|
4775
4785
|
[`0/${token}.held`]: "",
|
|
@@ -4779,8 +4789,8 @@ async function createTurnDirectory(directory) {
|
|
|
4779
4789
|
async function publishDirectory(stage, target, files, beforeRename) {
|
|
4780
4790
|
try {
|
|
4781
4791
|
for (const [name, contents] of Object.entries(files)) {
|
|
4782
|
-
await (0, import_promises.mkdir)((0,
|
|
4783
|
-
await writeFileDurably((0,
|
|
4792
|
+
await (0, import_promises.mkdir)((0, import_node_path2.dirname)((0, import_node_path2.join)(stage, name)), { recursive: true, mode: PRIVATE_DIR_MODE });
|
|
4793
|
+
await writeFileDurably((0, import_node_path2.join)(stage, name), contents);
|
|
4784
4794
|
}
|
|
4785
4795
|
await beforeRename?.();
|
|
4786
4796
|
await (0, import_promises.rename)(stage, target);
|
|
@@ -4794,7 +4804,7 @@ async function publishDirectory(stage, target, files, beforeRename) {
|
|
|
4794
4804
|
}
|
|
4795
4805
|
async function releaseTurn(profile, turn, liveness) {
|
|
4796
4806
|
try {
|
|
4797
|
-
await markTurn((0,
|
|
4807
|
+
await markTurn((0, import_node_path2.join)(turn.directory, String(turn.slot)), turn.token, "done");
|
|
4798
4808
|
} catch {
|
|
4799
4809
|
settleOwnTurn(turn.directory, turn.slot, turn.token);
|
|
4800
4810
|
return;
|
|
@@ -4806,13 +4816,13 @@ async function isAbandonedTurnEntry(directory, name, liveness) {
|
|
|
4806
4816
|
const writer = /^\.(?:stage|deleted\.json)[-.]([0-9]+)[-.]/.exec(name)?.[1];
|
|
4807
4817
|
if (writer === void 0) return false;
|
|
4808
4818
|
if (Number(writer) !== process.pid) return !await isRecordedProcessAlive({ pid: Number(writer) }, liveness);
|
|
4809
|
-
return name.startsWith(".stage-") && await isStagedOwnerGone((0,
|
|
4819
|
+
return name.startsWith(".stage-") && await isStagedOwnerGone((0, import_node_path2.join)(directory, name, "owner.json"), liveness);
|
|
4810
4820
|
}
|
|
4811
4821
|
async function isAbandonedTurnDirectoryStage(directory, name, liveness) {
|
|
4812
4822
|
const writer = /^\.stage-.+-([0-9]+)-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.exec(name)?.[1];
|
|
4813
4823
|
if (writer === void 0) return false;
|
|
4814
4824
|
if (Number(writer) !== process.pid) return !await isRecordedProcessAlive({ pid: Number(writer) }, liveness);
|
|
4815
|
-
return isStagedOwnerGone((0,
|
|
4825
|
+
return isStagedOwnerGone((0, import_node_path2.join)(directory, name, "0", "owner.json"), liveness);
|
|
4816
4826
|
}
|
|
4817
4827
|
async function isStagedOwnerGone(recordPath, liveness) {
|
|
4818
4828
|
const owner = await readJson(recordPath).catch(() => null);
|
|
@@ -4821,10 +4831,10 @@ async function isStagedOwnerGone(recordPath, liveness) {
|
|
|
4821
4831
|
async function collectTurns(profile, turn, liveness) {
|
|
4822
4832
|
for (const [directory, abandoned] of [
|
|
4823
4833
|
[turn.directory, isAbandonedTurnEntry],
|
|
4824
|
-
[(0,
|
|
4834
|
+
[(0, import_node_path2.dirname)(turn.directory), isAbandonedTurnDirectoryStage]
|
|
4825
4835
|
]) {
|
|
4826
4836
|
for (const name of await (0, import_promises.readdir)(directory)) {
|
|
4827
|
-
if (await abandoned(directory, name, liveness)) await (0, import_promises.rm)((0,
|
|
4837
|
+
if (await abandoned(directory, name, liveness)) await (0, import_promises.rm)((0, import_node_path2.join)(directory, name), { recursive: true, force: true }).catch(() => void 0);
|
|
4828
4838
|
}
|
|
4829
4839
|
}
|
|
4830
4840
|
const older = (await (0, import_promises.readdir)(turn.directory)).filter((name) => TURN.test(name)).map(Number).filter((slot) => slot < turn.slot).sort((left, right) => left - right);
|
|
@@ -4832,13 +4842,13 @@ async function collectTurns(profile, turn, liveness) {
|
|
|
4832
4842
|
const candidate = await readTurn(turn.directory, slot);
|
|
4833
4843
|
if (candidate === null || candidate === "damaged" || !candidate.done) continue;
|
|
4834
4844
|
if (candidate.held) {
|
|
4835
|
-
if (await exists((0,
|
|
4845
|
+
if (await exists((0, import_node_path2.join)(turn.directory, String(slot - 1)))) continue;
|
|
4836
4846
|
const next = await readTurn(turn.directory, slot + 1);
|
|
4837
4847
|
if (next === null || next === "damaged" || !next.held || !next.done) continue;
|
|
4838
4848
|
}
|
|
4839
4849
|
await waitForTestBarrier(TEST_LOCK_TURN_COLLECT_BARRIER_DIR, profile);
|
|
4840
|
-
const trash = (0,
|
|
4841
|
-
if (await (0, import_promises.rename)((0,
|
|
4850
|
+
const trash = (0, import_node_path2.join)(turn.directory, `.trash-${(0, import_node_crypto.randomUUID)()}`);
|
|
4851
|
+
if (await (0, import_promises.rename)((0, import_node_path2.join)(turn.directory, String(slot)), trash).then(() => true, () => false)) {
|
|
4842
4852
|
await (0, import_promises.rm)(trash, { recursive: true, force: true }).catch(() => void 0);
|
|
4843
4853
|
}
|
|
4844
4854
|
}
|
|
@@ -4855,8 +4865,8 @@ async function publishProfileLock(profile, lockPath, token, requireProfile, live
|
|
|
4855
4865
|
return false;
|
|
4856
4866
|
}
|
|
4857
4867
|
await waitForTestBarrier(TEST_LOCK_PUBLISH_BARRIER_DIR, profile);
|
|
4858
|
-
const ownerPath = (0,
|
|
4859
|
-
const staged = (0,
|
|
4868
|
+
const ownerPath = (0, import_node_path2.join)(lockPath, "owner.json");
|
|
4869
|
+
const staged = (0, import_node_path2.join)((0, import_node_path2.dirname)(lockPath), `.lock-owner-${token}.tmp`);
|
|
4860
4870
|
const owner = `${JSON.stringify({ pid: process.pid, createdAt: (/* @__PURE__ */ new Date()).toISOString(), token, ...processOwner(liveness) }, null, 2)}
|
|
4861
4871
|
`;
|
|
4862
4872
|
try {
|
|
@@ -4880,7 +4890,7 @@ function lacksHardLinks(error) {
|
|
|
4880
4890
|
return typeof error === "object" && error !== null && "code" in error && NO_HARD_LINK_ERRORS.has(String(error.code));
|
|
4881
4891
|
}
|
|
4882
4892
|
async function releaseProfileLock(profile, lockPath, token) {
|
|
4883
|
-
const ownerPath = (0,
|
|
4893
|
+
const ownerPath = (0, import_node_path2.join)(lockPath, "owner.json");
|
|
4884
4894
|
const owner = await readJson(ownerPath).catch(() => null);
|
|
4885
4895
|
if (owner?.token !== token) return;
|
|
4886
4896
|
await (0, import_promises.rm)(ownerPath, { force: true });
|
|
@@ -4892,9 +4902,9 @@ async function signalTestLockContention(profile) {
|
|
|
4892
4902
|
const configuredPath = process.env[TEST_LOCK_CONTENTION_SIGNAL_PATH];
|
|
4893
4903
|
const configuredHome = process.env.TC_HOME;
|
|
4894
4904
|
if (!configuredPath || !configuredHome) return;
|
|
4895
|
-
const home = (0,
|
|
4896
|
-
const signalPath = (0,
|
|
4897
|
-
const pathFromHome = (0,
|
|
4905
|
+
const home = (0, import_node_path2.resolve)(configuredHome);
|
|
4906
|
+
const signalPath = (0, import_node_path2.resolve)(configuredPath);
|
|
4907
|
+
const pathFromHome = (0, import_node_path2.relative)(home, signalPath);
|
|
4898
4908
|
if (pathFromHome === "" || pathFromHome === ".." || pathFromHome.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || pathFromHome.startsWith("../") || pathFromHome.startsWith("..\\")) {
|
|
4899
4909
|
return;
|
|
4900
4910
|
}
|
|
@@ -4917,15 +4927,15 @@ async function recoverOwnerlessLock(profile, lockPath, liveness, staleAfterMs) {
|
|
|
4917
4927
|
const onlyOrphanedClaims = entries.length > 0 && entries.every((entry) => RECOVERY_CLAIM.test(entry));
|
|
4918
4928
|
if (!onlyOrphanedClaims && (!aged || recoveryFenced(checkedAt, staleAfterMs))) return false;
|
|
4919
4929
|
for (const name of entries.filter((entry) => RECOVERY_CLAIM.test(entry))) {
|
|
4920
|
-
const claimPath = (0,
|
|
4930
|
+
const claimPath = (0, import_node_path2.join)(lockPath, name);
|
|
4921
4931
|
if (await hasLiveRecoveryOwner(claimPath, liveness)) {
|
|
4922
|
-
if (!await exists((0,
|
|
4932
|
+
if (!await exists((0, import_node_path2.join)(lockPath, "owner.json"))) await (0, import_promises.rename)(claimPath, (0, import_node_path2.join)(lockPath, "owner.json"));
|
|
4923
4933
|
return false;
|
|
4924
4934
|
}
|
|
4925
4935
|
await (0, import_promises.rm)(claimPath, { force: true });
|
|
4926
4936
|
}
|
|
4927
4937
|
for (const name of entries.filter((entry) => ABANDONED_CLAIM.test(entry))) {
|
|
4928
|
-
await (0, import_promises.rm)((0,
|
|
4938
|
+
await (0, import_promises.rm)((0, import_node_path2.join)(lockPath, name), { force: true });
|
|
4929
4939
|
}
|
|
4930
4940
|
await (0, import_promises.rmdir)(lockPath);
|
|
4931
4941
|
} catch {
|
|
@@ -4955,21 +4965,21 @@ function recoveryFenced(since, staleAfterMs) {
|
|
|
4955
4965
|
return performance.now() - since >= staleAfterMs / 2;
|
|
4956
4966
|
}
|
|
4957
4967
|
async function removeAgedOwnerFiles(lockPath, staleAfterMs) {
|
|
4958
|
-
const directory = (0,
|
|
4968
|
+
const directory = (0, import_node_path2.dirname)(lockPath);
|
|
4959
4969
|
const names = await (0, import_promises.readdir)(directory).catch(() => []);
|
|
4960
4970
|
for (const name of names.filter((entry) => STAGED_OWNER.test(entry))) {
|
|
4961
|
-
const path = (0,
|
|
4971
|
+
const path = (0, import_node_path2.join)(directory, name);
|
|
4962
4972
|
const aged = await (0, import_promises.stat)(path).then(({ mtimeMs }) => Date.now() - mtimeMs >= staleAfterMs, () => false);
|
|
4963
4973
|
if (aged) await (0, import_promises.rm)(path, { force: true }).catch(() => void 0);
|
|
4964
4974
|
}
|
|
4965
4975
|
}
|
|
4966
4976
|
async function recoverStaleLock(profile, lockPath, liveness, staleAfterMs) {
|
|
4967
|
-
const ownerPath = (0,
|
|
4977
|
+
const ownerPath = (0, import_node_path2.join)(lockPath, "owner.json");
|
|
4968
4978
|
const observed = await (0, import_promises.readFile)(ownerPath, "utf8").catch(() => null);
|
|
4969
4979
|
if (observed === null) return recoverOwnerlessLock(profile, lockPath, liveness, staleAfterMs);
|
|
4970
4980
|
if (!await isAbandonedOwner(observed, ownerPath, liveness, staleAfterMs)) return false;
|
|
4971
4981
|
await waitForTestBarrier(TEST_LOCK_RECOVERY_BARRIER_DIR, profile);
|
|
4972
|
-
const claimPath = (0,
|
|
4982
|
+
const claimPath = (0, import_node_path2.join)(lockPath, `.recover-${(0, import_node_crypto.randomUUID)()}.json`);
|
|
4973
4983
|
let moved = false;
|
|
4974
4984
|
try {
|
|
4975
4985
|
await (0, import_promises.link)(ownerPath, claimPath);
|
|
@@ -4997,7 +5007,7 @@ async function recoverStaleLock(profile, lockPath, liveness, staleAfterMs) {
|
|
|
4997
5007
|
await waitForTestBarrier(TEST_LOCK_CLAIM_BARRIER_DIR, profile);
|
|
4998
5008
|
await waitForTestBarrier(TEST_LOCK_CLAIMED_BARRIER_DIR, profile);
|
|
4999
5009
|
for (const name of (await (0, import_promises.readdir)(lockPath).catch(() => [])).filter((entry) => RECOVERY_CLAIM.test(entry))) {
|
|
5000
|
-
if ((0,
|
|
5010
|
+
if ((0, import_node_path2.join)(lockPath, name) !== claimPath) await (0, import_promises.rm)((0, import_node_path2.join)(lockPath, name), { force: true });
|
|
5001
5011
|
}
|
|
5002
5012
|
if (await (0, import_promises.unlink)(claimPath).then(() => true, () => false)) await (0, import_promises.rmdir)(lockPath).catch(() => void 0);
|
|
5003
5013
|
await removeAgedOwnerFiles(lockPath, staleAfterMs);
|
|
@@ -5021,9 +5031,9 @@ async function waitForTestBarrier(environmentName, profile) {
|
|
|
5021
5031
|
const barrierDirectory = process.env[environmentName];
|
|
5022
5032
|
if (!barrierDirectory) return;
|
|
5023
5033
|
await (0, import_promises.mkdir)(barrierDirectory, { recursive: true });
|
|
5024
|
-
const readyPath = (0,
|
|
5034
|
+
const readyPath = (0, import_node_path2.join)(barrierDirectory, `ready-${process.pid}-${profile}`);
|
|
5025
5035
|
await (0, import_promises.writeFile)(readyPath, "ready\n", { encoding: "utf8", flag: "wx" }).catch(() => void 0);
|
|
5026
|
-
const releasePath = (0,
|
|
5036
|
+
const releasePath = (0, import_node_path2.join)(barrierDirectory, "release");
|
|
5027
5037
|
while (true) {
|
|
5028
5038
|
try {
|
|
5029
5039
|
await (0, import_promises.readFile)(releasePath, "utf8");
|
|
@@ -5080,7 +5090,7 @@ function isErrno(error, code) {
|
|
|
5080
5090
|
function sleep(milliseconds) {
|
|
5081
5091
|
return new Promise((resolve2) => setTimeout(resolve2, milliseconds));
|
|
5082
5092
|
}
|
|
5083
|
-
var import_node_crypto, import_node_async_hooks, import_node_fs, import_promises, import_node_net, import_node_os,
|
|
5093
|
+
var import_node_crypto, import_node_async_hooks, import_node_fs, import_promises, import_node_net, import_node_os, import_node_path2, DEFAULT_PROFILE, DEFAULT_LOCK_TIMEOUT_MS, DEFAULT_LOCK_RETRY_MS, DEFAULT_STALE_LOCK_MS, TEST_LOCK_CONTENTION_SIGNAL_PATH, PRIVATE_FILE_MODE, PRIVATE_DIR_MODE, TEST_LOCK_RECOVERY_BARRIER_DIR, TEST_LOCK_OWNERLESS_BARRIER_DIR, TEST_LOCK_PUBLISH_BARRIER_DIR, TEST_LOCK_RELEASE_BARRIER_DIR, TEST_LOCK_CLAIM_BARRIER_DIR, TEST_LOCK_CLAIMED_BARRIER_DIR, TEST_LOCK_VERIFIED_BARRIER_DIR, TEST_LOCK_MOVED_BARRIER_DIR, TEST_LOCK_TURN_PUBLISH_BARRIER_DIR, TEST_LOCK_TURN_SETTLE_BARRIER_DIR, TEST_LOCK_TURN_COLLECT_BARRIER_DIR, TEST_LOCK_LIVENESS_BARRIER_DIR, invocationStateRoot, heldProfileLocks, _a2, processInstanceId, cachedProcessOrigin, LIVENESS_SOCKET, LIVENESS_PROBE_TIMEOUT_MS, ProfileLockTimeoutError, ProfileDeletedError, TURN, _a3, relinquishedTurns, MARKER_RETRY_DELAYS_MS, SETTLE_RETRY_MS, SETTLE_RETRIES, NO_HARD_LINK_ERRORS, ABANDONED_CLAIM, RECOVERY_CLAIM, STAGED_OWNER;
|
|
5084
5094
|
var init_state = __esm({
|
|
5085
5095
|
"src/state.ts"() {
|
|
5086
5096
|
"use strict";
|
|
@@ -5090,7 +5100,7 @@ var init_state = __esm({
|
|
|
5090
5100
|
import_promises = require("fs/promises");
|
|
5091
5101
|
import_node_net = require("net");
|
|
5092
5102
|
import_node_os = require("os");
|
|
5093
|
-
|
|
5103
|
+
import_node_path2 = require("path");
|
|
5094
5104
|
DEFAULT_PROFILE = "default";
|
|
5095
5105
|
DEFAULT_LOCK_TIMEOUT_MS = 2e3;
|
|
5096
5106
|
DEFAULT_LOCK_RETRY_MS = 25;
|
|
@@ -5443,7 +5453,7 @@ function isSafeRecovery(value, action) {
|
|
|
5443
5453
|
if (!("command" in record)) return true;
|
|
5444
5454
|
const command = record.command;
|
|
5445
5455
|
if (typeof command !== "string") return false;
|
|
5446
|
-
const profile =
|
|
5456
|
+
const profile = /^\S+ --profile (\S+) /.exec(command)?.[1];
|
|
5447
5457
|
if (profile === void 0 || !SAFE_PROFILE_TOKEN.test(profile)) return false;
|
|
5448
5458
|
return action === "sign_in" ? Object.values(SIGN_IN_TEMPLATES).some((template) => template(profile) === command) : migrationCommand(profile) === command;
|
|
5449
5459
|
}
|
|
@@ -5451,14 +5461,15 @@ var SAFE_PROFILE_TOKEN, MIGRATION_OPERATION_ID, SIGN_IN_TEMPLATES, migrationComm
|
|
|
5451
5461
|
var init_recovery = __esm({
|
|
5452
5462
|
"src/recovery.ts"() {
|
|
5453
5463
|
"use strict";
|
|
5464
|
+
init_cli_name();
|
|
5454
5465
|
SAFE_PROFILE_TOKEN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
5455
5466
|
MIGRATION_OPERATION_ID = "tinycloud.auth.capabilities";
|
|
5456
5467
|
SIGN_IN_TEMPLATES = {
|
|
5457
|
-
local: (profile) =>
|
|
5458
|
-
openkey: (profile) =>
|
|
5459
|
-
scoped: (profile) =>
|
|
5468
|
+
local: (profile) => `${CLI_NAME} --profile ${profile} auth login --method local`,
|
|
5469
|
+
openkey: (profile) => `${CLI_NAME} --profile ${profile} auth login --method openkey`,
|
|
5470
|
+
scoped: (profile) => `${CLI_NAME} --profile ${profile} auth login --method openkey --paste --manifest <manifest.json>`
|
|
5460
5471
|
};
|
|
5461
|
-
migrationCommand = (profile) =>
|
|
5472
|
+
migrationCommand = (profile) => `${CLI_NAME} --profile ${profile} auth caps`;
|
|
5462
5473
|
}
|
|
5463
5474
|
});
|
|
5464
5475
|
|
|
@@ -6960,7 +6971,7 @@ function ownerOfSpace(space) {
|
|
|
6960
6971
|
return ownerOrUndefined(`did:pkh:eip155:${match[1]}:${match[2].toLowerCase()}`);
|
|
6961
6972
|
}
|
|
6962
6973
|
function putCommands(names, scope) {
|
|
6963
|
-
return dedupe(names).map((name) =>
|
|
6974
|
+
return dedupe(names).map((name) => `${CLI_NAME} secrets put ${name}${scope === void 0 ? "" : ` --scope ${scope}`} --stdin`).join("; ");
|
|
6964
6975
|
}
|
|
6965
6976
|
function dedupe(names) {
|
|
6966
6977
|
return [...new Set(names)];
|
|
@@ -6973,6 +6984,7 @@ var init_secret_request = __esm({
|
|
|
6973
6984
|
"src/secret-request.ts"() {
|
|
6974
6985
|
"use strict";
|
|
6975
6986
|
nodeSdk3 = __toESM(require("@tinycloud/node-sdk"), 1);
|
|
6987
|
+
init_cli_name();
|
|
6976
6988
|
SECRET_MANAGER_ORIGIN = "https://secrets.tinycloud.xyz";
|
|
6977
6989
|
SECRET_REQUEST_MAX_NAMES = 10;
|
|
6978
6990
|
SECRET_REQUEST_MAX_URL_LENGTH = 8192;
|
|
@@ -7081,7 +7093,7 @@ function classifySecretRead(reference, result, localOwner) {
|
|
|
7081
7093
|
approval: {
|
|
7082
7094
|
kind: "openkey",
|
|
7083
7095
|
requestId: "runtime-hint",
|
|
7084
|
-
fallback:
|
|
7096
|
+
fallback: `${CLI_NAME} auth grant <request-artifact>`
|
|
7085
7097
|
}
|
|
7086
7098
|
};
|
|
7087
7099
|
case "node_unreachable":
|
|
@@ -7184,6 +7196,7 @@ var init_secrets_get = __esm({
|
|
|
7184
7196
|
"src/operations/secrets-get.ts"() {
|
|
7185
7197
|
"use strict";
|
|
7186
7198
|
import_zod5 = require("zod");
|
|
7199
|
+
init_cli_name();
|
|
7187
7200
|
init_errors2();
|
|
7188
7201
|
init_secret_request();
|
|
7189
7202
|
init_secrets();
|
|
@@ -7996,7 +8009,7 @@ var init_contract = __esm({
|
|
|
7996
8009
|
|
|
7997
8010
|
// src/delegation-binding.ts
|
|
7998
8011
|
function bindingMigrationPath(profile) {
|
|
7999
|
-
return (0,
|
|
8012
|
+
return (0, import_node_path3.join)(profilePath(profile), "delegation-binding-migration.json");
|
|
8000
8013
|
}
|
|
8001
8014
|
function storedDelegationKind(entry) {
|
|
8002
8015
|
if (!isRecord4(entry)) return "refused";
|
|
@@ -8251,11 +8264,11 @@ function recordKey(entry) {
|
|
|
8251
8264
|
function isRecord4(value) {
|
|
8252
8265
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8253
8266
|
}
|
|
8254
|
-
var
|
|
8267
|
+
var import_node_path3, nodeSdk5, REQUEST_ID_PREFIX, BINDING_NOTES, MIGRATION_LOCK_TIMEOUT_MS, NOT_REPLAYED, DELEGATION_CID;
|
|
8255
8268
|
var init_delegation_binding = __esm({
|
|
8256
8269
|
"src/delegation-binding.ts"() {
|
|
8257
8270
|
"use strict";
|
|
8258
|
-
|
|
8271
|
+
import_node_path3 = require("path");
|
|
8259
8272
|
init_operations_bundle();
|
|
8260
8273
|
nodeSdk5 = __toESM(require("@tinycloud/node-sdk"), 1);
|
|
8261
8274
|
init_artifacts();
|
|
@@ -8812,7 +8825,7 @@ async function createRestoredRuntime(target, resolved) {
|
|
|
8812
8825
|
)) {
|
|
8813
8826
|
return failed(summary, operationError(
|
|
8814
8827
|
"PROFILE_MIGRATION_REQUIRED",
|
|
8815
|
-
`Profile "${profileName}" has a one-time stored-grant upgrade to finish. Run one authenticated command on it (
|
|
8828
|
+
`Profile "${profileName}" has a one-time stored-grant upgrade to finish. Run one authenticated command on it (${CLI_NAME} --profile <profile> auth caps), then retry.`,
|
|
8816
8829
|
{ retryable: false, details: { recovery: migrationRecovery(profileName) } }
|
|
8817
8830
|
));
|
|
8818
8831
|
}
|
|
@@ -8923,6 +8936,7 @@ var nodeSdk6;
|
|
|
8923
8936
|
var init_runtime = __esm({
|
|
8924
8937
|
"src/runtime.ts"() {
|
|
8925
8938
|
"use strict";
|
|
8939
|
+
init_cli_name();
|
|
8926
8940
|
nodeSdk6 = __toESM(require("@tinycloud/node-sdk"), 1);
|
|
8927
8941
|
init_authority();
|
|
8928
8942
|
init_errors2();
|
|
@@ -8943,7 +8957,8 @@ module.exports = __toCommonJS(index_exports);
|
|
|
8943
8957
|
|
|
8944
8958
|
// src/invoke.ts
|
|
8945
8959
|
var import_node_crypto3 = require("crypto");
|
|
8946
|
-
var
|
|
8960
|
+
var import_node_path4 = require("path");
|
|
8961
|
+
init_cli_name();
|
|
8947
8962
|
var import_node_sdk = require("@tinycloud/node-sdk");
|
|
8948
8963
|
init_jcs();
|
|
8949
8964
|
init_errors2();
|
|
@@ -9515,7 +9530,7 @@ function normalizeInvocationTarget(target) {
|
|
|
9515
9530
|
const stateRoot = candidate.stateRoot;
|
|
9516
9531
|
const allowOwnerProfile = candidate.allowOwnerProfile;
|
|
9517
9532
|
const privateKey = candidate.privateKey;
|
|
9518
|
-
if (profile !== void 0 && typeof profile !== "string" || host !== void 0 && typeof host !== "string" || stateRoot !== void 0 && (typeof stateRoot !== "string" || !(0,
|
|
9533
|
+
if (profile !== void 0 && typeof profile !== "string" || host !== void 0 && typeof host !== "string" || stateRoot !== void 0 && (typeof stateRoot !== "string" || !(0, import_node_path4.isAbsolute)(stateRoot)) || allowOwnerProfile !== void 0 && typeof allowOwnerProfile !== "boolean" || privateKey !== void 0 && typeof privateKey !== "string") {
|
|
9519
9534
|
return void 0;
|
|
9520
9535
|
}
|
|
9521
9536
|
return {
|
|
@@ -9636,7 +9651,7 @@ function approvalAction(request, node) {
|
|
|
9636
9651
|
kind: "openkey",
|
|
9637
9652
|
requestId: request.requestId,
|
|
9638
9653
|
...url === void 0 ? {} : { url },
|
|
9639
|
-
fallback:
|
|
9654
|
+
fallback: `${CLI_NAME} auth grant <request-artifact>`
|
|
9640
9655
|
};
|
|
9641
9656
|
}
|
|
9642
9657
|
function exactCapabilities2(value) {
|