Skip to content

feat(auth): Sign in with CoinPay - #167

Merged
sh1pt-actions-fleet[bot] merged 1 commit into
masterfrom
feat/coinpay-signin
Oct 29, 2026
Merged

sh1pt-actions-fleet[bot] merged 1 commit into
masterfrom
feat/coinpay-signin

Conversation

@sh1pt-actions-fleet

Copy link
Copy Markdown
Contributor

Sign in with CoinPay, the house master account.

  • Confidential OIDC client cp_e15154efcfa3d1f4d519a224 (OAuth 2.1, PKCE required, not legacy), auth code + PKCE S256 + state + nonce via @profullstack/coinpay-onboard/oauth 0.3.1, redirect https://pairux.com/api/v1/coinpay/oauth/callback, scopes openid profile email.
  • Bound by CoinPay sub in public.coinpay_identities (migration 20261029060000, already applied to prod by hand + NOTIFY pgrst). Never by email. A new CoinPay login creates a new auth user with an @coinpay.pairux.invalid placeholder; the CoinPay email is unverified contact info only.
  • Session is minted server side (admin generateLink magic-link hash redeemed with verifyOtp), refused for accounts whose email is unconfirmed. Pending invite / ?ref= handled like /auth/callback.
  • Invite bonuses still require a verified email: credits.ts treats the placeholder as unconfirmed, so CoinPay-only accounts stay pending.
  • UI: "Sign in with CoinPay" first on /login and /signup; Connect / Disconnect card on /settings. Strings added to all 19 locales.
  • The pairux CLI signs in through /cli/authorize on the website, so it inherits CoinPay. The desktop app's password login is unchanged.

Tests: src/lib/coinpay-signin.test.ts + a credits case. tsc clean, web vitest 117 files / 1233 tests green.

🤖 Generated with Claude Code

CoinPay is the house master account. Confidential OIDC client with PKCE S256,
state and nonce via @profullstack/coinpay-onboard/oauth; redirect
/api/v1/coinpay/oauth/callback.

- Binds to the CoinPay sub in public.coinpay_identities (RLS on, service role
  only), never by email. A first CoinPay login creates a new auth user with an
  undeliverable placeholder address; the CoinPay email is unverified contact
  info on the identity row. Session minted server side (admin magic-link hash
  redeemed with verifyOtp), refused for unconfirmed accounts.
- "Sign in with CoinPay" first on /login and /signup; Connect / Disconnect
  card in Settings (connect needs this session; disconnect refused when
  CoinPay is the only way in). Strings in all 19 locales.
- Invite bonuses keep requiring a confirmed email: credits.ts treats the
  placeholder address as unconfirmed.
- Tests: email collision gets a new account, connect needs a session,
  forged/edited/expired pending cookie, bad state/nonce, placeholder invite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​profullstack/​coinpay-onboard@​0.3.17610010093100
Added@​profullstack/​footer@​0.5.08310010095100

View full report

@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

54 finding(s)

HIGH/CRITICAL: 4 | MEDIUM: 29 | LOW: 21

Severity Rule Location
HIGH sh-eval-expansion .githooks/pre-commit:33
HIGH js-electron-node-integration apps/desktop/src/main/window.ts:49
HIGH sh-unquoted-expansion-destructive apps/installer/scripts/install.sh:717
HIGH sh-unquoted-expansion-destructive apps/installer/scripts/install.sh:921
MEDIUM sh-remote-script-execution apps/installer/scripts/install.sh:693
MEDIUM sh-remote-script-execution apps/installer/scripts/install.sh:824
MEDIUM sh-remote-script-execution apps/installer/scripts/install.sh:826
MEDIUM sh-remote-script-execution apps/installer/scripts/install.sh:1084
MEDIUM sh-remote-script-execution apps/installer/scripts/install.sh:1086
MEDIUM sh-remote-script-execution apps/livekit/setup-livekit-server.sh:93
MEDIUM sh-remote-script-execution apps/turn/deploy-droplet.sh:62
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:52
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:79
MEDIUM js-unescaped-html-sink apps/web/src/app/c/[handle]/page.tsx:199
MEDIUM js-open-redirect apps/web/src/app/cli/authorize/consent.tsx:68
MEDIUM js-unescaped-html-sink apps/web/src/app/l/[joinCode]/page.tsx:146
MEDIUM js-unescaped-html-sink apps/web/src/app/l/[joinCode]/page.tsx:230
MEDIUM js-unescaped-html-sink apps/web/src/app/layout.tsx:150
MEDIUM js-unescaped-html-sink apps/web/src/app/live/page.tsx:154
MEDIUM js-unescaped-html-sink apps/web/src/app/page.tsx:98
MEDIUM js-unescaped-html-sink apps/web/src/app/pricing/page.tsx:262
MEDIUM js-open-redirect apps/web/src/app/settings/copilot/copilot-settings.tsx:144
MEDIUM js-unescaped-html-sink apps/web/src/app/u/[username]/page.tsx:285
MEDIUM js-open-redirect apps/web/src/components/billing/useCheckout.ts:81
MEDIUM js-unescaped-html-sink apps/web/src/components/pit-footer.tsx:24
MEDIUM js-open-redirect apps/web/src/hooks/useDesktopHandoff.ts:24
MEDIUM redos-nested-quantifier apps/web/src/lib/deliverable.ts:11
MEDIUM js-unescaped-html-sink apps/web/src/lib/player/player.ts:124
MEDIUM js-unescaped-html-sink apps/web/src/lib/player/player.ts:393
MEDIUM js-unescaped-html-sink apps/web/src/lib/player/player.ts:396
MEDIUM js-unescaped-html-sink apps/web/src/lib/player/player.ts:405
MEDIUM js-unescaped-html-sink apps/web/src/lib/player/player.ts:608
MEDIUM sql-template-interpolation packages/ai-core/src/prompts.ts:36
LOW secret-generic-credential apps/desktop/src/main/agent-cli/commands.test.ts:138
LOW secret-generic-credential apps/desktop/src/main/agent-cli/commands.test.ts:139
LOW secret-generic-credential apps/desktop/src/main/agent-cli/commands.test.ts:340
LOW secret-generic-credential apps/desktop/src/main/agent-cli/commands.test.ts:341
LOW secret-generic-credential apps/desktop/src/main/agent-cli/commands.test.ts:371
LOW secret-generic-credential apps/desktop/src/main/agent-cli/commands.test.ts:372
LOW secret-generic-credential apps/desktop/src/main/agent-cli/commands.test.ts:383
LOW secret-generic-credential apps/desktop/src/main/agent-cli/commands.test.ts:397
LOW secret-generic-credential apps/desktop/src/main/agent-cli/commands.test.ts:398
LOW secret-generic-credential apps/desktop/src/main/agent-cli/commands.test.ts:405
LOW secret-generic-credential apps/desktop/src/main/agent-cli/commands.test.ts:415
LOW secret-generic-credential apps/desktop/src/main/agent-cli/commands.test.ts:416
LOW secret-generic-credential apps/desktop/src/main/agent-cli/commands.test.ts:453
LOW secret-generic-credential apps/desktop/src/main/agent-cli/commands.test.ts:454
LOW secret-generic-credential apps/desktop/src/main/agent-cli/copilot.test.ts:92
LOW secret-generic-credential apps/livekit/fly.toml:12
LOW secret-generic-credential apps/turn/fly.toml:11

…and 4 more. Full results in the Security tab.

Snippets are redacted; ThreatCrush never prints matched credential material.

@sh1pt-actions-fleet
sh1pt-actions-fleet Bot merged commit 3264579 into master Oct 29, 2026
15 checks passed
@sh1pt-actions-fleet
sh1pt-actions-fleet Bot deleted the feat/coinpay-signin branch October 29, 2026 06:03
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