feat: pre-check DWH reachability before creating a session (local dev only)

New session now refuses to spawn a Pi runtime that would only die in bootstrap
retrieval when the DWH/vector host is unreachable (e.g. a dropped VPN). Before
`session new`, POST /sessions probes the DWH via `tht db ping`; if it is down it
returns 503 {code:"dwh_unreachable"} with a clear message and creates nothing.

- Gated behind the THT_DWH_PRECHECK flag (default off), enabled only by the local
  dev launcher (run-stack.sh) — containers/CI never pay the probe, and existing
  tests that don't set it are unaffected.
- ThtRunner.dbPing() runs `tht db ping` with a 10s timeout (run() gains an optional
  timeout that SIGKILLs a hung child).
- Frontend: apiFetch throws a typed ApiError (status + parsed payload); the new-
  session composer shows the specific alert on `dwh_unreachable` instead of the
  generic retry hint, keeping the question for retry.

Verified live on an isolated backend (precheck on + broken DWH host → 503
dwh_unreachable, no session created) and via unit tests (backend 228, frontend 308).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-18 12:08:47 +02:00
co-authored by Claude Opus 4.8
parent 84da3b149b
commit 3453f3ae23
10 changed files with 158 additions and 8 deletions
+7
View File
@@ -16,6 +16,12 @@ export interface AppConfig {
secretsFile?: string;
secretFiles: Readonly<Record<string, string | undefined>>;
modelApiKeyFile?: string;
/**
* Local-only: when true, POST /sessions probes DWH reachability (`tht db ping`) and
* refuses to create a session if it is down. Off by default so containers/CI never
* pay the probe; the local dev launcher (run-stack.sh) opts in via THT_DWH_PRECHECK.
*/
dwhPrecheck: boolean;
}
export function loadConfig(env: Record<string, string | undefined>): AppConfig {
const authMode = env.AUTH_MODE ?? "none";
@@ -99,5 +105,6 @@ export function loadConfig(env: Record<string, string | undefined>): AppConfig {
secretsFile,
secretFiles,
modelApiKeyFile,
dwhPrecheck: env.THT_DWH_PRECHECK === "true" || env.THT_DWH_PRECHECK === "1",
};
}