qa/harness-server.js boots the real server with chain reads stubbed (COLD=1 reproduces the cached-index
state that left #787 without a profile). qa/join-flow-e2e.mjs drives the real /join-now page with a fake
wallet producing genuine secp256k1 signatures.
Three scenarios pass: signs on a cold index (9) - the gate appears on their own dashboard; refuses to
sign (10) - REGRESSION, the join still completes and redirects with the page usable; signs on a warm
index (9). Full set green: profiles-unit 28, signin-fallback 7, gate-e2e 47, join-flow 9/10/9, plus the
live shared-link check.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Findings fixed: the gate's buttons had no stable ids (fragile to test and maintain), and finishing the
gate left the member on the pitch tab where the profile card and Messages are not visible, so
completion now opens the Position Dashboard tab. /api/public/profile/email-start returns devCode
outside production so the flow is testable locally, matching the InstantAdPay pattern.
qa/profiles-unit.mjs (28 assertions) and qa/gate-e2e.mjs (47 assertions, real sessions, real UI) with
a README. All pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>