# Buildbox Scratch Bind Fleet Design

audience: AI coding agents first.

## Decision

Extend canonical `modules/buildbox/host-config/apply.sh` scratch declaration. Add one fleet wrapper that preflights all selected registry hosts, then hardens hosts sequentially through existing guarded `buildbox harden <host>`.

Do NOT create independent mount machinery. Existing migration already provides quiesce, `<target>.migrated` recovery, fstab verification, idempotency, and reboot-safe bind ordering.

## Scope

Add regenerable, high-churn paths:

- `/var/lib/buildbox/runs` → `/home/user/runs`
- `/var/lib/buildbox/playwright` → `/home/user/.cache/ms-playwright`
- Per-runner scratch working directory `_work` only; keep runner installation, registration credentials, config, and service files on root.

Exclude `~/Projects`, `~/.claude`, whole runner roots, credentials, and durable Git object stores.

## Fleet command

One script accepts optional registry host names; no names means every reachable host. It MUST:

1. Resolve hosts from canonical registry.
2. Preflight every host before first mutation:
   - SSH reachable.
   - scratch filesystem mounted and source is labeled `buildbox-scratch`.
   - scratch free space exceeds source bytes plus 10 GiB reserve.
   - no conflicting mount or `.migrated` state except resumable canonical state.
3. Stop before mutation if any host fails.
4. Run existing guarded harden operation one host at a time.
5. Verify expected mount sources, fstab declarations, old stash absence, root/scratch free space, and host return after each host.
6. Stop remaining hosts on first failure. Existing host remains recoverable through `<target>.migrated`; wrapper MUST print exact recovery command.

## Runner `_work` discovery

Discover only `/home/user/actions-runner-*/_work` immediate paths. Generate deterministic bind declarations during apply. Never move runner root. Reject symlink targets, non-directory targets, unexpected owners, or source paths outside `/home/user/actions-runner-*/_work`.

## Rollback

Rollback one host only. Stop runner services, unmount affected bind, restore `<target>.migrated` when present, remove only managed fstab block, restart services. Never fleet-roll back automatically after another host succeeded.

## Testing

- Extend scratch declaration tests for fixed binds and dynamic runner `_work` binds.
- Test preflight-all means zero harden calls when one host fails.
- Test sequential order and stop-on-first-failure.
- Test idempotent rerun and exact registry host validation.
- Run buildbox focused tests and shell syntax checks.

## Architecture Decisions

- Reuse existing migration seam; separate implementation would duplicate risky filesystem logic.
- Keep fleet execution sequential; concurrent root storage migration creates avoidable fleet-wide outage risk.
- Keep whole runner directories on root because registration credentials are durable; move `_work` only.
