Architecture
CaptchaService is a single Spring Boot application backed by a PostgreSQL database. All public traffic enters through CaptchaController, which delegates to a thin service layer; JPA repositories persist the challenge and invalidation state to PostgreSQL.
Component Diagram
graph TB
%% External Client
Client
%% External Services
subgraph "External Services"
PostgreSQL[(PostgreSQL<br/>Database)]
end
%% Main CaptchaService Application
subgraph "CaptchaService Application"
%% Monitoring & Management
subgraph "Monitoring"
Actuator["**Spring Actuator**<br/>/actuator/info<br/>/actuator/health<br/>/actuator/metrics"]
end
%% API Endpoints Detail
subgraph "CaptchaController"
ChallengeEndpoint["**postChallenge()**<br/>Create CAPTCHA Challenge"]
VerifyEndpoint["**postVerify()**<br/>Verify CAPTCHA Solution"]
end
%% Service Layer
subgraph "Service Layer"
CaptchaService["**CaptchaService**<br/>Core CAPTCHA Logic"]
DifficultyService["**DifficultyService**<br/>Adaptive Difficulty Management"]
SiteAuthService["**SiteAuthService**<br/>Site Key/Secret Validation"]
SourceAddressService["**SourceAddressService**<br/>IP Address Validation"]
ExpiredDataService["**ExpiredDataService**<br/>Cleanup Scheduler"]
end
%% Data Layer
subgraph "Data Layer"
CaptchaRequestRepo["**CaptchaRequestRepository**<br/>JPA Repository"]
InvalidatedPayloadRepo["**InvalidatedPayloadRepository**<br/>JPA Repository"]
subgraph "JPA Entities"
CaptchaRequestEntity["**CaptchaRequest**<br/>Entity"]
InvalidatedPayloadEntity["**InvalidatedPayload**<br/>Entity"]
end
end
%% Properties/Configuration
subgraph "Configuration Properties"
CaptchaProperties["**CaptchaProperties**<br/>HMAC Key, Sites Config"]
CaptchaSite["**CaptchaSite**<br/>Site-specific Settings"]
DifficultyItem["**DifficultyItem**<br/>Difficulty Mappings"]
end
end
%% Request Flow
Client -->|POST /api/v1/challenge| ChallengeEndpoint
Client -->|POST /api/v1/verify| VerifyEndpoint
Client --> Monitoring
%% Controller to Services
ChallengeEndpoint --> CaptchaService
VerifyEndpoint --> CaptchaService
ChallengeEndpoint --> SiteAuthService
VerifyEndpoint --> SiteAuthService
ChallengeEndpoint --> SourceAddressService
%% Service Interactions
CaptchaService --> DifficultyService
CaptchaService --> CaptchaRequestRepo
CaptchaService --> InvalidatedPayloadRepo
CaptchaService --> AltchaLib
DifficultyService --> CaptchaRequestRepo
ExpiredDataService -->|Scheduled Cleanup| CaptchaRequestRepo
ExpiredDataService -->|Scheduled Cleanup| InvalidatedPayloadRepo
%% Data Layer
CaptchaRequestRepo --> CaptchaRequestEntity
InvalidatedPayloadRepo --> InvalidatedPayloadEntity
CaptchaRequestEntity -.->|JPA/Hibernate| PostgreSQL
InvalidatedPayloadEntity -.->|JPA/Hibernate| PostgreSQL
%% Configuration Dependencies
CaptchaService -.->|Uses| CaptchaProperties
SiteAuthService -.->|Uses| CaptchaProperties
SourceAddressService -.->|Uses| CaptchaProperties
DifficultyService -.->|Uses| CaptchaProperties
%% Database Migration
Flyway -.->|Schema Management| PostgreSQL
Components
CaptchaController— REST entry point. ExposesPOST /api/v1/captcha/challengeandPOST /api/v1/captcha/verify.CaptchaService— core challenge generation and verification, wrapping the ALTCHA library.DifficultyService— computes the proof-of-work difficulty for a given site and source address, based on recent traffic.SiteAuthService— validates thesiteKey/siteSecretpair sent by every client.SourceAddressService— validates the client IP against the per-site allow-list / observation window.ExpiredDataService— scheduled job that removes expired challenges and invalidated payloads.- JPA layer — two repositories (
CaptchaRequestRepository,InvalidatedPayloadRepository) backed by Hibernate entities and PostgreSQL. - Flyway — manages schema migrations under
src/main/resources/db/migration/. - Spring Actuator — exposes
/actuator/health,/actuator/info,/actuator/metrics, and/actuator/prometheus.
Request Flow
- The client POSTs
siteKey,siteSecret, andclientAddressto/api/v1/captcha/challenge. SiteAuthServiceauthenticates the site,SourceAddressServicevalidates the IP, andDifficultyServicepicks the right difficulty based on the per-site difficulty map and recent visit count.CaptchaServiceasks ALTCHA to generate a signed challenge, persists aCaptchaRequest, and returns the challenge.- The client solves the proof-of-work and POSTs the solved payload to
/api/v1/captcha/verify. CaptchaServiceverifies the signature and HMAC, marks the payload invalidated (so it cannot be reused), and returns{ "valid": true | false }.