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
- `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
## Run locally
## Local development
Requires Python 3.12.
```sh
```bash
python -m venv .venv
. .venv/bin/activate
pip install -e '.[dev]'
ruff format --check .
ruff check .
mypy app
pytest -q
uvicorn app.main:app --reload
```
OpenAPI is at `http://localhost:8000/docs`.
Create and check a monitor:
## Examples
```sh
curl -s http://localhost:8000/healthz
curl -s http://localhost:8000/readyz
curl -s -X POST http://localhost:8000/monitors -H 'content-type: application/json' \
-d '{"name":"example","url":"https://example.com/?token=secret","timeout_seconds":3}'
curl -s -X POST http://localhost:8000/monitors/UUID/check
curl -s http://localhost:8000/monitors/UUID/status
```bash
curl -sS -X POST http://localhost:8000/monitors \
-H 'content-type: application/json' \
-d '{"name":"example","url":"https://example.com/health?token=secret"}'
curl -sS -X POST http://localhost:8000/monitors/MONITOR_UUID/check
curl -sS http://localhost:8000/monitors/MONITOR_UUID/status
curl -sS http://localhost:8000/health/ready
```
CRUD also supports `GET /monitors`, `GET|PUT|DELETE /monitors/{id}`.
OpenAPI is at `/docs`. There is intentionally no authentication.
## 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_MAX_REDIRECTS` | 5 | 0..10 |
| `MONITOR_MAX_MONITORS` | 1000 | 1..100000 |
| `MONITOR_LOG_LEVEL` | INFO | standard uppercase level |
| `MONITOR_APP_NAME` | endpoint-monitor | string |
| `MONITOR_LOG_LEVEL` | INFO | logging level |
| `MONITOR_CONNECT_TIMEOUT_SECONDS` | 2 | >0, <=30 |
| `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
```sh
```bash
docker build -t endpoint-monitor .
docker run --rm -p 8000:8000 endpoint-monitor
# 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
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.
The image runs as a non-root user and deliberately uses one worker. A restart loses
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