Files
NODEDC_MISSION_CORE/docs/audits/2026-09-08-node-runtime-and-system-monitor.md
T

8.5 KiB

Node local viewer and onboard system monitoring

Approved operator job and placement

Owner request: investigate the black onboard window after local K1 START, and add «Мониторинг системы БК» to the selected apparatus in Fleet. The selected board owns measurements and history; UI navigation, capture and network outages must not control collection. This is a detail view in the existing Fleet workspace, not the compute-worker contour or a new primary navigation root. An independent System workspace would lose the selected apparatus context; a modal would constrain history inspection. The owner explicitly selected the apparatus-detail entry. Novelty class A: domain content in admitted composition.

Reuse SettingsCard, ApplicationPanel, Button, Select, StatusBadge, ResourceRow, Icon(activity/refresh/chevron-left), and the existing TelemetrySeries domain renderer. Domain cards contain current metrics; selected series shows source time, min/max/mean and gaps. No missing generic visual primitive is required. States: collecting, historical/offline, waiting for first sample, unavailable metric, storage failure, replication backlog, loading/query failure, empty range. No acquisition, provisioning, shell or host-reconfiguration action belongs here.

Reproduced diagnosis

R17 installed WebKitGTK 2.52.6 on Ubuntu. Public standalone Rerun 0.36.3 starts and stays responsive using WebGL2. WebGPU is unavailable. RTCPeerConnection is undefined, and constructing it raises ReferenceError. The shared preview effect constructs that API synchronously after viewer readiness, outside its catch. Node had no React error boundary. The historical window and WebKit processes remained alive with an empty accessible document; Node/K1 services did not restart. App cgroup memory peak was about 811 MiB and OOM counters were all zero. Ten-minute sysstat samples cannot rule out brief peaks but do not support memory exhaustion. The camera consumer lease subsequently expired from queue age; that is a delivery symptom, not proof of GPU/RAM exhaustion.

Enabling WebKit's WebRTC setting alone and supplying missing GStreamer modules in an isolated diagnostic environment did not expose the API. No global graphics workaround or new browser engine is admitted on this evidence. The local carrier uses authenticated loopback HTTP and the same plugin-owned bounded RRD/fMP4 delivery, acknowledgements, recording cursor and release logic. Remote paired WebRTC remains unchanged. There is no second capture implementation.

Telemetry architecture and limits

An independent native collector samples Linux counters every second and commits to a dedicated local PostgreSQL/TimescaleDB database. It uses only an OS-protected Unix socket, with no database TCP listener or embedded credential. Acquisition does not depend on that service. CPU/RAM/swap/pressure, per-interface bytes and errors, per-disk I/O, filesystem capacity, temperatures, observable GPU counters, USB topology/link speed and service cgroup usage/OOM counters are separate series. Unsupported counters remain null with a reason; USB negotiated speed is never presented as measured traffic. No USB payload, process arguments or environment variables are collected. UI exceptions carry only category and asset positions.

Raw retention target: seven days, with a two-GiB database target and two-GiB free disk reserve. Capacity is checked once per minute; writes pause at the target and oldest completed hourly chunks are removed. This is not a strict filesystem quota: a minute of writes, WAL and temporary files may exceed the database target. Retention and capacity loss are visible, never disguised as zeros. Bounded batches replicate over the existing paired mTLS connection. Core commits idempotently before acknowledging; disconnects leave local collection running. Latest status and historical delivery cursors are distinct so a fresh snapshot cannot skip unreplicated history. Historical timestamps and boot identity survive reconnection. Core's local archive is queryable while the board is offline.

Acceptance must separate fixture checks, real host collection, local viewer compatibility and owner hardware scans. A healthy repeated laboratory scan does not establish critical-scenario qualification of the K1 Bridge contour.

Implementation acceptance before installation

A bounded native WebKitGTK probe on the owner Ubuntu loads the unmodified production hook through a minified Vite bundle. Its source is synthetic RRD (100 points) and a synthetic H.264/fMP4 camera; it cannot submit device commands. The 2026-09-07 22:28 UTC probe reports the error boundary present with the shell alive, then hasScene=true, presented=true, cameraPresented=true. Video time advances to 2.9 s. After the fixture ends, freshness expires while the scene remains. This establishes compatibility for these fixtures, not live K1 load. Local transport uses completed bounded reads, a stable viewer cursor and native EventTarget dispatch. Remote transport keeps WebRTC with guarded construction.

Native PostgreSQL 16.15 / TimescaleDB 2.29.2 was exercised using privately extracted signed packages and a temporary socket-only cluster. Three real host samples with 184 discovered metrics were committed and replayed in order. The temporary cluster was stopped and removed. Installed-service acceptance is a separate gate.

Core keeps seven-day raw data plus minute min/max/sum/count rollups. Long ranges use complete minute buckets, preserving extrema; the selected end is rounded to the last complete minute. Missing intervals break the plot. Replica writes run outside the control heartbeat; only a durable committed cursor is ACKed. The archive is a best-effort diagnostic record at one-second sampling resolution; unobserved subsecond peaks and unsupported hardware counters remain unproved.

Packages: Node 0.8.15 and K1 0.1.14, with exact signed Timescale OSS/loader 2.29.2~ubuntu24.04-1615. The dedicated 16/ndc-monitor PostgreSQL cluster has no TCP listener. Its service memory cap is 384 MiB, collector cap 128 MiB; CPU caps are 25% and 15% of one core respectively. An initial PostgreSQL install suppresses automatic creation of an unrelated default cluster through a temporary supported postgresql-common configuration drop-in, removed on installer exit. Acquisition is protected by the existing package preinst guard and is not a test action.

R18 staging and current boundary

2026-09-08: source commits f0802d2 and e57511f; Node package provenance is f0802d2, the K1 manifest ordering correction is e57511f. No runtime files were added by the latter correction. Node Debian SHA-256: 515dbc6d0ed5f7065db59c54ae759e3b03b89dfceb0c0249e241cc0c598d6b71. K1 public Debian SHA-256: c30091b02fe16d5bc9f810c2ba7f0a7d6033f5dd67d8520a59187ea783394f4c. The immutable owner release directory is mission-core-node-20260908-r18. Local/remote hashes match; artifact inspection admits 102 Node and 185 K1 files, no private application key or symlinks. APT simulation: two package upgrades, 13 new dependency packages, zero removals. Existing bindings/records/authority are retained by the package lifecycle. The installer is open in the owner's Ubuntu session and awaits local sudo. Installed predecessors are still Node 0.8.14 and K1 0.1.13; do not report R18 as installed on this evidence.

Validation: frontend typecheck, 812 frontend unit tests, Node Go packages, 15 focused Python monitor/local-carrier/package-lifecycle tests, and 10 existing remote media tests passed. Node and Core production builds passed. The final plot correction separately verifies negative values remain distinct from zero. Private evidence lives in the experiment directory with SHA-256 manifest, UTC/monotonic probe records and operator notes, outside normal Git.

The canonical Core service was restarted through its exact launchd process group and recovered /api/health; new listener PID 57378, no backend on 8765. Browser QA confirms the Rover detail entry, empty-history state, and normal / expanded workspace modes. Escape does not resize the pre-existing outer Fleet workspace; no new keyboard behavior was added there. Data selector/time-window and installed telemetry UI checks remain pending the first real replicated sample. The temporary native probe already verifies actual viewer rendering.

Pending owner sudo: installed service/version checks, socket-only cluster, archive growth, measured collector overhead, Core durable ACK/backfill, and browser QA with real telemetry. A new physical K1 scan and critical scenarios remain operator qualification, not an automatically exercised acceptance step.