Infrastruktura i Deployment
Projekt Lumos Islands składa się z trzech komponentów:
- Flutter App (iOS + Android) — budowane lokalnie na macOS
- Manager-Content (Go server) — deployment w Docker
- IDEA (VitePress docs) — statyczna strona
Supabase (BaaS)
Supabase jako backend-as-a-service:
Baza danych — PostgreSQL (hosted by Supabase)
- Migracje:
supabase migrationCLI - Row Level Security (RLS) na tabelach
- Supabase client w Go (
supabase-golub bezpośredniopgx/sqlxdo PostgreSQL URL)
Storage — Supabase Storage (S3-compatible)
- Buckety:
avatars,media(video, audio, images),creative-submissions - Public bucket dla preset avatarów i media content
- Private bucket dla creative submissions
- CDN: Supabase CDN (automatyczny)
- Upload przez Go server (nie bezpośrednio z Flutter)
- Limity: avatar 2MB, media 100MB, creative 10MB
Auth — Supabase Auth (uzupełniające)
- Supabase Auth używany do emaili (wysyłanie kodów weryfikacyjnych)
- Własna warstwa JWT w Go server (nie Supabase Auth bezpośrednio dla app auth)
- Email templates konfigurowane w Supabase Dashboard
Realtime — Supabase Realtime (opcjonalnie w przyszłości)
- Broadcast do push notifications
- Na start: polling, później migration do realtime
JWT Specyfikacja
- Algorytm: HS256
- Secret: env var
JWT_SECRET(min 32 znaki) - Expiry: 30 dni (child), 7 dni (parent)
- Claims:
{ "sub": "user_id", "role": "child|parent|school", "iat": ..., "exp": ... } - Refresh: brak refresh tokena w v1 — po wygaśnięciu ponowne logowanie (PIN jest szybki)
- Logout: usunięcie tokena z Flutter Secure Storage (stateless JWT, brak server-side revocation w v1)
Docker Deployment (Manager-Content)
dockerfile
# Multi-stage build
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o server ./cmd/server
FROM alpine:3.19
RUN apk add --no-cache ca-certificates
COPY --from=builder /app/server /server
COPY --from=builder /app/web /web
EXPOSE 8080
CMD ["/server"]Docker Compose (dev):
yaml
services:
manager:
build: ./manager-content
ports: ["8080:8080"]
env_file: .env
volumes:
- ./manager-content:/app # hot reload z airEnvironment variables:
| Zmienna | Opis | Przykład |
|---|---|---|
DATABASE_URL | Supabase PostgreSQL connection string | postgresql://... |
SUPABASE_URL | Supabase project URL | https://xxx.supabase.co |
SUPABASE_SERVICE_KEY | Supabase service role key | eyJ... |
JWT_SECRET | Secret do podpisywania JWT | super-secret-key-32-chars-min |
PORT | Port serwera | 8080 |
ENV | Środowisko | development / production |
GitHub Actions CI/CD
Plik: .github/workflows/deploy.yml
Trigger: push na main
Steps:
- Checkout
- Go tests (
go test ./...) - Build Docker image
- Push do GitHub Container Registry (ghcr.io)
- Deploy (SSH do serwera, docker pull + restart)
yaml
name: Deploy Manager-Content
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.23'
- run: go test ./...
build-push:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
context: ./manager-content
push: true
tags: ghcr.io/${{ github.repository }}/manager:latestFlutter App Build (macOS)
Budowane lokalnie na macOS. Makefile w katalogu app/:
makefile
.PHONY: build run test
# Zbuduj i wyślij do App Store (iOS)
build-ios:
flutter build ipa --release
xcrun altool --upload-app \
--type ios \
--file build/ios/ipa/*.ipa \
--apiKey $(APP_STORE_API_KEY) \
--apiIssuer $(APP_STORE_ISSUER)
# Zbuduj APK (Android)
build-android:
flutter build appbundle --release
# Zbuduj obie platformy
build: build-ios build-android
# Uruchom lokalne
run:
flutter run
# Testy
test:
flutter testWymagane:
- macOS z Xcode 15+
- Flutter SDK 3.x
- Apple Developer Account + API Key
APP_STORE_API_KEYiAPP_STORE_ISSUERw.envlub export
Monitoring i Logi
- Go server: structured logging (slog) w JSON
- Docker logs -> stdout/stderr
- Health check:
GET /health->200 OK - Supabase Dashboard: monitoring bazy danych
- Sentry (opcjonalnie): error tracking w Go + Flutter
CORS
go
cors := cors.New(cors.Options{
AllowedOrigins: []string{"https://manager.lumosislands.com"},
AllowedMethods: []string{"GET", "POST", "PATCH", "DELETE"},
AllowedHeaders: []string{"Authorization", "Content-Type", "Device-Id"},
AllowCredentials: true,
})Flutter app (/app/*): brak CORS (natywna apka, nie przeglądarka)
Rate Limiting
| Endpoint | Limit | Window |
|---|---|---|
POST /app/auth/* | 10 req | 1 min |
POST /api/auth/* | 10 req | 1 min |
GET /app/* | 100 req | 1 min |
POST /app/* | 30 req | 1 min |
| Uploady (multipart) | 5 req | 1 min |
Implementacja: middleware w chi (in-memory, per IP)