Files
gilles 08919752e3 feat: socle BDD (tâche 1.9 Phase 1-2) + moteur APT (tâche 2 SJ-0→3) + WIP capabilities/auth/Rust
Checkpoint multi-chantiers (arbre vert : tsc 0 erreur, 70 tests, build OK).
- tâche 1.9 Phase 1 : schéma socle (machine_state/events/reports/raw_artifacts/
  hardware/metrics + colonnes étendues) + wiring refresh/execute. Migration 0002.
- tâche 1.9 Phase 2 : machine_credentials + machine_host_keys (non destructif,
  dual-read + backfill). Migration 0003. Fix séquence journal de migration.
- tâche 2 : SJ-0 (types étendus rétro-compatibles, réducteur Docker, resolveTemplate),
  SJ-1 (update-analyze enrichi), SJ-2 (apply + diff dpkg + timeout inactivité SSH),
  SJ-3 (reboot vérifié boot_id).
- WIP parallèle inclus : /api/capabilities, auth/apiTokens/apiClients, system metrics,
  scaffold app_rust, ajustements frontend.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 19:50:25 +02:00

46 lines
1.4 KiB
TypeScript

// server/index.ts
import { serve } from "@hono/node-server";
import { Hono } from "hono";
import { WebSocketServer } from "ws";
import type { IncomingMessage } from "node:http";
import type { Duplex } from "node:stream";
import { env } from "./env.js";
import { runMigrations } from "./db/migrate.js";
import { api } from "./routes/index.js";
import { outputHub } from "./ws/outputHub.js";
import { startWorker } from "./jobs/worker.js";
env.requireMasterKey();
runMigrations();
const app = new Hono();
app.onError((err, c) => {
console.error("[api]", err.message);
return c.json({ error: err.message || "Erreur serveur" }, 500);
});
app.route("/api", api);
app.get("/health", (c) => c.json({ ok: true }));
const server = serve({ fetch: app.fetch, port: env.port }, (info) =>
console.log(`[server] http://localhost:${info.port}`),
);
// WebSocket: /api/ws/machines/:id/output
const wss = new WebSocketServer({ noServer: true });
server.on("upgrade", (req: IncomingMessage, socket: Duplex, head: Buffer) => {
const match = /^\/api\/ws\/machines\/([^/]+)\/output$/.exec(req.url ?? "");
if (!match) {
socket.destroy();
return;
}
const machineId = match[1]!;
wss.handleUpgrade(req, socket, head, (ws) => {
const unsub = outputHub.subscribe(machineId, (chunk) => {
if (ws.readyState === ws.OPEN) ws.send(chunk);
});
ws.on("close", unsub);
});
});
startWorker();