Show each server's Forgetting version in the panel

- awg-agent sends its install's VERSION (from the CLI's env, else the
  project's .env) in the auth frame; the hub keeps it in nodes.version
  (added by migration), so an offline node still shows the last one.
- GET /ui/nodes returns version per server (0 is the panel's own) and the
  panel's version at the top.
- ServerBar: a vX.Y.Z chip next to the AWG generation. A node older or
  newer than the panel, or one that sends no version (agent before
  0.3.4, shown as v?.?.?), gets a warm chip with an "update it" tooltip.
- App.css: tertiary-container tokens from design.md (light) and a warm
  dark pair; they did not exist yet.
- Mock server: panel 0.3.3, Frankfurt behind on 0.3.2, Amsterdam with no
  version.
This commit is contained in:
2026-09-27 18:03:57 +03:00
parent eb0ec2878c
commit 5c3bf21918
8 changed files with 98 additions and 24 deletions
+11
View File
@@ -23,6 +23,16 @@ const INTERNAL_AUTH_KEY_FILE = process.env.INTERNAL_AUTH_KEY_FILE ?? "/etc/amnez
const CLI_ENV_FILE = process.env.CLI_ENV_FILE ?? "";
let joinSecret = process.env.JOIN_SECRET ?? ""; // одноразовый, живёт до первого успешного подключения
// Версия Forgetting на этой ноде — панель показывает её в карточке сервера. CLI передаёт её из
// .env в корне проекта; при запуске вручную читаем тот же .env сами.
function envFromFile(file: string, key: string): string {
try {
const m = fs.readFileSync(file, "utf8").match(new RegExp(`^\\s*${key}\\s*=\\s*(.*)$`, "m"));
return m ? m[1].trim() : "";
} catch { return ""; }
}
const VERSION = process.env.VERSION || envFromFile(path.join(__dirname, "..", ".env"), "VERSION");
if (!CORE_HOST || !CORE_PORT || !CORE_PIN || !NODE_ID) {
console.error("agent: не заданы CORE_HOST / CORE_PORT / CORE_PIN / NODE_ID — выполните `awg-ctrl join <ссылка>`");
process.exit(1);
@@ -138,6 +148,7 @@ function connectOnce(): Promise<{ authFailed: boolean }> {
sig: crypto.sign(null, authMsg(m.nonce), nodeKey).toString("base64url"),
};
if (joinSecret) auth.join = { secret: joinSecret, pub: nodePubRaw };
if (VERSION) auth.version = VERSION;
ws.send(JSON.stringify(auth));
} else if (m.t === "ready") {
ready = true; backoff = 1000; armDead();