Operator→agent request/reply gains an `exec` verb (the protocol's
second, after `ping`). The dashboard's "Run command" tab and the
device log panels now reach a real device instead of stubs.
- contracts: `Verb::Exec`, `CommandRequest::Exec`, `ExecReply`
(capped output + truncated flag). Reuses the existing
`device-commands.<id>.>` subject — no callout permission change.
- agent: command server runs `sh -c` with a 25s deadline
(kill_on_drop), captures stdout/stderr capped at 256 KiB.
- operator: `FleetCommandsClient::exec` (30s timeout); thread the
authenticated NATS client into `RealFleetService` via
`spawn_dashboard`. `run_command` and a new `device_logs`
(`podman logs --tail 200` of the device's deployment container)
compose exec — no separate logs verb at n=1.
- frontend: replace the fake SSE log stream with a one-shot
`/devices/{id}/logs/tail` fetch (load + Refresh), CSP-safe;
auto-scroll to the latest line.
serve-web (no NATS) returns a clear "not configured" error for these
two actions; the deployed operator wires them.
25 lines
845 B
TOML
25 lines
845 B
TOML
[package]
|
|
name = "harmony-fleet-agent"
|
|
version = "0.1.0"
|
|
edition = "2024"
|
|
rust-version = "1.85"
|
|
|
|
[dependencies]
|
|
harmony-fleet-auth = { path = "../harmony-fleet-auth" }
|
|
harmony-reconciler-contracts = { path = "../../harmony-reconciler-contracts" }
|
|
harmony = { path = "../../harmony", default-features = false, features = ["podman"] }
|
|
async-nats = { workspace = true }
|
|
async-trait = { workspace = true }
|
|
chrono = { workspace = true }
|
|
futures-util = { workspace = true }
|
|
serde = { workspace = true }
|
|
serde_json = { workspace = true }
|
|
# `process` is agent-local: only the exec command server shells out.
|
|
tokio = { workspace = true, features = ["process"] }
|
|
tracing = { workspace = true }
|
|
tracing-subscriber = { workspace = true }
|
|
anyhow = { workspace = true }
|
|
clap = { workspace = true }
|
|
toml = { workspace = true }
|
|
thiserror = { workspace = true }
|