quiet-metrics/symfony-metrics
Symfony bundle that integrates Quiet Metrics into Symfony applications, providing service wiring and configuration for collecting and exposing application metrics to support monitoring, reporting, and observability.
Architecture fit. v0.6.0 adds a narrowly-scoped, opt-in HTTP surface: a single well-known endpoint (GET/HEAD /.well-known/quietmetrics.json) that serves a site-ownership proof consumed by the Quiet Metrics SEO tab. The feature is implemented as a kernel-level listener (SiteVerificationListener, kernel.request, priority 200) rather than a routed controller. That is the correct architecture for this problem — the endpoint must answer before the firewall and session stack, and it must be reachable without authentication — but it means the feature lives outside the application's normal middleware, routing, and authorization layers. Treat it as infrastructure, not application code.
Integration feasibility. The change is additive and self-contained: one boolean config key (seo_crawl, default false), one listener, one path. There is no data model change, no migration, no schema, and no persistence. The listener is registered unconditionally (because %env()% is resolved at runtime), but it short-circuits to a pass-through unless both seo_crawl is true and secret_key is set. That double gate is the right design and materially limits blast radius. Integration effort should be measured in hours, dominated by verification and change-control rather than development.
Technical risk. The risks are concentrated and mostly verifiable:
secret_key itself. If it is the raw secret, this is a credential exposed on an unauthenticated public path and the assessment should escalate to a security review before adoption. This is the single most important question to close.'%env(bool:QUIET_METRICS_SEO_CRAWL)%' is safe only with the bool: processor. A hand-written %env(QUIET_METRICS_SEO_CRAWL)% would pass the string "false", which is truthy. Configuration drift here silently enables a public endpoint.quiet-metrics/php-metrics ^0.6 is a hard floor. On a 0.x caret constraint this pins to 0.6.x, which is reasonably tight, but pre-1.0 means minor releases may still carry behavioral changes. Any other package pinning php-metrics below 0.6 will conflict.Key questions.
secret_key, a hash, or an opaque token? Can it be rotated independently?/.well-known/quietmetrics.json?seo_crawl=true but secret_key is empty — pass-through, or a 4xx?Accept variants other than application/json?Cache-Control: no-store accompanied by Pragma: no-cache, and does the listener set X-Content-Type-Options: nosniff?bool: processor applied everywhere the env var is referenced, including documentation examples?Stack fit. The release notes describe Symfony idioms (kernel.request, %env()%, "bundle"), while the parent package is tracked here as a Laravel/PHP package. Confirm which runtime this actually targets before committing. If a Laravel adapter exists, map the listener onto a global middleware with equivalent early-ordering, and ensure the config key is read from config/*.php (not a raw env() call at request time) so php artisan config:cache does not silently freeze or null the value. If the package is Symfony-only, treat the Laravel fit as unresolved and re-scope.
Migration path. Low-ceremony and reversible at every step:
quiet-metrics/php-metrics to ^0.6 in a branch; confirm no other dependency pins it lower.seo_crawl to the published config with a default of false and keep the env reference commented or explicitly cast.seo_crawl=false to production first — this validates that the listener registers and passes through cleanly with zero behavior change.Compatibility. The change is backward compatible by default: existing installs get a no-op listener and no new endpoint. The only breaking surface is the dependency floor. Consumers on php-metrics 0.5.x must upgrade in lockstep, which is the sequencing constraint that governs the rollout.
Sequencing.
curl -i for GET and HEAD, confirm 200, application/json, no-store; verify a request with the flag off returns the application's normal response.Maintenance. Very low steady-state burden — one config key, one listener, one dependency constraint. The ongoing obligations are (a) tracking php-metrics 0.6.x patch releases given the pre-1.0 API stability, and (b) keeping the config and env var in sync across environments. Documentation should state the bool: requirement explicitly; that is the most likely source of a self-inflicted incident.
Support. The feature is easy to troubleshoot because it is binary and independently observable: curl the well-known path and you know whether it is working. Support burden rises only if the SEO tab reports "unverified" and the cause is ambiguous — e.g. a CDN or WAF stripping the response rather than the package failing. Publish a short diagnostic checklist (endpoint responds → payload matches expectation → crawler can reach it → verification completed in the tab).
Scaling. Negligible. The listener runs per request but does only a boolean check and a string-key presence check before returning early. When enabled, the response is a small static payload with no-store, so it will not consume cache capacity. It is not a CDN-cacheable asset by design — expect it to hit origin on every crawler request, which is a trivial volume.
Failure modes.
seo_crawl coerced truthy from the string "false" → public endpoint unintentionally live. Highest-likelihood human error.secret_key is unset, and the SEO tab stays unverified with no error surfaced to the operator.no-store ignored by an intermediary, or a hardened web server config denying dotfile paths, causing intermittent verification failures.php-metrics at 0.5.x and the bump fails at deploy time rather than in CI.secret_key changes the proof and silently invalidates the SEO tab verification until re-run.Ramp-up. Effectively zero for engineers — the concept is one flag and one URL. The real ramp-up cost is on the operator/SEO side: someone must own the verification step in the Quiet Metrics SEO tab and know to re-run it after any secret rotation. Assign that owner and document it before enabling. For a TPM, the decision to adopt is low-cost and low-risk contingent on the payload-disclosure answer; if the endpoint serves a derived token rather than the secret itself, this is a routine opt-in feature and can be scheduled as a minor change. If it serves the raw secret, route it through security review first.
How can I help you explore Laravel packages today?