Skip to content

Commit 99a4cbf

Browse files
committed
Complete DEV Supabase DB migration through product cutover and closeout audit - PR_26166_166-172 & Handle Supabase password reset rate limits with safe user messaging - PR_26166_173-password-reset-rate-limit-message
1 parent ca20f8e commit 99a4cbf

66 files changed

Lines changed: 37225 additions & 1264 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.

.env.example

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
# Game Foundry Studio local development environment
22

3-
# Supabase Auth is the default auth provider. Local DB remains the product data provider.
3+
# Supabase Auth and Supabase Postgres are the default DEV auth/product data providers.
44
# Missing Supabase configuration reports provider diagnostics instead of falling back.
55
GAMEFOUNDRY_AUTH_PROVIDER=supabase-auth
6-
GAMEFOUNDRY_DB_PROVIDER=local-db
6+
GAMEFOUNDRY_DB_PROVIDER=supabase-postgres
77

8-
# Future Supabase DEV browser-safe configuration.
9-
# Leave values empty until a reviewed Supabase DEV project exists.
8+
# Supabase DEV browser-safe configuration.
9+
# Leave values empty in this example; local values belong in .env.local.
1010
GAMEFOUNDRY_SUPABASE_URL=
1111
GAMEFOUNDRY_SUPABASE_ANON_KEY=
1212

13-
# Future Supabase DEV server-only configuration.
13+
# Supabase DEV server-only configuration.
1414
# Do not expose these values to browser JavaScript, HTML, reports, or screenshots.
1515
GAMEFOUNDRY_SUPABASE_SERVICE_ROLE_KEY=
1616
GAMEFOUNDRY_SUPABASE_DATABASE_URL=

admin/db-viewer.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ <h2>DB Inspector</h2>
6161
<div class="content-stack content-stack--compact" data-admin-db-local-status>
6262
<p><strong>Current URL:</strong> <span data-admin-db-status-current-url>Checking...</span></p>
6363
<p><strong>Detected server mode:</strong> <span data-admin-db-status-server-mode>Checking...</span></p>
64+
<p><strong>Data provider:</strong> <span data-admin-db-status-provider>Checking...</span></p>
65+
<p><strong>Data source:</strong> <span data-admin-db-status-source>Checking...</span></p>
6466
<p><strong>Local API availability:</strong> <span data-admin-db-status-api>Checking...</span></p>
6567
<p><strong>Expected API endpoint:</strong> <span data-admin-db-status-endpoint>/api/session/current</span></p>
6668
<p><strong>Admin setup endpoint:</strong> <span data-admin-db-status-setup-endpoint>/api/admin/setup/reseed</span></p>

admin/db-viewer.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ async function loadLocalDbViewer() {
4040
return;
4141
}
4242
const session = currentSession();
43-
if (session.mode !== "local-db") {
44-
showGatewayStatus(session.diagnostic || "DB Viewer is available only in Local DB mode.");
43+
if (!session.authenticated) {
44+
showGatewayStatus(session.diagnostic || "Sign in with an admin account to open DB Viewer.");
4545
return;
4646
}
4747
const module = await import("../src/engine/api/local-db-viewer-ui.js");

assets/theme-v2/js/account-auth-actions.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const submitButton = document.querySelector("[data-account-auth-submit]");
66
const action = form?.getAttribute("data-account-auth-form") || "";
77
const ACCOUNT_IDENTITY_SETUP_MESSAGE = "Account identity setup is incomplete. Please contact support.";
88
const AUTH_UNAVAILABLE_MESSAGE = "The site is currently unavailable. Please try again later.";
9+
const PASSWORD_RESET_RATE_LIMIT_MESSAGE = "Too many reset requests. Please wait and try again later.";
910
let authStatus = null;
1011

1112
function setStatus(message) {
@@ -36,6 +37,9 @@ async function readJson(response, fallbackMessage) {
3637
if (payload?.error === ACCOUNT_IDENTITY_SETUP_MESSAGE) {
3738
throw new Error(ACCOUNT_IDENTITY_SETUP_MESSAGE);
3839
}
40+
if (payload?.error === PASSWORD_RESET_RATE_LIMIT_MESSAGE) {
41+
throw new Error(PASSWORD_RESET_RATE_LIMIT_MESSAGE);
42+
}
3943
throw new Error(fallbackMessage);
4044
}
4145
return payload?.data || {};

assets/theme-v2/js/admin-db-status-panel.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@ function renderAdminDbStatus() {
2929
const session = sessionResponse.payload?.data || {};
3030
const mode = session.mode || "unknown";
3131
const persistence = session.persistence || "unknown persistence";
32-
setText(fields.serverMode, `PASS: ${mode} (${persistence}).`);
32+
const providerResponse = safeRequestServerApi("/providers/contract");
33+
if (providerResponse.ok) {
34+
const authProviderId = providerResponse.payload?.data?.activeProviders?.authProviderId || mode;
35+
const providerLabel = authProviderId === "supabase-auth" ? "Supabase Auth" : persistence;
36+
setText(fields.serverMode, `PASS: ${authProviderId} (${providerLabel}).`);
37+
} else {
38+
setText(fields.serverMode, `PASS: ${mode} (${persistence}).`);
39+
}
3340
setText(fields.api, "PASS: /api/session/current responded.");
3441
}
3542

docs_build/dev/codex_commands.md

Lines changed: 253 additions & 0 deletions
Large diffs are not rendered by default.

docs_build/dev/commit_comment.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Add DEV Supabase auth test user cleanup - PR_26166_165-auth-test-user-cleanup
1+
Handle password reset rate limits safely - PR_26166_173-password-reset-rate-limit-message
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# PR_26166_166 Cleanup Report
2+
3+
## Summary
4+
5+
PASS
6+
7+
- Validation wrote one live DEV Supabase Auth test account.
8+
- Cleanup deleted the Supabase Auth user, matching `users` row, and matching `user_roles` row.
9+
- Final dry-run confirmed zero matching `codex-*` or `playwright-*` `@example.test` test accounts.
10+
- UAT/PROD were not touched.
11+
12+
## Created Test Records
13+
14+
- `codex-pr166-audit-1781574550756@example.test` userKey=`01KV71WKFRC9XD10D8MZRB7ZJG`
15+
16+
## Deleted Test Records
17+
18+
- `codex-pr166-audit-1781574550756@example.test` userKey=`01KV71WKFRC9XD10D8MZRB7ZJG`; Auth deleted=true; Auth not found=false; user_roles deleted=1; users deleted=1
19+
20+
## Final Cleanup Confirmation
21+
22+
- Command: `npm run cleanup:supabase-dev-auth-test-users -- --dry-run --json`
23+
- `testDataCandidates`: 0
24+
- `testDataCreated`: 0
25+
- `testDataDeleted`: 0 in final dry-run mode
26+
- `auditReassignmentRequired`: false
27+
- `status`: PASS
28+
29+
## Non-Test Records
30+
31+
Six non-test users were skipped by the cleanup matcher and were not deleted.
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# PR_26166_166-dev-supabase-auth-closeout-audit
2+
3+
## Branch Validation
4+
5+
PASS
6+
7+
- Current branch: `main`
8+
- Expected branch: `main`
9+
- Local branches found: `main`
10+
- `docs_build/dev/PROJECT_INSTRUCTIONS.md` read before execution.
11+
12+
## Scope Summary
13+
14+
PASS
15+
16+
- Audited Supabase Auth readiness after PR_165 cleanup tooling.
17+
- Validated live DEV Create Account, Sign In, `/api/session/current`, Sign Out, `users`, `roles`, and `user_roles`.
18+
- Confirmed Codex-created test users were cleaned up before packaging.
19+
- Confirmed product data provider remains `local-db`.
20+
- No runtime code, DDL, product cutover, UAT, or PROD resources were changed.
21+
- No `.env.local` or secret values were changed or committed.
22+
23+
## Requirement Checklist
24+
25+
- PASS - Treat PR_166 as one separate BUILD unit.
26+
- PASS - Main branch only; current branch was `main`.
27+
- PASS - Read `docs_build/dev/PROJECT_INSTRUCTIONS.md` before work.
28+
- PASS - Audit Supabase Auth readiness after PR_165 cleanup tooling.
29+
- PASS - Validate Create Account.
30+
- PASS - Validate Sign In.
31+
- PASS - Validate `/api/session/current`.
32+
- PASS - Validate Sign Out through `POST /api/session/logout`.
33+
- PASS - Validate `users`, `roles`, and `user_roles`.
34+
- PASS - Confirm test users are cleaned up.
35+
- PASS - Confirm product data still uses Local DB.
36+
- PASS - Run `npm run validate:supabase-dev`.
37+
- PASS - Run targeted auth/session validation.
38+
- PASS - Cleanup ran after validation data was created.
39+
- PASS - Reports list created and deleted test records.
40+
- PASS - Playwright impacted: targeted auth/session Playwright run completed.
41+
- PASS - Full samples smoke was not run.
42+
43+
## Live DEV Auth Audit
44+
45+
PASS
46+
47+
- Created validation account: `codex-pr166-audit-1781574550756@example.test`
48+
- Created user key: `01KV71WKFRC9XD10D8MZRB7ZJG`
49+
- Create Account: identity provisioned.
50+
- Sign In: resolved the same user key.
51+
- `/api/session/current`: returned authenticated user and `user` role.
52+
- Sign Out: `POST /api/session/logout` returned guest session.
53+
- Post-sign-out `/api/session/current`: returned guest session.
54+
- `users`: row found for created Supabase-auth user.
55+
- `user_roles`: row found for created user.
56+
- `roles`: linked role row found with `roleSlug=user`.
57+
- Provider contract: auth provider `supabase-auth`; product/database provider `local-db`.
58+
59+
## Validation Lane Report
60+
61+
Executed lanes:
62+
63+
- runtime/integration: live DEV local API auth lifecycle audit.
64+
- integration: `npm run validate:supabase-dev`
65+
- contract/runtime: `node --test tests/dev-runtime/SupabaseProviderContractStub.test.mjs`
66+
- targeted Playwright auth/session: `npx playwright test tests/playwright/account/SupabaseSignInSession.spec.mjs --project=playwright --workers=1 --reporter=list`
67+
- cleanup/live DEV: `npm run cleanup:supabase-dev-auth-test-users -- --dry-run --json`
68+
69+
Skipped lanes:
70+
71+
- Full samples smoke: SKIP by request and because samples were not in scope.
72+
- Admin DB Viewer validation: SKIP for PR_166 because Admin DB Viewer behavior was not changed.
73+
- Targeted provider/API validation for migrated product areas: SKIP for PR_166 because no product areas were migrated.
74+
- `npm run test:workspace-v2`: SKIP because no Project Workspace, toolState, or workspace runtime behavior changed. The command name is legacy; user-facing language remains Project Workspace.
75+
76+
## Validation Results
77+
78+
- PASS - Live DEV auth lifecycle audit.
79+
- PASS - `npm run validate:supabase-dev` (overall PASS; DEV direct PostgreSQL TLS warning remains advisory: `SELF_SIGNED_CERT_IN_CHAIN`)
80+
- PASS - `node --test tests/dev-runtime/SupabaseProviderContractStub.test.mjs` (29 tests passed)
81+
- PASS - `npx playwright test tests/playwright/account/SupabaseSignInSession.spec.mjs --project=playwright --workers=1 --reporter=list` (1 test passed)
82+
- PASS - `npm run cleanup:supabase-dev-auth-test-users -- --dry-run --json` returned `testDataCandidates: 0`.
83+
84+
## Manual Validation Notes
85+
86+
- Live local API validation used real Supabase DEV Auth and identity tables with `GAMEFOUNDRY_DB_PROVIDER=local-db`.
87+
- The account lifecycle was validated through server API routes, matching the browser-owned-provider boundary: browser surfaces call API/service contracts only.
88+
- Product data remained Local DB throughout the audit.
89+
- The created Codex validation account was deleted before packaging.
90+
- No UAT or PROD resources were created.
91+
92+
## Playwright V8 Coverage
93+
94+
- Report: `docs_build/dev/reports/playwright_v8_coverage_report.txt`
95+
- Guardrail: `docs_build/dev/reports/coverage_changed_js_guardrail.txt`
96+
- PR_166 does not introduce runtime JS source changes. The coverage report is regenerated by the targeted account Playwright run and may list PR_165 runtime files from the repository coverage reporter's HEAD/context scan as advisory warnings.
97+
98+
## Required Artifacts
99+
100+
- `docs_build/dev/reports/PR_26166_166-dev-supabase-auth-closeout-audit_report.md`
101+
- `docs_build/dev/reports/PR_26166_166-dev-supabase-auth-closeout-audit_cleanup_report.md`
102+
- `docs_build/dev/reports/codex_review.diff`
103+
- `docs_build/dev/reports/codex_changed_files.txt`
104+
- `tmp/PR_26166_166-dev-supabase-auth-closeout-audit_delta.zip`
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# PR_26166_167-product-data-provider-contract-hardening
2+
3+
## Branch Validation
4+
5+
PASS
6+
7+
- Current branch: `main`
8+
- Expected branch: `main`
9+
- Local branches found: `main`
10+
- `docs_build/dev/PROJECT_INSTRUCTIONS.md` read before PR_167 execution.
11+
12+
## Scope Summary
13+
14+
PASS
15+
16+
- Hardened the browser Toolbox registry client so product metadata must resolve through `/api/toolbox/registry/snapshot`.
17+
- Removed the silent empty browser-owned registry fallback from `toolbox/tool-registry-api-client.js`.
18+
- Kept the static missing-image path as display fallback only; it no longer carries product registry data.
19+
- Added contract coverage for API-backed browser product-data entrypoints.
20+
- No product table cutover was introduced.
21+
- No Supabase product tables, UAT resources, PROD resources, `.env.local`, secrets, password tables, or browser-owned auth/provider logic were changed.
22+
23+
## Requirement Checklist
24+
25+
- PASS - Treat PR_167 as one separate BUILD unit.
26+
- PASS - Main branch only; current branch was `main`.
27+
- PASS - Read `docs_build/dev/PROJECT_INSTRUCTIONS.md` before work.
28+
- PASS - Harden product-data provider contracts before cutover.
29+
- PASS - Ensure browser pages use API/service contracts only.
30+
- PASS - Identify and fix browser-owned product data paths: fixed the Toolbox registry API client's synthesized empty registry fallback.
31+
- PASS - No product table cutover was introduced.
32+
- PASS - Product data remains Local DB for this PR.
33+
- PASS - No silent fallback remains in the Toolbox registry client when the API contract is unavailable.
34+
- PASS - `npm run validate:supabase-dev` was skipped because PR_167 does not touch Supabase setup or Supabase data.
35+
- PASS - Targeted provider/API validation ran.
36+
- PASS - Targeted Playwright validation ran.
37+
- PASS - `npm run test:workspace-v2` ran because runtime/tool registry behavior changed. The command name is legacy; user-facing language remains Project Workspace.
38+
- PASS - No Supabase validation data was written, so no Supabase cleanup report is required.
39+
- PASS - Playwright impacted: yes.
40+
- PASS - Full samples smoke was not run.
41+
42+
## Product-Data Contract Findings
43+
44+
PASS
45+
46+
- Finding fixed: `toolbox/tool-registry-api-client.js` previously caught registry API failures and synthesized `{ activeTools: [], tools: [] }` in the browser. That made the browser own product metadata fallback state and could hide a broken API contract.
47+
- Fix: registry reads now fail visibly with the server API diagnostic until `/api/toolbox/registry/snapshot` succeeds.
48+
- Fix: a failed read is retryable, so transient route timing does not permanently freeze the diagnostic.
49+
- Preserved behavior: `getToolImageSource()` may still return `/assets/theme-v2/images/image-missing.svg` when a tool lacks an image field; that is a display asset fallback, not a product-data registry fallback.
50+
51+
## Validation Lane Report
52+
53+
Executed lanes:
54+
55+
- contract/runtime: `node --check toolbox/tool-registry-api-client.js`
56+
- contract/runtime: `node --check tests/dev-runtime/ProductDataProviderContractHardening.test.mjs`
57+
- contract/runtime: `node --test tests/dev-runtime/ProductDataProviderContractHardening.test.mjs`
58+
- provider contract regression: `node --test tests/dev-runtime/SupabaseProviderContractStub.test.mjs`
59+
- targeted Playwright provider/API: `GAMEFOUNDRY_AUTH_PROVIDER=local-db GAMEFOUNDRY_DB_PROVIDER=local-db npx playwright test tests/playwright/tools/ToolImageRegistry.spec.mjs tests/playwright/tools/ToolboxAdminMetadataSsot.spec.mjs --project=playwright --workers=1 --reporter=list`
60+
- Project Workspace legacy lane: `GAMEFOUNDRY_AUTH_PROVIDER=local-db GAMEFOUNDRY_DB_PROVIDER=local-db npm run test:workspace-v2`
61+
62+
Skipped lanes:
63+
64+
- `npm run validate:supabase-dev`: SKIP because this PR does not touch Supabase configuration, Supabase Auth, Supabase DDL, or Supabase data.
65+
- Full samples smoke: SKIP by request and because samples were not in scope.
66+
- Admin DB Viewer validation: SKIP because Admin DB Viewer behavior is not changed in PR_167.
67+
- Product cutover validation: SKIP because no product table cutover occurs until PR_170.
68+
69+
## Validation Results
70+
71+
- PASS - `node --check toolbox/tool-registry-api-client.js`
72+
- PASS - `node --check tests/dev-runtime/ProductDataProviderContractHardening.test.mjs`
73+
- PASS - `node --test tests/dev-runtime/ProductDataProviderContractHardening.test.mjs` (3 tests passed)
74+
- PASS - `node --test tests/dev-runtime/SupabaseProviderContractStub.test.mjs` (29 tests passed)
75+
- PASS - Targeted Playwright provider/API lane (9 tests passed)
76+
- PASS - `npm run test:workspace-v2` (5 tests passed)
77+
78+
## Manual Validation Notes
79+
80+
- Captured Admin Tool Votes diagnostics during the first targeted run and confirmed the zero-row page state was caused by an auth-provider selector mismatch, not product metadata rendering.
81+
- Reran the impacted browser lane with explicit `GAMEFOUNDRY_AUTH_PROVIDER=local-db` and `GAMEFOUNDRY_DB_PROVIDER=local-db`, matching PR_167's pre-cutover Local DB product-data scope.
82+
- Verified Admin Tool Votes and Toolbox index render from API snapshots and do not request the retired browser registry module.
83+
- Validation wrote no Supabase records. Playwright-created local DB state used per-run temp SQLite files and was cleaned up when each test server closed.
84+
85+
## Playwright V8 Coverage
86+
87+
- Report: `docs_build/dev/reports/playwright_v8_coverage_report.txt`
88+
- Guardrail: `docs_build/dev/reports/coverage_changed_js_guardrail.txt`
89+
- PR_167 changed runtime JS: `toolbox/tool-registry-api-client.js`
90+
- Coverage evidence: `(90%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 26/29`
91+
- Advisory note: because the PR stack is still uncommitted locally, the coverage report also lists changed runtime JS from earlier stacked PRs as warnings.
92+
93+
## Required Artifacts
94+
95+
- `docs_build/dev/reports/PR_26166_167-product-data-provider-contract-hardening_report.md`
96+
- `docs_build/dev/reports/codex_review.diff`
97+
- `docs_build/dev/reports/codex_changed_files.txt`
98+
- `docs_build/dev/reports/playwright_v8_coverage_report.txt`
99+
- `docs_build/dev/reports/coverage_changed_js_guardrail.txt`
100+
- `tmp/PR_26166_167-product-data-provider-contract-hardening_delta.zip`

0 commit comments

Comments
 (0)