A Cluster ERP server answers three unauthenticated operational routes: /.well-known/security.txt, /health, and /ready. This page describes what each returns, the settings behind them, and the tests and scripts that depend on them. The routes are defined in src/cluster_erp/server/app.py; the document builder is src/cluster_erp/server/security_txt.py. The full list of system routes is in system endpoints.
Scope and source¶
- Defined in:
src/cluster_erp/server/app.py(security_txt,health,ready) andsrc/cluster_erp/server/security_txt.py(security_txt_body). - Count: three routes, counted from the
@app.getdecorators atsrc/cluster_erp/server/app.py:1459-1476.
Security.txt¶
GET /.well-known/security.txt answers HTTP 404 when no contact is configured, and otherwise a text/plain document (src/cluster_erp/server/app.py:1459-1466). The route is not in the OpenAPI schema (src/cluster_erp/server/app.py:1459).
| Field | Content | Source |
|---|---|---|
Contact |
security_contact; a value with @ and no scheme becomes a mailto: address. |
src/cluster_erp/server/security_txt.py:21-25 |
Expires |
Now plus security_expires_days, clamped to 1 to 365 days, in UTC. |
src/cluster_erp/server/security_txt.py:26-30 |
Preferred-Languages |
tr, en. |
src/cluster_erp/server/security_txt.py:31 |
Policy |
security_policy_url, only when set. |
src/cluster_erp/server/security_txt.py:33-34 |
Canonical |
public_base_url plus the route path, only when set. |
src/cluster_erp/server/security_txt.py:35-37 |
| Setting | Variable | Value | Source |
|---|---|---|---|
security_contact |
CLUSTER_ERP_SECURITY_CONTACT |
<value> |
src/cluster_erp/config/settings.py:296 |
security_policy_url |
CLUSTER_ERP_SECURITY_POLICY_URL |
<value> |
src/cluster_erp/config/settings.py:297 |
security_expires_days |
CLUSTER_ERP_SECURITY_EXPIRES_DAYS |
<value> |
src/cluster_erp/config/settings.py:298 |
public_base_url |
CLUSTER_ERP_PUBLIC_BASE_URL |
<value> |
src/cluster_erp/config/settings.py:292 |
The module states that an empty or fictional security.txt is worse than none, which is why the route answers 404 without a contact (src/cluster_erp/server/security_txt.py:4-7).
Liveness¶
GET /health answers {"status": "healthy", "version": <app version>} and touches no backing store, so a database outage never restarts the process through a supervisor (src/cluster_erp/server/app.py:1469-1474).
Readiness¶
GET /ready asks each backing store SELECT 1 under the deadline readiness_timeout_seconds (src/cluster_erp/server/app.py:1485-1493, src/cluster_erp/config/settings.py:649).
| Check | Present when | Source |
|---|---|---|
database |
always | src/cluster_erp/server/app.py:1495 |
control_plane |
multi-tenant mode | src/cluster_erp/server/app.py:1496-1498 |
| Outcome | Status code | Body | Source |
|---|---|---|---|
| every check passes | 200 | {"status": "ready", "checks": {...}} |
src/cluster_erp/server/app.py:1499-1503 |
| any check fails | 503 | {"status": "not_ready", "checks": {...}} |
src/cluster_erp/server/app.py:1499-1503 |
A failing check is reported as fail and the error goes only to the server log, so the answer never contains a host name or connection string (src/cluster_erp/server/app.py:1477-1493).
Contract tests and consumers¶
| Consumer | Use | Source |
|---|---|---|
tests/test_readiness_contract.py |
Checks that /health carries a version and that /ready names every store with only pass or fail. A live test: without a server it fails unless CLUSTER_SKIP_LIVE_TESTS=1 is set. |
tests/test_readiness_contract.py:1-64 |
tests/test_security_txt.py |
Checks the 404 case, the mailto: conversion, the fields, and the one-year ceiling. |
tests/test_security_txt.py:20-51 |
deploy/install.sh |
Polls /ready for up to five minutes before it reports a release as live. |
deploy/install.sh:247-257 |
deploy/docker/Dockerfile |
The container health check calls /ready. |
deploy/docker/Dockerfile:43-44 |
Constraints and validation¶
security_expires_daysis clamped by the builder, not by the settings validator (src/cluster_erp/server/security_txt.py:27).- The readiness deadline is a float number of seconds with the default
2.0(src/cluster_erp/config/settings.py:649).
Terms introduced¶
| Term | Code identifier | Definition | Turkish term | Source |
|---|---|---|---|---|
| liveness probe | /health |
The route that says whether the process is alive, without touching any store. | canlılık yoklaması | src/cluster_erp/server/app.py:1469-1474 |
| readiness probe | /ready |
The route /ready that says whether the process may take traffic, by asking each store one question. |
hazırlık yoklaması | src/cluster_erp/server/app.py:1476-1504 |
Related pages¶
Verified against commit 92f8051 on 2026-11-13.