Game sync and live services for independent game developers (targeting itch.io)
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Requirements#

Functional Requirements#

1. Storage Management#

  • 2GB default quota per user (soft limits at 80%, cumulative tracking)
  • Hard limit enforcement when quota exceeded
  • Cumulative tracking (never resets)
  • Blob count limits (default: 1000)

2. GDPR Compliance#

  • Automatic EU country detection via GeoLite2 database
  • EU users must store data in EU data centers
  • Non-EU users can use default backend
  • Country detection failure must crash application
  • GeoLite2 database path configurable via GEOIP_DATABASE_PATH environment variable
  • Block uploads until country is set in profile
  • Provide country consent flow with GDPR alerts

3. Multi-Backend Storage#

  • Bunny Storage support (default backend)
  • DigitalOcean Spaces support (alternative backend)
  • Real-time cost calculation from backend APIs
  • 1-hour cost cache with automatic background refresh
  • Backend selection based on user location (GDPR-compliant)
  • Automatic storage backups (Bunny built-in: 7-day retention)

4. Authentication#

  • JWT for XRPC endpoints (24-hour expiration)
  • Passkey for admin CLI (terminal-only, no web UI)
  • Terminal registration via single interactive command with QR code
  • HTTP endpoint for credential response (from phone)
  • Age encryption for passkeys database (synced to Bunny Storage)
  • Session cookies for web UI (7-day expiration)
  • Session cookies created after country consent
  • HTTP-only, Secure, SameSite=Lax settings for cookies

5. Passkey Management#

  • Terminal-only registration (no web UI)
  • Single interactive command: scrtchbk-ctl passkey-register <username>
  • Display QR code in terminal (ASCII art)
  • Wait for HTTP POST /auth/passkey/response from phone
  • Store credentials in passkeys database
  • Encrypt passkeys database with age
  • Sync to Bunny Storage bucket after every registration
  • Encryption key loaded from .env.age environment variable
  • 5-minute timeout for credential response

6. Cost Management#

  • Real-time storage cost per GB (Bunny: $0.01, DO: $0.005)
  • Real-time bandwidth cost per GB (Bunny: $0.005, DO: $0.008)
  • Combined total cost calculation
  • 1-hour cache duration
  • Automatic background refresh task (tokio)
  • Cached using cached proc macro for memoization
  • Cache cleared every hour to force recalculation
  • Individual backend costs cached separately
  • Combined total cost cached separately

7. Admin Controls#

  • CLI tool named scrtchbk-ctl
  • Direct database access (no authentication required)
  • System statistics command
  • User management commands (list, view, set quota)
  • Blob management commands (list, soft delete)
  • Cleanup command for expired soft-deleted blobs (14-day retention)
  • Passkey commands (register, sync)
  • Database query commands
  • Static binary (separate build.sr.ht)

8. Web UI#

  • Homepage with deployment information and real-time cost estimates
  • Protected self-view page (session cookie auth required)
  • Country consent flow page
  • HTMX for dynamic interactions
  • minijinja templates with Object contexts
  • 7-day session cookie expiration
  • HTTP-only, Secure, SameSite=Lax cookie settings

9. Configuration#

  • Priority: Environment variables > config.toml > defaults
  • Age decryption on startup (.env.age)
  • GeoLite2 database path via GEOIP_DATABASE_PATH environment variable
  • Session cookie configuration (7-day expiration)
  • Separate build.sr.ht for admin CLI

10. Deployment#

  • Deployment metadata generated fresh at every startup
  • Static binary builds via build.sr.ht
  • No CI/CD (manual deployment to Hetzner VPS)
  • Deployment info stored in deployment-info.json

Non-Functional Requirements#

1. Technology Stack#

  • Rust 2021 edition
  • Axum 0.7 (web framework)
  • Diesel 2.1 (ORM)
  • SQLite (database via rsky)
  • minijinja 2.0 (templates)
  • age 0.11 (encryption)
  • cached 0.1 (memoization)
  • fs-err-tokio 0.2 (error handling)
  • webauthn-rs 0.5 (passkey)
  • aws-sdk-s3 1.20 (Bunny/DigitalOcean)
  • maxminddb 0.24 (GeoIP)
  • qrcode 0.14 (QR codes)
  • cookie 0.18 (session cookies)

2. Performance#

  • Cost calculations cached for 1 hour
  • Background refresh task for cache
  • Async/await throughout
  • Connection pooling for databases
  • Real-time API calls to storage backends

3. Security#

  • Zero-knowledge (server cannot decrypt user data)
  • Age encryption at rest (passkeys in Bunny Storage)
  • HTTPS-only for production
  • Secure cookies (HTTP-only, Secure flag, SameSite=Lax)
  • JWT tokens (24-hour expiration)
  • Session tokens (7-day expiration)
  • Separate passkeys database for admin credentials

4. Reliability#

  • Bunny Storage 99.95% uptime SLA
  • DigitalOcean Spaces 99.9% uptime SLA
  • Soft deletion with 14-day retention (grace period for recovery)
  • Automatic storage backups (Bunny built-in, 7-day retention)
  • GeoIP detection with crash on failure (admin must configure)

5. Usability#

  • Terminal-only passkey registration with QR codes
  • Clear error messages for configuration failures
  • GDPR consent flow with storage restrictions explained
  • Mobile-responsive HTMX interface
  • Real-time cost estimates on homepage

6. Maintainability#

  • Separate admin CLI from web server
  • Comprehensive documentation
  • Diesel migrations for schema changes
  • Build.sr.ht for reproducible deployments
  • Error handling with miette for detailed diagnostics

7. Scalability#

  • Dual storage backends (Bunny + DigitalOcean)
  • GDPR-compliant region routing
  • Cost cache reduces API calls
  • Connection pooling for databases
  • Background tasks for non-blocking operations

Constraints#

  • Budget: $80/month maximum

    • Hetzner EU VPS: $5.50
    • DigitalOcean US VPS: $12 (upgraded)
    • Bunny Storage: $11 total (separate EU/US buckets)
    • Sentry: $15 (team plan)
    • uptime.io: $7
    • Elastic Email: $5
    • Turso: $10 (for metadata only)
  • Storage backends must be S3-compatible

  • Passkey registration must be terminal-only

  • GeoIP database must be configured before starting

  • Application must crash if GeoIP detection fails

  • Session cookies must expire after 7 days

  • Soft-deleted blobs must be retained for 14 days

  • Cost cache must refresh every hour

  • Passkeys must sync to Bunny Storage after registration

  • Age encryption key must be in .env.age