Skip to content

Commit 994b844

Browse files
authored
Merge PR_26179_OWNER_035-dev-auth-user-key-db-authority
Fix DEV auth user key authority.
2 parents 13cbe98 + 1fe3081 commit 994b844

15 files changed

Lines changed: 566 additions & 150 deletions
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# PR_26179_OWNER_035-dev-auth-user-key-db-authority Branch Validation
2+
3+
Status: PASS
4+
5+
- Current branch: `PR_26179_OWNER_035-dev-auth-user-key-db-authority`
6+
- Base branch: `main`
7+
- Rebased onto latest synchronized main: PASS
8+
- Worktree clean before validation: PASS
9+
- Main excludes the fix until PR merge: PASS
10+
- Branch ready to push/open PR: PASS
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# PR_26179_OWNER_035-dev-auth-user-key-db-authority Manual Validation Notes
2+
3+
Status: READY FOR OWNER VALIDATION
4+
5+
Manual checks after merge:
6+
7+
1. Run the approved DEV identity sync against DEV.
8+
2. Confirm `qbytes.dq@gmail.com` exists in Supabase Auth.
9+
3. Confirm `qbytes.dq@gmail.com` exists in the product `users` table.
10+
4. Confirm product `users.authProviderUserId` equals Supabase Auth `auth.users.id`.
11+
5. Sign in as `qbytes.dq@gmail.com` without changing password.
12+
6. Confirm the resolved session uses the database `users.key`.
13+
14+
Packaging note:
15+
16+
- Read-only pre-package verification found the Auth user present but the product users row missing on the current DEV target.
17+
- The mutating DEV identity sync was intentionally not run during this package/push step.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# PR_26179_OWNER_035-dev-auth-user-key-db-authority
2+
3+
## Summary
4+
5+
This PR makes DEV account session resolution treat the database `users` row as authoritative.
6+
7+
Runtime sign-in now resolves a session only when the Supabase Auth user id matches `users.authProviderUserId`. Matching by email alone is not accepted for login/session resolution. Email remains valid only for the approved DEV identity sync step that locates the existing database `users` row before writing the real Supabase Auth id back to `users.authProviderUserId`.
8+
9+
## Branch Status
10+
11+
- Source branch: `PR_26179_OWNER_035-dev-auth-user-key-db-authority`
12+
- Base branch: `main`
13+
- Rebased onto main HEAD: `13cbe98955c1bcc014bff07480b7d3399386e72f`
14+
- Main still excludes this fix until PR merge: yes
15+
16+
## Diagnostic Findings
17+
18+
### Where `users.key` comes from
19+
20+
- DEV seed setup still defines static fixture keys in `src/dev-runtime/seed/seed-db-keys.mjs` for seed/bootstrap data.
21+
- Before this PR, DEV Supabase identity sync used those seed constants as the authoritative app user keys.
22+
- After this PR, DEV sync locates existing database `users` rows by email and reads `users.key` from the database row. Missing or duplicate database rows are explicit setup errors.
23+
24+
### Where `authProviderUserId` is populated
25+
26+
- Account provisioning continues to write `authProviderUserId` in `src/dev-runtime/server/local-api-router.mjs` through the API/server path.
27+
- DEV identity sync reads Supabase Auth `auth.users.id`, reads the existing product `users.key` from the database row found by email, then writes the real Auth id to `users.authProviderUserId`.
28+
29+
### Runtime resolution
30+
31+
- Supabase sign-in/session resolution now requires an active product `users` row whose `authProviderUserId` equals the Supabase Auth user id.
32+
- If Auth succeeds but the product row is not linked, the API returns a controlled setup message directing the operator to run the approved DEV identity sync.
33+
- Runtime login no longer hardcodes DavidQ/user keys and no longer uses display name as an identity key.
34+
35+
## Exact Fix
36+
37+
- Removed email fallback from Supabase sign-in session resolution.
38+
- Added a Creator-safe setup failure when Auth succeeds but the matching email row has not been linked to the Auth id.
39+
- Added a narrow server-side Postgres client injection hook for tests, with default runtime behavior unchanged.
40+
- Refactored DEV creator identity sync so canonical identity definitions are email-based and database `users.key` is read from existing rows.
41+
- Changed role assignment and cleanup repair logic to derive canonical user keys from database rows.
42+
- Removed the Alfa toolbox tag/design/configuration helper behavior that upserted seed `users` rows over DEV account keys.
43+
- Changed the DEV identity sync default so existing Supabase Auth users are updated without sending a password. Password updates now require explicit `--update-passwords`.
44+
- Added regression tests for auth id matching, stale authProviderUserId handling, existing database key preservation, missing database rows, Tags API seeding not modifying `users`, and password-safe sync defaults.
45+
46+
## Current DEV Data Note
47+
48+
Read-only verification before packaging found:
49+
50+
- `qbytes.dq@gmail.com` exists in Supabase Auth.
51+
- `qbytes.dq@gmail.com` is currently missing from the product `users` table.
52+
- Therefore `users.authProviderUserId` is not synced for that account yet.
53+
54+
The mutating DEV identity sync was not run during this package/push step. Next action after this PR is merged: run the approved DEV identity sync against the current DEV database, then re-test sign-in.
55+
56+
## Files Changed
57+
58+
- `src/dev-runtime/server/local-api-router.mjs` - updated
59+
- `src/dev-runtime/testing/supabase-dev-creator-identity-seed-sync.mjs` - updated
60+
- `src/dev-runtime/toolbox-api/alfa-tool-services.mjs` - updated
61+
- `dev/scripts/sync-supabase-dev-creator-identities.mjs` - updated
62+
- `dev/tests/dev-runtime/SupabaseProviderContractStub.test.mjs` - updated
63+
- `dev/tests/dev-runtime/SupabaseDevCreatorIdentitySeedSync.test.mjs` - updated
64+
- `dev/tests/dev-runtime/TagsApiService.test.mjs` - updated
65+
66+
## Validation
67+
68+
PASS:
69+
70+
- `git diff --check`
71+
- `npm run validate:canonical-structure`
72+
- `node --check src/dev-runtime/server/local-api-router.mjs`
73+
- `node --check src/dev-runtime/testing/supabase-dev-creator-identity-seed-sync.mjs`
74+
- `node --check src/dev-runtime/toolbox-api/alfa-tool-services.mjs`
75+
- `node --check dev/scripts/sync-supabase-dev-creator-identities.mjs`
76+
- `node --check dev/tests/dev-runtime/SupabaseProviderContractStub.test.mjs`
77+
- `node --check dev/tests/dev-runtime/SupabaseDevCreatorIdentitySeedSync.test.mjs`
78+
- `node --check dev/tests/dev-runtime/TagsApiService.test.mjs`
79+
- `node --test dev/tests/dev-runtime/SupabaseDevCreatorIdentitySeedSync.test.mjs`
80+
- `node --test --test-name-pattern "Supabase sign-in resolves|Supabase sign-in does not" dev/tests/dev-runtime/SupabaseProviderContractStub.test.mjs`
81+
- `node --test dev/tests/dev-runtime/TagsApiService.test.mjs`
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# PR_26179_OWNER_035-dev-auth-user-key-db-authority Requirement Checklist
2+
3+
Status: PASS
4+
5+
- Database `users` row is authoritative for `users.key`: PASS
6+
- Runtime sign-in does not use hardcoded DavidQ/user keys: PASS
7+
- Runtime sign-in does not use display name as identity key: PASS
8+
- Supabase Auth id must match `users.authProviderUserId`: PASS
9+
- Email is used only by DEV identity sync to locate existing DB rows: PASS
10+
- DEV identity sync reads DB-owned `users.key`: PASS
11+
- DEV identity sync writes Auth id to `users.authProviderUserId`: PASS
12+
- Toolbox seed helper no longer upserts seed rows into `users`: PASS
13+
- Existing Auth user password is not changed by default sync: PASS
14+
- Required reports under `dev/reports/`: PASS
15+
- Repo-structured ZIP under `dev/workspace/zips/`: PASS
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# PR_26179_OWNER_035-dev-auth-user-key-db-authority Validation Lane Report
2+
3+
Status: PASS
4+
5+
Lane: Owner auth identity authority and DEV sync guardrails.
6+
7+
Coverage:
8+
9+
- Supabase session resolution requires `users.authProviderUserId` to match Auth id.
10+
- Stale `authProviderUserId` does not create a session by email fallback.
11+
- DEV identity sync requires existing product users rows and preserves DB-owned keys.
12+
- Tags API service seeding does not write seed user rows into `users`.
13+
- Canonical repository structure remains valid.
14+
15+
Not run:
16+
17+
- Full workspace smoke. Not required for this package/push step; targeted auth and Tags guardrail validation passed.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# PR_26179_OWNER_035-dev-auth-user-key-db-authority Validation Report
2+
3+
Status: PASS
4+
5+
Validated commands:
6+
7+
- `git diff --check` - PASS
8+
- `npm run validate:canonical-structure` - PASS
9+
- `node --check src/dev-runtime/server/local-api-router.mjs` - PASS
10+
- `node --check src/dev-runtime/testing/supabase-dev-creator-identity-seed-sync.mjs` - PASS
11+
- `node --check src/dev-runtime/toolbox-api/alfa-tool-services.mjs` - PASS
12+
- `node --check dev/scripts/sync-supabase-dev-creator-identities.mjs` - PASS
13+
- `node --check dev/tests/dev-runtime/SupabaseProviderContractStub.test.mjs` - PASS
14+
- `node --check dev/tests/dev-runtime/SupabaseDevCreatorIdentitySeedSync.test.mjs` - PASS
15+
- `node --check dev/tests/dev-runtime/TagsApiService.test.mjs` - PASS
16+
- `node --test dev/tests/dev-runtime/SupabaseDevCreatorIdentitySeedSync.test.mjs` - PASS, 2 tests
17+
- `node --test --test-name-pattern "Supabase sign-in resolves|Supabase sign-in does not" dev/tests/dev-runtime/SupabaseProviderContractStub.test.mjs` - PASS, 2 tests
18+
- `node --test dev/tests/dev-runtime/TagsApiService.test.mjs` - PASS, 3 tests
-3.93 KB
Binary file not shown.

dev/reports/codex_review.diff

-54.7 KB
Binary file not shown.

dev/scripts/sync-supabase-dev-creator-identities.mjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,21 +66,24 @@ function formatRecordList(label, records, selector) {
6666
const args = new Set(process.argv.slice(2));
6767
const json = args.has("--json");
6868
const dryRun = args.has("--dry-run");
69+
const updatePasswords = args.has("--update-passwords");
6970
const envLoad = loadEnvLocal();
7071

7172
try {
72-
const result = await syncSupabaseDevCreatorIdentities({ dryRun });
73+
const result = await syncSupabaseDevCreatorIdentities({ dryRun, updatePasswords });
7374
if (json) {
7475
console.log(JSON.stringify({
7576
envLocalLoaded: envLoad.loaded,
7677
envLocalLoadedKeys: envLoad.loadedKeys,
78+
updatePasswords,
7779
...result,
7880
}, null, 2));
7981
} else {
8082
console.log(`Supabase DEV creator identity sync: ${result.status}`);
8183
console.log(envLoad.loaded
8284
? `.env.local loaded (${envLoad.loadedKeys} key(s) applied).`
8385
: ".env.local was not found.");
86+
console.log(`Password updates for existing Auth users: ${updatePasswords ? "enabled" : "disabled"}.`);
8487
formatCounts("Before", result.beforeCounts);
8588
formatCounts("After", result.afterCounts);
8689
formatRecordList("Auth upserts", result.authUpsertRecords, (record) => `${record.email}: ${record.action}`);

0 commit comments

Comments
 (0)