From 97dc67515a63126051887927d03c41336b17d86d Mon Sep 17 00:00:00 2001 From: Bravo Team Date: Wed, 24 Jun 2026 15:40:00 -0400 Subject: [PATCH] Require authentication before Idea Board save actions --- assets/toolbox/idea-board/js/index.js | 31 +- ...st-save-auth-redirect_branch-validation.md | 22 + ...ve-auth-redirect_instruction-compliance.md | 31 + ...e-auth-redirect_manual-validation-notes.md | 37 + ...a-board-guest-save-auth-redirect_report.md | 51 ++ ...ve-auth-redirect_requirements-checklist.md | 19 + ...uest-save-auth-redirect_validation-lane.md | 36 + .../dev/reports/codex_changed_files.txt | 33 +- docs_build/dev/reports/codex_review.diff | 695 ++++++++++++++---- .../reports/coverage_changed_js_guardrail.txt | 10 +- .../reports/playwright_v8_coverage_report.txt | 39 +- .../tools/IdeaBoardTableNotes.spec.mjs | 118 ++- .../tools/ToolboxRoutePages.spec.mjs | 5 +- 13 files changed, 941 insertions(+), 186 deletions(-) create mode 100644 docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_branch-validation.md create mode 100644 docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_instruction-compliance.md create mode 100644 docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_manual-validation-notes.md create mode 100644 docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_report.md create mode 100644 docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_requirements-checklist.md create mode 100644 docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_validation-lane.md diff --git a/assets/toolbox/idea-board/js/index.js b/assets/toolbox/idea-board/js/index.js index 25607bc8d..0c10d2dc1 100644 --- a/assets/toolbox/idea-board/js/index.js +++ b/assets/toolbox/idea-board/js/index.js @@ -437,6 +437,7 @@ function ideaIdFromText(text) { } function saveIdeaRow(root, row) { + if (!requireAuthenticatedWrite(root)) return; const idea = row.querySelector("[data-idea-board-idea-input]")?.value.trim(); const pitch = row.querySelector("[data-idea-board-pitch-input]")?.value.trim(); const status = row.querySelector("[data-idea-board-idea-status-input]")?.value; @@ -479,6 +480,7 @@ function saveIdeaRow(root, row) { } function saveNoteRow(root, row) { + if (!requireAuthenticatedWrite(root)) return; const ideaId = row.dataset.ideaId; const idea = ideaRecord(ideaId); if (idea && isLockedIdea(idea)) { @@ -533,6 +535,7 @@ function toggleNotes(root, ideaId) { } function deleteIdea(root, ideaId) { + if (!requireAuthenticatedWrite(root)) return; const index = ideaTable.findIndex((record) => record.ideaId === ideaId); if (index < 0) { updateStatus(root, "Idea Board could not delete that idea."); @@ -588,6 +591,20 @@ function currentSessionState() { } } +function requireAuthenticatedWrite(root) { + const sessionState = currentSessionState(); + if (!sessionState.apiAvailable) { + updateStatus(root, "API session status could not be verified. Try again shortly."); + return false; + } + if (!sessionState.authenticated) { + updateStatus(root, "Sign in before saving Idea Board changes."); + window.location.href = signInUrl(); + return false; + } + return true; +} + function createProject(root, ideaId) { const record = ideaRecord(ideaId); if (!record) { @@ -598,16 +615,7 @@ function createProject(root, ideaId) { updateStatus(root, "Set this idea to Ready before creating a project."); return; } - const sessionState = currentSessionState(); - if (!sessionState.apiAvailable) { - updateStatus(root, "Sign-in status could not be verified. Try again shortly."); - return; - } - if (!sessionState.authenticated) { - updateStatus(root, "Sign in to create a Game Hub project."); - window.location.href = signInUrl(); - return; - } + if (!requireAuthenticatedWrite(root)) return; const repository = gameHubProjectRepository(); const project = repository.createGame({ name: record.idea, @@ -638,6 +646,7 @@ function archiveIdea(root, ideaId) { updateStatus(root, "Idea Board could not archive that idea."); return; } + if (!requireAuthenticatedWrite(root)) return; if (record.status !== "Archived") record.previousStatus = record.status; record.status = "Archived"; record.updated = today(); @@ -657,6 +666,7 @@ function restoreIdea(root, ideaId) { updateStatus(root, "Idea Board could not restore that idea."); return; } + if (!requireAuthenticatedWrite(root)) return; record.status = previousStatusForRestore(record); record.previousStatus = record.status; record.updated = today(); @@ -742,6 +752,7 @@ function handleNoteAction(root, actionControl) { updateStatus(root, "Editing note."); render(root); } else if (action === "delete") { + if (!requireAuthenticatedWrite(root)) return; const index = noteTable.findIndex((note) => note.noteId === noteId && note.ideaId === ideaId && !note.system); if (index >= 0) { noteTable.splice(index, 1); diff --git a/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_branch-validation.md b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_branch-validation.md new file mode 100644 index 000000000..3e0239894 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_branch-validation.md @@ -0,0 +1,22 @@ +# PR_26175_BRAVO_011 Branch Validation + +Date: 2026-06-24 + +## Branch Gate + +- PASS: Current branch was verified as `main` before planning and implementation. +- PASS: Worktree was verified clean before the PR branch was created. +- PASS: `origin/main` was pulled/rebased before the PR branch was created. +- PASS: `HEAD`, `main`, and `origin/main` were synced at `dd7a3732e4225e42fe1033d37090abe179e6d5a5`. +- PASS: Work moved to scoped branch `pr/26175-BRAVO-011-idea-board-guest-save-auth-redirect`. + +## Current State Before Commit + +- Branch: `pr/26175-BRAVO-011-idea-board-guest-save-auth-redirect` +- Base commit: `dd7a3732e4225e42fe1033d37090abe179e6d5a5` +- Origin/main sync before edits: `0/0` +- Worktree: dirty with intended PR files and required reports. + +## Result + +PASS: Branch and clean-worktree gates passed before implementation. Current dirty state is expected PR output before commit. diff --git a/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_instruction-compliance.md b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_instruction-compliance.md new file mode 100644 index 000000000..11c593d22 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_instruction-compliance.md @@ -0,0 +1,31 @@ +# PR_26175_BRAVO_011 Instruction Compliance + +Date: 2026-06-24 + +## Governance + +- PASS: Read ProjectInstructions before implementation. +- PASS: Initial branch was `main`; implementation did not begin until after the main-branch gate passed. +- PASS: Initial worktree was clean before implementation. +- PASS: Scope remained limited to Idea Board auth gating, impacted tests, and required reports. +- PASS: No engine core files modified. +- PASS: No `start_of_day` files modified. +- PASS: No `imageDataUrl` contract usage introduced. +- PASS: No runtime code outside the Idea Board save/auth path was changed. + +## Frontend / Runtime Rules + +- PASS: No inline runtime script/style/event handlers added. +- PASS: No browser-owned product-data SSoT added. +- PASS: No localStorage/sessionStorage product-data persistence added. +- PASS: Existing API/session terminology and helpers were used. + +## Reporting / Packaging + +- PASS: Required PR reports created. +- PASS: V8 coverage reports refreshed after Playwright route coverage. +- PASS: `codex_review.diff`, `codex_changed_files.txt`, and repo-structured ZIP are generated for this run. + +## ZIP + +- `tmp/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_delta.zip` diff --git a/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_manual-validation-notes.md b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_manual-validation-notes.md new file mode 100644 index 000000000..03f98b044 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_manual-validation-notes.md @@ -0,0 +1,37 @@ +# PR_26175_BRAVO_011 Manual Validation Notes + +Date: 2026-06-24 + +## Reviewed Runtime Paths + +- `toolbox/idea-board/index.html` +- `assets/toolbox/idea-board/js/index.js` +- `src/api/session-api-client.js` +- `src/api/server-api-client.js` +- Sign-in route usage: `account/sign-in.html` + +## Persist Actions Verified + +- Add idea save: guest redirects before save. +- Edit idea save: guest redirects before update. +- Delete idea: guest redirects before delete. +- Add note save: guest redirects before save. +- Edit note save: guest redirects before update. +- Delete note: guest redirects before delete. +- Create project: guest redirects before `createGame`. +- Archive project idea: guest redirects before archive mutation. +- Restore archived project idea: guest redirects before restore mutation. + +## Browse Actions Verified + +- Guest can load the Idea Board. +- Guest can expand existing idea notes. +- Guest remains on `toolbox/idea-board/index.html` while browsing. + +## Data Safety Notes + +- No production data was modified. +- No migration or database write was executed outside Playwright local test servers. +- No browser product-data SSoT was added. +- No `localStorage` or `sessionStorage` product-data persistence was added. +- No fake login or silent fallback was added. diff --git a/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_report.md b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_report.md new file mode 100644 index 000000000..498138c5c --- /dev/null +++ b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_report.md @@ -0,0 +1,51 @@ +# PR_26175_BRAVO_011 Idea Board Guest Save Auth Redirect + +Date: 2026-06-24 + +## Scope + +Require an authenticated API session before Idea Board save or persist actions. Guests may still browse the Idea Board, expand rows, and inspect notes. Guests are redirected to `account/sign-in.html` before any save/persist mutation. + +## Review Findings + +- PASS: ProjectInstructions and governance documents were reviewed before implementation. +- PASS: Initial branch was `main`, worktree was clean, and `main`/`origin/main` were synced at `dd7a3732e4225e42fe1033d37090abe179e6d5a5` before the PR branch was created. +- PASS: `toolbox/idea-board/index.html` delegates runtime behavior to `assets/toolbox/idea-board/js/index.js`. +- PASS: Existing auth/session helper is `getSessionCurrent()` from `src/api/session-api-client.js`, backed by the API session contract. +- PASS: Existing sign-in route pattern uses `account/sign-in.html`. +- PASS: Persisting Idea Board actions identified: idea save, idea delete, note save, note delete, create project, archive, and restore. +- PASS: Browse-only actions identified: loading the board, expanding/collapsing notes, filtering, starting/canceling edit rows, and opening existing project links. + +## Implementation Summary + +- Added one shared Idea Board write guard, `requireAuthenticatedWrite(root)`, using the existing API session helper. +- Applied the guard before every Idea Board mutation/write path: idea save, note save, idea delete, note delete, create project, archive, and restore. +- Preserved guest browsing by leaving load, filter, expand/collapse, and non-persist UI actions unauthenticated. +- Expanded Playwright coverage so guest add/edit/delete idea, add/edit/delete note, create project, archive, and restore actions redirect to sign-in before writes. +- Kept the implementation on the existing API contract; no browser product-data SSoT, fake login, localStorage/sessionStorage product data, or environment-specific branch was introduced. + +## Affected Files + +- `assets/toolbox/idea-board/js/index.js` +- `tests/playwright/tools/IdeaBoardTableNotes.spec.mjs` +- `tests/playwright/tools/ToolboxRoutePages.spec.mjs` +- `docs_build/dev/reports/playwright_v8_coverage_report.txt` +- `docs_build/dev/reports/coverage_changed_js_guardrail.txt` + +## Validation Summary + +- PASS: Targeted node guardrail passed. +- PASS: Runtime grep found no `localStorage` or `sessionStorage` use in Idea Board runtime HTML/JS. +- PASS: Runtime grep found no inline script/style/event-handler additions in Idea Board runtime HTML/JS. +- PASS: Focused Playwright guest redirect test passed. +- PASS: Focused Playwright Toolbox-to-Idea-Board launch test passed after filtering unrelated selected-game status polling from the no-write assertion. +- PASS: Playwright V8 coverage report includes `assets/toolbox/idea-board/js/index.js`. +- WARN: Bundled Playwright Chromium was missing and `npx playwright install chromium` stalled with a partial install; focused browser validation used installed Google Chrome through a temporary config that was removed after validation. +- WARN: Full legacy Playwright files still have unrelated expectation drift documented in the validation lane report. + +## Recommended Next PR + +Create a follow-up validation cleanup PR for existing Toolbox/Game Hub drift: + +- Refresh `ToolboxRoutePages` expected tool counts, Game Hub route alias expectations, failed module-load assertions, and local dev port guard expectation. +- Refresh or repair the Game Hub expanded child-row summary expectation in `IdeaBoardTableNotes`. diff --git a/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_requirements-checklist.md b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_requirements-checklist.md new file mode 100644 index 000000000..4100a8b51 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_requirements-checklist.md @@ -0,0 +1,19 @@ +# PR_26175_BRAVO_011 Requirements Checklist + +Date: 2026-06-24 + +| Requirement | Result | Evidence | +| --- | --- | --- | +| Guests may browse the Idea Board. | PASS | Playwright expands `top-thoughts` as a guest and remains on `toolbox/idea-board/index.html`. | +| Guests may not save creator-owned data. | PASS | Guest save/persist controls redirect before mutation. | +| Every save/persist action redirects unauthenticated users to `account/sign-in.html`. | PASS | Covered add/edit/delete idea, add/edit/delete note, create project, archive, and restore. | +| Redirect before any API write. | PASS | Guest create/archive/restore assertions reset and inspect create-game requests; no write request is sent before redirect. | +| All environments use the same API contract. | PASS | Uses existing `getSessionCurrent()` API session helper; no environment-specific branch added. | +| Do not introduce browser-owned product data. | PASS | No new browser persistence or product-data SSoT added. | +| Do not use localStorage/sessionStorage as product-data SSoT. | PASS | Runtime grep found no `localStorage` or `sessionStorage` in Idea Board runtime HTML/JS. | +| Do not introduce fake login behavior. | PASS | Runtime uses existing API session helper only; tests use repo test session endpoint. | +| No silent fallbacks. | PASS | API session verification failure blocks the write and reports status. | +| Use API terminology only. | PASS | New unavailable status uses API session terminology. | +| Keep PR limited to scope. | PASS | Runtime change is limited to Idea Board write gating; tests and reports cover the same scope. | +| Create required reports. | PASS | PR report, branch validation, requirement checklist, validation lane, manual notes, instruction compliance, review diff, changed files, and V8 coverage reports are included. | +| Create repo-structured ZIP under `tmp/`. | PASS | `tmp/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_delta.zip`. | diff --git a/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_validation-lane.md b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_validation-lane.md new file mode 100644 index 000000000..c7ffdfcc9 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_validation-lane.md @@ -0,0 +1,36 @@ +# PR_26175_BRAVO_011 Validation Lane + +Date: 2026-06-24 + +## Commands + +| Command | Result | Notes | +| --- | --- | --- | +| `git diff --check` | PASS | CRLF warnings only for touched Playwright specs. | +| `rg -n "localStorage|sessionStorage" assets/toolbox/idea-board/js/index.js toolbox/idea-board/index.html` | PASS | No runtime matches. | +| `rg -n "