Files
worker/docs/inventory.md
Gleb Tv fd1a010e31
Все проверки выполнены успешно
CI / test (push) Successful in 30s
Docker / Build and publish worker image (push) Successful in 10m49s
docs: migrate worker implementation plans
2026-07-13 18:19:00 +03:00

6.3 KiB

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 rstuff 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:

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:

{
  "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 rstuff

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 rstuff rsmon.inventory.v1 stream remains a control-plane output/input, not 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.