From 7c698f045638b6f74520f206da32e439cba8a988 Mon Sep 17 00:00:00 2001 From: DavidQ Date: Tue, 23 Jun 2026 19:38:38 -0400 Subject: [PATCH] ALFA 008 game hub feature matrix --- docs_build/dev/BUILD_PR.md | 54 +- ...ALFA_008-game-hub-feature-matrix_report.md | 35 + ...b-feature-matrix_requirements-checklist.md | 15 + ...game-hub-feature-matrix_validation-lane.md | 11 + .../dev/reports/codex_changed_files.txt | 29 +- docs_build/dev/reports/codex_review.diff | 1429 +---------------- 6 files changed, 97 insertions(+), 1476 deletions(-) create mode 100644 docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md create mode 100644 docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md create mode 100644 docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md diff --git a/docs_build/dev/BUILD_PR.md b/docs_build/dev/BUILD_PR.md index cf7378880..dd5b4d28f 100644 --- a/docs_build/dev/BUILD_PR.md +++ b/docs_build/dev/BUILD_PR.md @@ -1,59 +1,63 @@ -# PR_26175_ALFA_006-game-hub-create-project-validation +# PR_26175_ALFA_008-game-hub-feature-matrix ## Purpose -Add creator-facing validation for the Game Hub create-project row so blank game names do not silently create fallback projects. +Audit the current Game Hub workflow and publish a feature matrix that maps implemented creator-facing behavior to code and Playwright evidence. ## Source Of Truth -This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_006-game-hub-create-project-validation`. +This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_008-game-hub-feature-matrix`. ## Exact Scope -- Validate the Game Hub add-game row before calling the repository create method. -- Block signed-in creator saves when the game name is blank or whitespace-only. -- Keep the add-game row open after validation failure. -- Show a creator-safe validation message in the existing Game Hub status log. -- Mark the game name input invalid for accessibility. -- Preserve valid create/open/delete behavior. -- Preserve guest save redirect behavior. +- Produce a Game Hub feature matrix only. +- Audit Game Hub table workflow, selected/open game behavior, create/edit/delete actions, child tables, guest save gating, empty/error states, Theme V2 layout, and targeted Game Hub coverage. +- Use current `main` behavior as evidence. +- Preserve Game Hub UI/product behavior. - Preserve API/service/repository contracts. -- Add targeted Playwright coverage for the create validation path. +- Preserve previous ALFA Game Hub cleanup and create-validation behavior. +- Do not implement product/UI changes unless validation exposes a requirement-critical defect. ## Exact Targets - `docs_build/dev/BUILD_PR.md` -- `toolbox/game-hub/game-hub.js` -- `tests/playwright/tools/GameHubMockRepository.spec.mjs` -- `docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_report.md` -- `docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_validation-lane.md` -- `docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_requirements-checklist.md` +- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md` +- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md` +- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md` - `docs_build/dev/reports/codex_review.diff` - `docs_build/dev/reports/codex_changed_files.txt` +## Evidence Sources +- `toolbox/game-hub/index.html` +- `toolbox/project-workspace/index.html` +- `toolbox/game-hub/game-hub.js` +- `toolbox/game-hub/game-hub-api-client.js` +- `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js` +- `tests/playwright/tools/GameHubMockRepository.spec.mjs` + ## Out Of Scope -- No repository/API/service contract changes. -- No Game Journey completion-metrics changes. +- No Game Hub product or UI changes. +- No Game Journey changes. - No shared toolbox status bar changes. -- No unrelated Game Hub workflow changes. - No browser-owned product data as source of truth. -- No silent create-name fallback in the Game Hub page flow. +- No API/service/repository contract changes. - No inline styles, style blocks, or page-local CSS. - No engine core changes. - No `start_of_day` folder changes. +- No ALFA_007 work. ## Validation -Run targeted create-project validation: +Run targeted Game Hub validation: ```powershell -npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1 --grep "Game Hub creates, opens, and deletes mock games" +npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1 ``` -Also verify changed source does not introduce inline styles or style blocks: +Also verify changed docs/reports do not introduce inline styles or style blocks: ```powershell -rg -n "<[s]tyle|[s]tyle=" toolbox/game-hub/game-hub.js tests/playwright/tools/GameHubMockRepository.spec.mjs docs_build/dev/BUILD_PR.md docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_report.md docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_validation-lane.md docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_requirements-checklist.md +rg -n "<[s]tyle|[s]tyle=" docs_build/dev/BUILD_PR.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md ``` ## Artifact Create repo-structured delta ZIP: ```text -tmp/PR_26175_ALFA_006-game-hub-create-project-validation_delta.zip +tmp/PR_26175_ALFA_008-game-hub-feature-matrix_delta.zip ``` diff --git a/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md new file mode 100644 index 000000000..3fbcfdb04 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md @@ -0,0 +1,35 @@ +# PR_26175_ALFA_008-game-hub-feature-matrix Report + +## Overall Status +PASS + +## Summary +ALFA_008 produced a report-only Game Hub feature matrix from current `main` behavior. No product/UI/source implementation changes were needed. Targeted Game Hub validation passed with 14/14 Playwright tests. + +## Feature Matrix +| Feature Area | Status | Current Behavior | Source Evidence | Validation Evidence | +| --- | --- | --- | --- | --- | +| Deprecated project workspace route | PASS | Older Project Workspace links land on a Game Hub handoff page and expose one creator-facing Game Hub action. | `toolbox/project-workspace/index.html:17`, `toolbox/project-workspace/index.html:20`, `toolbox/project-workspace/index.html:21`, `toolbox/project-workspace/index.html:22` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:244`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:248`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:251` | +| Game Hub page shell | PASS | Game Hub uses Theme V2 shared classes, a wide tool workspace, center Games panel, and shared status elements. | `toolbox/game-hub/index.html:24`, `toolbox/game-hub/index.html:25`, `toolbox/game-hub/index.html:26`, `toolbox/game-hub/index.html:36`, `toolbox/game-hub/index.html:37`, `toolbox/game-hub/index.html:39` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:263`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:873`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:878`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:880` | +| Game table ownership | PASS | The Game Hub page owns the creator-facing game table and renders it in the center panel only. | `toolbox/game-hub/game-hub.js:538`, `toolbox/game-hub/game-hub.js:561`, `toolbox/game-hub/game-hub.js:563`, `toolbox/game-hub/game-hub.js:567`, `toolbox/game-hub/game-hub.js:569` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:288`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:289`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:296`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:298` | +| Parent row display | PASS | Parent rows display Game, Purpose, Status, and Actions without owner/role/next-tool columns. | `toolbox/game-hub/game-hub.js:500`, `toolbox/game-hub/game-hub.js:515`, `toolbox/game-hub/game-hub.js:518`, `toolbox/game-hub/game-hub.js:519`, `toolbox/game-hub/game-hub.js:523` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:298`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:304`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:305`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:306`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:307` | +| Selected/open game affordance | PASS | Selection is represented by the game toggle button only; rows do not gain active-row attributes or row highlighting. | `toolbox/game-hub/game-hub.js:500`, `toolbox/game-hub/game-hub.js:515`, `toolbox/game-hub/game-hub.js:768`, `toolbox/game-hub/game-hub.js:771`, `toolbox/game-hub/game-hub.js:776` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:308`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:311`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:314`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:324`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:326` | +| Add game workflow | PASS | Creators can open an add row, enter Game/Purpose/Status, save a new game, and cancel without saving. | `toolbox/game-hub/game-hub.js:428`, `toolbox/game-hub/game-hub.js:441`, `toolbox/game-hub/game-hub.js:448`, `toolbox/game-hub/game-hub.js:451`, `toolbox/game-hub/game-hub.js:699`, `toolbox/game-hub/game-hub.js:707` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:379`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:398`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:401`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:411`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:426`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:430` | +| Create-name validation | PASS | Blank and whitespace-only names are blocked in the page flow before repository create, keeping the add row open and showing a creator-safe status message. | `toolbox/game-hub/game-hub.js:681`, `toolbox/game-hub/game-hub.js:684`, `toolbox/game-hub/game-hub.js:687`, `toolbox/game-hub/game-hub.js:690`, `toolbox/game-hub/game-hub.js:703`, `toolbox/game-hub/game-hub.js:707` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:386`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:389`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:391`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:392`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:393`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:397` | +| Repository contract preservation | PASS | The Game Hub API client still uses the shared server repository client, and the mock repository contract remains unchanged. The lower-level repository still has defensive defaults, but ALFA_006 page validation prevents blank names from becoming creator-facing Game Hub creates. | `toolbox/game-hub/game-hub-api-client.js:1`, `toolbox/game-hub/game-hub-api-client.js:15`, `toolbox/game-hub/game-hub-api-client.js:16`, `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js:378`, `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js:381`, `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js:419` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:391`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:392`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:396`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:397` | +| Edit game purpose/status | PASS | Existing game names are read-only in edit mode while Purpose and Status remain editable. | `toolbox/game-hub/game-hub.js:464`, `toolbox/game-hub/game-hub.js:470`, `toolbox/game-hub/game-hub.js:471`, `toolbox/game-hub/game-hub.js:475`, `toolbox/game-hub/game-hub.js:478`, `toolbox/game-hub/game-hub.js:727`, `toolbox/game-hub/game-hub.js:741`, `toolbox/game-hub/game-hub.js:752` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:413`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:417`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:418`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:419`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:424`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:780` | +| Delete open game | PASS | Signed-in creators can delete the active non-source-linked game, and source-linked games are protected. | `toolbox/game-hub/game-hub.js:834`, `toolbox/game-hub/game-hub.js:838`, `toolbox/game-hub/game-hub.js:845`, `toolbox/game-hub/game-hub.js:851`, `toolbox/game-hub/game-hub.js:852` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:451`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:452`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:454`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:860`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:861` | +| Source idea child table | PASS | Source-linked games can expose read-only Idea Board context without edit/delete controls. | `toolbox/game-hub/game-hub.js:399`, `toolbox/game-hub/game-hub.js:401`, `toolbox/game-hub/game-hub.js:404`, `toolbox/game-hub/game-hub.js:415`, `toolbox/game-hub/game-hub.js:422` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:462`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:559`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:563`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:568`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:576` | +| Readiness output child table | PASS | Every expanded game can expose readiness output and checklist context from Game Journey progress data. | `toolbox/game-hub/game-hub.js:353`, `toolbox/game-hub/game-hub.js:370`, `toolbox/game-hub/game-hub.js:372`, `toolbox/game-hub/game-hub.js:385`, `toolbox/game-hub/game-hub.js:386`, `toolbox/game-hub/game-hub.js:408` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:362`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:365`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:579`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:581`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:826`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:858` | +| Guest browsing/save gating | PASS | Guests can browse Game Hub but save operations redirect to sign-in and delete is disabled. | `toolbox/game-hub/game-hub.js:131`, `toolbox/game-hub/game-hub.js:139`, `toolbox/game-hub/game-hub.js:147`, `toolbox/game-hub/game-hub.js:151`, `toolbox/game-hub/game-hub.js:174`, `toolbox/game-hub/game-hub.js:178` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:593`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:601`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:603`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:604`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:617`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:623` | +| Empty state | PASS | Empty project lists show a creator-safe prompt and keep Add Game available. | `toolbox/game-hub/game-hub.js:557`, `toolbox/game-hub/game-hub.js:558`, `toolbox/game-hub/game-hub.js:570` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:633`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:680`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:687`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:688`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:690` | +| Unavailable/error states | PASS | Repository and active-game errors use creator-safe messages without leaking backend details. | `toolbox/game-hub/game-hub.js:66`, `toolbox/game-hub/game-hub.js:70`, `toolbox/game-hub/game-hub.js:82`, `toolbox/game-hub/game-hub.js:89`, `toolbox/game-hub/game-hub.js:549`, `toolbox/game-hub/game-hub.js:550` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:697`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:713`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:716`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:724`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:749`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:771` | +| Role-focused Toolbox discovery | PASS | Toolbox role filters still include Game Hub where expected while hiding unavailable role-focused tools. | `tests/playwright/tools/GameHubMockRepository.spec.mjs:996`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1000`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1002`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1010`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1012`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1030` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:996`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1012`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1024`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1034` | + +## Validation +- PASS: `npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1` +- Result: 14 passed, 0 failed. +- PASS: Inline-style/style-block report scan completed with no matches after reports were created. + +## Artifact +- `tmp/PR_26175_ALFA_008-game-hub-feature-matrix_delta.zip` diff --git a/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md new file mode 100644 index 000000000..25f65acd6 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md @@ -0,0 +1,15 @@ +# PR_26175_ALFA_008-game-hub-feature-matrix Requirements Checklist + +| Requirement | Status | Evidence | +| --- | --- | --- | +| Replace stale BUILD source of truth with ALFA_008 | PASS | `docs_build/dev/BUILD_PR.md:1` identifies `PR_26175_ALFA_008-game-hub-feature-matrix`. | +| Produce a Game Hub feature matrix only | PASS | `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md` contains the feature matrix and no product source files were changed. | +| Audit Game Hub table workflow completion | PASS | Matrix rows cover Game table ownership, parent rows, selection affordance, add/create validation, edit, delete, child tables, guest gating, and error states. | +| Use current main behavior as evidence | PASS | Matrix evidence points to `toolbox/game-hub/index.html`, `toolbox/project-workspace/index.html`, `toolbox/game-hub/game-hub.js`, `toolbox/game-hub/game-hub-api-client.js`, `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js`, and `tests/playwright/tools/GameHubMockRepository.spec.mjs`. | +| Preserve Game Hub UI/product behavior | PASS | No Game Hub product/UI/source implementation files were modified in this PR. | +| Preserve API/service/repository contracts | PASS | No API, service, or repository files were modified. Matrix records existing API/repository evidence without changing contracts. | +| Preserve previous ALFA cleanup and create validation behavior | PASS | Targeted Game Hub spec passed 14/14 tests, including ALFA_005 selector cleanup and ALFA_006 create-name validation assertions. | +| Do not add browser-owned product data as source of truth | PASS | No runtime/product JSON or browser-owned data contract files were modified. | +| Do not add inline styles, style blocks, or page-local CSS | PASS | ALFA_008 changes are docs/reports only, and the targeted style scan found no matches. | +| Create required reports | PASS | Report, validation lane, requirements checklist, review diff, and changed-files report are included. | +| Create repo-structured delta ZIP | PASS | `tmp/PR_26175_ALFA_008-game-hub-feature-matrix_delta.zip` was created after reports were finalized. | diff --git a/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md new file mode 100644 index 000000000..71a5ec416 --- /dev/null +++ b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md @@ -0,0 +1,11 @@ +# PR_26175_ALFA_008-game-hub-feature-matrix Validation Lane + +## Commands +| Command | Status | Evidence | +| --- | --- | --- | +| `npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1` | PASS | 14 passed, 0 failed. Covered deprecated route, create/open/delete, parent/child tables, guest save gating, empty state, unavailable state, active-game error state, malformed active-game payloads, purpose/status edits, readiness rows, wide Theme V2 layout, representative toolbox layout, Learn guidance, and member-role filters. | +| `rg -n "<[s]tyle|[s]tyle=" docs_build/dev/BUILD_PR.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md` | PASS | No inline style or style block matches in ALFA_008 changed docs/reports. | + +## Notes +- Playwright updated shared coverage report outputs during validation; those generated files were restored because they are outside ALFA_008 exact targets. +- No product/UI/source implementation files were changed for this audit. diff --git a/docs_build/dev/reports/codex_changed_files.txt b/docs_build/dev/reports/codex_changed_files.txt index 9dca38cd8..15aa8521d 100644 --- a/docs_build/dev/reports/codex_changed_files.txt +++ b/docs_build/dev/reports/codex_changed_files.txt @@ -1,23 +1,6 @@ -.env.example -admin/infrastructure.html -admin/system-health.html -assets/theme-v2/js/admin-infrastructure.js -assets/theme-v2/js/admin-system-health.js -docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard.md -docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard_PLAN.md -docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-instruction-compliance-checklist.md -docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-manual-validation-notes.md -docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization.md -docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization_PLAN.md -docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization-instruction-compliance-checklist.md -docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization-manual-validation-notes.md -docs_build/dev/reports/PR_26175_CHARLIE_EOD-branch-validation.md -docs_build/dev/reports/PR_26175_CHARLIE_EOD-closeout.md -docs_build/dev/reports/PR_26175_CHARLIE_EOD-merge-summary.md -scripts/validate-storage-config.mjs -src/dev-runtime/server/local-api-router.mjs -src/dev-runtime/storage/storage-config.mjs -tests/dev-runtime/AdminHealthOperations.test.mjs -tests/dev-runtime/StorageConfig.test.mjs -tests/playwright/tools/AdminHealthOperationsPage.spec.mjs -tests/playwright/tools/AdminPlatformToolsWireframes.spec.mjs +docs_build/dev/BUILD_PR.md +docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md +docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md +docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md +docs_build/dev/reports/codex_review.diff +docs_build/dev/reports/codex_changed_files.txt diff --git a/docs_build/dev/reports/codex_review.diff b/docs_build/dev/reports/codex_review.diff index b57c0ef6b..a180fc02c 100644 --- a/docs_build/dev/reports/codex_review.diff +++ b/docs_build/dev/reports/codex_review.diff @@ -1,1428 +1 @@ -diff --git a/.env.example b/.env.example -index f293b6f83..9d5e4301b 100644 ---- a/.env.example -+++ b/.env.example -@@ -50,6 +50,11 @@ GAMEFOUNDRY_DB_BACKUP_DIR= - - # Server-only project asset storage configuration. - # Browser uploads must go through the server API and must not receive these secrets. -+# Approved GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX values: -+# DEV /dev/projects/ -+# IST /ist/projects/ -+# UAT /uat/projects/ -+# PRD /prod/projects/ - GAMEFOUNDRY_STORAGE_ENDPOINT= - GAMEFOUNDRY_STORAGE_ACCESS_KEY_ID= - -diff --git a/admin/infrastructure.html b/admin/infrastructure.html -index 0c9e90b3e..89bf99e0d 100644 ---- a/admin/infrastructure.html -+++ b/admin/infrastructure.html -@@ -41,7 +41,7 @@ -

/dev/projects/

-

/ist/projects/

-

/uat/projects/

--

/prd/projects/

-+

/prod/projects/

- - - -@@ -81,7 +81,7 @@ - DEV/dev/projects/Loading - IST/ist/projects/Loading - UAT/uat/projects/Loading -- PRD/prd/projects/Loading -+ PRD/prod/projects/Loading - - - -diff --git a/admin/system-health.html b/admin/system-health.html -index f5330bcdd..65ff3c12e 100644 ---- a/admin/system-health.html -+++ b/admin/system-health.html -@@ -39,6 +39,7 @@ - Health Sections -
-

Environment Summary

-+

Local API Startup

-

Database Health

-

Storage Health

-

Runtime Environment

-@@ -74,6 +75,21 @@ - - -
-+
-+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+
Local API Startup Diagnostics
FieldSafe ValueStatus
Startup diagnosticsWaiting for safe API statusPENDING
-+
-
- - -diff --git a/assets/theme-v2/js/admin-infrastructure.js b/assets/theme-v2/js/admin-infrastructure.js -index 0251c32d6..b470c84df 100644 ---- a/assets/theme-v2/js/admin-infrastructure.js -+++ b/assets/theme-v2/js/admin-infrastructure.js -@@ -6,7 +6,7 @@ const STORAGE_PATH_LANES = Object.freeze([ - Object.freeze({ lane: "DEV", path: "/dev/projects/" }), - Object.freeze({ lane: "IST", path: "/ist/projects/" }), - Object.freeze({ lane: "UAT", path: "/uat/projects/" }), -- Object.freeze({ lane: "PRD", path: "/prd/projects/" }), -+ Object.freeze({ lane: "PRD", path: "/prod/projects/" }), - ]); - - class AdminInfrastructureStoragePathStatus { -diff --git a/assets/theme-v2/js/admin-system-health.js b/assets/theme-v2/js/admin-system-health.js -index 09e7a3bb3..72ddd7ea8 100644 ---- a/assets/theme-v2/js/admin-system-health.js -+++ b/assets/theme-v2/js/admin-system-health.js -@@ -38,6 +38,7 @@ class AdminSystemHealthController { - node.dataset.adminSystemHealthStorageStatus, - node, - ])); -+ this.startupRows = root.querySelector("[data-admin-system-health-startup-rows]"); - this.runtimeRows = root.querySelector("[data-admin-system-health-runtime-rows]"); - } - -@@ -80,6 +81,7 @@ class AdminSystemHealthController { - ["host", "database", "migration", "connection"].forEach((key) => { - this.setStatus(key, "PENDING", reason); - }); -+ this.renderStartupPending(reason); - this.renderStoragePending(reason); - } - -@@ -118,6 +120,45 @@ class AdminSystemHealthController { - this.setStorageStatus("bucket", storageStatus.bucketStatus || storageStatus.status, reason); - } - -+ renderStartupPending(reason) { -+ if (!this.startupRows) { -+ return; -+ } -+ const row = document.createElement("tr"); -+ row.append( -+ this.createCell("Local API startup diagnostics"), -+ this.createCell("not available"), -+ this.createStatusCell("PENDING", reason), -+ ); -+ this.startupRows.replaceChildren(row); -+ } -+ -+ renderStartupDiagnostics(localApiStartup = {}) { -+ if (!this.startupRows) { -+ return; -+ } -+ if (localApiStartup?.secretsExposed === true || localApiStartup?.secretEditingAllowed === true) { -+ this.renderStartupPending("Safe Local API startup diagnostics were blocked because the response exposed secret controls."); -+ return; -+ } -+ const rows = Array.isArray(localApiStartup.rows) ? localApiStartup.rows : []; -+ if (!rows.length) { -+ this.renderStartupPending("Safe Local API startup diagnostics returned no rows."); -+ return; -+ } -+ const fragment = document.createDocumentFragment(); -+ rows.forEach((startupRow) => { -+ const row = document.createElement("tr"); -+ row.append( -+ this.createCell(startupRow.field), -+ this.createCell(startupRow.value), -+ this.createStatusCell(startupRow.status, startupRow.reason || localApiStartup.message), -+ ); -+ fragment.append(row); -+ }); -+ this.startupRows.replaceChildren(fragment); -+ } -+ - storageResultTarget(result = {}) { - if (typeof result.keysListed === "number" && result.actionId === "storage-list") { - return `${result.keysListed} object(s) under ${asText(result.projectsPrefix, "configured prefix")}`; -@@ -210,6 +251,7 @@ class AdminSystemHealthController { - return; - } - this.renderPostgresStatus(data?.databaseStatus || {}); -+ this.renderStartupDiagnostics(data?.localApiStartup || {}); - this.renderStorageStatus(data?.storageStatus || {}); - this.runStorageDiagnostics(); - this.renderRuntimeEnvironment(data?.runtimeEnvironment || {}); -diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-instruction-compliance-checklist.md b/docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-instruction-compliance-checklist.md -new file mode 100644 -index 000000000..977f218b5 ---- /dev/null -+++ b/docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-instruction-compliance-checklist.md -@@ -0,0 +1,20 @@ -+# PR_26175_CHARLIE_002 Instruction Compliance Checklist -+ -+| Requirement | Status | Evidence | -+|---|---:|---| -+| Read active ProjectInstructions | PASS | Reviewed README, root Project Instructions, team ownership, and PLAN report. | -+| Active branch remains Charlie stack branch | PASS | Branch is `PR_26172_CHARLIE_repository-compliance-stack`. | -+| Worktree clean before implementation | PASS | Start gate showed clean worktree. | -+| Implement only approved System Health dashboard scope | PASS | Changes are limited to System Health page/controller/API status payload and targeted tests. | -+| Preserve existing Postgres behavior | PASS | Database Health rendering and payload remain in place. | -+| Preserve existing R2 behavior | PASS | Storage Health and connectivity action behavior remain in place. | -+| Preserve Runtime Environment behavior | PASS | Runtime environment rows continue to mask secret-like values. | -+| Preserve Limits behavior | PASS | Limits/capacity table and payload remain in place. | -+| Preserve Diagnostics Plan and Diagnostics Log behavior | PASS | Existing tables remain in the page. | -+| Use PASS/WARN/FAIL/PENDING correctly | PASS | Deferred configurable multiple runtime ports are `PENDING`; real status rows use `PASS`/`WARN`. | -+| Every non-PASS status has reason text | PASS | Startup rendering uses existing `applyStatusNode()` helper with reason text. | -+| Do not expose secrets | PASS | URL credentials are redacted; tests assert raw credentials are absent. | -+| Do not implement telemetry | PASS | No telemetry code or route added. | -+| Do not implement configurable runtime ports | PASS | Multiple runtime ports are only marked deferred/cancelled. | -+| Required reports created | PASS | PR report, manual notes, checklist, Codex diff, and changed-files report created. | -+| Repo-structured ZIP under `tmp/` | PASS | `tmp/PR_26175_CHARLIE_002-system-health-dashboard_delta.zip`. | -diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-manual-validation-notes.md b/docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-manual-validation-notes.md -new file mode 100644 -index 000000000..6ea7cafe8 ---- /dev/null -+++ b/docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-manual-validation-notes.md -@@ -0,0 +1,29 @@ -+# PR_26175_CHARLIE_002 Manual Validation Notes -+ -+## Manual Review -+ -+- Confirmed active branch was `PR_26172_CHARLIE_repository-compliance-stack`. -+- Confirmed implementation stayed within Admin System Health dashboard and Local API status payload. -+- Confirmed no Team Bravo branch changes were made. -+- Confirmed no telemetry implementation was added. -+- Confirmed configurable multiple runtime ports are reported as `PENDING` / `deferred/cancelled` only. -+- Confirmed Postgres, R2, Runtime Environment, Limits, Diagnostics Plan, and Diagnostics Log sections remain present. -+ -+## Secret Exposure Review -+ -+- Local API startup diagnostic URL display removes username/password credentials. -+- Runtime secret masking behavior remains unchanged. -+- Targeted API test checks raw API URL and site URL credentials are not serialized in the `localApiStartup` payload. -+- Targeted Playwright test checks System Health page does not expose test secret values. -+ -+## Validation Results -+ -+- `git diff --check`: PASS. -+- `node --test tests/dev-runtime/LocalApiStartupLogging.test.mjs`: PASS. -+- `node --test tests/dev-runtime/AdminHealthOperations.test.mjs`: PASS. -+- `npx playwright test tests/playwright/tools/AdminHealthOperationsPage.spec.mjs`: PASS. -+ -+## Notes -+ -+- Playwright refreshed coverage report artifacts during validation; those generated changes were restored because they are outside this PR's required report set. -+- No samples were run. -diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard.md b/docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard.md -new file mode 100644 -index 000000000..3cd56805f ---- /dev/null -+++ b/docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard.md -@@ -0,0 +1,88 @@ -+# PR_26175_CHARLIE_002-system-health-dashboard -+ -+## Summary -+ -+Implemented the approved System Health dashboard increment for safe Local API startup diagnostics. -+ -+The dashboard now surfaces a server-owned Local API Startup Diagnostics table that reports: -+ -+- approved startup diagnostics format availability -+- Environment Variables section masking/redaction behavior -+- configured startup bind target -+- configured site URL status -+- configured or derived API URL -+- configured API URL port -+- configurable multiple runtime ports as `PENDING` and `deferred/cancelled` -+ -+The implementation preserves existing Postgres, R2, Runtime Environment, Limits, Diagnostics Plan, and Diagnostics Log behavior. -+ -+## Scope Controls -+ -+| Requirement | Result | Notes | -+|---|---:|---| -+| Active branch remains `PR_26172_CHARLIE_repository-compliance-stack` | PASS | Work stayed on the Charlie stack branch. | -+| Implement only approved System Health dashboard scope | PASS | Changes are limited to Admin System Health dashboard/API status and targeted tests. | -+| Preserve existing Postgres behavior | PASS | Existing database status rendering and server payload remain intact. | -+| Preserve existing R2 behavior | PASS | Existing storage status and connectivity action behavior remain intact. | -+| Preserve Runtime Environment behavior | PASS | Existing runtime environment masking/rendering remains intact. | -+| Preserve Limits behavior | PASS | Existing limits/capacity rows and usage placeholders remain intact. | -+| Preserve Diagnostics Plan and Diagnostics Log behavior | PASS | Existing tables remain; only Local API startup diagnostics table was added. | -+| Use PASS/WARN/FAIL/PENDING correctly | PASS | Real known-good checks are `PASS`; missing configured site URL is `WARN`; deferred multiple runtime ports is `PENDING`. | -+| Do not expose secrets | PASS | URL credentials are redacted, secret values are not returned, and tests assert no raw credentials appear. | -+| Do not implement telemetry | PASS | No telemetry collection, storage, route, or metric implementation was added. | -+| Do not implement configurable runtime ports | PASS | Multiple runtime ports are explicitly reported as `PENDING` / `deferred/cancelled`. | -+ -+## Files Changed -+ -+- `admin/system-health.html` -+- `assets/theme-v2/js/admin-system-health.js` -+- `src/dev-runtime/server/local-api-router.mjs` -+- `tests/dev-runtime/AdminHealthOperations.test.mjs` -+- `tests/playwright/tools/AdminHealthOperationsPage.spec.mjs` -+- `docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard.md` -+- `docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-manual-validation-notes.md` -+- `docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-instruction-compliance-checklist.md` -+- `docs_build/dev/reports/codex_review.diff` -+- `docs_build/dev/reports/codex_changed_files.txt` -+ -+## Implementation Notes -+ -+- Added `systemHealthLocalApiStartupDiagnostics()` in the Local API router so the browser receives structured, sanitized diagnostics instead of parsing startup console output. -+- Added a `localApiStartup` payload to `/api/admin/system-health/status`. -+- Added Local API Startup Diagnostics table markup to `admin/system-health.html`. -+- Extended `assets/theme-v2/js/admin-system-health.js` to render startup diagnostic rows using the existing shared status helpers. -+- Added API-level tests for local startup diagnostics rows, deferred runtime ports, and URL credential redaction. -+- Added Playwright coverage for the new dashboard table and static markup. -+ -+## Validation Lane Report -+ -+| Command | Result | -+|---|---:| -+| `git diff --check` | PASS | -+| `node --test tests/dev-runtime/LocalApiStartupLogging.test.mjs` | PASS, 2 tests | -+| `node --test tests/dev-runtime/AdminHealthOperations.test.mjs` | PASS, 4 tests | -+| `npx playwright test tests/playwright/tools/AdminHealthOperationsPage.spec.mjs` | PASS, 3 tests | -+ -+## Skipped Lanes -+ -+- Full samples smoke: skipped; the scope is Admin System Health dashboard diagnostics only. -+- Broad Playwright suite: skipped; targeted System Health coverage passed. -+- Telemetry validation: skipped; telemetry was explicitly out of scope and not implemented. -+- Configurable runtime port validation: skipped; configurable multiple runtime ports were explicitly deferred/cancelled and not implemented. -+ -+## Dependency Notes -+ -+The current branch already contains the approved Local API startup diagnostics formatter shape: -+ -+- deterministic `Environment Variables` section -+- deterministic `All Runtime Ports being used by Service` section -+- secret-like value masking -+- URL credential redaction -+ -+Validation confirmed the startup formatter remains intact through `tests/dev-runtime/LocalApiStartupLogging.test.mjs`. -+ -+## ZIP Artifact -+ -+Repo-structured delta ZIP: -+ -+- `tmp/PR_26175_CHARLIE_002-system-health-dashboard_delta.zip` -diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard_PLAN.md b/docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard_PLAN.md -new file mode 100644 -index 000000000..b486a097b ---- /dev/null -+++ b/docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard_PLAN.md -@@ -0,0 +1,163 @@ -+# PLAN_PR: PR_26175_CHARLIE_002-system-health-dashboard -+ -+Team: Charlie -+ -+Purpose: Plan a scoped System Health dashboard increment that builds on the Local API startup diagnostics lane without implementing configurable multiple runtime ports or unrelated telemetry/governance work. -+ -+## Branch and Context Validation -+ -+| Check | Expected | Actual | Status | -+|---|---|---|---| -+| Starting branch before switch | `pr/26172-BRAVO-text2speech-messages-inventory` | `pr/26172-BRAVO-text2speech-messages-inventory` | PASS | -+| Bravo worktree clean before switch | no output from `git status --short` | clean | PASS | -+| Bravo branch merged | not merged | not merged | PASS | -+| Bravo branch modified | no | no | PASS | -+| Charlie branch resolved | existing Team Charlie branch | `PR_26172_CHARLIE_repository-compliance-stack` | PASS | -+| Charlie branch synced | local equals remote | `0 0` against `origin/PR_26172_CHARLIE_repository-compliance-stack` | PASS | -+| Active team | Team Charlie | Team Charlie | PASS | -+| Active assignment | PLAN_PR for System Health dashboard | `PR_26175_CHARLIE_002-system-health-dashboard` | PASS | -+ -+## Dependency Gate -+ -+This PR depends on: -+ -+- `PR_26175_CHARLIE_001-local-api-startup-diagnostics` -+ -+Start gate for APPLY/build: -+ -+- PASS only when PR_001 is merged or the approved stack branch includes its committed startup diagnostics work. -+- PASS only when the Local API startup output matches the approved diagnostics format. -+- FAIL if PR_001 is absent, unmerged, or if startup diagnostics output is still ambiguous. -+ -+## Scope -+ -+Plan only for a System Health dashboard increment. -+ -+Allowed implementation scope for the later APPLY/build: -+ -+- Use existing Admin System Health page and safe API client patterns. -+- Surface Local API startup diagnostics inside the System Health dashboard only if PR_001 provides a safe structured contract or stable parseable output. -+- Keep dashboard data server-owned and browser-safe. -+- Preserve existing Theme V2 Admin System Health layout. -+- Preserve existing Postgres, R2, runtime environment, limits/capacity, diagnostics plan, and diagnostics log sections unless a narrowly scoped dashboard row/section addition is required. -+- Use PASS/WARN/FAIL indicators only when backed by real diagnostics. -+- Use PENDING or equivalent non-failure status for intentionally unwired dashboard items. -+- Provide hover/title or accessible reason text for every non-PASS status. -+- Do not expose secrets, raw connection strings, access keys, tokens, service role values, or database credentials. -+ -+Out of scope: -+ -+- Configurable multiple runtime ports implementation. -+- New telemetry foundation. -+- In-use delete governance. -+- New persistence. -+- New database schema. -+- New R2 write behavior beyond existing safe connectivity actions. -+- Runtime feature work outside Admin/System Health. -+- Any changes to Team Bravo branch or reports. -+ -+Deferred/cancelled carry-forward: -+ -+- Configurable multiple runtime ports remains cancelled/deferred for this System Health dashboard PR. -+- `PR_26175_CHARLIE_004-telemetry-foundation` remains deferred. -+- `PR_26175_CHARLIE_005-in-use-delete-governance-rule` remains future governance. -+ -+## Current Relevant Implementation Inventory -+ -+Existing files to review during APPLY/build: -+ -+- `admin/system-health.html` -+- `assets/theme-v2/js/admin-system-health.js` -+- `src/api/admin-system-health-api-client.js` -+- `src/dev-runtime/server/local-api-router.mjs` -+- `scripts/start-local-api-server.mjs` -+- `tests/playwright/tools/AdminHealthOperationsPage.spec.mjs` -+- `tests/playwright/tools/AdminPlatformToolsWireframes.spec.mjs` -+- `tests/dev-runtime/AdminHealthOperations.test.mjs` -+- `tests/dev-runtime/LocalApiStartupLogging.test.mjs` -+ -+Existing System Health route/API surface: -+ -+- Browser client calls `/api/admin/system-health/status`. -+- Browser client calls `/api/admin/system-health/storage-connectivity-action`. -+- Local API router already returns `databaseStatus`, `storageStatus`, `runtimeEnvironment`, `limitsStatus`, `operationsHealth`, `overview`, and `summary`. -+- Admin System Health page already renders Postgres-only database diagnostics, R2 diagnostics, runtime environment rows, limits/capacity, diagnostics plan, and diagnostics log. -+ -+Existing validation evidence: -+ -+- `tests/playwright/tools/AdminHealthOperationsPage.spec.mjs` covers safe System Health rendering, Postgres diagnostics, R2 diagnostics, runtime key masking, admin-only access, and no inline scripts/styles. -+- `tests/dev-runtime/AdminHealthOperations.test.mjs` covers `/api/admin/system-health/status` admin access and blocks Creator sessions. -+- `docs_build/dev/reports/PR_26171_018-local-api-startup-diagnostics.md` documents an older startup diagnostics shape, including environment variable output and runtime port listing. -+- `docs_build/dev/reports/PR_26169_026-local-api-startup-url-logging.md` documents earlier Local API startup URL logging behavior. -+ -+## Proposed APPLY/Build Steps -+ -+1. Start from the approved Charlie branch or the owner-approved stack branch containing PR_001. -+2. Verify dependency: -+ - confirm PR_001 commit/report exists in the branch or mainline dependency chain; -+ - run the startup diagnostics unit test; -+ - confirm approved startup output format. -+3. Inspect `scripts/start-local-api-server.mjs` and the PR_001 startup diagnostics contract. -+4. Add a System Health dashboard row/section for Local API startup diagnostics only if the data source is safe and stable. -+5. If PR_001 exposes only console text, prefer a server-owned helper in `src/dev-runtime/server/local-api-router.mjs` that returns sanitized startup diagnostic metadata rather than browser-parsing console output. -+6. Extend `src/api/admin-system-health-api-client.js` only if a new API route is needed; otherwise reuse `/admin/system-health/status`. -+7. Extend `assets/theme-v2/js/admin-system-health.js` to render any new dashboard data with existing status helper functions. -+8. Update `admin/system-health.html` only for scoped dashboard placeholders/rows required by the new diagnostics. -+9. Update targeted tests only. -+10. Produce reports and delta ZIP. -+ -+## Approved Diagnostics Format Expectation -+ -+The later APPLY/build must verify PR_001 startup output before changing dashboard behavior. Expected properties: -+ -+- Environment variables are listed in a deterministic section. -+- Secret-like values are masked. -+- URL credentials are redacted. -+- Runtime URL/API URL/database/storage information is shown only as safe diagnostics. -+- Configurable multiple runtime ports are not implemented in this PR. -+- Cancelled/deferred multiple-port work is documented rather than built. -+ -+## Status Model -+ -+Use existing status model: -+ -+- `PASS`: known good, backed by real diagnostic evidence. -+- `WARN`: actionable partial/missing configuration, not a placeholder. -+- `FAIL`: actual failed diagnostic or blocked required behavior. -+- `PENDING`: intentional future wiring or dependency not active yet. -+ -+Every non-PASS status must include title or accessible reason text. -+ -+## Validation Plan -+ -+Required targeted validation for APPLY/build: -+ -+- `git diff --check` -+- `node --test tests/dev-runtime/LocalApiStartupLogging.test.mjs` -+- `node --test tests/dev-runtime/AdminHealthOperations.test.mjs` -+- `npx playwright test tests/playwright/tools/AdminHealthOperationsPage.spec.mjs` -+- Targeted browser/static validation for no secret exposure: -+ - no raw `DATABASE_URL`; -+ - no `PASSWORD`, `SECRET`, `TOKEN`, `KEY`, `SERVICE_ROLE`, or `JWT` values exposed; -+ - no inline scripts/styles introduced. -+ -+Skipped lanes: -+ -+- Full samples smoke: skipped because the scope is Admin System Health dashboard diagnostics only. -+- Broad Playwright: skipped unless targeted Admin/System Health tests require support coverage. -+- Runtime feature tests outside System Health: skipped as out of scope. -+ -+## Required Reports for APPLY/Build -+ -+- `docs_build/dev/reports/codex_review.diff` -+- `docs_build/dev/reports/codex_changed_files.txt` -+- `docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard.md` -+- `docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-manual-validation-notes.md` -+- `docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-instruction-compliance-checklist.md` -+- repo-structured delta ZIP under `tmp/` -+ -+## PLAN_PR Result -+ -+PLAN status: PASS. -+ -+Recommendation: Continue to APPLY only after `PR_26175_CHARLIE_001-local-api-startup-diagnostics` is present in the approved dependency chain and its startup output format has been validated. -diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization-instruction-compliance-checklist.md b/docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization-instruction-compliance-checklist.md -new file mode 100644 -index 000000000..00ec50d7c ---- /dev/null -+++ b/docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization-instruction-compliance-checklist.md -@@ -0,0 +1,22 @@ -+# PR_26175_CHARLIE_003 Instruction Compliance Checklist -+ -+| Requirement | Status | Evidence | -+|---|---:|---| -+| Active branch remains `PR_26172_CHARLIE_repository-compliance-stack` | PASS | Branch gate returned `PR_26172_CHARLIE_repository-compliance-stack`. | -+| Worktree clean before BUILD | PASS | `git status --short` returned no output before edits. | -+| Local/origin sync before BUILD is `0 0` | PASS | Sync check returned `0 0`. | -+| Scope only R2 storage configuration standardization | PASS | Changes are limited to prefix config, safe status surfaces, validation, tests, and reports. | -+| Standardize around `GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX` | PASS | Shared approved prefix list added in `storage-config.mjs`. | -+| Allow `/dev/projects/` | PASS | Included in `STORAGE_PROJECTS_ALLOWED_PREFIXES`; covered by tests/status surfaces. | -+| Allow `/ist/projects/` | PASS | Included in `STORAGE_PROJECTS_ALLOWED_PREFIXES`; covered by tests/status surfaces. | -+| Allow `/uat/projects/` | PASS | Included in `STORAGE_PROJECTS_ALLOWED_PREFIXES`; covered by tests/status surfaces. | -+| Allow `/prod/projects/` | PASS | Included in `STORAGE_PROJECTS_ALLOWED_PREFIXES`; PRD lane references updated to `/prod/projects/`. | -+| Reject unapproved project prefixes | PASS | New storage-config test rejects `/production/projects/`, `/qa/projects/`, and `/projects/`. | -+| Preserve R2 list/read/write/delete behavior | PASS | Connectivity action code paths were not changed; storage validation list/readiness passed with `--use-system-ca`. | -+| Preserve System Health and Infrastructure safe status surfaces | PASS | Targeted Admin Health Operations and Infrastructure Playwright validations passed. | -+| Do not expose secrets | PASS | Safe config excludes access and secret keys; validation output did not print credential values. | -+| Do not implement telemetry | PASS | No telemetry implementation was added. | -+| Do not implement configurable runtime ports | PASS | Runtime port code was not changed. | -+| Do not edit ignored local `.env` files | PASS | Only `.env.example` was updated. | -+| Required reports under `docs_build/dev/reports/` | PASS | PR report, manual notes, checklist, codex diff, and changed-files reports are produced. | -+| Repo-structured ZIP under `tmp/` | PASS | ZIP produced as `tmp/PR_26175_CHARLIE_003-r2-storage-standardization_delta.zip`. | -diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization-manual-validation-notes.md b/docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization-manual-validation-notes.md -new file mode 100644 -index 000000000..8a14de4ca ---- /dev/null -+++ b/docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization-manual-validation-notes.md -@@ -0,0 +1,34 @@ -+# PR_26175_CHARLIE_003 Manual Validation Notes -+ -+## Manual Checks Completed During BUILD -+ -+- Confirmed active branch remained `PR_26172_CHARLIE_repository-compliance-stack`. -+- Confirmed worktree was clean before BUILD edits. -+- Confirmed branch local/origin sync was `0 0` before BUILD edits. -+- Reviewed ProjectInstructions and approved PLAN report. -+- Reviewed exact target files for R2 storage config, Local API status surface, Admin Infrastructure, storage validation, and targeted tests. -+ -+## Behavioral Notes -+ -+- `GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX` now accepts only normalized project prefixes in the approved lane list. -+- PRD lane display now uses `/prod/projects/`. -+- Invalid project prefixes return a safe validation error that names approved values and does not expose credentials. -+- R2 list/read/write/delete code paths were not changed. -+- System Health and Infrastructure status surfaces continue to hide storage credentials. -+ -+## Validation Notes -+ -+- `git diff --check` passed. -+- `node --test tests/dev-runtime/StorageConfig.test.mjs` passed. -+- `node --test tests/dev-runtime/AdminHealthOperations.test.mjs` passed. -+- Targeted Admin Infrastructure Playwright storage path tests passed. -+- Targeted Admin System Health Playwright route tests passed. -+- `node scripts/validate-storage-config.mjs` failed on local certificate trust before a code failure was observed. -+- `node --use-system-ca scripts/validate-storage-config.mjs` passed and confirmed R2 list/readiness for `/dev/projects/`. -+ -+## Skipped Validation -+ -+- Full samples smoke was skipped because the approved scope was storage prefix standardization only. -+- Broad Playwright was skipped because targeted Admin status validations passed. -+- Telemetry validation was skipped because telemetry is out of scope. -+- Configurable runtime port validation was skipped because runtime ports are out of scope. -diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization.md b/docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization.md -new file mode 100644 -index 000000000..2aa5109c2 ---- /dev/null -+++ b/docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization.md -@@ -0,0 +1,82 @@ -+# PR_26175_CHARLIE_003-r2-storage-standardization -+ -+Team: Charlie -+ -+Purpose: Standardize R2 project asset storage around `GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX` and the approved project prefix set. -+ -+## Branch Validation -+ -+| Check | Expected | Actual | Status | -+|---|---|---|---| -+| Active branch | `PR_26172_CHARLIE_repository-compliance-stack` | `PR_26172_CHARLIE_repository-compliance-stack` | PASS | -+| Worktree before BUILD | clean | clean | PASS | -+| Local/origin sync before BUILD | `0 0` | `0 0` | PASS | -+| Team ownership | Charlie storage/infrastructure | R2 storage configuration standardization | PASS | -+ -+## Implementation Summary -+ -+- Added `STORAGE_PROJECTS_PREFIX_LANES` and `STORAGE_PROJECTS_ALLOWED_PREFIXES` as the shared approved project prefix contract. -+- Restricted `loadStorageConfig()` to normalized prefixes matching: -+ - `/dev/projects/` -+ - `/ist/projects/` -+ - `/uat/projects/` -+ - `/prod/projects/` -+- Updated Admin Infrastructure and Local API storage path status to use `/prod/projects/` for the PRD lane. -+- Kept R2 list/read/write/delete behavior unchanged and still routed through the configured project prefix. -+- Updated `.env.example` comments and `scripts/validate-storage-config.mjs` safe output to name approved prefixes. -+- Added focused `node:test` coverage for prefix normalization, allow-list validation, missing prefix handling, and safe config secret masking. -+ -+## Files Changed -+ -+- `.env.example` -+- `admin/infrastructure.html` -+- `assets/theme-v2/js/admin-infrastructure.js` -+- `scripts/validate-storage-config.mjs` -+- `src/dev-runtime/server/local-api-router.mjs` -+- `src/dev-runtime/storage/storage-config.mjs` -+- `tests/dev-runtime/StorageConfig.test.mjs` -+- `tests/playwright/tools/AdminPlatformToolsWireframes.spec.mjs` -+ -+## Scope Guardrails -+ -+| Requirement | Status | Notes | -+|---|---:|---| -+| Preserve R2 list/read/write/delete behavior | PASS | Connectivity action code paths were not changed. | -+| Preserve System Health safe status surface | PASS | Existing Admin Health Operations test and page spec passed. | -+| Preserve Infrastructure safe status surface | PASS | Storage path status rows now use the shared approved prefix list. | -+| Do not expose secrets | PASS | Safe config excludes access key and secret key values; validation output printed no secret values. | -+| Do not implement telemetry | PASS | No telemetry code was added. | -+| Do not implement configurable runtime ports | PASS | Runtime port logic was not changed. | -+| Do not edit local ignored `.env` files | PASS | Only `.env.example` was updated. | -+ -+## Validation Lane Report -+ -+| Command | Result | -+|---|---:| -+| `git diff --check` | PASS | -+| `node --test tests/dev-runtime/StorageConfig.test.mjs` | PASS, 5 tests | -+| `node --test tests/dev-runtime/AdminHealthOperations.test.mjs` | PASS, 4 tests | -+| `npx playwright test tests/playwright/tools/AdminPlatformToolsWireframes.spec.mjs --grep "Infrastructure storage path status"` | PASS, 4 tests | -+| `npx playwright test tests/playwright/tools/AdminHealthOperationsPage.spec.mjs` | PASS, 3 tests | -+| `node scripts/validate-storage-config.mjs` | FAIL due local Node certificate trust error before code changes were needed | -+| `node --use-system-ca scripts/validate-storage-config.mjs` | PASS; R2 list/readiness succeeded for `/dev/projects/` with 0 objects | -+ -+## Validation Notes -+ -+- The first `validate-storage-config` run loaded `.env`, confirmed all storage keys were present, and printed only safe endpoint, bucket, and prefix values. It failed on `UNABLE_TO_VERIFY_LEAF_SIGNATURE`. -+- The rerun with `--use-system-ca` passed and confirmed the R2 list/readiness behavior under the approved `/dev/projects/` prefix. -+- Active code, config, Admin UI, and targeted tests no longer use `/prd/projects/`. -+- Historical report references to `/prd/projects/` were left untouched as report history. -+ -+## Skipped Lanes -+ -+- Full samples smoke: skipped; out of scope for R2 prefix standardization. -+- Broad Playwright: skipped; targeted Admin Infrastructure and System Health specs passed. -+- Telemetry validation: skipped; telemetry is explicitly out of scope. -+- Configurable runtime port validation: skipped; runtime ports are explicitly out of scope. -+ -+## BUILD Result -+ -+BUILD status: PASS. -+ -+Recommendation: Keep this commit on the Charlie stack for owner review. -diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization_PLAN.md b/docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization_PLAN.md -new file mode 100644 -index 000000000..08cbb72cd ---- /dev/null -+++ b/docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization_PLAN.md -@@ -0,0 +1,150 @@ -+# PLAN_PR: PR_26175_CHARLIE_003-r2-storage-standardization -+ -+Team: Charlie -+ -+Purpose: Plan a scoped R2 storage configuration standardization PR around `GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX` and the approved project storage prefixes. -+ -+## Branch and Context Validation -+ -+| Check | Expected | Actual | Status | -+|---|---|---|---| -+| Active branch | `PR_26172_CHARLIE_repository-compliance-stack` | `PR_26172_CHARLIE_repository-compliance-stack` | PASS | -+| Worktree before PLAN changes | clean | clean | PASS | -+| Local/origin sync before PLAN changes | `0 0` | `0 0` | PASS | -+| Active team | Team Charlie | Team Charlie | PASS | -+| Ownership scope | Infrastructure / Storage / System Health | R2 storage configuration standardization | PASS | -+ -+## Scope -+ -+Plan only for R2 storage configuration standardization. -+ -+Approved standard: -+ -+- Configuration variable: `GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX` -+- Allowed project storage prefixes: -+ - `/dev/projects/` -+ - `/ist/projects/` -+ - `/uat/projects/` -+ - `/prod/projects/` -+ -+Allowed APPLY/build scope: -+ -+- Standardize project asset storage config validation around the approved prefix set. -+- Keep R2 as the project asset storage provider direction. -+- Keep object keys server-owned and under the configured prefix. -+- Keep prefix normalization for slash and backslash cleanup, then validate against the approved prefix set. -+- Keep safe status surfaces in Admin Infrastructure and Admin System Health aligned with the same allowed prefix set. -+- Preserve existing R2 list/read/write/delete connectivity behavior. -+- Preserve existing Postgres, Runtime Environment, Limits, Diagnostics Plan, and Diagnostics Log behavior. -+- Preserve secret masking and never return access key or secret key values. -+ -+Explicitly out of scope: -+ -+- Telemetry implementation. -+- Configurable runtime ports. -+- New storage provider abstraction. -+- Live R2 credential changes. -+- New persistence tables or database schema. -+- Backup prefix changes beyond checking for conflicts with project storage prefix rules. -+- Editing local ignored `.env` files. -+- Samples smoke. -+ -+## Current Implementation Inventory -+ -+Exact target files reviewed: -+ -+- `src/dev-runtime/storage/storage-config.mjs` -+- `src/dev-runtime/storage/r2-project-asset-storage.mjs` -+- `src/dev-runtime/server/local-api-router.mjs` -+- `scripts/validate-storage-config.mjs` -+- `admin/infrastructure.html` -+- `assets/theme-v2/js/admin-infrastructure.js` -+- `admin/system-health.html` -+- `assets/theme-v2/js/admin-system-health.js` -+- `tests/playwright/tools/AdminPlatformToolsWireframes.spec.mjs` -+ -+Current findings: -+ -+- `storage-config.mjs` normalizes `GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX` but currently accepts any non-empty normalized prefix. -+- `local-api-router.mjs` already has `STORAGE_PROJECTS_PREFIX_LANES` with the four approved prefixes and reports invalid paths in Infrastructure/System Health status. -+- `admin/infrastructure.html` lists `/dev/projects/`, `/ist/projects/`, `/uat/projects/`, and `/prd/projects/`. -+- `assets/theme-v2/js/admin-infrastructure.js` mirrors those four paths client-side for fallback/error rows. -+- `AdminPlatformToolsWireframes.spec.mjs` has focused coverage for missing, invalid, DEV, and IST path status and includes the full four-prefix list. -+- `scripts/validate-storage-config.mjs` validates configured R2 connectivity but depends on `loadStorageConfig()` for prefix acceptance. -+- `.env.example` includes `GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX=` but does not currently enforce a value. -+- Tracked `.env.dev`, `.env.ist`, `.env.uat`, and `.env.prd` files were not present in this workspace when searched. Local ignored environment files must not be edited by this PR. -+ -+## Proposed APPLY/Build Steps -+ -+1. Add an exported approved project prefix list in `src/dev-runtime/storage/storage-config.mjs`, for example `STORAGE_PROJECTS_ALLOWED_PREFIXES`. -+2. Update `loadStorageConfig()` so `GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX` is normalized first, then accepted only when it matches one of: -+ - `/dev/projects/` -+ - `/ist/projects/` -+ - `/uat/projects/` -+ - `/prod/projects/` -+3. Return a safe validation error when the prefix is missing or outside the approved list. -+4. Update `src/dev-runtime/server/local-api-router.mjs` to reuse the storage-config approved prefix list where practical, or keep its lane metadata explicitly synchronized if importing would create an unwanted dependency. -+5. Update `scripts/validate-storage-config.mjs` output so invalid prefixes report the approved values without printing secrets. -+6. Update `.env.example` comments near `GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX` to document the approved values. Leave the value blank if templates should not default to a lane. -+7. Add or update targeted Node tests for `normalizeStorageProjectsPrefix()` and `loadStorageConfig()`: -+ - accepts slash variants that normalize to approved prefixes; -+ - rejects `/qa/projects/`; -+ - rejects generic `/projects/`; -+ - rejects empty values; -+ - never exposes access key or secret key values in safe config. -+8. Update targeted Admin/System Health validation only if the payload shape changes. -+9. Produce required reports and repo-structured ZIP. -+ -+## Status and Severity Rules -+ -+Use existing status model: -+ -+- `PASS`: configured prefix matches exactly one approved lane. -+- `WARN`: missing or incomplete storage configuration. -+- `FAIL`: malformed or unsafe storage configuration if the existing caller expects failure semantics. -+- `PENDING`: intentionally unwired future work only. -+ -+For this PR, invalid project prefixes should remain visible and actionable. The recommended server-facing status is `WARN` unless an existing route/test already treats invalid prefix as `ERROR` and preserving that behavior is safer. Browser-facing status must not expose secret values. -+ -+## Validation Plan -+ -+Required targeted validation for APPLY/build: -+ -+- `git diff --check` -+- `node --test tests/dev-runtime/StorageConfig.test.mjs` or equivalent new targeted storage-config test -+- `node --test tests/dev-runtime/AdminHealthOperations.test.mjs` -+- `npx playwright test tests/playwright/tools/AdminPlatformToolsWireframes.spec.mjs --grep "Infrastructure storage path status"` -+- `npx playwright test tests/playwright/tools/AdminHealthOperationsPage.spec.mjs` -+- `node scripts/validate-storage-config.mjs` only when `.env` is present and configured; otherwise document SKIP from script output. -+ -+Required static checks: -+ -+- Verify `GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX` appears in config/docs/status surfaces. -+- Verify approved prefixes appear: -+ - `/dev/projects/` -+ - `/ist/projects/` -+ - `/uat/projects/` -+ - `/prod/projects/` -+- Verify no raw R2 credentials are printed in reports, tests, or status payloads. -+ -+Skipped lanes: -+ -+- Full samples smoke: skipped because scope is R2 storage config standardization only. -+- Broad Playwright: skipped unless targeted Admin/System Health validation fails. -+- Telemetry validation: skipped because telemetry is explicitly out of scope. -+- Runtime-port validation: skipped because configurable runtime ports are explicitly out of scope. -+ -+## Required Reports for APPLY/Build -+ -+- `docs_build/dev/reports/codex_review.diff` -+- `docs_build/dev/reports/codex_changed_files.txt` -+- `docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization.md` -+- `docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization-manual-validation-notes.md` -+- `docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization-instruction-compliance-checklist.md` -+- repo-structured delta ZIP under `tmp/` -+ -+## PLAN_PR Result -+ -+PLAN status: PASS. -+ -+Recommendation: Proceed to BUILD/APPLY on the active Charlie stack branch if owner approves the scoped server-side prefix validation and targeted test additions. -diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_EOD-branch-validation.md b/docs_build/dev/reports/PR_26175_CHARLIE_EOD-branch-validation.md -new file mode 100644 -index 000000000..64dfdbb53 ---- /dev/null -+++ b/docs_build/dev/reports/PR_26175_CHARLIE_EOD-branch-validation.md -@@ -0,0 +1,35 @@ -+# PR_26175_CHARLIE EOD Branch Validation -+ -+## Context -+ -+| Check | Expected | Actual | Status | -+|---|---|---|---| -+| Current branch before EOD closeout | `PR_26172_CHARLIE_repository-compliance-stack` | `PR_26172_CHARLIE_repository-compliance-stack` | PASS | -+| Active team | Team Charlie | Team Charlie | PASS | -+| Worktree before committing PR_003 BUILD | clean | dirty with scoped PR_003 BUILD files | WARN | -+| Action for dirty worktree | commit scoped completed BUILD work | `a7e05a124 BUILD_PR PR_26175_CHARLIE_003 r2 storage standardization` | PASS | -+| Branch local/origin after PR_003 push | `0 0` | `0 0` | PASS | -+| Latest main fetched | `origin/main` current | `793cf755c Merge PR_26175_ALFA_005 game hub audit findings cleanup` | PASS | -+| Latest main reconciled into Charlie | required before main merge | `a401ac694 Merge latest main into Charlie compliance stack` | PASS | -+| Merge conflicts | resolved only in generated Codex report artifacts | `codex_changed_files.txt`, `codex_review.diff` regenerated during EOD | PASS | -+ -+## PR Review -+ -+| PR Scope | Evidence | Status | -+|---|---|---:| -+| `PR_26175_CHARLIE_001-local-api-startup-diagnostics` | No matching `PR_26175_CHARLIE_001` commit or report found in fetched refs or current branch. Earlier startup diagnostics evidence exists under `PR_26171_018-local-api-startup-diagnostics`. | REVIEW NOTE | -+| `PR_26175_CHARLIE_002-system-health-dashboard` | `446579503 PLAN_PR PR_26175_CHARLIE_002 system health dashboard`; `5de48d1f7 BUILD_PR PR_26175_CHARLIE_002 system health dashboard`; required reports present. | PASS | -+| `PR_26175_CHARLIE_003-r2-storage-standardization` | `a2c0dd1b1 PLAN_PR PR_26175_CHARLIE_003 r2 storage standardization`; `a7e05a124 BUILD_PR PR_26175_CHARLIE_003 r2 storage standardization`; required reports present. | PASS | -+ -+## Branch Status Before Main Merge -+ -+- Branch: `PR_26172_CHARLIE_repository-compliance-stack` -+- Worktree: clean before EOD report generation -+- Branch relative to `origin/main` after latest-main reconciliation: ahead with Charlie PR_002/PR_003 closeout commits -+- Branch relative to `origin/PR_26172_CHARLIE_repository-compliance-stack` before final EOD push: ahead due latest-main reconciliation and EOD reports -+ -+## Hard Stops -+ -+- PR_004 was not started. -+- PR_005 was not started. -+- No unrelated implementation work was added during EOD closeout. -diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_EOD-closeout.md b/docs_build/dev/reports/PR_26175_CHARLIE_EOD-closeout.md -new file mode 100644 -index 000000000..b93f2636f ---- /dev/null -+++ b/docs_build/dev/reports/PR_26175_CHARLIE_EOD-closeout.md -@@ -0,0 +1,47 @@ -+# PR_26175_CHARLIE EOD Closeout Report -+ -+## Summary -+ -+Team Charlie EOD closeout prepared the `PR_26172_CHARLIE_repository-compliance-stack` branch for merge into `main`. -+ -+## Completed Work Reviewed -+ -+- `PR_26175_CHARLIE_002-system-health-dashboard` -+- `PR_26175_CHARLIE_003-r2-storage-standardization` -+ -+Review note: -+ -+- `PR_26175_CHARLIE_001-local-api-startup-diagnostics` was requested for review, but no matching `PR_26175_CHARLIE_001` commit or report was found in current branch or fetched refs. Prior startup diagnostics material exists under `PR_26171_018-local-api-startup-diagnostics`. -+ -+## Validation Performed During Closeout -+ -+| Validation | Result | -+|---|---:| -+| Branch context check | PASS | -+| Worktree check after PR_003 commit | PASS | -+| Branch push after PR_003 commit | PASS | -+| Latest main fetch with `schannel` | PASS | -+| Merge latest `origin/main` into Charlie | PASS | -+| Conflict resolution | PASS, generated Codex artifacts only | -+| PR_004 not started | PASS | -+| PR_005 not started | PASS | -+ -+## EOD Artifact Set -+ -+- `docs_build/dev/reports/PR_26175_CHARLIE_EOD-branch-validation.md` -+- `docs_build/dev/reports/PR_26175_CHARLIE_EOD-merge-summary.md` -+- `docs_build/dev/reports/PR_26175_CHARLIE_EOD-closeout.md` -+- `docs_build/dev/reports/codex_review.diff` -+- `docs_build/dev/reports/codex_changed_files.txt` -+- `tmp/PR_26175_CHARLIE_EOD-closeout_delta.zip` -+ -+## Deferred / Not Started -+ -+- `PR_26175_CHARLIE_004-telemetry-foundation` -+- `PR_26175_CHARLIE_005-in-use-delete-governance-rule` -+ -+## Closeout Status -+ -+Status before final main merge: READY FOR EOD MERGE. -+ -+Final repository state is recorded after main checkout, pull, merge, push, and sync verification. -diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_EOD-merge-summary.md b/docs_build/dev/reports/PR_26175_CHARLIE_EOD-merge-summary.md -new file mode 100644 -index 000000000..83a8af35b ---- /dev/null -+++ b/docs_build/dev/reports/PR_26175_CHARLIE_EOD-merge-summary.md -@@ -0,0 +1,57 @@ -+# PR_26175_CHARLIE EOD Merge Summary -+ -+## Requested Action -+ -+EOD Team Charlie closeout for `PR_26172_CHARLIE_repository-compliance-stack`. -+ -+Owner instruction included: -+ -+- Verify Charlie branch clean and synced. -+- Review completed PRs 001, 002, and 003. -+- Merge Team Charlie branch into main following repository governance. -+- Push main. -+- Generate EOD reports and ZIP artifact. -+- Do not start PR_004 or PR_005. -+ -+## Reconciliation Summary -+ -+- Default `git fetch origin` failed because local OpenSSL certificate verification could not find the issuer certificate. -+- `git -c http.sslBackend=schannel fetch origin` succeeded. -+- `origin/main` advanced to `793cf755c Merge PR_26175_ALFA_005 game hub audit findings cleanup`. -+- Charlie branch was clean and synced after committing and pushing PR_003 BUILD work. -+- `origin/main` was merged into Charlie in `a401ac694 Merge latest main into Charlie compliance stack`. -+- Conflicts occurred only in generated Codex report artifacts and were resolved by regenerating closeout reports. -+ -+## Commits Reviewed -+ -+| Commit | Summary | -+|---|---| -+| `446579503` | PLAN_PR PR_26175_CHARLIE_002 system health dashboard | -+| `5de48d1f7` | BUILD_PR PR_26175_CHARLIE_002 system health dashboard | -+| `a2c0dd1b1` | PLAN_PR PR_26175_CHARLIE_003 r2 storage standardization | -+| `a7e05a124` | BUILD_PR PR_26175_CHARLIE_003 r2 storage standardization | -+| `a401ac694` | Merge latest main into Charlie compliance stack | -+ -+## Main Merge Plan -+ -+After this EOD report commit: -+ -+1. Push `PR_26172_CHARLIE_repository-compliance-stack`. -+2. Checkout `main`. -+3. Pull latest `origin/main`. -+4. Merge `PR_26172_CHARLIE_repository-compliance-stack` into `main`. -+5. Push `main`. -+6. Verify final branch is `main`. -+7. Verify worktree is clean. -+8. Verify local/origin sync is `0 0`. -+ -+## Final Main Merge Note -+ -+- Main advanced again to `8ac1bb1d2` before the final Charlie merge. -+- The final main merge had conflicts only in generated Codex report artifacts. -+- The final Codex report artifacts were regenerated from the merge index before committing the main merge. -+ -+## Notes -+ -+- The actual final main commit is recorded in the final Codex response after the merge/push step completes. -+- PR_004 and PR_005 were not started. -diff --git a/scripts/validate-storage-config.mjs b/scripts/validate-storage-config.mjs -index 032195b24..e84193ba9 100644 ---- a/scripts/validate-storage-config.mjs -+++ b/scripts/validate-storage-config.mjs -@@ -3,7 +3,11 @@ import fs from "node:fs"; - import path from "node:path"; - import process from "node:process"; - import { createConfiguredProjectAssetStorage } from "../src/dev-runtime/storage/r2-project-asset-storage.mjs"; --import { STORAGE_ENV_KEYS, loadStorageConfig } from "../src/dev-runtime/storage/storage-config.mjs"; -+import { -+ STORAGE_ENV_KEYS, -+ STORAGE_PROJECTS_ALLOWED_PREFIXES, -+ loadStorageConfig, -+} from "../src/dev-runtime/storage/storage-config.mjs"; - - const ENV_FILE = ".env"; - -@@ -64,6 +68,7 @@ console.log(`PASS - Storage env keys present=${presentKeys.length}/${STORAGE_ENV - - if (!config.configured) { - console.log(`SKIP - Storage DEV values are not fully configured in .env (${config.missingKeys?.join(", ") || config.validationError}).`); -+ console.log(`SKIP - Approved project storage prefixes: ${STORAGE_PROJECTS_ALLOWED_PREFIXES.join(", ")}.`); - process.exit(0); - } - -diff --git a/src/dev-runtime/server/local-api-router.mjs b/src/dev-runtime/server/local-api-router.mjs -index 577375844..1c6e9c126 100644 ---- a/src/dev-runtime/server/local-api-router.mjs -+++ b/src/dev-runtime/server/local-api-router.mjs -@@ -17,7 +17,11 @@ import { - createInputMappingToolMockRepository, - } from "../persistence/tool-repositories/input-mapping-mock-repository.js"; - import { createConfiguredBackupStorage, createConfiguredProjectAssetStorage } from "../storage/r2-project-asset-storage.mjs"; --import { loadStorageConfig } from "../storage/storage-config.mjs"; -+import { -+ STORAGE_PROJECTS_PREFIX_LANES, -+ loadStorageConfig, -+ normalizeStorageProjectsPrefix, -+} from "../storage/storage-config.mjs"; - import { createPostgresBackup } from "../database/postgres-backup-service.mjs"; - import { - GFSP_PACKAGE_REQUIRED_FILES, -@@ -311,6 +315,12 @@ const RUNTIME_ENV_SECRET_MARKERS = Object.freeze([ - "JWT", - "DATABASE_URL", - ]); -+const LOCAL_API_STARTUP_DEFAULT_HOST = "127.0.0.1"; -+const LOCAL_API_STARTUP_DEFAULT_PORT = "5501"; -+const LOCAL_API_STARTUP_DEFAULT_PORT_BY_PROTOCOL = Object.freeze({ -+ "http:": "80", -+ "https:": "443", -+}); - const SYSTEM_HEALTH_USAGE_NOT_AVAILABLE = "NOT AVAILABLE"; - const SYSTEM_HEALTH_USAGE_CONTRACTS = Object.freeze({ - GAMEFOUNDRY_DB_CONNECTION_LIMIT: Object.freeze({ -@@ -329,12 +339,6 @@ const SYSTEM_HEALTH_USAGE_CONTRACTS = Object.freeze({ - integrationPoint: "Future R2 provider telemetry can report project asset storage bytes used through the Local API.", - }), - }); --const STORAGE_PROJECTS_PREFIX_LANES = Object.freeze([ -- Object.freeze({ lane: "DEV", path: "/dev/projects/" }), -- Object.freeze({ lane: "IST", path: "/ist/projects/" }), -- Object.freeze({ lane: "UAT", path: "/uat/projects/" }), -- Object.freeze({ lane: "PRD", path: "/prd/projects/" }), --]); - const STORAGE_CONNECTIVITY_ACTIONS = Object.freeze([ - Object.freeze({ id: "storage-list", label: "List" }), - Object.freeze({ id: "storage-write-test-object", label: "Write test object" }), -@@ -497,8 +501,9 @@ function dotEnvValue(key) { - - function storageProjectsPrefixStatus() { - const currentPath = dotEnvValue(STORAGE_PROJECTS_PREFIX_ENV_KEY); -- const matchedLane = STORAGE_PROJECTS_PREFIX_LANES.find((lane) => lane.path === currentPath.value); -- const invalidPath = !currentPath.found || !currentPath.value || !matchedLane; -+ const normalizedPath = normalizeStorageProjectsPrefix(currentPath.value); -+ const matchedLane = STORAGE_PROJECTS_PREFIX_LANES.find((lane) => lane.path === normalizedPath); -+ const invalidPath = !currentPath.found || !normalizedPath || !matchedLane; - const rows = STORAGE_PROJECTS_PREFIX_LANES.map((lane) => { - if (invalidPath) { - return { -@@ -508,7 +513,7 @@ function storageProjectsPrefixStatus() { - value: "ERROR", - }; - } -- const active = currentPath.value === lane.path; -+ const active = normalizedPath === lane.path; - return { - ...lane, - active, -@@ -519,7 +524,7 @@ function storageProjectsPrefixStatus() { - return { - configured: !invalidPath, - invalidPath, -- missing: !currentPath.found || !currentPath.value, -+ missing: !currentPath.found || !normalizedPath, - rows, - secretsExposed: false, - status: invalidPath ? "ERROR" : "PASS", -@@ -735,6 +740,117 @@ function overallHealthStatus(rows) { - return "PASS"; - } - -+function localApiStartupPortFromUrl(value) { -+ const rawValue = String(value || "").trim(); -+ if (!rawValue) { -+ return "not configured"; -+ } -+ try { -+ const parsedUrl = new URL(rawValue); -+ return parsedUrl.port || LOCAL_API_STARTUP_DEFAULT_PORT_BY_PROTOCOL[parsedUrl.protocol] || "not configured"; -+ } catch { -+ return "invalid URL"; -+ } -+} -+ -+function localApiStartupUrlDisplay(value, fallback = "not configured") { -+ const rawValue = String(value || "").trim(); -+ if (!rawValue) { -+ return fallback; -+ } -+ try { -+ const parsedUrl = new URL(rawValue); -+ if (parsedUrl.username) { -+ parsedUrl.username = "********"; -+ } -+ if (parsedUrl.password) { -+ parsedUrl.password = "********"; -+ } -+ parsedUrl.search = ""; -+ parsedUrl.hash = ""; -+ return parsedUrl.toString(); -+ } catch { -+ return "invalid URL"; -+ } -+} -+ -+function localApiStartupBindTarget(env = process.env) { -+ const host = String(env.GAMEFOUNDRY_LOCAL_API_HOST || LOCAL_API_STARTUP_DEFAULT_HOST).trim() || LOCAL_API_STARTUP_DEFAULT_HOST; -+ const port = String(env.GAMEFOUNDRY_LOCAL_API_PORT || LOCAL_API_STARTUP_DEFAULT_PORT).trim() || LOCAL_API_STARTUP_DEFAULT_PORT; -+ const portStatus = /^[1-9]\d*$/.test(port) ? "PASS" : "WARN"; -+ return { -+ host, -+ port, -+ status: portStatus, -+ value: `${host}:${port}`, -+ }; -+} -+ -+function systemHealthLocalApiStartupDiagnostics(env = process.env) { -+ const bindTarget = localApiStartupBindTarget(env); -+ const configuredApiUrl = String(env.GAMEFOUNDRY_API_URL || "").trim(); -+ const derivedApiUrl = `http://${bindTarget.value}/api`; -+ const siteUrl = String(env.GAMEFOUNDRY_SITE_URL || "").trim(); -+ const rows = [ -+ { -+ field: "Approved diagnostics format", -+ reason: "Startup output includes deterministic Environment Variables and All Runtime Ports sections.", -+ status: "PASS", -+ value: "Environment Variables + All Runtime Ports", -+ }, -+ { -+ field: "Environment variable diagnostics", -+ reason: "Startup output masks secret-like values and redacts URL credentials before printing.", -+ status: "PASS", -+ value: "masked and redacted", -+ }, -+ { -+ field: "Configured startup bind target", -+ reason: bindTarget.status === "PASS" -+ ? "Local API startup uses the configured or default host and port for the bind target." -+ : "GAMEFOUNDRY_LOCAL_API_PORT must be a positive integer.", -+ status: bindTarget.status, -+ value: bindTarget.value, -+ }, -+ { -+ field: "Configured site URL", -+ reason: siteUrl -+ ? "GAMEFOUNDRY_SITE_URL is available for startup diagnostics." -+ : "GAMEFOUNDRY_SITE_URL is not configured; startup diagnostics will print not configured.", -+ status: siteUrl ? "PASS" : "WARN", -+ value: localApiStartupUrlDisplay(siteUrl), -+ }, -+ { -+ field: "Configured API URL", -+ reason: configuredApiUrl -+ ? "GAMEFOUNDRY_API_URL is configured and displayed without URL credentials." -+ : "GAMEFOUNDRY_API_URL is not configured; startup diagnostics derive /api from the bind target.", -+ status: "PASS", -+ value: localApiStartupUrlDisplay(configuredApiUrl || derivedApiUrl), -+ }, -+ { -+ field: "Configured API URL port", -+ reason: "Port is derived from the configured or startup-derived API URL for display only.", -+ status: "PASS", -+ value: localApiStartupPortFromUrl(configuredApiUrl || derivedApiUrl), -+ }, -+ { -+ field: "Configurable multiple runtime ports", -+ reason: "Configurable multiple runtime ports are explicitly deferred/cancelled for this PR.", -+ status: "PENDING", -+ value: "deferred/cancelled", -+ }, -+ ]; -+ const actionableRows = rows.filter((row) => row.status !== "PENDING"); -+ return { -+ message: "Local API startup diagnostics use the approved safe output format; configurable multiple runtime ports remain deferred.", -+ rows, -+ secretEditingAllowed: false, -+ secretsExposed: false, -+ status: overallHealthStatus(actionableRows), -+ }; -+} -+ - function systemHealthSummary(rows) { - const counts = systemHealthCounts(rows); - const total = counts.PASS + counts.WARN + counts.FAIL; -@@ -3512,6 +3628,7 @@ LIMIT 1; - const databaseStatus = await this.ownerDatabaseStatus(); - const storageStatus = this.ownerStorageStatus(); - const environmentStatus = storageProjectsPrefixStatus(); -+ const localApiStartup = systemHealthLocalApiStartupDiagnostics(); - const limitRows = systemHealthLimitRows(); - const limitsStatus = systemHealthLimitStatus(limitRows); - const packageStatus = projectPackageReadinessStatus(); -@@ -3563,6 +3680,11 @@ LIMIT 1; - ? "Required limits are configured correctly; live usage is NOT AVAILABLE until provider usage metrics are exposed safely." - : "One or more required limits are missing or invalid in current .env.", - }, -+ { -+ area: "Local API startup diagnostics", -+ status: localApiStartup.status, -+ summary: localApiStartup.message, -+ }, - { - area: "Migration status", - status: databaseStatus.migrationStatus || "WARN", -@@ -3596,6 +3718,12 @@ LIMIT 1; - { area: "Environment configuration", field: environmentStatus.variableName, status: environmentStatus.status, value: environmentStatus.configured ? "valid lane match" : "missing or invalid" }, - { area: "Secrets status", field: "Storage access key", status: storageStatus.accessKeyStatus || "WARN", value: storageStatus.accessKeyConfigured ? "configured; value hidden" : "not configured" }, - { area: "Secrets status", field: "Storage secret key", status: storageStatus.secretKeyStatus || "WARN", value: storageStatus.secretKeyConfigured ? "configured; value hidden" : "not configured" }, -+ ...localApiStartup.rows.map((row) => ({ -+ area: "Local API startup diagnostics", -+ field: row.field, -+ status: row.status, -+ value: row.value, -+ })), - { area: "Migration status", field: "Migration counts", status: databaseStatus.migrationStatus || "WARN", value: `DDL=${databaseStatus.migrationCounts?.DDL || 0}; DML=${databaseStatus.migrationCounts?.DML || 0}` }, - { area: "Project package readiness", field: ".gfsp decision", status: packageStatus.status, value: packageStatus.decisionPath }, - { area: "Project package readiness", field: "Runtime scaffold", status: packageStatus.status, value: `${packageStatus.contract?.packageType || "Game Foundry Studio Project"} ${packageStatus.contract?.contractVersion || ""}`.trim() }, -@@ -3615,6 +3743,7 @@ LIMIT 1; - adminOperations: "/admin/operations.html", - }, - limits: limitRows, -+ localApiStartup, - message: "Admin System Health loaded safe status only.", - operationsHealth, - overview, -diff --git a/src/dev-runtime/storage/storage-config.mjs b/src/dev-runtime/storage/storage-config.mjs -index e54f404cc..ceecc8469 100644 ---- a/src/dev-runtime/storage/storage-config.mjs -+++ b/src/dev-runtime/storage/storage-config.mjs -@@ -8,6 +8,15 @@ export const STORAGE_ENV_KEYS = Object.freeze([ - ...STORAGE_CONNECTION_ENV_KEYS, - "GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX", - ]); -+export const STORAGE_PROJECTS_PREFIX_LANES = Object.freeze([ -+ Object.freeze({ lane: "DEV", path: "/dev/projects/" }), -+ Object.freeze({ lane: "IST", path: "/ist/projects/" }), -+ Object.freeze({ lane: "UAT", path: "/uat/projects/" }), -+ Object.freeze({ lane: "PRD", path: "/prod/projects/" }), -+]); -+export const STORAGE_PROJECTS_ALLOWED_PREFIXES = Object.freeze( -+ STORAGE_PROJECTS_PREFIX_LANES.map((lane) => lane.path), -+); - export const DB_BACKUP_STORAGE_PROVIDER_ENV = "GAMEFOUNDRY_DB_BACKUP_STORAGE_PROVIDER"; - export const DB_BACKUP_PREFIX_ENV = "GAMEFOUNDRY_DB_BACKUP_PREFIX"; - export const DB_BACKUP_STORAGE_ENV_KEYS = Object.freeze([ -@@ -38,6 +47,10 @@ export function normalizeStorageProjectsPrefix(value) { - return normalizeStoragePrefix(value); - } - -+function storageProjectsPrefixValidationError() { -+ return `GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX must be one of ${STORAGE_PROJECTS_ALLOWED_PREFIXES.join(", ")}.`; -+} -+ - export function loadStorageConfig(env = process.env) { - const missingKeys = STORAGE_ENV_KEYS.filter((key) => !envValue(env, key)); - if (missingKeys.length) { -@@ -80,6 +93,18 @@ export function loadStorageConfig(env = process.env) { - }, - }; - } -+ if (!STORAGE_PROJECTS_ALLOWED_PREFIXES.includes(projectsPrefix)) { -+ return { -+ configured: false, -+ missingKeys: [], -+ safe: { -+ bucket: envValue(env, "GAMEFOUNDRY_STORAGE_BUCKET"), -+ endpoint: endpoint.origin, -+ projectsPrefix, -+ }, -+ validationError: storageProjectsPrefixValidationError(), -+ }; -+ } - - return { - accessKeyId: envValue(env, "GAMEFOUNDRY_STORAGE_ACCESS_KEY_ID"), -diff --git a/tests/dev-runtime/AdminHealthOperations.test.mjs b/tests/dev-runtime/AdminHealthOperations.test.mjs -index 7f7ae4f3c..69f2b146d 100644 ---- a/tests/dev-runtime/AdminHealthOperations.test.mjs -+++ b/tests/dev-runtime/AdminHealthOperations.test.mjs -@@ -108,6 +108,8 @@ async function apiJson(baseUrl, pathName, request = {}) { - - test("Admin can view operational health while Creator sessions are blocked", async () => { - await withEnv({ -+ GAMEFOUNDRY_API_URL: "http://api-user:api-secret@127.0.0.1:5501/api", -+ GAMEFOUNDRY_SITE_URL: "http://site-user:site-secret@127.0.0.1:5500", - GAMEFOUNDRY_SUPABASE_ANON_KEY: undefined, - GAMEFOUNDRY_SUPABASE_SERVICE_ROLE_KEY: undefined, - GAMEFOUNDRY_SUPABASE_URL: undefined, -@@ -127,6 +129,22 @@ test("Admin can view operational health while Creator sessions are blocked", asy - method: "POST", - }); - const health = await apiJson(server.baseUrl, "/api/admin/system-health/status"); -+ assert.equal(health.localApiStartup.secretEditingAllowed, false); -+ assert.equal(health.localApiStartup.secretsExposed, false); -+ assert.equal(Array.isArray(health.localApiStartup.rows), true); -+ assert.equal( -+ health.localApiStartup.rows.some((row) => row.field === "Approved diagnostics format" && row.status === "PASS"), -+ true, -+ ); -+ assert.equal( -+ health.localApiStartup.rows.some((row) => row.field === "Configurable multiple runtime ports" && row.status === "PENDING" && row.value === "deferred/cancelled"), -+ true, -+ ); -+ const startupText = JSON.stringify(health.localApiStartup); -+ assert.equal(startupText.includes("api-user"), false); -+ assert.equal(startupText.includes("api-secret"), false); -+ assert.equal(startupText.includes("site-user"), false); -+ assert.equal(startupText.includes("site-secret"), false); - assert.equal(Array.isArray(health.operationsHealth.summaryRows), true); - assert.deepEqual( - health.operationsHealth.summaryRows.map((row) => row.area), -diff --git a/tests/dev-runtime/StorageConfig.test.mjs b/tests/dev-runtime/StorageConfig.test.mjs -new file mode 100644 -index 000000000..b7e30cd6f ---- /dev/null -+++ b/tests/dev-runtime/StorageConfig.test.mjs -@@ -0,0 +1,72 @@ -+import assert from "node:assert/strict"; -+import test from "node:test"; -+import { -+ STORAGE_PROJECTS_ALLOWED_PREFIXES, -+ loadStorageConfig, -+ normalizeStorageProjectsPrefix, -+} from "../../src/dev-runtime/storage/storage-config.mjs"; -+ -+function validStorageEnv(projectsPrefix = "/dev/projects/") { -+ return { -+ GAMEFOUNDRY_STORAGE_ACCESS_KEY_ID: "test-access-key", -+ GAMEFOUNDRY_STORAGE_BUCKET: "gamefoundry-test-assets", -+ GAMEFOUNDRY_STORAGE_ENDPOINT: "https://r2.example.invalid", -+ GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX: projectsPrefix, -+ GAMEFOUNDRY_STORAGE_SECRET_ACCESS_KEY: "test-secret-key", -+ }; -+} -+ -+test("storage projects prefix normalizes slash variants", () => { -+ assert.equal(normalizeStorageProjectsPrefix("dev/projects"), "/dev/projects/"); -+ assert.equal(normalizeStorageProjectsPrefix("\\ist\\projects\\"), "/ist/projects/"); -+ assert.equal(normalizeStorageProjectsPrefix(" /uat/projects/ "), "/uat/projects/"); -+ assert.equal(normalizeStorageProjectsPrefix("prod/projects/"), "/prod/projects/"); -+}); -+ -+test("storage config accepts only approved project storage prefixes", () => { -+ assert.deepEqual(STORAGE_PROJECTS_ALLOWED_PREFIXES, [ -+ "/dev/projects/", -+ "/ist/projects/", -+ "/uat/projects/", -+ "/prod/projects/", -+ ]); -+ -+ STORAGE_PROJECTS_ALLOWED_PREFIXES.forEach((projectsPrefix) => { -+ const config = loadStorageConfig(validStorageEnv(projectsPrefix)); -+ assert.equal(config.configured, true); -+ assert.equal(config.safe.projectsPrefix, projectsPrefix); -+ }); -+}); -+ -+test("storage config rejects unapproved project storage prefixes", () => { -+ ["/production/projects/", "/qa/projects/", "/projects/"].forEach((projectsPrefix) => { -+ const config = loadStorageConfig(validStorageEnv(projectsPrefix)); -+ assert.equal(config.configured, false); -+ assert.equal(config.safe.projectsPrefix, projectsPrefix); -+ assert.match(config.validationError, /GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX must be one of/); -+ assert.equal(config.validationError.includes("/prod/projects/"), true); -+ }); -+}); -+ -+test("storage config reports missing project storage prefix", () => { -+ const env = validStorageEnv(""); -+ const config = loadStorageConfig(env); -+ assert.equal(config.configured, false); -+ assert.deepEqual(config.missingKeys, ["GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX"]); -+ assert.equal(config.safe.projectsPrefix, ""); -+}); -+ -+test("storage safe config does not expose credential values", () => { -+ const env = validStorageEnv("/prod/projects/"); -+ const config = loadStorageConfig(env); -+ assert.equal(config.configured, true); -+ assert.deepEqual(config.safe, { -+ bucket: "gamefoundry-test-assets", -+ endpoint: "https://r2.example.invalid", -+ projectsPrefix: "/prod/projects/", -+ }); -+ assert.equal(Object.hasOwn(config.safe, "accessKeyId"), false); -+ assert.equal(Object.hasOwn(config.safe, "secretAccessKey"), false); -+ assert.equal(JSON.stringify(config.safe).includes("test-access-key"), false); -+ assert.equal(JSON.stringify(config.safe).includes("test-secret-key"), false); -+}); -diff --git a/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs b/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs -index 9287e4310..f3c860186 100644 ---- a/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs -+++ b/tests/playwright/tools/AdminHealthOperationsPage.spec.mjs -@@ -129,6 +129,11 @@ test("Admin System Health renders Postgres diagnostics through the safe status A - await expect(page.getByRole("table", { name: "Environment summary" })).toContainText("IST"); - await expect(page.getByRole("table", { name: "Environment summary" })).toContainText("UAT"); - await expect(page.getByRole("table", { name: "Environment summary" })).toContainText("PRD"); -+ await expect(page.getByRole("table", { name: "Local API startup diagnostics" })).toContainText("Approved diagnostics format"); -+ await expect(page.getByRole("table", { name: "Local API startup diagnostics" })).toContainText("Environment Variables + All Runtime Ports"); -+ await expect(page.getByRole("table", { name: "Local API startup diagnostics" })).toContainText("Configurable multiple runtime ports"); -+ await expect(page.getByRole("table", { name: "Local API startup diagnostics" })).toContainText("deferred/cancelled"); -+ await expect(page.getByRole("table", { name: "Local API startup diagnostics" })).not.toContainText("secret"); - await expect(page.getByRole("table", { name: "Database health" })).toContainText("Postgres"); - await expect(page.locator("[data-admin-system-health-db-value='provider']")).toHaveText("Postgres"); - await expect(page.locator("[data-admin-system-health-db-value='host']")).not.toHaveText("Configured host placeholder"); -@@ -213,6 +218,7 @@ test("Admin System Health operations page keeps scripts and styles external", as - expect(pageSource).not.toContain("No active failure is declared"); - expect(pageSource).not.toContain("SQLite"); - expect(pageSource).toContain("Diagnostics Plan"); -+ expect(pageSource).toContain("Local API Startup Diagnostics"); - expect(pageSource).toContain("Server-owned Postgres health reader"); - expect(pageSource).toContain("Server-owned Cloudflare R2 storage diagnostic"); - expect(pageSource).toContain("assets/theme-v2/js/admin-system-health.js"); -diff --git a/tests/playwright/tools/AdminPlatformToolsWireframes.spec.mjs b/tests/playwright/tools/AdminPlatformToolsWireframes.spec.mjs -index bed813761..61ba37122 100644 ---- a/tests/playwright/tools/AdminPlatformToolsWireframes.spec.mjs -+++ b/tests/playwright/tools/AdminPlatformToolsWireframes.spec.mjs -@@ -37,7 +37,7 @@ function storagePathStatusFor(configuredPath) { - { lane: "DEV", path: "/dev/projects/" }, - { lane: "IST", path: "/ist/projects/" }, - { lane: "UAT", path: "/uat/projects/" }, -- { lane: "PRD", path: "/prd/projects/" }, -+ { lane: "PRD", path: "/prod/projects/" }, - ]; - const matchedLane = lanes.find((lane) => lane.path === configuredPath); - const invalidPath = !matchedLane; -@@ -480,7 +480,7 @@ async function expectStoragePathStatusRows(page, expectedValues) { - const storageRows = page.locator("[data-admin-storage-path-status-rows] tr"); - await expect(storageRows).toHaveCount(4); - const lanes = ["DEV", "IST", "UAT", "PRD"]; -- const paths = ["/dev/projects/", "/ist/projects/", "/uat/projects/", "/prd/projects/"]; -+ const paths = ["/dev/projects/", "/ist/projects/", "/uat/projects/", "/prod/projects/"]; - for (let index = 0; index < lanes.length; index += 1) { - await expect(storageRows.nth(index).locator("td")).toHaveText([ - lanes[index], -@@ -554,7 +554,7 @@ for (const adminPage of ADMIN_WIREFRAME_PAGES) { - await expect(page.locator("body")).toContainText("/dev/projects/"); - await expect(page.locator("body")).toContainText("/ist/projects/"); - await expect(page.locator("body")).toContainText("/uat/projects/"); -- await expect(page.locator("body")).toContainText("/prd/projects/"); -+ await expect(page.locator("body")).toContainText("/prod/projects/"); - await expect(page.locator("body")).toContainText("GAMEFOUNDRY_STORAGE_PROJECTS_PREFIX"); - await expectStoragePathStatusRows(page, ["yes", "no", "no", "no"]); - const infrastructureImage = page.locator("[data-image-zoom-target='admin-infrastructure-image-zoom']"); +diff --git a/docs_build/dev/BUILD_PR.md b/docs_build/dev/BUILD_PR.mdindex cf7378880..dd5b4d28f 100644--- a/docs_build/dev/BUILD_PR.md+++ b/docs_build/dev/BUILD_PR.md@@ -1,59 +1,63 @@-# PR_26175_ALFA_006-game-hub-create-project-validation+# PR_26175_ALFA_008-game-hub-feature-matrix ## Purpose-Add creator-facing validation for the Game Hub create-project row so blank game names do not silently create fallback projects.+Audit the current Game Hub workflow and publish a feature matrix that maps implemented creator-facing behavior to code and Playwright evidence. ## Source Of Truth-This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_006-game-hub-create-project-validation`.+This `BUILD_PR.md` is the source of truth for `PR_26175_ALFA_008-game-hub-feature-matrix`. ## Exact Scope-- Validate the Game Hub add-game row before calling the repository create method.-- Block signed-in creator saves when the game name is blank or whitespace-only.-- Keep the add-game row open after validation failure.-- Show a creator-safe validation message in the existing Game Hub status log.-- Mark the game name input invalid for accessibility.-- Preserve valid create/open/delete behavior.-- Preserve guest save redirect behavior.+- Produce a Game Hub feature matrix only.+- Audit Game Hub table workflow, selected/open game behavior, create/edit/delete actions, child tables, guest save gating, empty/error states, Theme V2 layout, and targeted Game Hub coverage.+- Use current `main` behavior as evidence.+- Preserve Game Hub UI/product behavior. - Preserve API/service/repository contracts.-- Add targeted Playwright coverage for the create validation path.+- Preserve previous ALFA Game Hub cleanup and create-validation behavior.+- Do not implement product/UI changes unless validation exposes a requirement-critical defect. ## Exact Targets - `docs_build/dev/BUILD_PR.md`-- `toolbox/game-hub/game-hub.js`-- `tests/playwright/tools/GameHubMockRepository.spec.mjs`-- `docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_report.md`-- `docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_validation-lane.md`-- `docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_requirements-checklist.md`+- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md`+- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md`+- `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md` - `docs_build/dev/reports/codex_review.diff` - `docs_build/dev/reports/codex_changed_files.txt` +## Evidence Sources+- `toolbox/game-hub/index.html`+- `toolbox/project-workspace/index.html`+- `toolbox/game-hub/game-hub.js`+- `toolbox/game-hub/game-hub-api-client.js`+- `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js`+- `tests/playwright/tools/GameHubMockRepository.spec.mjs`+ ## Out Of Scope-- No repository/API/service contract changes.-- No Game Journey completion-metrics changes.+- No Game Hub product or UI changes.+- No Game Journey changes. - No shared toolbox status bar changes.-- No unrelated Game Hub workflow changes. - No browser-owned product data as source of truth.-- No silent create-name fallback in the Game Hub page flow.+- No API/service/repository contract changes. - No inline styles, style blocks, or page-local CSS. - No engine core changes. - No `start_of_day` folder changes.+- No ALFA_007 work. ## Validation-Run targeted create-project validation:+Run targeted Game Hub validation: ```powershell-npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1 --grep "Game Hub creates, opens, and deletes mock games"+npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1 ``` -Also verify changed source does not introduce inline styles or style blocks:+Also verify changed docs/reports do not introduce inline styles or style blocks: ```powershell-rg -n "<[s]tyle|[s]tyle=" toolbox/game-hub/game-hub.js tests/playwright/tools/GameHubMockRepository.spec.mjs docs_build/dev/BUILD_PR.md docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_report.md docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_validation-lane.md docs_build/dev/reports/PR_26175_ALFA_006-game-hub-create-project-validation_requirements-checklist.md+rg -n "<[s]tyle|[s]tyle=" docs_build/dev/BUILD_PR.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md ``` ## Artifact Create repo-structured delta ZIP: ```text-tmp/PR_26175_ALFA_006-game-hub-create-project-validation_delta.zip+tmp/PR_26175_ALFA_008-game-hub-feature-matrix_delta.zip ```diff --git a/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.mdnew file mode 100644index 000000000..3fbcfdb04--- /dev/null+++ b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md@@ -0,0 +1,35 @@+# PR_26175_ALFA_008-game-hub-feature-matrix Report++## Overall Status+PASS++## Summary+ALFA_008 produced a report-only Game Hub feature matrix from current `main` behavior. No product/UI/source implementation changes were needed. Targeted Game Hub validation passed with 14/14 Playwright tests.++## Feature Matrix+| Feature Area | Status | Current Behavior | Source Evidence | Validation Evidence |+| --- | --- | --- | --- | --- |+| Deprecated project workspace route | PASS | Older Project Workspace links land on a Game Hub handoff page and expose one creator-facing Game Hub action. | `toolbox/project-workspace/index.html:17`, `toolbox/project-workspace/index.html:20`, `toolbox/project-workspace/index.html:21`, `toolbox/project-workspace/index.html:22` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:244`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:248`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:251` |+| Game Hub page shell | PASS | Game Hub uses Theme V2 shared classes, a wide tool workspace, center Games panel, and shared status elements. | `toolbox/game-hub/index.html:24`, `toolbox/game-hub/index.html:25`, `toolbox/game-hub/index.html:26`, `toolbox/game-hub/index.html:36`, `toolbox/game-hub/index.html:37`, `toolbox/game-hub/index.html:39` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:263`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:873`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:878`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:880` |+| Game table ownership | PASS | The Game Hub page owns the creator-facing game table and renders it in the center panel only. | `toolbox/game-hub/game-hub.js:538`, `toolbox/game-hub/game-hub.js:561`, `toolbox/game-hub/game-hub.js:563`, `toolbox/game-hub/game-hub.js:567`, `toolbox/game-hub/game-hub.js:569` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:288`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:289`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:296`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:298` |+| Parent row display | PASS | Parent rows display Game, Purpose, Status, and Actions without owner/role/next-tool columns. | `toolbox/game-hub/game-hub.js:500`, `toolbox/game-hub/game-hub.js:515`, `toolbox/game-hub/game-hub.js:518`, `toolbox/game-hub/game-hub.js:519`, `toolbox/game-hub/game-hub.js:523` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:298`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:304`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:305`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:306`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:307` |+| Selected/open game affordance | PASS | Selection is represented by the game toggle button only; rows do not gain active-row attributes or row highlighting. | `toolbox/game-hub/game-hub.js:500`, `toolbox/game-hub/game-hub.js:515`, `toolbox/game-hub/game-hub.js:768`, `toolbox/game-hub/game-hub.js:771`, `toolbox/game-hub/game-hub.js:776` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:308`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:311`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:314`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:324`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:326` |+| Add game workflow | PASS | Creators can open an add row, enter Game/Purpose/Status, save a new game, and cancel without saving. | `toolbox/game-hub/game-hub.js:428`, `toolbox/game-hub/game-hub.js:441`, `toolbox/game-hub/game-hub.js:448`, `toolbox/game-hub/game-hub.js:451`, `toolbox/game-hub/game-hub.js:699`, `toolbox/game-hub/game-hub.js:707` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:379`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:398`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:401`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:411`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:426`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:430` |+| Create-name validation | PASS | Blank and whitespace-only names are blocked in the page flow before repository create, keeping the add row open and showing a creator-safe status message. | `toolbox/game-hub/game-hub.js:681`, `toolbox/game-hub/game-hub.js:684`, `toolbox/game-hub/game-hub.js:687`, `toolbox/game-hub/game-hub.js:690`, `toolbox/game-hub/game-hub.js:703`, `toolbox/game-hub/game-hub.js:707` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:386`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:389`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:391`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:392`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:393`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:397` |+| Repository contract preservation | PASS | The Game Hub API client still uses the shared server repository client, and the mock repository contract remains unchanged. The lower-level repository still has defensive defaults, but ALFA_006 page validation prevents blank names from becoming creator-facing Game Hub creates. | `toolbox/game-hub/game-hub-api-client.js:1`, `toolbox/game-hub/game-hub-api-client.js:15`, `toolbox/game-hub/game-hub-api-client.js:16`, `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js:378`, `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js:381`, `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js:419` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:391`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:392`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:396`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:397` |+| Edit game purpose/status | PASS | Existing game names are read-only in edit mode while Purpose and Status remain editable. | `toolbox/game-hub/game-hub.js:464`, `toolbox/game-hub/game-hub.js:470`, `toolbox/game-hub/game-hub.js:471`, `toolbox/game-hub/game-hub.js:475`, `toolbox/game-hub/game-hub.js:478`, `toolbox/game-hub/game-hub.js:727`, `toolbox/game-hub/game-hub.js:741`, `toolbox/game-hub/game-hub.js:752` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:413`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:417`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:418`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:419`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:424`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:780` |+| Delete open game | PASS | Signed-in creators can delete the active non-source-linked game, and source-linked games are protected. | `toolbox/game-hub/game-hub.js:834`, `toolbox/game-hub/game-hub.js:838`, `toolbox/game-hub/game-hub.js:845`, `toolbox/game-hub/game-hub.js:851`, `toolbox/game-hub/game-hub.js:852` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:451`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:452`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:454`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:860`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:861` |+| Source idea child table | PASS | Source-linked games can expose read-only Idea Board context without edit/delete controls. | `toolbox/game-hub/game-hub.js:399`, `toolbox/game-hub/game-hub.js:401`, `toolbox/game-hub/game-hub.js:404`, `toolbox/game-hub/game-hub.js:415`, `toolbox/game-hub/game-hub.js:422` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:462`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:559`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:563`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:568`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:576` |+| Readiness output child table | PASS | Every expanded game can expose readiness output and checklist context from Game Journey progress data. | `toolbox/game-hub/game-hub.js:353`, `toolbox/game-hub/game-hub.js:370`, `toolbox/game-hub/game-hub.js:372`, `toolbox/game-hub/game-hub.js:385`, `toolbox/game-hub/game-hub.js:386`, `toolbox/game-hub/game-hub.js:408` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:362`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:365`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:579`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:581`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:826`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:858` |+| Guest browsing/save gating | PASS | Guests can browse Game Hub but save operations redirect to sign-in and delete is disabled. | `toolbox/game-hub/game-hub.js:131`, `toolbox/game-hub/game-hub.js:139`, `toolbox/game-hub/game-hub.js:147`, `toolbox/game-hub/game-hub.js:151`, `toolbox/game-hub/game-hub.js:174`, `toolbox/game-hub/game-hub.js:178` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:593`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:601`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:603`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:604`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:617`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:623` |+| Empty state | PASS | Empty project lists show a creator-safe prompt and keep Add Game available. | `toolbox/game-hub/game-hub.js:557`, `toolbox/game-hub/game-hub.js:558`, `toolbox/game-hub/game-hub.js:570` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:633`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:680`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:687`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:688`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:690` |+| Unavailable/error states | PASS | Repository and active-game errors use creator-safe messages without leaking backend details. | `toolbox/game-hub/game-hub.js:66`, `toolbox/game-hub/game-hub.js:70`, `toolbox/game-hub/game-hub.js:82`, `toolbox/game-hub/game-hub.js:89`, `toolbox/game-hub/game-hub.js:549`, `toolbox/game-hub/game-hub.js:550` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:697`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:713`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:716`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:724`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:749`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:771` |+| Role-focused Toolbox discovery | PASS | Toolbox role filters still include Game Hub where expected while hiding unavailable role-focused tools. | `tests/playwright/tools/GameHubMockRepository.spec.mjs:996`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1000`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1002`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1010`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1012`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1030` | `tests/playwright/tools/GameHubMockRepository.spec.mjs:996`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1012`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1024`, `tests/playwright/tools/GameHubMockRepository.spec.mjs:1034` |++## Validation+- PASS: `npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1`+- Result: 14 passed, 0 failed.+- PASS: Inline-style/style-block report scan completed with no matches after reports were created.++## Artifact+- `tmp/PR_26175_ALFA_008-game-hub-feature-matrix_delta.zip`diff --git a/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.mdnew file mode 100644index 000000000..25f65acd6--- /dev/null+++ b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md@@ -0,0 +1,15 @@+# PR_26175_ALFA_008-game-hub-feature-matrix Requirements Checklist++| Requirement | Status | Evidence |+| --- | --- | --- |+| Replace stale BUILD source of truth with ALFA_008 | PASS | `docs_build/dev/BUILD_PR.md:1` identifies `PR_26175_ALFA_008-game-hub-feature-matrix`. |+| Produce a Game Hub feature matrix only | PASS | `docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md` contains the feature matrix and no product source files were changed. |+| Audit Game Hub table workflow completion | PASS | Matrix rows cover Game table ownership, parent rows, selection affordance, add/create validation, edit, delete, child tables, guest gating, and error states. |+| Use current main behavior as evidence | PASS | Matrix evidence points to `toolbox/game-hub/index.html`, `toolbox/project-workspace/index.html`, `toolbox/game-hub/game-hub.js`, `toolbox/game-hub/game-hub-api-client.js`, `src/dev-runtime/persistence/tool-repositories/game-workspace-mock-repository.js`, and `tests/playwright/tools/GameHubMockRepository.spec.mjs`. |+| Preserve Game Hub UI/product behavior | PASS | No Game Hub product/UI/source implementation files were modified in this PR. |+| Preserve API/service/repository contracts | PASS | No API, service, or repository files were modified. Matrix records existing API/repository evidence without changing contracts. |+| Preserve previous ALFA cleanup and create validation behavior | PASS | Targeted Game Hub spec passed 14/14 tests, including ALFA_005 selector cleanup and ALFA_006 create-name validation assertions. |+| Do not add browser-owned product data as source of truth | PASS | No runtime/product JSON or browser-owned data contract files were modified. |+| Do not add inline styles, style blocks, or page-local CSS | PASS | ALFA_008 changes are docs/reports only, and the targeted style scan found no matches. |+| Create required reports | PASS | Report, validation lane, requirements checklist, review diff, and changed-files report are included. |+| Create repo-structured delta ZIP | PASS | `tmp/PR_26175_ALFA_008-game-hub-feature-matrix_delta.zip` was created after reports were finalized. |diff --git a/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.mdnew file mode 100644index 000000000..71a5ec416--- /dev/null+++ b/docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md@@ -0,0 +1,11 @@+# PR_26175_ALFA_008-game-hub-feature-matrix Validation Lane++## Commands+| Command | Status | Evidence |+| --- | --- | --- |+| `npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs --workers=1` | PASS | 14 passed, 0 failed. Covered deprecated route, create/open/delete, parent/child tables, guest save gating, empty state, unavailable state, active-game error state, malformed active-game payloads, purpose/status edits, readiness rows, wide Theme V2 layout, representative toolbox layout, Learn guidance, and member-role filters. |+| `rg -n "<[s]tyle|[s]tyle=" docs_build/dev/BUILD_PR.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md` | PASS | No inline style or style block matches in ALFA_008 changed docs/reports. |++## Notes+- Playwright updated shared coverage report outputs during validation; those generated files were restored because they are outside ALFA_008 exact targets.+- No product/UI/source implementation files were changed for this audit.diff --git a/docs_build/dev/reports/codex_changed_files.txt b/docs_build/dev/reports/codex_changed_files.txtindex 9dca38cd8..15aa8521d 100644--- a/docs_build/dev/reports/codex_changed_files.txt+++ b/docs_build/dev/reports/codex_changed_files.txt@@ -1,23 +1,6 @@-?.env.example-admin/infrastructure.html-admin/system-health.html-assets/theme-v2/js/admin-infrastructure.js-assets/theme-v2/js/admin-system-health.js-docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard.md-docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard_PLAN.md-docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-instruction-compliance-checklist.md-docs_build/dev/reports/PR_26175_CHARLIE_002-system-health-dashboard-manual-validation-notes.md-docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization.md-docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization_PLAN.md-docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization-instruction-compliance-checklist.md-docs_build/dev/reports/PR_26175_CHARLIE_003-r2-storage-standardization-manual-validation-notes.md-docs_build/dev/reports/PR_26175_CHARLIE_EOD-branch-validation.md-docs_build/dev/reports/PR_26175_CHARLIE_EOD-closeout.md-docs_build/dev/reports/PR_26175_CHARLIE_EOD-merge-summary.md-scripts/validate-storage-config.mjs-src/dev-runtime/server/local-api-router.mjs-src/dev-runtime/storage/storage-config.mjs-tests/dev-runtime/AdminHealthOperations.test.mjs-tests/dev-runtime/StorageConfig.test.mjs-tests/playwright/tools/AdminHealthOperationsPage.spec.mjs-tests/playwright/tools/AdminPlatformToolsWireframes.spec.mjs+docs_build/dev/BUILD_PR.md+docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_report.md+docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_validation-lane.md+docs_build/dev/reports/PR_26175_ALFA_008-game-hub-feature-matrix_requirements-checklist.md+docs_build/dev/reports/codex_review.diff+docs_build/dev/reports/codex_changed_files.txt \ No newline at end of file
Database Health - Postgres Only