Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 21 additions & 10 deletions assets/toolbox/idea-board/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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.");
Expand Down Expand Up @@ -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) {
Expand All @@ -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,
Expand Down Expand Up @@ -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();
Expand All @@ -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();
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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`
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
@@ -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`. |
Original file line number Diff line number Diff line change
@@ -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 "<script>|<style|style=|onclick=|onchange=|oninput=|onsubmit=" toolbox/idea-board/index.html assets/toolbox/idea-board/js/index.js` | PASS | No matches. |
| `node scripts/run-node-test-files.mjs tests/regression/CanonicalRepositoryStructureGuardrail.test.mjs` | PASS | 1 file, 2 tests passed. |
| `npx playwright test tests/playwright/tools/IdeaBoardTableNotes.spec.mjs --config=tmp/playwright-system-chrome.config.cjs --workers=1 --reporter=list -g "Idea Board guest write actions redirect to sign in before saving data"` | PASS | Guest redirects verified for all scoped write actions. |
| `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs --config=tmp/playwright-system-chrome.config.cjs --workers=1 --reporter=list -g "Idea Board launches from Toolbox with accordion table notes model"` | PASS | Idea Board route and V8 coverage path exercised. |
| `npx playwright test tests/playwright/tools/IdeaBoardTableNotes.spec.mjs --config=tmp/playwright-system-chrome.config.cjs --workers=1 --reporter=list` | WARN | 3 passed, 1 failed in downstream Game Hub expanded-row expectation: expected 3 child rows, received 2 (`source-idea`, `readiness-output`). This is unrelated legacy drift. |
| `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs --config=tmp/playwright-system-chrome.config.cjs --workers=1 --reporter=list` | WARN | 6 passed, 5 failed in unrelated toolbox metadata/route/local-port expectations. The Idea Board launch test passed. |

## Browser Setup Note

- WARN: Default Playwright Chromium was missing at `C:\Users\davidq\AppData\Local\ms-playwright\chromium-1217\chrome-win64\chrome.exe`.
- WARN: `npx playwright install chromium` stalled with only partial placeholder files and was stopped.
- PASS: Focused browser validation was rerun with installed Google Chrome through a temporary `tmp/playwright-system-chrome.config.cjs`, then the temp config and `tmp/test-results` were removed.

## Full-Suite Residual Failures

- `ToolboxRoutePages`: expected `Game Hub` route `/toolbox/game-workspace/index.html` not visible.
- `ToolboxRoutePages`: expected toolbox status counts `Planned (28)` and `Beta (6)`; actual `Planned (27)` and `Beta (8)`.
- `ToolboxRoutePages`: Game Crew route run recorded failed requests for shared toolbox metadata modules.
- `ToolboxRoutePages`: local dev port guard expected redirect to port `5501`; page remained on the ephemeral test server port.
- `IdeaBoardTableNotes`: Game Hub row expansion expected `summary`, `source-idea`, and `readiness-output`; rendered `source-idea` and `readiness-output`.

## Result

PASS: BRAVO_011 validation lane passed for scoped guest-save auth redirect behavior.

WARN: Broad legacy Playwright files are not fully green due to unrelated existing drift listed above.
33 changes: 30 additions & 3 deletions docs_build/dev/reports/codex_changed_files.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
docs_build/dev/reports/PR_26175_OWNER_055-remaining-open-pr-action-plan.md
docs_build/dev/reports/codex_changed_files.txt
docs_build/dev/reports/codex_review.diff
# git diff --cached --name-status origin/main
M assets/toolbox/idea-board/js/index.js
A docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_branch-validation.md
A docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_instruction-compliance.md
A docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_manual-validation-notes.md
A docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_report.md
A docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_requirements-checklist.md
A docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_validation-lane.md
M docs_build/dev/reports/codex_changed_files.txt
M docs_build/dev/reports/codex_review.diff
M docs_build/dev/reports/coverage_changed_js_guardrail.txt
M docs_build/dev/reports/playwright_v8_coverage_report.txt
M tests/playwright/tools/IdeaBoardTableNotes.spec.mjs
M tests/playwright/tools/ToolboxRoutePages.spec.mjs

# git diff --cached --stat origin/main
assets/toolbox/idea-board/js/index.js | 31 +-
...d-guest-save-auth-redirect_branch-validation.md | 22 +
...st-save-auth-redirect_instruction-compliance.md | 31 +
...t-save-auth-redirect_manual-validation-notes.md | 37 ++
...1-idea-board-guest-save-auth-redirect_report.md | 51 ++
...st-save-auth-redirect_requirements-checklist.md | 19 +
...ard-guest-save-auth-redirect_validation-lane.md | 36 ++
docs_build/dev/reports/codex_changed_files.txt | 33 +-
docs_build/dev/reports/codex_review.diff | 695 +++++++++++++++++----
.../dev/reports/coverage_changed_js_guardrail.txt | 10 +-
.../dev/reports/playwright_v8_coverage_report.txt | 39 +-
.../playwright/tools/IdeaBoardTableNotes.spec.mjs | 118 +++-
tests/playwright/tools/ToolboxRoutePages.spec.mjs | 5 +-
13 files changed, 941 insertions(+), 186 deletions(-)
Loading
Loading