Captcha API

Piko's captcha service verifies tokens from Cloudflare Turnstile, Google reCAPTCHA v3, hCaptcha, and a built-in HMAC challenge useful for development. The service normalises provider scores onto a 0.0-1.0 scale so downstream policy code does not have to know which provider produced a token. For the design rationale see about captcha. For task recipes see how to captcha and how to security. Source file: wdk/captcha/facade.go.

Entry points

func Verify(ctx context.Context, token, remoteIP, action string) error
func GetDefaultService() (ServicePort, error)

Verify is the usual call site. It looks up the default service, verifies the token, and returns a typed error. Piko passes the action label through to providers that support action-based fraud detection (reCAPTCHA v3, Turnstile).

Types

TypePurpose
ServicePortService interface. Wraps provider selection, rate limiting, and score enforcement.
ProviderProvider interface. Implemented by each backend adapter.
ProviderTypeEnum identifying a provider kind.
VerifyRequestFull verification request. See fields below.
VerifyResponseProvider response including normalised score. See fields below.
ServiceConfigService configuration. See fields below.
CaptchaErrorTyped error. Pairs with the error constants listed below.

Verify-request fields

FieldTypePurpose
TokenstringCaptcha response token from the client widget.
RemoteIPstringClient IP, forwarded to the provider for extra validation.
ActionstringOptional action name (reCAPTCHA v3, Turnstile). Identifies the form or flow the token guards.

Verify-response fields

FieldTypePurpose
Timestamptime.TimeWhen the user solved the challenge.
Score*float64Normalised confidence score. 0.0 indicates a likely bot, 1.0 a likely human. The pointer is always non-nil; binary providers fill in 1.0 on success and 0.0 on failure.
ActionstringAction echoed back by the provider. Confirms the token matches the expected action.
HostnamestringHostname the provider issued the token for, as the provider reports it.
ErrorCodes[]stringProvider-specific error codes when verification fails. Diagnostic only; do not show to users.
SuccessboolWhether verification passed.

ServiceConfig fields

FieldTypeDefaultPurpose
DefaultScoreThresholdfloat640.5Minimum score required for score-based providers. Individual actions may override.
VerifyRateLimitint20 / IP / minVerification calls per IP per minute. Zero disables.
ChallengeRateLimitint30 / IP / minChallenge-token generation calls per IP per minute. Zero disables.

captcha_dto.DefaultServiceConfig() returns a *ServiceConfig populated with the defaults above. The helper lives on the data transfer object (DTO) package captcha_dto. The wdk/captcha facade does not re-export it.

Provider constants

ConstantMeaning
ProviderTypeHMACChallengeBuilt-in HMAC challenge. Development only.
ProviderTypeTurnstileCloudflare Turnstile.
ProviderTypeRecaptchaV3Google reCAPTCHA v3.
ProviderTypeHCaptchahCaptcha.

Score normalisation

Providers report confidence in different ways. Piko maps them into a single 0.0-1.0 scale. VerifyResponse.Score is a *float64 and is always populated by every provider (the binary providers fill in 1.0 on success and 0.0 on failure instead of leaving the pointer nil).

ProviderNative signalNormalised to
TurnstilePass/fail (no score)1.0 on success, 0.0 on failure.
reCAPTCHA v30.0-1.0 scorePassed through unchanged.
hCaptchaPass/fail1.0 on success, 0.0 on failure.
HMAC challengePass/fail1.0 on success, 0.0 on failure.

Actions consume the score through the same VerifyResponse.Score field regardless of provider. Score-based policies (reCAPTCHA v3) compare against DefaultScoreThreshold or an action-specific override.

Errors

ErrCaptchaDisabled, ErrVerificationFailed, ErrTokenMissing, ErrTokenExpired, ErrProviderUnavailable, ErrScoreBelowThreshold.

Providers

Each provider sub-package exposes NewProvider(Config) (captcha_domain.CaptchaProvider, error).

captcha_provider_turnstile

type Config struct {
    SiteKey   string // public key embedded in the widget
    SecretKey string // server-side verification key
}

Constructor: captcha_provider_turnstile.NewProvider(Config).

captcha_provider_recaptcha_v3

type Config struct {
    SiteKey   string
    SecretKey string
}

Constructor: captcha_provider_recaptcha_v3.NewProvider(Config).

captcha_provider_hcaptcha

type Config struct {
    SiteKey   string
    SecretKey string
}

Constructor: captcha_provider_hcaptcha.NewProvider(Config).

captcha_provider_hmac_challenge

type Config struct {
    Clock  clock.Clock   // time source for token generation and TTL checks; defaults to the real system clock when nil
    Secret []byte        // at least 16 bytes
    TTL    time.Duration // defaults to 5 minutes
}

Constructor: captcha_provider_hmac_challenge.NewProvider(Config). Deterministic, no external calls, useful in tests and local development. Never ship to production.

Bootstrap options

OptionPurpose
piko.WithCaptchaProvider(name, provider)Registers a provider under name.
piko.WithDefaultCaptchaProvider(name)Marks the registered provider with name as the default.

See also