diff --git a/sojorn_docs/FUNKWHALE_DEPLOYMENT.md b/sojorn_docs/FUNKWHALE_DEPLOYMENT.md new file mode 100644 index 0000000..016ee9e --- /dev/null +++ b/sojorn_docs/FUNKWHALE_DEPLOYMENT.md @@ -0,0 +1,143 @@ +# Funkwhale Deployment Guide + +Funkwhale provides the audio library for the audio overlay system in Quips. + +## Server Setup + +SSH to the server and run: + +```bash +ssh -i ~/.ssh/mpls.pem patrick@116.202.231.103 + +# Create Funkwhale directory +mkdir -p /opt/funkwhale/{data,music,media,static,nginx} +cd /opt/funkwhale +``` + +## docker-compose.yml + +Create `/opt/funkwhale/docker-compose.yml`: + +```yaml +version: "3" + +services: + funkwhale: + image: funkwhale/all-in-one:1.4.0 + container_name: funkwhale + restart: unless-stopped + environment: + - FUNKWHALE_HOSTNAME=audio.sojorn.net + - FUNKWHALE_PROTOCOL=https + - NESTED_PROXY=1 + - DJANGO_SECRET_KEY=${FUNKWHALE_SECRET_KEY} + - DATABASE_URL=postgresql://funkwhale:${FUNKWHALE_DB_PASS}@db/funkwhale + - CACHE_URL=redis://redis:6379/0 + - EMAIL_CONFIG=smtp+tls://${SMTP_USER}:${SMTP_PASS}@${SMTP_HOST}:${SMTP_PORT} + - DEFAULT_FROM_EMAIL=no-reply@sojorn.net + volumes: + - ./data:/data + - ./music:/music:ro + - ./media:/srv/funkwhale/data/media + - ./static:/srv/funkwhale/data/static + ports: + - "127.0.0.1:5000:80" + depends_on: + - db + - redis + + db: + image: postgres:15-alpine + restart: unless-stopped + environment: + - POSTGRES_USER=funkwhale + - POSTGRES_PASSWORD=${FUNKWHALE_DB_PASS} + - POSTGRES_DB=funkwhale + volumes: + - ./data/db:/var/lib/postgresql/data + + redis: + image: redis:7-alpine + restart: unless-stopped + volumes: + - ./data/redis:/data +``` + +Create `/opt/funkwhale/.env`: +```env +FUNKWHALE_SECRET_KEY= +FUNKWHALE_DB_PASS= +``` + +Start it: +```bash +cd /opt/funkwhale && docker compose up -d + +# Wait for startup (~60s), then create superuser: +docker compose exec funkwhale manage createsuperuser +``` + +## Nginx Config + +Add a server block to `/etc/nginx/sites-available/sojorn` (or create a new one): + +```nginx +server { + listen 443 ssl; + server_name audio.sojorn.net; + + ssl_certificate /etc/letsencrypt/live/audio.sojorn.net/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/audio.sojorn.net/privkey.pem; + + client_max_body_size 500M; + + location / { + proxy_pass http://127.0.0.1:5000; + 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; + } +} +``` + +Get the certificate: +```bash +sudo certbot --nginx -d audio.sojorn.net +sudo nginx -t && sudo systemctl reload nginx +``` + +## Wire into Go Backend + +Add to `/opt/sojorn/.env`: +```env +FUNKWHALE_BASE=http://127.0.0.1:5000 +``` + +Then rebuild and restart: +```bash +cd /opt/sojorn/go-backend && go build -o bin/api ./cmd/api/... +echo PASSWORD | sudo -S systemctl restart sojorn-api.service +``` + +## Seed With Royalty-Free Music + +Funkwhale can import from local directories. Drop MP3s into `/opt/funkwhale/music/` then: + +```bash +docker compose exec funkwhale manage import_files \ + "/music/" --recursive --noinput +``` + +Good free sources: [Free Music Archive](https://freemusicarchive.org), [ccMixter](https://ccmixter.org). + +## Verify + +```bash +curl http://127.0.0.1:5000/api/v1/tracks/?playable=true +# Should return JSON with track list + +# Via Go proxy (after adding FUNKWHALE_BASE): +curl https://api.sojorn.net/api/v1/audio/library?q=jazz \ + -H "Authorization: Bearer " +``` diff --git a/sojorn_docs/TODO.md b/sojorn_docs/TODO.md index bd8bc72..a85a7ec 100644 --- a/sojorn_docs/TODO.md +++ b/sojorn_docs/TODO.md @@ -1,7 +1,7 @@ # Sojorn Development Status **Last Updated**: February 18, 2026 -**Branch**: **Status**: Active Development — substantial MVP complete, several systems still being wired +**Branch**: goSojorn — **Status**: Active Development — MVP near-complete --- @@ -16,6 +16,7 @@ - Feed algorithm: engagement weighting, cooling period (0.2x multiplier), 60/20/20 diversity injection, impression recording - Repost/boost: 4 repost types, amplification analytics, trending posts - Image/video uploads to Cloudflare R2 with signed URLs +- GET /media/sign?path=X — resolves relative R2 keys to full URLs - Video moderation: FFmpeg frame extraction -> R2 upload -> Google Vision AI + OpenAI analysis - Follow/unfollow, search (users/posts/hashtags/beacons) - Profile widget system with layout persistence @@ -26,10 +27,13 @@ - Capsule key distribution and auto-healing rotation - Group feed endpoint - Capsule admin: rotate keys, invite member, remove member, settings + - GET /users/by-handle/:handle — profile lookup for capsule invite - Health check service: /health, /health/detailed, /health/ready, /health/live - Content moderation: OpenAI text + Google Vision images, Three Poisons scoring - NSFW labeling, blur toggles, appeal system, safe links - GeoIP, Nginx reverse proxy + SSL/TLS +- Audio overlay proxy: GET /audio/library, GET /audio/library/:trackId/listen + - Returns 503 until FUNKWHALE_BASE is set — gracefully handled in Flutter ### Admin Panel (Next.js, port 3001) - Dashboard, user management, post management, bulk actions @@ -41,18 +45,34 @@ - Groups and Capsules page (list, member management, deactivate, key rotation status) - Quip Repair page (list missing thumbnails, server-side FFmpeg repair) +### Flutter App +- Full audio overlay system in Quip recorder: + - AudioLibraryScreen: Device tab (file_picker) + Library tab (Funkwhale via Go proxy) + - EnhancedQuipRecorderScreen: music button, audio chip, volume slider + - VideoStitchingService: ffmpeg audio mix pass (amix with dropout_transition) +- Group navigation (clusters → GroupScreen) +- Public cluster group feed +- Share post via share_plus +- Signed media URL resolution via Go backend + --- ## Needs Server Deploy -Code is on goSojorn branch, NOT yet live. Run from WSL Ubuntu: +Code is on goSojorn branch, NOT yet live. The `internal` remote may be missing on the server. - ssh -i ~/.ssh/mpls.pem patrick@116.202.231.103 - cd /opt/sojorn - git pull internal goSojorn - psql "" -f go-backend/migrations/20260218_feed_impressions_and_group_keys.sql - cd go-backend && go build -o bin/api ./cmd/api/... - echo PASSWORD | sudo -S systemctl restart sojorn-api.service +```bash +ssh -i ~/.ssh/mpls.pem patrick@116.202.231.103 +cd /opt/sojorn + +# Add internal remote if missing: +git remote get-url internal 2>/dev/null || git remote add internal https://git.mp.ls/patrick/sojorn.git + +git pull internal goSojorn +psql "$DATABASE_URL" -f go-backend/migrations/20260218_feed_impressions_and_group_keys.sql +cd go-backend && go build -o bin/api ./cmd/api/... +echo PASSWORD | sudo -S systemctl restart sojorn-api.service +``` --- @@ -60,23 +80,19 @@ Code is on goSojorn branch, NOT yet live. Run from WSL Ubuntu: ### High Priority -**Audio Overlay System** -- Flutter: AudioLibraryScreen (Device tab + Funkwhale Library tab) -- Flutter: Voice overlay recording + ffmpeg_kit mixing -- Backend: Funkwhale proxy (GET /audio/search, GET /audio/track/:id) -- Infrastructure: Funkwhale Docker pod + Nginx proxy at /funkwhale/ - -**Small Backend Gaps** -- GET /media/sign?path=X endpoint (Flutter getSignedMediaUrl calls this, not yet in Go routes) -- GET /users/by-handle/:handle (used by capsule invite -- verify exists) +**Funkwhale Infrastructure** (audio library backend) +- Deploy Funkwhale Docker pod on server — see sojorn_docs/FUNKWHALE_DEPLOYMENT.md +- Add to /opt/sojorn/.env: `FUNKWHALE_BASE=http://127.0.0.1:5000` +- Seed with royalty-free tracks +- Optional: `audio.sojorn.net` Nginx block + SSL cert ### Medium Priority **Flutter Polish** -- sojorn_rich_text.dart -- profile navigation from @mentions -- post_with_video_widget.dart -- post options menu (edit, delete, report) -- video_player_with_comments.dart -- more options button -- reading_post_card.dart -- share functionality +- sojorn_rich_text.dart — profile navigation from @mentions +- post_with_video_widget.dart — post options menu (edit, delete, report) +- video_player_with_comments.dart — more options button +- reading_post_card.dart — share functionality **Algorithm Transparency** - Show users why a post appeared in their feed @@ -88,7 +104,7 @@ Code is on goSojorn branch, NOT yet live. Run from WSL Ubuntu: - Delete go-backend/cmd/supabase-migrate/ (dead tool) - Remove stale Supabase comments in go-backend/internal/middleware/auth.go - Remove forceResetBrokenKeys() from simple_e2ee_service.dart -- go-backend root: loose check_table.go, seed_groups*.go -- conflicting main, move or delete +- go-backend root: loose check_table.go, seed_groups*.go — conflicting main, move or delete **Infrastructure** - CI/CD pipeline (currently manual deploy) @@ -106,3 +122,5 @@ Code is on goSojorn branch, NOT yet live. Run from WSL Ubuntu: - Capsule auto key rotation on open + admin modals (rotate, invite, remove, settings) - Flutter: group navigation, group feed, share_plus, signed URL, quip repair wired to Go - Health check service wired into routes +- GET /media/sign and GET /users/by-handle/:handle endpoints added +- Full audio overlay system: AudioLibraryScreen, Funkwhale proxy routes, ffmpeg amix