Commit graph

42 commits

Author SHA1 Message Date
31cbd18128 ci: cache slow runtime apt deps in a prebuilt base image
Splits the runtime apt installs (gdal-bin, snmp, libsnmp40, locales,
BEAM runtime libs) into k8s/Dockerfile.base, hosted at
codeberg.org/gmcintire/towerops-base:latest. The app Dockerfile now
does FROM that base instead of re-installing gdal (~500 MB) on every
push.

The new build-base workflow rebuilds the base image only when
k8s/Dockerfile.base or the workflow itself changes, weekly via cron
(Sundays 06:00 UTC, with CACHE_BUST=<ISO week> to force apt-get update
on a week boundary), or via workflow_dispatch.

Production workflow now uses buildx + does docker login before the
build so it can pull the private base image.
2026-05-05 11:19:49 -05:00
158ee9d323 feat: add Texas LIDAR DEM catalog with on-demand elevation reads
Catalog-only system for LIDAR-derived 1m DEMs covering Texas. We do not
mirror raster data — the DB stores tile metadata (URL + footprint
geometry) and elevation values are streamed on-demand from public USGS
3DEP / TNRIS Cloud-Optimized GeoTIFFs via GDAL /vsicurl/ HTTP byte-range
reads. Used for future tower coverage line-of-sight calculations.

- Enable PostGIS extension; tile footprints indexed via GiST
- Catalog sync from USGS 3DEP (primary) and TNRIS (fallback for gaps)
- Tile dedup by ST_Contains so TNRIS doesn't duplicate 3DEP coverage
- Single-point reads via gdallocationinfo with tile fallthrough on nodata
- Grid retrieval via gdal_translate AAIGrid with multi-tile mosaicing
- Monthly Oban cron worker keeps catalog fresh
- gdal-bin added to runtime image; geo_postgis dep added
2026-05-04 13:03:28 -05:00
247bbe58da refactor: address audit recommendations from results.md
Applies the 11 recommendations from the codebase optimization review.

Module decomposition:
- Extract Towerops.Topology.InferenceEngine: pulls device-role inference
  (capability rules, vendor matching, evidence merging) out of the topology
  context. Topology now delegates merge_confidence/2,
  infer_role_from_capabilities/1, and infer_device_role/1.
- Extract Towerops.Accounts.TOTP: TOTP secret/QR generation, multi-device
  verification, recovery code lifecycle, and sudo MFA logic. Accounts
  delegates the public TOTP API for backwards compatibility.
- Extract Towerops.Accounts.Sessions: browser session create/list/touch/
  revoke/anonymize/expire. Accounts delegates the public session API.
- Extract Towerops.Snmp.Queries: time-series read paths
  (sensor readings, interface stats, latest-per-id batches).
- Extract Towerops.Snmp.Monitoring: time-series write paths
  (sensor/interface/processor reading inserts, batch inserts via
  Repo.insert_all). Snmp.ex shrinks from 2985 to 2742 lines.

DRY refactoring:
- Add per-schema Query modules (Devices.DeviceQuery, Alerts.AlertQuery)
  with composable for_organization/for_site/with_status/etc filters;
  refactor list_site_devices, count_organization_devices,
  count_site_devices, count_site_devices_down, count_organization_alerts
  to compose them.
- Introduce create_discovered_checks/6 helper in Snmp; collapses 4 nearly
  identical Enum.reduce blocks for sensors/interfaces/processors/storage.
- Unify MAC and ARP evidence collectors behind collect_lookup_evidence/3
  (lldp/cdp were already factored).

Pattern matching:
- Replace cond block in infer_role_from_capabilities/1 with a declarative
  @role_rules table consulted via Enum.find_value (Elixir 1.19 forbids `in`
  with runtime lists in guards, so multi-clause functions weren't an option).
- Replace inline `if since` in get_sensor_readings/2 with a maybe_filter_since
  pipe helper.

Performance:
- Replace Enum.each + Repo.insert per evidence row in upsert_link with a
  single Repo.insert_all batch (truncates :observed_at to seconds).

Human-centric:
- Decompose build_device_lookup/1 into fetch_lookup_devices, map_ips_to_ids,
  map_names_to_ids, map_macs_to_ids.
- Adopt Towerops.Result.map/2 in Snmp.Client.do_get_multiple_sequential
  (kept narrow; `with` is preferred over Result.and_then for chained
  operations and is already used widely).

CLAUDE.md updates:
- Replace stale main→staging / production-branch deployment notes with the
  current flow: PRs deploy to Dokku staging, push to main runs the
  ExUnit gate then builds an image; argocd-image-updater rolls production.
- Refresh data-model diagram and references from "Equipment" to "Device"
  (post equipment→devices rename migration).
- Correct stale architecture facts: Hammer → in-tree Towerops.RateLimit,
  Rust NIF → C NIF (libnetsnmp), gitlab-registry → forgejo-registry,
  expand the Oban queue and cron lists, list actual implemented Ecto types.

All 10,228 tests pass.
2026-04-30 12:33:41 -05:00
aa46ff2bd3
docs: replace flux/fluxcd references with argocd 2026-04-29 11:15:53 -05:00
f68b828c8f
ci: add test gates for production deployments
Adds Forgejo Actions CI/CD workflows:

Production deployment (.forgejo/workflows/production.yml):
- Runs on push to 'production' branch
- Test gates (must pass before deploy):
  * All ExUnit tests with coverage
  * All e2e Playwright tests
- Only deploys if both test suites pass
- Builds Docker image
- Pushes to git.mcintire.me registry
- Updates k8s/deployment.yaml with new image tag
- FluxCD auto-applies changes

Main branch testing (.forgejo/workflows/test.yml):
- Runs on push to 'main' or pull requests
- Runs ExUnit tests with coverage
- Runs e2e tests
- No deployment (staging still via Dokku)

Updated CLAUDE.md with CI/CD pipeline documentation.
2026-03-06 17:40:50 -06:00
7f7e289325
docs: add critical git workflow rule - never push to production without explicit instruction 2026-03-06 17:09:52 -06:00
03ec4ee59a
docs: add e2e testing requirement to CLAUDE.md 2026-03-06 16:59:26 -06:00
c0546814aa
docs: add deployment instructions for staging and production 2026-03-06 13:21:21 -06:00
076b8454de
docs: merge upstream Phoenix AGENTS.md with project-specific patterns
- Add module design/complexity guidelines, quality checks (credo, sobelow,
  coverage), security guidelines (deps.audit), updated auth section with
  live_session details, OTP guidelines, and expanded Elixir core rules
  from cheezy/kanban upstream AGENTS.md
- Move project-specific patterns into AGENTS.md: browser navigation URL
  state, JS hook memory leak prevention, LiveView form data access,
  SNMP test mocking patterns
- Trim CLAUDE.md to project architecture docs only, removing sections
  now covered in AGENTS.md
2026-02-18 09:08:33 -06:00
f44510bf47
docs: update user-facing changelog and document changelog maintenance
Updated priv/static/changelog.txt with all recent changes from CHANGELOG.txt
in concise, user-facing format. Enhanced CLAUDE.md to document the dual
changelog system (technical CHANGELOG.txt vs user-facing priv/static/changelog.txt)
with clear guidelines on what to include in each and when to update them.
2026-02-12 10:38:27 -06:00
1602322518
docs: condense CLAUDE.md from 43KB to 16KB to improve AI context loading
Reduced file size by 62% while preserving all critical information:
- Simplified data model diagram to hierarchical text format
- Removed verbose code examples, keeping essential patterns
- Condensed sections while retaining actionable information
- Streamlined Custom Ecto Types, Browser Navigation, and Memory Leak sections

The condensed version maintains all necessary guidance for AI assistants
working on the project without overwhelming the context window.
2026-02-12 09:35:41 -06:00
97b396a763
docs: add browser navigation best practices and design document
Add comprehensive documentation for idiomatic Phoenix LiveView URL state
management to ensure browser back/forward buttons work correctly.

Changes:
- Add design document: docs/plans/2026-02-12-browser-navigation-fix-design.md
  - Documents the problem (18 LiveViews missing handle_params/3)
  - Provides idiomatic Phoenix patterns using push_patch/2
  - Includes migration strategy for updating all LiveViews
  - Contains testing protocols and success criteria

- Update CLAUDE.md: Add "Browser Navigation and URL State Management" section
  - Documents the three core patterns: tabs, modals, filters
  - Establishes critical rules for all future LiveView development
  - Provides working code examples for each pattern
  - Links to official Phoenix documentation

Key Principles:
- URL is single source of truth for visible state
- Use push_patch/2 in event handlers, never assign for URL-backed state
- Always implement handle_params/3 to validate and process URL params
- Use Phoenix built-ins (no custom helpers needed)

This ensures future LiveView development follows the correct pattern
and browser navigation works as users expect.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-12 09:20:14 -06:00
cb3f2edf50
polling fix 2026-02-11 13:54:23 -06:00
c93144cc37
snmp v3 support 2026-02-04 12:02:38 -06:00
5b84844e97
doc update 2026-02-03 09:07:06 -06:00
5d5116681a
device edit refactor 2026-02-02 10:00:00 -06:00
f938b263cd
Mikrotik backup and gettext start 2026-02-02 09:11:22 -06:00
23af86ba73
add mikrotik device handling 2026-02-01 16:42:39 -06:00
02833d0b44 Add rate limiting to auth and API endpoints using Hammer 2026-02-01 14:59:54 -06:00
04c33b0719
paginate audit logs 2026-02-01 13:27:56 -06:00
480789c3e2 banner dissmiss and mikrotik version and license 2026-01-31 13:07:09 -06:00
c4ce7a94ca memory leak fixing 2026-01-31 10:40:19 -06:00
efc6e7a3ab paginate discovered devices 2026-01-31 10:31:37 -06:00
22ae257b60 refactor 2026-01-31 09:35:07 -06:00
dc29673c29 compress CLAUDE.md 2026-01-30 17:13:34 -06:00
cd06f437bb fix my-data page 2026-01-30 16:47:11 -06:00
eebeb31456 refactor: move admin dashboards to /admin namespace
- Move Oban Web from /oban to /admin/oban
- Move LiveDashboard from /dashboard to /admin/dashboard
- Both remain protected by :require_superuser plug
- Update documentation to reflect new paths
2026-01-30 13:37:39 -06:00
836749ba6b complete overhaul of snmp engine 2026-01-30 10:41:07 -06:00
b341f89332 prod ip db import 2026-01-28 13:28:11 -06:00
7ecc986bcd support prod ip db import 2026-01-28 13:20:53 -06:00
f240d429c9 support prod ip db import 2026-01-28 13:09:29 -06:00
6920333d6a
impersonate fix 2026-01-27 10:45:06 -06:00
bb86dec559
add oban pro 2026-01-26 17:07:42 -06:00
d2abe9a14d
add network map 2026-01-25 15:24:35 -06:00
ee8a3220c4
refactor: convert periodic workers to Oban Cron for better resilience
Replaced GenServer-based periodic workers with Oban Cron jobs to improve
pod rollover resilience and simplify architecture.

Worker Changes:
- NeighborCleanupWorker: GenServer → Oban Cron (hourly)
  - Cleans stale neighbors, ARP entries, and MAC addresses
  - Runs every hour via Oban.Plugins.Cron

- StaleAgentWorker: GenServer → Oban Cron (every minute)
  - Detects agents that haven't checked in for 10+ minutes
  - Refactored to reduce nesting (extracted helper functions)
  - Removed stateful tracking (now stateless, re-evaluates each run)

- AgentLatencyEvaluator: GenServer → Oban Cron (every 5 minutes)
  - Latency-based agent reassignment with 20% threshold
  - Removed trigger_evaluation/0 (no longer needed)

- JobHealthCheckWorker: NEW Oban Cron worker (every 10 minutes)
  - Safety net to recover missing monitor/poller jobs
  - Auto-creates jobs for devices with monitoring/SNMP enabled

Infrastructure Changes:
- Removed Monitoring.Supervisor (no longer needed)
- Updated application.ex to remove GenServer workers from supervision tree
- Added Oban.Plugins.Cron to dev.exs and runtime.exs
- All workers now run cluster-wide via PostgreSQL-backed coordination

Test Updates:
- Updated all worker tests to call perform(%Oban.Job{args: %{}})
- Removed GenServer lifecycle tests (start_link, send messages, etc.)
- Removed async sleep calls (no longer needed)

Benefits:
- Better pod rollover resilience (Cron jobs run cluster-wide)
- Simpler architecture (no GenServers for periodic tasks)
- Better observability (all jobs visible in Oban dashboard)
- Safety net for missing jobs (JobHealthCheckWorker)
- Stateless workers (easier to reason about and test)

Documentation:
- Updated CLAUDE.md with Background Job Architecture section
- Documented job types, queues, and resilience features

All tests passing (3,686 tests, 0 failures).
2026-01-24 16:56:28 -06:00
5109f7b6a1
docs: update CLAUDE.md to reflect Oban worker architecture
Changes:
- Replace Exq references with Oban in LiveDashboard metrics section
- Add new 'Background Job Architecture' section documenting Oban workers
- Document DevicePollerWorker, DeviceMonitorWorker, DiscoveryWorker
- Update SNMP Polling Architecture to reference new workers
- Document automatic job lifecycle management
- Clarify direct Oban worker pattern (no GenServer/coordinator layer)

This ensures documentation matches the refactored architecture.
2026-01-24 16:42:17 -06:00
b1fedcda45
updates 2026-01-17 17:49:53 -06:00
cca873abc8
Document LiveDashboard metrics in CLAUDE.md
Added section explaining available telemetry metrics including:
- Phoenix, Database, and VM metrics
- Exq background job metrics
- Redis/Valkey metrics

Includes instructions on accessing LiveDashboard
2026-01-17 17:27:00 -06:00
dcd4588304
fix neighbors 2026-01-16 16:09:15 -06:00
9a6369bd27
Fix agent API protobuf support and Mix.env runtime error
Fixed two critical issues preventing agent communication:

1. Fix Mix.env() runtime error in production
   - Replace Mix.env() with Application.get_env(:towerops, :env)
   - Add :env config to test.exs
   - Mix module not available in production releases

2. Add Protocol Buffers support to agent API endpoints
   - GET /api/v1/agent/config now accepts application/x-protobuf
   - POST /api/v1/agent/heartbeat now accepts application/x-protobuf
   - Added conversion functions for config/equipment/sensors/interfaces
   - Maintains JSON backward compatibility as fallback

All agent controller tests passing (14 tests, 0 failures)
2026-01-14 16:35:47 -06:00
eb7dbb2d0e
Add comprehensive Kubernetes deployment documentation
Document complete setup process for deploying Towerops to a Talos
Kubernetes cluster, including:
- All required infrastructure prerequisites
- GitLab agent for CI/CD
- Newt for Pangolin forwarding
- Secrets management with 1Password
- FluxCD GitOps configuration
- Deployment process and troubleshooting
2026-01-14 13:14:10 -06:00
daa8aa3966
add claude.md to git 2026-01-13 13:21:33 -06:00