From 557adf383e204536ad0fb4aaf3c2a7878af818e5 Mon Sep 17 00:00:00 2001 From: demo-bot Date: Sun, 9 Aug 2026 15:35:52 +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 | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 00a90cd..20886ec 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,77 @@ -# crucible-agent-build-fastapi-endpoint +# Endpoint Monitor -Auto-generated agent: build-fastapi-endpoint \ No newline at end of file +A typed, unauthenticated FastAPI service that keeps endpoint monitor definitions in concurrency-safe process-local memory and checks HTTP(S) targets on demand. It measures total latency, records the final HTTP status, follows bounded redirects, emits redacted JSON events, and rejects SSRF destinations at every hop. + +## Security and operational boundaries + +The service is deliberately unauthenticated; expose it only on a trusted network. It rejects credentials in URLs and rejects every DNS result set containing a non-global address (loopback, RFC1918/private, link-local, reserved, multicast, or unspecified). Approved DNS answers are pinned into the actual connection resolver, closing the resolution/connection DNS-rebinding gap. Redirects receive the same checks. Response bodies are never consumed. + +State is **process-local and ephemeral**. Restarting loses all monitors, and multiple workers would each have divergent state. Run exactly one worker, as the supplied commands do. Use a persistent shared store before scaling horizontally. + +## Layout + +See `docs/service-design.md` for the complete contract. Application modules are under `app/`, tests under `tests/`, and validation evidence/checklists in `docs/verification.md`. + +## Local development + +Python 3.12 is required. + +```bash +python -m venv .venv +. .venv/bin/activate +python -m pip install -e '.[dev]' +ruff format --check . +ruff check . +mypy app +pytest +uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 1 +``` + +No test performs a real outbound request; checker transport and resolution are mocked. + +## API examples + +```bash +curl -s http://127.0.0.1:8000/healthz +curl -s -X POST http://127.0.0.1:8000/v1/monitors \ + -H 'content-type: application/json' \ + -d '{"name":"example","url":"https://example.com/health"}' +curl -s http://127.0.0.1:8000/v1/monitors +curl -s -X POST http://127.0.0.1:8000/v1/monitors/MONITOR_UUID/check +curl -s http://127.0.0.1:8000/v1/monitors/MONITOR_UUID/status +curl -s -X PATCH http://127.0.0.1:8000/v1/monitors/MONITOR_UUID \ + -H 'content-type: application/json' -d '{"name":"renamed"}' +curl -i -X DELETE http://127.0.0.1:8000/v1/monitors/MONITOR_UUID +``` + +Interactive OpenAPI documentation is at `/docs`. `up` means 200–399, `down` means 400–599, `error` means checking could not safely produce an HTTP response, and `unknown` means never checked. + +## Configuration + +All settings are validated at startup. + +| Variable | Default | Bounds | +|---|---:|---:| +| `MONITOR_APP_NAME` | `endpoint-monitor` | string | +| `MONITOR_LOG_LEVEL` | `INFO` | logging level | +| `MONITOR_REQUEST_TIMEOUT_SECONDS` | `5` | >0, <=30 | +| `MONITOR_CONNECT_TIMEOUT_SECONDS` | `2` | >0, <=10 | +| `MONITOR_MAX_REDIRECTS` | `5` | 0–10 | + +## Container + +```bash +docker build -t endpoint-monitor:local . +docker run --rm -p 8000:8000 endpoint-monitor:local +# or +docker compose up --build +``` + +The image uses a slim runtime, a non-root user, one Uvicorn worker, and an internal health check. Smoke test it with: + +```bash +curl --fail http://127.0.0.1:8000/healthz +curl --fail http://127.0.0.1:8000/readyz +``` + +Logs contain JSON application events with query values replaced by `REDACTED`; Uvicorn access logging is disabled in the container so raw query strings are not reintroduced there.