241 lines
10 KiB
Markdown
241 lines
10 KiB
Markdown
|
|
# Roadmap Page Redesign — Execution Plan
|
|||
|
|
|
|||
|
|
**Created:** 2026-05-11
|
|||
|
|
**Scope:** Replace AdminDashboard with a standalone RoadmapPage using kanban-style priority lanes
|
|||
|
|
**Reference:** `docs/ROADMAP_UI_AUDIT.md`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 1 — Neo: Backend API Split & Parsing Fix
|
|||
|
|
|
|||
|
|
**Agent:** Neo
|
|||
|
|
**Priority:** Must complete before Task 2
|
|||
|
|
**Estimated time:** 2-3 hours
|
|||
|
|
|
|||
|
|
### What
|
|||
|
|
Split `/api/about-admin` into two endpoints so the dev log (54KB) isn't shipped on page load, and add structured FUTURE.md parsing on the backend.
|
|||
|
|
|
|||
|
|
### Changes
|
|||
|
|
|
|||
|
|
**1. New endpoint: `GET /api/roadmap`**
|
|||
|
|
- Reads `FUTURE.md`
|
|||
|
|
- Returns parsed JSON array of roadmap items (not raw markdown)
|
|||
|
|
- Each item: `{ id, priority, priorityLabel, title, description, rationale, implementationNotes, effort, added, addedBy, status }`
|
|||
|
|
- Parse `**Description:**`, `**Rationale:**`, `**Implementation Notes:**` into separate fields
|
|||
|
|
- Extract effort estimate from Implementation Notes (regex: `Estimated effort: X-Y hours` → `effort: "X-Yh"`)
|
|||
|
|
- Filter out strikethrough/completed items server-side
|
|||
|
|
- Group counts by priority tier in response: `{ items: [...], counts: { critical: 1, high: 3, medium: 4, low: 3, niceToHave: 1 } }`
|
|||
|
|
|
|||
|
|
**2. New endpoint: `GET /api/dev-log`**
|
|||
|
|
- Reads `DEVELOPMENT_LOG.md`
|
|||
|
|
- Returns parsed JSON array of log entries (not raw markdown)
|
|||
|
|
- Each entry: `{ version, date, status, agents: [{name, status, time, notes}], filesModified: [...] }`
|
|||
|
|
- Called lazily — frontend only fetches when Activity Log tab is selected
|
|||
|
|
|
|||
|
|
**3. Keep `/api/about-admin` unchanged**
|
|||
|
|
- Still returns `version`, `future` (raw), `developmentLog` (raw) for backward compatibility
|
|||
|
|
- AdminDashboard continues to work until we swap it out
|
|||
|
|
|
|||
|
|
### Files
|
|||
|
|
- `routes/aboutAdmin.js` — add `/api/roadmap` and `/api/dev-log` routes
|
|||
|
|
- `client/api.js` — add `roadmap()` and `devLog()` functions
|
|||
|
|
|
|||
|
|
### Acceptance criteria
|
|||
|
|
- `GET /api/roadmap` returns JSON with structured items and counts
|
|||
|
|
- `GET /api/dev-log` returns parsed log entries
|
|||
|
|
- `GET /api/about-admin` still works unchanged
|
|||
|
|
- Completed/strikethrough items are excluded from `/api/roadmap`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 2 — Scarlett: RoadmapPage UI (Kanban Lanes + Tabs)
|
|||
|
|
|
|||
|
|
**Agent:** Scarlett
|
|||
|
|
**Priority:** Depends on Task 1
|
|||
|
|
**Estimated time:** 6-8 hours
|
|||
|
|
**Stack mandate:** Vite + React (NOT Next.js). All UI components must use shadcn/ui primitives. Styling via Tailwind CSS only.
|
|||
|
|
|
|||
|
|
### What
|
|||
|
|
Build a standalone `RoadmapPage.jsx` with kanban-style priority lanes and a tab for the Activity Log. Replace the current AdminDashboard component.
|
|||
|
|
|
|||
|
|
### Changes
|
|||
|
|
|
|||
|
|
**1. New file: `client/pages/RoadmapPage.jsx`**
|
|||
|
|
- Fetch data from `/api/roadmap` on mount
|
|||
|
|
- Lazy-fetch `/api/dev-log` only when Activity Log tab is selected
|
|||
|
|
- Page-level scroll only (no nested scroll containers)
|
|||
|
|
- Page header: "🗺️ Roadmap" title + version badge (from `/api/roadmap` response or `APP_VERSION`)
|
|||
|
|
|
|||
|
|
**2. Kanban lane layout (Roadmap tab)**
|
|||
|
|
- Desktop (`lg+`): 5-column grid — one lane per priority (CRITICAL, HIGH, MEDIUM, LOW, NICE TO HAVE)
|
|||
|
|
- Tablet (`sm–lg`): 2-column grid (CRITICAL+HIGH | MEDIUM+LOW+NICE TO HAVE)
|
|||
|
|
- Mobile (`< sm`): single column, lanes stack vertically as collapsible sections
|
|||
|
|
- Each lane header: priority emoji + label + item count badge (e.g., "🔴 Critical (1)")
|
|||
|
|
- Lane header has colored top border from PRIORITY_COLORS map
|
|||
|
|
|
|||
|
|
**3. Roadmap item cards**
|
|||
|
|
- Compact card: priority badge, title (bold, 2-3 line clamp), date added, effort estimate
|
|||
|
|
- Click to expand via shadcn `Collapsible` (Radix-based, accessible, `aria-expanded`)
|
|||
|
|
- Expanded view shows three labeled sections: Description, Rationale, Implementation Notes — properly styled, not raw markdown
|
|||
|
|
- "Expand All / Collapse All" toggle button above the lane grid
|
|||
|
|
|
|||
|
|
**4. Activity Log tab**
|
|||
|
|
- shadcn `Tabs` component with two tabs: "Roadmap" | "Activity Log"
|
|||
|
|
- Activity Log shows parsed dev log entries in vertical timeline format
|
|||
|
|
- Each entry: version, date, agent badges with status icons, files modified count
|
|||
|
|
- Expandable details (click to see full entry content)
|
|||
|
|
- Lazy-loaded — only fetch when tab is selected
|
|||
|
|
|
|||
|
|
**5. Replace shadcn/ui components (not custom)**
|
|||
|
|
- `SimpleCollapsible` → shadcn `Collapsible` (`Collapsible`, `CollapsibleTrigger`, `CollapsibleContent`)
|
|||
|
|
- `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent` for the tab switcher
|
|||
|
|
- Keep existing `Card`, `Badge`, `Button` usage
|
|||
|
|
- Use shadcn `Accordion` for mobile lane fallback if needed
|
|||
|
|
|
|||
|
|
### Files
|
|||
|
|
- **NEW:** `client/pages/RoadmapPage.jsx` — the entire new page
|
|||
|
|
- **MODIFY:** `client/App.jsx` — update `/admin/roadmap` route to render `<RoadmapPage />` instead of `<AboutPage admin />`; add lazy import
|
|||
|
|
- **MODIFY:** `client/pages/AboutPage.jsx` — remove `admin` prop, remove `AdminDashboard` import, revert to public-only about page
|
|||
|
|
- **DELETE:** `client/components/AdminDashboard.jsx` — replaced entirely by RoadmapPage
|
|||
|
|
- Check if shadcn `Collapsible` and `Tabs` are already installed; if not, add via `npx shadcn@latest add collapsible`
|
|||
|
|
|
|||
|
|
### Acceptance criteria
|
|||
|
|
- `/admin/roadmap` renders RoadmapPage with kanban lanes
|
|||
|
|
- `/admin` and `/about` no longer show the admin dashboard
|
|||
|
|
- Desktop: 5 priority lanes side by side
|
|||
|
|
- Mobile: lanes stack vertically
|
|||
|
|
- Each item card expands to show Description/Rationale/Notes as separate styled sections
|
|||
|
|
- Activity Log tab lazy-loads dev log data
|
|||
|
|
- No `SimpleCollapsible` usage — all shadcn `Collapsible`
|
|||
|
|
- All interactive elements keyboard-focusable with `aria-expanded`
|
|||
|
|
- Dark mode and light mode both render correctly
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 3 — Private_Hudson: Security Review
|
|||
|
|
|
|||
|
|
**Agent:** Private_Hudson
|
|||
|
|
**Priority:** After Task 2
|
|||
|
|
**Estimated time:** 1-2 hours
|
|||
|
|
|
|||
|
|
### What
|
|||
|
|
Review the new endpoints and page for security issues.
|
|||
|
|
|
|||
|
|
### Current CSRF Security Context
|
|||
|
|
|
|||
|
|
Bill Tracker uses a **double-submit cookie pattern** for CSRF protection:
|
|||
|
|
|
|||
|
|
- **Cookie:** `bt_csrf_token` (set by `csrfTokenProvider` middleware on every response)
|
|||
|
|
- **Header:** Frontend reads token from `document.cookie` and sends it as `x-csrf-token` header on all state-changing requests (POST, PUT, DELETE, PATCH)
|
|||
|
|
- **Validation:** `csrfMiddleware` compares cookie value to header/query/body value — must match exactly
|
|||
|
|
- **Token generation:** `crypto.randomBytes(32).toString('hex')` (256-bit)
|
|||
|
|
|
|||
|
|
**Configuration (env vars):**
|
|||
|
|
- `CSRF_HTTP_ONLY` — defaults to `false` (SPA needs JS to read cookie for double-submit)
|
|||
|
|
- `CSRF_SAME_SITE` — defaults to `strict`
|
|||
|
|
- `CSRF_SECURE` — defaults to `true` (HTTPS only)
|
|||
|
|
- `CSRF_COOKIE_NAME` — defaults to `bt_csrf_token`
|
|||
|
|
|
|||
|
|
**CSRF-exempt routes (via `req.csrfSkip`):**
|
|||
|
|
- `POST /api/auth/login` — no session exists yet, nothing to hijack
|
|||
|
|
- `POST /api/auth/logout-all` — uses session cookie directly
|
|||
|
|
|
|||
|
|
**All other state-changing routes have CSRF enforced**, including:
|
|||
|
|
- `POST /api/auth/change-password` — covered by `csrfMiddleware` on `/api/auth` mount
|
|||
|
|
- `POST /api/profile/change-password` — covered by `csrfMiddleware` on `/api/profile` mount
|
|||
|
|
- All `/api/bills`, `/api/payments`, `/api/categories`, `/api/tracker`, `/api/analytics`, etc.
|
|||
|
|
|
|||
|
|
⚠️ **Known stale comment:** `routes/auth.js` line 120 has a comment saying "Exempt from CSRF" on the change-password route, but there is NO `req.csrfSkip` set — the route IS protected. The comment is wrong and should be removed.
|
|||
|
|
|
|||
|
|
### Checks for New Endpoints
|
|||
|
|
- `/api/roadmap` and `/api/dev-log` are GET routes — CSRF middleware only validates POST/PUT/DELETE/PATCH, so they're safe by default. But confirm they still require admin auth.
|
|||
|
|
- No FUTURE.md internal file paths leak through the API (the `redactSensitiveContent` function from `aboutAdmin.js` is applied)
|
|||
|
|
- `/api/roadmap` doesn't expose implementation details that could aid an attacker (file paths, internal IPs, etc.)
|
|||
|
|
- `/api/dev-log` doesn't expose agent names/tokens that shouldn't be visible
|
|||
|
|
- XSS check: all parsed content rendered through React's JSX (auto-escaped) or sanitized
|
|||
|
|
- Route: confirm `/admin/roadmap` is behind `<RequireAuth role="admin">`
|
|||
|
|
- Fix stale comment in `routes/auth.js` line 120 (remove or correct the "Exempt from CSRF" note)
|
|||
|
|
|
|||
|
|
### Files
|
|||
|
|
- `routes/aboutAdmin.js` — review new routes
|
|||
|
|
- `client/pages/RoadmapPage.jsx` — review rendering
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 4 — Bishop: Verification + Docs Update
|
|||
|
|
|
|||
|
|
**Agent:** Bishop
|
|||
|
|
**Priority:** After Tasks 2 and 3
|
|||
|
|
**Estimated time:** 2-3 hours
|
|||
|
|
|
|||
|
|
### What
|
|||
|
|
Build, test, verify the redesign works, update docs.
|
|||
|
|
|
|||
|
|
### Steps
|
|||
|
|
1. Run `scripts/docker-test.sh` — fresh build on port 3036
|
|||
|
|
2. Test: admin login → navigate to `/admin/roadmap`
|
|||
|
|
3. Verify: 5 priority lanes render on desktop
|
|||
|
|
4. Verify: lanes stack on mobile viewport
|
|||
|
|
5. Verify: click item card → expands to show Description/Rationale/Notes
|
|||
|
|
6. Verify: Activity Log tab loads data on click (not on page load)
|
|||
|
|
7. Verify: `/about` and `/admin` no longer show admin dashboard
|
|||
|
|
8. Verify: `/admin/roadmap` requires admin auth (non-admin gets redirect)
|
|||
|
|
9. Verify: dark mode + light mode both look correct
|
|||
|
|
10. Verify: keyboard navigation works (Tab, Enter/Space to expand)
|
|||
|
|
11. Update `client/lib/version.js` — bump patch version
|
|||
|
|
12. Update `STRUCTURE.md` — add RoadmapPage, remove AdminDashboard, update AboutPage description
|
|||
|
|
13. Update Engineering Reference Manual — grep headings, update relevant sections only
|
|||
|
|
|
|||
|
|
### Files
|
|||
|
|
- `client/lib/version.js` — version bump
|
|||
|
|
- `package.json` — version bump
|
|||
|
|
- `STRUCTURE.md` — add RoadmapPage, remove AdminDashboard
|
|||
|
|
- `docs/Engineering_Reference_Manual.md` — targeted section updates
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 5 — Ripley: Final Commit & Push
|
|||
|
|
|
|||
|
|
**Agent:** Ripley
|
|||
|
|
**Priority:** After Task 4
|
|||
|
|
|
|||
|
|
### What
|
|||
|
|
Final review, commit, push, deploy.
|
|||
|
|
|
|||
|
|
### Steps
|
|||
|
|
1. Review all changes
|
|||
|
|
2. `git add -A && git commit -m "feat: redesign roadmap page as kanban-style priority lanes"`
|
|||
|
|
3. `git push origin dev`
|
|||
|
|
4. `scripts/docker-test.sh` — rebuild and redeploy
|
|||
|
|
5. Update HISTORY.md with the change
|
|||
|
|
6. Update FUTURE.md — add "Roadmap page redesign" if not already there, or reference this work
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Dependency Graph
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Task 1 (Neo: API split)
|
|||
|
|
└──→ Task 2 (Scarlett: UI) ──→ Task 3 (Hudson: Security) ──→ Task 4 (Bishop: Verify) ──→ Task 5 (Ripley: Commit)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Tasks 1 and 2 are sequential. Tasks 3 and 4 are sequential after 2. Task 5 is final.
|
|||
|
|
|
|||
|
|
## Estimated Total Time
|
|||
|
|
|
|||
|
|
| Task | Agent | Time |
|
|||
|
|
|------|-------|------|
|
|||
|
|
| 1 | Neo | 2-3h |
|
|||
|
|
| 2 | Scarlett | 6-8h |
|
|||
|
|
| 3 | Hudson | 1-2h |
|
|||
|
|
| 4 | Bishop | 2-3h |
|
|||
|
|
| 5 | Ripley | 30m |
|
|||
|
|
| **Total** | | **12-17h** |
|
|||
|
|
|
|||
|
|
## Rollback Plan
|
|||
|
|
|
|||
|
|
If the redesign has issues in production:
|
|||
|
|
- Revert `App.jsx` route to `<AboutPage admin />`
|
|||
|
|
- Restore `AdminDashboard.jsx` from git
|
|||
|
|
- Roadmap page works again in the old format
|
|||
|
|
- New `/api/roadmap` and `/api/dev-log` endpoints are additive — no data loss
|