Skip to content

feat(core): add test_accounts_captcha for staging CAPTCHA bypass#454

Open
blink-claw-bot wants to merge 2 commits intoblinkbitcoin:mainfrom
blink-claw-bot:kn/test-accounts-captcha-v2
Open

feat(core): add test_accounts_captcha for staging CAPTCHA bypass#454
blink-claw-bot wants to merge 2 commits intoblinkbitcoin:mainfrom
blink-claw-bot:kn/test-accounts-captcha-v2

Conversation

@blink-claw-bot
Copy link
Copy Markdown

Summary

Adds a test_accounts_captcha config option to galoy.yaml that allows specific phone numbers to bypass Geetest CAPTCHA validation in requestPhoneCodeWithCaptcha(). This enables automated agents and CI pipelines to authenticate on staging without solving CAPTCHA challenges.

Background

This recreates the functionality from PR #417 (merged then reverted in #424). The revert was due to:

  1. Quickstart changes included — quickstart files are auto-generated and should not be modified manually
  2. Missing proper tests — the original PR only had shallow unit tests for config parsing

What is different this time

  • No quickstart changes — only core/api/ files are modified
  • No unrelated dependency bumps — no package.json or pnpm-lock.yaml changes
  • Proper tests with mocked dependencies:
    • Unit tests for getTestAccountsCaptcha() config parsing (3 tests)
    • Integration-style tests with fully mocked dependencies testing requestPhoneCodeWithCaptcha() behavior (7 tests):
      • CAPTCHA skipped when phone is in test_accounts_captcha (Geetest.validate NOT called)
      • Rate limiting still applied after CAPTCHA bypass
      • Logging occurs when CAPTCHA is skipped
      • Tracing attributes set when CAPTCHA is skipped
      • CAPTCHA validated normally when phone is NOT in list
      • CAPTCHA validation errors returned when phone is not in list and Geetest fails
      • Empty test_accounts_captcha array means normal CAPTCHA flow

Changes

  • core/api/galoy.yaml — Add test_accounts_captcha: [] config
  • core/api/src/config/schema.ts — Add JSON schema for test_accounts_captcha
  • core/api/src/config/schema.types.d.ts — Add TypeScript type
  • core/api/src/config/yaml.ts — Add getTestAccountsCaptcha() function
  • core/api/src/app/authentication/request-code.ts — Check test_accounts_captcha before Geetest validation
  • core/api/test/unit/app/auth/test-accounts-captcha.spec.ts — Unit tests for config parsing
  • core/api/test/unit/app/auth/request-code-captcha-bypass.spec.ts — Mocked integration tests for bypass logic

How it works

In requestPhoneCodeWithCaptcha(), before calling Geetest CAPTCHA validation, the function checks if the phone number exists in test_accounts_captcha. If it does:

  1. Skip Geetest validation entirely
  2. Log the bypass (baseLogger.info)
  3. Set tracing attributes (requestCode.captchaSkipped: true)
  4. Continue with rate limiting and the rest of the normal flow

Allows specific phone numbers (configured in galoy.yaml) to bypass
Geetest CAPTCHA validation. Enables automated agents to authenticate
on staging without solving challenges.

Changes:
- Add test_accounts_captcha config option (schema + types + yaml parser)
- Skip CAPTCHA in requestPhoneCodeWithCaptcha when phone is in list
- Add logging and tracing when CAPTCHA is skipped
- Integration tests with mocked dependencies verify bypass logic
- Unit tests for config parsing

Recreates blinkbitcoin#417 (reverted in blinkbitcoin#424) with:
- No quickstart changes (auto-generated)
- No unrelated dependency bumps
- Proper integration tests with mocking
Copilot AI review requested due to automatic review settings February 11, 2026 12:31
@github-actions github-actions Bot added the core label Feb 11, 2026
@blink-claw-bot
Copy link
Copy Markdown
Author

Commit overview

Recreates #417 (reverted in #424) with proper testing and no quickstart changes.

Core changes

  • galoy.yaml: Added test_accounts_captcha: [] config
  • config/schema.ts: JSON schema for the new array (objects with phone string)
  • config/schema.types.d.ts: TypeScript type
  • config/yaml.ts: getTestAccountsCaptcha() function
  • request-code.ts: Skip Geetest CAPTCHA when phone is in test_accounts_captcha, with logging + tracing

Tests (267 lines)

Unit test (test-accounts-captcha.spec.ts):

  • Config parsing returns correct phones
  • Empty config returns empty array

Integration test (request-code-captcha-bypass.spec.ts, 225 lines):

  • Phone in list → CAPTCHA skipped, Geetest.validate NOT called
  • Phone not in list → CAPTCHA validated normally
  • Empty list → CAPTCHA validated normally
  • CAPTCHA failure propagated when phone not in list
  • Logging verified when CAPTCHA skipped
  • Tracing attributes verified when CAPTCHA skipped

What's different from #417

  • ❌ No quickstart changes (auto-generated, shouldn't be in PR)
  • ❌ No unrelated dep bumps
  • ✅ Integration tests with mocked dependencies
  • ✅ 6 test cases covering bypass logic, failure, logging, and tracing

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a staging-oriented configuration option to bypass Geetest CAPTCHA for a controlled set of test phone numbers, enabling automated authentication flows (CI/agents) without weakening rate limiting or other checks.

Changes:

  • Introduces test_accounts_captcha in YAML config + JSON schema/type definitions.
  • Adds getTestAccountsCaptcha() config accessor.
  • Updates requestPhoneCodeWithCaptcha() to skip Geetest validation for configured test phones, with logging + tracing.
  • Adds unit and mocked integration-style tests covering bypass and non-bypass flows.

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
core/api/galoy.yaml Adds test_accounts_captcha: [] to default config.
core/api/src/config/schema.ts Extends config JSON schema to validate/default the new setting.
core/api/src/config/schema.types.d.ts Extends YamlSchema typing with test_accounts_captcha.
core/api/src/config/yaml.ts Adds getTestAccountsCaptcha() accessor.
core/api/src/app/authentication/request-code.ts Skips Geetest validation for configured test phones; adds log + tracing attribute.
core/api/test/unit/app/auth/test-accounts-captcha.spec.ts Unit tests for getTestAccountsCaptcha() parsing behavior.
core/api/test/unit/app/auth/request-code-captcha-bypass.spec.ts Mocked integration-style tests for bypass behavior and normal CAPTCHA flow.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -0,0 +1,225 @@
import { CaptchaUserFailToPassError } from "@/domain/captcha/errors"

// Mock functions declared at module scope — jest.fn() calls are hoisted.
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The comment about hoisting is misleading: Jest hoists jest.mock() calls, but jest.fn() declarations are not hoisted. Consider rewording to avoid confusion (e.g., explain that the mock factory is hoisted and therefore must not reference later-initialized variables).

Suggested change
// Mock functions declared at module scope jest.fn() calls are hoisted.
// Mock functions declared at module scope so hoisted jest.mock() factories can reference them.

Copilot uses AI. Check for mistakes.
Collapse multiline arrays to single line to stay within printWidth 90.
@blink-claw-bot
Copy link
Copy Markdown
Author

Commit 945f70ec3 — fix: prettier formatting

What: Collapsed multiline arrays in test-accounts-captcha.spec.ts to single lines.
Why: CI check-lint failed — prettier enforces printWidth 90, multiline arrays exceeded it.
Files: core/api/test/unit/app/auth/test-accounts-captcha.spec.ts (+2/-8)
Tests: No logic change — formatting only.

@dolcalmi
Copy link
Copy Markdown

why do you need this? for staging or local env?

@blink-claw-bot
Copy link
Copy Markdown
Author

For staging — it lets CI and automated agents (like me) authenticate without solving Geetest CAPTCHAs. The config only applies to explicitly listed test phone numbers, so production is unaffected.

The use case: we run automated E2E tests and need to log in to staging accounts programmatically. Without this, every auth flow hits the CAPTCHA wall.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants