Some checks failed
Validate / Hassfest (push) Has been cancelled
Build a complete standalone web server for Immich album change notifications, independent of Home Assistant. Uses the shared core library from Phase 1. Server features: - FastAPI with async SQLite (SQLModel + aiosqlite) - Multi-user auth with JWT (admin/user roles, setup wizard) - CRUD APIs: Immich servers, album trackers, message templates, notification targets (Telegram + webhook), user management - APScheduler background polling per tracker - Jinja2 template rendering with live preview - Album browser proxied from Immich API - Event logging and dashboard status endpoint - Docker deployment (single container, SQLite in volume) 39 API routes, 14 integration tests passing. Also adds Phase 6 (Claude AI Telegram bot enhancement) to the primary plan as an optional future phase. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
124 lines
4.3 KiB
Markdown
124 lines
4.3 KiB
Markdown
# Phase 3: Build Standalone Server Backend
|
|
|
|
**Status**: In progress
|
|
**Parent**: [primary-plan.md](primary-plan.md)
|
|
|
|
---
|
|
|
|
## Goal
|
|
|
|
Build a standalone FastAPI web server that provides Immich album change notifications without Home Assistant, using the shared core library from Phase 1.
|
|
|
|
---
|
|
|
|
## Tech Stack
|
|
|
|
- **Framework**: FastAPI (async-native, OpenAPI docs)
|
|
- **Database**: SQLite via SQLModel (SQLAlchemy + Pydantic)
|
|
- **Auth**: bcrypt + JWT (multi-user, admin/user roles)
|
|
- **Scheduler**: APScheduler (async jobs per tracker)
|
|
- **Notifications**: Core TelegramClient + new WebhookClient
|
|
- **Templates**: Jinja2 (same syntax as HA blueprint)
|
|
- **Deployment**: Docker (single container, SQLite in volume)
|
|
|
|
---
|
|
|
|
## Directory Structure
|
|
|
|
```
|
|
packages/server/
|
|
pyproject.toml
|
|
src/immich_watcher_server/
|
|
__init__.py
|
|
main.py # FastAPI app, lifespan, static mount
|
|
config.py # Settings from env vars
|
|
database/
|
|
__init__.py
|
|
models.py # SQLModel table definitions
|
|
engine.py # Engine creation, session factory
|
|
auth/
|
|
__init__.py
|
|
jwt.py # JWT token creation/validation
|
|
dependencies.py # FastAPI dependency for current_user
|
|
routes.py # /api/auth/* endpoints
|
|
api/
|
|
__init__.py
|
|
servers.py # CRUD /api/servers/*
|
|
trackers.py # CRUD /api/trackers/*
|
|
templates.py # CRUD /api/templates/*
|
|
targets.py # CRUD /api/targets/*
|
|
users.py # CRUD /api/users/* (admin)
|
|
status.py # GET /api/status
|
|
services/
|
|
__init__.py
|
|
scheduler.py # APScheduler setup, job management
|
|
watcher.py # Album polling + change detection
|
|
notifier.py # Dispatch notifications (Telegram/webhook)
|
|
webhook/
|
|
__init__.py
|
|
client.py # Generic webhook POST JSON
|
|
Dockerfile
|
|
docker-compose.yml
|
|
```
|
|
|
|
---
|
|
|
|
## Tasks
|
|
|
|
### 1. Package setup `[ ]`
|
|
- pyproject.toml with deps: fastapi, uvicorn, sqlmodel, pyjwt, bcrypt, apscheduler, jinja2, immich-watcher-core
|
|
|
|
### 2. Database models `[ ]`
|
|
- `User`: id, username, hashed_password, role (admin/user), created_at
|
|
- `ImmichServer`: id, user_id, name, url, api_key, external_domain, created_at
|
|
- `NotificationTarget`: id, user_id, type (telegram/webhook), name, config JSON, created_at
|
|
- `MessageTemplate`: id, user_id, name, body (Jinja2), is_default, created_at
|
|
- `AlbumTracker`: id, user_id, server_id FK, name, album_ids JSON, event_types JSON, target_ids JSON, template_id FK (nullable), scan_interval, enabled, quiet_hours_start, quiet_hours_end, created_at
|
|
- `AlbumState`: id, tracker_id FK, album_id, asset_ids JSON, last_updated
|
|
- `EventLog`: id, tracker_id FK, event_type, album_name, details JSON, created_at
|
|
|
|
### 3. Auth `[ ]`
|
|
- POST /api/auth/setup (create first admin, only when no users exist)
|
|
- POST /api/auth/login (returns JWT access + refresh tokens)
|
|
- GET /api/auth/me (current user info)
|
|
- JWT dependency for all protected routes
|
|
|
|
### 4. API endpoints `[ ]`
|
|
- CRUD for servers, trackers, templates, targets
|
|
- GET /api/servers/{id}/albums (proxy to Immich)
|
|
- POST /api/templates/{id}/preview (render with sample data)
|
|
- POST /api/targets/{id}/test (send test notification)
|
|
- POST /api/trackers/{id}/trigger (force check)
|
|
- GET /api/trackers/{id}/history (recent events)
|
|
- GET /api/status (dashboard data)
|
|
- CRUD /api/users (admin only)
|
|
|
|
### 5. Background scheduler `[ ]`
|
|
- APScheduler with AsyncIOScheduler
|
|
- One job per enabled tracker at its scan_interval
|
|
- Job: fetch album -> detect changes -> render template -> notify
|
|
- Start/stop jobs when trackers are created/updated/deleted
|
|
|
|
### 6. Notification dispatch `[ ]`
|
|
- TelegramClient from core (reuse)
|
|
- WebhookClient: POST JSON to configured URL with event data
|
|
- Jinja2 template rendering with same variables as blueprint
|
|
|
|
### 7. Docker `[ ]`
|
|
- Multi-stage Dockerfile (build frontend -> Python runtime)
|
|
- docker-compose.yml for standalone deployment
|
|
|
|
---
|
|
|
|
## Acceptance Criteria
|
|
|
|
- [ ] Server starts, creates SQLite DB on first run
|
|
- [ ] First-run setup creates admin account
|
|
- [ ] Can add Immich server, browse albums
|
|
- [ ] Can create tracker, template, and notification target
|
|
- [ ] Scheduler polls albums and detects changes
|
|
- [ ] Telegram notifications sent on album changes
|
|
- [ ] Webhook notifications sent on album changes
|
|
- [ ] JWT auth protects all endpoints
|
|
- [ ] Docker build works
|