Skip to content

feat: add CAPTCHA protection to subscribe form (#729) - #803

Open
otherwiseGG wants to merge 21 commits into
rajnandan1:mainfrom
otherwiseGG:729-integrate-captcha
Open

feat: add CAPTCHA protection to subscribe form (#729)#803
otherwiseGG wants to merge 21 commits into
rajnandan1:mainfrom
otherwiseGG:729-integrate-captcha

Conversation

@otherwiseGG

@otherwiseGG otherwiseGG commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Fixes the email flooding issue from #729 - the subscribe form's login action had no rate limiting or human verification, so anyone could spam unlimited emails and trigger real OTP sends.

Added CAPTCHA support with hCaptcha, Google reCAPTCHA, and Cloudflare Turnstile, following the same pattern the app already uses for Analytics Providers: a Captcha Providers admin page, site-data backed config, and a public site-key-only endpoint the client widget reads from. Only one provider can be active at a time.

The subscribe form now requires a solved token before the OTP email gets sent, verified server-side against the provider's siteverify endpoint. Falls back to normal (no captcha) behavior if nothing's configured, so this is fully backwards compatible.

A couple of problems came up wiring the actual widgets that are worth calling out for review (since i used Claude to help me with these Issues):

  • reCAPTCHA attaches .render to window.grecaptcha asynchronously after script load, so calling it immediately can throw grecaptcha.render is not a function. Gated on .ready() when the SDK exposes it.
  • The subscribe dialog sets pointer-events: none on <body> while open (its scroll-lock). reCAPTCHA's expanded image challenge gets injected as a direct child of <body> too, so it was silently inheriting that and becoming click-through, closing the dialog when you tried to interact with it. Re-enabled pointer-events on the challenge overlay specifically.

Tested against all three providers on a live instance, including the actual reCAPTCHA image challenge end to end, not just the checkbox.

Fixes #729

Preview:

image image

Summary by CodeRabbit

  • New Features
    • Added CAPTCHA protection for public subscription forms with hCaptcha, Google reCAPTCHA, or Cloudflare Turnstile.
    • Added provider management settings for credentials, activation, status, and single-provider selection.
    • Subscription sign-in now requires successful CAPTCHA verification when enabled.
    • Added validation feedback, server error messages, and challenge reset handling.
  • Documentation
    • Added v4 documentation covering setup, supported providers, credentials, and verification behavior.
  • Bug Fixes
    • Improved API route handling to prevent unintended file imports.

Copilot AI lite review requested due to automatic review settings August 6, 2026 01:05
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Added CAPTCHA support for hCaptcha, reCAPTCHA, and Turnstile. The subscription flow now verifies CAPTCHA tokens before login. Added provider management, shared settings UI, documentation, tests, and permission wiring.

Changes

CAPTCHA protection

Layer / File(s) Summary
Configuration and provider discovery
src/lib/server/controllers/..., src/lib/server/db/...
Added CAPTCHA site-data definitions, prefix queries, configuration parsing, and active-provider discovery.
Server verification and login enforcement
src/lib/server/controllers/captchaController.ts, src/lib/server/api-server/subscription/..., src/routes/(kener)/captcha-config.json/...
Added provider token verification, public configuration output, subscription login enforcement, supported handler filtering, and tests.
Client widget and subscription gating
src/lib/components/Captcha.svelte, src/lib/components/SubscribeMenu.svelte, src/lib/components/*.test.ts
Added SDK loading, widget rendering, readiness callbacks, token submission, dialog interaction handling, reset behavior, and browser tests.

Provider management

Layer / File(s) Summary
Provider settings interface
src/lib/client/types/provider-settings.ts, src/lib/components/manage/ProviderSettingsPanel.svelte, src/routes/(manage)/manage/app/...
Added reusable provider loading, editing, persistence, active-state handling, CAPTCHA settings, and analytics-panel reuse.
Navigation and permissions
src/routes/(manage)/+layout.svelte, src/lib/allPerms.ts
Added permission-filtered navigation for CAPTCHA provider settings.

Documentation

Layer / File(s) Summary
CAPTCHA setup documentation
src/routes/(docs)/docs/content/v4/captcha.md, src/routes/(docs)/docs/content/v4/subscriptions.md, src/routes/(docs)/docs.json
Documented provider setup, activation, verification, and the subscription CAPTCHA requirement.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SubscribeMenu
  participant CaptchaConfigEndpoint
  participant CaptchaSDK
  participant SubscriptionAPI
  participant CaptchaController
  participant CaptchaProvider
  SubscribeMenu->>CaptchaConfigEndpoint: Fetch active provider and site key
  CaptchaConfigEndpoint-->>SubscribeMenu: Return public CAPTCHA configuration
  SubscribeMenu->>CaptchaSDK: Load SDK and render widget
  CaptchaSDK-->>SubscribeMenu: Return token and readiness
  SubscribeMenu->>SubscriptionAPI: Submit email and captchaToken
  SubscriptionAPI->>CaptchaController: VerifyCaptchaToken(captchaToken)
  CaptchaController->>CaptchaProvider: Send verification request
  CaptchaProvider-->>CaptchaController: Return success status
  CaptchaController-->>SubscriptionAPI: Return verification result
  SubscriptionAPI-->>SubscribeMenu: Return login response
Loading

Poem

A rabbit checks the signup gate,
Three providers validate the state.
Tokens cross the server line,
Failed checks stop the login sign.
Settings choose one active key—
Hop safely through CAPTCHA’s tree!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The implementation addresses issue #729 by requiring and server-verifying CAPTCHA before sending subscription OTP emails.
Out of Scope Changes check ✅ Passed The provider settings, shared components, tests, documentation, and supporting data APIs directly support the CAPTCHA protection objective.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding CAPTCHA protection to the subscribe form.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds configurable hCaptcha, reCAPTCHA, and Turnstile protection to public subscription OTP requests.

  • Adds provider administration, validated site-data storage, and a public site-key configuration endpoint.
  • Adds client-side CAPTCHA rendering, token lifecycle handling, and server-side provider verification.
  • Narrows dashboard API handler discovery to supported HTTP-method filenames and adds accompanying tests and documentation.

Confidence Score: 4/5

The PR is not yet safe to merge because incomplete credentials for an enabled CAPTCHA provider still block every subscription OTP request without presenting users a challenge.

The public configuration endpoint translates the controller's misconfigured state into no active provider, while the subscription endpoint interprets that same state as verification failure, so affected users can submit the ungated form but can never receive an OTP.

Files Needing Attention: src/lib/server/controllers/captchaController.ts, src/routes/(kener)/captcha-config.json/+server.ts

Important Files Changed

Filename Overview
src/lib/server/controllers/captchaController.ts Resolves provider configuration and verifies tokens, but maps incomplete enabled configuration differently between public discovery and server enforcement.
src/lib/components/SubscribeMenu.svelte Integrates CAPTCHA gating and now replaces consumed tokens by returning resend users to a newly mounted challenge.
src/lib/components/Captcha.svelte Loads provider SDKs, renders widgets, exposes reset behavior, and handles asynchronous SDK readiness.
src/routes/(kener)/captcha-config.json/+server.ts Publishes only provider and site-key data, while treating incomplete enabled configuration as though CAPTCHA were disabled.
src/lib/server/api-server/subscription/post.ts Verifies CAPTCHA before invoking the existing OTP login operation.
src/lib/components/manage/ProviderSettingsPanel.svelte Adds reusable provider configuration UI with single-active-provider enforcement and guarded persistence.

Sequence Diagram

sequenceDiagram
  participant User
  participant UI as Subscribe Menu
  participant Config as captcha-config.json
  participant Provider as CAPTCHA Provider
  participant API as Subscription API
  participant Mail as OTP Sender
  UI->>Config: Request active provider and site key
  Config-->>UI: Provider configuration
  UI->>Provider: Render and solve challenge
  Provider-->>UI: Single-use token
  UI->>API: Login request with email and token
  API->>Provider: Verify token with secret key
  Provider-->>API: Verification result
  alt Verification succeeds
    API->>Mail: Send OTP
    API-->>UI: Success
  else Verification fails
    API-->>UI: Captcha verification failed
  end
Loading

Reviews (6): Last reviewed commit: "fix: send user back to solve a fresh cap..." | Re-trigger Greptile

Comment thread src/lib/server/controllers/captchaController.ts Outdated

@coderabbitai coderabbitai 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.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/components/Captcha.svelte`:
- Around line 34-45: Update loadScript so an existing provider script is awaited
until it finishes loading rather than resolving immediately. Cache and reuse the
in-flight Promise at module scope, or attach one-time load and error listeners
to the existing script, ensuring callers reject on load failure and only proceed
after the provider script is ready.

In `@src/lib/components/manage/ProviderSettingsPanel.svelte`:
- Around line 59-81: Update fetchData in ProviderSettingsPanel.svelte (lines
59-81) to surface result.error via toast.error and assign selected =
providers[0] ?? null in finally so failed loads still initialize the form.
Update save (lines 100-112) to avoid sending client-side requirements for other
providers; send only their disable intent, preserve stored requirements
server-side, or block saving until loading succeeds.
- Around line 204-215: Update the requirements rendering in the selected
provider settings panel so the Input id and Label for use a whitespace-free slug
derived from req.label, while keeping req.label as the visible label text.
Ensure the same derived identifier is used for both attributes to preserve their
association.
- Around line 14-29: Move the exported ProviderDefinition and
ProviderRequirement interfaces out of ProviderSettingsPanel.svelte into
src/lib/client/types/provider-settings.ts, then import and re-export them from
the component as needed so existing type-only consumers can use
ProviderDefinition without conflicting with the component’s default export.
Update +page.svelte or other consumers to import the type from the dedicated
module or component type export while preserving the existing shapes.

In `@src/lib/components/SubscribeMenu.svelte`:
- Around line 116-119: Update the failed login request handling in SubscribeMenu
so a rejected CAPTCHA token resets or remounts the Captcha instance, not just
captchaToken, restoring the Continue flow with a replacement token. Use the
Captcha rendering/configuration near the existing instance and add a browser
test covering a completed token being rejected and the widget issuing a new
token.

In `@src/lib/server/controllers/captchaController.ts`:
- Around line 51-55: Update the CAPTCHA verification fetch in the controller to
use an AbortController with a short configured timeout, passing its signal to
fetch and clearing the timeout after completion. Treat an abort like other
verification failures and return the existing failure response instead of
allowing the request to wait indefinitely.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9f8ac08e-adc4-4d20-9ea6-7ce77eafa6ed

📥 Commits

Reviewing files that changed from the base of the PR and between 880080c and d86f6b8.

⛔ Files ignored due to path filters (3)
  • static/hcaptcha.png is excluded by !**/*.png
  • static/recaptcha.png is excluded by !**/*.png
  • static/turnstile.png is excluded by !**/*.png
📒 Files selected for processing (23)
  • src/lib/allPerms.ts
  • src/lib/components/Captcha.svelte
  • src/lib/components/Captcha.svelte.test.ts
  • src/lib/components/SubscribeMenu.svelte
  • src/lib/components/SubscribeMenu.svelte.test.ts
  • src/lib/components/manage/ProviderSettingsPanel.svelte
  • src/lib/server/api-server/index.ts
  • src/lib/server/api-server/subscription/post.test.ts
  • src/lib/server/api-server/subscription/post.ts
  • src/lib/server/controllers/captchaController.test.ts
  • src/lib/server/controllers/captchaController.ts
  • src/lib/server/controllers/siteDataController.ts
  • src/lib/server/controllers/siteDataKeys.ts
  • src/lib/server/db/dbimpl.ts
  • src/lib/server/db/repositories/site-data.ts
  • src/routes/(docs)/docs.json
  • src/routes/(docs)/docs/content/v4/captcha.md
  • src/routes/(docs)/docs/content/v4/subscriptions.md
  • src/routes/(kener)/captcha-config.json/+server.ts
  • src/routes/(kener)/captcha-config.json/captcha-config.test.ts
  • src/routes/(manage)/+layout.svelte
  • src/routes/(manage)/manage/app/analytics-providers/+page.svelte
  • src/routes/(manage)/manage/app/captcha-providers/+page.svelte

Comment thread src/lib/components/Captcha.svelte Outdated
Comment thread src/lib/components/manage/ProviderSettingsPanel.svelte Outdated
Comment thread src/lib/components/manage/ProviderSettingsPanel.svelte Outdated
Comment thread src/lib/components/manage/ProviderSettingsPanel.svelte
Comment thread src/lib/components/SubscribeMenu.svelte
Comment thread src/lib/server/controllers/captchaController.ts

Copilot AI 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.

Pull request overview

Adds optional CAPTCHA protection to the public subscription login flow to mitigate email/OTP flooding (#729), with admin-configurable provider settings and a public site-key-only config endpoint consumed by the client widget.

Changes:

  • Introduces CAPTCHA provider management in the admin UI (single-active provider) and a reusable ProviderSettingsPanel.
  • Adds public /captcha-config.json endpoint + client-side Captcha widget integration into SubscribeMenu, and server-side token verification on subscription login.
  • Updates docs/navigation/permissions and adds tests for controller, API route, and UI gating.

Reviewed changes

Copilot reviewed 23 out of 26 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/routes/(manage)/manage/app/captcha-providers/+page.svelte New admin page to configure CAPTCHA providers via shared settings panel.
src/routes/(manage)/manage/app/analytics-providers/+page.svelte Refactors analytics provider settings to use ProviderSettingsPanel.
src/routes/(manage)/+layout.svelte Adds “Captcha Providers” navigation entry.
src/routes/(kener)/captcha-config.json/+server.ts Adds public endpoint returning active provider + site key only.
src/routes/(kener)/captcha-config.json/captcha-config.test.ts Tests config endpoint output and secret non-disclosure.
src/routes/(docs)/docs/content/v4/subscriptions.md Documents CAPTCHA requirement in subscription flow when enabled.
src/routes/(docs)/docs/content/v4/captcha.md New documentation page for CAPTCHA setup and providers.
src/routes/(docs)/docs.json Adds Captcha docs entry to docs navigation.
src/lib/server/db/repositories/site-data.ts Adds getAllSiteDataByPrefix helper and reuses it for analytics.
src/lib/server/db/dbimpl.ts Exposes/binds getAllSiteDataByPrefix on db impl.
src/lib/server/controllers/siteDataKeys.ts Registers new captcha.* site-data keys as valid JSON objects.
src/lib/server/controllers/siteDataController.ts Adds GetAllCaptchaData() to fetch/parse captcha site-data entries.
src/lib/server/controllers/captchaController.ts Adds active-provider resolution and server-side token verification.
src/lib/server/controllers/captchaController.test.ts Unit tests for provider resolution + verification behavior.
src/lib/server/api-server/subscription/post.ts Requires CAPTCHA verification for subscription “login” action.
src/lib/server/api-server/subscription/post.test.ts Tests CAPTCHA gating behavior for subscription login action.
src/lib/server/api-server/index.ts Narrows eager glob import to method files to avoid bundling co-located tests.
src/lib/components/SubscribeMenu.svelte Adds CAPTCHA widget + token submission and dialog iframe interaction handling.
src/lib/components/SubscribeMenu.svelte.test.ts Tests client-side gating of Continue button based on captcha config.
src/lib/components/manage/ProviderSettingsPanel.svelte New reusable provider settings component (shared by analytics + captcha).
src/lib/components/Captcha.svelte New client CAPTCHA loader/renderer with provider-agnostic render path.
src/lib/components/Captcha.svelte.test.ts Tests captcha widget presence + required-state reporting.
src/lib/allPerms.ts Adds route permission mapping for captcha providers admin page.

Comment thread src/lib/server/api-server/subscription/post.ts
Comment thread src/lib/components/SubscribeMenu.svelte
Comment thread src/lib/server/api-server/subscription/post.ts
Comment thread src/lib/components/Captcha.svelte

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/server/controllers/captchaController.test.ts`:
- Around line 103-123: Update the “aborts the verify request after a timeout
instead of hanging indefinitely” test to advance fake timers by exactly the
five-second timeout boundary rather than 10,000ms, so it fails if
VERIFY_TIMEOUT_MS exceeds the intended limit. Keep the existing assertions and
cleanup unchanged.

In `@src/lib/server/controllers/captchaController.ts`:
- Around line 30-44: Update resolveCaptchaConfig and the related
GetActiveCaptchaProvider/VerifyCaptchaToken flow to enforce a single enabled
supported CAPTCHA provider before selecting or validating one. Detect multiple
enabled keys from GetAllCaptchaData and return a consistent misconfigured result
or otherwise reject the configuration, ensuring both callers cannot choose
different providers from unordered data.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ef5876dc-79d1-4f9e-b4ac-950d44114511

📥 Commits

Reviewing files that changed from the base of the PR and between d86f6b8 and 0b745e0.

📒 Files selected for processing (2)
  • src/lib/server/controllers/captchaController.test.ts
  • src/lib/server/controllers/captchaController.ts

Comment thread src/lib/server/controllers/captchaController.test.ts
Comment thread src/lib/server/controllers/captchaController.ts

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/components/SubscribeMenu.svelte.test.ts`:
- Around line 68-86: Update the test around the Turnstile setup and
Captcha.loadScript flow to stub script loading or dispatch a load event on the
created script after configuring window.turnstile. Ensure the script-loading
promise resolves without external I/O while preserving the existing render and
reset assertions.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a6379d56-96b9-4769-8392-243a5e44e807

📥 Commits

Reviewing files that changed from the base of the PR and between 0b745e0 and 07de0a3.

📒 Files selected for processing (6)
  • src/lib/components/Captcha.svelte
  • src/lib/components/Captcha.svelte.test.ts
  • src/lib/components/SubscribeMenu.svelte
  • src/lib/components/SubscribeMenu.svelte.test.ts
  • src/lib/server/api-server/subscription/post.test.ts
  • src/lib/server/api-server/subscription/post.ts

Comment thread src/lib/components/SubscribeMenu.svelte.test.ts
Comment thread src/lib/server/controllers/captchaController.ts

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/components/Captcha.svelte`:
- Around line 16-24: Update loadScript to handle an existing script that
completed before listeners were attached: track load/error completion for
scripts created by the loader, and check CAPTCHA provider readiness for
externally existing scripts before awaiting events. Ensure the promise resolves
or rejects immediately when completion is already known, and add a regression
test that dispatches load before invoking loadScript.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: dc6dc7d3-3279-41bc-962d-77cd5f6e53f9

📥 Commits

Reviewing files that changed from the base of the PR and between 07de0a3 and 8521b7d.

📒 Files selected for processing (7)
  • src/lib/client/types/provider-settings.ts
  • src/lib/components/Captcha.svelte
  • src/lib/components/Captcha.svelte.test.ts
  • src/lib/components/manage/ProviderSettingsPanel.svelte
  • src/lib/components/manage/ProviderSettingsPanel.svelte.test.ts
  • src/routes/(manage)/manage/app/analytics-providers/+page.svelte
  • src/routes/(manage)/manage/app/captcha-providers/+page.svelte

Comment thread src/lib/components/Captcha.svelte Outdated
Comment thread src/lib/components/SubscribeMenu.svelte

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/components/Captcha.svelte`:
- Around line 31-38: Update loadScript to check whether an existing provider
script is already loaded before attaching listeners or waiting on it, resolving
immediately when ready. Ensure existing failed scripts are removed or replaced
so retries cannot reuse a dead element, and add regression tests covering both
previously-loaded and previously-failed script states.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6d7b8efe-5422-412d-8db2-7f4e44bd68b2

📥 Commits

Reviewing files that changed from the base of the PR and between 8521b7d and 644c9e4.

📒 Files selected for processing (2)
  • src/lib/components/Captcha.svelte
  • src/lib/components/Captcha.svelte.test.ts

Comment thread src/lib/components/Captcha.svelte
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.

email flooding

2 participants