diff --git a/admin/system-health.html b/admin/system-health.html
index b4b9f477f..8573b3310 100644
--- a/admin/system-health.html
+++ b/admin/system-health.html
@@ -43,6 +43,7 @@
Admin
Local API Startup
Database Health
Storage Health
+ Health Check History
Runtime Environment
Limits & Capacity
Diagnostics Plan
@@ -143,11 +144,29 @@ System Health Tables
- | Bucket | Configured bucket placeholder | PENDING |
- | List | Objects prefix | PENDING |
- | Read | Health object | PENDING |
- | Write | Health object | PENDING |
- | Delete | Health object | PENDING |
+ | Bucket connectivity | Loading | PENDING |
+ | List | Loading | PENDING |
+ | Upload | Loading | PENDING |
+ | Read | Loading | PENDING |
+ | Delete | Loading | PENDING |
+ | Last checked | Loading | PENDING |
+
+
+
+
+
+ Health Check History
+
+
+ | Time |
+ Environment |
+ Area |
+ Result |
+ Summary |
+
+
+
+ | Loading | Loading | Current environment | PENDING | Waiting for safe API status. |
diff --git a/assets/theme-v2/js/admin-system-health.js b/assets/theme-v2/js/admin-system-health.js
index 61b446a3e..e0c2cab9f 100644
--- a/assets/theme-v2/js/admin-system-health.js
+++ b/assets/theme-v2/js/admin-system-health.js
@@ -9,8 +9,9 @@ import {
} from "../../js/shared/status.js";
const STORAGE_DIAGNOSTIC_ACTIONS = Object.freeze([
+ Object.freeze({ actionId: "storage-bucket-connectivity", key: "bucket" }),
Object.freeze({ actionId: "storage-list", key: "list" }),
- Object.freeze({ actionId: "storage-write-test-object", key: "write" }),
+ Object.freeze({ actionId: "storage-upload-test-object", key: "upload" }),
Object.freeze({ actionId: "storage-read-test-object", key: "read" }),
Object.freeze({ actionId: "storage-delete-test-object", key: "delete" }),
]);
@@ -46,6 +47,7 @@ class AdminSystemHealthController {
node.dataset.adminSystemHealthStorageStatus,
node,
]));
+ this.historyRows = root.querySelector("[data-admin-system-health-history-rows]");
this.startupRows = root.querySelector("[data-admin-system-health-startup-rows]");
this.runtimeRows = root.querySelector("[data-admin-system-health-runtime-rows]");
}
@@ -106,6 +108,7 @@ class AdminSystemHealthController {
});
this.renderStartupPending(reason);
this.renderStoragePending(reason);
+ this.renderHistoryPending(reason);
}
renderEnvironmentIdentity(environmentIdentity = {}) {
@@ -127,7 +130,7 @@ class AdminSystemHealthController {
}
renderStoragePending(reason) {
- ["bucket", "list", "read", "write", "delete"].forEach((key) => {
+ ["bucket", "list", "upload", "read", "delete", "lastChecked"].forEach((key) => {
this.setStorageStatus(key, "PENDING", reason);
});
this.renderRuntimePending(reason);
@@ -153,8 +156,10 @@ class AdminSystemHealthController {
renderStorageStatus(storageStatus = {}) {
const reason = storageStatus.message || "Cloudflare R2 configuration status returned by the safe Admin System Health API.";
- this.setStorageValue("bucket", storageStatus.bucket, "not configured");
+ this.setStorageValue("bucket", storageStatus.environmentFolder ? `${storageStatus.bucket || "not configured"} ${storageStatus.environmentFolder}` : storageStatus.bucket, "not configured");
this.setStorageStatus("bucket", storageStatus.bucketStatus || storageStatus.status, reason);
+ this.setStorageValue("lastChecked", storageStatus.lastChecked, "not available");
+ this.setStorageStatus("lastChecked", storageStatus.lastChecked ? "PASS" : "WARN", reason);
}
renderStartupPending(reason) {
@@ -198,9 +203,12 @@ class AdminSystemHealthController {
storageResultTarget(result = {}) {
if (typeof result.keysListed === "number" && result.actionId === "storage-list") {
- return `${result.keysListed} object(s) under ${asText(result.projectsPrefix, "configured prefix")}`;
+ return `${result.keysListed} object(s) under ${asText(result.environmentFolder, "current environment folder")}`;
}
- return result.testObjectKey || result.projectsPrefix || result.message || "diagnostic target unavailable";
+ if (result.actionId === "storage-bucket-connectivity") {
+ return result.environmentFolder || result.message || "bucket connectivity target unavailable";
+ }
+ return result.testObjectKey || result.environmentFolder || result.message || "diagnostic target unavailable";
}
renderStorageResult(key, result = {}) {
@@ -210,6 +218,49 @@ class AdminSystemHealthController {
}
this.setStorageValue(key, this.storageResultTarget(result));
this.setStorageStatus(key, result.status, result.message || "R2 diagnostic returned without a message.");
+ if (result.lastChecked) {
+ this.setStorageValue("lastChecked", result.lastChecked);
+ this.setStorageStatus("lastChecked", "PASS", "Most recent current-environment R2 health check timestamp.");
+ }
+ }
+
+ renderHistoryPending(reason) {
+ if (!this.historyRows) {
+ return;
+ }
+ const row = document.createElement("tr");
+ row.append(
+ this.createCell("not available"),
+ this.createCell("current environment"),
+ this.createCell("Health Check History"),
+ this.createStatusCell("PENDING", reason),
+ this.createCell("Safe health check history is not available."),
+ );
+ this.historyRows.replaceChildren(row);
+ }
+
+ renderHealthCheckHistory(historyRows = []) {
+ if (!this.historyRows) {
+ return;
+ }
+ const rows = Array.isArray(historyRows) ? historyRows : [];
+ if (!rows.length) {
+ this.renderHistoryPending("Safe Admin System Health API returned no current-environment health check history rows.");
+ return;
+ }
+ const fragment = document.createDocumentFragment();
+ rows.forEach((historyRow) => {
+ const row = document.createElement("tr");
+ row.append(
+ this.createCell(historyRow.checkedAt),
+ this.createCell(historyRow.environmentName),
+ this.createCell(historyRow.area),
+ this.createStatusCell(historyRow.result || historyRow.status, historyRow.summary),
+ this.createCell(historyRow.summary),
+ );
+ fragment.append(row);
+ });
+ this.historyRows.replaceChildren(fragment);
}
runStorageDiagnostics() {
@@ -292,6 +343,7 @@ class AdminSystemHealthController {
this.renderStartupDiagnostics(data?.localApiStartup || {});
this.renderStorageStatus(data?.storageStatus || {});
this.runStorageDiagnostics();
+ this.renderHealthCheckHistory(data?.healthCheckHistory || []);
this.renderRuntimeEnvironment(data?.runtimeEnvironment || {});
} catch (error) {
const message = error instanceof Error ? error.message : "Safe Admin System Health API is unavailable.";
diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_009-system-health-current-r2-health.md b/docs_build/dev/reports/PR_26175_CHARLIE_009-system-health-current-r2-health.md
new file mode 100644
index 000000000..a0cd45bc9
--- /dev/null
+++ b/docs_build/dev/reports/PR_26175_CHARLIE_009-system-health-current-r2-health.md
@@ -0,0 +1,41 @@
+# PR_26175_CHARLIE_009 System Health Current R2 Health
+
+## Scope
+
+Team: Charlie
+
+Purpose: Add current-environment Cloudflare R2 folder health only to Admin System Health.
+
+## Changes
+
+- Replaced the System Health Storage Health rows with current-environment R2 checks:
+ - bucket connectivity
+ - list
+ - upload
+ - read
+ - delete
+ - last checked
+- System Health storage diagnostics run against the current environment folder only:
+ - Local: `/local`
+ - DEV: `/dev`
+ - IST: `/ist`
+ - UAT: `/uat`
+ - PRD: `/prd`
+- Preserved the separate Admin Infrastructure storage diagnostic path that uses the configured project prefix.
+- Updated focused API and Playwright tests.
+
+## Architecture Constraint
+
+PASS. R2 health checks target only the current deployment environment folder. No peer environment R2 folders are actively checked by System Health.
+
+## Validation
+
+- PASS: `node --check src/dev-runtime/server/local-api-router.mjs`
+- PASS: `node --check assets/theme-v2/js/admin-system-health.js`
+- PASS: `git diff --check`
+- PASS: `node --test tests/dev-runtime/AdminHealthOperations.test.mjs`
+- PASS: `npx playwright test tests/playwright/tools/AdminHealthOperationsPage.spec.mjs --workers=1 --reporter=line`
+
+## Artifact
+
+- `tmp/PR_26175_CHARLIE_009-system-health-current-r2-health_delta.zip`
diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_010-system-health-history-and-closeout.md b/docs_build/dev/reports/PR_26175_CHARLIE_010-system-health-history-and-closeout.md
new file mode 100644
index 000000000..c8f5ff396
--- /dev/null
+++ b/docs_build/dev/reports/PR_26175_CHARLIE_010-system-health-history-and-closeout.md
@@ -0,0 +1,68 @@
+# PR_26175_CHARLIE_010 System Health History and Closeout
+
+## Scope
+
+Team: Charlie
+
+Purpose: Add current-environment Health Check History and close out the System Health stacked expansion chain.
+
+## Chain
+
+- `PR_26175_CHARLIE_006-project-instructions-system-health-infrastructure`
+ - Branch: `PR_26175_CHARLIE_006-project-instructions-system-health-infrastructure`
+ - Commit: `c870b812faded383094fb13fc60ae9cfc7f14889`
+ - Result: pushed to origin, not merged.
+- `PR_26175_CHARLIE_007-system-health-environment-identity`
+ - Branch: `pr/26175-CHARLIE-007-system-health-environment-identity`
+ - Commit: `6556e73efcd8ae13b51b56288416c88688e67634`
+ - Draft PR: https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/151
+- `PR_26175_CHARLIE_008-system-health-current-database-health`
+ - Branch: `pr/26175-CHARLIE-008-system-health-current-database-health`
+ - Commit: `2603aeb6e5a7ccca516051953cbd70a5a6c94c4b`
+ - Draft PR: https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/152
+- `PR_26175_CHARLIE_009-system-health-current-r2-health`
+ - Branch: `pr/26175-CHARLIE-009-system-health-current-r2-health`
+ - Commit: `9740705fbe73dffd43744ab66338f8e4a925eed4`
+ - Draft PR: https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/153
+- `PR_26175_CHARLIE_010-system-health-history-and-closeout`
+ - Branch: `pr/26175-CHARLIE-010-system-health-history-and-closeout`
+ - Commit and draft PR URL are assigned after this report is committed and pushed.
+
+## Changes
+
+- Added Health Check History to the Admin System Health page.
+- Health Check History is derived from the current deployment only:
+ - Environment Summary
+ - Database Health
+ - Storage Health
+ - Runtime Health
+- Warning and failure rows are generated only from current-environment health rows.
+- Creator sessions remain blocked from Admin System Health and do not trigger status or storage health requests.
+
+## Governance
+
+- PASS: System Health is one page per deployed environment.
+- PASS: Each deployment actively checks only itself.
+- PASS: The Environment Map remains a static reference for Local, DEV, IST, UAT, and PRD.
+- PASS: System Health does not actively check peer databases or peer R2 folders.
+- PASS: Cancelled initiatives remain not doing:
+ - Environment Isolation & Developer Experience
+ - multi-port workspace framework
+ - Alpha/Beta/User runtime separation
+ - runtime port management initiative
+
+## Validation
+
+- PASS: `node --check src/dev-runtime/server/local-api-router.mjs`
+- PASS: `node --check assets/theme-v2/js/admin-system-health.js`
+- PASS: `git diff --check`
+- PASS: `node --test tests/dev-runtime/AdminHealthOperations.test.mjs`
+- PASS: `node --test tests/dev-runtime/PublicEnvironmentConfig.test.mjs`
+- PASS: `npx playwright test tests/playwright/tools/AdminHealthOperationsPage.spec.mjs --workers=1 --reporter=line`
+
+## Artifacts
+
+- `tmp/PR_26175_CHARLIE_007-system-health-environment-identity_delta.zip`
+- `tmp/PR_26175_CHARLIE_008-system-health-current-database-health_delta.zip`
+- `tmp/PR_26175_CHARLIE_009-system-health-current-r2-health_delta.zip`
+- `tmp/PR_26175_CHARLIE_010-system-health-history-and-closeout_delta.zip`
diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-branch-validation.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-branch-validation.md
new file mode 100644
index 000000000..e2d3a2b30
--- /dev/null
+++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-branch-validation.md
@@ -0,0 +1,15 @@
+# PR_26175_CHARLIE_011 Branch Validation
+
+## Start Gate
+
+- PASS: Current branch was `pr/26175-CHARLIE-010-system-health-history-and-closeout`.
+- PASS: Worktree was clean before implementation.
+- PASS: Build remained on the current Charlie continuation branch.
+- PASS: No rebase was performed.
+- PASS: No new root branch was created.
+
+## Final Branch Target
+
+- Branch to push: `pr/26175-CHARLIE-010-system-health-history-and-closeout`
+- Expected draft PR to update: https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/155
+- Merge status: no merge requested or performed.
diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-manual-validation-notes.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-manual-validation-notes.md
new file mode 100644
index 000000000..e8b6eae26
--- /dev/null
+++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-manual-validation-notes.md
@@ -0,0 +1,26 @@
+# PR_26175_CHARLIE_011 Manual Validation Notes
+
+## Admin Submenu Order
+
+Visible labels after the change:
+
+`Admin Tools`, `Analytics`, `Controls`, `Creators`, `DB Viewer`, `Environments`, `Game Migration`, `Infrastructure`, `Invites`, `Moderation`, `Operations`, `Platform Settings`, `Ratings`, `Responsibilities`, `Site Setup`, `System Health`, `Tool Votes`
+
+## Route Preservation
+
+The only source navigation reorder moved this existing item:
+
+- `Creators`
+ - path remained `admin/users.html`
+ - route remained `admin-users`
+ - label remained `Creators`
+
+All other Admin navigation objects remained unchanged.
+
+## Open-Page Check
+
+The targeted Playwright navigation test collected every active Admin submenu href from the rendered submenu and requested each page through the local test server. Every response returned a status below HTTP 400.
+
+## Duplicate Check
+
+The targeted Playwright navigation test checks for duplicate rendered labels and duplicate active hrefs. The targeted unit script also checks duplicate labels and existing active paths.
diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-requirement-checklist.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-requirement-checklist.md
new file mode 100644
index 000000000..39afb7966
--- /dev/null
+++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-requirement-checklist.md
@@ -0,0 +1,42 @@
+# PR_26175_CHARLIE_011 Requirement Checklist
+
+## Branch Rules
+
+- PASS: Continued on `pr/26175-CHARLIE-010-system-health-history-and-closeout`.
+- PASS: Did not return to `main`.
+- PASS: Did not rebase.
+- PASS: Did not create a new root branch.
+- PASS: Hard stop conditions were checked before implementation.
+
+## Objective
+
+- PASS: Admin submenu entries are alphabetized by displayed text.
+
+## Scope
+
+- PASS: Located Admin submenu definition in `src/api/admin-owner-navigation.js`.
+- PASS: Sorted submenu entries by displayed text.
+- PASS: Preserved routes, URLs, IDs, CSS classes, Theme V2 styling, and existing renderer behavior.
+- PASS: Did not rename pages.
+- PASS: Did not rename folders.
+- PASS: Did not modify page content.
+- PASS: No unrelated cleanup.
+
+## Validation
+
+- PASS: Verified submenu labels are alphabetical.
+- PASS: Verified every Admin page path exists and every Admin submenu href opens below HTTP 400 in targeted Playwright.
+- PASS: Verified no duplicate labels or hrefs.
+- PASS: Ran affected Playwright navigation tests.
+- PASS: Ran affected targeted unit tests.
+
+## Artifacts
+
+- PASS: `docs_build/dev/reports/codex_review.diff`
+- PASS: `docs_build/dev/reports/codex_changed_files.txt`
+- PASS: `docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md`
+- PASS: validation report
+- PASS: branch validation report
+- PASS: requirement checklist
+- PASS: manual validation notes
+- PASS: repository ZIP under `tmp/`
diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-validation.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-validation.md
new file mode 100644
index 000000000..aeec3f443
--- /dev/null
+++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-validation.md
@@ -0,0 +1,22 @@
+# PR_26175_CHARLIE_011 Validation Report
+
+## Commands
+
+- PASS: `node --check src/api/admin-owner-navigation.js`
+- PASS: `node --input-type=module` alphabetical/duplicate/path verification script
+ - Result: `PASS labels=17 active=16`
+ - Order: `Admin Tools | Analytics | Controls | Creators | DB Viewer | Environments | Game Migration | Infrastructure | Invites | Moderation | Operations | Platform Settings | Ratings | Responsibilities | Site Setup | System Health | Tool Votes`
+- PASS: `git diff --check`
+ - Result: no whitespace errors; CRLF conversion warnings only.
+- PASS: `node --test tests/dev-runtime/ApiMenuPathCleanup.test.mjs`
+ - Result: 6 passed.
+- PASS: `node --test --test-name-pattern "Admin and Owner navigation are shared" tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs`
+ - Result: 1 passed.
+- PASS: `npx playwright test tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs --workers=1 --reporter=line`
+ - Result: 4 passed.
+- PASS: `npx playwright test tests/playwright/tools/AdminInvitationsNavPage.spec.mjs --workers=1 --reporter=line`
+ - Result: 3 passed.
+
+## Note
+
+A non-targeted full-file run of `tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs` was not used for final validation because its first non-navigation test fails on a pre-existing missing `src/engine/api` directory assertion. The affected navigation subtest passed by name.
diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md
new file mode 100644
index 000000000..7dcbe5262
--- /dev/null
+++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md
@@ -0,0 +1,47 @@
+# PR_26175_CHARLIE_011 Admin Submenu Alphabetical Order
+
+## Scope
+
+Team: Charlie
+
+Purpose: Alphabetize the Admin submenu by visible menu labels only.
+
+## Branch
+
+- Continuation branch: `pr/26175-CHARLIE-010-system-health-history-and-closeout`
+- Start gate: PASS
+ - Current branch matched the expected Charlie continuation branch.
+ - Worktree was clean before implementation.
+
+## Changes
+
+- Moved `Creators` into its alphabetical position in `src/api/admin-owner-navigation.js`.
+- Preserved each Admin menu item label, path, route id, disabled state, and renderer behavior.
+- Updated affected navigation tests that pin visible Admin menu label order.
+- Added Playwright coverage of:
+ - alphabetical visible label order
+ - duplicate detection
+ - duplicate href detection
+ - each Admin submenu href opening with an HTTP status below 400
+
+## Non-Changes
+
+- No page files were renamed.
+- No folders were renamed.
+- No page content was modified.
+- No routes, URLs, permissions, icons, IDs, CSS classes, Theme V2 styling, or event handlers were changed.
+- No menu outside the Admin submenu was reordered.
+
+## Validation Summary
+
+- PASS: Admin labels are alphabetical.
+- PASS: No duplicate Admin labels.
+- PASS: No duplicate Admin hrefs.
+- PASS: Every active Admin submenu item points to an existing page path.
+- PASS: Every Admin submenu href opened with an HTTP status below 400 in the targeted Playwright navigation test.
+- PASS: Targeted unit tests passed.
+- PASS: Targeted Playwright navigation tests passed.
+
+## Artifact
+
+- `tmp/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order_delta.zip`
diff --git a/docs_build/dev/reports/codex_changed_files.txt b/docs_build/dev/reports/codex_changed_files.txt
index b4511a59b..5efcd7443 100644
--- a/docs_build/dev/reports/codex_changed_files.txt
+++ b/docs_build/dev/reports/codex_changed_files.txt
@@ -1,30 +1,21 @@
-# git diff --cached --name-status origin/main
-M assets/toolbox/idea-board/js/index.js
-A docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_branch-validation.md
-A docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_instruction-compliance.md
-A docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_manual-validation-notes.md
-A docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_report.md
-A docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_requirements-checklist.md
-A docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_validation-lane.md
-M docs_build/dev/reports/codex_changed_files.txt
-M docs_build/dev/reports/codex_review.diff
-M docs_build/dev/reports/coverage_changed_js_guardrail.txt
-M docs_build/dev/reports/playwright_v8_coverage_report.txt
-M tests/playwright/tools/IdeaBoardTableNotes.spec.mjs
-M tests/playwright/tools/ToolboxRoutePages.spec.mjs
-
-# git diff --cached --stat origin/main
- assets/toolbox/idea-board/js/index.js | 31 +-
- ...d-guest-save-auth-redirect_branch-validation.md | 22 +
- ...st-save-auth-redirect_instruction-compliance.md | 31 +
- ...t-save-auth-redirect_manual-validation-notes.md | 37 ++
- ...1-idea-board-guest-save-auth-redirect_report.md | 51 ++
- ...st-save-auth-redirect_requirements-checklist.md | 19 +
- ...ard-guest-save-auth-redirect_validation-lane.md | 36 ++
- docs_build/dev/reports/codex_changed_files.txt | 33 +-
- docs_build/dev/reports/codex_review.diff | 695 +++++++++++++++++----
- .../dev/reports/coverage_changed_js_guardrail.txt | 10 +-
- .../dev/reports/playwright_v8_coverage_report.txt | 39 +-
- .../playwright/tools/IdeaBoardTableNotes.spec.mjs | 118 +++-
- tests/playwright/tools/ToolboxRoutePages.spec.mjs | 5 +-
- 13 files changed, 941 insertions(+), 186 deletions(-)
+admin/system-health.html
+assets/theme-v2/js/admin-system-health.js
+docs_build/dev/reports/PR_26175_CHARLIE_009-system-health-current-r2-health.md
+docs_build/dev/reports/PR_26175_CHARLIE_010-system-health-history-and-closeout.md
+docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-branch-validation.md
+docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-manual-validation-notes.md
+docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-requirement-checklist.md
+docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-validation.md
+docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md
+docs_build/dev/reports/codex_changed_files.txt
+docs_build/dev/reports/codex_review.diff
+docs_build/dev/reports/coverage_changed_js_guardrail.txt
+docs_build/dev/reports/playwright_v8_coverage_report.txt
+src/api/admin-owner-navigation.js
+src/dev-runtime/server/local-api-router.mjs
+tests/dev-runtime/AdminHealthOperations.test.mjs
+tests/dev-runtime/ApiMenuPathCleanup.test.mjs
+tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs
+tests/playwright/tools/AdminHealthOperationsPage.spec.mjs
+tests/playwright/tools/AdminInvitationsNavPage.spec.mjs
+tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs
diff --git a/docs_build/dev/reports/codex_review.diff b/docs_build/dev/reports/codex_review.diff
index 360819abd..67ec1ada8 100644
--- a/docs_build/dev/reports/codex_review.diff
+++ b/docs_build/dev/reports/codex_review.diff
@@ -1,571 +1,1112 @@
-diff --git a/assets/toolbox/idea-board/js/index.js b/assets/toolbox/idea-board/js/index.js
-index 25607bc8d..0c10d2dc1 100644
---- a/assets/toolbox/idea-board/js/index.js
-+++ b/assets/toolbox/idea-board/js/index.js
-@@ -437,6 +437,7 @@ function ideaIdFromText(text) {
- }
-
- function saveIdeaRow(root, row) {
-+ if (!requireAuthenticatedWrite(root)) return;
- const idea = row.querySelector("[data-idea-board-idea-input]")?.value.trim();
- const pitch = row.querySelector("[data-idea-board-pitch-input]")?.value.trim();
- const status = row.querySelector("[data-idea-board-idea-status-input]")?.value;
-@@ -479,6 +480,7 @@ function saveIdeaRow(root, row) {
- }
-
- function saveNoteRow(root, row) {
-+ if (!requireAuthenticatedWrite(root)) return;
- const ideaId = row.dataset.ideaId;
- const idea = ideaRecord(ideaId);
- if (idea && isLockedIdea(idea)) {
-@@ -533,6 +535,7 @@ function toggleNotes(root, ideaId) {
- }
-
- function deleteIdea(root, ideaId) {
-+ if (!requireAuthenticatedWrite(root)) return;
- const index = ideaTable.findIndex((record) => record.ideaId === ideaId);
- if (index < 0) {
- updateStatus(root, "Idea Board could not delete that idea.");
-@@ -588,6 +591,20 @@ function currentSessionState() {
- }
- }
-
-+function requireAuthenticatedWrite(root) {
-+ const sessionState = currentSessionState();
-+ if (!sessionState.apiAvailable) {
-+ updateStatus(root, "API session status could not be verified. Try again shortly.");
-+ return false;
-+ }
-+ if (!sessionState.authenticated) {
-+ updateStatus(root, "Sign in before saving Idea Board changes.");
-+ window.location.href = signInUrl();
-+ return false;
-+ }
-+ return true;
-+}
+diff --git a/admin/system-health.html b/admin/system-health.html
+index b4b9f477f..8573b3310 100644
+--- a/admin/system-health.html
++++ b/admin/system-health.html
+@@ -43,6 +43,7 @@
+ Local API Startup
+ Database Health
+ Storage Health
++ Health Check History
+ Runtime Environment
+ Limits & Capacity
+ Diagnostics Plan
+@@ -143,11 +144,29 @@
+
+
+
+- | Bucket | Configured bucket placeholder | PENDING |
+- | List | Objects prefix | PENDING |
+- | Read | Health object | PENDING |
+- | Write | Health object | PENDING |
+- | Delete | Health object | PENDING |
++ | Bucket connectivity | Loading | PENDING |
++ | List | Loading | PENDING |
++ | Upload | Loading | PENDING |
++ | Read | Loading | PENDING |
++ | Delete | Loading | PENDING |
++ | Last checked | Loading | PENDING |
++
++
++
++
++
++ Health Check History
++
++
++ | Time |
++ Environment |
++ Area |
++ Result |
++ Summary |
++
++
++
++ | Loading | Loading | Current environment | PENDING | Waiting for safe API status. |
+
+
+
+diff --git a/assets/theme-v2/js/admin-system-health.js b/assets/theme-v2/js/admin-system-health.js
+index 61b446a3e..e0c2cab9f 100644
+--- a/assets/theme-v2/js/admin-system-health.js
++++ b/assets/theme-v2/js/admin-system-health.js
+@@ -9,8 +9,9 @@ import {
+ } from "../../js/shared/status.js";
+
+ const STORAGE_DIAGNOSTIC_ACTIONS = Object.freeze([
++ Object.freeze({ actionId: "storage-bucket-connectivity", key: "bucket" }),
+ Object.freeze({ actionId: "storage-list", key: "list" }),
+- Object.freeze({ actionId: "storage-write-test-object", key: "write" }),
++ Object.freeze({ actionId: "storage-upload-test-object", key: "upload" }),
+ Object.freeze({ actionId: "storage-read-test-object", key: "read" }),
+ Object.freeze({ actionId: "storage-delete-test-object", key: "delete" }),
+ ]);
+@@ -46,6 +47,7 @@ class AdminSystemHealthController {
+ node.dataset.adminSystemHealthStorageStatus,
+ node,
+ ]));
++ this.historyRows = root.querySelector("[data-admin-system-health-history-rows]");
+ this.startupRows = root.querySelector("[data-admin-system-health-startup-rows]");
+ this.runtimeRows = root.querySelector("[data-admin-system-health-runtime-rows]");
+ }
+@@ -106,6 +108,7 @@ class AdminSystemHealthController {
+ });
+ this.renderStartupPending(reason);
+ this.renderStoragePending(reason);
++ this.renderHistoryPending(reason);
+ }
+
+ renderEnvironmentIdentity(environmentIdentity = {}) {
+@@ -127,7 +130,7 @@ class AdminSystemHealthController {
+ }
+
+ renderStoragePending(reason) {
+- ["bucket", "list", "read", "write", "delete"].forEach((key) => {
++ ["bucket", "list", "upload", "read", "delete", "lastChecked"].forEach((key) => {
+ this.setStorageStatus(key, "PENDING", reason);
+ });
+ this.renderRuntimePending(reason);
+@@ -153,8 +156,10 @@ class AdminSystemHealthController {
+
+ renderStorageStatus(storageStatus = {}) {
+ const reason = storageStatus.message || "Cloudflare R2 configuration status returned by the safe Admin System Health API.";
+- this.setStorageValue("bucket", storageStatus.bucket, "not configured");
++ this.setStorageValue("bucket", storageStatus.environmentFolder ? `${storageStatus.bucket || "not configured"} ${storageStatus.environmentFolder}` : storageStatus.bucket, "not configured");
+ this.setStorageStatus("bucket", storageStatus.bucketStatus || storageStatus.status, reason);
++ this.setStorageValue("lastChecked", storageStatus.lastChecked, "not available");
++ this.setStorageStatus("lastChecked", storageStatus.lastChecked ? "PASS" : "WARN", reason);
+ }
+
+ renderStartupPending(reason) {
+@@ -198,9 +203,12 @@ class AdminSystemHealthController {
+
+ storageResultTarget(result = {}) {
+ if (typeof result.keysListed === "number" && result.actionId === "storage-list") {
+- return `${result.keysListed} object(s) under ${asText(result.projectsPrefix, "configured prefix")}`;
++ return `${result.keysListed} object(s) under ${asText(result.environmentFolder, "current environment folder")}`;
+ }
+- return result.testObjectKey || result.projectsPrefix || result.message || "diagnostic target unavailable";
++ if (result.actionId === "storage-bucket-connectivity") {
++ return result.environmentFolder || result.message || "bucket connectivity target unavailable";
++ }
++ return result.testObjectKey || result.environmentFolder || result.message || "diagnostic target unavailable";
+ }
+
+ renderStorageResult(key, result = {}) {
+@@ -210,6 +218,49 @@ class AdminSystemHealthController {
+ }
+ this.setStorageValue(key, this.storageResultTarget(result));
+ this.setStorageStatus(key, result.status, result.message || "R2 diagnostic returned without a message.");
++ if (result.lastChecked) {
++ this.setStorageValue("lastChecked", result.lastChecked);
++ this.setStorageStatus("lastChecked", "PASS", "Most recent current-environment R2 health check timestamp.");
++ }
++ }
+
- function createProject(root, ideaId) {
- const record = ideaRecord(ideaId);
- if (!record) {
-@@ -598,16 +615,7 @@ function createProject(root, ideaId) {
- updateStatus(root, "Set this idea to Ready before creating a project.");
- return;
- }
-- const sessionState = currentSessionState();
-- if (!sessionState.apiAvailable) {
-- updateStatus(root, "Sign-in status could not be verified. Try again shortly.");
-- return;
-- }
-- if (!sessionState.authenticated) {
-- updateStatus(root, "Sign in to create a Game Hub project.");
-- window.location.href = signInUrl();
-- return;
-- }
-+ if (!requireAuthenticatedWrite(root)) return;
- const repository = gameHubProjectRepository();
- const project = repository.createGame({
- name: record.idea,
-@@ -638,6 +646,7 @@ function archiveIdea(root, ideaId) {
- updateStatus(root, "Idea Board could not archive that idea.");
- return;
- }
-+ if (!requireAuthenticatedWrite(root)) return;
- if (record.status !== "Archived") record.previousStatus = record.status;
- record.status = "Archived";
- record.updated = today();
-@@ -657,6 +666,7 @@ function restoreIdea(root, ideaId) {
- updateStatus(root, "Idea Board could not restore that idea.");
- return;
- }
-+ if (!requireAuthenticatedWrite(root)) return;
- record.status = previousStatusForRestore(record);
- record.previousStatus = record.status;
- record.updated = today();
-@@ -742,6 +752,7 @@ function handleNoteAction(root, actionControl) {
- updateStatus(root, "Editing note.");
- render(root);
- } else if (action === "delete") {
-+ if (!requireAuthenticatedWrite(root)) return;
- const index = noteTable.findIndex((note) => note.noteId === noteId && note.ideaId === ideaId && !note.system);
- if (index >= 0) {
- noteTable.splice(index, 1);
-diff --git a/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_branch-validation.md b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_branch-validation.md
++ renderHistoryPending(reason) {
++ if (!this.historyRows) {
++ return;
++ }
++ const row = document.createElement("tr");
++ row.append(
++ this.createCell("not available"),
++ this.createCell("current environment"),
++ this.createCell("Health Check History"),
++ this.createStatusCell("PENDING", reason),
++ this.createCell("Safe health check history is not available."),
++ );
++ this.historyRows.replaceChildren(row);
++ }
++
++ renderHealthCheckHistory(historyRows = []) {
++ if (!this.historyRows) {
++ return;
++ }
++ const rows = Array.isArray(historyRows) ? historyRows : [];
++ if (!rows.length) {
++ this.renderHistoryPending("Safe Admin System Health API returned no current-environment health check history rows.");
++ return;
++ }
++ const fragment = document.createDocumentFragment();
++ rows.forEach((historyRow) => {
++ const row = document.createElement("tr");
++ row.append(
++ this.createCell(historyRow.checkedAt),
++ this.createCell(historyRow.environmentName),
++ this.createCell(historyRow.area),
++ this.createStatusCell(historyRow.result || historyRow.status, historyRow.summary),
++ this.createCell(historyRow.summary),
++ );
++ fragment.append(row);
++ });
++ this.historyRows.replaceChildren(fragment);
+ }
+
+ runStorageDiagnostics() {
+@@ -292,6 +343,7 @@ class AdminSystemHealthController {
+ this.renderStartupDiagnostics(data?.localApiStartup || {});
+ this.renderStorageStatus(data?.storageStatus || {});
+ this.runStorageDiagnostics();
++ this.renderHealthCheckHistory(data?.healthCheckHistory || []);
+ this.renderRuntimeEnvironment(data?.runtimeEnvironment || {});
+ } catch (error) {
+ const message = error instanceof Error ? error.message : "Safe Admin System Health API is unavailable.";
+diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_009-system-health-current-r2-health.md b/docs_build/dev/reports/PR_26175_CHARLIE_009-system-health-current-r2-health.md
new file mode 100644
-index 000000000..3e0239894
+index 000000000..a0cd45bc9
--- /dev/null
-+++ b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_branch-validation.md
-@@ -0,0 +1,22 @@
-+# PR_26175_BRAVO_011 Branch Validation
++++ b/docs_build/dev/reports/PR_26175_CHARLIE_009-system-health-current-r2-health.md
+@@ -0,0 +1,41 @@
++# PR_26175_CHARLIE_009 System Health Current R2 Health
++
++## Scope
++
++Team: Charlie
++
++Purpose: Add current-environment Cloudflare R2 folder health only to Admin System Health.
++
++## Changes
+
-+Date: 2026-06-24
++- Replaced the System Health Storage Health rows with current-environment R2 checks:
++ - bucket connectivity
++ - list
++ - upload
++ - read
++ - delete
++ - last checked
++- System Health storage diagnostics run against the current environment folder only:
++ - Local: `/local`
++ - DEV: `/dev`
++ - IST: `/ist`
++ - UAT: `/uat`
++ - PRD: `/prd`
++- Preserved the separate Admin Infrastructure storage diagnostic path that uses the configured project prefix.
++- Updated focused API and Playwright tests.
+
-+## Branch Gate
++## Architecture Constraint
+
-+- PASS: Current branch was verified as `main` before planning and implementation.
-+- PASS: Worktree was verified clean before the PR branch was created.
-+- PASS: `origin/main` was pulled/rebased before the PR branch was created.
-+- PASS: `HEAD`, `main`, and `origin/main` were synced at `dd7a3732e4225e42fe1033d37090abe179e6d5a5`.
-+- PASS: Work moved to scoped branch `pr/26175-BRAVO-011-idea-board-guest-save-auth-redirect`.
++PASS. R2 health checks target only the current deployment environment folder. No peer environment R2 folders are actively checked by System Health.
+
-+## Current State Before Commit
++## Validation
+
-+- Branch: `pr/26175-BRAVO-011-idea-board-guest-save-auth-redirect`
-+- Base commit: `dd7a3732e4225e42fe1033d37090abe179e6d5a5`
-+- Origin/main sync before edits: `0/0`
-+- Worktree: dirty with intended PR files and required reports.
++- PASS: `node --check src/dev-runtime/server/local-api-router.mjs`
++- PASS: `node --check assets/theme-v2/js/admin-system-health.js`
++- PASS: `git diff --check`
++- PASS: `node --test tests/dev-runtime/AdminHealthOperations.test.mjs`
++- PASS: `npx playwright test tests/playwright/tools/AdminHealthOperationsPage.spec.mjs --workers=1 --reporter=line`
+
-+## Result
++## Artifact
+
-+PASS: Branch and clean-worktree gates passed before implementation. Current dirty state is expected PR output before commit.
-diff --git a/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_instruction-compliance.md b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_instruction-compliance.md
++- `tmp/PR_26175_CHARLIE_009-system-health-current-r2-health_delta.zip`
+diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_010-system-health-history-and-closeout.md b/docs_build/dev/reports/PR_26175_CHARLIE_010-system-health-history-and-closeout.md
new file mode 100644
-index 000000000..11c593d22
+index 000000000..c8f5ff396
--- /dev/null
-+++ b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_instruction-compliance.md
-@@ -0,0 +1,31 @@
-+# PR_26175_BRAVO_011 Instruction Compliance
++++ b/docs_build/dev/reports/PR_26175_CHARLIE_010-system-health-history-and-closeout.md
+@@ -0,0 +1,68 @@
++# PR_26175_CHARLIE_010 System Health History and Closeout
+
-+Date: 2026-06-24
++## Scope
+
-+## Governance
++Team: Charlie
++
++Purpose: Add current-environment Health Check History and close out the System Health stacked expansion chain.
++
++## Chain
++
++- `PR_26175_CHARLIE_006-project-instructions-system-health-infrastructure`
++ - Branch: `PR_26175_CHARLIE_006-project-instructions-system-health-infrastructure`
++ - Commit: `c870b812faded383094fb13fc60ae9cfc7f14889`
++ - Result: pushed to origin, not merged.
++- `PR_26175_CHARLIE_007-system-health-environment-identity`
++ - Branch: `pr/26175-CHARLIE-007-system-health-environment-identity`
++ - Commit: `6556e73efcd8ae13b51b56288416c88688e67634`
++ - Draft PR: https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/151
++- `PR_26175_CHARLIE_008-system-health-current-database-health`
++ - Branch: `pr/26175-CHARLIE-008-system-health-current-database-health`
++ - Commit: `2603aeb6e5a7ccca516051953cbd70a5a6c94c4b`
++ - Draft PR: https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/152
++- `PR_26175_CHARLIE_009-system-health-current-r2-health`
++ - Branch: `pr/26175-CHARLIE-009-system-health-current-r2-health`
++ - Commit: `9740705fbe73dffd43744ab66338f8e4a925eed4`
++ - Draft PR: https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/153
++- `PR_26175_CHARLIE_010-system-health-history-and-closeout`
++ - Branch: `pr/26175-CHARLIE-010-system-health-history-and-closeout`
++ - Commit and draft PR URL are assigned after this report is committed and pushed.
++
++## Changes
+
-+- PASS: Read ProjectInstructions before implementation.
-+- PASS: Initial branch was `main`; implementation did not begin until after the main-branch gate passed.
-+- PASS: Initial worktree was clean before implementation.
-+- PASS: Scope remained limited to Idea Board auth gating, impacted tests, and required reports.
-+- PASS: No engine core files modified.
-+- PASS: No `start_of_day` files modified.
-+- PASS: No `imageDataUrl` contract usage introduced.
-+- PASS: No runtime code outside the Idea Board save/auth path was changed.
++- Added Health Check History to the Admin System Health page.
++- Health Check History is derived from the current deployment only:
++ - Environment Summary
++ - Database Health
++ - Storage Health
++ - Runtime Health
++- Warning and failure rows are generated only from current-environment health rows.
++- Creator sessions remain blocked from Admin System Health and do not trigger status or storage health requests.
+
-+## Frontend / Runtime Rules
++## Governance
+
-+- PASS: No inline runtime script/style/event handlers added.
-+- PASS: No browser-owned product-data SSoT added.
-+- PASS: No localStorage/sessionStorage product-data persistence added.
-+- PASS: Existing API/session terminology and helpers were used.
++- PASS: System Health is one page per deployed environment.
++- PASS: Each deployment actively checks only itself.
++- PASS: The Environment Map remains a static reference for Local, DEV, IST, UAT, and PRD.
++- PASS: System Health does not actively check peer databases or peer R2 folders.
++- PASS: Cancelled initiatives remain not doing:
++ - Environment Isolation & Developer Experience
++ - multi-port workspace framework
++ - Alpha/Beta/User runtime separation
++ - runtime port management initiative
+
-+## Reporting / Packaging
++## Validation
+
-+- PASS: Required PR reports created.
-+- PASS: V8 coverage reports refreshed after Playwright route coverage.
-+- PASS: `codex_review.diff`, `codex_changed_files.txt`, and repo-structured ZIP are generated for this run.
++- PASS: `node --check src/dev-runtime/server/local-api-router.mjs`
++- PASS: `node --check assets/theme-v2/js/admin-system-health.js`
++- PASS: `git diff --check`
++- PASS: `node --test tests/dev-runtime/AdminHealthOperations.test.mjs`
++- PASS: `node --test tests/dev-runtime/PublicEnvironmentConfig.test.mjs`
++- PASS: `npx playwright test tests/playwright/tools/AdminHealthOperationsPage.spec.mjs --workers=1 --reporter=line`
+
-+## ZIP
++## Artifacts
+
-+- `tmp/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_delta.zip`
-diff --git a/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_manual-validation-notes.md b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_manual-validation-notes.md
++- `tmp/PR_26175_CHARLIE_007-system-health-environment-identity_delta.zip`
++- `tmp/PR_26175_CHARLIE_008-system-health-current-database-health_delta.zip`
++- `tmp/PR_26175_CHARLIE_009-system-health-current-r2-health_delta.zip`
++- `tmp/PR_26175_CHARLIE_010-system-health-history-and-closeout_delta.zip`
+diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-branch-validation.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-branch-validation.md
new file mode 100644
-index 000000000..03f98b044
+index 000000000..e2d3a2b30
--- /dev/null
-+++ b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_manual-validation-notes.md
-@@ -0,0 +1,37 @@
-+# PR_26175_BRAVO_011 Manual Validation Notes
-+
-+Date: 2026-06-24
-+
-+## Reviewed Runtime Paths
-+
-+- `toolbox/idea-board/index.html`
-+- `assets/toolbox/idea-board/js/index.js`
-+- `src/api/session-api-client.js`
-+- `src/api/server-api-client.js`
-+- Sign-in route usage: `account/sign-in.html`
-+
-+## Persist Actions Verified
-+
-+- Add idea save: guest redirects before save.
-+- Edit idea save: guest redirects before update.
-+- Delete idea: guest redirects before delete.
-+- Add note save: guest redirects before save.
-+- Edit note save: guest redirects before update.
-+- Delete note: guest redirects before delete.
-+- Create project: guest redirects before `createGame`.
-+- Archive project idea: guest redirects before archive mutation.
-+- Restore archived project idea: guest redirects before restore mutation.
-+
-+## Browse Actions Verified
-+
-+- Guest can load the Idea Board.
-+- Guest can expand existing idea notes.
-+- Guest remains on `toolbox/idea-board/index.html` while browsing.
-+
-+## Data Safety Notes
-+
-+- No production data was modified.
-+- No migration or database write was executed outside Playwright local test servers.
-+- No browser product-data SSoT was added.
-+- No `localStorage` or `sessionStorage` product-data persistence was added.
-+- No fake login or silent fallback was added.
-diff --git a/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_report.md b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_report.md
++++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-branch-validation.md
+@@ -0,0 +1,15 @@
++# PR_26175_CHARLIE_011 Branch Validation
++
++## Start Gate
++
++- PASS: Current branch was `pr/26175-CHARLIE-010-system-health-history-and-closeout`.
++- PASS: Worktree was clean before implementation.
++- PASS: Build remained on the current Charlie continuation branch.
++- PASS: No rebase was performed.
++- PASS: No new root branch was created.
++
++## Final Branch Target
++
++- Branch to push: `pr/26175-CHARLIE-010-system-health-history-and-closeout`
++- Expected draft PR to update: https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/155
++- Merge status: no merge requested or performed.
+diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-manual-validation-notes.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-manual-validation-notes.md
new file mode 100644
-index 000000000..498138c5c
+index 000000000..e8b6eae26
--- /dev/null
-+++ b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_report.md
-@@ -0,0 +1,51 @@
-+# PR_26175_BRAVO_011 Idea Board Guest Save Auth Redirect
++++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-manual-validation-notes.md
+@@ -0,0 +1,26 @@
++# PR_26175_CHARLIE_011 Manual Validation Notes
+
-+Date: 2026-06-24
++## Admin Submenu Order
+
-+## Scope
++Visible labels after the change:
+
-+Require an authenticated API session before Idea Board save or persist actions. Guests may still browse the Idea Board, expand rows, and inspect notes. Guests are redirected to `account/sign-in.html` before any save/persist mutation.
++`Admin Tools`, `Analytics`, `Controls`, `Creators`, `DB Viewer`, `Environments`, `Game Migration`, `Infrastructure`, `Invites`, `Moderation`, `Operations`, `Platform Settings`, `Ratings`, `Responsibilities`, `Site Setup`, `System Health`, `Tool Votes`
+
-+## Review Findings
++## Route Preservation
+
-+- PASS: ProjectInstructions and governance documents were reviewed before implementation.
-+- PASS: Initial branch was `main`, worktree was clean, and `main`/`origin/main` were synced at `dd7a3732e4225e42fe1033d37090abe179e6d5a5` before the PR branch was created.
-+- PASS: `toolbox/idea-board/index.html` delegates runtime behavior to `assets/toolbox/idea-board/js/index.js`.
-+- PASS: Existing auth/session helper is `getSessionCurrent()` from `src/api/session-api-client.js`, backed by the API session contract.
-+- PASS: Existing sign-in route pattern uses `account/sign-in.html`.
-+- PASS: Persisting Idea Board actions identified: idea save, idea delete, note save, note delete, create project, archive, and restore.
-+- PASS: Browse-only actions identified: loading the board, expanding/collapsing notes, filtering, starting/canceling edit rows, and opening existing project links.
++The only source navigation reorder moved this existing item:
+
-+## Implementation Summary
++- `Creators`
++ - path remained `admin/users.html`
++ - route remained `admin-users`
++ - label remained `Creators`
+
-+- Added one shared Idea Board write guard, `requireAuthenticatedWrite(root)`, using the existing API session helper.
-+- Applied the guard before every Idea Board mutation/write path: idea save, note save, idea delete, note delete, create project, archive, and restore.
-+- Preserved guest browsing by leaving load, filter, expand/collapse, and non-persist UI actions unauthenticated.
-+- Expanded Playwright coverage so guest add/edit/delete idea, add/edit/delete note, create project, archive, and restore actions redirect to sign-in before writes.
-+- Kept the implementation on the existing API contract; no browser product-data SSoT, fake login, localStorage/sessionStorage product data, or environment-specific branch was introduced.
++All other Admin navigation objects remained unchanged.
+
-+## Affected Files
++## Open-Page Check
+
-+- `assets/toolbox/idea-board/js/index.js`
-+- `tests/playwright/tools/IdeaBoardTableNotes.spec.mjs`
-+- `tests/playwright/tools/ToolboxRoutePages.spec.mjs`
-+- `docs_build/dev/reports/playwright_v8_coverage_report.txt`
-+- `docs_build/dev/reports/coverage_changed_js_guardrail.txt`
++The targeted Playwright navigation test collected every active Admin submenu href from the rendered submenu and requested each page through the local test server. Every response returned a status below HTTP 400.
+
-+## Validation Summary
++## Duplicate Check
++
++The targeted Playwright navigation test checks for duplicate rendered labels and duplicate active hrefs. The targeted unit script also checks duplicate labels and existing active paths.
+diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-requirement-checklist.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-requirement-checklist.md
+new file mode 100644
+index 000000000..39afb7966
+--- /dev/null
++++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-requirement-checklist.md
+@@ -0,0 +1,42 @@
++# PR_26175_CHARLIE_011 Requirement Checklist
++
++## Branch Rules
++
++- PASS: Continued on `pr/26175-CHARLIE-010-system-health-history-and-closeout`.
++- PASS: Did not return to `main`.
++- PASS: Did not rebase.
++- PASS: Did not create a new root branch.
++- PASS: Hard stop conditions were checked before implementation.
+
-+- PASS: Targeted node guardrail passed.
-+- PASS: Runtime grep found no `localStorage` or `sessionStorage` use in Idea Board runtime HTML/JS.
-+- PASS: Runtime grep found no inline script/style/event-handler additions in Idea Board runtime HTML/JS.
-+- PASS: Focused Playwright guest redirect test passed.
-+- PASS: Focused Playwright Toolbox-to-Idea-Board launch test passed after filtering unrelated selected-game status polling from the no-write assertion.
-+- PASS: Playwright V8 coverage report includes `assets/toolbox/idea-board/js/index.js`.
-+- WARN: Bundled Playwright Chromium was missing and `npx playwright install chromium` stalled with a partial install; focused browser validation used installed Google Chrome through a temporary config that was removed after validation.
-+- WARN: Full legacy Playwright files still have unrelated expectation drift documented in the validation lane report.
++## Objective
+
-+## Recommended Next PR
++- PASS: Admin submenu entries are alphabetized by displayed text.
+
-+Create a follow-up validation cleanup PR for existing Toolbox/Game Hub drift:
++## Scope
++
++- PASS: Located Admin submenu definition in `src/api/admin-owner-navigation.js`.
++- PASS: Sorted submenu entries by displayed text.
++- PASS: Preserved routes, URLs, IDs, CSS classes, Theme V2 styling, and existing renderer behavior.
++- PASS: Did not rename pages.
++- PASS: Did not rename folders.
++- PASS: Did not modify page content.
++- PASS: No unrelated cleanup.
++
++## Validation
+
-+- Refresh `ToolboxRoutePages` expected tool counts, Game Hub route alias expectations, failed module-load assertions, and local dev port guard expectation.
-+- Refresh or repair the Game Hub expanded child-row summary expectation in `IdeaBoardTableNotes`.
-diff --git a/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_requirements-checklist.md b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_requirements-checklist.md
++- PASS: Verified submenu labels are alphabetical.
++- PASS: Verified every Admin page path exists and every Admin submenu href opens below HTTP 400 in targeted Playwright.
++- PASS: Verified no duplicate labels or hrefs.
++- PASS: Ran affected Playwright navigation tests.
++- PASS: Ran affected targeted unit tests.
++
++## Artifacts
++
++- PASS: `docs_build/dev/reports/codex_review.diff`
++- PASS: `docs_build/dev/reports/codex_changed_files.txt`
++- PASS: `docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md`
++- PASS: validation report
++- PASS: branch validation report
++- PASS: requirement checklist
++- PASS: manual validation notes
++- PASS: repository ZIP under `tmp/`
+diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-validation.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-validation.md
new file mode 100644
-index 000000000..4100a8b51
+index 000000000..aeec3f443
--- /dev/null
-+++ b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_requirements-checklist.md
-@@ -0,0 +1,19 @@
-+# PR_26175_BRAVO_011 Requirements Checklist
-+
-+Date: 2026-06-24
-+
-+| Requirement | Result | Evidence |
-+| --- | --- | --- |
-+| Guests may browse the Idea Board. | PASS | Playwright expands `top-thoughts` as a guest and remains on `toolbox/idea-board/index.html`. |
-+| Guests may not save creator-owned data. | PASS | Guest save/persist controls redirect before mutation. |
-+| Every save/persist action redirects unauthenticated users to `account/sign-in.html`. | PASS | Covered add/edit/delete idea, add/edit/delete note, create project, archive, and restore. |
-+| Redirect before any API write. | PASS | Guest create/archive/restore assertions reset and inspect create-game requests; no write request is sent before redirect. |
-+| All environments use the same API contract. | PASS | Uses existing `getSessionCurrent()` API session helper; no environment-specific branch added. |
-+| Do not introduce browser-owned product data. | PASS | No new browser persistence or product-data SSoT added. |
-+| Do not use localStorage/sessionStorage as product-data SSoT. | PASS | Runtime grep found no `localStorage` or `sessionStorage` in Idea Board runtime HTML/JS. |
-+| Do not introduce fake login behavior. | PASS | Runtime uses existing API session helper only; tests use repo test session endpoint. |
-+| No silent fallbacks. | PASS | API session verification failure blocks the write and reports status. |
-+| Use API terminology only. | PASS | New unavailable status uses API session terminology. |
-+| Keep PR limited to scope. | PASS | Runtime change is limited to Idea Board write gating; tests and reports cover the same scope. |
-+| Create required reports. | PASS | PR report, branch validation, requirement checklist, validation lane, manual notes, instruction compliance, review diff, changed files, and V8 coverage reports are included. |
-+| Create repo-structured ZIP under `tmp/`. | PASS | `tmp/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_delta.zip`. |
-diff --git a/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_validation-lane.md b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_validation-lane.md
++++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order-validation.md
+@@ -0,0 +1,22 @@
++# PR_26175_CHARLIE_011 Validation Report
++
++## Commands
++
++- PASS: `node --check src/api/admin-owner-navigation.js`
++- PASS: `node --input-type=module` alphabetical/duplicate/path verification script
++ - Result: `PASS labels=17 active=16`
++ - Order: `Admin Tools | Analytics | Controls | Creators | DB Viewer | Environments | Game Migration | Infrastructure | Invites | Moderation | Operations | Platform Settings | Ratings | Responsibilities | Site Setup | System Health | Tool Votes`
++- PASS: `git diff --check`
++ - Result: no whitespace errors; CRLF conversion warnings only.
++- PASS: `node --test tests/dev-runtime/ApiMenuPathCleanup.test.mjs`
++ - Result: 6 passed.
++- PASS: `node --test --test-name-pattern "Admin and Owner navigation are shared" tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs`
++ - Result: 1 passed.
++- PASS: `npx playwright test tests/playwright/tools/AdminOwnerNavigationBoundary.spec.mjs --workers=1 --reporter=line`
++ - Result: 4 passed.
++- PASS: `npx playwright test tests/playwright/tools/AdminInvitationsNavPage.spec.mjs --workers=1 --reporter=line`
++ - Result: 3 passed.
++
++## Note
++
++A non-targeted full-file run of `tests/dev-runtime/ArchitectureCleanupApiNavInvitations.test.mjs` was not used for final validation because its first non-navigation test fails on a pre-existing missing `src/engine/api` directory assertion. The affected navigation subtest passed by name.
+diff --git a/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md
new file mode 100644
-index 000000000..c7ffdfcc9
+index 000000000..7dcbe5262
--- /dev/null
-+++ b/docs_build/dev/reports/PR_26175_BRAVO_011-idea-board-guest-save-auth-redirect_validation-lane.md
-@@ -0,0 +1,36 @@
-+# PR_26175_BRAVO_011 Validation Lane
++++ b/docs_build/dev/reports/PR_26175_CHARLIE_011-admin-submenu-alphabetical-order.md
+@@ -0,0 +1,47 @@
++# PR_26175_CHARLIE_011 Admin Submenu Alphabetical Order
++
++## Scope
+
-+Date: 2026-06-24
++Team: Charlie
+
-+## Commands
++Purpose: Alphabetize the Admin submenu by visible menu labels only.
++
++## Branch
+
-+| Command | Result | Notes |
-+| --- | --- | --- |
-+| `git diff --check` | PASS | CRLF warnings only for touched Playwright specs. |
-+| `rg -n "localStorage|sessionStorage" assets/toolbox/idea-board/js/index.js toolbox/idea-board/index.html` | PASS | No runtime matches. |
-+| `rg -n "