Skip to content

Commit 7451844

Browse files
committed
Clarify local API server entrypoint and stop static login API calls - PR_26158_033-local-server-entrypoint-cleanup
1 parent 61870d6 commit 7451844

6 files changed

Lines changed: 114 additions & 17 deletions

File tree

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

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

111111
const currentScript = document.currentScript || document.querySelector("script[src*='gamefoundry-partials.js']");
112112
const assetRoot = currentScript ? new URL("../", currentScript.src) : null;
113+
const apiBackedLoginDiagnostic = "Use the API-backed local server for login.";
113114

114115
function assetUrl(path) {
115116
if (!assetRoot) return rootPrefix() + path;
@@ -142,6 +143,11 @@
142143
return "Local server API route unavailable for " + method + " " + url + " (" + status + "). Start the API-backed local server route instead of a static-only server.";
143144
}
144145

146+
function isStaticLocalEntrypoint() {
147+
return ["127.0.0.1", "localhost"].includes(window.location.hostname) &&
148+
window.location.port === "5500";
149+
}
150+
145151
function missingSessionApiLoginState(diagnostic) {
146152
return {
147153
authenticated: false,
@@ -163,6 +169,9 @@
163169
}
164170

165171
function localDevLoginState() {
172+
if (isStaticLocalEntrypoint()) {
173+
return missingSessionApiLoginState(apiBackedLoginDiagnostic);
174+
}
166175
try {
167176
const request = new XMLHttpRequest();
168177
request.open("GET", "/api/session/current", false);

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ 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 apiBackedLoginDiagnostic = "Use the API-backed local server for login.";
1617

1718
function currentReturnTo() {
1819
const params = new URLSearchParams(window.location.search);
@@ -95,6 +96,11 @@ function errorMessage(error) {
9596
return error instanceof Error ? error.message : String(error || "Session API unavailable.");
9697
}
9798

99+
function isStaticLocalEntrypoint() {
100+
return ["127.0.0.1", "localhost"].includes(window.location.hostname) &&
101+
window.location.port === "5500";
102+
}
103+
98104
function renderError(error) {
99105
const message = errorMessage(error);
100106
modeButtons.forEach((button) => {
@@ -122,6 +128,10 @@ function renderError(error) {
122128
}
123129

124130
function render() {
131+
if (isStaticLocalEntrypoint()) {
132+
renderError(new Error(apiBackedLoginDiagnostic));
133+
return;
134+
}
125135
try {
126136
const session = getSessionCurrent();
127137
const mode = getSessionModes().find((item) => item.id === session.mode) || {
@@ -158,6 +168,10 @@ function render() {
158168
modeButtons.forEach((button) => {
159169
button.addEventListener("click", () => {
160170
const modeId = button.dataset.loginMode || "local-mem";
171+
if (isStaticLocalEntrypoint()) {
172+
renderError(new Error(apiBackedLoginDiagnostic));
173+
return;
174+
}
161175
try {
162176
setSessionMode(modeId);
163177
dispatchModeChanged();
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# PR_26158_033 Local Server Entrypoint Cleanup Report
2+
3+
## Executive Summary
4+
5+
Static `127.0.0.1:5500` is no longer treated as a supported login/session entrypoint. When `login.html` is opened from that static server, the page displays:
6+
7+
`Use the API-backed local server for login.`
8+
9+
The static 5500 path does not call `/api/session/current`, and Local Mem / Local DB controls remain disabled. API-backed Local Mem and Local DB behavior still works through the real local server.
10+
11+
## Implementation
12+
13+
| Area | Change | Evidence |
14+
| --- | --- | --- |
15+
| Login page runtime | Detects `127.0.0.1:5500` / `localhost:5500` before session API calls and renders the API-backed server diagnostic. | `assets/theme-v2/js/login-session.js` |
16+
| Shared header partial | Detects the unsupported static local entrypoint before header/account session reads, preventing `/api/session/current` from static 5500 pages. | `assets/theme-v2/js/gamefoundry-partials.js` |
17+
| Static Playwright | Uses `127.0.0.1:5500` explicitly and asserts no `/api/session/current` or `/api/session/` requests are made. | `tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs` |
18+
19+
## Requirement Checklist
20+
21+
| Requirement | Evidence | Status |
22+
| --- | --- | --- |
23+
| Read `docs_build/dev/PROJECT_INSTRUCTIONS.md` first. | Read before implementation. | PASS |
24+
| Remove static `127.0.0.1:5500` as a supported login/session entrypoint. | Static 5500 detection now renders a blocked diagnostic before session API usage. | PASS |
25+
| Add visible page diagnostic: `Use the API-backed local server for login.` | Static 5500 Playwright verifies this exact text appears in login status. | PASS |
26+
| Do not call `/api/session/current` from static-only 5500 pages. | Static 5500 Playwright records all requests and asserts no `/api/session/current` or `/api/session/` requests. | PASS |
27+
| Do not make Local Mem or Local DB appear usable from static-only 5500. | Static 5500 Playwright verifies both mode buttons are disabled and not selected. | PASS |
28+
| Preserve API-backed Local Mem and Local DB behavior when served from the real local server. | `LoginSessionMode.spec.mjs` passed 5/5. | PASS |
29+
| Document `ShowOneChild.js` / `ActionableCoachmark` is browser-extension injected if repo audit confirms it. | Repo audit found no `ShowOneChild.js` file and no active repo HTML/JS load path; test noise filtering only treats those names as extension noise when an extension URL scheme is present. Therefore any observed runtime `ShowOneChild.js` / `ActionableCoachmark` error is browser-extension injected, not repo-served. | PASS |
30+
| Do not add shims or fallbacks. | No `ActionableCoachmark` global, static API fallback, or login fallback shim was added. | PASS |
31+
| Do not add UAT/Prod behavior. | No UAT/Prod login choices or adapter behavior changed. | PASS |
32+
33+
## ShowOneChild / ActionableCoachmark Evidence
34+
35+
| Check | Evidence | Result |
36+
| --- | --- | --- |
37+
| Repo-owned file search | `Get-ChildItem -Path . -Recurse -Filter ShowOneChild.js -File` returned no files. | PASS |
38+
| Active HTML/JS reference search | Scoped active HTML/JS `rg` found only `tests/helpers/browserExtensionNoise.mjs`, `tests/playwright/tools/ApiStaticRouteRecovery.spec.mjs`, and `tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs`. | PASS |
39+
| Browser-extension injection conclusion | No repo-owned file or load path exists. The existing helper requires `chrome-extension://`, `moz-extension://`, or `extension://` before treating these script names as extension noise. | PASS |
40+
| Shim check | No shim or fallback global was added. | PASS |
41+
42+
## Validation Commands
43+
44+
| Command | Result |
45+
| --- | --- |
46+
| `node --check assets/theme-v2/js/login-session.js` | PASS |
47+
| `node --check assets/theme-v2/js/gamefoundry-partials.js` | PASS |
48+
| `node --check src/engine/api/server-api-client.js` | PASS |
49+
| `node --check tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs` | PASS |
50+
| `npx playwright test tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs` | PASS, 1/1 |
51+
| `npx playwright test tests/playwright/tools/LoginSessionMode.spec.mjs` | PASS, 5/5 |
52+
| `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs` | PASS, 1/1 |
53+
| `git diff --check` | PASS, with Git line-ending warnings only |
54+
55+
## Skipped Lanes
56+
57+
| Lane | Decision | Reason |
58+
| --- | --- | --- |
59+
| AdminDbViewer Playwright | SKIP | DB Viewer routes and rendering were not changed. |
60+
| Full samples smoke | SKIP | No sample files, sample loader, or shared sample framework changed. |
61+
| Full Playwright suite | SKIP | Requested targeted lanes cover the changed login/session and toolbox-route surfaces. |
62+
63+
## Notes
64+
65+
- Playwright emitted Node SQLite experimental warnings from the existing Local DB path. They are not introduced by this PR and did not fail validation.
66+
- This PR intentionally does not add fallback behavior for static servers. The visible diagnostic directs users to the API-backed local server.

docs_build/dev/reports/playwright_v8_coverage_report.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ 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-
(80%) Theme V2 Shared JS - exercised 3 runtime JS files
17+
(81%) Theme V2 Shared JS - exercised 3 runtime JS files
1818

1919
Changed runtime JS files covered:
2020
(53%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 10/19
@@ -26,10 +26,10 @@ Files with executed line/function counts where available:
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
2828
(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
29+
(83%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 442/442; executed functions 33/40
3030
(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
3231
(88%) src/engine/api/session-api-client.js - executed lines 34/34; executed functions 7/8
32+
(89%) assets/theme-v2/js/login-session.js - executed lines 182/182; executed functions 16/18
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:
@@ -38,5 +38,5 @@ Uncovered or low-coverage changed JS files:
3838
Changed JS files considered:
3939
(0%) tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs - changed JS file not collected as browser runtime coverage
4040
(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
41+
(83%) assets/theme-v2/js/gamefoundry-partials.js - changed JS file with browser V8 coverage
42+
(89%) assets/theme-v2/js/login-session.js - changed JS file with browser V8 coverage
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
# PR_26158_032 Testing Lane Execution Report
1+
# PR_26158_033 Testing Lane Execution Report
22

33
## Lanes Run
44

55
| Lane | Command | Result |
66
| --- | --- | --- |
77
| Changed-file syntax | `node --check assets/theme-v2/js/login-session.js`; `node --check assets/theme-v2/js/gamefoundry-partials.js`; `node --check src/engine/api/server-api-client.js`; `node --check tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs` | PASS |
8-
| Static-only login API-required Playwright | `npx playwright test tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs` | PASS, 1/1 |
8+
| Static 127.0.0.1:5500 login Playwright | `npx playwright test tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs` | PASS, 1/1 |
99
| LoginSessionMode Playwright | `npx playwright test tests/playwright/tools/LoginSessionMode.spec.mjs` | PASS, 5/5 |
1010
| ToolboxRoutePages Playwright | `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs` | PASS, 1/1 |
11-
| Changed-file/static validation | `git diff --check` | PASS, with Git line-ending warning only |
11+
| Changed-file/static validation | `git diff --check` | PASS, with Git line-ending warnings only |
1212
| ShowOneChild/ActionableCoachmark reference audit | `Get-ChildItem -Path . -Recurse -Filter ShowOneChild.js -File`; scoped active HTML/JS `rg` | PASS |
1313
| Runtime JS V8 coverage | Playwright coverage generated by targeted runs | PASS/WARN; `docs_build/dev/reports/playwright_v8_coverage_report.txt` and `coverage_changed_js_guardrail.txt` generated. |
1414

1515
## Validation Notes
1616

1717
| Check | Evidence | Result |
1818
| --- | --- | --- |
19-
| Static-only login shows visible API-required diagnostic. | `StaticOnlyLoginApiRequired.spec.mjs` serves `login.html` from a static-only `127.0.0.1` server and verifies `Session API required` plus the `/api/session/current` route-unavailable diagnostic. | PASS |
20-
| Static-only login modes do not silently work. | `StaticOnlyLoginApiRequired.spec.mjs` verifies Local Mem and Local DB buttons are disabled and not selected when `/api/session/current` is unavailable. | PASS |
21-
| Static-only login does not make mode/user session updates. | `StaticOnlyLoginApiRequired.spec.mjs` verifies no `/api/session/mode`, `/api/session/users`, or `/api/session/modes` requests occur. | PASS |
19+
| Static `127.0.0.1:5500` login shows visible API-backed server diagnostic. | `StaticOnlyLoginApiRequired.spec.mjs` serves `login.html` on `127.0.0.1:5500` and verifies `Use the API-backed local server for login.` is visible. | PASS |
20+
| Static `127.0.0.1:5500` login does not call `/api/session/current`. | `StaticOnlyLoginApiRequired.spec.mjs` records all requests and asserts no request URL contains `/api/session/current` or `/api/session/`. | PASS |
21+
| Static `127.0.0.1:5500` login modes do not appear usable. | Static lane verifies Local Mem and Local DB buttons are disabled and not selected. | PASS |
2222
| API-backed Local Mem and Local DB behavior still works. | `LoginSessionMode.spec.mjs` passed 5/5, including Local DB session behavior. | PASS |
2323
| Toolbox route pages still render. | `ToolboxRoutePages.spec.mjs` passed 1/1 for Project Journey, Colors, and Assets `/tools/...` aliases. | PASS |
2424
| Repo-owned ShowOneChild/ActionableCoachmark errors are absent. | Static-only Playwright asserts no non-extension `ShowOneChild`, `showOneChild`, or `ActionableCoachmark` error text in page or console errors. | PASS |
@@ -29,4 +29,4 @@
2929
| --- | --- | --- |
3030
| AdminDbViewer Playwright | SKIP | DB Viewer routes, DB adapters, and admin DB rendering were not changed. |
3131
| Full samples smoke | SKIP | No samples, shared sample loader, or sample framework files changed. |
32-
| Full Playwright suite | SKIP | Static-only login, API-backed login, toolbox route, syntax, static, and V8 coverage checks cover the changed surfaces. |
32+
| Full Playwright suite | SKIP | Static 5500 login, API-backed login, toolbox route, syntax, static, and V8 coverage checks cover the changed surfaces. |

tests/playwright/tools/StaticOnlyLoginApiRequired.spec.mjs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { expect, test } from "@playwright/test";
55
import { isBrowserExtensionNoise } from "../../helpers/browserExtensionNoise.mjs";
66
import { workspaceV2CoverageReporter } from "../../helpers/workspaceV2CoverageReporter.mjs";
77

8+
const STATIC_LOCAL_PORT = 5500;
9+
810
function contentTypeForPath(filePath) {
911
const extension = path.extname(filePath).toLowerCase();
1012
if (extension === ".html") return "text/html; charset=utf-8";
@@ -45,11 +47,11 @@ async function startStaticOnlyServer() {
4547

4648
await new Promise((resolve, reject) => {
4749
server.once("error", reject);
48-
server.listen(0, "127.0.0.1", resolve);
50+
server.listen(STATIC_LOCAL_PORT, "127.0.0.1", resolve);
4951
});
5052
const address = server.address();
5153
if (!address || typeof address === "string") {
52-
throw new Error("Failed to start static-only test server.");
54+
throw new Error("Failed to start static-only 127.0.0.1:5500 test server.");
5355
}
5456
return {
5557
baseUrl: `http://127.0.0.1:${address.port}`,
@@ -63,12 +65,16 @@ test.afterAll(async () => {
6365
await workspaceV2CoverageReporter.writeReport();
6466
});
6567

66-
test("static-only login requires API-backed session routes", async ({ page }) => {
68+
test("static 127.0.0.1:5500 login requires the API-backed local server", async ({ page }) => {
6769
const server = await startStaticOnlyServer();
70+
const requests = [];
6871
const failedRequests = [];
6972
const pageErrors = [];
7073
const consoleErrors = [];
7174

75+
page.on("request", (request) => {
76+
requests.push(request.url());
77+
});
7278
page.on("response", (response) => {
7379
if (response.status() >= 400) {
7480
failedRequests.push(`${response.status()} ${response.url()}`);
@@ -101,13 +107,15 @@ test("static-only login requires API-backed session routes", async ({ page }) =>
101107
await expect(page.locator("[data-login-mode-title]")).toHaveText("Session API required");
102108
await expect(page.locator("[data-login-mode-description]")).toContainText("Start the API-backed local server");
103109
await expect(page.locator("[data-login-mode-status]")).toContainText("Login/session diagnostic");
104-
await expect(page.locator("[data-login-mode-status]")).toContainText("Local server API route unavailable for GET /api/session/current (404)");
110+
await expect(page.locator("[data-login-mode-status]")).toContainText("Use the API-backed local server for login.");
105111
await expect(page.locator("[data-login-user]")).toHaveCount(0);
106112
await expect(page.locator("[data-login-user-status]")).toContainText("No local users are available until /api/session responds");
107113
await expect(page.getByRole("button", { name: "UAT" })).toHaveCount(0);
108114
await expect(page.getByRole("button", { name: "Prod" })).toHaveCount(0);
109115

110-
expect(failedRequests.filter((request) => request.includes("/api/session/current")).length).toBeGreaterThan(0);
116+
expect(requests.filter((request) => request.includes("/api/session/current"))).toEqual([]);
117+
expect(requests.filter((request) => request.includes("/api/session/"))).toEqual([]);
118+
expect(failedRequests.filter((request) => request.includes("/api/session/current"))).toEqual([]);
111119
expect(failedRequests.filter((request) => request.includes("/api/session/mode"))).toEqual([]);
112120
expect(failedRequests.filter((request) => request.includes("/api/session/users"))).toEqual([]);
113121
expect(failedRequests.filter((request) => request.includes("/api/session/modes"))).toEqual([]);

0 commit comments

Comments
 (0)