@rosthq/cli 0.7.27 → 0.7.28
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 +56 -10
- package/dist/index.js.map +3 -3
- package/dist/token-store.d.ts +18 -1
- package/dist/token-store.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -37346,15 +37346,25 @@ ${secret}
|
|
|
37346
37346
|
}
|
|
37347
37347
|
};
|
|
37348
37348
|
var DarwinTokenStore = class extends KeychainTokenStore {
|
|
37349
|
-
constructor(run2 = runExecFile, filePath) {
|
|
37349
|
+
constructor(run2 = runExecFile, filePath, stderr = process.stderr) {
|
|
37350
37350
|
super(run2);
|
|
37351
37351
|
this.filePath = filePath;
|
|
37352
|
+
this.stderr = stderr;
|
|
37352
37353
|
}
|
|
37353
37354
|
filePath;
|
|
37355
|
+
stderr;
|
|
37354
37356
|
backend = null;
|
|
37357
|
+
fileBackendReason = null;
|
|
37355
37358
|
fileStore = null;
|
|
37356
37359
|
async read() {
|
|
37357
|
-
|
|
37360
|
+
if (await this.selectBackend() === "file") {
|
|
37361
|
+
return this.file().read();
|
|
37362
|
+
}
|
|
37363
|
+
const keychainSession = await super.read();
|
|
37364
|
+
if (keychainSession) {
|
|
37365
|
+
return keychainSession;
|
|
37366
|
+
}
|
|
37367
|
+
return this.readFileStoreBestEffort();
|
|
37358
37368
|
}
|
|
37359
37369
|
async write(session) {
|
|
37360
37370
|
if (await this.selectBackend() === "file") {
|
|
@@ -37362,20 +37372,49 @@ var DarwinTokenStore = class extends KeychainTokenStore {
|
|
|
37362
37372
|
return;
|
|
37363
37373
|
}
|
|
37364
37374
|
await super.write(session);
|
|
37375
|
+
if (await this.keychainReadBackFailed(session)) {
|
|
37376
|
+
this.backend = "file";
|
|
37377
|
+
this.fileBackendReason = "unreadable";
|
|
37378
|
+
await this.file().write(session);
|
|
37379
|
+
await super.clear();
|
|
37380
|
+
this.warnKeychainNotReadableBack();
|
|
37381
|
+
}
|
|
37365
37382
|
}
|
|
37366
37383
|
async clear() {
|
|
37367
|
-
if (await this.selectBackend() === "file") {
|
|
37368
|
-
await this.file().clear();
|
|
37369
|
-
return;
|
|
37370
|
-
}
|
|
37371
37384
|
await super.clear();
|
|
37385
|
+
await this.file().clear();
|
|
37372
37386
|
}
|
|
37373
37387
|
describe() {
|
|
37374
|
-
|
|
37388
|
+
if (this.backend !== "file") {
|
|
37389
|
+
return super.describe();
|
|
37390
|
+
}
|
|
37391
|
+
return this.fileBackendReason === "unreadable" ? "owner-only file store (macOS keychain not readable back cross-process)" : "owner-only file store (no usable macOS keychain)";
|
|
37375
37392
|
}
|
|
37376
37393
|
file() {
|
|
37377
37394
|
return this.fileStore ??= new FileTokenStore(this.filePath);
|
|
37378
37395
|
}
|
|
37396
|
+
async readFileStoreBestEffort() {
|
|
37397
|
+
try {
|
|
37398
|
+
return await this.file().read();
|
|
37399
|
+
} catch {
|
|
37400
|
+
return null;
|
|
37401
|
+
}
|
|
37402
|
+
}
|
|
37403
|
+
async keychainReadBackFailed(session) {
|
|
37404
|
+
try {
|
|
37405
|
+
const readBack = await super.read();
|
|
37406
|
+
return readBack?.accessToken !== session.accessToken;
|
|
37407
|
+
} catch {
|
|
37408
|
+
return true;
|
|
37409
|
+
}
|
|
37410
|
+
}
|
|
37411
|
+
warnKeychainNotReadableBack() {
|
|
37412
|
+
const envKey = brandEnvKey2("CLI_ALLOW_FILE_TOKEN_STORE");
|
|
37413
|
+
this.stderr.write(
|
|
37414
|
+
`NOTICE: the macOS Keychain accepted the session but it was not readable back (cross-process keychain read failed). Wrote the session to the ${this.file().describe()} instead. For headless / non-interactive use, export ${envKey}=1 so later commands read it directly.
|
|
37415
|
+
`
|
|
37416
|
+
);
|
|
37417
|
+
}
|
|
37379
37418
|
async selectBackend() {
|
|
37380
37419
|
if (this.backend) {
|
|
37381
37420
|
return this.backend;
|
|
@@ -37384,7 +37423,12 @@ var DarwinTokenStore = class extends KeychainTokenStore {
|
|
|
37384
37423
|
await this.run("security", ["find-generic-password", "-s", serviceName, "-a", accountName, "-w"]);
|
|
37385
37424
|
this.backend = "keychain";
|
|
37386
37425
|
} catch (error51) {
|
|
37387
|
-
|
|
37426
|
+
if (isKeychainUnusableError(error51)) {
|
|
37427
|
+
this.backend = "file";
|
|
37428
|
+
this.fileBackendReason = "unusable";
|
|
37429
|
+
} else {
|
|
37430
|
+
this.backend = "keychain";
|
|
37431
|
+
}
|
|
37388
37432
|
}
|
|
37389
37433
|
return this.backend;
|
|
37390
37434
|
}
|
|
@@ -37513,7 +37557,7 @@ function createTokenStore(options = {}) {
|
|
|
37513
37557
|
}
|
|
37514
37558
|
const platform2 = options.platform ?? process.platform;
|
|
37515
37559
|
if (platform2 === "darwin") {
|
|
37516
|
-
return new DarwinTokenStore(options.execFile, tokenPath);
|
|
37560
|
+
return new DarwinTokenStore(options.execFile, tokenPath, options.stderr ?? process.stderr);
|
|
37517
37561
|
}
|
|
37518
37562
|
if (platform2 === "win32") {
|
|
37519
37563
|
return new WindowsCredentialTokenStore(options.execFile);
|
|
@@ -45005,7 +45049,7 @@ External connectors are being rolled out provider by provider, conservatively (r
|
|
|
45005
45049
|
order: 48,
|
|
45006
45050
|
title: "CLI and MCP installation guide",
|
|
45007
45051
|
summary: "Install the public CLI, register remote token-backed MCP clients, and find the full command and tool catalog.",
|
|
45008
|
-
version: "2026-07-04.
|
|
45052
|
+
version: "2026-07-04.19",
|
|
45009
45053
|
public: true,
|
|
45010
45054
|
audiences: ["human", "cli", "mcp", "in_app_agent"],
|
|
45011
45055
|
stages: ["company_setup", "staffing"],
|
|
@@ -45193,6 +45237,8 @@ Notes:
|
|
|
45193
45237
|
|
|
45194
45238
|
By default the CLI stores the session in the **macOS Keychain** (on darwin). There is no built-in Windows or Linux keychain integration today \u2014 on any non-macOS host, or any machine without a keychain, the CLI errors with "No OS credential store is available" unless you opt into the file store.
|
|
45195
45239
|
|
|
45240
|
+
On macOS, the CLI now **verifies the keychain write is readable back** right after \`login\`. On some headless/service hosts the keychain accepts the write but a later command's process cannot read it back (an ACL scoped to the writing binary, a re-locked login keychain, or a launchd/SSH session with no keychain), so \`login\` reports success yet the next command prints "Not logged in". When that readback fails, the CLI **automatically** writes the session to the same owner-only file store (directory \`0700\`, file \`0600\`), prints a one-line stderr notice, and later commands read it back transparently \u2014 so a headless macOS agent "just works" with no flag. For a fully unattended macOS host, export \`{{envPrefix}}_CLI_ALLOW_FILE_TOKEN_STORE=1\` anyway so every command uses the file store directly.
|
|
45241
|
+
|
|
45196
45242
|
For headless Linux, CI runners, or any no-keychain environment, set \`{{envPrefix}}_CLI_ALLOW_FILE_TOKEN_STORE=1\` to opt into the **development-only plain-file token store**. It is **not encrypted** \u2014 it writes the file with owner-only permissions (directory \`0700\`, file \`0600\`) and prints a stderr warning. It stores **only CLI session tokens** (access + refresh token), never tenant secrets, API keys, or vault refs. Treat that file as a credential: do not bake it into a shared image and do not commit it.
|
|
45197
45243
|
|
|
45198
45244
|
The CLI checks this flag on **every** invocation, not just \`login\`. Export it for the whole shell or CI job (so \`{{cli}} whoami\`, \`{{cli}} onboard status\`, and the rest also find the file store), not only on the login line:
|