mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-11 00:14:00 +00:00
feat(multiplayer): wire structured event logging into server routes
server/observability existed fully unit-tested but was imported by nothing outside its own package -- no HTTP handler ever called it, so its credential redaction protected zero real log output. Wire it into Service via an optional Log field (nil-safe, so every existing Service literal keeps compiling unchanged) and call it from the two workload-authenticated server routes -- register and result -- at every outcome: unauthorized, rejected, conflict and success. Wire cmd/control-plane to actually emit those events as JSON lines on stderr. Add a secret canary test that drives both routes end to end with realistic bearer-token and result-nonce values and asserts neither literal secret appears anywhere in what Service.Log actually received -- a stronger claim than the existing observability unit test, which only proves redact() strips a synthetic value under a denylisted key name. redact() is still key-name-based, not content-based: a future call site that logs a secret under an unlisted key name would not be caught by this test or by redact() itself, only by the same discipline applied here of never putting raw request/token bytes into Fields. Queue, proposal and assignment mutation routes are not wired yet.
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/cosmic-clash/cosmic-clash/server/api"
|
||||
"github.com/cosmic-clash/cosmic-clash/server/migrations"
|
||||
"github.com/cosmic-clash/cosmic-clash/server/observability"
|
||||
"github.com/cosmic-clash/cosmic-clash/server/store"
|
||||
_ "github.com/jackc/pgx/v5/stdlib"
|
||||
"github.com/redis/go-redis/v9"
|
||||
@@ -90,9 +91,21 @@ func newAPIHandler(db *sql.DB, indexes ...api.CandidateIndex) http.Handler {
|
||||
CandidateIndex: candidateIndex,
|
||||
ProbeRecorder: store.PostgresQueue{DB: db},
|
||||
Now: func() time.Time { return time.Now().UTC() },
|
||||
Log: logEvent,
|
||||
}).Handler()
|
||||
}
|
||||
|
||||
// logEvent writes one credential-safe structured event per line to stderr.
|
||||
// Best-effort: a logging failure must never fail or block the request it
|
||||
// describes, so encode errors are swallowed rather than surfaced.
|
||||
func logEvent(event observability.Event) {
|
||||
payload, err := observability.Encode(event)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, string(payload))
|
||||
}
|
||||
|
||||
func envOrDefault(name, fallback string) string {
|
||||
if value := os.Getenv(name); value != "" {
|
||||
return value
|
||||
|
||||
Reference in New Issue
Block a user