# 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 → Organization (Organizations) ├─ Site (Sites) → Equipment ├─ Equipment → SNMPDevice, MonitoringCheck, Alert └─ AgentToken → AgentAssignment → Equipment 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) and Alerts - AgentToken authenticates remote agents for local SNMP polling ``` **Note**: Update this diagram when making data model changes. ## Essential Commands ### Setup and Development - `mix setup` - Install dependencies, create/migrate database, build assets - `mix phx.server` - Start Phoenix server (http://localhost:4000) - `iex -S mix phx.server` - Start server with IEx shell ### Testing and Quality - `mix test` - Run all tests - `mix test --failed` - Re-run failed tests - `mix test --cover` - Run with coverage (target: 90% minimum) - `mix precommit` - **Run before committing**: compiles with warnings as errors, formats, runs tests - `mix dialyzer` - Static type analysis ### Database - `mix ecto.create/migrate/reset` - Database operations - `mix ecto.gen.migration name_using_underscores` - Generate migration ### Assets - `mix assets.build/deploy` - Build CSS/JS assets (auto-rebuilds on save in dev) ## Architecture ### Application Structure Standard Phoenix conventions: business logic in `lib/towerops/`, web interface in `lib/towerops_web/`. **Key Configuration**: - **Binary IDs**: UUID primary keys by default (`binary_id: true`) - **Timestamps**: `:utc_datetime` for all timestamps - **Web server**: Bandit adapter - **HTTP client**: `:req` library (Req module) - ONLY approved client - **Ecto repos**: `[Towerops.Repo]` ### Web Layer All LiveViews get these imports via `html_helpers/0`: - `ToweropsWeb.CoreComponents` - Core UI (`<.button>`, `<.input>`, `<.form>`) - `ToweropsWeb.Layouts`, `Phoenix.LiveView.JS`, Gettext, verified routes (`~p`) ### Rate Limiting Uses Hammer (ETS-backed): - **Auth endpoints**: 10 req/min per IP (`/users/log-in`, `/users/register`, TOTP) - **API v1**: 1000 req/min per IP (`/api/v1/*`) - **Admin API**: Not rate limited (superuser only) - Returns `429 Too Many Requests` with `Retry-After` header - Disabled in test: `config :towerops, :rate_limiting_enabled, false` ### Asset Pipeline - **Tailwind CSS v4**: Uses `@import "tailwindcss"` in `assets/css/app.css` (no config file) - **esbuild**: Bundles `assets/js/app.js` - Import all vendor assets into app.js/app.css - no external src/href in layouts - No inline `