Files
worker/docs/inventory.md
2026-08-12 18:40:43 +03:00

167 строки
6.4 KiB
Markdown

# Worker Host Inventory
## Purpose And Boundary
Inventory connects checks to the host, service, Compose project, domain, and
deployment that they observe. The worker collects facts; the RSMon control
plane validates identity, applies account scope, reconciles lifecycle, and
persists the inventory projection.
The control-plane inventory entities remain `Server`, `ServerIp`, `Site`,
`Deployment`, `Domain`, `Repo`, and `site_repos`. Their API and legacy stream
projection are control-plane concerns. This repository owns only local
discovery and worker-originated reports.
## Existing Collectors
Current state:
- `internal/webapp/inventory.go` discovers Linux processes, command lines,
working directories, TCP listeners, and basic resource facts.
- snapshots are stored in the local web-console SQLite database;
- `internal/distworker/server_metrics.go` reports bounded process/network host
snapshots, but not normalized application inventory;
- external `deploymentd` remains the implemented authoritative collector for
nginx, Docker Compose, and host inventory on the control plane.
The worker does not currently send an inventory report to the control plane.
It must not claim deploymentd parity until the protocol, ingestion, and
reconciliation tests below are complete.
## Target Package Layout
Move collection ownership out of `internal/webapp`:
```text
internal/inventory/
collector.go orchestration and partial-success envelope
process_linux.go procfs process and listener discovery
docker.go Docker and Compose discovery behind capability
nginx.go read-only nginx virtual-host discovery
systemd.go allowlisted unit discovery
normalize.go stable IDs and control-plane report conversion
store.go optional local snapshot interface
```
The web console consumes a read-only snapshot interface. The runner consumes a
bounded report interface. Collectors return per-section errors; one failed
section does not discard successful sections.
## Report Contract
Add a typed `WorkerInventoryReport` branch to `internal/wire`:
```json
{
"kind": "result",
"inventory": {
"schema": "rsmon.worker.inventory.v1",
"report_id": "uuid",
"server_id": 42,
"collected_at": "2026-07-13T15:00:00Z",
"full_snapshot": true,
"host": {},
"addresses": [],
"processes": [],
"compose_projects": [],
"nginx_sites": [],
"systemd_units": [],
"errors": [{"section": "docker", "code": "unavailable"}]
}
}
```
Constraints:
- `report_id` is stable across transport retries and unique across collection
runs.
- `server_id` comes from authenticated `WorkerInit.ServerID`, never local env.
- A full snapshot permits missing-item reconciliation; partial reports do not.
- Section and total item counts, strings, labels, and serialized bytes are
bounded before enqueue.
- Environment variable values, file contents, process environments, container
secrets, and Compose `.env` values are never included.
- The control plane rejects a report when the worker is not linked to the
server or the private worker's account does not own it.
## Normalization
Stable local identity keys:
- process app: executable plus canonical working directory;
- Compose site: Docker Compose project name plus canonical project directory;
- Compose deployment: project plus service name;
- nginx deployment: canonical config path;
- domain: normalized lowercase hostname without trailing dot;
- systemd service: unit name.
Container IDs and PIDs are observations, not stable entity IDs. Never use them
as the sole upsert key. Every deployment includes `last_seen_at`; only a full
successful section can mark previously observed entities missing.
## Collector Requirements
### Processes
- Group related processes deterministically by executable, working directory,
and parent relationship.
- Parse TCP and UDP listeners for IPv4 and IPv6.
- Do not read another process's environment.
- Exclude kernel threads and the worker itself from application suggestions.
### Docker And Compose
- Disabled without an explicit Docker capability.
- Prefer Docker/Compose JSON output and labels; do not parse human tables.
- Collect project, service, image, state, ports, mount paths, health, and
Traefik host rules. Exclude environment values and registry credentials.
- Treat Docker socket access as root-equivalent and report the capability to
the operator.
### Nginx
- Read only configured allowlisted roots.
- Collect config path, listen values, server names, auth presence, root path,
and proxy presence. Do not send certificate private-key paths or contents.
### Host And Server IPs
- Collect hostname, OS/kernel summary, and valid non-loopback addresses.
- Do not guess a primary address; report interface and route metadata so the
control plane can apply policy.
## Relationship To deploymentd And RSLogin
Worker reports and deploymentd ingest are complementary producers of the same
control-plane projection. During migration:
- deploymentd remains authoritative for sections it currently reports;
- worker inventory is feature-gated per server;
- every row records source and source report ID;
- reconciliation occurs per source and section to prevent one producer from
deleting another producer's observations;
- the former rstuff stream direction is superseded; RSMon owns inventory and
RSLogin supplies trusted project and SSH-access input through a separate
control-plane integration, never a worker protocol.
## Delivery Phases
1. Start and stop the existing process collector; move it behind an interface.
2. Add typed report and control-plane ingestion for process/host/address data.
3. Add read-only Docker and Compose discovery.
4. Add nginx and systemd discovery.
5. Add source-aware reconciliation and deploymentd comparison mode.
6. Enable monitor suggestions only after operators confirm discovered targets.
## Acceptance Tests
- A worker restart preserves no false stable identity based on PID/container ID.
- A failed Docker section does not erase successful nginx or process data.
- Partial reports never mark absent deployments missing.
- Full reports reconcile only rows owned by the same source and section.
- Cross-account and worker/server mismatch reports are rejected.
- Fixture snapshots prove no environment values or credential-like fields are
serialized.
- Worker and deploymentd fixtures normalize equivalent Compose/nginx entities
to the same control-plane identity without deleting each other's rows.