Commit graph

314 commits

Author SHA1 Message Date
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
e68ebdb62d
fix: sync AgentLive.Index modal state to URL for browser navigation
Update AgentLive.Index to properly handle browser back/forward buttons
by syncing the setup token modal to URL parameters.

Changes:
- Update handle_params/3 to read modal param and set modal state
- Update show_setup handler to use push_patch with ?modal=setup
- Update close_token_modal handler to use push_patch (remove modal param)
- Update handle_agent_creation_success to use push_patch after creating agent

Behavior:
- Browser back button now closes the setup modal without navigating away
- URL reflects current modal state (?modal=setup)
- Bookmarkable URLs restore exact modal state (can share agent setup URL)
- After creating agent, modal opens via URL state

Follows idiomatic Phoenix LiveView pattern using push_patch/2 and
handle_params/3 as documented in CLAUDE.md.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-12 09:28:39 -06:00
d84a685878
fix: sync UserSettingsLive modal state to URL for browser navigation
Update UserSettingsLive to properly handle browser back/forward buttons
by syncing all modal state to URL parameters.

Changes:
- Update handle_params/3 to read modal param and set modal states
- Add build_settings_path/2 helper to construct URLs with preserved params
- Update all modal show/close handlers to use push_patch instead of assign:
  - add_token modal
  - token_created modal (shown after creating token)
  - revoke_all modal
  - add_device modal (TOTP)
  - device_qr modal (shown after creating device)
  - recovery_codes modal

Behavior:
- Browser back button now closes modals without navigating away
- URL reflects current modal state (?modal=add_token, etc.)
- Tab and page params preserved when opening/closing modals
- Bookmarkable URLs restore exact modal state

Follows idiomatic Phoenix LiveView pattern using push_patch/2 and
handle_params/3 as documented in CLAUDE.md.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-12 09:26:45 -06:00
26bb3d5ca1
color network map nodes by device status
green for online, yellow for unknown, red for offline. previously
nodes were colored by device type which didn't convey health state.
also remove agent last_seen_at display from device detail page since
the offline badge already communicates agent health.
2026-02-11 15:41:50 -06:00
475dea639a
remove agent last_seen_at display from device detail page
the offline badge already communicates agent health status,
so the relative timestamp is redundant.
2026-02-11 15:35:59 -06:00
45357e334a
fix live polling to use effective agent from site/org cascade
live poll mode used get_device_assignment which only checks direct
device-level assignments. devices with agent assigned at site or
org level fell through to direct Phoenix SNMP. replaced with
get_effective_agent_token which walks the full cascade.
2026-02-11 14:12:42 -06:00
10d1157ec3
fix agent discovery system OIDs returning no_such_name
gosnmp returns OIDs with leading dots (e.g., ".1.3.6.1.2.1.1.1.0")
but the Replay adapter did exact-match lookups without the dot.
Walks already normalized both sides, so interfaces worked. GETs
did not, breaking all system OID resolution (sysDescr, sysName, etc).
2026-02-11 12:46:44 -06:00
d36fcbe628
fix raw discovery data timestamp to use user's timezone 2026-02-11 12:41:31 -06:00
c9f154f8cd
fix 5 failing tests
- increase timing threshold in session activity test (flaky at 50ms)
- show org name instead of agent ID in admin agents list
- fix agent live tests wiping auth session with init_test_session
- add resilient error handling in FourOhFourTracker for missing redis
2026-02-11 12:21:06 -06:00
92eb583a8b
fix siteless devices not inheriting org default agent
devices assigned directly to an org (no site) were excluded from
apply_agent_to_all_equipment due to inner join through site table.
also fix fallback agent resolution to check device.organization
when device.site is nil.
2026-02-11 12:20:53 -06:00
e4623f0c3d
show agent ID instead of org name in admin agents list
Makes it easier to identify and reference specific agents in the admin view
2026-02-11 11:56:09 -06:00
f53332672b
add IP allowlist link to superadmin nav, rename whitelist/blacklist to allowlist/denylist 2026-02-11 11:40:44 -06:00
c5d8d73a0c
add row_link to table component for proper anchor tags
Replace phx-click JS.navigate with real <.link navigate> elements
on table rows so users can Ctrl+Click to open in new tabs, use
right-click context menus, and navigate via keyboard. Adds row_link
attr to <.table> core component and applies it to all agent tables.
Converts device list custom table from phx-click to inner links.
2026-02-11 08:46:03 -06:00
77cf289058
Add real-time device list with PubSub and LiveView streams
Broadcast org-scoped PubSub events from Devices context mutations
(create, update, delete, status change). Convert DeviceLive.Index
from assigns to streams with flat row items. Subscribe on mount so
the device list updates automatically across browser tabs.
2026-02-10 17:38:58 -06:00
4d73e77f3a
Add 404-based brute force protection system
Implements automated detection and blocking of IPs exhibiting scanning behavior (5+ unique 404s within 1 minute).

Key features:
- Progressive ban escalation (5 min → 1 hour → permanent)
- CIDR range and exact IP whitelisting
- Redis-backed 404 path tracking with 60s TTL
- Cloudflare WAF integration for permanent bans
- Admin UI for whitelist and blocked IP management
- Oban cron jobs for cleanup (expired bans, stale violations)
- ETS caching for whitelist performance

Components:
- Plug: ToweropsWeb.Plugs.BruteForceProtection
- Context: Towerops.Security.BruteForce
- Schemas: IpBlock, IpWhitelist
- Workers: CloudflareBanWorker, ExpiredBanCleanupWorker, StaleViolationCleanupWorker
- Admin UI: /admin/security (superuser only)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 16:31:48 -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
c066399e18
Allow superadmins to view and edit any agent regardless of org
The admin agents page links to /agents/:id but the show and edit
pages were scoped to the current user's organization, causing 404s
for agents belonging to other orgs.
2026-02-10 12:19:20 -06:00
c1fca6276a
Add real-time updates to admin agents page via PubSub
Broadcast agent lifecycle events (created/deleted) on a separate
"admin:agents" topic so the admin page updates dynamically when
agents are added or removed from any organization.
2026-02-10 11:20:51 -06:00
c6caa81850
Group cloud pollers and org agents separately on admin agents page
Cloud pollers render in their own table at the top, org agents
below with the organization name shown under each agent name.
2026-02-10 11:07:41 -06:00
6a66203e48
Add link to admin agents page from admin dashboard 2026-02-10 11:04:55 -06:00
183f2a89ac
Add admin agents page at /admin/agents
Superuser-only page showing all agents across all organizations
and cloud pollers in a single table with live-ticking timestamps
and real-time status updates via PubSub.
2026-02-10 10:56:10 -06:00
5c59777baa
Live-ticking relative timestamps on agents page 2026-02-10 10:24:21 -06:00
481fc6d4a2
Add absolute format to timestamp component to fix render flash 2026-02-10 10:19:54 -06:00
d1cd567cd5
Show full timestamp below relative time in Last Seen column 2026-02-10 10:07:44 -06:00
e9afac3e9d
Show full timestamp below relative time on Last Seen card 2026-02-10 09:55:34 -06:00
07a9366892
clean up agent view 2026-02-10 09:48:09 -06:00
ba56dee1ca
remove date helper 2026-02-10 09:15:41 -06:00
fce1a8b229
Show full version timestamp with friendly date on agents page 2026-02-10 09:04:56 -06:00
94405f0716
fix agents updates 2026-02-10 08:08:34 -06:00
144e04b998
change metadata version to version 2026-02-09 17:39:33 -06:00
41594e5a96
fix bugs on agents screen 2026-02-09 14:03:40 -06:00
ae9b393137
Fix agent page jumping by using streams for real-time updates
- Convert agent_tokens from assign to stream to prevent full page re-renders
- Update handle_info callbacks to only update the specific agent that changed
- Only update stats when agent status changes, not device counts
- Prevents IP address from temporarily disappearing during updates
2026-02-09 13:39:59 -06:00
94bcf8ac4e
fix bug on device add/edit page with mikrotik api fields showing 2026-02-09 13:01:47 -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
b12a03b82f
update 2026-02-09 08:47:53 -06:00
7a57f7c9d2
fix: resolve critical sensor discovery pipeline data loss
Critical fixes to sensor discovery and display pipeline:

- Fix float value rejection: Change is_integer guards to is_number in
  vendor.ex, dynamic.ex to accept decimal sensor values (temperature,
  counters, etc.)
- Fix scale factor calculation: Rewrite base.ex divisor calculation
  using pure integer arithmetic to prevent rounding errors
- Add missing sensor type support: Current, power, fan, load, and
  signal quality sensor categories now filtered and assigned in UI
- Refactor resolve_snmp_community to reduce cyclomatic complexity

Impact:
- Sensors with float values (DHCP leases, connection counts, precise
  temperatures) no longer silently dropped before database
- ENTITY-SENSOR-MIB divisors calculated correctly without float errors
- UI coverage increased from ~35% to ~60% of discovered sensor types

Files modified:
- lib/towerops/snmp/profiles/vendors/vendor.ex
- lib/towerops/snmp/profiles/dynamic.ex
- lib/towerops/snmp/profiles/base.ex
- lib/towerops_web/live/device_live/show.ex
- lib/towerops/devices.ex

Documentation: SENSOR_PIPELINE_FIXES.md
2026-02-09 08:32:24 -06:00
b823b5e848
feat: display cloud poller name on device page
Show the specific cloud poller name (e.g., dfw, lon) alongside "Cloud"
when a device is assigned to a cloud poller. Displays as "Cloud (dfw)"
instead of just "Cloud" for better visibility of which poller is being used.

When no agent is assigned, continues to show just "Cloud".
2026-02-08 11:40:58 -06:00
10b1168044
refactor: round latency graph values to 1 decimal place
Display latency values with single decimal precision (e.g., 114.1ms)
for improved readability in graphs. This ensures consistency between
the raw chart data and tooltip formatting.
2026-02-08 11:13:39 -06:00
d431931cfe
update hammer 2026-02-08 10:08:31 -06:00
8d4333b237
fix superadmin page 2026-02-07 11:58:56 -06:00
3931a9c14a
more tests and fixes 2026-02-07 11:50:18 -06:00
3eb3d4890e
Merge branch 'feature/job-monitoring-dashboard'
# Conflicts:
#	lib/towerops/workers/device_poller_worker.ex
#	lib/towerops/workers/discovery_worker.ex
2026-02-06 19:01:08 -06:00
070241d15a
feat: add queue depth display to health metrics
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-06 18:37:21 -06:00
1eaf6d9ac5
feat: build recent activity timeline with color-coded events
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-06 18:35:55 -06:00
8bceb6dce2
feat: build comprehensive health metrics panel with success rates
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-06 18:34:43 -06:00
1e45b1609b
feat: build detailed problems section UI for stuck and failed jobs
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-06 18:33:21 -06:00
daa223c49d
feat: enhance active operations display with device context
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-06 18:32:06 -06:00
2fb0101bab
feat: add job monitoring link to admin dashboard
Add Job Monitoring card to admin dashboard with:
- Hero icon for visual identification
- Brief description of monitoring capabilities
- Link to /admin/monitoring dashboard

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-06 18:28:41 -06:00