mirror of
https://github.com/multica-ai/multica.git
synced 2026-08-04 17:18:35 +02:00
* fix(cli): fail fast with login hint when starting daemon unauthenticated 'multica daemon start' (background mode) spawned the child first and only then polled its health port. When the user never ran 'multica login', the child died instantly on resolveAuth, but the parent kept polling for the full 45s readiness window and ended with a vague "check logs" warning and exit code 0 — looking like a silent hang. Check the stored config token before spawning (mirroring daemon.resolveAuth, which only accepts the config token) and exit immediately with an actionable "run 'multica login'" hint. 'daemon restart' gets the same guard BEFORE its stop phase: it used to stop the running daemon first and only then fail auth inside the start phase, leaving the user with no daemon at all. The foreground path already failed fast and is unchanged. * fix(cli): report early daemon child exit with an actionable reason Background 'daemon start' Release()d the child immediately and then polled the health port blind. Any preflight failure — server unreachable, stored token rejected with 401 — killed the child within a second, but the parent still sat through the full 45s readiness window and ended with a vague "check logs" warning and exit code 0. Keep a Wait() goroutine on the child and select on it inside the readiness poll. When the child dies before reporting ready, classify what this startup attempt appended to the log and fail with exit code 1 and a one-line reason plus next step: - token rejected / 401 -> run 'multica login' (profile-scoped) - connection refused / DNS / timeout -> server unreachable at <url> - anything else -> short log excerpt with DBG/INF noise dropped * fix(cli): probe token validity and server reachability before restart stops the daemon requireDaemonAuth only rejects an empty stored token, so a revoked or expired token — or an unreachable server — passed the restart guard, the running daemon was stopped, and the replacement child then died in preflight, leaving no daemon at all (#5165). daemon restart now runs a whoami round-trip (same /api/me call as 'multica auth status') against the server the daemon will talk to, using the stored token, before entering the stop phase — and only when a daemon is actually running, so plain 'daemon start' keeps its zero-round-trip happy path. On 401 it reports the re-login hint; on a transport error it reports the unreachable server; both state that the running daemon was left untouched. Regression tests cover a non-empty stored token against a fake 401 server and an unreachable server, asserting /shutdown is never requested on the fake running daemon.