Two levels
Five layers
1
Capture
?ref=<CODE> on any landing page writes to localStorage["cc:ref-code"] via captureRefFromUrl(), called on app mount. Deliberately not a cookie — no Safari or ad-blocker loss.2
Carry
The stashed code travels as a
cc:ref:<CODE> SIWE resource line, the same channel as the partner role hint.3
Bind
siwe-verify’s resolveRoles stamps merchants.partner_referrer_id only on the first merchant-row insert — new-merchant-only, first-touch. Guarded against inactive partners and self-referral. Bound once, never overwritten by a later link.4
Manual recovery
A field in merchant Settings calls
bind-referral, which binds only while partner_referrer_id IS NULL. Recovers a capture lost to cleared local storage.5
Platform override
/platform-admin → Merchants calls platform-admin-set-referrer — the only path that can change an already-bound merchant. Writes an audit_logs row.Codes
Six characters, canonical, generated bygenerateReferralCode, excluding 0, 1, and O to avoid transcription errors.
Compliance
The partner payout address is screened for sanctions before it is baked into a pool’s immutable init code, regardless of whether that partner has ever signed in. A referrer auto-created from a code may never have completed SIWE and therefore never been screened at sign-in. This is self-protection as much as compliance: a sanctioned or frozen address committed into an immutable pool permanently locks funds for everyone in that pool.Partner acquisition
/partners is the public landing page. It sets setPartnerRoleHint("partner"), and siwe-verify auto-creates the referrers row on first sign-in, so there is no separate signup.
Latent bug worth remembering
merchants.name is NOT NULL with no default. The auto-create path in resolveRoles did not seed it, so the insert errored, the error was swallowed, and all new merchant self-onboarding silently failed. It now seeds name: "Merchant <0x6>".
The lesson generalises: a swallowed insert error in an auth path produces a silent, total onboarding failure with no visible symptom.