Skip to content

Commit 603a22a

Browse files
committed
Fix DB auth foundation seed ownership, grouped DDL DML artifacts, guest seed data, reseed routing, and DB Viewer ordering - PR_26164_101-db-auth-foundation-fixes
1 parent 22bb0be commit 603a22a

102 files changed

Lines changed: 4720 additions & 13402 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

account/sign-in.html

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,6 @@ <h1>Sign In</h1>
2626
<aside class="side-menu" aria-label="Session mode">
2727
<button class="btn btn--compact" type="button" data-login-mode="local-db">Local DB</button>
2828
<p class="status" role="status" data-login-mode-disabled-message hidden>Use the API-backed local server for sign-in. Run npm run dev:local-api and open http://127.0.0.1:5501/account/sign-in.html. Local DB is disabled until the local API server is running.</p>
29-
<hr>
30-
<section class="content-stack" aria-labelledby="login-reseed-title">
31-
<div>
32-
<div class="kicker">Database</div>
33-
<h2 id="login-reseed-title">Reseed</h2>
34-
</div>
35-
<p><strong>Active DB mode:</strong> <span data-login-reseed-active-mode>Checking...</span></p>
36-
<p><strong>Reseed target:</strong> <span data-login-reseed-target>Checking...</span></p>
37-
<div class="action-group" role="group" aria-label="Reseed active DB">
38-
<button class="btn btn--compact" type="button" data-login-reseed-start>Reseed Active DB</button>
39-
<button class="btn btn--compact" type="button" data-login-reseed-confirm hidden>Confirm Reseed</button>
40-
<button class="btn btn--compact" type="button" data-login-reseed-cancel hidden>Cancel</button>
41-
</div>
42-
<p class="status" role="status" data-login-reseed-status>Checking...</p>
43-
</section>
4429
</aside>
4530
<div class="card">
4631
<div class="card-body content-stack">

admin/db-viewer.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ <h2 data-admin-db-mode-title>Local DB</h2>
3434
<div class="accordion-body content-stack">
3535
<p data-admin-db-scope-description>Current tool Local DB records are displayed as a read-only human-readable dump.</p>
3636
<p>Use the diagnostics panel to confirm table attribution, relationships, and table bleed checks.</p>
37+
<button class="btn btn--compact" type="button" data-admin-setup-reseed>Reseed Local DB</button>
38+
<p class="status" role="status" data-admin-setup-status>SKIP: No setup action has been run.</p>
3739
</div>
3840
</details>
3941
</div>
@@ -76,6 +78,7 @@ <h2>DB Inspector</h2>
7678
<div data-partial="footer"></div>
7779
<script src="assets/theme-v2/js/gamefoundry-partials.js" defer></script>
7880
<script src="assets/theme-v2/js/tool-display-mode.js" defer></script>
81+
<script type="module" src="assets/theme-v2/js/admin-setup-actions.js"></script>
7982
<script type="module" src="admin/db-viewer.js"></script>
8083
</body>
8184

admin/site-setup.html

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<div class="container">
1919
<div class="kicker">Admin Wireframe</div>
2020
<h1>Site Setup</h1>
21-
<p class="lede">Reserve the future setup owner for controlled platform bootstrap actions without executing setup work.</p>
21+
<p class="lede">Admin-owned setup actions for controlled Local DB bootstrap and review.</p>
2222
</div>
2323
</section>
2424
<section class="section">
@@ -41,11 +41,12 @@ <h2>Admin</h2>
4141
</nav>
4242
</details>
4343
<details class="vertical-accordion" open>
44-
<summary>Setup Preview</summary>
44+
<summary>Setup Actions</summary>
4545
<div class="accordion-body content-stack">
4646
<label>Setup Area <select disabled><option>Default roles</option><option>First admin</option><option>Tool metadata bootstrap</option><option>Starter platform settings</option><option>Ticket categories</option></select></label>
4747
<label>Review Mode <select disabled><option>Foundation only</option><option>Local DB dry run</option><option>Admin approval</option></select></label>
48-
<button class="btn btn--compact" type="button" disabled>Preview Setup Action</button>
48+
<button class="btn btn--compact" type="button" data-admin-setup-reseed>Reseed Local DB</button>
49+
<p class="status" role="status" data-admin-setup-status>SKIP: No setup action has been run.</p>
4950
</div>
5051
</details>
5152
</div>
@@ -56,7 +57,7 @@ <h2>Admin</h2>
5657
<div class="kicker">Setup Ownership</div>
5758
<h2 id="admin-site-setup-title">Controlled Setup Foundation</h2>
5859
</div>
59-
<p>This foundation page identifies where future setup and seed actions belong. Runtime setup actions are not executable in this PR.</p>
60+
<p>This page owns controlled Local DB setup entry points. Reseed actions call admin-gated server APIs and report visible PASS/FAIL/WARN/SKIP status.</p>
6061
<div class="table-wrapper">
6162
<table class="data-table" aria-label="Site setup ownership foundation">
6263
<caption>Future Site Setup Ownership</caption>
@@ -86,14 +87,14 @@ <h2>Inspector</h2>
8687
<details class="vertical-accordion" open>
8788
<summary>Status</summary>
8889
<div class="accordion-body content-stack">
89-
<p class="status" role="status">Wireframe only. Site setup actions are not read, written, or executed.</p>
90+
<p class="status" role="status" data-admin-setup-status>SKIP: No setup action has been run.</p>
9091
</div>
9192
</details>
9293
<details class="vertical-accordion" open>
9394
<summary>DDL/DML Review</summary>
9495
<div class="accordion-body content-stack">
9596
<p>DDL remains under docs_build/database/ddl/.</p>
96-
<p>Temporary DEV setup review DML remains under docs_build/database/dml/ until this page owns executable setup behavior in a later PR.</p>
97+
<p>Temporary DEV setup review DML is grouped under docs_build/database/dml/. Local DB reseed runs through the server API.</p>
9798
</div>
9899
</details>
99100
</div>
@@ -105,6 +106,7 @@ <h2>Inspector</h2>
105106
<div data-partial="footer"></div>
106107
<script src="assets/theme-v2/js/gamefoundry-partials.js" defer></script>
107108
<script src="assets/theme-v2/js/tool-display-mode.js" defer></script>
109+
<script type="module" src="assets/theme-v2/js/admin-setup-actions.js"></script>
108110
</body>
109111

110112
</html>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { reseedAdminSetup } from "../../../src/engine/api/admin-setup-api-client.js";
2+
3+
const reseedButtons = Array.from(document.querySelectorAll("[data-admin-setup-reseed]"));
4+
const statusFields = Array.from(document.querySelectorAll("[data-admin-setup-status]"));
5+
6+
function setStatus(message, status = "PASS") {
7+
const text = `${status}: ${message}`;
8+
statusFields.forEach((field) => {
9+
field.textContent = text;
10+
});
11+
}
12+
13+
function setBusy(isBusy) {
14+
reseedButtons.forEach((button) => {
15+
button.disabled = isBusy;
16+
if (isBusy) {
17+
button.setAttribute("aria-disabled", "true");
18+
} else {
19+
button.removeAttribute("aria-disabled");
20+
}
21+
});
22+
}
23+
24+
function runReseed() {
25+
setBusy(true);
26+
setStatus("Running Local DB reseed through Admin setup.", "WARN");
27+
try {
28+
const result = reseedAdminSetup();
29+
setStatus(result.message || "Local DB reseed completed through Admin setup.", result.status || "PASS");
30+
window.dispatchEvent(new CustomEvent("gamefoundry:mock-db-changed", {
31+
detail: result.snapshot || null,
32+
}));
33+
} catch (error) {
34+
const message = error instanceof Error ? error.message : String(error || "Admin setup reseed failed.");
35+
setStatus(message, "FAIL");
36+
} finally {
37+
setBusy(false);
38+
}
39+
}
40+
41+
reseedButtons.forEach((button) => {
42+
button.addEventListener("click", runReseed);
43+
});

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

Lines changed: 0 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
signIn,
66
setSessionMode,
77
} from "../../../src/engine/api/session-api-client.js";
8-
import { seedMockDb } from "../../../src/engine/api/mock-db-api-client.js";
98

109
const modeButtons = Array.from(document.querySelectorAll("[data-login-mode]"));
1110
const modeTitle = document.querySelector("[data-login-mode-title]");
@@ -15,21 +14,11 @@ const modeDisabledMessage = document.querySelector("[data-login-mode-disabled-me
1514
const userControls = document.querySelector("[data-login-user-controls]");
1615
const userStatus = document.querySelector("[data-login-user-status]");
1716
const continueLink = document.querySelector("[data-login-continue]");
18-
const reseedFields = {
19-
activeMode: document.querySelector("[data-login-reseed-active-mode]"),
20-
cancelButton: document.querySelector("[data-login-reseed-cancel]"),
21-
confirmButton: document.querySelector("[data-login-reseed-confirm]"),
22-
startButton: document.querySelector("[data-login-reseed-start]"),
23-
status: document.querySelector("[data-login-reseed-status]"),
24-
target: document.querySelector("[data-login-reseed-target]"),
25-
};
2617
const localApiStartCommand = "npm run dev:local-api";
2718
const localApiLoginUrl = "http://127.0.0.1:5501/account/sign-in.html";
2819
const expectedSessionEndpoint = "/api/session/current";
2920
const apiBackedLoginDiagnostic = `Use the API-backed local server for sign-in. Run ${localApiStartCommand} and open ${localApiLoginUrl}.`;
3021
const staticModeDisabledMessage = `Use the API-backed local server for sign-in. Run ${localApiStartCommand} and open ${localApiLoginUrl}. Local DB is disabled until the local API server is running.`;
31-
let reseedConfirmationPending = false;
32-
let reseedStatusMessage = "";
3322
const localStatusFields = {
3423
api: document.querySelector("[data-login-status-api]"),
3524
apiUrl: document.querySelector("[data-login-status-api-url]"),
@@ -92,55 +81,6 @@ function updateLocalDevelopmentStatus({ apiAvailability, disabledReason, serverM
9281
}
9382
}
9483

95-
function setReseedButtonState(button, disabled) {
96-
if (!button) {
97-
return;
98-
}
99-
button.disabled = disabled;
100-
if (disabled) {
101-
button.setAttribute("aria-disabled", "true");
102-
} else {
103-
button.removeAttribute("aria-disabled");
104-
}
105-
}
106-
107-
function reseedModeLabel(mode) {
108-
return mode?.label || mode?.environment || mode?.id || "selected DB mode";
109-
}
110-
111-
function updateReseedControls({ apiAvailable, mode, statusMessage }) {
112-
const modeLabel = apiAvailable ? reseedModeLabel(mode) : "Unavailable";
113-
const message = statusMessage || (apiAvailable
114-
? `Ready to reseed ${modeLabel}.`
115-
: "Reseed unavailable until the Local API is available.");
116-
if (reseedFields.activeMode) {
117-
reseedFields.activeMode.textContent = modeLabel;
118-
}
119-
if (reseedFields.target) {
120-
reseedFields.target.textContent = modeLabel;
121-
}
122-
if (reseedFields.status) {
123-
reseedFields.status.textContent = message;
124-
}
125-
setReseedButtonState(reseedFields.startButton, !apiAvailable || reseedConfirmationPending);
126-
setReseedButtonState(reseedFields.confirmButton, !apiAvailable || !reseedConfirmationPending);
127-
setReseedButtonState(reseedFields.cancelButton, !apiAvailable || !reseedConfirmationPending);
128-
if (reseedFields.confirmButton) {
129-
reseedFields.confirmButton.hidden = !apiAvailable || !reseedConfirmationPending;
130-
}
131-
if (reseedFields.cancelButton) {
132-
reseedFields.cancelButton.hidden = !apiAvailable || !reseedConfirmationPending;
133-
}
134-
}
135-
136-
function currentModeForReseed() {
137-
const session = getCurrentUser();
138-
return getSessionModes().find((item) => item.id === session.mode) || {
139-
id: session.mode,
140-
label: session.environment || session.mode,
141-
};
142-
}
143-
14484
function dispatchSessionChanged() {
14585
window.dispatchEvent(new CustomEvent("gamefoundry:mock-db-session-user-changed", {
14686
detail: getCurrentUser(),
@@ -220,8 +160,6 @@ function renderError(error) {
220160
const disabledReason = message === apiBackedLoginDiagnostic
221161
? staticModeDisabledMessage
222162
: `Local DB is disabled because ${message}`;
223-
reseedConfirmationPending = false;
224-
reseedStatusMessage = "Reseed unavailable until the Local API is available.";
225163
modeButtons.forEach((button) => {
226164
button.disabled = true;
227165
button.setAttribute("aria-disabled", "true");
@@ -252,11 +190,6 @@ function renderError(error) {
252190
disabledReason,
253191
serverMode,
254192
});
255-
updateReseedControls({
256-
apiAvailable: false,
257-
mode: null,
258-
statusMessage: reseedStatusMessage,
259-
});
260193
updateContinueLink();
261194
}
262195

@@ -296,11 +229,6 @@ function render() {
296229
disabledReason: "Local DB is enabled because the Local API is available.",
297230
serverMode: `API-backed local server (${mode.label || session.mode})`,
298231
});
299-
updateReseedControls({
300-
apiAvailable: true,
301-
mode,
302-
statusMessage: reseedStatusMessage,
303-
});
304232
if (modeDisabledMessage) {
305233
modeDisabledMessage.hidden = true;
306234
modeDisabledMessage.textContent = "";
@@ -320,8 +248,6 @@ modeButtons.forEach((button) => {
320248
return;
321249
}
322250
try {
323-
reseedConfirmationPending = false;
324-
reseedStatusMessage = "";
325251
setSessionMode(modeId);
326252
dispatchModeChanged();
327253
render();
@@ -345,51 +271,4 @@ userControls?.addEventListener("click", (event) => {
345271
}
346272
});
347273

348-
reseedFields.startButton?.addEventListener("click", () => {
349-
try {
350-
const mode = currentModeForReseed();
351-
const modeLabel = reseedModeLabel(mode);
352-
reseedConfirmationPending = true;
353-
reseedStatusMessage = `Confirm reseed for ${modeLabel}.`;
354-
render();
355-
} catch (error) {
356-
reseedConfirmationPending = false;
357-
reseedStatusMessage = `Reseed unavailable: ${errorMessage(error)}`;
358-
renderError(error);
359-
}
360-
});
361-
362-
reseedFields.cancelButton?.addEventListener("click", () => {
363-
try {
364-
const modeLabel = reseedModeLabel(currentModeForReseed());
365-
reseedConfirmationPending = false;
366-
reseedStatusMessage = `Reseed canceled for ${modeLabel}.`;
367-
render();
368-
} catch (error) {
369-
reseedConfirmationPending = false;
370-
reseedStatusMessage = `Reseed canceled. ${errorMessage(error)}`;
371-
renderError(error);
372-
}
373-
});
374-
375-
reseedFields.confirmButton?.addEventListener("click", () => {
376-
try {
377-
const modeLabel = reseedModeLabel(currentModeForReseed());
378-
seedMockDb();
379-
reseedConfirmationPending = false;
380-
reseedStatusMessage = `Reseed complete for ${modeLabel}.`;
381-
dispatchModeChanged();
382-
render();
383-
} catch (error) {
384-
const message = errorMessage(error);
385-
let modeLabel = "selected DB mode";
386-
try {
387-
modeLabel = reseedModeLabel(currentModeForReseed());
388-
} catch {}
389-
reseedConfirmationPending = false;
390-
reseedStatusMessage = `Reseed failed for ${modeLabel}: ${message}`;
391-
render();
392-
}
393-
});
394-
395274
render();

docs_build/database/README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
# Database Artifact Ownership
22

3-
Database schema and setup review artifacts are owned outside runtime source.
3+
Database schema, DML review, and seed artifacts are grouped under `docs_build/database/`.
44

55
## Ownership
66

77
- DEV database DDL belongs in `docs_build/database/ddl/`.
88
- DEV setup or DML review artifacts belong in `docs_build/database/dml/`.
9-
- DDL must not be placed under `src/` or `docs/`.
10-
- DML files in this folder are temporary setup/review artifacts unless promoted by a future Admin Site Setup workflow.
9+
- Seed artifacts belong in `docs_build/database/seed/`.
10+
- Guest seed artifacts belong in `docs_build/database/seed/guest/` and are read-only.
11+
- DDL/DML/seed artifacts must not be placed under `src/` or `docs/`.
1112
- Identity records use `key` as the primary identifier. Shared audit ownership uses `createdBy` and `updatedBy` references to `users.key`.
1213

13-
## Execution Boundary
14+
## Grouping
15+
16+
Each product area/tool owns one grouped file in `ddl/`, `dml/`, and `seed/`. Account tables stay in `account.sql` / `account.json`; tool metadata, planning, and votes remain separate grouped files.
1417

15-
Codex may execute DEV database setup only.
18+
## Execution Boundary
1619

17-
UAT and production SQL execution is user-controlled. Codex may prepare review artifacts, but it must not execute UAT or production SQL.
20+
Runtime DEV setup and reseed actions must call server-side APIs. Browser pages must not directly seed authoritative DB records or generate authoritative DB keys.
1821

19-
Long-term seed behavior belongs in Admin -> Site Setup, not permanent seed SQL. Temporary DML files may document review setup data while the Admin Site Setup workflow is planned.
22+
Codex may execute DEV database setup only. UAT and production SQL execution is user-controlled. Codex may prepare review artifacts, but it must not execute UAT or production SQL.

docs_build/database/ddl/dev-app-identity-schema.sql renamed to docs_build/database/ddl/account.sql

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
-- Game Foundry Studio DEV database DDL
2-
-- Ownership: docs_build/database/ddl/
2+
-- Group: Account
3+
-- Ownership: docs_build/database/ddl/account.sql
34
-- Target DEV database: gamefoundry_dev
4-
-- Scope: app identity tables only. No custom password tables are defined here.
5+
-- Scope: account identity tables only. No custom password tables are defined here.
56
-- Identity ownership follows the project key-based governance model.
67

78
CREATE TABLE IF NOT EXISTS users (

docs_build/database/ddl/admin.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-- Game Foundry Studio DEV database DDL
2+
-- Group: Admin
3+
-- Ownership: docs_build/database/ddl/admin.sql
4+
-- Runtime Local DB schemas for these tables are currently owned by src/dev-runtime/persistence/mock-db-store.js.
5+
-- This grouped file documents the product/tool ownership boundary until an executable migration PR promotes the table DDL.
6+
-- Owned tables: none active
7+
-- Note: Admin Site Setup owns explicit server-side setup/reseed entry points. No persistent admin table exists in this PR.
8+
9+
-- Server/API layer owns authoritative key generation for records in this group.

docs_build/database/ddl/asset.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-- Game Foundry Studio DEV database DDL
2+
-- Group: Asset
3+
-- Ownership: docs_build/database/ddl/asset.sql
4+
-- Runtime Local DB schemas for these tables are currently owned by src/dev-runtime/persistence/mock-db-store.js.
5+
-- This grouped file documents the product/tool ownership boundary until an executable migration PR promotes the table DDL.
6+
-- Owned tables: asset_role_definitions, asset_library_items, asset_storage_objects, asset_import_events, asset_validation_items
7+
8+
-- Server/API layer owns authoritative key generation for records in this group.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-- Game Foundry Studio DEV database DDL
2+
-- Group: Controls
3+
-- Ownership: docs_build/database/ddl/controls.sql
4+
-- Runtime Local DB schemas for these tables are currently owned by src/dev-runtime/persistence/mock-db-store.js.
5+
-- This grouped file documents the product/tool ownership boundary until an executable migration PR promotes the table DDL.
6+
-- Owned tables: game_input_mappings, player_controller_profiles, player_input_device_selections, input_custom_action_records
7+
8+
-- Server/API layer owns authoritative key generation for records in this group.

0 commit comments

Comments
 (0)