CommandService and QueryService are the ConnectRPC API on -listen:
one port, three wire formats, a write service and a read service kept
strictly apart. This is the API the dashboard itself calls, so nothing
reachable through it is a second-class integration.
1. One port, three protocols
jaque speaks ConnectRPC: plain JSON over HTTP/1.1 (curl-friendly, no
generated client needed), gRPC, and gRPC-Web, all on the same port as the
dashboard and /metrics (-listen).
curl -s -X POST http://127.0.0.1:8080/jaque.v1.QueryService/ListStatus \
-H 'Content-Type: application/json' -d '{}'
2. CommandService -- writes
Six RPCs, one per command variant: ProcessCheckResult,
ProcessCheckResults (batch, all-or-nothing validation, in-order
enqueue), AcknowledgeProblem, RemoveAcknowledgement,
ScheduleDowntime, DeleteDowntime. AcknowledgeProblem,
RemoveAcknowledgement and ScheduleDowntime all take a Target, which
is either one object (host/service) or every object a label selector
matches -- the same mechanism the dashboard's bulk actions use.
A success response means enqueued, not applied -- the engine resolves commands asynchronously at its own pace.
-api-token (empty by default, meaning open) protects writes only:
curl -s -X POST http://127.0.0.1:8080/jaque.v1.CommandService/AcknowledgeProblem \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <token>' \
-d '{"target":{"object":{"host":"gw"}},"sticky":true,"author":"ops","comment":"known issue"}'
3. QueryService -- reads, no token required
ListStatus (current state of one host, one service, or the whole
fleet -- optionally narrowed by a label selector), ListHistory (recent
transitions for one object or the global feed), ListObjects (every
configured object plus its labels), ListContacts, ListViews,
ListSinks (the configured perfdata sinks -- name, type, input and
selector), and GetServerInfo (the running binary's version -- the
release-stamped vX.Y.Z, or "dev" for anything else). Every read
comes from the projection, never from the engine or the event log
directly -- reads never block on write throughput. Unlike CommandService,
reads never require -api-token: the bearer token protects writes only.
4. This is the dashboard's own API
Every action in Dashboard -- acknowledge, downtime, the status table, history -- is a call to one of these RPCs. There's no separate, richer internal API the UI gets and scripts don't.
5. Security considerations
-api-token, when set, is checked with a constant-time comparison so a
response-time difference cannot leak how much of the token matched; when
unset every CommandService write is open to anyone who can reach
-listen. QueryService is never gated by -api-token, by design -- see
section 3 -- so it should not carry anything an unauthenticated caller
should not see: ListSinks and ListContacts deliberately omit sink URLs,
headers and contact target payloads (webhook URLs, command lines) from
their responses, because those can carry credentials. AcknowledgeProblem
and ScheduleDowntime's author/comment fields are operator-supplied
free text with no server-side validation beyond the RPC's type -- the same
posture the event log carries them into, see Event log
schema, section 4. There is no
transport encryption at this layer: run behind a reverse proxy or a
network boundary you control if -listen is reachable beyond a trusted
network.