CHAOS/v0.1.0/API

The HTTP API

chaosd exposes an HTTP/JSON API served by the chaos-api crate. It is the contract every control surface builds against; the CLI consumes only this API. An OpenAPI 3 document is generated from the route annotations, committed, drift-tested in CI, and served at /swagger-ui.

Transport

In this release the API is served over a Unix domain socket, not a TCP port. There is no TLS and no authentication on this surface yet; those are planned for a later phase. The socket path defaults to /run/chaosd/chaosd.sock and is set in chaosd configuration. The daemon removes any stale socket on start and unlinks it on clean shutdown.

The API speaks ordinary HTTP/1.1 over the socket. The CLI ships a minimal Unix-socket client; any HTTP client that can connect to a Unix socket works the same way.

Endpoints

MethodPathPurpose
GET/v1/systemVersion, port bindings, backend capabilities
GET/v1/impairments/{direction}Current applied state for a direction
PUT/v1/impairments/{direction}Apply an impairment to a direction
DELETE/v1/impairments/{direction}Clear all impairments on a direction
GET/v1/impairments/{direction}/statsLive qdisc statistics for a direction
GET/v1/calibration/baselineThe stored calibration baseline

{direction} is port1 or port2. An unknown direction segment is a 400.

System

GET /v1/system reports the daemon version, the resolved per-direction bindings, and the backend capabilities:

json
{
  "version": "0.1.0",
  "ports": [
    { "direction": "port1", "interface": "enp4s0", "bdf": "0000:04:00.0" },
    { "direction": "port2", "interface": "enp5s0", "bdf": "0000:05:00.0" }
  ],
  "capabilities": {
    "supports_latency": true,
    "supports_loss_bernoulli": true,
    "supports_loss_gilbert_elliott": false,
    "supports_rate": true,
    "supports_distributions": [ { "kind": "uniform" }, { "kind": "normal" }, { "kind": "pareto" } ],
    "backend_name": "…",
    "backend_version": "…"
  }
}

Read, apply, clear

GET /v1/impairments/{direction} returns the current AppliedState — the kernel read-back.

PUT /v1/impairments/{direction} takes an Impairment body, programs it, and returns the post-apply AppliedState with any divergence:

bash
curl --unix-socket /run/chaosd/chaosd.sock \
  -X PUT http://localhost/v1/impairments/port1 \
  -H 'content-type: application/json' \
  -d '{"latency":{"kind":"constant","duration":40000000}}'
json
{
  "direction": "port1",
  "impairment": { "latency": { "kind": "constant", "duration": 40000000 } },
  "captured_at": 123456789,
  "captured_at_wall": 1700000000000000000
}

The divergence array is omitted when empty. DELETE /v1/impairments/{direction} clears the direction and returns the cleared state; a foreign root qdisc is left in place and surfaced as a divergence.

Statistics

GET /v1/impairments/{direction}/stats returns a LinkStats sample — cumulative counters plus monotonic and wall-clock sample timestamps. Poll it and compute rates from deltas between samples; the wire shape never carries rates.

Calibration baseline

GET /v1/calibration/baseline returns the stored baseline as opaque JSON, read from the configured baseline_path. When no baseline is stored, it returns 404.

Errors

Errors are returned as application/problem+json (RFC 7807) with type, title, status, and detail:

StatusCondition
400Unknown direction or malformed body
403Permission denied — the daemon lacks CAP_NET_ADMIN
404No calibration baseline stored
422Unsupported configuration or kernel rejection
500Backend or I/O error

A 422 is the response to an impairment the backend cannot apply — for example Gilbert-Elliott loss or the paretonormal distribution in this release.

OpenAPI

The generated OpenAPI document is the source of truth for the surface and is served at /api-docs/openapi.json, with the Swagger UI mounted at /swagger-ui. A CI test fails if the committed spec drifts from the annotations, so the spec and the handlers stay in lockstep. Any change to this surface is a gated change kept synchronized with the spec.

Next steps