Files
Vibe Coder 4ae44e36fc
Some checks failed
ci / lint (push) Successful in 1m16s
ci / openapi (push) Successful in 30s
ci / postgres (push) Successful in 3m38s
ci / test (push) Has been cancelled
Record the distributed poller as a deferred v2 item
The owner asked whether remote pollers could work per site over an
outbound-only MQTT link, keep polling while the master is down, and
receive device credentials sealed to their own key. The assessment
found it feasible but deferred it to v2, so the requirements, the gaps
in the current code and the main risks are written down for later.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 21:26:26 +00:00
..

nmon build milestones

The build follows the six gated milestones in docs/spec/spec.md. Each milestone has its own document here. It is written before any code for that milestone and its Gate log is filled in when the gate passes. A milestone is done only when:

  1. make lint is clean: maintainability is a hard rule (docs/MAINTAINABILITY.md), and every gate script runs lint first,
  2. every acceptance line it closes (from build-detail.md) has a test that passes,
  3. make test (go test -race ./...) and make test-integration pass,
  4. its gate command (make gate-mN) passes when run by the supervisor, and
  5. the tree is committed and tagged mN.
# Milestone Gate Doc Status
M1 Skeleton and fixtures nmon serve polls the counters fixture and /api/v1/query returns rising ifHCInOctets M1 passed, tagged m1
M2 Discovery and profiles every fixture's expect.yaml passes, including v1 and v3, and the PDU budget holds M2 passed, tagged m2
M3 Graphs and UI a port's in/out graph renders at 1 h, 24 h and 30 d from the counters fixture M3 passed, tagged m3
M4 Alerting stopping a parent fixture sends one notification naming it and its children M4 passed, tagged m4
M5 Push ingest, rollup, checks a replayed Proxmox sample shows under its node and a 2 y query hits the 1 h tier M5 passed, tagged m5
M6 Auth and ops a viewer gets 403 on PUT (2,000-device loadtest skipped, approved deviation) M6 passed, tagged m6
v1.3 BGP peers and MAC/ARP/FDB lookup MAC/IP lookup, BGP peers and bgp_peer_down, see the gate list in the doc v1.3 built, gate log filled in (not tagged)
M7 gNMI streaming after v1; not built in this run — out of scope

How the work is run

  • Supervisor (Claude Opus): writes these docs, splits each milestone into work packages (WPs), reviews every diff, runs every gate command itself, commits and tags.
  • Implementers (Claude Sonnet sub-agents): one WP each. WPs in different internal/ packages run in parallel. Shared files (go.mod, cmd/nmon/*.go wiring, openapi.json, Makefile) are changed only by the supervisor or by the single WP that owns them in that milestone.

Departures from the spec are recorded in docs/DEVIATIONS.md.

Rules every WP follows (from "Decisions that don't move")

  • Maintainability is a hard rule. Follow docs/MAINTAINABILITY.md: zero golangci-lint and ESLint findings in your packages, the function, complexity and file-size limits, and the layering rules. Every WP brief cites it.

  • One static binary, CGO_ENABLED=0. No raw SQL outside internal/store.

  • The 60 s poll path talks only to devices (SNMP, ICMP) and the local hot store.

  • Metric labels on SNMP series: device=<slug>, plus iface=<ULID> on interface series. Nothing else.

  • Every port is polled, up or down. Only the profile's exclude_ifname patterns drop a port.

  • Rollups store rates, never raw counters.

  • IPv6 first: every network path works on v6 and v4; tests default to ::1.

  • Time comes from internal/clock. No time.Now()/time.Sleep in logic that a test must control.

  • Tests never need real hardware. Fixtures are .snmprec files served by internal/simagent.

Deferred (revisit after v1 milestones)

  • Deployment playbook: install layout (binary, /usr/share/nmon/mibs sidecar, systemd unit granting port 162, key file location), TLS/ACME or proxy setup, IdP configuration, backups, and upgrades. Raised by the user on 2026-10-22; deliberately postponed.

  • Web push notifications (v2): a webpush receiver kind in internal/notify (RFC 8291 payload encryption, RFC 8292 VAPID, standard-library crypto), per-user subscriptions (needs M6 users), a service worker in the UI, and push endpoints in the outbound allow-list. Out of v1 per the spec's non-goals ("alerts go to webhooks and email only"). Owner deferred it to v2 on 2026-10-22. Until then, a webhook receiver pointed at ntfy or Gotify gives phone push.

  • Distributed poller (v2): remote pollers per site or rule that spool to disk while the master is down, send signed chunks over an outbound-only link (MQTT through a broker), and receive device credentials sealed to their own key. Assessed feasible on 2026-10-25 and deferred to v2 by the owner. Requirements, gaps and risks: v2-distributed-poller.md.

  • BMC support: SNMP profiles for Dell iDRAC, HPE iLO and Supermicro (health, temperatures, fans, PSUs, power, RAID) feeding the Health/Power/Environment tabs; a native Redfish collector later. Today, Redfish works only via an exporter pushing with a push token. Owner: "good enough for now" (2026-10-23).

Post-v1 additions

  • Device management UI (2026-10-23): the UI had no way to add a device. Added an admin-only "Add device" dialog on the device list (IPv6/IPv4 addresses, SNMP v1/v2c/v3, synchronous discovery with the reattach 409 flow) and an Actions menu on the device page (Edit with parents and SNMP replacement, Rediscover now, Retire; Purge now asks for the device name). New API route POST /api/v1/devices/{slug}/retire (admin, audited, additive). The SNMP fields are one shared component (web/src/components/SnmpFields.tsx). Screenshots: docs/screenshots/devices-mgmt/.

  • Profiles, profile pinning and row navigation (2026-10-23): new shipped profiles ubiquiti-edgeswitch, ubiquiti-unifi-switch, ubiquiti-unifi-ap and vyos; discovery re-matches unpinned devices every run (and at startup) and an admin can pin a profile from the Edit dialog (DEVIATIONS 39, 40); the device header explains why a device is generic. On the device list, the interface search results and the poller health table, a click anywhere in a row (or Enter on a focused row) opens the device or graph; the name stays a real link. Screenshots: docs/screenshots/v1.0.1/.

Review artifacts

  • From M3 on, each UI milestone's gate captures Playwright screenshots of every page into docs/screenshots/<milestone>/ for the user to review.