// auditlog-devserver stellt AUD-03s ExportHandler sowie AUD-08s // IngestHandler (internal/audit) bereit — Export fuer die Next.js-Ansicht // (AUD-04), Ingest fuer physisch getrennte Module (Archive CMP-04 u.a.). // Getrennt von cmd/core aus demselben Grund wie die anderen *-devserver // (siehe LIC-04/TEN-05): echte Auth/RBAC ist noch nicht in die zentrale // Server-Topologie verdrahtet. // // Authorize wird hier mit einem geteilten Admin-Token ueber // crypto/subtle.ConstantTimeCompare umgesetzt — demselben Timing-safe-Muster // wie internal/audit.timingsafe (AUD-02), NICHT ueber eine neue // Rollen-/Rechteschicht, da diese Kachel ausdruecklich nur von AUD-03 // abhaengt und keine Rechteverwaltung duplizieren soll. package main import ( "context" "log" "net/http" "os" "gitea.perlbach24.de/scripte/nexarch/common/httpharden" "gitea.perlbach24.de/scripte/nexarch/internal/audit" "gitea.perlbach24.de/scripte/nexarch/internal/auditadmin" "gitea.perlbach24.de/scripte/nexarch/internal/db" "gitea.perlbach24.de/scripte/nexarch/internal/svcauth" ) func main() { dsn := os.Getenv("NEXARCH_REGISTRY_DSN") if dsn == "" { log.Fatal("NEXARCH_REGISTRY_DSN nicht gesetzt") } adminToken := os.Getenv("NEXARCH_AUDIT_ADMIN_TOKEN") if adminToken == "" { log.Fatal("NEXARCH_AUDIT_ADMIN_TOKEN nicht gesetzt") } serviceToken := os.Getenv("NEXARCH_AUDIT_SERVICE_TOKEN") if serviceToken == "" { log.Fatal("NEXARCH_AUDIT_SERVICE_TOKEN nicht gesetzt") } addr := os.Getenv("NEXARCH_AUDITLOG_LISTEN_ADDR") if addr == "" { addr = "127.0.0.1:8083" } // QA-15 F-09: kein "*" mehr — explizite Ursprungsliste (fail closed ohne // Konfiguration, siehe svcauth.OriginsFromEnv). allowedOrigins := svcauth.OriginsFromEnv("NEXARCH_AUDITLOG_ALLOWED_ORIGINS") ctx := context.Background() pool, err := db.Connect(ctx, dsn) if err != nil { log.Fatalf("db: %v", err) } defer pool.Close() auditLog := audit.NewLog(pool) tokenAuthorize := auditadmin.NewTokenAuthorizer(adminToken) authorize := func(_ context.Context, caller string) bool { return tokenAuthorize(caller) } handler := audit.NewExportHandler(auditLog, authorize) ingestHandler := audit.NewIngestHandler(auditLog, serviceToken) mux := http.NewServeMux() mux.HandleFunc("/audit/export", svcauth.CORS(allowedOrigins, "GET, OPTIONS", handler.Export)) mux.HandleFunc("/audit/ingest", ingestHandler.Ingest) mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) log.Printf("auditlog-devserver listening on %s", addr) log.Fatal(httpharden.ListenAndServe(addr, mux)) }