diff --git a/docs/service-contract.md b/docs/service-contract.md new file mode 100644 index 0000000..3d49987 --- /dev/null +++ b/docs/service-contract.md @@ -0,0 +1,30 @@ +# Endpoint Monitor Service Contract + +## Resource and lifecycle + +A monitor has an immutable UUID `id`, a `name`, an HTTP(S) `url`, and timestamps. Its current status starts as `unknown` and becomes `up` only when an on-demand check receives a 2xx or 3xx (after following redirects); all other HTTP responses and transport failures are `down`. Status records include check time, latency, HTTP status when available, and a redacted error. + +State is process-local and in memory. It is lost at restart and is neither shared nor replicated across workers; production deployment must therefore use one worker. Store operations and status replacement are protected by one `asyncio.Lock`. A check updates the record only if it still exists. + +## API + +- `POST /monitors` -> 201, create a monitor. +- `GET /monitors` -> 200, list monitors. +- `GET /monitors/{id}` -> 200 or 404. +- `PATCH /monitors/{id}` -> 200 or 404; omitted fields are unchanged. +- `DELETE /monitors/{id}` -> 204 or 404. +- `POST /monitors/{id}/check` -> 200 check result, 400 for a security-policy rejection, or 404. +- `GET /monitors/{id}/status` -> 200 current status or 404. +- `GET /healthz` is liveness; `GET /readyz` confirms the process store and checker are initialized. + +Errors have the shape `{"error":{"code":"...","message":"..."}}`; validation errors additionally carry `details`. There is no authentication. + +## Outbound security and operations + +Checks accept only HTTP and HTTPS, reject URL credentials, resolve every initial and redirect target, and reject a target if any resolved address is loopback, private, link-local, multicast, reserved, unspecified, or otherwise non-global. Redirects are followed manually up to the configured bound so each hop is checked. Requests and connection pools have bounded timeouts. This DNS validation prevents ordinary private-address and redirect SSRF; like resolver-then-connect designs generally, it cannot completely eliminate DNS rebinding TOCTOU without a transport that pins the validated address. + +Logs are JSON objects and include monitor ID, event, status, latency, and a URL with query and fragment removed. Credentials and query values are never logged. Environment settings are prefixed `MONITOR_` and validated at startup. + +## Project layout + +`src/monitor_service` contains settings, models, store, checker, logging, and API composition. `tests` contains unit and API tests. Packaging, container files, validation commands, and operating guidance live at repository root.