Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/swarm-logs
Repository files (latest commit first)
Filename Latest commit message Latest commit date
atlas 44984e0d36 move install_crypto_provider to swarm-secret-client
The rustls provider install is process setup every swarm binary runs, and
swarm-secret-client depends on no other swarm crate, so a binary that only
needs the provider and the store no longer links the queue client.

- swarm-secret-client/src/lib.rs, Cargo.toml: the function, its test, a
  `//!` line on why it lives there, and the rustls dependency; rustls
  `ring` as a dev-dependency feature, so the test builds both providers as
  the binaries do and fails if the install is dropped.
- swarm-queue-client/src/lib.rs, Cargo.toml: function and test removed;
  `connect()` calls the secret client's; rustls dropped (no other use),
  swarm-secret-client added.
- swarm-metrics-auth/Cargo.toml: drop swarm-queue-client, whose only use
  was the provider; the binary no longer links async-nats.
- swarm-logs-auth, swarm-logs, swarm-metrics, swarm-ci-metrics Cargo.toml:
  the dep comment no longer names the provider (they keep the dep for
  agent_token / the OIDC mint).
- Cargo.toml: the rustls comment names the provider's new home.
- 14 call sites (hive-agent, hive-c0re, hive-subagent-mcp x2,
  swarm-builder, swarm-ci-metrics, swarm-claude-login, swarm-controller,
  swarm-logs-auth, swarm-logs, swarm-metrics-auth, swarm-metrics,
  swarm-nats-auth, swarm-review-classifier): one-line path change.
- Cargo.lock: the dependency edges above.
2026-10-18 03:18:43 +02:00
..
src move install_crypto_provider to swarm-secret-client 2026-10-18 03:18:43 +02:00
Cargo.toml move install_crypto_provider to swarm-secret-client 2026-10-18 03:18:43 +02:00
README.md swarm-logs-auth: rate-limit verification and cache positive verdicts 2026-10-14 01:54:54 +02:00

swarm-logs

An agent's CLI for the swarm log store. One verb — swarm-logs query '<LogsQL>' — so reading logs pipes and greps like any other command instead of being a hand-rolled token request plus a curl, per query.

Read-only and query-only. There is no ingest path here (that is the collector's), and no tail: streaming is a different LogsQL endpoint with a different response shape, left for a follow-up rather than folded in.

Distinct from hive-metric, the other half of the same surface from an agent's seat: that one writes a custom metric, this one reads logs.

⚠️ There is no scoping

The gateway forwards the query unmodified, so any authenticated caller reads the whole swarm's logs — every hive's, not only its own. That is the rule in force rather than an omission here; when read permissions exist they attach at the gateway location, not in this binary.

How it authenticates

As the agent itself. On each query it reads the agent's own queue secret, swarm/agents/<agent>/queue, from the swarm secret store with the agent's store certificate (nix/agent-modules/bao.nix), the same read hive-agent makes for its queue connection. It sends the secret as Authorization: Bearer swarm-agent.<agent>.<secret>, spelled by swarm_queue_client::agent_token.

At the gateway, nginx hands a bearer of that shape to swarm-logs-auth, which compares it with the stored secret (swarm-agent-verify, the check the queue's auth callout also uses). A 401 makes swarm-logs read the secret again and retry once, which covers a secret re-minted between the read and the check. swarm-logs-auth grants a secret it has verified for 60 s by default without asking the store again, so a replaced secret also keeps working for up to that long. A 403 is the gateway's per-address rate limit on these checks; it is not retried.

🩸 The secret is never logged or rendered into an error.

Configuration

Supplied by nix/agent-modules/logs.nix, which wraps the binary — the same shape swarmctl is configured in, and for the same reason: every value is derived from an option that module owns, so a default here would be an address we hope points at something.

variable what
HIVE_AGENT_LOGS_QUERY_URL the LogsQL query endpoint
HIVE_AGENT_NAME this agent's name; the store path and role
BAO_ADDR the secret store's address
BAO_CLIENT_CERT path of the agent's live store certificate
BAO_CLIENT_KEY path of its key
BAO_CACERT path of the store's CA; missing or empty is fine

With no HIVE_AGENT_LOGS_QUERY_URL the binary says there is no log store; with the URL and no store address it reports a deployment bug by name.

Output

$ swarm-logs query 'atlas-otel-probe' --limit 5

One log message per line by default (the record's _msg), which is what a grep pattern is written against. --format json passes the store's NDJSON through unmodified, for _time, _stream and jq.

A record the projection cannot understand — no string _msg, or not JSON at all — is printed whole rather than dropped. Silently losing a row would make an incomplete answer indistinguishable from a complete one.

A non-200 is reported with its body and a non-zero exit, never as an empty result. That is the whole reason the gateway grew a separate machine route: the operator's browser route answers an unauthenticated caller with authelia's login page as a 200 with an HTML body, and a client that reads only the status code records a query that succeeded and matched nothing.