tests/factories.py owns make_user/headers_for/make_application/
make_server/make_workspace; conftest personas (scoping_rbac,
new viewer_headers/developer_headers fixtures) ride them. The
byte-identical _seed_app pair (container scale/sleep), two variants
(image_update, waf) and three server fixtures (fleet doctor/repair)
migrate as proof. Ratchet freezes the 44-file hand-minted-JWT and
65-file direct-Application() populations.
Note: test_fleet_doctor.py::test_dns_fail_when_unresolved fails
pre-existing on this machine (warn vs fail), unrelated to this change.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- ContainerSleepPolicy model (per-app: enabled, idle_timeout_minutes,
last_activity_at, asleep) + a sleep badge in Application.to_dict.
- ContainerSleepService: sleep/wake an app (compose_down/up or
stop/start_container, local), record_activity, and sweep_idle() which
stops enabled+awake apps idle past their timeout — and never sleeps an app
with no activity baseline.
- apps.py endpoints: GET/PUT /<id>/sleep-policy, POST /<id>/sleep,
POST /<id>/wake, POST /sweep-idle (admin, cron-drivable).
- 9 tests: policy, sleep/wake, docker-failure, remote guard, sweep
selection, no-baseline skip, endpoints, auth.
Follow-ups: traffic-based idle detection (feed record_activity from the nginx
log) and request-triggered wake-on-demand; remote-server sleep.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>