v1.3.3Stable release

Stable release v1.3.3

HTTP API and metrics contract

1.3.3 contract: /v1 routes, JSON fields, errors and Prometheus metrics. The journal schema version remains independent.

The current containers list stays empty and /readyz returns 503. The optional last_complete_snapshot field provides historical data. The failed_action field identifies the action and container when known.

Private agent and public interface

The agent listens on 127.0.0.1:9808 by default. The routes below describe that agent directly. The optional Nginx UI proxy exposes fewer routes and adds authentication. The public demo does not forward /metrics, /healthz, /readyz or notification receipts.

Reads use cached data and never trigger collection or Docker actions. JSON responses use application/json; charset=utf-8 and disable caching. HEAD keeps the response status and representation headers without a body. No endpoint changes configuration.

Routes and access

RouteMethods and responseAccess
/healthzGET, HEAD · 200 when the server responds.No agent credential.
/readyzGET, HEAD · 200 ready, otherwise 503.No agent credential.
/v1/statusGET, HEAD · 200, including degraded states.Dedicated bearer token when --status-token-file is configured.
/metricsGET, HEAD · 200, Prometheus text.By default, /metrics is open. Set serve --metrics-token-file FILE and configure the scraper with the matching bearer token to require authentication. Use --status-token-file for status reads.
/v1/actionsPOST · 202 with the recorded request.Enabled actions, dedicated token and exact origin.
/v1/auditGET, HEAD · 200 with an event page.Enabled reader and dedicated audit token.
/v1/audit/exportGET, HEAD · 200, CSV or JSONL attachment.Same access as journal reads.
/v1/notificationsPOST · 202 with the recorded receipt count.Enabled receiver and separate bearer token.

Supported but incorrect methods on an active route return 405 with Allow. Unknown or noncanonical paths and disabled protected capabilities return 404. No CORS endpoint or implicit trailing-slash aliases are provided.

Status, freshness and missing fields

api_version is 1. Clients must ignore additional fields. ready requires the last completed cycle to succeed with a monotonic age at most the configured threshold. running describes a cycle in progress; a previous fresh result can remain ready during that collection.

Before the first success, after failure or once data becomes stale, containers is []. Status remains HTTP 200 while /readyz returns 503. Success timestamps and counters remain available. Staleness alone does not add an error. Manual execution invalidates freshness before mutation.

Unknown or unrequested measurements are null in JSON objects and absent from Prometheus samples. A known zero remains zero. Sizes use bytes, timestamps use Unix seconds and percentages use 0–100 units; CPU can exceed 100 on multiple cores.

manual_actions is always present: {"enabled":false} when disabled, otherwise allowed states and up to 32 recent requests. audit_enabled indicates whether the journal reader is available. The actions counters describe automatic decisions only, including maintenance.

Manual requests and errors

The JSON body contains exactly request_id, container_id and action. IDs are respectively 32 and 64 lowercase hexadecimal characters. Discover commands through manual_actions.allowed_states, including maintenance commands when enabled.

A 202 response confirms acceptance, not successful execution. States are queued, running, succeeded and failed. Read manual_actions.recent for the outcome. A retained ID with the same payload and actor returns the existing request without re-execution. A different payload or actor returns 409. That protection ends after eviction or process restart.

One request can be pending or running across the agent. Container protection, selection, state and cooldown are rechecked before execution, so an accepted request may later fail. Queue expiry is checked when dequeuing after more than 60 seconds.

Errors use {"error":"reason"}: 400 for invalid requests, 403 for credentials or protected containers, 409 for failed preconditions, 413 for size, 415 for content type and 503 for unavailable audit storage. Reasons remain English machine-readable values. The full reference lists each reason and distinguishes initial rejection from later failure.

Journal, cursors and exports

A page contains records, next_cursor, page_cursor, scanned_bytes and limit. It is bounded to 100 events, 1 MiB of reads and 512 KiB of encoded event data, plus response overhead. An empty page may still offer a cursor for older events.

Filters combine with AND: since, until, container, source, category, result and correlation_id. Container matching uses a case-insensitive substring; correlation requires the exact ID. Dates must include a timezone. Unknown or repeated parameters are rejected.

Cursors are bound to filters and actor, exclude later appends, and expire after 15 minutes or loss of required data. A restart invalidates their signature: 400 invalid_cursor. Recognized expiry returns 410 cursor_expired. A read failure returns 503, never an empty page presented as complete.

Export uses the displayed page_cursor and the same filters to download that page only. The administrative audit-export command remains available for all retained events. See the audit guide for retention and escaping.

Metrics and notifications

The metric catalogue defines names, types, units and label keys. Tests cover every documented family. Container labels are id and name, plus specific keys such as status, health, group, path or window_seconds. Exposition order and HELP text are not fixed interfaces.

When the agent is unready, container samples are omitted; HELP/TYPE declarations can remain. Agent counters reset at process restart. Counts within an event window are gauges, not cumulative counters.

The notification receiver accepts the Alertmanager version-4 format and responds with {"recorded":N,"delivery_status":"not_reported"}. This confirms receipt recording, not email or Slack delivery. Retries may create repeated correlated receipts. A storage failure midway through a batch may leave earlier receipts stored.

Read examples

These commands target the private agent address:

AGENT_URL='http://127.0.0.1:9808'
curl --fail-with-body --silent --show-error "$AGENT_URL/healthz"
curl --fail-with-body --silent --show-error "$AGENT_URL/readyz"
curl --fail-with-body --silent --show-error "$AGENT_URL/v1/status"
curl --fail-with-body --silent --show-error "$AGENT_URL/metrics"

The full reference also provides curl commands to submit an authorized action, look up its correlation and export exactly the displayed page. Those examples require your private tokens and configured origin; they do not target the public demo.

Contract evolution

/v1 is retained. Actions and notifications accept one application/json header with optional parameters, including charset=utf-8. Bodies remain UTF-8; duplicate content-type headers return 415. Future incompatible changes follow the deprecation policy.