Add Docker setup, .env.example, updated .gitignore/CHANGELOG and ADRs 004-007 + arc42 template

This commit is contained in:
zwitschi committed 2026-08-02 16:05:18 +02:00
1 parent dafcec1303
commit 0785260689
13 files changed
+724 -3

No files matched your search

@@ -0,0 +1,101 @@
# ADR-004: Video Admin Web Interface (Upload, Playlist Management, Schedule Overrides)
**Status:** Proposed
**Date:** 2026-08-02
**Author:** AI Assistant (following AGENTS.md and ADR-002/ADR-003)
**Related ADRs:** [ADR-001](./ADR-001.md), [ADR-002](./ADR-002-module-structure.md), [ADR-003](./ADR-003-tech-stack.md)
## Context
The system requires an administrative interface for content owners to:
- Upload new video files (with automatic normalization validation).
- Manage the playlist (add, remove, reorder, preview).
- Override the schedule (insert emergency slate, change start times).
- View current playout status and logs.
- Enforce normalization rules from ADR-001 before files are added to the playlist.
This interface must be lightweight, secure, and integrated with the playout service and Cloudflare R2. It should follow the "update documentation first" rule and the folder structure from ADR-002.
## Decision Drivers
1. **Lightweight & Maintainable** – Prefer server-rendered or minimal JS (HTMX + Tailwind) over heavy SPA frameworks to align with ADR-003's "lightweight" principle.
2. **Security** – Strict authentication, file type/size validation, and R2 upload permissions.
3. **Usability** – Drag-and-drop playlist editor, progress indicators for normalization and upload, real-time playout status.
4. **Integration** – Must call playout service APIs for validation and playlist updates; upload directly to R2 with metadata.
5. **Traceability** – All admin actions must be logged for moderation/audit (future ADR-005).
## Decision
Create a dedicated **admin web interface** in a new `frontend/admin/` directory (or under a protected route in the main SPA).
**Tech Stack (per ADR-003)**:
- **Frontend**: HTMX + Tailwind CSS + Alpine.js (minimal JS, server-rendered HTML). Alternative: React if complex interactions are needed later.
- **Backend**: Go (or Node.js) API endpoints exposed by the playout service or a dedicated `backend/admin/` service.
- **Authentication**: JWT or session-based (admin roles only). Use Cloudflare Access or simple OAuth for production.
- **File Handling**: Upload → validate with ffprobe (codec, fps, keyframes, duration) → normalize if needed → store in R2 with metadata.
- **Playlist Editor**: Drag-and-drop UI that updates a shared playlist file or database record used by the playout worker.
**UI Layout**:
- Sidebar navigation (Dashboard, Upload, Playlist, Schedule, Logs).
- Upload page with progress bar, normalization report, and "Add to Playlist" button.
- Playlist page with reorderable list, preview thumbnails, and "Apply to Live" button.
- Live status dashboard showing current segment, next video, and playout health.
- Schedule override form for inserting emergency content.
**Folder Placement** (per ADR-002):
- `frontend/admin/` – Admin-specific HTML/JS components.
- `backend/playout/internal/admin/` – API handlers (or new `backend/admin/` service if complexity grows).
- Documentation and API specs added to `docs/architecture/`.
## Rationale
- HTMX keeps the admin interface lightweight and aligns with the overall "no heavy frontend frameworks" philosophy from ADR-003.
- Early validation and normalization enforcement prevents playout errors (key requirement from ADR-001).
- Integration with existing playout service and R2 keeps the architecture consistent.
- Admin actions will be fully auditable, paving the way for ADR-005 (moderation and user management).
This decision was planned in `TODO.md` before implementation, per AGENTS.md.
## Consequences
**Positive**:
- Content owners can manage the channel without SSH or direct server access.
- Normalization is enforced at upload time, reducing runtime errors.
- Clear separation of admin UI from public viewer SPA.
**Negative / Risks**:
- Additional attack surface (file uploads) – mitigate with strict validation, size limits, and virus scanning (future).
- Admin UI must be protected by strong auth (planned for ADR-005).
- Initial development effort for drag-and-drop playlist editor.
**Alternatives Considered**:
- Full React Admin (rejected – heavier than needed).
- Third-party tool (e.g., Directus or Strapi) – rejected for independence and to stay within the self-hosted lightweight stack.
- CLI-only admin – rejected for usability.
## Implementation Plan
1. Create this ADR-004 (done).
2. Implement backend API endpoints in `backend/playout/` for validation and playlist updates.
3. Build the HTMX-based admin UI in `frontend/admin/`.
4. Add authentication middleware.
5. Update `docker-compose.yml` to serve the admin interface (protected route).
6. Write tests for normalization validation.
**Next ADR**: ADR-005 (user management, moderation dashboard, analytics).
## References
- ADR-001: Normalization requirements, HLS playout, R2 usage.
- ADR-002: Folder structure (admin UI belongs under frontend or a protected route).
- ADR-003: Lightweight frontend preference (HTMX/Tailwind over heavy frameworks).
- arc42 documentation: Building Block View (admin as part of the overall system).
This ADR ensures all admin interface decisions are documented before code is written.
@@ -0,0 +1,105 @@
# ADR-005: Web Admin Interfaces for User Management, Moderation, and Analytics
**Status:** Proposed
**Date:** 2026-08-02
**Author:** AI Assistant (following AGENTS.md, ADR-002, ADR-003, and ADR-004)
**Related ADRs:** [ADR-001](./ADR-001.md), [ADR-002](./ADR-002-module-structure.md), [ADR-003](./ADR-003-tech-stack.md), [ADR-004](./ADR-004-admin-video.md)
## Context
Building on ADR-004 (video admin interface), the system requires additional protected admin interfaces for:
- **User Management**: View registered users, manage roles, ban/suspend accounts.
- **Moderation Tools**: Real-time moderation dashboard, mute/timeout/ban users, review/delete messages, view moderation audit log.
- **Analytics**: Basic dashboard showing concurrent viewers, chat activity, popular videos, cache hit ratio, R2 usage, and playout health metrics.
These interfaces must be secure, auditable, and integrated with the chat backend, database, and monitoring systems. All admin actions must be logged for compliance and review.
## Decision Drivers
1. **Consistency** – Use the same lightweight tech stack decided in ADR-004 (HTMX + Tailwind + Alpine.js) to avoid introducing new frameworks.
2. **Security & Auditability** – All actions must require admin authentication and be logged immutably.
3. **Real-time Needs** – Moderation dashboard should show live chat activity (WebSocket integration).
4. **Simplicity** – Analytics should use existing Prometheus/Grafana data where possible rather than building a duplicate system.
5. **Separation of Concerns** – Video admin (ADR-004) and user/moderation/analytics admin should share a common admin layout but remain modular.
## Decision
Extend the admin interface started in ADR-004 with additional protected sections:
**Tech Stack (consistent with ADR-003 and ADR-004)**:
- **Frontend**: HTMX + Tailwind + Alpine.js for all admin pages. Shared layout with sidebar navigation.
- **Backend**: Go API endpoints (protected by JWT/session middleware) in `backend/admin/` or extended from the chat/playout services.
- **Authentication**: Role-based (admin, moderator, viewer). Use Cloudflare Access or JWT with short expiry for production.
- **Data Sources**:
- User management: PostgreSQL queries.
- Moderation: Chat database + Redis for live bans.
- Analytics: Prometheus metrics (viewer count, cache hits, R2 ops) + custom queries on chat history.
**UI Structure**:
- Common admin layout (`/admin/` route, protected).
- **Users** tab: Searchable table, role assignment, ban/unban actions.
- **Moderation** tab: Live chat feed, quick mute/ban/report review, audit log with filters.
- **Analytics** tab: Dashboard with charts (concurrent viewers, chat volume, top videos, cache hit ratio, storage usage). Embed Grafana panels where possible.
**Folder Placement** (per ADR-002):
- `frontend/admin/` – Reused and extended from ADR-004 (add moderation and analytics components).
- `backend/admin/` – New module for admin-specific API handlers (or extend `backend/chat/` and `backend/playout/`).
- API documentation and OpenAPI spec added to `docs/architecture/`.
**Logging**: All admin actions (ban, delete message, schedule override) written to an immutable audit log table.
## Rationale
- Reusing HTMX/Tailwind from ADR-004 keeps the admin interface lightweight and consistent.
- Centralizing admin functionality under `/admin/` reduces maintenance overhead.
- Leveraging Prometheus/Grafana for analytics avoids duplicating metrics collection.
- Immutable audit logging supports future compliance and moderation review (key requirement for a public chat system).
This ADR was planned in `TODO.md` before any implementation, per AGENTS.md.
## Consequences
**Positive**:
- Unified admin experience for content, users, moderation, and analytics.
- Strong audit trail for all privileged actions.
- Real-time moderation capabilities integrated with the chat backend.
**Negative / Risks**:
- Admin interface becomes a larger attack surface – mitigate with strict rate limiting, IP allowlisting, and Cloudflare WAF.
- Real-time moderation may increase load on the chat service (monitor Redis and WebSocket connections).
- Analytics queries on large chat history could be expensive – use aggregation tables or limit retention (planned in future ADR).
**Alternatives Considered**:
- Separate admin SPA (React AdminJS) – rejected for consistency with ADR-004 and to avoid framework bloat.
- Third-party moderation tools (e.g., Discourse moderation suite) – rejected to maintain full self-hosted control.
- No analytics – rejected because operators need visibility into cache hit ratio, viewer count, and R2 costs.
## Implementation Plan
1. Create this ADR-005 (done).
2. Extend the admin layout from ADR-004 with new tabs (Users, Moderation, Analytics).
3. Implement backend API endpoints for user management, moderation actions, and metrics aggregation.
4. Add WebSocket support for live moderation feed.
5. Integrate Prometheus queries for analytics dashboard.
6. Add comprehensive audit logging for all admin actions.
7. Update authentication middleware and tests.
8. Document API contracts and update `docker-compose.yml` to expose the admin interface securely.
**Next Steps**: After both admin ADRs are complete, move to implementation of the Playout Service (highest priority in the core modules section of TODO.md).
## References
- ADR-001: Chat features, moderation requirements, monitoring needs.
- ADR-002: Folder structure – admin UI belongs under `frontend/admin/`.
- ADR-003: Lightweight frontend (HTMX/Tailwind) and Go backend preference.
- ADR-004: Video admin interface (shared layout and authentication approach).
- arc42 documentation: Cross-cutting Concepts (security, monitoring) and Building Block View (admin as extension of the system).
This completes the admin interface documentation phase. All decisions are now traceable before any code is written.
@@ -0,0 +1,100 @@
# ADR-006: Data Storage Strategy (SQLite vs PostgreSQL)
**Status:** Proposed
**Date:** 2026-08-02
**Author:** AI Assistant (following AGENTS.md, ADR-002, ADR-003, ADR-004, ADR-005)
**Related ADRs:** [ADR-001](./ADR-001.md), [ADR-003](./ADR-003-tech-stack.md), [ADR-005](./ADR-005-admin-moderation-analytics.md), [ADR-007](./ADR-007-redis-usage.md)
## Context
The system needs persistent storage for:
- Chat messages and history (public rooms and private DMs).
- User accounts, roles, and ban lists.
- Moderation audit log (immutable record of admin and moderator actions).
- Playlist metadata and schedule overrides.
- System configuration (including Redis settings adjustable via admin UI per ADR-005/ADR-007).
From ADR-003 we prefer operational simplicity. ADR-005 requires a robust audit trail. We must decide between **SQLite** (embedded, zero-config) and **PostgreSQL** (full-featured, scalable) and document how the admin interface can view and adjust storage-related configuration.
## Decision Drivers
1. **Operational Simplicity** – Minimize infrastructure (no separate DB server for SQLite).
2. **Performance & Concurrency** – Chat and moderation may have high write volume.
3. **Backup and Recovery** – Easy point-in-time recovery and replication.
4. **Admin Capabilities** – Admin UI must be able to view storage stats, run vacuum/analyze, and switch between SQLite and PostgreSQL (with migration path).
5. **Auditability** – Moderation log must be immutable and queryable.
6. **Cost** – Avoid managed database costs during early stages.
## Decision
**Primary storage for v1: SQLite** (embedded in the chat and admin services).
**Migration Path**: Provide a clear upgrade path to PostgreSQL when concurrency or replication needs exceed SQLite capabilities (target v2 or when concurrent users > 500).
**Admin Interface Capabilities** (extension of ADR-005):
- "System Configuration" tab showing current storage engine, database size, connection stats, and vacuum status.
- Buttons to run `VACUUM`, `ANALYZE`, or trigger a backup.
- Configuration form to switch connection string (SQLite file path vs PostgreSQL URL) and restart services gracefully.
- Audit log of all configuration changes.
**Technical Details**:
- Use SQLite with WAL mode for better concurrency.
- Use GORM or sqlx (Go) or Prisma (if Node.js fallback) for ORM/migrations.
- Store large chat history in a separate table with retention policy (e.g., 30 days).
- Moderation log as an append-only table with triggers for immutability.
**Folder Placement** (per ADR-002):
- Database models and migrations in `backend/shared/db/` or `backend/chat/internal/db/`.
- Admin UI pages for storage management in `frontend/admin/system/`.
## Rationale
- SQLite aligns with ADR-003's emphasis on operational simplicity and low resource usage for the initial deployment on a single Hetzner VPS.
- It eliminates the need for a separate database container in `docker-compose.yml` during early development.
- The admin interface can provide visibility and basic maintenance operations, fulfilling the requirement from the previous TODO plan.
- PostgreSQL can be introduced later with a migration script when scale demands it (replication, advanced querying, full-text search on chat).
## Consequences
**Positive**:
- Zero-config database for quick local development and small-scale production.
- Simple backups (just copy the `.db` file).
- Admin UI can directly manage and monitor storage without external tools.
**Negative / Risks**:
- SQLite has limited concurrency compared to PostgreSQL (WAL mode helps but is not a full replacement).
- Large chat history or analytics queries may become slow – plan retention policy and archiving.
- Migration to PostgreSQL will require downtime or dual-write strategy (documented in this ADR).
**Alternatives Considered**:
- PostgreSQL from day one – rejected for added operational complexity (separate service, connection pooling, managed service cost).
- Pure key-value store (e.g., BoltDB) – rejected because SQL is better for audit logs and complex moderation queries.
- Managed database (Neon, Supabase) – rejected to maintain full self-hosted independence per ADR-001.
## Implementation Plan
1. Create this ADR-006 (done).
2. Add SQLite support in `backend/shared/db/` with GORM migrations.
3. Implement admin UI pages for storage monitoring and configuration (linked to ADR-005).
4. Add configuration reload capability without full restart where possible.
5. Write migration script from SQLite to PostgreSQL.
6. Update `docker-compose.yml` to optionally include PostgreSQL.
7. Add tests for data access patterns and admin configuration changes.
**Next ADR**: ADR-007 (Redis usage and admin configuration capabilities).
## References
- ADR-001: Chat persistence, moderation log, monitoring requirements.
- ADR-003: Preference for operational simplicity and Go backend.
- ADR-005: Admin interface for user management, moderation, and analytics – this ADR extends it with storage and Redis config capabilities.
- arc42 documentation: Cross-cutting Concepts (data management, monitoring) and Risks & Technical Debts.
This ADR ensures all data storage decisions are documented before code is written, maintaining full traceability.
@@ -0,0 +1,108 @@
# ADR-007: Redis Usage (Where, When, and How) + Admin Configuration Capabilities
**Status:** Proposed
**Date:** 2026-08-02
**Author:** AI Assistant (following AGENTS.md and previous ADRs)
**Related ADRs:** [ADR-001](./ADR-001.md), [ADR-003](./ADR-003-tech-stack.md), [ADR-005](./ADR-005-admin-moderation-analytics.md), [ADR-006](./ADR-006-data-storage.md)
## Context
Redis is planned for several real-time and transient use cases in the chat and playout services. ADR-005 and ADR-006 require that the admin interface be able to view Redis statistics and adjust configuration values (rate limits, TTLs, presence expiry, etc.) with full audit logging.
We must explicitly document:
- Exact use cases for Redis.
- Configuration policies (TTL, persistence, high availability).
- Graceful degradation if Redis is unavailable.
- Admin interface capabilities to inspect and modify Redis settings.
## Decision Drivers
1. **Performance** – Redis is ideal for presence, rate limiting, and pub/sub.
2. **Simplicity** – Use a single Redis instance initially; document scaling path.
3. **Observability** – Admin UI must provide real-time visibility and configuration controls.
4. **Reliability** – Define fallback behavior (e.g., disable rate limiting if Redis is down).
5. **Auditability** – All configuration changes made via admin UI must be logged.
## Decision
**Use Redis 7+** as the primary in-memory store with the following defined use cases:
**Defined Use Cases**:
- **Presence**: Track online users per room (SET with TTL).
- **Rate Limiting**: Per-user and per-IP rate limits using Redis INCR + EXPIRE.
- **Pub/Sub**: Broadcast chat messages and moderation events to connected WebSocket clients.
- **Cache**: Short-lived cache for playout status and "now playing" metadata (from ADR-001).
- **Session Data**: Temporary admin session tokens (if not using JWT).
**Configuration Policies**:
- Default TTL for presence: 60 seconds (refreshed on activity).
- Rate limit windows: 10 requests per 10 seconds per user (configurable via admin UI).
- Persistence: RDB snapshots every 15 minutes + AOF for safety.
- High Availability: Start with single instance; add Sentinel or Cluster in v2.
- Fallback: If Redis is unavailable, disable real-time presence and rate limiting but continue basic chat functionality (with warning in logs and admin UI).
**Admin Interface Capabilities** (extension of ADR-005):
- Dedicated "Redis Configuration" tab in the admin dashboard.
- View real-time stats: memory usage, connected clients, key counts, hit/miss ratio, slow log.
- Adjustable parameters: rate limit thresholds, presence TTL, cache TTL, pub/sub channel prefixes.
- Actions: Flush specific keys/patterns, trigger save, view slow log, test connectivity.
- All changes are audited to the moderation log (with before/after values) and require confirmation.
**Folder Placement** (per ADR-002):
- Redis client wrapper in `backend/shared/redis/`.
- Admin UI components in `frontend/admin/system/redis/`.
- Configuration defaults in `backend/shared/config/redis.go`.
## Rationale
- Redis is the standard choice for the real-time features required by the chat system (ADR-001).
- Explicit documentation of use cases and fallback behavior prevents misuse.
- Admin interface capabilities fulfill the requirement from the TODO plan and ADR-005, giving operators full control without SSH access.
- Starting simple (single instance) aligns with ADR-003's operational simplicity goal while providing a clear scaling path.
## Consequences
**Positive**:
- Clear, auditable, and configurable Redis usage.
- Admin UI provides powerful observability and tuning without restarting services.
- Graceful degradation path defined.
**Negative / Risks**:
- Redis becomes a single point of failure for presence and rate limiting (mitigated by fallback logic).
- Memory usage must be monitored (admin UI will surface this).
- Configuration changes via admin UI must be carefully validated to prevent accidental DoS or data loss.
**Alternatives Considered**:
- No Redis (use only PostgreSQL) – rejected for performance on real-time features.
- Dragonfly or KeyDB – rejected to stay with mature, well-supported Redis.
- In-memory Go maps only – rejected for lack of persistence and cross-process sharing.
## Implementation Plan
1. Create this ADR-007 (done).
2. Implement Redis client wrapper with configuration reload support.
3. Build the admin UI tab for Redis stats and configuration (linked to ADR-005).
4. Add fallback logic in chat and playout services when Redis is unavailable.
5. Update `docker-compose.yml` to include Redis with persistence.
6. Add monitoring (Prometheus exporter) and admin audit logging for configuration changes.
7. Write tests for rate limiting, presence, and admin configuration flows.
**Next Steps**: After ADR-006 and ADR-007 are reviewed, mark the "Create ADRs for Data Storage, Caching, and Admin Capabilities" section as completed in TODO.md and move it to DONE.md. Then proceed with implementation of the Playout Service.
## References
- ADR-001: Chat features requiring presence, rate limiting, and pub/sub.
- ADR-003: Go preference and operational simplicity.
- ADR-005: Admin interface foundation – this ADR extends it with Redis and storage configuration capabilities.
- ADR-006: Data storage decision (Redis complements the primary SQL store).
- arc42 documentation: Cross-cutting Concepts (caching, monitoring, security) and Deployment View.
This completes the documentation for data storage and caching decisions. All admin capabilities are now traceable before implementation begins.