# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## CRITICAL: Read AGENTS.md First **Before starting any work in this repository**, you MUST read `AGENTS.md` in the project root. - `AGENTS.md` contains comprehensive Phoenix/LiveView/Elixir guidelines that are mandatory for this project - These guidelines take precedence over general development practices when there's a conflict - Always read `AGENTS.md` at the start of a new conversation or when resuming work - Follow the project-specific patterns, conventions, and constraints documented there ## Project Overview Towerops is a Phoenix 1.8 web application built with Elixir, using Ecto for database operations (PostgreSQL), LiveView for real-time interactions, and Tailwind CSS v4 for styling. ### Data Model Relationships ``` ┌─────────────┐ │ User │ │ (Accounts) │ └──────┬──────┘ │ owns/member of (many-to-many) │ ↓ ┌──────────────────────────────────────────────────────┐ │ Organization │ │ (Organizations) │ └────┬────────────┬─────────────┬──────────────────────┘ │ │ │ │ has many │ has many │ has many │ │ │ ↓ ↓ ↓ ┌─────────┐ ┌──────────┐ ┌────────────────┐ │ Site │ │Equipment │ │ AgentToken │ │ (Sites) │ │(Equipment│ │ (Agents) │ └────┬────┘ └────┬─────┘ └────────┬───────┘ │ │ │ │ has many │ has one │ assigned via │ │ │ ↓ ↓ ↓ ┌──────────┐ ┌──────────────┐ ┌──────────────────┐ │Equipment │ │ SNMPDevice │ │ AgentAssignment │◀──┐ │(Equipment│ │(Snmp.Devices)│ │ (Agents) │ │ └────┬─────┘ └──────────────┘ └──────────────────┘ │ │ │ │ │ has many └───────────────┘ ├────────────────┬─────────────────┘ │ │ assigns equipment ↓ ↓ to agent ┌──────────────┐ ┌─────────┐ │MonitoringCheck│ │ Alert │ │ (Monitoring) │ │ (Alerts)│ └──────────────┘ └─────────┘ Key Relationships: - User can own/belong to multiple Organizations - Organization has default_agent_token_id (optional) - Equipment belongs to both Site and Organization (denormalized) - Equipment can be assigned to one AgentToken via AgentAssignment - Equipment has one SNMPDevice with Sensors and Interfaces - Equipment has many MonitoringChecks (polling results) - Equipment has many Alerts (equipment_down, equipment_up) - AgentToken authenticates remote agents for local SNMP polling ``` **Note to AI assistants**: When you make changes to the data model (migrations, schema additions, new contexts), update this diagram to reflect the current state. ## Essential Commands ### Setup and Development - `mix setup` - Install dependencies, create/migrate database, setup and build assets - `mix phx.server` - Start the Phoenix server (accessible at http://localhost:4000) - `iex -S mix phx.server` - Start server with interactive Elixir shell ### Testing and Quality - `mix test` - Run all tests (automatically creates and migrates test database) - `mix test test/path/to/specific_test.exs` - Run a specific test file - `mix test --failed` - Re-run only previously failed tests - `mix test --cover` - Run tests with coverage report (generates HTML report in `cover/` directory) - `mix precommit` - **Run before committing**: compiles with warnings as errors, unlocks unused deps, formats code, and runs tests **Coverage Target**: 90% minimum (currently configured threshold) - Coverage reports show line-by-line coverage in `cover/` directory - View detailed HTML report: `open cover/modules_*.html` - Current status: 60.40% overall (as of Jan 12, 2026, 6:35 PM) - Recent improvements (Session 1): - Towerops.Snmp: 10.87% → 97.83% (+87%) - Towerops.Snmp.Profiles.NetSnmp: 56.79% → 92.59% (+35.8%) - Towerops.Monitoring.Supervisor: 21.21% → 63.64% (+42%) - Towerops.Snmp.Profiles.Cisco: 20.22% → 57.30% (+37%) - ToweropsWeb.EquipmentLive.Show: 35.51% → 46.38% (+10.87%) **Coverage Notes**: - Protobuf-generated modules (Towerops.Agent.*) show 0% but don't need tests - Focus areas for improvement (in priority order): - Towerops.Monitoring context (33.33%) - SNMP profiles: NetSnmp (56.79%), Base (69.52%), Mikrotik (77.97%) - LiveView modules: EquipmentLive.Show (35.51%), EquipmentLive.Form (46.73%) - Accounts modules: UserCredentialController (33.93%), Accounts context (61.82%) - 0% coverage modules (Admin, WebAuthn, etc.) - may be intentionally untested ### Database - `mix ecto.create` - Create the database - `mix ecto.migrate` - Run pending migrations - `mix ecto.reset` - Drop, create, and migrate database - `mix ecto.gen.migration migration_name_using_underscores` - Generate a new migration file ### Assets - `mix assets.build` - Build CSS and JS assets (Tailwind + esbuild) - `mix assets.deploy` - Build minified assets for production ## Architecture ### Application Structure The application follows standard Phoenix conventions with clear separation between business logic (`lib/towerops/`) and web interface (`lib/towerops_web/`): - **Towerops.Application** - OTP application that supervises: - Telemetry for metrics - Repo (Ecto) for database - DNSCluster for service discovery - PubSub for pub/sub messaging - Endpoint (web server) - **ToweropsWeb** - Main web module that provides `use` macros for: - `:router` - Route definitions - `:controller` - Traditional request/response controllers - `:live_view` - LiveView modules - `:live_component` - LiveView component modules - `:html` - Phoenix.Component modules ### Key Configuration Details - **Binary IDs**: Generators use binary (UUID) primary keys by default (`binary_id: true`) - **Timestamps**: Use `:utc_datetime` for all timestamps - **Web server**: Uses Bandit adapter (not Cowboy) - **HTTP client**: Uses `:req` library (Req module) - this is the only approved HTTP client - **Ecto repos**: `[Towerops.Repo]` ### Web Layer Patterns All LiveViews, LiveComponents, and HTML modules automatically get these imports/aliases via `html_helpers/0`: - `ToweropsWeb.CoreComponents` - Core UI components (`<.button>`, `<.input>`, `<.form>`, etc.) - `ToweropsWeb.Layouts` - Layout components (aliased, no need to re-alias) - `Phoenix.LiveView.JS` - Client-side JS commands - Gettext for translations - Verified routes with `~p` sigil ### Asset Pipeline - **Tailwind CSS v4**: Uses new `@import "tailwindcss"` syntax in `assets/css/app.css`, no `tailwind.config.js` needed - **esbuild**: Bundles JavaScript from `assets/js/app.js` - All vendor scripts/styles must be imported into app.js/app.css - cannot reference external src/href in layouts - No inline `