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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 33 additions & 10 deletions admin/system-health.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ <h2>Admin</h2>
<details class="vertical-accordion" open>
<summary>Health Sections</summary>
<div class="accordion-body content-stack">
<p>Environment Summary</p>
<p>Environment Identity</p>
<p>Environment Map</p>
<p>Local API Startup</p>
<p>Database Health</p>
<p>Storage Health</p>
Expand All @@ -57,21 +58,43 @@ <h2>Admin</h2>
<h2 id="admin-system-health-title">System Health Tables</h2>
</div>
<div class="table-wrapper">
<table class="data-table" aria-label="Environment summary">
<caption>Environment Summary</caption>
<table class="data-table" aria-label="Environment identity">
<caption>Environment Identity</caption>
<thead>
<tr>
<th scope="col">Environment</th>
<th scope="col">Purpose</th>
<th scope="col">Promotion Gate</th>
<th scope="col">Field</th>
<th scope="col">Current Deployment</th>
<th scope="col">Status</th>
</tr>
</thead>
<tbody>
<tr><td>DEV</td><td>Local implementation and diagnostics</td><td>Developer validation</td><td data-health-status="PASS">PASS</td></tr>
<tr><td>IST</td><td>Integrated system testing</td><td>Cross-feature validation</td><td data-health-status="PASS">PASS</td></tr>
<tr><td>UAT</td><td>User acceptance testing</td><td>Owner review</td><td data-health-status="PASS">PASS</td></tr>
<tr><td>PRD</td><td>Production runtime</td><td>EOD approval</td><td data-health-status="PASS">PASS</td></tr>
<tr><td>Environment name</td><td data-admin-system-health-environment-value="name">Loading</td><td data-health-status="PENDING" data-admin-system-health-environment-status="name" title="Reason: current environment identity has not loaded yet." aria-label="PENDING: current environment identity has not loaded yet.">PENDING</td></tr>
<tr><td>Hosting model</td><td data-admin-system-health-environment-value="hostingModel">Loading</td><td data-health-status="PENDING" data-admin-system-health-environment-status="hostingModel" title="Reason: current environment identity has not loaded yet." aria-label="PENDING: current environment identity has not loaded yet.">PENDING</td></tr>
<tr><td>Site URL</td><td data-admin-system-health-environment-value="siteUrl">Loading</td><td data-health-status="PENDING" data-admin-system-health-environment-status="siteUrl" title="Reason: current environment identity has not loaded yet." aria-label="PENDING: current environment identity has not loaded yet.">PENDING</td></tr>
<tr><td>API URL</td><td data-admin-system-health-environment-value="apiUrl">Loading</td><td data-health-status="PENDING" data-admin-system-health-environment-status="apiUrl" title="Reason: current environment identity has not loaded yet." aria-label="PENDING: current environment identity has not loaded yet.">PENDING</td></tr>
<tr><td>Database model</td><td data-admin-system-health-environment-value="databaseModel">Loading</td><td data-health-status="PENDING" data-admin-system-health-environment-status="databaseModel" title="Reason: current environment identity has not loaded yet." aria-label="PENDING: current environment identity has not loaded yet.">PENDING</td></tr>
<tr><td>Storage folder</td><td data-admin-system-health-environment-value="storageFolder">Loading</td><td data-health-status="PENDING" data-admin-system-health-environment-status="storageFolder" title="Reason: current environment identity has not loaded yet." aria-label="PENDING: current environment identity has not loaded yet.">PENDING</td></tr>
<tr><td>Last health check</td><td data-admin-system-health-environment-value="lastHealthCheck">Loading</td><td data-health-status="PENDING" data-admin-system-health-environment-status="lastHealthCheck" title="Reason: current environment identity has not loaded yet." aria-label="PENDING: current environment identity has not loaded yet.">PENDING</td></tr>
</tbody>
</table>
</div>
<div class="table-wrapper">
<table class="data-table" aria-label="Environment map">
<caption>Environment Map</caption>
<thead>
<tr>
<th scope="col">Environment</th>
<th scope="col">Hosting model</th>
<th scope="col">Database model</th>
<th scope="col">Storage folder</th>
</tr>
</thead>
<tbody>
<tr><td>Local</td><td>VS Code + Local API</td><td>Local Docker PostgreSQL</td><td>/local</td></tr>
<tr><td>DEV</td><td>Local Docker</td><td>Local Docker PostgreSQL</td><td>/dev</td></tr>
<tr><td>IST</td><td>Local Docker</td><td>Local Docker PostgreSQL</td><td>/ist</td></tr>
<tr><td>UAT</td><td>Cloudflare</td><td>Supabase PostgreSQL</td><td>/uat</td></tr>
<tr><td>PRD</td><td>Cloudflare</td><td>Supabase PostgreSQL</td><td>/prd</td></tr>
</tbody>
</table>
</div>
Expand Down
44 changes: 43 additions & 1 deletion assets/theme-v2/js/admin-system-health.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ function asText(value, fallback = "not available") {
class AdminSystemHealthController {
constructor(root) {
this.root = root;
this.environmentValues = new Map(Array.from(root.querySelectorAll("[data-admin-system-health-environment-value]")).map((node) => [
node.dataset.adminSystemHealthEnvironmentValue,
node,
]));
this.environmentStatuses = new Map(Array.from(root.querySelectorAll("[data-admin-system-health-environment-status]")).map((node) => [
node.dataset.adminSystemHealthEnvironmentStatus,
node,
]));
this.dbValues = new Map(Array.from(root.querySelectorAll("[data-admin-system-health-db-value]")).map((node) => [
node.dataset.adminSystemHealthDbValue,
node,
Expand All @@ -43,7 +51,7 @@ class AdminSystemHealthController {
}

init() {
if ((!this.dbValues.size && !this.storageValues.size) || document.querySelector("[data-session-access-blocked='admin']") || window.GameFoundrySessionGuard?.blocked === true) {
if ((!this.environmentValues.size && !this.dbValues.size && !this.storageValues.size) || document.querySelector("[data-session-access-blocked='admin']") || window.GameFoundrySessionGuard?.blocked === true) {
return;
}
this.load();
Expand All @@ -56,6 +64,18 @@ class AdminSystemHealthController {
}
}

setEnvironmentValue(key, value, fallback) {
const node = this.environmentValues.get(key);
if (node) {
node.textContent = asText(value, fallback);
}
}

setEnvironmentStatus(key, status, reason = "") {
const node = this.environmentStatuses.get(key);
this.setStatusNode(node, status, reason);
}

setStorageValue(key, value, fallback) {
const node = this.storageValues.get(key);
if (node) {
Expand All @@ -78,13 +98,34 @@ class AdminSystemHealthController {
}

renderPending(reason) {
["name", "hostingModel", "siteUrl", "apiUrl", "databaseModel", "storageFolder", "lastHealthCheck"].forEach((key) => {
this.setEnvironmentStatus(key, "PENDING", reason);
});
["host", "database", "migration", "connection"].forEach((key) => {
this.setStatus(key, "PENDING", reason);
});
this.renderStartupPending(reason);
this.renderStoragePending(reason);
}

renderEnvironmentIdentity(environmentIdentity = {}) {
const reason = environmentIdentity.message || "Current deployment environment identity returned by the safe Admin System Health API.";
this.setEnvironmentValue("name", environmentIdentity.name, "Unknown");
this.setEnvironmentStatus("name", environmentIdentity.status, reason);
this.setEnvironmentValue("hostingModel", environmentIdentity.hostingModel, "not configured");
this.setEnvironmentStatus("hostingModel", environmentIdentity.hostingModel ? "PASS" : "WARN", reason);
this.setEnvironmentValue("siteUrl", environmentIdentity.siteUrl, "not configured");
this.setEnvironmentStatus("siteUrl", environmentIdentity.siteUrlStatus, reason);
this.setEnvironmentValue("apiUrl", environmentIdentity.apiUrl, "not configured");
this.setEnvironmentStatus("apiUrl", environmentIdentity.apiUrlStatus, reason);
this.setEnvironmentValue("databaseModel", environmentIdentity.databaseModel, "not configured");
this.setEnvironmentStatus("databaseModel", environmentIdentity.databaseModel ? "PASS" : "WARN", reason);
this.setEnvironmentValue("storageFolder", environmentIdentity.storageFolder, "not configured");
this.setEnvironmentStatus("storageFolder", environmentIdentity.storageFolderStatus, reason);
this.setEnvironmentValue("lastHealthCheck", environmentIdentity.lastHealthCheck, "not available");
this.setEnvironmentStatus("lastHealthCheck", environmentIdentity.lastHealthCheck ? "PASS" : "WARN", reason);
}

renderStoragePending(reason) {
["bucket", "list", "read", "write", "delete"].forEach((key) => {
this.setStorageStatus(key, "PENDING", reason);
Expand Down Expand Up @@ -250,6 +291,7 @@ class AdminSystemHealthController {
this.renderPending("Safe Admin System Health API refused to render because the response exposed secret controls.");
return;
}
this.renderEnvironmentIdentity(data?.environmentIdentity || {});
this.renderPostgresStatus(data?.databaseStatus || {});
this.renderStartupDiagnostics(data?.localApiStartup || {});
this.renderStorageStatus(data?.storageStatus || {});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# PR_26175_CHARLIE_007 System Health Environment Identity

## Scope

Team: Charlie

Purpose: Add current deployment environment identity to Admin System Health and keep the all-environment map as static reference only.

## Changes

- Added a server-owned current environment identity model for Local, DEV, IST, UAT, and PRD.
- Added current deployment fields for environment name, hosting model, site URL, API URL, database model, storage folder, and last health check.
- Replaced the active multi-environment summary table with a current deployment identity table.
- Added a static Environment Map for Local, DEV, IST, UAT, and PRD without health status fields.
- Updated focused API and Playwright tests.

## Architecture Constraint

PASS. System Health displays the current deployment environment only. The Environment Map is static reference content and does not actively health-check other environments.

## 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`

## Notes

GitHub CLI is unavailable in this workspace. Branch push uses local `git`; draft PR creation uses the GitHub connector when available, otherwise the manual compare URL is reported.
5 changes: 3 additions & 2 deletions docs_build/dev/reports/coverage_changed_js_guardrail.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Missing changed runtime JS files are WARN, not FAIL.
Source: Playwright/Chromium built-in V8 coverage from the active Playwright run.

Changed runtime JS files considered:
(100%) none changed - no changed runtime JS files
(0%) src/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
(89%) assets/theme-v2/js/admin-system-health.js - executed lines 288/288; executed functions 33/37

Guardrail warnings:
(100%) none changed - no changed runtime JS files
(0%) src/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file missing from coverage; advisory only
35 changes: 17 additions & 18 deletions docs_build/dev/reports/playwright_v8_coverage_report.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,31 @@ Note: entry percentages use function coverage when available, otherwise line cov
Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran.

Exercised tool entry points detected:
(69%) Toolbox Index - exercised 3 runtime JS files
(46%) Toolbox Index - exercised 1 runtime JS files
(0%) Tool Template V2 - not exercised by this Playwright run
(74%) Theme V2 Shared JS - exercised 3 runtime JS files
(78%) Theme V2 Shared JS - exercised 4 runtime JS files

Changed runtime JS files covered:
(100%) none changed - no changed runtime JS files
(0%) src/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
(89%) assets/theme-v2/js/admin-system-health.js - executed lines 288/288; executed functions 33/37

Files with executed line/function counts where available:
(8%) src/api/session-api-client.js - executed lines 68/68; executed functions 1/12
(17%) src/api/toolbox-votes-api-client.js - executed lines 46/46; executed functions 1/6
(25%) toolbox/game-hub/game-hub-api-client.js - executed lines 26/26; executed functions 1/4
(36%) src/shared/toolbox/tool-metadata-inventory.js - executed lines 2041/2041; executed functions 12/33
(50%) toolbox/tools-page-accordions.js - executed lines 1156/1156; executed functions 1/2
(59%) assets/toolbox/colors/js/index.js - executed lines 1859/1859; executed functions 122/207
(63%) src/api/server-api-client.js - executed lines 167/167; executed functions 12/19
(36%) src/api/server-api-client.js - executed lines 167/167; executed functions 5/14
(46%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 12/26
(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 204/204; executed functions 9/14
(65%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 1001/1001; executed functions 58/89
(65%) src/api/public-config-client.js - executed lines 209/209; executed functions 17/26
(67%) src/api/game-journey-completion-api-client.js - executed lines 15/15; executed functions 2/3
(76%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 22/29
(100%) assets/theme-v2/js/toolbox-status-bar.js - executed lines 398/398; executed functions 35/35
(74%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 1001/1001; executed functions 69/93
(80%) src/api/admin-owner-navigation.js - executed lines 42/42; executed functions 4/5
(83%) assets/js/shared/status.js - executed lines 37/37; executed functions 5/6
(89%) assets/theme-v2/js/admin-system-health.js - executed lines 288/288; executed functions 33/37
(91%) assets/theme-v2/js/admin-owner-navigation.js - executed lines 58/58; executed functions 10/11
(100%) src/api/admin-system-health-api-client.js - executed lines 19/19; executed functions 3/3

Uncovered or low-coverage changed JS files:
(100%) none changed - no changed runtime JS files
(0%) src/dev-runtime/server/local-api-router.mjs - WARNING: uncovered changed runtime JS file; advisory only

Changed JS files considered:
(0%) assets/toolbox/idea-board/js/index.js - changed JS file not collected as browser runtime coverage
(0%) tests/playwright/tools/IdeaBoardTableNotes.spec.mjs - changed JS file not collected as browser runtime coverage
(0%) tests/playwright/tools/ToolboxRoutePages.spec.mjs - changed JS file not collected as browser runtime coverage
(0%) src/dev-runtime/server/local-api-router.mjs - changed JS file not collected as browser runtime coverage
(0%) tests/dev-runtime/AdminHealthOperations.test.mjs - changed JS file not collected as browser runtime coverage
(0%) tests/playwright/tools/AdminHealthOperationsPage.spec.mjs - changed JS file not collected as browser runtime coverage
(89%) assets/theme-v2/js/admin-system-health.js - changed JS file with browser V8 coverage
Loading
Loading