refactor(server): audit.WriteOrLog wrapper; migrate 13 sites (T5)

Add audit.WriteOrLog: a one-line wrapper around Write that logs at
Warn and swallows the error, matching the package contract that
audit failures must not break user-facing operations.

Migrate the 13 call sites across 7 files in internal/api/ from the
3-line "if err != nil { logger.Warn(...) }" shape to a single call.
audit.Write stays exported for tests + any future caller that
needs strict semantics.

Adds three tests: success (no log), failure-via-closed-pool (Warn
record with action+err keys), and nil-logger (no panic). Tests
skip when MINSTREL_TEST_DATABASE_URL is unset, matching the
existing harness convention.
This commit is contained in:
2026-05-07 21:33:14 -04:00
parent 49218e5231
commit 965df28127
9 changed files with 103 additions and 46 deletions
+3 -7
View File
@@ -196,14 +196,10 @@ func (h *handlers) handleRegister(w http.ResponseWriter, r *http.Request) {
if user.IsAdmin {
auditMeta["first_admin"] = true
}
if err := audit.Write(r.Context(), h.pool, user.ID, user.ID, audit.ActionRegister, auditMeta); err != nil {
h.logger.Warn("register: audit write failed", "err", err)
}
audit.WriteOrLog(r.Context(), h.pool, h.logger, user.ID, user.ID, audit.ActionRegister, auditMeta)
if usedInviteToken != "" {
if err := audit.Write(r.Context(), h.pool, user.ID, user.ID, audit.ActionInviteRedeem,
map[string]any{"token": usedInviteToken}); err != nil {
h.logger.Warn("register: audit invite-redeem write failed", "err", err)
}
audit.WriteOrLog(r.Context(), h.pool, h.logger, user.ID, user.ID, audit.ActionInviteRedeem,
map[string]any{"token": usedInviteToken})
}
writeJSON(w, http.StatusOK, LoginResponse{