# AnimalTrack Event-sourced animal tracking for poultry farm management. Built with FastHTML, MonsterUI, and SQLite. ## Features - **Egg Collection** - Quick capture of daily egg counts by location - **Feed Tracking** - Record purchases and distribution with cost tracking - **Animal Registry** - Track cohorts, movements, and lifecycle events - **Historical Queries** - Point-in-time resolution using interval projections - **Event Sourcing** - Full audit trail with edit/delete support ## Development Setup ### Prerequisites - [Nix](https://nixos.org/download.html) with flakes enabled - [direnv](https://direnv.net/) (optional but recommended) ### Quick Start ```bash # Clone the repo git clone cd animaltrack # Enter dev environment direnv allow # or: nix develop # Run the server animaltrack serve ``` The server starts at http://localhost:3366 (3366 = EGG in leetspeak). ### CLI Commands ```bash # Run database migrations animaltrack migrate # Load seed data (users, locations, species, products, feed types) animaltrack seed # Start the web server animaltrack serve [--port 3366] [--host 0.0.0.0] # Create a new migration animaltrack create-migration "add users table" ``` ### Running Tests ```bash pytest tests/ -v ``` ## Deployment ### Docker Build the Docker image using Nix: ```bash nix build .#dockerImage docker load < result ``` Run the container: ```bash docker run -d \ -p 8080:3366 \ -v /data/animaltrack:/var/lib/animaltrack \ -e CSRF_SECRET="your-secret-here" \ -e TRUSTED_PROXY_IPS="10.0.0.1,10.0.0.2" \ gitea.v.paler.net/ppetru/animaltrack:latest ``` ### Environment Variables | Variable | Required | Default | Description | |----------|----------|---------|-------------| | `CSRF_SECRET` | **Yes** | - | Secret for CSRF token generation | | `DB_PATH` | No | `animaltrack.db` | SQLite database path | | `PORT` | No | `3366` | Server port | | `AUTH_HEADER_NAME` | No | `X-Oidc-Username` | Header containing username from reverse proxy | | `TRUSTED_PROXY_IPS` | No | (empty) | Comma-separated IPs that can set auth headers | | `CSRF_COOKIE_NAME` | No | `csrf_token` | CSRF cookie name | | `SEED_ON_START` | No | `false` | Run seeds on startup | | `LOG_LEVEL` | No | `INFO` | Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) | | `METRICS_ENABLED` | No | `true` | Enable Prometheus metrics at /metrics | | `DEV_MODE` | No | `false` | Bypasses auth, sets default user for development | | `BASE_PATH` | No | `/` | URL base path for reverse proxy setups | ### Reverse Proxy Configuration AnimalTrack expects authentication to be handled by a reverse proxy (e.g., Authelia, Authentik, oauth2-proxy). The proxy should: 1. Authenticate users via OIDC/OAuth2 2. Forward the username in `X-Oidc-Username` header (configurable via `AUTH_HEADER_NAME`) 3. Be listed in `TRUSTED_PROXY_IPS` to be trusted Example Caddy configuration: ``` animaltrack.example.com { forward_auth authelia:9091 { uri /api/verify?rd=https://auth.example.com copy_headers Remote-User Remote-Groups Remote-Email header_up X-Oidc-Username {http.auth.resp.Remote-User} } reverse_proxy animaltrack:3366 } ``` ### Data Persistence Mount a volume to `/var/lib/animaltrack` for the SQLite database: ```bash -v /path/on/host:/var/lib/animaltrack ``` The database file will be created at `$DB_PATH` (default: `/var/lib/animaltrack/animaltrack.db` in Docker). ### Health Check - `GET /healthz` - Returns 200 if database is writable, 503 otherwise - `GET /metrics` - Prometheus metrics (when `METRICS_ENABLED=true`) ## Architecture - **Event Sourcing** - All state changes are events. Events are immutable. - **Projections** - Materialized views updated synchronously in transactions. - **Interval Tables** - Track animal locations, tags, and attributes over time. - **ULID IDs** - Time-ordered, sortable, unique identifiers. - **Integer Timestamps** - Milliseconds since Unix epoch for all timestamps. - **Integer Money** - All prices stored as cents for precision. ## License Proprietary - All rights reserved.