Skip to content

Commit 61870d6

Browse files
committed
Remove static API fallbacks and require explicit local API diagnostics - PR_26158_032-remove-static-api-fallbacks
1 parent 96926ec commit 61870d6

8 files changed

Lines changed: 112 additions & 161 deletions

File tree

assets/theme-v2/js/gamefoundry-partials.js

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@
110110

111111
const currentScript = document.currentScript || document.querySelector("script[src*='gamefoundry-partials.js']");
112112
const assetRoot = currentScript ? new URL("../", currentScript.src) : null;
113-
const staticApiDiagnosticKey = "GameFoundryStaticApiUnavailableDiagnostic";
114113

115114
function assetUrl(path) {
116115
if (!assetRoot) return rootPrefix() + path;
@@ -143,14 +142,6 @@
143142
return "Local server API route unavailable for " + method + " " + url + " (" + status + "). Start the API-backed local server route instead of a static-only server.";
144143
}
145144

146-
function cachedStaticApiDiagnostic() {
147-
return String(window[staticApiDiagnosticKey] || "");
148-
}
149-
150-
function cacheStaticApiDiagnostic(message) {
151-
window[staticApiDiagnosticKey] = message;
152-
}
153-
154145
function missingSessionApiLoginState(diagnostic) {
155146
return {
156147
authenticated: false,
@@ -172,10 +163,6 @@
172163
}
173164

174165
function localDevLoginState() {
175-
const cachedDiagnostic = cachedStaticApiDiagnostic();
176-
if (cachedDiagnostic) {
177-
return missingSessionApiLoginState(cachedDiagnostic);
178-
}
179166
try {
180167
const request = new XMLHttpRequest();
181168
request.open("GET", "/api/session/current", false);
@@ -184,9 +171,7 @@
184171
const payload = request.responseText ? JSON.parse(request.responseText) : null;
185172
if (request.status < 200 || request.status >= 300 || payload?.ok === false) {
186173
if (request.status === 404 || request.status === 405) {
187-
const diagnostic = localRouteUnavailableDiagnostic("GET", "/api/session/current", request.status);
188-
cacheStaticApiDiagnostic(diagnostic);
189-
throw new Error(diagnostic);
174+
throw new Error(localRouteUnavailableDiagnostic("GET", "/api/session/current", request.status));
190175
}
191176
throw new Error(payload?.error || "Session API did not return a valid current session.");
192177
}
@@ -332,11 +317,10 @@
332317
const pagePath = currentPagePath() || "index.html";
333318
const requirement = protectedPageRequirement(pagePath);
334319
if (!requirement) {
335-
const diagnostic = cachedStaticApiDiagnostic();
336320
window.GameFoundrySessionGuard = {
337321
blocked: false,
338-
diagnostic,
339-
mode: diagnostic ? "missing-api" : "",
322+
diagnostic: "",
323+
mode: "",
340324
pagePath,
341325
requirement: ""
342326
};

assets/theme-v2/js/login-session.js

Lines changed: 5 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,6 @@ const modeStatus = document.querySelector("[data-login-mode-status]");
1313
const userControls = document.querySelector("[data-login-user-controls]");
1414
const userStatus = document.querySelector("[data-login-user-status]");
1515
const continueLink = document.querySelector("[data-login-continue]");
16-
const staticModeDetails = {
17-
"local-mem": {
18-
description: "Uses MockDbAdapter backed by in-memory lists when the API-backed local server is running.",
19-
diagnostic: "Static-only server detected. Local Mem selection remains available, but local users and persistence require the API-backed local server.",
20-
environment: "Local Mem",
21-
id: "local-mem",
22-
label: "Local Mem",
23-
persistence: "Memory",
24-
},
25-
"local-db": {
26-
description: "Uses LocalDbAdapter backed by server SQLite storage.",
27-
diagnostic: "Static-only server detected. Local DB requires the API-backed local server; start the local server API to use SQLite-backed Local DB.",
28-
environment: "Local DB",
29-
id: "local-db",
30-
label: "Local DB",
31-
persistence: "Local DB",
32-
},
33-
};
34-
let staticApiUnavailable = false;
35-
let staticModeId = "local-mem";
36-
let staticApiDiagnostic = "";
3716

3817
function currentReturnTo() {
3918
const params = new URLSearchParams(window.location.search);
@@ -116,55 +95,22 @@ function errorMessage(error) {
11695
return error instanceof Error ? error.message : String(error || "Session API unavailable.");
11796
}
11897

119-
function isStaticApiUnavailable(message) {
120-
return message.includes("Local server API route unavailable") ||
121-
message.includes("/api/session") && message.includes("(404)");
122-
}
123-
124-
function renderStaticApiUnavailable(modeId, error) {
125-
const mode = staticModeDetails[modeId] || staticModeDetails["local-mem"];
126-
staticApiUnavailable = true;
127-
staticModeId = mode.id;
128-
staticApiDiagnostic = errorMessage(error);
129-
renderModeButtons(mode);
130-
if (userControls) {
131-
userControls.replaceChildren();
132-
userControls.hidden = true;
133-
}
134-
if (modeTitle) {
135-
modeTitle.textContent = mode.label;
136-
}
137-
if (modeDescription) {
138-
modeDescription.textContent = mode.description;
139-
}
140-
if (modeStatus) {
141-
modeStatus.textContent = `Environment: ${mode.environment}. Persistence: ${mode.persistence}. Diagnostic: ${mode.diagnostic} ${staticApiDiagnostic}`;
142-
}
143-
if (userStatus) {
144-
userStatus.textContent = "No local users are available because the API-backed local server is unavailable.";
145-
}
146-
updateContinueLink();
147-
}
148-
14998
function renderError(error) {
15099
const message = errorMessage(error);
151-
if (isStaticApiUnavailable(message)) {
152-
renderStaticApiUnavailable(staticModeId, error);
153-
return;
154-
}
155100
modeButtons.forEach((button) => {
156-
button.disabled = false;
157-
button.removeAttribute("aria-disabled");
101+
button.disabled = true;
102+
button.setAttribute("aria-disabled", "true");
103+
setSelectedButton(button, false);
158104
});
159105
if (userControls) {
160106
userControls.replaceChildren();
161107
userControls.hidden = true;
162108
}
163109
if (modeTitle) {
164-
modeTitle.textContent = "Session API unavailable";
110+
modeTitle.textContent = "Session API required";
165111
}
166112
if (modeDescription) {
167-
modeDescription.textContent = "Start the local server API to select a session.";
113+
modeDescription.textContent = "Start the API-backed local server to choose Local Mem or Local DB.";
168114
}
169115
if (modeStatus) {
170116
modeStatus.textContent = `Login/session diagnostic: ${message}`;
@@ -178,7 +124,6 @@ function renderError(error) {
178124
function render() {
179125
try {
180126
const session = getSessionCurrent();
181-
staticApiUnavailable = false;
182127
const mode = getSessionModes().find((item) => item.id === session.mode) || {
183128
description: "",
184129
id: session.mode,
@@ -213,16 +158,11 @@ function render() {
213158
modeButtons.forEach((button) => {
214159
button.addEventListener("click", () => {
215160
const modeId = button.dataset.loginMode || "local-mem";
216-
if (staticApiUnavailable) {
217-
renderStaticApiUnavailable(modeId, staticApiDiagnostic);
218-
return;
219-
}
220161
try {
221162
setSessionMode(modeId);
222163
dispatchModeChanged();
223164
render();
224165
} catch (error) {
225-
staticModeId = modeId;
226166
renderError(error);
227167
}
228168
});

docs_build/dev/reports/coverage_changed_js_guardrail.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Missing changed runtime JS files are WARN, not FAIL.
66
Source: Playwright/Chromium built-in V8 coverage from the active Playwright run.
77

88
Changed runtime JS files considered:
9-
(55%) src/engine/api/server-api-client.js - executed lines 186/186; executed functions 12/22
9+
(53%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 10/19
1010

1111
Guardrail warnings:
1212
(100%) none - no changed runtime JS coverage warnings

docs_build/dev/reports/playwright_v8_coverage_report.txt

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,29 @@ Note: coverage entries are aggregated across every page/tool where coverageRepor
1414
Exercised tool entry points detected:
1515
(61%) Toolbox Index - exercised 3 runtime JS files
1616
(0%) Tool Template V2 - not exercised by this Playwright run
17-
(77%) Theme V2 Shared JS - exercised 3 runtime JS files
17+
(80%) Theme V2 Shared JS - exercised 3 runtime JS files
1818

1919
Changed runtime JS files covered:
20-
(55%) src/engine/api/server-api-client.js - executed lines 186/186; executed functions 12/22
20+
(53%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 10/19
2121

2222
Files with executed line/function counts where available:
23-
(55%) src/engine/api/server-api-client.js - executed lines 186/186; executed functions 12/22
23+
(53%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 10/19
2424
(55%) toolbox/project-journey/project-journey.js - executed lines 1003/1003; executed functions 54/99
2525
(60%) src/engine/api/mock-db-api-client.js - executed lines 19/19; executed functions 3/5
2626
(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 201/201; executed functions 9/14
2727
(67%) admin/db-viewer.js - executed lines 53/53; executed functions 4/6
28-
(79%) assets/theme-v2/js/login-session.js - executed lines 227/227; executed functions 15/19
29-
(80%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 448/448; executed functions 33/41
3028
(81%) toolbox/tool-registry-api-client.js - executed lines 148/148; executed functions 22/27
29+
(82%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 434/434; executed functions 32/39
3130
(85%) src/engine/api/mock-db-viewer-ui.js - executed lines 510/510; executed functions 82/96
31+
(88%) assets/theme-v2/js/login-session.js - executed lines 169/169; executed functions 15/17
3232
(88%) src/engine/api/session-api-client.js - executed lines 34/34; executed functions 7/8
3333
(100%) toolbox/project-journey/project-journey-api-client.js - executed lines 12/12; executed functions 2/2
3434

3535
Uncovered or low-coverage changed JS files:
3636
(100%) none - no low-coverage changed runtime JS files
3737

3838
Changed JS files considered:
39-
(0%) tests/helpers/browserExtensionNoise.mjs - changed JS file not collected as browser runtime coverage
40-
(0%) tests/playwright/tools/StaticOnlyLoginFallback.spec.mjs - changed JS file not collected as browser runtime coverage
41-
(55%) src/engine/api/server-api-client.js - changed JS file with browser V8 coverage
42-
(79%) assets/theme-v2/js/login-session.js - changed JS file with browser V8 coverage
43-
(80%) assets/theme-v2/js/gamefoundry-partials.js - changed JS file with browser V8 coverage
39+
(0%) tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs - changed JS file not collected as browser runtime coverage
40+
(53%) src/engine/api/server-api-client.js - changed JS file with browser V8 coverage
41+
(82%) assets/theme-v2/js/gamefoundry-partials.js - changed JS file with browser V8 coverage
42+
(88%) assets/theme-v2/js/login-session.js - changed JS file with browser V8 coverage
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# PR_26158_032 Remove Static API Fallbacks Report
2+
3+
## Executive Summary
4+
5+
Removed the PR_030/PR_031 static-only login fallback. A missing `/api/session/current` now leaves login/session mode unavailable with a visible API-required diagnostic instead of presenting Local Mem or Local DB as usable choices.
6+
7+
API-backed Local Mem and SQLite-backed Local DB behavior remains intact behind the server API boundary.
8+
9+
## Implementation
10+
11+
| Area | Change | Evidence |
12+
| --- | --- | --- |
13+
| Login session UI | Removed static fallback mode data/state and now disables Local Mem/Local DB controls when session API reads fail. | `assets/theme-v2/js/login-session.js` |
14+
| Header/session partials | Removed the shared static diagnostic cache from PR_031; missing session API failures are not cached as success-like browser state. | `assets/theme-v2/js/gamefoundry-partials.js` |
15+
| Server API client | Removed static API diagnostic cache and duplicate-suppression behavior; missing API requests throw visible diagnostics through the normal client path. | `src/engine/api/server-api-client.js` |
16+
| Static-only Playwright | Replaced the fallback test with an API-required test that verifies disabled mode controls and actionable diagnostics. | `tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs` |
17+
18+
## Requirement Checklist
19+
20+
| Requirement | Evidence | Status |
21+
| --- | --- | --- |
22+
| Read `docs_build/dev/PROJECT_INSTRUCTIONS.md` first. | Read before implementation. | PASS |
23+
| Remove static-only login fallback behavior added in PR_030/PR_031. | Removed `staticModeDetails`, `staticApiUnavailable`, `renderStaticApiUnavailable`, `GameFoundryStaticApiUnavailableDiagnostic`, and related cache logic. | PASS |
24+
| Local Mem and Local DB require the correct local API server path when login/session state depends on `/api/session/current`. | Static-only test verifies both buttons are disabled when `/api/session/current` is unavailable. | PASS |
25+
| If `/api/session/current` is unavailable, show a visible actionable API-required diagnostic. | Static-only test verifies `Session API required` and the route-unavailable diagnostic text. | PASS |
26+
| Do not pretend login/session mode is usable. | Static-only test verifies Local Mem and Local DB are disabled and not selected. | PASS |
27+
| Keep errors visible; do not suppress or cache missing API failures as success-like state. | Removed browser static API cache and diagnostic dedupe path from `gamefoundry-partials.js` and `server-api-client.js`. | PASS |
28+
| Preserve SQLite-backed Local DB behind API boundary. | `LoginSessionMode.spec.mjs` passed 5/5, including Local DB mode. | PASS |
29+
| Preserve real API-backed Local Mem/Local DB behavior when API server is running. | `LoginSessionMode.spec.mjs` passed 5/5. | PASS |
30+
| Prove `ShowOneChild.js` / `ActionableCoachmark` is external if still not repo-owned; do not add shims. | `Get-ChildItem -Path . -Recurse -Filter ShowOneChild.js -File` returned no files; scoped active HTML/JS `rg` found only test guard references. No shim added. | PASS |
31+
| Do not add UAT/Prod behavior. | No UAT/Prod login choices or adapter behavior changed; existing LoginSessionMode assertions still pass. | PASS |
32+
| Do not modify `start_of_day` folders. | `git status --short` shows no `start_of_day` changes. | PASS |
33+
| Run changed-file syntax checks. | `node --check` passed for changed JS/spec files. | PASS |
34+
| Run LoginSessionMode Playwright with API server running. | `npx playwright test tests/playwright/tools/LoginSessionMode.spec.mjs` passed 5/5. | PASS |
35+
| Add/run static-only login test proving API-required diagnostic appears and login modes do not silently work. | `npx playwright test tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs` passed 1/1. | PASS |
36+
| Run ToolboxRoutePages Playwright. | `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs` passed 1/1. | PASS |
37+
| Do not run full samples smoke unless directly impacted. | Full samples smoke skipped; samples and sample loader/framework were not touched. | PASS |
38+
39+
## ShowOneChild / ActionableCoachmark Evidence
40+
41+
| Check | Evidence | Result |
42+
| --- | --- | --- |
43+
| Repo-owned file search | `Get-ChildItem -Path . -Recurse -Filter ShowOneChild.js -File` returned no files. | PASS |
44+
| Active HTML/JS reference search | Scoped active HTML/JS `rg` found `tests/helpers/browserExtensionNoise.mjs`, `tests/playwright/tools/ApiStaticRouteRecovery.spec.mjs`, and `tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs` only. | PASS |
45+
| Shim check | No `ActionableCoachmark` global or shim was added. | PASS |
46+
47+
## Validation Commands
48+
49+
| Command | Result |
50+
| --- | --- |
51+
| `node --check assets/theme-v2/js/login-session.js` | PASS |
52+
| `node --check assets/theme-v2/js/gamefoundry-partials.js` | PASS |
53+
| `node --check src/engine/api/server-api-client.js` | PASS |
54+
| `node --check tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs` | PASS |
55+
| `npx playwright test tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs` | PASS, 1/1 |
56+
| `npx playwright test tests/playwright/tools/LoginSessionMode.spec.mjs` | PASS, 5/5 |
57+
| `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs` | PASS, 1/1 |
58+
| `git diff --check` | PASS, with Git line-ending warning only |
59+
60+
## Skipped Lanes
61+
62+
| Lane | Decision | Reason |
63+
| --- | --- | --- |
64+
| AdminDbViewer Playwright | SKIP | DB Viewer routes and rendering were not changed. |
65+
| Full samples smoke | SKIP | No sample files, sample loader, or shared sample framework changed. |
66+
| Full Playwright suite | SKIP | Requested targeted lanes cover the changed login/session and toolbox-route surfaces. |
67+
68+
## Notes
69+
70+
- Playwright emitted Node SQLite experimental warnings from the existing Local DB path. They are not introduced by this PR and did not fail validation.
71+
- Historical reports for PR_030/PR_031 still document the older fallback behavior; PR_032 supersedes that behavior in active runtime and test coverage.

0 commit comments

Comments
 (0)