From 12c238cdceb02e75d906e92f725208cf3626a9d4 Mon Sep 17 00:00:00 2001 From: demo-bot Date: Sun, 9 Aug 2026 15:41:02 +0000 Subject: [PATCH] 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. --- README.md | 90 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index bb97a9e..9324451 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,77 @@ -# Endpoint Monitor Service +# Endpoint Monitor API -A typed FastAPI API that keeps endpoint monitors in concurrency-safe, process-local memory and performs SSRF-aware checks on demand. The service has no authentication and should not be exposed directly to untrusted users. +A typed FastAPI service for process-local endpoint monitors and secure, on-demand HTTP checks. -## Quick start +## Features -Requires Python 3.12. +- CRUD monitor resources and current-status retrieval +- bounded HTTP/HTTPS checks with latency measurement +- SSRF protection on every DNS lookup and redirect hop +- JSON logs with URL credentials, query strings, and fragments redacted +- health/readiness endpoints and validated `MONITOR_` environment settings +- concurrency-safe in-memory state -```sh -python -m venv .venv -. .venv/bin/activate -python -m pip install -e '.[dev]' -./scripts/validate.sh -uvicorn monitor_service.api:app --reload +## Layout + +- `docs/service-contract.md` — API and architecture contract +- `app/` — settings, models, store, checker, logging, and FastAPI routes +- `tests/` — API and checker/security tests using mocked outbound HTTP +- `docs/verification.md` — validation commands and expected evidence + +## Run locally + +```bash +python -m venv .venv && . .venv/bin/activate +pip install -e '.[dev]' +uvicorn app.main:app --reload ``` -Create and check a monitor: +Open `http://127.0.0.1:8000/docs`. -```sh -curl -sS -X POST http://localhost:8000/monitors -H 'content-type: application/json' \ - -d '{"name":"Example","url":"https://example.com/?secret=not-logged"}' -curl -sS -X POST http://localhost:8000/monitors/MONITOR_UUID/check -curl -sS http://localhost:8000/monitors/MONITOR_UUID/status +## Examples + +```bash +curl -sS -X POST http://127.0.0.1:8000/monitors \ + -H 'content-type: application/json' \ + -d '{"name":"example","url":"https://example.com/"}' +curl -sS http://127.0.0.1:8000/monitors +curl -sS -X POST http://127.0.0.1:8000/monitors/MONITOR_ID/check +curl -sS http://127.0.0.1:8000/monitors/MONITOR_ID/status +curl -sS http://127.0.0.1:8000/healthz +curl -sS http://127.0.0.1:8000/readyz ``` -OpenAPI is at `/docs`. Liveness and readiness are at `/healthz` and `/readyz`. +PUT accepts the same body as POST and replaces the mutable fields. DELETE returns 204. Unknown IDs return the JSON error envelope documented in the service contract. ## Configuration -All settings use the `MONITOR_` prefix: `APP_NAME`, `LOG_LEVEL`, `CONNECT_TIMEOUT_SECONDS` (default 3), `READ_TIMEOUT_SECONDS` (5), `POOL_TIMEOUT_SECONDS` (3), `MAX_REDIRECTS` (5), and `USER_AGENT`. Invalid or out-of-range values fail startup. Use one worker: memory is not durable or shared among processes. +All settings are validated at startup. -## Security behavior +| Variable | Default | Meaning | +|---|---:|---| +| `MONITOR_REQUEST_TIMEOUT_SECONDS` | `5.0` | Total check timeout, range 0.1–30 | +| `MONITOR_MAX_REDIRECTS` | `5` | Manual redirect limit, range 0–10 | +| `MONITOR_MAX_MONITORS` | `1000` | Process-local monitor capacity | +| `MONITOR_LOG_LEVEL` | `INFO` | Python log level | -Every initial and redirected HTTP(S) target is resolved before a request. A hop is denied if any answer is non-global, URL credentials are denied, redirect count is bounded, and timeouts are finite. Logs and check responses remove URL query and fragment data. See `docs/service-contract.md` for status/error semantics and the documented DNS resolver/connect TOCTOU limitation. +Private, loopback, link-local, multicast, reserved, and otherwise non-global resolved addresses are rejected. URL userinfo is rejected. Only HTTP and HTTPS are accepted. + +## Quality checks + +```bash +ruff format --check . +ruff check . +mypy app +pytest -q +``` ## Container -```sh +```bash docker build -t endpoint-monitor . docker run --rm -p 8000:8000 endpoint-monitor -# or: docker compose up --build -curl -f http://localhost:8000/healthz +# or +docker compose up --build ``` -The image is two-stage, runs as a non-root user, contains a healthcheck, and deliberately starts one Uvicorn worker. - -## Layout and verification - -- `docs/service-contract.md`: API and architecture contract -- `src/monitor_service/`: application, checker, state, models, settings, logging -- `tests/`: API, concurrency, checker, SSRF redirect/DNS, failure, and redaction tests -- `scripts/validate.sh`: the authoritative Ruff format/lint, mypy, and pytest contract -- `Dockerfile` and `compose.yaml`: container workflows - -Run `./scripts/validate.sh`. Container verification additionally uses the build/run/curl commands above. `VALIDATION.md` records what was and was not executed by generation; it must not be read as a substitute for fresh CI output. +The container has a non-root user and one worker intentionally. State is process-local and is lost on restart; multiple workers/replicas do not share monitors. Use a durable shared database before horizontal scaling or production persistence is required.