Files
crucible-agent-build-fastap…/README.md

84 lines
3.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Endpoint Monitor
A typed FastAPI service that stores endpoint monitors in process-local memory and performs secure, on-demand HTTP checks.
## Quick start
Requires Python 3.12.
```sh
python -m venv .venv
. .venv/bin/activate
pip install -e '.[dev]'
make check
uvicorn app.main:app --reload --workers 1
```
Create and check a monitor:
```sh
curl -sS -X POST http://localhost:8000/v1/monitors \
-H 'content-type: application/json' \
-d '{"name":"example","url":"https://example.com/health?token=do-not-log"}'
curl -sS -X POST http://localhost:8000/v1/monitors/MONITOR_UUID/checks
curl -sS http://localhost:8000/v1/monitors/MONITOR_UUID/status
```
Interactive OpenAPI documentation is at `/docs`. The full route/status/error contract and SSRF model are in [docs/service-design.md](docs/service-design.md).
## Configuration
All values are startup-validated and use environment prefix `MONITOR_`:
| Variable | Default | Constraint |
|---|---:|---|
| `MONITOR_APP_NAME` | endpoint-monitor | string |
| `MONITOR_LOG_LEVEL` | INFO | logging level |
| `MONITOR_CHECK_TIMEOUT_SECONDS` | 5 | >0, <=30 |
| `MONITOR_MAX_REDIRECTS` | 5 | 010 |
| `MONITOR_MAX_RESPONSE_BYTES` | 1000000 | 110000000 |
Checks resolve every hop and block any hostname with a non-public answer. Redirects are manual and bounded; total elapsed timeout and response size are bounded. Query and fragment data and URL credentials are redacted from structured logs. URL credentials are rejected. Application checks cannot create a perfect DNS-rebinding boundary; use deny-by-default egress networking or a hardened outbound proxy in sensitive deployments.
## Tests and quality
```sh
make lint # Ruff formatting check and lint
make type # strict mypy
make test # pytest API/unit suite
make check # all three
```
Tests are directly inspectable under `tests/`: CRUD/operations and API mapping (`test_api.py`), lock concurrency and stale compare-and-set updates (`test_store.py`), timeouts/statuses/DNS and redirect SSRF/log redaction (`test_checker.py`), and environment validation (`test_config.py`). Outbound requests use `httpx.MockTransport`; tests do not access the network.
## Container
```sh
docker build -t endpoint-monitor:local .
docker run --rm -p 8000:8000 endpoint-monitor:local
# or
docker compose up --build
```
The image runs as a non-root user, has a liveness healthcheck, and deliberately starts one Uvicorn worker.
## Layout
```text
app/ service implementation
checker.py bounded checks, DNS/redirect SSRF policy
config.py validated environment settings
logging.py structured JSON and URL redaction
main.py FastAPI routes and lifecycle
models.py API schemas and status semantics
store.py lock-protected in-memory state and CAS updates
tests/ mocked unit and API tests
docs/service-design.md contract and architecture
docs/verification.md execution record and reproducible commands
Dockerfile, compose.yaml, pyproject.toml, Makefile
```
## Important limitations
All monitors disappear on restart. State is not shared between processes, hosts, or Uvicorn workers, so run exactly one worker. There is no authentication; place the service behind an authenticated gateway if exposed. For durable or horizontally scaled use, replace `MonitorStore` with a transactional shared datastore and coordinate check ownership.