From 67254ede7156f93507f1ab5005863613785ed728 Mon Sep 17 00:00:00 2001 From: demo-bot Date: Sun, 9 Aug 2026 15:57:57 +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 | 95 +++++++++++++++++++++++++++---------------------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index fd5f903..f966cb2 100644 --- a/README.md +++ b/README.md @@ -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