managarten/services/mana-sync/internal/config/config.go
Till JS ed76f53b00 feat(sync): Phase 2 — server-side billing gate, cron charging, email notifications
Server-side gating (mana-sync Go):
- New billing.Checker with 5-minute cache per user
- Middleware wraps POST/GET /sync/{appId} endpoints
- Returns 402 Payment Required when sync subscription inactive
- Fail-open: if mana-credits is unreachable, sync is allowed
- Config: MANA_CREDITS_URL + MANA_SERVICE_KEY env vars

Recurring charge cron (mana-credits):
- Hourly setInterval checks for due sync subscriptions
- Calls chargeRecurring() which debits credits and advances nextChargeAt
- On insufficient credits: pauses subscription, sends email via mana-notify

Email notifications:
- Sends "Cloud Sync pausiert" email via mana-notify when subscription paused
- Uses POST /api/v1/notifications/send with X-Service-Key auth

Client-side 402 handling:
- sync.ts detects 402 from push/pull, fires onBillingRequired callback
- Layout wires callback to reload syncBilling store → shows pause banner

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 22:28:57 +02:00

37 lines
1.1 KiB
Go

package config
import (
"os"
"strconv"
)
// Config holds all configuration for the sync server.
type Config struct {
Port int
DatabaseURL string
JWKSUrl string // mana-auth JWKS endpoint for JWT validation
CORSOrigins string
ManaCreditsURL string // mana-credits service URL for billing checks
ServiceKey string // Service-to-service auth key
}
// Load reads configuration from environment variables with sensible defaults.
func Load() *Config {
port, _ := strconv.Atoi(getEnv("PORT", "3050"))
return &Config{
Port: port,
DatabaseURL: getEnv("DATABASE_URL", "postgresql://mana:devpassword@localhost:5432/mana_sync"),
JWKSUrl: getEnv("JWKS_URL", "http://localhost:3001/api/auth/jwks"),
CORSOrigins: getEnv("CORS_ORIGINS", "http://localhost:5173,http://localhost:5188"),
ManaCreditsURL: getEnv("MANA_CREDITS_URL", "http://localhost:3061"),
ServiceKey: getEnv("MANA_SERVICE_KEY", "dev-service-key"),
}
}
func getEnv(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}