Deployment and observability audit rules
Auditable rules for deploying and operating Front-Commerce projects, covering health checks, metrics, logs, environment configuration, and version hygiene.
These rules verify that a Front-Commerce project is operable in production: that
failures are detected before customers report them, that configuration is
environment-driven, and that the deployed versions are supportable. Rules marked
static can be verified from the repository alone, runtime rules require
a running application (local or a deployed URL), and manual rules require
human judgment. Use the rule codes (AUDIT-INFRA-NN) to reference findings in
audit reports.
AUDIT-INFRA-01 — Expose and supervise the health and metrics endpoints
Severity: important — Detection: runtime
Rule: The /__front-commerce/health endpoint returns 200 on every
production instance, the /__front-commerce/metrics endpoint is enabled and
protected, and both are consumed by a supervision tool (orchestrator probe,
uptime monitor, Prometheus).
Why: Without a wired health probe, an instance that fails to boot keeps receiving traffic and serves errors until a human notices. Without metrics, memory leaks and backend slowdowns are invisible until they become outages.
How to check:
- Health endpoint:
Expectcurl -s -o /dev/null -w "%{http_code}" https://<site>/__front-commerce/health
200. A503means the application is not ready; a404means the deployment strips the path — both are findings. - Metrics endpoint: confirm
FRONT_COMMERCE_CLOUD_METRICS_KEYis defined in the production environment, then:Expect Prometheus-format output includingcurl -s -H "Authorization: Basic $FRONT_COMMERCE_CLOUD_METRICS_KEY" https://<site>/__front-commerce/metrics | headoutbound_requests_durationhistograms for backend services. An unauthenticated200on this endpoint is a security finding; a404means metrics are disabled. - Ask the team which system polls each endpoint and what alert fires on failure. Endpoints that respond but that nothing watches do not satisfy this rule.
AUDIT-INFRA-02 — Configure health checks for critical backend services
Severity: important — Detection: static + runtime
Rule: Every backend service the storefront cannot run without (commerce
platform, search engine, payment provider) has a registered health check
(services.MaintenanceMode.addHealthCheckService) so the store switches to
maintenance mode automatically when the service is down.
Why: Without automatic detection, a backend outage surfaces as broken pages, failed checkouts, and error noise instead of a clean maintenance page — and recovery requires a human to notice and intervene twice (once to enable maintenance mode, once to disable it).
How to check:
- Find the registered checks:
Compare the list against the backends configured ingrep -rn "addHealthCheckService" app extensions
front-commerce.config.ts(commerce extension, search, payments). A critical backend without a health check is a finding. - Verify the schedule: look for
maintenance.healthChecks.scheduleinfront-commerce.config.ts. The default is every 10 seconds; confirm the configured value is a deliberate choice compatible with the backend's own rate limits. - Confirm
FRONT_COMMERCE_MAINTENANCE_MODE_AUTHORIZATION_TOKENis set, so operators can also toggle maintenance mode and health checks manually. - Runtime (staging): make one monitored service unreachable and confirm the
store serves the maintenance page (
503) within the configured interval, then recovers on its own when the service returns.
AUDIT-INFRA-03 — Monitor critical application logs
Severity: important — Detection: runtime + manual
Rule: Production logs are aggregated and reviewed: GraphQL errors, SSR errors, and abnormal 404 volume each have a defined owner and an alerting or review routine.
Why: These three log families are the earliest signal of real problems — broken resolvers after a backend deployment, SSR regressions that degrade SEO and first paint, and 404 storms that reveal broken links, misconfigured redirects, or bot probing. Unread logs detect nothing.
How to check:
- Ask where production logs go (aggregator, files, stdout collector) and who looks at them. "Nobody, unless something breaks" is a finding.
- Inspect a recent window (24–48 h) of application logs for recurring GraphQL resolver errors and SSR errors. Recurring errors that no ticket tracks are findings.
- Analyze HTTP status distribution in the access logs, for example with
goaccess:Look at the 404 panel: a high or growing 404 rate on product/category URLs points at missing redirects (see the SEO rules).goaccess access.log --log-format=COMBINED - Cross-check with the codebase: silent
catchblocks that return empty values without logging defeat this rule at the source —flags candidates worth reviewing.grep -rn -A2 "catch" app extensions | grep -B1 "return \[\]\|return null"
AUDIT-INFRA-04 — Drive configuration from environment variables, and expose only FRONT_COMMERCE_WEB_* to the client
Severity: important — Detection: static
Rule: Environment-dependent values (backend URLs, keys, feature toggles)
come from environment variables — never hardcoded — and client-side code reads
only variables prefixed with FRONT_COMMERCE_WEB_.
Why: Hardcoded values make the same build behave differently than intended
across environments (staging pointing at production backends is a classic
incident). And any non-WEB_ variable referenced in client code is either
bundled into public JavaScript (leaking it) or undefined at runtime (breaking
the feature).
How to check:
- Client-side
process.envusage — list every reference outside.server.files and loaders:For each hit in code that ships to the browser (components, hooks, client utilities), the variable must start withgrep -rn "process.env" app extensions --include="*.tsx" --include="*.ts" | grep -v ".server."FRONT_COMMERCE_WEB_. Anything else is a violation. - Hardcoded environment-specific values:
URLs and keys embedded in source instead of read from configuration are violations (test fixtures excepted).grep -rnE "https?://[a-z0-9.-]*(staging|preprod|prod|magento|localhost)" app extensions front-commerce.config.ts
- Confirm
.env.dist(or equivalent template) documents every variable the code reads, so environments can be reproduced.
AUDIT-INFRA-05 — Remove the example-extensions directory
Severity: minor — Detection: static
Rule: The project does not contain the skeleton's example-extensions
directory, and front-commerce.config.ts references none of its extensions.
Why: The examples ship as learning material, not production code. Keeping them adds dead routes and demo endpoints to the deployed application, enlarges the attack surface, and confuses future maintainers about what is real project code.
How to check:
-
test -d example-extensions && echo "VIOLATION: directory present"
-
Any import from the directory is a violation. If one example was genuinely adopted, its code must be moved intogrep -rn "example-extensions" front-commerce.config.ts app
extensions/under a project-owned name.
AUDIT-INFRA-06 — Customize the maintenance and offline pages
Severity: minor — Detection: static + runtime
Rule: The maintenance page (shown during backend maintenance mode) and the offline page (shown by the PWA without network) are overridden to match the project's brand.
Why: These pages appear exactly when users are already experiencing a degraded moment. A default, unbranded framework page at that moment reads as a broken site and erodes trust, where a branded page reads as a handled situation.
How to check:
- Static: look for the theme overrides —
No matching override means the default framework pages ship as-is.find app/theme -path "*pages/Offline*" -o -path "*pages/Error/Maintenance*" -o -path "*pages/Maintenance*"
- Runtime: on an environment where
FRONT_COMMERCE_ENVis notproduction, open/__front-commerce/maintenanceand/__front-commerce/offlineand confirm both render project branding (logo, colors, wording, translated copy). - For the offline page, also verify the PWA setup is complete (service worker
registered,
manifest.jsonbranded) so the page can actually be served offline.
AUDIT-INFRA-07 — Serve the correct robots.txt per environment
Severity: important — Detection: runtime
Rule: Production serves a robots.txt that allows crawling and declares the
sitemap; staging and preview environments serve Disallow: / (or are otherwise
blocked from indexing).
Why: The two failure modes are both costly: a production store that disallows crawling disappears from search results, and an indexable staging environment creates duplicate content that competes with production and leaks unreleased catalog data.
How to check:
- Production:
Expectcurl -s https://<production-site>/robots.txt
Allow: /(or no globalDisallow) and aSitemap:line pointing at the production sitemap URL. A globalDisallow: /here is a critical SEO finding. - Staging/preprod:
Expectcurl -s https://<staging-site>/robots.txt
Disallow: /. Front-Commerce generates this automatically outside production mode; if the environment runs in production mode, indexing must be blocked another way (HTTP auth,x-robots-tag). - If the project overrides
app/routes/robots[.txt].tsx, read the override:allowCrawling(or the equivalent logic) must depend on the environment, not be hardcoded totrue.
AUDIT-INFRA-08 — Run supported, up-to-date Front-Commerce and Node.js versions
Severity: important — Detection: static
Rule: The project uses a currently supported Front-Commerce release line, lags no more than a few minor versions behind the latest release, and runs a Node.js version supported by that release.
Why: Version lag is the most recurrent audit finding, and it compounds: each skipped minor makes the next upgrade larger and riskier, while security fixes and performance improvements ship only in recent releases. An end-of-life Node.js version stops receiving security patches entirely.
How to check:
- Read the deployed versions:
grep -E "\"@front-commerce/(core|remix)\"" package.jsongrep -E "\"node\"" package.jsoncat .nvmrc 2>/dev/null
- Compare the
@front-commerce/*version against the latest release listed on the changelog. Record the gap in minor versions; more than two or three minors behind, or a major line that no longer receives fixes, is a finding with the upgrade path as remediation. - Verify the Node.js version (engines field,
.nvmrc, or the deployment image) is an active or maintenance LTS line and matches the requirement of the Front-Commerce release in use. - Check the lockfile is committed and consistent (
pnpm-lock.yamlor equivalent), so the audited versions are the deployed ones.