restic-manager · Phase 0 wireframes

Low-fidelity wireframes for Phase 1/2 screens. Purpose: confirm the data each screen needs before the API in spec.md §6.1 and the WS messages in §6.2 are locked in. Grayscale on purpose — visual design is deferred to Phase 5 (and a focused hi-fi pass on the restore wizard in Phase 3).

[GET /api/...] tags mark REST data sources. [WS: ...] tags mark WebSocket message dependencies. Open the “Findings” section at the bottom for spec gaps.

Screen 1 · Dashboard (/)
user: alice (admin) · logout
Fleet status
10 online · 1 offline · 1 degraded
Last sync 12s ago
Storage (sum across repos)
2.4 TB across 12 repos
+18 GB last 24h
Open alerts
3 · 1 critical
2 unacked
[ search hosts · filter by tag · status ]
+ Add host

Hosts

prod-db-01 linux/amd64
online

Last backup
2h ago · success
Repo
412 GB · 1,284 snapshots
Alerts
View Backup now
staging-app linux/arm64
degraded

Last backup
9h ago · failed
Repo
88 GB · 412 snapshots
Alerts
2 · 1 critical
View Retry
laptop-bob windows/amd64
offline

Last seen
3d ago
Repo
142 GB · 88 snapshots
Alerts
1
View Backup now
… more host cards (12 total in target deployment)

Recent activity (fleet-wide)

WhenHostKindStatusDuration
2h agoprod-db-01backupsucceeded00:14:22view
3h agoweb-02backupsucceeded00:08:11view
9h agostaging-appbackupfailed00:01:03view
1d agoprod-db-01checksucceeded00:42:17view
1d agoweb-01prunesucceeded00:04:55view
Screen 2 · Host detail (/hosts/:id)
user: alice (admin)
« Dashboard / Hosts

prod-db-01

linux/amd64 · agent 0.4.2 · restic 0.17.1 · last seen 12s ago
online tag: prod tag: db
Currently: idle
Backup now Run check
[ filter by tag · path · date range ]
[ sort: newest first ]
SnapshotTimePathsTagsSizeFiles
3a8f1e2h ago/var/lib/postgresauto, daily412 GB1.2Mrestore · diff
8c7b221d ago/var/lib/postgresauto, daily411 GB1.2Mrestore · diff
4f0a992d ago/var/lib/postgres, /etcauto, weekly411 GB1.2Mrestore · diff
… 1,281 more · load more

Other tabs (preview, not navigated):
Tab · Schedules
KindCronPathsRetentionEnabled
backup0 2 * * */var/lib/postgres7d/4w/12m[x]
forget+prune0 4 * * 0per policy[x]
check0 5 1 * *[ ]
+ New schedule
schedule editor (expanded form)
kind: [backup ▾]
cron: [ 0 2 * * * ]   human: every day at 02:00
paths: [ /var/lib/postgres ] [+ add]
excludes: [ *.tmp, /tmp ]
tags: [ auto, daily ]
retention: keep [7] daily, [4] weekly, [12] monthly · keep-tag [ ]
bandwidth: upload [ ] KB/s · download [ ] KB/s   §14.2
pre-hook: [ pg_dump ... ]   §14.3 admin-only
post-hook: [ ... ]
enabled: [x]
Tab · Jobs (host-scoped)
StartedKindStatusDurationBy
2h agobackupsucceeded00:14:22schedule
1d agochecksucceeded00:42:17schedule
2d agobackupcancelled00:00:42alice
3d agobackupfailed00:01:09schedule
Tab · Repo
URL
rest:https://restic.lab…/prod-db-01
Kind
rest (append-only)
Total size
412 GB
Dedup ratio
4.2×
Snapshots
1,284
Last check
1d ago · clean
Lock state
unlocked
Credential
append-only · rotated 14d ago
Run check Unlock Forget+prune (admin)
Tab · Settings
Tags
prod, db [+ add]
Default pre-hook
(empty)
Default post-hook
(empty)
Hook shell
/bin/sh
Default bandwidth caps
none
Enrollment
enrolled 42d ago · Regenerate token
Agent
0.4.2 · auto-update [x] · Force update now
Danger zone
Remove host does not touch repo data
Screen 3 · Job detail (/jobs/:id) — running state
user: alice (admin)
« prod-db-01 / Jobs

backup · prod-db-01

job j_01HJ8K7 · started 4m12s ago · triggered by alice
running schedule: nightly-pg
Cancel job
Progress
38% · ~6m remaining
156 GB of 412 GB · 482k of 1.2M files
Files new
2,103
Files changed
418
Bytes added
2.4 GB
Throughput
42 MB/s
Live log (streaming via WS)
14:02:11 [agent] starting restic backup --json 14:02:11 [agent] pre_hook: pg_dump | gzip > /tmp/dump.sql.gz 14:02:48 [pre_hook] dump complete (1.2 GB) 14:02:49 [restic] open repository 14:02:50 [restic] lock repository 14:02:50 [restic] load index files 14:02:53 [restic] start scan 14:02:55 [restic] start backup on /var/lib/postgres 14:03:01 [restic] {"message_type":"status","percent_done":0.04,"total_files":1234567,"files_done":48234,"total_bytes":442000000000,"bytes_done":17600000000} 14:04:22 [restic] {"message_type":"status","percent_done":0.18,"...} 14:05:55 [restic] {"message_type":"status","percent_done":0.31,"...} 14:06:23 [restic] warning: failed to lstat /var/lib/postgres/pg_wal/.lock 14:06:24 [restic] {"message_type":"status","percent_done":0.38,"...}
[ ] auto-scroll   [ ] show stderr only   download full log

Findings — gaps in spec.md §6 surfaced by Phase 0 wireframing

  1. Aggregate fleet endpoint missing. Dashboard summary strip and Prometheus metrics (§14.4) both need fleet rollups. Add GET /api/fleet/summary returning host counts by status, total repo bytes, open alert counts. Cheaper than client fanout and reused by /metrics.
  2. Host list response is too thin. Domain model Host (§5) has status + last_seen_at; cards need last_backup_at, last_backup_status, repo_size_bytes, snapshot_count, open_alert_count, current_job_id. Either add columns or compute server-side and include in GET /api/hosts.
  3. Job actor not modelled. Job table tracks scheduled_id but not who (user vs schedule vs system) triggered a run-now. Dashboard "Recent activity" and Jobs tab both want this. Add Job.actor_kind + Job.actor_id — cheaper than joining AuditLog every time.
  4. WS job.progress JSON shape is undefined. §6.2 lists the message name only. Lock the shape now: {percent_done: float, files_done: int, total_files: int, bytes_done: int, total_bytes: int, eta_seconds: int, throughput_bps: int}. Keeps client + agent in lockstep before Phase 1 codes against it.
  5. Repo response needs more fields. §6.1 says size/last-check/lock state. Wireframe also wants: dedup ratio, snapshot count, credential rotation timestamp, append-only flag. Most derive from restic stats + Credential row — expose them through GET /api/hosts/:id/repo.
  6. Snapshot filtering needs server support. Tag/path/date filters belong on the server (12-host fleets are small but a single host can hold thousands of snapshots). Add query params to GET /api/hosts/:id/snapshots: ?tag=, ?path=, ?since=, ?limit=. Distinct-tag list endpoint optional — could be derived client-side at first.
  7. Job listing needs query params. Recent activity, host-scoped jobs, and the Jobs page all use GET /api/jobs. Lock down: ?host_id=, ?kind=, ?status=, ?since=, ?limit=, ?order=. Pagination too.
  8. Agent self-update endpoint not in §6.1. §4.2 describes the mechanism but no REST endpoint exists. Settings tab wants a "Force update now" button — add POST /api/hosts/:id/agent/update.
  9. Schedule retention/options JSON shape. §14.2 (bandwidth) and §14.3 (hooks) both extend Schedule. Document the canonical shape now (retention_policy, options.limit_upload, options.limit_download, pre_hook, post_hook) so the schedule editor and the agent can both target it.
  10. HTMX-vs-WS responsibility split. Decision: only the Job detail screen needs WS. Dashboard, Hosts, Snapshots use HTMX polling (10s). This avoids fan-out complexity for v1; revisit if dashboard feels stale.