diff --git a/docs/superpowers/specs/2026-07-06-persistence-editors-ui-design.md b/docs/superpowers/specs/2026-07-06-persistence-editors-ui-design.md new file mode 100644 index 0000000..67e1534 --- /dev/null +++ b/docs/superpowers/specs/2026-07-06-persistence-editors-ui-design.md @@ -0,0 +1,254 @@ +# Plan 3b: Editor Handlers, Views, and Front Controller Design + +## Purpose + +Plan 3b of the four-plan BattleForge build. Completes the web layer that Plan 3a started: the seven remaining PHP tasks that ship the editor pages, the front controller, the full-flow integration test, and CI verification. + +Plan 3a delivered 10 of 17 written tasks: toolchain, output escaping, CSRF, Request/Response, Router, JSON serializer, image validator, image upload service, scenario draft, and the first two HTTP handlers (home page and asset serving). Plan 3b delivers the remaining 7: + +- The five remaining HTTP handlers (team editor GET/POST, battlefield editor GET/POST, image upload POST, start-match POST) +- The six view templates +- The full front controller that wires the routes together and issues the CSRF + upload tokens +- A full-flow integration test +- CI verification +- Final whole-branch code review + +The design is a delta on `docs/superpowers/specs/2026-07-06-persistence-editors-design.md` (the Plan 3 spec), which is the authoritative design. This document records only the clarifications and decisions that are specific to Plan 3b; everything else is inherited from the Plan 3 spec. + +## Success Criteria + +Plan 3b succeeds when a new user, without developer assistance, can: + +1. Visit `http://localhost:8000/`, see the home page, and click "New scenario". +2. Fill in two teams of 3-6 units each on the team editor, upload a custom image, and save. The browser shows a "Saved" toast and the scenario lands in `localStorage` under `scenario:{id}`. +3. Navigate to the battlefield editor, paint a small grid, place deployment zones, place an objective (when the victory condition requires it), and save. The same `localStorage` key is updated with the assembled scenario. +4. Click "Start match" and have the initial `MatchState` round-trip through the server's `PostStartMatch` endpoint, land in `localStorage` under `match:current`, and render the "match loaded" stub. +5. Refresh the page, navigate around, and find their scenarios still in their browser. +6. Try a forged cross-site POST and see a 403. Try to access another user's uploaded image and see a 404. + +## Out of Scope (deferred to Plan 3c or Plan 4) + +- The JavaScript surface: `public/js/storage.js`, `public/js/grid-editor.js`, ESLint, Prettier. The current handlers and views render with HTML form submits and a `