This is the checklist from the spec. Run it against a fresh container after Phase 7 lands. Expected outcome is noted next to each step; edit this file (and open a bug) if any step deviates.
docker compose down && rm -rf data/app.sqlite
docker compose up --build
.env should have EITHER valid ENTRA_* values OR LOCAL_ADMIN_EMAIL +
LOCAL_ADMIN_PASSWORD set. Below, "sign in" means whichever flow you
configured.
Fresh container, empty DB → sign in → you're the admin.
admin badge.
SELECT is_admin FROM users LIMIT 1 in data/app.sqlite returns 1.
audit_log has rows: CREATE user / BOOTSTRAP_ADMIN user / LOGIN user.Create a sprint with 4 weeks.
/sprints/1; empty-state banner says "No workers".
Clicking Settings opens the settings page. The weeks table shows
4 rows with max_working_days 5.0 each and ISO week numbers computed
from the start date.Add 6 workers, reorder by dragging — reload persists order.
/sprints/1/settings → add all 6 to the sprint via Add →
buttons.audit_log shows UPDATE sprint_worker rows for every moved row
(unchanged rows emit nothing thanks to the no-op rule).Fill Arbeitstage; Ressourcen / Reserven / Available update live.
/sprints/1 → edit a day cell (0.5-step input).Ressourcen, − Reserven, Available). Status pill flashes "Saved N
cell(s)". audit_log has one CREATE sprint_worker_days row per edited
cell.Add tasks, assign days — Tot updates; over-commit turns Available red but still saves.
Tot cell shows 10; that worker's Available in the capacity
strip goes negative and turns red. The assignment is persisted
(reload still shows 10); audit_log has CREATE task + CREATE
task_assignment.Sort task table by Owner, then by a worker column; clear → original drag order returns.
Owner header — rows sort asc, header shows "↑".data-sort-order (the drag-persisted order).Filter tasks: Prio=1, Owner=X, free-text "report".
Rename a worker in /workers — reflected everywhere.
/sprints/1 in another tab.audit_log has an UPDATE
worker row./audit shows one row per change with diffs visible.
<details> opens
to show pretty-printed JSON snapshots.Sign out; unauthenticated → redirect to /auth/login.
audit_log has a LOGOUT user row./workers or /sprints/1/settings while anonymous →
redirected to /auth/login (and then Entra, or the local form).If you have Tool_Sprint_PlanningSample.xlsx handy:
Ressourcen should match Excel: sum across weeks.− Reserven should match: round_to_0.5(Ressourcen * 0.8) with reserve = 20 %.Available should be
(Ressourcen − Reserven) − N, and turn red when negative.With the app running, curl -I http://localhost:8080/ should report:
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Content-Security-Policy: default-src 'self'; script-src 'self' …; …
Strict-Transport-Security appears only when APP_BASE_URL uses https://.