From 17b8722c364a429bd4cd2e6149730a12ebd635c3 Mon Sep 17 00:00:00 2001 From: demo-bot Date: Sun, 9 Aug 2026 15:49:56 +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 | 66 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 3a175d1..735df26 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,59 @@ -# Endpoint Monitor +# Endpoint Monitor Service -A typed, unauthenticated FastAPI service for process-local monitor CRUD and secure on-demand HTTP checks. See [SERVICE_DESIGN.md](SERVICE_DESIGN.md) for the complete contract and [VERIFICATION.md](VERIFICATION.md) for honest generation-time evidence. +A typed FastAPI service for process-local endpoint monitors and secure, on-demand HTTP checks. The complete contract and security semantics are in [SPEC.md](SPEC.md). -## Layout - -- `app/main.py`: API composition and lifecycle -- `app/models.py`, `app/store.py`: schemas and lock-protected memory -- `app/security.py`, `app/checker.py`: SSRF policy, redirects, timing, HTTP -- `tests/`: API, checker/security, store, and redaction tests - -## Local development +## Quick start Requires Python 3.12. -```bash +```sh python -m venv .venv . .venv/bin/activate pip install -e '.[dev]' -ruff format --check . -ruff check . -mypy app -pytest +make check uvicorn app.main:app --reload ``` -Create and check a monitor: +Open `http://127.0.0.1:8000/docs`. Example: -```bash -curl -sS -X POST http://localhost:8000/v1/monitors \ +```sh +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 -X POST http://localhost:8000/v1/monitors/UUID_FROM_ABOVE/check -curl -sS http://localhost:8000/v1/monitors/UUID_FROM_ABOVE/status + -d '{"name":"Example","url":"https://example.com/health?token=not-logged"}' +curl -sS -X POST http://127.0.0.1:8000/monitors/UUID/check +curl -sS http://127.0.0.1:8000/monitors/UUID/status ``` -OpenAPI is at `/docs` and `/openapi.json`. - ## Configuration -All settings are validated at startup. Variables are `MONITOR_REQUEST_TIMEOUT_SECONDS` (default 5, max 30), `MONITOR_CONNECT_TIMEOUT_SECONDS` (default 2, max 10), `MONITOR_MAX_REDIRECTS` (default 5, max 10), and `MONITOR_LOG_LEVEL` (default `INFO`). +Settings are validated at startup and use the `MONITOR_` prefix: `LOG_LEVEL` (default `INFO`), `TOTAL_TIMEOUT_SECONDS` (10, max 60), `CONNECT_TIMEOUT_SECONDS` (3), `READ_TIMEOUT_SECONDS` (5), `MAX_REDIRECTS` (5, max 10), and `USER_AGENT`. Connect/read values cannot exceed total timeout. -## Container +## Security behavior -```bash -docker build -t endpoint-monitor . -docker run --rm -p 8000:8000 endpoint-monitor +Every hop is resolved and all returned addresses must be globally routable. A mixed public/private DNS response is rejected. A dedicated connector receives only the validated addresses for that hop, so the HTTP library cannot perform a second unvalidated lookup; TLS still verifies the URL hostname. Redirects are followed manually only after the next URL passes the same policy. Literal IPs are classified identically, URL credentials are rejected, environment proxies are ignored, redirect count is bounded, and the entire operation (including DNS and all hops) has a total timeout. Logs contain a redacted URL with no query, fragment, or credentials. + +The checks in `tests/test_security.py` provide inspectable evidence for private/special IP blocking, mixed-answer rejection, address pinning, per-hop redirect validation, total timeout mapping, and query redaction. `tests/test_atomic.py` proves revision-based atomic status application. Outbound HTTP is faked in tests; tests never depend on the public network. + +## Docker + +```sh +docker build -t endpoint-monitor:local . +docker run --rm -p 8000:8000 endpoint-monitor:local # or docker compose up --build -curl -f http://localhost:8000/readyz ``` -The image runs as a non-root user and intentionally starts one worker. Memory is lost on restart, is not shared between workers/containers, and has no durability or horizontal consistency. The API has no authentication and should not be exposed directly to untrusted networks. DNS re-resolution by the underlying HTTP transport leaves a DNS-rebinding window after policy validation; use network-level egress controls in production. +The image runs as a non-root user with exactly one Uvicorn worker and a healthcheck. + +## Layout + +* `SPEC.md` — route/status/error/security contract and architecture +* `app/main.py` — FastAPI routes and dependency wiring +* `app/store.py` — lock-protected volatile state and compare-and-set status +* `app/security.py` — URL redaction, DNS resolution, and IP policy +* `app/checker.py` — pinned transport, redirects, timeouts, latency/error mapping +* `tests/` — API, policy, timeout, logging, and concurrency tests + +## Operational limitation + +There is deliberately no database. All monitors vanish on restart and multiple processes would have divergent state. Keep one worker, as the container does. For durability or horizontal scaling, replace `MonitorStore` with shared transactional storage before deployment. There is no authentication; place the service behind suitable network and identity controls.