feat(swarm): remote teardown API + UI (per-decky and per-host)

Agents already exposed POST /teardown; the master was missing the plumbing
to reach it. Add:

- POST /api/v1/swarm/hosts/{uuid}/teardown — admin-gated. Body
  {decky_id: str|null}: null tears the whole host, a value tears one decky.
  On worker failure the master returns 502 and leaves DB shards intact so
  master and agent stay aligned.
- BaseRepository.delete_decky_shard(name) + sqlmodel impl for per-decky
  cleanup after a single-decky teardown.
- SwarmHosts page: "Teardown all" button (keeps host enrolled).
- SwarmDeckies page: per-row "Teardown" button.

Also exclude setuptools' build/ staging dir from the enrollment tarball —
`pip install -e` on the master generates build/lib/decnet_web/node_modules
and the bundle walker was leaking it to agents. Align pyproject's bandit
exclude with the git-hook invocation so both skip decnet/templates/.
This commit is contained in:
2026-04-19 19:39:28 -04:00
parent 6708f26e6b
commit 5dad1bb315
9 changed files with 305 additions and 3 deletions

View File

@@ -55,6 +55,9 @@ _EXCLUDES: tuple[str, ...] = (
".pytest_cache", ".pytest_cache/*",
".mypy_cache", ".mypy_cache/*",
"*.egg-info", "*.egg-info/*",
# setuptools build/ staging dir — created by `pip install` and leaks a
# nested decnet_web/node_modules/ copy into the bundle otherwise.
"build", "build/*", "build/**",
"*.pyc", "*.pyo",
"*.db", "*.db-wal", "*.db-shm", "decnet.db*",
"*.log",