- Structured logging: replace log.* with log/slog JSON output across backend - Request logger middleware: logs method, path, status, duration for all non-health requests - Rate limiting: token bucket (5 req/min, burst 10) on AI endpoints (/api/ai/*) - Integration tests: full critical path test (auth -> create case -> add deadline -> dashboard) - Seed demo data: 1 tenant, 5 cases with deadlines/appointments/parties/events - docker-compose.yml: add all required env vars (DATABASE_URL, SUPABASE_*, ANTHROPIC_API_KEY) - .env.example: document all env vars including DATABASE_URL and CalDAV note
47 lines
1.1 KiB
Go
47 lines
1.1 KiB
Go
package main
|
|
|
|
import (
|
|
"log/slog"
|
|
"net/http"
|
|
"os"
|
|
|
|
"mgit.msbls.de/m/KanzlAI-mGMT/internal/auth"
|
|
"mgit.msbls.de/m/KanzlAI-mGMT/internal/config"
|
|
"mgit.msbls.de/m/KanzlAI-mGMT/internal/db"
|
|
"mgit.msbls.de/m/KanzlAI-mGMT/internal/logging"
|
|
"mgit.msbls.de/m/KanzlAI-mGMT/internal/router"
|
|
"mgit.msbls.de/m/KanzlAI-mGMT/internal/services"
|
|
)
|
|
|
|
func main() {
|
|
logging.Setup()
|
|
|
|
cfg, err := config.Load()
|
|
if err != nil {
|
|
slog.Error("failed to load config", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
database, err := db.Connect(cfg.DatabaseURL)
|
|
if err != nil {
|
|
slog.Error("failed to connect to database", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
defer database.Close()
|
|
|
|
authMW := auth.NewMiddleware(cfg.SupabaseJWTSecret, database)
|
|
|
|
// Start CalDAV sync service
|
|
calDAVSvc := services.NewCalDAVService(database)
|
|
calDAVSvc.Start()
|
|
defer calDAVSvc.Stop()
|
|
|
|
handler := router.New(database, authMW, cfg, calDAVSvc)
|
|
|
|
slog.Info("starting KanzlAI API server", "port", cfg.Port)
|
|
if err := http.ListenAndServe(":"+cfg.Port, handler); err != nil {
|
|
slog.Error("server failed", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|