# Opal-Task Server Opal-task server provides a REST API for syncing tasks across multiple devices. This enables household task sharing and access from anywhere. ## Features - **REST API** - Chi-based HTTP API for task management - **API Key Authentication** - Secure authentication using bcrypt-hashed keys - **Bidirectional Sync** - Push and pull changes with conflict resolution - **Offline Support** - Queue changes when server is unreachable - **Change Tracking** - Automatic change log with configurable retention - **Single Database** - Shared household task database (v1) ## Quick Start ### 1. Build the Binary ```bash cd opal-task go build -o opal main.go ``` ### 2. Generate API Key On your server (with direct database access): ```bash ./opal server keygen --name "My Device" --db /var/lib/opal/opal.db ``` Output: ``` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ API Key Generated Successfully ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Name: My Device Key: oak_abc123... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ⚠️ IMPORTANT: Save this key securely! It will not be displayed again. ``` ### 3. Start the Server ```bash ./opal server start --addr :8080 --db /var/lib/opal/opal.db ``` ### 4. Configure Client On your local machine or phone: ```bash opal sync init --url https://opal.yourdomain.com --key oak_abc123... ``` Or use interactive mode: ```bash opal sync init # Enter server URL: https://opal.yourdomain.com # Enter API key: oak_abc123... ``` ### 5. Sync Your Tasks ```bash # Full bidirectional sync opal sync now # Push local changes only opal sync up # Pull server changes only opal sync down # Initial merge (for existing local database) opal sync merge --prefer-local ``` ## Server Deployment ### Option 1: SystemD Service (Recommended) **1. Install Binary** ```bash # Build go build -o opal main.go # Copy to system location sudo cp opal /usr/local/bin/ # Create data directory sudo mkdir -p /var/lib/opal sudo chown $USER:$USER /var/lib/opal ``` **2. Generate First API Key** ```bash opal server keygen --name "Admin" --db /var/lib/opal/opal.db # Save the generated key! ``` **3. Create SystemD Service** Create `/etc/systemd/system/opal.service`: ```ini [Unit] Description=Opal Task API Server After=network.target [Service] Type=simple User=your-user WorkingDirectory=/var/lib/opal ExecStart=/usr/local/bin/opal server start --addr :8080 --db /var/lib/opal/opal.db Restart=always RestartSec=5 [Install] WantedBy=multi-user.target ``` **4. Enable and Start Service** ```bash sudo systemctl daemon-reload sudo systemctl enable opal sudo systemctl start opal sudo systemctl status opal ``` ### Option 2: Direct Execution ```bash # Run in background nohup ./opal server start --addr :8080 --db /var/lib/opal/opal.db > opal.log 2>&1 & ``` ## Reverse Proxy Setup ### Caddy (Recommended) Add to your Caddyfile: ``` opal.yourdomain.com { reverse_proxy localhost:8080 } ``` Reload Caddy: ```bash sudo systemctl reload caddy ``` ### Nginx ```nginx server { listen 443 ssl http2; server_name opal.yourdomain.com; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; location / { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` ## API Endpoints ### Authentication All endpoints (except `/health`) require authentication via API key: ``` Authorization: Bearer oak_abc123... ``` ### Health Check ``` GET /health ``` Returns server status. ### Tasks ``` GET /tasks - List tasks (with filters) GET /tasks/{uuid} - Get specific task POST /tasks - Create task PUT /tasks/{uuid} - Update task DELETE /tasks/{uuid} - Delete task POST /tasks/{uuid}/complete - Mark task complete POST /tasks/{uuid}/start - Start task POST /tasks/{uuid}/stop - Stop task ``` **Query Parameters for GET /tasks:** - `status` - pending, completed, deleted - `project` - Project name - `priority` - L, M, H, D - `tag` - Tag name (can specify multiple) ### Tags ``` GET /tasks/{uuid}/tags - Get task tags POST /tasks/{uuid}/tags - Add tag DELETE /tasks/{uuid}/tags/{tag} - Remove tag GET /tags - List all tags ``` ### Projects ``` GET /projects - List all projects ``` ### Sync ``` POST /sync/changes - Get changes since timestamp POST /sync/push - Push local changes ``` ### API Keys ``` GET /auth/keys - List API keys DELETE /auth/keys/{id} - Revoke API key ``` ## Client Configuration Sync settings are stored in `~/.config/jade/opal.yml`: ```yaml # Task settings default_filter: status:pending default_sort: due,priority color_output: true week_start_day: monday default_due_time: "" # Sync settings sync_enabled: true sync_url: https://opal.yourdomain.com sync_api_key: oak_abc123... sync_client_id: 550e8400-e29b-41d4-a716-446655440000 sync_strategy: last-write-wins sync_queue_offline: true ``` ## Sync Strategies - **last-write-wins** (default) - Most recently modified version wins - **server-wins** - Server version always wins - **client-wins** - Client version always wins ## Change Log Retention By default, the change log retains entries for 30 days. This can be configured in the database: ```sql UPDATE sync_config SET value = '60' WHERE key = 'change_log_retention_days'; ``` Or programmatically: ```go engine.SetChangeLogRetentionDays(60) ``` Cleanup runs manually or can be scheduled: ```bash # In your cron or systemd timer ./opal server cleanup --db /var/lib/opal/opal.db ``` ## Troubleshooting ### Server won't start - Check if port 8080 is already in use: `sudo lsof -i :8080` - Verify database path exists and is writable - Check logs: `journalctl -u opal -f` ### Client can't connect - Test server health: `curl https://opal.yourdomain.com/health` - Verify API key is correct - Check firewall allows traffic on port 8080 - Ensure reverse proxy is properly configured ### Sync conflicts - View conflict log: `opal sync log` - Conflicts are automatically resolved based on strategy - By default, last-write-wins is used ### Offline changes not syncing - Check queue status: `opal sync status` - Verify `sync_queue_offline: true` in config - Clear queue if needed: Delete `~/.config/jade/sync_queue.json` ## Database Schema ### Core Tables - `tasks` - Main task storage - `tags` - Task tags (many-to-many) - `working_set` - Display ID mapping (client-local) ### Sync Tables - `users` - User accounts (currently single shared user) - `api_keys` - Authentication keys - `sync_state` - Per-client sync state - `change_log` - Change tracking (key:value format) - `sync_config` - Server configuration ## Security Considerations - API keys are hashed with bcrypt before storage - Never log full API keys - Use HTTPS in production (via reverse proxy) - Implement rate limiting for production use - Backup database regularly - Rotate API keys periodically ## Future Enhancements - OAuth2 with Authentik for web/mobile clients - Per-user task separation with sharing - Real-time sync via WebSockets - Web/mobile frontend (SvelteKit PWA) - Access control (share specific tags/projects) - Audit logging - Database backup automation ## Support For issues or questions: - Check logs: `journalctl -u opal -f` - View sync status: `opal sync status` - View conflicts: `opal sync log` - Test connectivity: `curl https://opal.yourdomain.com/health` ## License Same as opal-task main project.