feat(breakglass): add "back up a world now" console peer (§B4 Sync)

Adds a break-glass console operation that snapshots a stopped world by
calling the felis-api internal face while the API is alive, rather than
rendering the backup Job locally: the Job needs felis-api deployment
coordinates the console does not hold.

The peer resolves the felis-api-internal ClusterIP Service + service
token from the control namespace, POSTs the internal backup endpoint
with the operator os_user for audit attribution, and maps 409/503/404
to friendly outcome cards. Core decision logic lives in backupnow.go
(unit-tested against a fake client + httptest); tui_backupnow.go is the
untested bubbletea glue mirroring tui_halt.go.
This commit is contained in:
flyemoji committed 2026-07-07 19:32:13 +09:00
1 parent 4918d93412
commit fc748d3462
9 files changed
+594 -2

No files matched your search

+11
View File
@@ -216,6 +216,17 @@ func TestInternalBackup(t *testing.T) {
}
})
t.Run("os_user body attributes the audit to the operator", func(t *testing.T) {
api, repo, _, _ := mk()
w := do(api.InternalHandler(), "POST", path, `{"os_user":"alice"}`, jsonHeader)
if w.Code != http.StatusAccepted {
t.Fatalf("code = %d, want 202 (%s)", w.Code, w.Body.String())
}
if len(repo.audits) != 1 || repo.audits[0].Actor != "alice" || repo.audits[0].Source != "internal" {
t.Fatalf("audit actor should be the os_user, not break-glass: %+v", repo.audits)
}
})
t.Run("running server -> 409 not_stopped, no backup", func(t *testing.T) {
api, _, cl, backuper := mk()
cl.byName["survival"].Ready = true