clementine-agent 1.18.151 → 1.18.152
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/dashboard.js +29 -2
- package/package.json +1 -1
package/dist/cli/dashboard.js
CHANGED
|
@@ -2047,9 +2047,36 @@ export async function cmdDashboard(opts) {
|
|
|
2047
2047
|
jsonParser(req, res, next);
|
|
2048
2048
|
});
|
|
2049
2049
|
// ── Dashboard authentication ────────────────────────────────────────
|
|
2050
|
-
|
|
2050
|
+
// 1.18.152 — persist the token across restarts. Before this, every
|
|
2051
|
+
// dashboard startup (manual restart, auto-respawn, crash recovery)
|
|
2052
|
+
// generated a fresh random token, which invalidated every browser
|
|
2053
|
+
// bookmark, open tab, and printed URL. Auto-respawn (1.18.146) +
|
|
2054
|
+
// auto-open browser (1.18.147) made this acutely visible — users
|
|
2055
|
+
// would re-open the dashboard and find the URL they had bookmarked
|
|
2056
|
+
// 401'd, then a new browser window would open with a different token,
|
|
2057
|
+
// and any hook commands installed in projects would silently 401 too.
|
|
2058
|
+
//
|
|
2059
|
+
// Fix: read the existing token if `~/.clementine/.dashboard-token`
|
|
2060
|
+
// already exists; only generate-and-persist on first-ever startup.
|
|
2061
|
+
// To rotate tokens deliberately, the user deletes the file and
|
|
2062
|
+
// restarts. Local-machine threat model assumes the home dir is
|
|
2063
|
+
// trusted (see feedback_security_model.md) — a persistent token here
|
|
2064
|
+
// is the same security posture as `~/.ssh/id_rsa`.
|
|
2051
2065
|
const tokenPath = path.join(BASE_DIR, '.dashboard-token');
|
|
2052
|
-
|
|
2066
|
+
let dashboardToken;
|
|
2067
|
+
try {
|
|
2068
|
+
const existing = readFileSync(tokenPath, 'utf-8').trim();
|
|
2069
|
+
// Strict format check — anything that doesn't look like a 48-hex-char
|
|
2070
|
+
// token (the format randomBytes(24).toString('hex') produces) gets
|
|
2071
|
+
// regenerated. Defends against truncated / corrupt files.
|
|
2072
|
+
if (!/^[a-f0-9]{48}$/.test(existing))
|
|
2073
|
+
throw new Error('invalid token format on disk');
|
|
2074
|
+
dashboardToken = existing;
|
|
2075
|
+
}
|
|
2076
|
+
catch {
|
|
2077
|
+
dashboardToken = randomBytes(24).toString('hex');
|
|
2078
|
+
writeFileSync(tokenPath, dashboardToken, { mode: 0o600 });
|
|
2079
|
+
}
|
|
2053
2080
|
// ── Remote access + session management ─────────────────────────────
|
|
2054
2081
|
const remoteConfig = loadRemoteConfig();
|
|
2055
2082
|
const sessions = new Map();
|