@inceptionstack/roundhouse 0.3.3 → 0.3.5

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli/setup.ts +36 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inceptionstack/roundhouse",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "type": "module",
5
5
  "description": "Multi-platform chat gateway that routes messages through a configured AI agent",
6
6
  "license": "MIT",
package/src/cli/setup.ts CHANGED
@@ -388,8 +388,30 @@ async function stepInstallPackages(opts: SetupOptions): Promise<void> {
388
388
  ok("psst vault exists");
389
389
  } else {
390
390
  log(" Initializing psst vault...");
391
- execOrFail("psst", ["init"], "psst init");
392
- ok("psst vault initialized");
391
+ // On headless servers, no keychain is available — use PSST_PASSWORD
392
+ const psstEnv = { ...process.env };
393
+ if (!psstEnv.PSST_PASSWORD) {
394
+ // Generate a random password and store it for future use
395
+ const psstPw = randomBytes(32).toString("base64");
396
+ const pwFile = resolve(ROUNDHOUSE_DIR, ".psst-password");
397
+ await atomicWriteText(pwFile, psstPw + "\n", 0o600);
398
+ psstEnv.PSST_PASSWORD = psstPw;
399
+ // Also set for subsequent psst calls in this process
400
+ process.env.PSST_PASSWORD = psstPw;
401
+ }
402
+ try {
403
+ execFileSync("psst", ["init"], {
404
+ encoding: "utf8", stdio: "pipe", timeout: 30_000,
405
+ env: psstEnv,
406
+ });
407
+ ok("psst vault initialized");
408
+ } catch (err: any) {
409
+ warn(`psst vault init failed: ${err.stderr?.trim() || err.message}`);
410
+ // Clean up orphan password file
411
+ try { await unlink(resolve(ROUNDHOUSE_DIR, ".psst-password")); } catch {}
412
+ delete process.env.PSST_PASSWORD;
413
+ opts.psst = false;
414
+ }
393
415
  }
394
416
 
395
417
  // Install pi-psst extension
@@ -549,6 +571,18 @@ async function stepConfigure(
549
571
  envLines.push(`ALLOWED_USERS=${envQuote(opts.users.join(","))}`);
550
572
  }
551
573
 
574
+ // If psst uses a generated password (headless), include it in env for systemd.
575
+ // Threat model tradeoff: the vault key is plaintext in a 0600 file, but this is
576
+ // unavoidable on headless servers with no keychain. The benefit is that individual
577
+ // secrets are still managed centrally via psst and injected at runtime.
578
+ if (opts.psst) {
579
+ const pwFile = resolve(ROUNDHOUSE_DIR, ".psst-password");
580
+ if (await fileExists(pwFile)) {
581
+ const pw = (await readFile(pwFile, "utf8")).trim();
582
+ envLines.push(`PSST_PASSWORD=${envQuote(pw)}`);
583
+ }
584
+ }
585
+
552
586
  if (opts.provider === "amazon-bedrock") {
553
587
  // Preserve existing AWS config
554
588
  let existingEnv: Record<string, string> = {};