decomposer: generate deliverable files for Define the service contract and project architecture for the FastAPI endpoint monitoring service.; Implement the typed monitor CRUD API and concurrency-safe in-memory state according to the service design.; Implement secure on-demand endpoint checks with status updates, latency measurement, robust error handling, and redacted structured logs.; Add operational API endpoints and environment-driven runtime configuration to the monitoring service.; Create automated tests for the monitoring service.; Package the service with Docker and developer documentation.; Validate the complete project.
Some checks failed
ci / test (push) Has been cancelled

This commit is contained in:
2026-08-09 15:57:57 +00:00
parent 08de86863d
commit 67254ede71

View File

@@ -1,72 +1,71 @@
# Endpoint Monitor # Endpoint Monitor Service
A typed FastAPI service that stores endpoint monitors in concurrency-safe, process-local memory and checks them on demand with bounded timeouts, redirect validation, DNS-based SSRF policy, latency/status updates, and redacted JSON logs. There is intentionally no authentication. A typed FastAPI service for process-local monitor CRUD and secure, on-demand HTTP
checks. The full contract and status semantics are in
[`docs/service-contract.md`](docs/service-contract.md).
## Layout ## Run locally
- `SPEC.md`: normative API, status, security, logging, and lifecycle contract
- `app/`: configuration, models, locked store, SSRF policy, checker, and API
- `tests/`: API/unit tests with mocked outbound HTTP and DNS
- `Dockerfile`, `compose.yaml`: single-worker container packaging
## Local development ```bash
Requires Python 3.12.
```sh
python -m venv .venv python -m venv .venv
. .venv/bin/activate . .venv/bin/activate
pip install -e '.[dev]' pip install -e '.[dev]'
ruff format --check .
ruff check .
mypy app
pytest -q
uvicorn app.main:app --reload uvicorn app.main:app --reload
``` ```
OpenAPI is at `http://localhost:8000/docs`. Create and check a monitor:
## Examples ```bash
```sh curl -sS -X POST http://localhost:8000/monitors \
curl -s http://localhost:8000/healthz -H 'content-type: application/json' \
curl -s http://localhost:8000/readyz -d '{"name":"example","url":"https://example.com/health?token=secret"}'
curl -s -X POST http://localhost:8000/monitors -H 'content-type: application/json' \ curl -sS -X POST http://localhost:8000/monitors/MONITOR_UUID/check
-d '{"name":"example","url":"https://example.com/?token=secret","timeout_seconds":3}' curl -sS http://localhost:8000/monitors/MONITOR_UUID/status
curl -s -X POST http://localhost:8000/monitors/UUID/check curl -sS http://localhost:8000/health/ready
curl -s http://localhost:8000/monitors/UUID/status
``` ```
CRUD also supports `GET /monitors`, `GET|PUT|DELETE /monitors/{id}`.
OpenAPI is at `/docs`. There is intentionally no authentication.
## Configuration ## Configuration
All settings are startup-validated. Invalid values prevent startup.
| Environment | Default | Constraint | All settings are validated at startup and use the `MONITOR_` prefix:
| Variable | Default | Constraint |
|---|---:|---| |---|---:|---|
| `MONITOR_REQUEST_TIMEOUT_SECONDS` | 5 | >0, <=30 | | `MONITOR_APP_NAME` | endpoint-monitor | string |
| `MONITOR_MAX_REDIRECTS` | 5 | 0..10 | | `MONITOR_LOG_LEVEL` | INFO | logging level |
| `MONITOR_MAX_MONITORS` | 1000 | 1..100000 | | `MONITOR_CONNECT_TIMEOUT_SECONDS` | 2 | >0, <=30 |
| `MONITOR_LOG_LEVEL` | INFO | standard uppercase level | | `MONITOR_CHECK_TIMEOUT_SECONDS` | 5 | >0, <=60 |
| `MONITOR_MAX_REDIRECTS` | 3 | 0..10 |
Per-monitor timeout overrides the default. Query strings are emitted only as `?REDACTED`. ## Quality checks
```bash
ruff format --check .
ruff check .
mypy app
pytest
```
Outbound HTTP is mocked in tests. Security cases cover private DNS answers, redirects
to loopback, bounded errors, compare-and-set status publication, and query redaction.
## Container ## Container
```sh
```bash
docker build -t endpoint-monitor . docker build -t endpoint-monitor .
docker run --rm -p 8000:8000 endpoint-monitor docker run --rm -p 8000:8000 endpoint-monitor
# or: docker compose up --build # or: docker compose up --build
curl http://localhost:8000/healthz
```
The image runs as a non-root user with exactly one Uvicorn worker.
## Verification
Run the lint, format, type, and test commands above, then:
```sh
docker build -t endpoint-monitor .
docker run -d --rm --name endpoint-monitor -p 8000:8000 endpoint-monitor
curl --fail http://localhost:8000/healthz
curl --fail http://localhost:8000/readyz
docker stop endpoint-monitor
``` ```
## Security and operational limitations The image runs as a non-root user and deliberately uses one worker. A restart loses
DNS and every redirect target are checked and non-global addresses are denied. This policy is defense in depth, not a substitute for egress firewalling: the standard HTTP transport performs its own DNS lookup, so hostile DNS rebinding between policy resolution and connection remains possible. Enforce outbound network policy in production. all monitors. Running multiple workers/replicas creates independent datasets and
inconsistent reads; use a shared durable store before scaling. DNS preflight is not a
replacement for network-level egress controls against rebinding.
Data is ephemeral and isolated per process. Restarting loses all monitors; multiple workers produce divergent state. There is no scheduler, persistence, cross-process readiness dependency, TLS termination, rate limiting, or authentication. Deploy one worker, place behind appropriate controls, and use persistent shared storage before scaling. ## Project layout
- `app/`: API, settings, locked store, checker, SSRF policy, JSON logging
- `tests/`: API, checker, store, configuration, and security tests
- `docs/service-contract.md`: routes, semantics, lifecycle, and threat boundaries
- `VERIFICATION.md`: exact validation commands and execution status