|
@@ -209,6 +209,7 @@ Pages (HTML):
|
|
|
| GET | `/sprints/{id}` | signed-in |
|
|
| GET | `/sprints/{id}` | signed-in |
|
|
|
| GET | `/sprints/{id}/present` | signed-in |
|
|
| GET | `/sprints/{id}/present` | signed-in |
|
|
|
| GET | `/sprints/{id}/settings` | admin |
|
|
| GET | `/sprints/{id}/settings` | admin |
|
|
|
|
|
+| POST | `/sprints/{id}/delete` | admin (form `_csrf` + `confirm_name` must match sprint name verbatim) |
|
|
|
| GET | `/audit` | admin |
|
|
| GET | `/audit` | admin |
|
|
|
| GET | `/settings` | admin |
|
|
| GET | `/settings` | admin |
|
|
|
| POST | `/settings` | admin (form CSRF via `_csrf`) |
|
|
| POST | `/settings` | admin (form CSRF via `_csrf`) |
|
|
@@ -1008,6 +1009,34 @@ with a `BOOTSTRAP_ADMIN` audit row.
|
|
|
status tests keep passing without modification; the migrator
|
|
status tests keep passing without modification; the migrator
|
|
|
picks up 004 on next request.
|
|
picks up 004 on next request.
|
|
|
|
|
|
|
|
|
|
+- [x] **Sprint settings: secured Delete sprint action** (`8e8b8fd`).
|
|
|
|
|
+ New "Danger zone" section at the bottom of `/sprints/{id}/settings`
|
|
|
|
|
+ with a `POST /sprints/{id}/delete` form gated three ways:
|
|
|
|
|
+ `SessionGuard::requireAdmin` + `verifyCsrf`, plus a `confirm_name`
|
|
|
|
|
+ field that must match `sprint.name` verbatim (server-side
|
|
|
|
|
+ authoritative check, with a `sprint-settings.js` UX guard that
|
|
|
|
|
+ keeps the submit button disabled until the typed name matches
|
|
|
|
|
+ and a final `window.confirm()` so a misclick on the now-enabled
|
|
|
|
|
+ button can't fire the destructive POST). Cascade audit (spec §7):
|
|
|
|
|
+ `SprintController::delete` snapshots every descendant before the
|
|
|
|
|
+ FK cascade fires — `task_assignments`, `sprint_worker_days`,
|
|
|
|
|
+ `tasks`, `sprint_workers`, `sprint_weeks` — and records one
|
|
|
|
|
+ DELETE per child plus one for the parent inside a single
|
|
|
|
|
+ transaction. Phase 22's `tasks.linked_task_id ON DELETE SET NULL`
|
|
|
|
|
+ on cross-sprint copies is also captured: rows in *other* sprints
|
|
|
|
|
+ whose `linked_task_id` pointed at one of this sprint's tasks get
|
|
|
|
|
+ an UPDATE audit (`linked_task_id` X → null) so the chain stays
|
|
|
|
|
+ reconstructable. On success the user lands on
|
|
|
|
|
+ `/?deleted=<sprint name>` with a green "Sprint X was deleted."
|
|
|
|
|
+ chip rendered by `views/home.twig`. New
|
|
|
|
|
+ `SprintRepository::delete(int $id): ?Sprint` returns the
|
|
|
|
|
+ pre-deletion snapshot for the parent audit row, mirroring
|
|
|
|
|
+ `TaskRepository::delete`. `tests/Cascade/CascadeAuditTest.php`
|
|
|
|
|
+ grows a fourth path covering the full sprint delete: sets up a
|
|
|
|
|
+ 2-worker / 4-week / 1-task / 2-assignment fixture, audits each
|
|
|
|
|
+ leaf, drops the sprint, then asserts the per-entity-type audit
|
|
|
|
|
+ count matches the cascade size. Tests: 149 / 424 (was 148 / 406).
|
|
|
|
|
+
|
|
|
### Upcoming
|
|
### Upcoming
|
|
|
|
|
|
|
|
Nothing scheduled.
|
|
Nothing scheduled.
|
|
@@ -1059,7 +1088,7 @@ for f in $(git ls-files '*.php'); do php -l "$f" | tail -1 | sed "s|^|$f: |"; do
|
|
|
Run the test suite:
|
|
Run the test suite:
|
|
|
```bash
|
|
```bash
|
|
|
vendor/bin/phpunit
|
|
vendor/bin/phpunit
|
|
|
-# → OK (143 tests, 392 assertions)
|
|
|
|
|
|
|
+# → OK (149 tests, 424 assertions)
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
The Phase 20 parser tests need `ext-dom`, `ext-zip`, `ext-xmlreader`,
|
|
The Phase 20 parser tests need `ext-dom`, `ext-zip`, `ext-xmlreader`,
|
|
@@ -1106,6 +1135,8 @@ before acting — nothing here is load-bearing once it grows stale.
|
|
|
## 13. Git history (as of this writing)
|
|
## 13. Git history (as of this writing)
|
|
|
|
|
|
|
|
```
|
|
```
|
|
|
|
|
+8e8b8fd Sprint settings: secured Delete sprint action
|
|
|
|
|
+be91620 SPEC.md: mark Phase 22 shipped (per-task hamburger menu)
|
|
|
c2dad80 Phase 22: per-task hamburger menu — move/copy/edit/reorder
|
|
c2dad80 Phase 22: per-task hamburger menu — move/copy/edit/reorder
|
|
|
e2f19d6 Phase 21: derive sprint week count from start/end dates
|
|
e2f19d6 Phase 21: derive sprint week count from start/end dates
|
|
|
62bb8b2 SPEC.md: mark Phase 20 shipped (XLSX import wizard)
|
|
62bb8b2 SPEC.md: mark Phase 20 shipped (XLSX import wizard)
|