meteo-concept/hcaptcha-bundle
Symfony bundle that adds hCaptcha protection to your forms with minimal setup. Includes a dedicated form type and server-side validation to block bots and spam, with simple configuration for Symfony applications.
Architecture fit — poor for direct use, good as a reference implementation. Unchanged by v4.5.0. This package is a Symfony bundle, not a Laravel package. Its value is delivered through Symfony's DependencyInjection, HttpKernel, Config, and Form components — service definitions in YAML/XML, form type extensions, and event subscribers. Laravel has none of these integration points: it uses its own container, its own validation pipeline, Blade, and Guzzle. The only genuine overlap is the underlying hCaptcha server-side verification call, which is a single outbound HTTPS POST to api.hcaptcha.com/siteverify with secret, response, sitekey, and optionally remoteip. That logic is small enough to reimplement in a Laravel service provider in a day. The bundle itself should not be installed in a Laravel application.
v4.5.0 is a version-support release and does not change this conclusion. The release adds Symfony 8.0 support, retains Symfony 6.4 and 7.4, and drops explicit testing for intermediate minors (6.0–6.3, 7.0–7.3). There are no new features, no new verification parameters, no changes to the hCaptcha contract, and no deprecations affecting behavior. The entire delta is Symfony-version alignment — which is precisely the axis a Laravel team does not care about. If anything, the release confirms the coupling: the maintainer's roadmap is Symfony framework compatibility, not framework-agnostic verification logic.
Integration feasibility. Direct composer require into a Laravel app remains non-viable — it would pull a bundle expecting FrameworkBundle, register services Laravel never boots, and provide no usable form or validation integration. Note that the Symfony 8 leg of v4.5.0 implies PHP 8.4, so the package's tested support matrix is now straddling PHP 8.2–8.4 depending on Symfony version; that matrix is irrelevant to us but is a reminder that any accidental install would drag in transitive constraints. The realistic path is unchanged: a thin Laravel-native port — config file for site key/secret, a ValidationRule object wrapping the siteverify call, a Blade component for the widget script, and a feature flag per form.
Technical risk.
NOASSERTION — still the highest-severity finding and not addressed by this release. Without a clear OSI license, copying code is a legal exposure and using it as a dependency is an audit finding. Resolve before any code reuse. v4.5.0 changes nothing here; do not let a routine version bump reset the clock on this gate.Key questions for the maintainer / code audit.
rqdata, custom difficulty), or checkbox only? (No change in v4.5.0.)remoteip and sitekey sent on verification, and is the returned hostname/credit validated or discarded? (No change.)error-codes (e.g. invalid-input-response, timeout-or-duplicate) surfaced to the form layer, and are tokens treated as strictly single-use? (No change.)symfony/http-client is mandatory.symfony/http-client dependency status still needs confirmation from composer.json.Stack fit. Target Laravel 10/11/12 on PHP 8.2+ with Guzzle (framework default) rather than adding symfony/http-client. The v4.5.0 Symfony 8 leg reinforces that the bundle's HTTP layer will track Symfony's client, not Laravel's — another reason not to depend on it. Reimplement as an internal package: HCaptchaService (verification), HCaptchaRule (validation), HCaptcha Blade component (widget + script), config publishable to config/hcaptcha.php, keys sourced from environment/secret manager. Expose the raw verification result so calling code can log error-codes and score when Enterprise is enabled.
Migration path. If a Symfony service using this bundle is being consolidated into a Laravel estate, do not port the bundle — port the behavior. Build a parity matrix covering: config keys and defaults, field naming convention, verification request parameters, error message strings, timeout value, and failure policy. That matrix is the acceptance test for the Laravel implementation. Pin the parity capture to v4.5.0 and record the version in the matrix header, since the maintainer has now demonstrated willingness to move framework baselines.
Compatibility. Three seams, all unchanged by v4.5.0: (1) HTTP client — the bundle uses Symfony HttpClient; Laravel's Http facade is Guzzle-backed, so response handling and timeout semantics differ; (2) front-end asset delivery — a Symfony bundle ships Twig/Encore/AssetMapper integration, which must be replaced with a Blade partial or a Vite-imported JS module; (3) localization — Symfony translator strings need Laravel lang files. The dropped testing for Symfony 6.0–6.3 and 7.0–7.3 is not relevant to us (we run neither), but it is a useful signal that the maintainer prunes support aggressively — do not assume a long tail of patch releases for any version you might reference.
Sequencing. Unchanged.
Maintenance. You will still own this code. The v4.5.0 release is a mild positive on vendor health — it shows the maintainer responds to framework releases — so the planning assumption moves from "likely abandoned" to "small, active, single-maintainer, with no obligation to us." Practically: pin v4.5.0 as the audited reference, vendor the verification logic into your own namespace, and stop tracking upstream after parity is achieved. Continue watching hCaptcha's API changelog, not the bundle's, as the primary dependency signal. If you retain any read-only tracking of upstream, note that its release cadence is now driven by Symfony majors (roughly annual), so silence between releases is expected and not evidence of abandonment.
Support. No commercial support path. The operative knowledge base is hCaptcha's own documentation plus your internal runbook. That runbook must cover: secret rotation without downtime, the fail-open/fail-closed decision and who can change it, how to verify the integration is live (a canary form submission with a known-bad token), and how to read error-codes in logs. Nothing in v4.5.0 adds or removes runbook surface.
Scaling. Every protected submission gains a synchronous external HTTP call — budget 100–300 ms p95 in the request path, more from regions far from hCaptcha's edge. This is a hard runtime dependency on a third party at your most conversion-sensitive funnel step. Set explicit connect/read timeouts (2s/3s), and note that retries are unsafe on the same token — hCaptcha tokens are single-use, so a retried verification will return timeout-or-duplicate even if the first call succeeded. Do not wrap this call in an automatic retry.
Failure modes.
Ramp-up. Low technical ramp: a mid-level Laravel engineer can deliver the port in 1–2 days, and there is no bundle to learn. The real ramp remains organizational — legal sign-off on the license, a documented abuse-response policy, and on-call familiarity with a new external dependency in the auth path. Budget the majority of effort there, not in code. v4.5.0 does not reduce that effort.
How can I help you explore Laravel packages today?