Skip to content

[#567] Support non-Farcaster wallet users#568

Merged
realproject7 merged 4 commits intomainfrom
task/567-non-fid-users
Mar 26, 2026
Merged

[#567] Support non-Farcaster wallet users#568
realproject7 merged 4 commits intomainfrom
task/567-non-fid-users

Conversation

@realproject7
Copy link
Copy Markdown
Owner

Summary

  • Migration 00028: make fid nullable, add unique index on primary_address for wallet-only user upserts
  • register-by-wallet: no longer returns 404 for non-Farcaster wallets — creates user record with fid=NULL, wallet address stored as primary_address
  • buildUserData: third path for wallet-only users (no SteemHunt, no Neynar)
  • Upsert logic: uses primary_address as key when fid is null (both register-by-wallet and onboard routes)
  • User lookup: getUserFromDB and all route lookups now search by primary_address as fallback
  • getFarcasterProfile: skips DB shortcut for wallet-only users so they don't get a broken profile object
  • Supabase types: fid is now number | null across Row/Insert/Update
  • All existing FID user flows are completely unaffected

Fixes #567

Test plan

  • Connect a non-Farcaster wallet → verify user record created (fid=NULL)
  • Profile page renders correctly for wallet-only user (truncated address, no FC data)
  • Connect a Farcaster wallet → verify existing behavior unchanged
  • Run migration 00028 against Supabase
  • Verify build passes (npm run build)

🤖 Generated with Claude Code

- Migration 00028: make fid nullable, add unique index on primary_address
- buildUserData: add third path for wallet-only users (fid=null)
- register-by-wallet: no longer rejects non-Farcaster wallets with 404,
  creates user record with fid=null and wallet address stored
- Upsert logic: use primary_address as key when fid is null
- User lookup: search by primary_address as fallback for wallet-only users
- getFarcasterProfile: skip DB shortcut for wallet-only users (fid=null)
- Supabase types: fid is now number | null across Row/Insert/Update

Fixes #567

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
plotlink Ignored Ignored Mar 26, 2026 4:00pm

Request Review

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T2b approves. Migration correctly handles nullable fid with partial unique index on primary_address. Dual lookup pattern is consistent across all routes. Wallet-only user path in buildUserData is clean. No issues found.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The wallet-only creation path is in place, but the new upsert logic still breaks when an existing wallet-only user later gains a Farcaster identity.

Findings

  • [high] Both update paths choose the lookup key from the new payload (userData.fid) instead of from the row that already exists. If a wallet-only row already exists for primary_address = <wallet> and that wallet later resolves to a Farcaster account, the insert will conflict on the new unique primary_address index, then the follow-up update will target fid = <new fid> even though the existing row still has fid = NULL. That means the update matches no row and the route 500s instead of upgrading the wallet-only user into an FID-backed user.
    • File: src/app/api/user/register-by-wallet/route.ts:114
    • File: src/app/api/user/onboard/route.ts:115
    • Suggestion: when existingUser was found, update by that existing row's identity (for example id or primary_address) rather than by userData.fid. Otherwise the wallet-only -> Farcaster transition is broken.

Decision

Requesting changes because the current upsert logic fails a realistic account-upgrade path and does not fully keep wallet-only and FID users interoperable.

When a wallet-only user (fid=null) later resolves to a Farcaster
identity, the update must target the existing row by id/primary_address,
not by the new fid which doesn't match the existing null fid row.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The wallet-only -> Farcaster upgrade path is fixed, but the latest fallback still regresses a normal FID-user refresh path.

Findings

  • [high] In register-by-wallet, the unique-violation fallback now updates by primary_address when existingUser was not found at lookup time. That breaks Farcaster users who connect through a newly verified wallet that is not yet present in the cached DB row. In that case the initial lookup misses, the insert conflicts on the existing unique fid, and the fallback update targets primary_address = <new wallet> even though the existing FID row usually has a different primary_address. The update matches no row and the route 500s, which violates the ticket's requirement that FID users remain unaffected.
    • File: src/app/api/user/register-by-wallet/route.ts:116
    • Suggestion: on unique-violation fallback, update by the actual conflicting identity. For FID-backed payloads that should still be fid = userData.fid; reserve the primary_address fallback for the wallet-only (fid = NULL) case or query the conflicting row first.

Decision

Requesting changes because the current fallback can still break existing Farcaster users when they connect through an address that has not yet been cached locally.

…s for wallet-only

When existingUser is null but insert conflicts on fid (FID user with
new wallet), update by fid. Only fall back to primary_address for
wallet-only (fid=null) conflicts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

register-by-wallet now handles both conflict cases, but onboard still has the same stale-wallet / existing-FID conflict gap.

Findings

  • [high] src/app/api/user/onboard/route.ts still only inserts when existingUser lookup misses, with no unique-violation recovery path. If an existing Farcaster user connects through a newly verified wallet that is not yet present in the cached DB row, the lookup misses, the insert conflicts on the existing unique fid, and the route returns 500 instead of refreshing the existing user. That means FID users are still not fully unaffected by this change.
    • File: src/app/api/user/onboard/route.ts:131
    • Suggestion: mirror the register-by-wallet conflict handling here as well: if insert hits 23505, update by fid for FID-backed payloads and by primary_address for wallet-only payloads, or otherwise resolve and update the conflicting row.

Decision

Requesting changes because the manual refresh path still breaks a realistic existing-user flow.

Mirror register-by-wallet's conflict handling: when insert conflicts
on fid or primary_address, fall back to update by the conflicting
identity instead of 500ing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE

Summary

The remaining conflict-handling gaps are fixed. Both register-by-wallet and onboard now recover from unique-violation inserts by updating the conflicting row through the correct identity, so wallet-only users and existing FID users both keep working.

Findings

  • None.

Decision

Approving because the nullable-FID schema change, wallet-only user path, and conflict recovery logic now satisfy the Batch 25 / #567 requirements without regressing existing Farcaster users.

@realproject7 realproject7 merged commit 6c995c5 into main Mar 26, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support non-Farcaster wallet users — make FID nullable, fix register flow

2 participants