Skip to content

V48 Gate 1: Identity and authentication interactive QA#248

Merged
geraldarthurdavis merged 19 commits into
version/v48from
v48/gate-1-identity-auth-interactive-qa
Jun 12, 2026
Merged

V48 Gate 1: Identity and authentication interactive QA#248
geraldarthurdavis merged 19 commits into
version/v48from
v48/gate-1-identity-auth-interactive-qa

Conversation

@geraldarthurdavis

Copy link
Copy Markdown
Contributor

Summary

Closes V48 Gate 1 — the identity/authentication interactive QA gate over promoted V47 canon. Sixteen commits of live-QA-driven repairs, evidence, and tooling; Track 1 of the V48 charter is complete and verified end-to-end on the staging-testnet deployment (ledger: BITCODE_V48_QA.md).

Functional repairs (all live-verified)

  • Wallet OAuth sign-in (F5): GoTrue validates redirect_to by exact string match — the ?next= query defeated the allow-list and stranded every auth code (and the PKCE verifier) on the Site URL origin; no session was ever minted, from localhost or production www. redirect_to is now query-free via uapi/lib/supabase-auth-redirect.ts; the post-auth destination travels through origin-local storage.
  • Identity-derived wallet binding (F5a): the canonical sign-up signs on the OAuth provider page, so nothing was staged client-side to replay and profiles stayed unbound. /api/wallet/authenticate gains a server-derived source: 'oauth-identity' mode; WalletSessionPersistenceBridge triggers it; the signed-in panel reconnect backfills payment address + signature proof.
  • Live on-chain BTC balance: new session-scoped GET /api/wallet/btc-balance (mempool.space, testnet4-first) feeding the Wallet pane "BTC in wallet" card — previously no chain-balance source existed anywhere.
  • Legacy /terminal landings (F8 interim): wallet sign-in lands on /packs; GitHub connect lands on /packs?auxillary-open-to=externals; all seven contract repair/recovery routes retargeted to /packs.
  • Externals Connected Scope showed 8 of 46 repositories (hard slice); now renders all.

Evidence, tooling, posture

  • BITCODE_V48_QA.md: findings F1–F11 with root-cause traces, fixes, verification evidence, and the Track 1 checklist (complete; email deferred by decision — wallet+GitHub is the identity root).
  • supabase/queries/v48_qa_01..05: committed QA SQL (auth/identity, binding, token-safe connections, repository inventory, Track 1 rollup) with run-after mapping.
  • BITCODE_SPEC_V48_NOTES.md: Gate 1 reflection + specification intent for the eventual draft family (notes-only posture preserved; draft-notes checker green).
  • Refreshed built .d.ts outputs isolated in their own commit.

Verification

  • Jest: new/updated suites for the redirect helper, wallet authenticate route (oauth-identity mode), persistence bridge, BTC balance route, VCS callbacks, externals pane — all green alongside the adjacent wallet/auxillaries suites.
  • Live QA: cold-state wallet sign-up (session in ~4s, auto-bind on /packs mount), GitHub App install with 46-repo inventory, fauceted testnet4 balance rendering, Track 1 rollup green in one row.
  • run-bitcode-spec-quality + draft-notes checker green locally and in pre-commit.

🤖 Generated with Claude Code

geraldarthurdavis and others added 19 commits June 12, 2026 16:01
…ost-auth on /packs

GoTrue validates redirect_to with exact string matching against the Auth
allow-list; the ?next= query the app appended defeated the match, so every
auth code fell back to the Site URL origin (apex bitcode.exchange) where the
PKCE verifier does not exist - no session was ever minted, from localhost or
production www. Proven via /auth/v1/authorize + garbage-code /auth/v1/callback
probes (matrix in BITCODE_V48_QA.md F5).

- uapi/lib/supabase-auth-redirect.ts: redirect_to stays query-free; the
  post-auth destination travels via origin-local storage, consumed once by
  LoginCallbackClient (explicit ?next= still wins for back-compat)
- Converted initiators: AuxillariesWalletConnectionPanel, SocialAccountLinker,
  SocialLoginButton
- Wallet sign-in now lands on /packs instead of the legacy /terminal overlay
  route that buildAuxillariesRoutePath still targets (QA ledger F8)
- Regression test tests/supabaseAuthRedirect.test.ts pins the query-free
  invariant; registered in jest.config.cjs
- BITCODE_V48_QA.md: F5 root cause corrected and verified (session mints,
  last_sign_in_at set), F8 legacy /terminal finding added, Track 1 updated;
  open residual: wallet binding fields stay null after sign-in

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The canonical wallet sign-up signs on the prod /tps/wallet/authorize page,
so nothing is staged in the initiating origin for WalletSessionPersistence-
Bridge to replay, /api/wallet/authenticate (the only settings.walletBinding
writer) was never called, and profiles stayed unbound after sign-in: Wallet
Auxillary showed 'No Bitcoin wallet connected' and Profile readiness blocked
on identity/binding. GoTrue also drops the provider's custom bitcoin_* claims
from identity_data, so the proof material is unrecoverable client-side.

- /api/wallet/authenticate: new source 'oauth-identity' mode derives the
  binding server-side from the GoTrue-verified custom:bitcode-bitcoin
  identity (address+network from the identity sub, provider from the
  userinfo label; no client-trusted wallet fields), writes
  settings.walletBinding (proofKind provider_session, status pending),
  user_connections (auth_source bitcoin_wallet_oauth_identity), and
  username; idempotent no-op when the binding already matches
- WalletSessionPersistenceBridge: when a session exists with nothing
  replayable staged locally, triggers the identity-derived bind and mirrors
  the result into the local wallet identity so the Wallet Auxillary renders
  the connection
- Route response now carries network; coverage in walletAuthenticateRoute
  and walletSessionPersistenceBridge tests (12 passing)
- BITCODE_V48_QA.md: F5a trace + fix + retest steps recorded

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ators

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…o consumer

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… in V48 notes

Records the accepted Gate 1 findings ledger (BITCODE_V48_QA.md F1-F10), the
redirect_to exact-match law, identity-derived wallet binding, the /packs
post-auth landing, and the specification intent queued for the full V48
draft family, which opens at Gate 1 closure per the V47 Gate 1 precedent.
Notes-only posture and all draft-notes checker phrases preserved
(check-bitcode-draft-notes + run-bitcode-spec-quality verified locally).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Regenerated .d.ts/tsbuildinfo outputs from the local workspace build during
V48 QA environment setup; no source changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Auth App residue

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…OST handler

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The VCS connect redirect targeted the legacy /terminal overlay root (QA
ledger F8). AuxillariesProvider reads the auxillary-open-to param on any
route, so the callback now lands on /packs?auxillary-open-to=externals and
the Externals pane opens over the canonical packs surface, making the new
GitHub connection immediately visible. Ledger records the verified install
(installation token, connection saved) after replacing placeholder GitHub
App env values.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ipts

- Externals Connected Scope hard-capped pills at 8 while announcing the full
  count (46); now renders every repository in a scrollable wrap
- Adds supabase/queries/v48_qa_01..05: auth/identity, profile wallet binding,
  token-safe connections projection, repository inventory, and a one-row
  Track 1 readiness rollup — each self-targets the latest wallet-identity
  user and documents when to run it; ledger carries the run-after map
- Ledger: GitHub connect + 46-repo inventory verified; token-exposure
  hygiene note (use the token-safe projection, never raw connection_data)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…l to /packs

'Add Email' (and every readiness repair CTA) navigated to the legacy
/terminal overlay root, which renders no auxillary experience. All seven
contract-emitted repair/recovery routes now target /packs?auxillary-open-to=
<pane>; AuxillariesProvider opens the pane overlay on any route. The v40
browser-proof checker pins only bitcode-browser-proof.ts route states, which
are untouched (QA ledger F8).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ty root

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Nothing in the codebase ever fetched a chain balance - btcFeeBalance was
only read from profile fields nothing writes, so the 'BTC in wallet' card
showed 'Binding pending' and the nav chip rendered null as 0 BTC.

- New session-scoped GET /api/wallet/btc-balance derives the bound
  addresses server-side from the profile wallet binding (no client-trusted
  address), queries mempool.space, and returns confirmed/pending sats+BTC.
  The ambiguous 'testnet' binding label tries testnet4 first, then
  testnet3, so fauceted coins surface wherever they landed.
- Wallet pane 'BTC in wallet' card now shows the live balance with network
  and pending-confirmation detail, falling back to posture text when the
  source is unavailable.
- Ledger documents testnet4 faucets (coinfaucet.eu, altquick.com) and the
  mempool.space testnet4 explorer patterns.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ress repair path proven

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…uthoring moves to its own gate

The signed-in Leather reconnect rewrites the wallet connection auth_source
from bitcoin_wallet_oauth_identity to bitcoin_wallet_provider, so the
rollup's wallet join now accepts both and surfaces payment_address,
proof_kind, and auth_source. Notes clarify the full V48 draft family opens
in a dedicated authoring gate; Gate 1 closes as the identity/auth QA gate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
engi-uapi Ready Ready Preview, Comment Jun 12, 2026 9:55pm

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 630ee980a3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const existingBinding =
asRecord(asRecord(settingsRecord?.bitcodeProfile)?.walletBinding) ??
asRecord(settingsRecord?.walletBinding);
if (readNonEmptyString(existingBinding?.address) === address) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Repair missing connection rows before idempotent no-op

If the OAuth-identity bind writes user_profiles successfully but the later user_connections upsert fails or is temporarily blocked, the profile now contains the same wallet address and every retry exits here before reattempting the connection write. That leaves the user with a wallet binding but no active wallet connection row even after the underlying failure is fixed, so the bridge cannot self-heal the state it is meant to backfill; the idempotency check should also verify/repair the connection record before returning.

Useful? React with 👍 / 👎.

@geraldarthurdavis
geraldarthurdavis merged commit 17a14e6 into version/v48 Jun 12, 2026
28 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.

1 participant