mirror of
https://github.com/Routstr/routstrd.git
synced 2026-10-05 12:28:23 +00:00
The SDK now defaults automatic DeepSeek model-path selection to off, so surface it as an operator setting: `autoModelPath` in ~/.routstrd/config.json (default false), threaded into routeRequests via the daemon request handler. Explicit x-routstr-model-path headers are unaffected. Requires a daemon restart after changing the value, matching how the other startup config fields reach the handler. Documented in the README config section; the config-store scenario covers the default and a round-trip.
117 lines
3.6 KiB
TypeScript
117 lines
3.6 KiB
TypeScript
// Scenario runner for config-store.perms.test.ts — executed as a standalone
|
|
// bun process with ROUTSTRD_DIR set before module evaluation. Not a test file.
|
|
import {
|
|
chmodSync,
|
|
existsSync,
|
|
readdirSync,
|
|
statSync,
|
|
writeFileSync,
|
|
} from "fs";
|
|
|
|
const { CONFIG_DIR, CONFIG_FILE } = await import("../../src/utils/config");
|
|
const {
|
|
ensureDirs,
|
|
ensureDirsSync,
|
|
loadDaemonConfig,
|
|
loadDaemonConfigSync,
|
|
saveDaemonConfig,
|
|
REQUESTS_DIR,
|
|
} = await import("../../src/daemon/config-store");
|
|
|
|
const modeOf = (p: string): number => statSync(p).mode & 0o777;
|
|
|
|
const baseConfig = {
|
|
port: 8008,
|
|
host: "127.0.0.1",
|
|
provider: null,
|
|
cocodPath: null,
|
|
};
|
|
|
|
function assert(cond: unknown, msg: string): void {
|
|
if (!cond) {
|
|
console.error(`ASSERT-FAIL: ${msg}`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
const scenario = process.argv[2];
|
|
|
|
switch (scenario) {
|
|
case "fresh-install": {
|
|
assert(loadDaemonConfigSync().autoModelPath === false, "autoModelPath must default to false");
|
|
saveDaemonConfig({
|
|
...baseConfig,
|
|
autoModelPath: true,
|
|
nsec: "nsec1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
|
|
});
|
|
assert(modeOf(CONFIG_DIR) === 0o700, `dir mode ${modeOf(CONFIG_DIR).toString(8)} != 700`);
|
|
assert(modeOf(CONFIG_FILE) === 0o600, `file mode ${modeOf(CONFIG_FILE).toString(8)} != 600`);
|
|
assert(
|
|
readdirSync(CONFIG_DIR).filter((f) => f.endsWith(".tmp")).length === 0,
|
|
"temp file left behind",
|
|
);
|
|
const loaded = await loadDaemonConfig();
|
|
assert(
|
|
loaded.nsec === "nsec1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
|
|
"nsec round-trip failed",
|
|
);
|
|
assert(loaded.port === 8008, "port round-trip failed");
|
|
assert(loaded.autoModelPath === true, "autoModelPath round-trip failed");
|
|
|
|
await ensureDirs();
|
|
assert(modeOf(CONFIG_DIR) === 0o700, "ensureDirs dir mode");
|
|
assert(modeOf(REQUESTS_DIR) === 0o700, "ensureDirs requests dir mode");
|
|
break;
|
|
}
|
|
|
|
case "repair-perms": {
|
|
// Simulate an install written by the vulnerable version.
|
|
ensureDirsSync();
|
|
writeFileSync(CONFIG_FILE, JSON.stringify(baseConfig), { mode: 0o644 });
|
|
chmodSync(CONFIG_DIR, 0o755);
|
|
chmodSync(CONFIG_FILE, 0o644);
|
|
assert(modeOf(CONFIG_FILE) === 0o644, "setup: file not 0644");
|
|
|
|
// Load repairs the file mode...
|
|
loadDaemonConfigSync();
|
|
assert(modeOf(CONFIG_FILE) === 0o600, "load did not repair file mode");
|
|
|
|
// ...and the next save repairs the directory mode too.
|
|
chmodSync(CONFIG_DIR, 0o755);
|
|
saveDaemonConfig({ ...baseConfig, port: 9009 });
|
|
assert(modeOf(CONFIG_DIR) === 0o700, "save did not repair dir mode");
|
|
assert(modeOf(CONFIG_FILE) === 0o600, "save did not keep file mode");
|
|
assert(loadDaemonConfigSync().port === 9009, "save did not persist port");
|
|
break;
|
|
}
|
|
|
|
case "write-failure": {
|
|
// Turn the config dir into a regular file: mkdir fails and no temp write
|
|
// can succeed, so saveDaemonConfig must surface the error synchronously.
|
|
writeFileSync(process.env.ROUTSTRD_DIR!, "blocked");
|
|
let threw = false;
|
|
try {
|
|
saveDaemonConfig(baseConfig);
|
|
} catch {
|
|
threw = true;
|
|
}
|
|
assert(threw, "saveDaemonConfig did not throw on unwritable target");
|
|
break;
|
|
}
|
|
|
|
case "corrupt-json": {
|
|
ensureDirsSync();
|
|
writeFileSync(CONFIG_FILE, "{ not json");
|
|
const loaded = await loadDaemonConfig();
|
|
assert(loaded.port === 8008, "did not fall back to defaults");
|
|
assert(existsSync(CONFIG_FILE), "config file vanished");
|
|
break;
|
|
}
|
|
|
|
default:
|
|
console.error(`unknown scenario: ${scenario}`);
|
|
process.exit(2);
|
|
}
|
|
|
|
console.log("SCENARIO-OK");
|