@rosthq/cli 0.7.162 → 0.7.163
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
CHANGED
|
@@ -29434,6 +29434,19 @@ var runnerPairingStartOutputSchema = external_exports.object({
|
|
|
29434
29434
|
expires_at: isoDateTime2,
|
|
29435
29435
|
expires_in: external_exports.number().int().nonnegative()
|
|
29436
29436
|
}).strict();
|
|
29437
|
+
var runnerPairingClaimInputSchema = external_exports.object({
|
|
29438
|
+
user_code: external_exports.string().min(8).max(12),
|
|
29439
|
+
service_key_public: external_exports.string().trim().min(1).max(1024).optional()
|
|
29440
|
+
}).strict();
|
|
29441
|
+
var runnerPairingClaimOutputSchema = external_exports.object({
|
|
29442
|
+
runner_id: uuid5,
|
|
29443
|
+
tenant_id: uuid5,
|
|
29444
|
+
runner_secret: external_exports.string().min(1),
|
|
29445
|
+
name: external_exports.string(),
|
|
29446
|
+
platform: external_exports.string(),
|
|
29447
|
+
service_key_generation: external_exports.number().int().nonnegative().optional(),
|
|
29448
|
+
service_key_bound: external_exports.boolean().optional()
|
|
29449
|
+
}).strict();
|
|
29437
29450
|
var runnerRevokeInputSchema = external_exports.object({
|
|
29438
29451
|
runner_id: uuid5
|
|
29439
29452
|
}).strict();
|
|
@@ -69609,7 +69622,7 @@ async function removeWorkspace(ws) {
|
|
|
69609
69622
|
|
|
69610
69623
|
// src/runner-serve.ts
|
|
69611
69624
|
import { execFile as execFileCallback5, spawn } from "node:child_process";
|
|
69612
|
-
import { createHash as createHash4, randomUUID } from "node:crypto";
|
|
69625
|
+
import { createHash as createHash4, createPrivateKey, createPublicKey as createPublicKey2, generateKeyPairSync, randomUUID } from "node:crypto";
|
|
69613
69626
|
import { constants as fsConstants6 } from "node:fs";
|
|
69614
69627
|
import { access as access3, chmod as chmod2, lstat as lstat2, mkdir as mkdir8, open as open2, readFile as readFile11, rename as rename2, rm as rm8, statfs, writeFile as writeFile8 } from "node:fs/promises";
|
|
69615
69628
|
import { cpus, homedir as homedir7, hostname as hostname3, platform, totalmem, tmpdir as tmpdir2 } from "node:os";
|
|
@@ -70369,16 +70382,20 @@ async function pairIfNeeded(client, fetchImpl, appUrl2, config2, io) {
|
|
|
70369
70382
|
`No paired runner state at ${config2.stateFile}. Provide --user-code <code> from Settings > Runners (Add a runner), or run \`${cliBrand.binName} login --device\` once to pair this runner.`
|
|
70370
70383
|
);
|
|
70371
70384
|
}
|
|
70385
|
+
const serviceKey = runnerServiceKeyPairForState(priorState);
|
|
70372
70386
|
const { runnerId, runnerSecret, tenantId: claimedTenantId, name: claimedName } = await claimRunnerPairingCode(
|
|
70373
70387
|
fetchImpl,
|
|
70374
70388
|
appUrl2,
|
|
70375
|
-
userCode
|
|
70389
|
+
userCode,
|
|
70390
|
+
serviceKey
|
|
70376
70391
|
);
|
|
70377
70392
|
const state = {
|
|
70378
70393
|
runner_id: runnerId,
|
|
70379
70394
|
runner_secret: runnerSecret,
|
|
70380
70395
|
...typeof claimedTenantId === "string" ? { tenant_id: claimedTenantId } : config2.expectedTenantId ? { tenant_id: config2.expectedTenantId } : {},
|
|
70381
|
-
name: typeof claimedName === "string" ? claimedName : config2.name
|
|
70396
|
+
name: typeof claimedName === "string" ? claimedName : config2.name,
|
|
70397
|
+
service_key_private: serviceKey.privateKey,
|
|
70398
|
+
service_key_public: serviceKey.publicKey
|
|
70382
70399
|
};
|
|
70383
70400
|
await saveState(config2.stateFile, state);
|
|
70384
70401
|
await reapSupersededRunnerHomes(priorState, runnerId, config2.homeDir);
|
|
@@ -70462,6 +70479,8 @@ async function loadState(filePath, expectedTenantId) {
|
|
|
70462
70479
|
runner_secret: parsed.runner_secret,
|
|
70463
70480
|
...typeof parsed.tenant_id === "string" ? { tenant_id: parsed.tenant_id } : {},
|
|
70464
70481
|
...typeof parsed.name === "string" ? { name: parsed.name } : {},
|
|
70482
|
+
...typeof parsed.service_key_private === "string" ? { service_key_private: parsed.service_key_private } : {},
|
|
70483
|
+
...typeof parsed.service_key_public === "string" ? { service_key_public: parsed.service_key_public } : {},
|
|
70465
70484
|
...isRuntimeSessionMap(parsed.runtime_sessions) ? { runtime_sessions: parsed.runtime_sessions } : {},
|
|
70466
70485
|
...isInFlightWorkOrderMap(parsed.in_flight_work_orders) ? { in_flight_work_orders: parsed.in_flight_work_orders } : {}
|
|
70467
70486
|
};
|
|
@@ -70496,8 +70515,56 @@ async function saveState(filePath, state) {
|
|
|
70496
70515
|
throw error51;
|
|
70497
70516
|
}
|
|
70498
70517
|
}
|
|
70499
|
-
|
|
70500
|
-
|
|
70518
|
+
var RUNNER_SERVICE_KEY_REPAIR_MESSAGE = "The persisted runner service key is invalid. Repair the local service-key state, then re-pair the runner or use explicit service-key rotation.";
|
|
70519
|
+
var RunnerServiceKeyError = class extends Error {
|
|
70520
|
+
code = "service_key_invalid";
|
|
70521
|
+
constructor() {
|
|
70522
|
+
super(RUNNER_SERVICE_KEY_REPAIR_MESSAGE);
|
|
70523
|
+
this.name = "RunnerServiceKeyError";
|
|
70524
|
+
}
|
|
70525
|
+
};
|
|
70526
|
+
function sshWireField(value) {
|
|
70527
|
+
const bytes = Buffer.isBuffer(value) ? value : Buffer.from(value, "utf8");
|
|
70528
|
+
const length = Buffer.allocUnsafe(4);
|
|
70529
|
+
length.writeUInt32BE(bytes.length, 0);
|
|
70530
|
+
return Buffer.concat([length, bytes]);
|
|
70531
|
+
}
|
|
70532
|
+
function openSshEd25519PublicKey(publicKey) {
|
|
70533
|
+
const der = publicKey.export({ type: "spki", format: "der" });
|
|
70534
|
+
if (!Buffer.isBuffer(der) || der.length < 32) {
|
|
70535
|
+
throw new Error("Unable to encode the runner service key.");
|
|
70536
|
+
}
|
|
70537
|
+
const rawKey = der.subarray(der.length - 32);
|
|
70538
|
+
const wire = Buffer.concat([sshWireField("ssh-ed25519"), sshWireField(rawKey)]);
|
|
70539
|
+
return `ssh-ed25519 ${wire.toString("base64")}`;
|
|
70540
|
+
}
|
|
70541
|
+
function generateRunnerServiceKeyPair() {
|
|
70542
|
+
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
70543
|
+
const privatePem = privateKey.export({ type: "pkcs8", format: "pem" });
|
|
70544
|
+
if (typeof privatePem !== "string") {
|
|
70545
|
+
throw new Error("Unable to persist the runner service key.");
|
|
70546
|
+
}
|
|
70547
|
+
return { privateKey: privatePem, publicKey: openSshEd25519PublicKey(publicKey) };
|
|
70548
|
+
}
|
|
70549
|
+
function runnerServiceKeyPairFromPrivate(privatePem) {
|
|
70550
|
+
const privateKey = createPrivateKey(privatePem);
|
|
70551
|
+
return { privateKey: privatePem, publicKey: openSshEd25519PublicKey(createPublicKey2(privateKey)) };
|
|
70552
|
+
}
|
|
70553
|
+
function runnerServiceKeyPairForState(state) {
|
|
70554
|
+
if (state?.service_key_private === void 0) {
|
|
70555
|
+
return generateRunnerServiceKeyPair();
|
|
70556
|
+
}
|
|
70557
|
+
try {
|
|
70558
|
+
return runnerServiceKeyPairFromPrivate(state.service_key_private);
|
|
70559
|
+
} catch {
|
|
70560
|
+
throw new RunnerServiceKeyError();
|
|
70561
|
+
}
|
|
70562
|
+
}
|
|
70563
|
+
async function claimRunnerPairingCode(fetchImpl, appUrl2, userCode, serviceKey) {
|
|
70564
|
+
const claim = await post2(fetchImpl, appUrl2, "/api/runner/pairing/claim", {
|
|
70565
|
+
user_code: userCode,
|
|
70566
|
+
...serviceKey ? { service_key_public: serviceKey.publicKey } : {}
|
|
70567
|
+
});
|
|
70501
70568
|
const runnerSecret = claim.json.runner_secret;
|
|
70502
70569
|
const runnerId = claim.json.runner_id;
|
|
70503
70570
|
const tenantId = claim.json.tenant_id;
|
|
@@ -70508,7 +70575,10 @@ async function claimRunnerPairingCode(fetchImpl, appUrl2, userCode) {
|
|
|
70508
70575
|
runnerId,
|
|
70509
70576
|
runnerSecret,
|
|
70510
70577
|
tenantId: typeof tenantId === "string" ? tenantId : null,
|
|
70511
|
-
name: typeof claim.json.name === "string" ? claim.json.name : null
|
|
70578
|
+
name: typeof claim.json.name === "string" ? claim.json.name : null,
|
|
70579
|
+
...serviceKey ? { serviceKeyPrivate: serviceKey.privateKey, serviceKeyPublic: serviceKey.publicKey } : {},
|
|
70580
|
+
...typeof claim.json.service_key_generation === "number" ? { serviceKeyGeneration: claim.json.service_key_generation } : {},
|
|
70581
|
+
...typeof claim.json.service_key_bound === "boolean" ? { serviceKeyBound: claim.json.service_key_bound } : {}
|
|
70512
70582
|
};
|
|
70513
70583
|
}
|
|
70514
70584
|
async function startPairing(client, config2) {
|
|
@@ -73974,7 +74044,14 @@ async function runPairingStage(sidecar, userCode, agent, fetchImpl, appUrl2, hom
|
|
|
73974
74044
|
}
|
|
73975
74045
|
if (userCode !== void 0) {
|
|
73976
74046
|
const priorState = await loadState(sidecar.state_file, expectedTenantId);
|
|
73977
|
-
|
|
74047
|
+
let serviceKey;
|
|
74048
|
+
try {
|
|
74049
|
+
serviceKey = runnerServiceKeyPairForState(priorState);
|
|
74050
|
+
} catch (error51) {
|
|
74051
|
+
const message = error51 instanceof RunnerServiceKeyError ? error51.message : RUNNER_SERVICE_KEY_REPAIR_MESSAGE;
|
|
74052
|
+
return { kind: "claim_failed", exitCode: 1, message: redactForLog(message) };
|
|
74053
|
+
}
|
|
74054
|
+
const claimResult = await claimRunnerPairingCodeSafe(fetchImpl, appUrl2, userCode, serviceKey);
|
|
73978
74055
|
if (!claimResult.ok) {
|
|
73979
74056
|
return { kind: "claim_failed", exitCode: claimResult.exitCode, message: claimResult.message };
|
|
73980
74057
|
}
|
|
@@ -73996,7 +74073,9 @@ async function runPairingStage(sidecar, userCode, agent, fetchImpl, appUrl2, hom
|
|
|
73996
74073
|
runner_id: claimResult.runnerId,
|
|
73997
74074
|
runner_secret: claimResult.runnerSecret,
|
|
73998
74075
|
...claimResult.tenantId !== null ? { tenant_id: claimResult.tenantId } : {},
|
|
73999
|
-
...claimResult.name !== null ? { name: claimResult.name } : {}
|
|
74076
|
+
...claimResult.name !== null ? { name: claimResult.name } : {},
|
|
74077
|
+
...claimResult.serviceKeyPrivate !== void 0 ? { service_key_private: claimResult.serviceKeyPrivate } : {},
|
|
74078
|
+
...claimResult.serviceKeyPublic !== void 0 ? { service_key_public: claimResult.serviceKeyPublic } : {}
|
|
74000
74079
|
};
|
|
74001
74080
|
await saveState(sidecar.state_file, newState);
|
|
74002
74081
|
await reapSupersededRunnerHomes(priorState, newState.runner_id, homeDir);
|
|
@@ -74021,9 +74100,9 @@ async function runPairingStage(sidecar, userCode, agent, fetchImpl, appUrl2, hom
|
|
|
74021
74100
|
}
|
|
74022
74101
|
return { kind: "needs_user_code" };
|
|
74023
74102
|
}
|
|
74024
|
-
async function claimRunnerPairingCodeSafe(fetchImpl, appUrl2, userCode) {
|
|
74103
|
+
async function claimRunnerPairingCodeSafe(fetchImpl, appUrl2, userCode, serviceKey) {
|
|
74025
74104
|
try {
|
|
74026
|
-
const claim = await claimRunnerPairingCode(fetchImpl, appUrl2, userCode);
|
|
74105
|
+
const claim = await claimRunnerPairingCode(fetchImpl, appUrl2, userCode, serviceKey);
|
|
74027
74106
|
return { ok: true, ...claim };
|
|
74028
74107
|
} catch (error51) {
|
|
74029
74108
|
const message = error51 instanceof Error ? error51.message : String(error51);
|