Commit graph

107 commits

Author SHA1 Message Date
0f3f16d443 fix: only send SNMP jobs to agent for SNMP-enabled devices (#180)
- Check device.snmp_enabled before creating discovery/polling jobs
- Also check snmp_enabled for MikroTik jobs
- Prevents agent from attempting SNMP operations on ping-only devices
- Fixes "Agent collected 0 OIDs" errors for devices without SNMP

Reviewed-on: graham/towerops-web#180
2026-03-26 11:10:27 -05:00
dba9a286d3 fix: respect device SNMP version for agent polling instead of forcing v2c (#166)
Devices configured as SNMPv1 were being force-upgraded to v2c for agent
polling, which breaks devices that don't support v2c (returning empty
OID responses and no throughput/capacity data).

Reviewed-on: graham/towerops-web#166
2026-03-25 12:52:24 -05:00
94fd8780de fix/counter-wrap-detection (#164)
Reviewed-on: graham/towerops-web#164
2026-03-25 12:25:13 -05:00
cc3533ce93 update more (#146)
Reviewed-on: graham/towerops-web#146
2026-03-24 16:32:09 -05:00
303c64ceae fix: set last_heartbeat_db_update on agent join to fix offline detection (#142)
When an agent joins, we update last_seen_at in the database but don't set
last_heartbeat_db_update in the socket. This causes the heartbeat throttling
logic to be out of sync:

- On join: DB updated, but last_heartbeat_db_update not set (nil)
- First heartbeat: Updates DB again because last_heartbeat_db_update is nil
- Subsequent heartbeats: Check if >30s since last DB update
- Problem: last_heartbeat_db_update tracks the first heartbeat, not the join DB update

This manifests when Phoenix recompiles during development - the channel process
continues running with old socket assigns, and if last_heartbeat_db_update is
recent, heartbeats won't update the DB. After 10+ minutes without DB updates,
the agent appears offline even though it's still connected.

Fix: Set last_heartbeat_db_update when we update the DB on join, so the
throttling logic accurately tracks the most recent DB update.

Reviewed-on: graham/towerops-web#142
2026-03-24 12:19:13 -05:00
56643dde86 fix: use correct struct field names for Check protobuf (#141)
The Check protobuf has a `oneof config` field which generates separate
fields in the Elixir struct: :http, :tcp, :dns, :ssl. However,
check_type_config/2 was returning [config: {:http, ...}] which doesn't
match the struct definition, causing a KeyError crash in
build_and_push_check_jobs/1.

This bug was originally fixed in e0a74e2f but was accidentally
reintroduced in f703e61b when attempting to use "tagged tuple config".

Fix: Return field-specific keyword lists (e.g., [http: %HttpCheckConfig{}])
instead of [config: {:http, ...}].

Also added comprehensive test that creates all 4 check types and verifies
no KeyError crash occurs when sending check jobs to agent.

Reviewed-on: graham/towerops-web#141
2026-03-24 12:04:48 -05:00
f703e61b12 fix: code quality improvements and test reliability (#139)
Various code quality improvements and fixes:

- Settings: return error instead of auto-creating unknown settings
- PagerDuty: proper backoff timing with to_timeout()
- Gaiia sync: remove unnecessary transaction wrapper
- HTTP/UISP: simplify test plug setup
- Agent channel: tagged tuple config for check types
- SNMP: fix Task.yield/shutdown pattern, remove stale preload
- Discovery: simplify error handling
- Tests: bump executor timeouts for CI reliability
- Dockerfile: remove unnecessary --force compile
- Renovate/CI: config cleanup

Split from #135.

Reviewed-on: graham/towerops-web#139
2026-03-24 09:12:59 -05:00
e0a74e2f77 fix: use correct struct field names when building check protobufs (#121)
check_type_config was returning `config: {:http, ...}` but the
Check struct has no :config field — it has :http, :tcp, :dns, :ssl
directly. This caused a KeyError crash in build_and_push_check_jobs.

Reviewed-on: graham/towerops-web#121
2026-03-22 17:04:07 -05:00
e54ee75513 Rewrite protobuf encoding/decoding in pure Gleam with integrated validation (#104)
Replace the protobuf hex package (agent.pb.ex) and hand-written validator
(validator.ex) with a pure Gleam implementation: wire format primitives,
all 23 message types, encode/decode functions, and validation merged into
decode. Thin Elixir wrappers in agent.ex preserve the existing struct API.

- Wire format: varint, length-delimited, double (IEEE 754 via FFI), tag encode/decode
- Types: all proto3 message types as Gleam custom types with enums and oneof
- Decode: field-level parsing with integrated validation (UUID, IP, hostname, limits)
- Encode: proto3 default omission, bytes_tree concatenation, map/repeated fields
- Wrappers: Elixir structs with encode/decode delegating to Gleam, enum atom conversion
- Remove {:protobuf, "~> 0.12"} dependency

Reviewed-on: graham/towerops-web#104
2026-03-21 16:08:40 -05:00
6859525a1b Integrate Gleam into the build pipeline and rewrite three pure-function modules (#98)
Set up mix_gleam archive, gleam_stdlib, and gleeunit deps. Add Gleam
compiler to all Dockerfiles, CI workflows, nix shell, and .tool-versions.

Rewrite Numeric, QueryHelpers, and URLValidator from Elixir to Gleam with
full ExUnit test coverage. Update all callers to use the Gleam modules
directly via :towerops@module syntax. Remove duplicate sanitize_like/1
private functions in snmp.ex and trace.ex.

Reviewed-on: graham/towerops-web#98
2026-03-21 07:30:36 -05:00
45a12ed181 Fix Check protobuf oneof field encoding for service checks (#101)
Protobuf oneof fields use a single :config key with tagged tuples
like {:dns, %DnsCheckConfig{}} rather than individual keys. The
check_type_config functions were setting e.g. dns: %DnsCheckConfig{}
directly, causing KeyError crashes in Check.__struct__/1.

Reviewed-on: graham/towerops-web#101
2026-03-21 06:56:48 -05:00
76b3dd6a93 add ssl/tls certificate expiration check type (#64)
add ssl check executor that connects via TLS, reads peer certificate
expiry, and returns OK/WARNING/CRITICAL based on configurable
warning_days threshold. includes protobuf config, liveview form fields,
agent channel encoding, oban worker dispatch, and unit tests.

Reviewed-on: graham/towerops-web#64
2026-03-17 16:14:22 -05:00
0c8bb35ef7 add query_helpers tests and fix all credo issues (#56)
- add tests for QueryHelpers.sanitize_like/1 (%, _, \ escaping)
- fix nesting depth in store_check_result, handle_check_state_change,
  graphql check resolver, checks controller, and ping executor
- fix cyclomatic complexity in build_check_protobuf by extracting
  check_type_config/2 function clauses
- fix formatting in api_docs_html template

Reviewed-on: graham/towerops-web#56
2026-03-17 10:43:57 -05:00
c6913685ee wire up service checks (HTTP/TCP/DNS) to remote agents (#50)
send check_jobs protobuf to agents during job dispatch cycle, handle
check_result messages back with state transitions and alert
creation/resolution. auto-assign checks to device's effective agent
token on creation, broadcast check changes via PubSub so connected
agents get immediate updates.

add edit/delete support for service checks on device show page with
form pre-population from existing check config. auto-fill TCP host
from device IP address.

includes validate_check_result/1 for protobuf validation and
list_checks_for_agent/2 for querying agent-assigned service checks.

also fixes pre-existing broken device_type_icon reference in device
index template.

Reviewed-on: graham/towerops-web#50
2026-03-16 17:25:02 -05:00
7251930404
add mobile app websocket channel and improve QR linking UX
- add MobileSocket for token-authenticated mobile WebSocket connections
- add MobileChannel with org-level and device-level real-time events
- add /mobile/socket endpoint for iOS app connections
- add "Link Mobile App" to user dropdown menu for discoverability
- improve QR code page with numbered steps and clearer instructions
- add socket/channel tests (17 total)
2026-03-13 17:28:36 -05:00
904ced77b9
fix: add recurring job dispatch timer for agent-polled devices
The server only sent polling/ping jobs to agents once on WebSocket join
and never re-dispatched them. After the first batch completed (~5-10s),
devices were never polled again until the agent reconnected.

:send_jobs now schedules a follow-up dispatch every 60s (configurable).
Unifies the timer management with :assignments_changed to prevent
accumulation.
2026-03-12 12:07:34 -05:00
72f81c572d
add real-time GraphQL API with time-series queries and subscriptions
- add absinthe_phoenix for WebSocket subscription support
- create GraphQL WebSocket socket with API token auth at /socket/graphql
- add time-series queries: deviceSensors, sensorReadings, interfaceTraffic, checkResults
- add subscriptions: deviceStatusChanged, alertEvent, sensorReadingsUpdated
- wire subscription triggers into agent_channel and alerts contexts
- add org-scoped access control for sensors/interfaces via join queries
- add 17 tests covering queries, org isolation, empty data edge cases, and auth
- update GraphQL API docs page with time-series and subscription sections
2026-03-12 10:24:39 -05:00
532d88ffb9
perf: disable Req retry for faster error tests
- Add retry: false to VISP Client HTTP requests
- Add retry: false to ReleaseChecker GitHub API requests
- Remove unused Plug.Conn import from RemoteIpLogger
- Remove unused default parameter from req_get/2

Results:
- VISP sync test: 7007ms → 113ms (62x faster)
- ReleaseChecker test: 7004ms → 17ms (402x faster)
- UserResetPasswordLive test: 1495ms → 284ms (5x faster)

Req's default retry behavior (1s, 2s, 4s exponential backoff) was
causing 7-second delays for HTTP 500/503 error responses in tests.
For these clients, immediate failure is preferred over retries.
2026-03-10 16:19:31 -05:00
07911dfa3e
perf(tests): make AgentChannel debounce delay configurable for faster tests
- Add :agent_channel_debounce_ms config (500ms prod, 50ms test)
- Reduce test timeouts from 700-1000ms to 150ms
- Performance improvements:
  * agent receives updated job list: 1567ms → 664ms (57% faster)
  * agent result for deleted device: 1059ms → 620ms (41% faster)
  * rapid assignment changes: 744ms → <500ms
  * debounces rapid changes: 613ms → <200ms
- Total time saved: ~2 seconds across affected tests
- No production behavior changed
2026-03-06 07:21:52 -06:00
192cf5b064
fix(alerts): resolve stuck alerts on every successful poll, not just status change
Previous fix only resolved alerts when device status changed from down to up.
This didn't help devices already marked as 'up' with stuck unresolved alerts.

Now:
- Always check for stuck device_down alerts after successful SNMP poll
- Also check for stuck device_up alerts (should always be auto-resolved)
- Logs when stuck alerts are found and resolved
- Works for existing stuck alerts without waiting for status to change

This fixes the 8 stuck alerts in production - they'll auto-resolve on next poll.
2026-03-05 16:54:00 -06:00
3f1d97218d
fix(alerts): auto-resolve device_down alerts when agent polls device successfully
When agents poll devices via SNMP and get successful results, the code was
only processing sensor/interface data without updating device status or
resolving alerts. This caused device_down alerts to persist even after
devices came back online.

This fix:
- Updates device status to 'up' when SNMP polling succeeds
- Auto-resolves any active device_down alerts
- Creates device_up alert (matching DeviceMonitorWorker behavior)
- Broadcasts device_status_changed via PubSub

Also fixes device_up alert creation to include resolved_at timestamp
(matching DeviceMonitorWorker behavior).

Test coverage: Added test verifying auto-resolution when device recovers.
2026-03-05 16:47:48 -06:00
1d928d4356
security: implement comprehensive security audit fixes
Critical Fixes:
- Remove /health/time endpoint exposing system time information
  * Prevents attackers from detecting time sync issues for TOTP attacks
  * Removed route and controller function, updated tests
- Add email confirmation check to account data export
  * GDPR export now requires confirmed email address
  * Prevents unconfirmed accounts from accessing data export
- Add path traversal validation for MIB archive uploads
  * Extract to temp directory, validate all paths, then copy if safe
  * Prevents malicious tar/zip files from writing outside target directory
  * Added validate_extracted_paths/1 helper function

High Priority Fixes:
- Add comprehensive input validation for mobile auth
  * Length limits: device_name (255), device_os (100), app_version (50), push_token (512)
  * Prevents database corruption and storage exhaustion
- Add heartbeat rate limiting to agent channel
  * Limit database updates to once per 30 seconds (max ~2/min per agent)
  * Prevents malicious agents from exhausting database connections
- Sanitize 500 error responses
  * Return generic error messages to clients
  * Log full details server-side with request_id for support
  * Prevents leaking stack traces and module names
- Add message size limits to agent channel
  * 10MB maximum for all protobuf messages (result, heartbeat, error)
  * Prevents DoS attacks via oversized payloads

Medium Priority Fixes:
- Add GraphQL query depth limits (max_depth: 10)
  * Prevents DoS from deeply nested queries
  * Complements existing complexity limits

Code Quality:
- Refactor agent channel handlers to reduce nesting depth
  * Extract message processing into separate private functions
  * Fixes Credo warnings about excessive nesting
  * Improves code readability and maintainability

Files changed:
- lib/towerops_web/controllers/health_controller.ex
- lib/towerops_web/controllers/api/account_data_controller.ex
- lib/towerops_web/controllers/api/v1/mib_controller.ex
- lib/towerops/mobile_sessions/mobile_session.ex
- lib/towerops_web/channels/agent_channel.ex
- lib/towerops_web/controllers/error_json.ex
- lib/towerops_web/router.ex
- CHANGELOG.txt
- priv/static/changelog.txt
- test/towerops_web/controllers/health_controller_test.exs
- test/towerops_web/controllers/error_json_test.exs

All 7,424 tests passing.
2026-03-05 13:08:10 -06:00
e0757fcd6a
feat: add LLDP topology discovery support from agent
Integrates LLDP neighbor discovery from towerops-agent into Phoenix:

- Updated protobuf definitions with LldpTopologyResult and LldpNeighbor messages
- Regenerated Elixir protobuf code (agent.pb.ex) with LLDP_TOPOLOGY job type
- Added validator for LLDP topology results with neighbor and management address validation
- Added AgentChannel handler for "lldp_topology_result" events
- Added Topology.upsert_neighbor/3 public API for storing agent-discovered neighbors
- Stores LLDP neighbors in device_neighbors table via validated protobuf messages

Agent changes were committed separately in towerops-agent repo (commit b6f60c8).

Files modified:
- priv/proto/agent.proto: Added LLDP message definitions
- lib/towerops/proto/agent.pb.ex: Regenerated from proto file
- lib/towerops/agent/validator.ex: Added validate_lldp_topology_result/1
- lib/towerops_web/channels/agent_channel.ex: Added lldp_topology_result handler
- lib/towerops/topology.ex: Added upsert_neighbor/3 public wrapper
2026-03-05 11:16:28 -06:00
86a5dc728c
fix: comprehensive bug fixes from reliability audit
Critical Fixes (5):
- Fix Task.yield_many race condition causing data corruption in DevicePollerWorker
- Fix Enum.zip data corruption in SNMP Base Profile with length validation
- Fix missing Alert schema fields for check alerts (check_id, severity, etc.)
- Fix memory leaks from uncancelled LiveView timers in 4 components
- Fix PubSub subscription leak in device form credential testing

High Severity Fixes (3):
- Fix clock skew bug in needs_discovery? check with DateTime.diff clamping
- Fix nil crash in interface status display with proper nil handling
- Fix migration index names after equipment→devices table rename

Medium Severity Fixes (6):
- Fix race condition in device monitor worker (duplicate maintenance checks)
- Fix missing preload validation in devices.ex get_org_default_agent
- Fix broad rescue clause in alerts.ex with specific error handling
- Fix fire-and-forget notification tasks with try-catch error logging
- Fix LiveView state bleeding between tabs (assign_new → assign)
- Add catch-all handle_info callbacks to 3 LiveViews

Infrastructure:
- Silence health check endpoint logs (/health, /health/time)
- Add migration to fix equipment index names missed in rename

Files Changed: 16 files modified, 1 migration added
All changes compile successfully and are backward-compatible.
2026-03-05 08:53:30 -06:00
34fe5d7e49 Security fixes: mask credentials in logs/API, fix cookie/CSP/LIKE injection/webhooks
CRITICAL fixes:
- Mask SNMP community string in agent channel logs (CRITICAL-1)
- Remove snmpv3 passwords from REST API responses, return _set booleans (CRITICAL-2)
- Replace snmp_community with snmp_community_set in GraphQL type (CRITICAL-3)

HIGH fixes:
- Fix cookie same_site from invalid 'Towerops' to 'Lax' (HIGH-4)
- Remove unsafe-eval from CSP script-src (HIGH-6)
- Block GraphQL introspection queries in production (HIGH-7)
- Sanitize LIKE wildcards in SNMP device name search (HIGH-8)
- Reject webhooks when no secret configured instead of accepting (HIGH-9)

MEDIUM fixes:
- Hash mobile session tokens (SHA-256) before DB storage (MEDIUM-10)
- Apply security headers in all environments, not just prod (MEDIUM-14)
- Add GraphQL query complexity limit (500) in production (MEDIUM-16)
- Fix X-Frame-Options to DENY to match frame-ancestors 'none' (MEDIUM-13)
2026-02-15 09:09:04 -06:00
9e7ee5099d refactor: fix all credo strict issues, format all code, fix broken routes
- Fix broken route paths in dashboard (/discovery, /subscribers/trace, /config-changes)
- Fix insights empty state settings link (org-scoped route)
- Add underscores to all 86400 literals across 6 files
- Alphabetize aliases in search.ex and agent_channel.ex
- Extract changelog parser helper to reduce nesting
- Extract dashboard impact calculation to reduce nesting
- Refactor agent_channel config change detection (pattern match, extract function)
- Combine double Enum.reject into single call in trace.ex
- Fix line length in trace.ex search query
- Replace length/1 > 0 with != [] in trace_live
- Run mix format on all files
2026-02-13 19:34:40 -06:00
5a3ede1f71 feat: config change → performance correlation system (Roadmap #2)
- New config_change_events table linking backup diffs to time windows
- ConfigChanges context with record/list functions and date filters
- Auto-detect changed sections from MikroTik config diffs
- Agent channel emits change events after backup creation
- Correlator engine: 2h before / 4h after QoE metric comparison
- Creates suspect_config_change insights on significant degradation
- Config Timeline LiveView with chart data, change list, detail view
- Device page: Config Timeline tab + Recent Config Changes card
- Dashboard: Recent Config Changes section with impact indicators
- Fix pre-existing integrations_live.html.heex scope bug
2026-02-13 17:56:55 -06:00
38a0681bf7
fix channel shutnown exception 2026-02-13 08:29:15 -06:00
a61abd836c
fix: cloud poller automatic rebalancing
- create MonitoringCheck schema for the monitoring_checks table, fixing
  silent data loss where ping results were dropped by the wrong schema
- update agent channel and device monitor worker to use new schema
- fix Stats queries to use MonitoringCheck instead of Check schema
- add list_online_cloud_pollers and list_cloud_polled_devices queries
- add CloudLatencyProbeWorker to dispatch cross-agent latency probes
  every 8 hours via PubSub to all online cloud pollers
- scope AgentLatencyEvaluator to cloud pollers only with cloud_only
  filter, lower min_checks (5), wider time window (48h), and
  device-level assignments to avoid changing site/org defaults
- update cron schedule: probes at 0/8/16h, evaluation at 0:30/8:30/16:30
- refactor monitoring.ex and http_executor.ex to fix credo complexity
2026-02-12 15:32:33 -06:00
fa2ebdb973
fix: add diagnostic logging for agent job refresh on device deletion
Enhanced AgentChannel logging to track device IDs across job list updates.
Added tests verifying server correctly excludes deleted devices from job lists.

Root cause: Bug is in Go agent (appends jobs without clearing), not Phoenix server.
2026-02-12 14:36:25 -06:00
1318b1b6b7
feat: live device timestamp updates and org-scoped alert PubSub
Always broadcast from update_device_status/2 so the device index
LiveView refreshes even when status hasn't changed. Add a 15-second
tick timer to keep "Last Checked" timestamps fresh between polls.
Scope alert PubSub topics to organization for defense-in-depth.
2026-02-12 11:01:56 -06:00
aa1bac0d46
perf: batch inserts, selective LiveView reloading, and database indexes for scale
Replace individual Repo.insert() with Repo.insert_all() for sensor readings,
interface stats, processor readings, and storage readings in agent channel and
device poller worker. Add partial/composite database indexes for common query
patterns. Dashboard now uses GROUP BY aggregation instead of loading all devices.
DeviceLive.Show only reloads data for the active tab on PubSub events.
DeviceLive.Index debounces status changes and skips quota queries on updates.
Agent polling preloads filtered to monitored sensors/interfaces only.
2026-02-12 10:16:10 -06:00
f00dc3ff12
test: expand agent channel coverage from 8% to 66%
add 54 tests covering join/terminate lifecycle, heartbeat, error,
credential_test_result, monitoring_check, mikrotik_result, catch-all
handle_in events, handle_info lifecycle messages, PubSub messages,
SNMP result edge cases, poll result sensor/interface data storage,
SNMPv3 credential paths, and monitoring-enabled device job building.

fix bug where error.error_message was used instead of error.message
matching the AgentError protobuf struct field name.
2026-02-11 16:52:12 -06:00
47fcbeb483
fix: agent discovery and polling accuracy improvements
- use 64-bit HC counters (ifHCInOctets/ifHCOutOctets) instead of 32-bit
  counters that wrap every ~34s on gigabit links
- fix negative integer parsing in replay adapter so sensor scale values
  like -3 produce correct divisors (1000) instead of falling through to 1
- replace walking entire Cisco enterprise tree with targeted subtrees to
  avoid timeouts; add Juniper, HP/H3C, Fortinet, Cambium vendor OIDs
- add missing discovery OIDs: ENTITY-STATE-MIB, HOST-RESOURCES-MIB
  tables, and UCD-SNMP-MIB Linux CPU stats fallback
2026-02-11 15:58:31 -06:00
edb330e4de
normalize OIDs to fix agent-polled sensor matching
strip leading dots from OID keys returned by agent so they match
sensor OIDs stored without leading dots. fixes ubiquiti airos
wireless sensors (clients, ccq, frequency, etc) not being polled.
also fix flaky sensor_change_detector tests using global pubsub topic.
2026-02-11 15:33:08 -06:00
abbe117f5e
add sensor value change events for all sensor types
extract sensor change detection from DevicePollerWorker into shared
SensorChangeDetector module. add sensor_value_changed event for non-%
sensors when value differs from last_value. agent channel now detects
changes and updates last_value, matching phoenix poller behavior.
2026-02-11 15:06:55 -06:00
6d597f7e76
round sensor readings to 1 decimal place
division by sensor_divisor produced full float precision values
like 34.09999999. apply Float.round/2 in both the phoenix poller
and agent channel paths.
2026-02-11 14:09:22 -06:00
2875866c07
fix agent-polled devices stuck in unknown status
store_monitoring_check saved ping results from agents but never
updated device status. DeviceMonitorWorker skips agent-assigned
devices, so nothing ever moved them from :unknown to :up/:down.

added update_device_status_from_check to derive status from check
result, update the device, create alerts on transitions, and
broadcast via PubSub — matching DeviceMonitorWorker behavior.
2026-02-11 14:03:04 -06:00
cb3f2edf50
polling fix 2026-02-11 13:54:23 -06:00
9e36d5030a
poll device immediately after discovery completes
newly discovered devices sat idle with no metric data until the
next scheduling cycle. now the channel sends a poll job (and ping
job if monitoring enabled) right after discovery succeeds, using
send(self(), ...) so discovery DB writes commit first.

also reduces k8s replicas from 3 to 2.
2026-02-11 13:24:55 -06:00
bd24dfcbed
add diagnostic logging for agent result handling 2026-02-11 12:00:04 -06:00
ecd9f78ba8
Add backward compatibility for PING results from older agents
Older agents send PING job results as SnmpResult messages instead of
MonitoringCheck messages, causing FunctionClauseError when
process_job_result/3 tried to pattern match on job_type: :PING.

Added handler that:
- Catches PING results in SnmpResult format
- Logs warning that agent should be upgraded
- Creates monitoring check with success status
- Stores result via store_monitoring_check

This prevents crashes while maintaining backward compatibility until
all production agents are upgraded to use MonitoringCheck format.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 13:18:40 -06:00
fbce65070a
Add agent restart and self-update commands
Add server-initiated restart and self-update capabilities for remote
agents. Restart broadcasts on the lifecycle PubSub topic causing the
agent to exit cleanly for Docker to restart. Self-update fetches the
latest release from GitHub, finds the matching binary for the agent's
architecture, and sends the download URL with SHA256 checksum.

- Add restart_agent/1 and update_agent/3 to Agents context
- Handle :restart_requested and :update_requested in AgentChannel
- Add superuser-only Restart and Update buttons on agent show page
- Add ReleaseChecker module for GitHub Releases API with 5-min cache
- Add arch field to AgentHeartbeat protobuf for architecture detection
- Store arch in agent metadata from heartbeat
2026-02-10 13:06:10 -06:00
6724a0a4bc
clean up agent view again 2026-02-10 09:51:28 -06:00
07a9366892
clean up agent view 2026-02-10 09:48:09 -06:00
95eafd0c47
routeros fixes and latency rounding 2026-02-09 17:30:06 -06:00
4cfab3b1ee
Reliability improvements: agent channel, polling, discovery, batch ops
- Add Task.Supervisor for supervised background tasks in agent channel
- Discovery worker retries transient failures (max 3 attempts)
- Log silent polling timeouts with named task identification
- Track errors in batch ARP/MAC upserts instead of silently ignoring
- Discovery gracefully degrades on interface/sensor timeout (partial results)
- Synchronous job dispatch on agent join to prevent race condition
- Surface SNMP result, monitoring check, and backup processing errors
- Atomic delete-stale + upsert for neighbors/ARP/MAC (transaction)
- Discovery transaction timeout (60s) with duration logging
- Heartbeat timeout detection (5min) closes stale agent channels
- Live poll timeout (60s) notifies waiting LiveView on expiry
- Disconnect agent channel when token is disabled or deleted
- Debounce rapid assignment changes to prevent redundant job dispatches
- Sensor index deduplication via YAML index template substitution
2026-02-09 16:28:12 -06:00
3b8e1ea639
Reliability improvements: Task.Supervisor, discovery retries, polling visibility
- Add Towerops.TaskSupervisor to supervision tree, replace bare spawn/1
  in agent channel with supervised tasks for polling data processing
- Change DiscoveryWorker from max_attempts: 1 to 3 with retryable error
  classification (transient errors retry, permanent errors discard)
- Name all 9 parallel polling tasks and log timeouts/crashes instead of
  silently dropping results via Stream.run()
- Add tests for TaskSupervisor presence and error classification
2026-02-09 16:05:30 -06:00
f7b5e63429
live update agent status 2026-02-09 12:58:54 -06:00
623fe07081
wip 2026-02-09 12:44:37 -06:00