package gateway import ( "context" "net/http" "time" "git.yeij.top/AskaEth/Cyrene_v2/internal/auth" ) // auditClaims records an admin write with the caller identity read from the // request context (populated by auth.Authorize). It is the who/what/when/result // audit trail required for admin operations; the "主代理代审" user-facing note is // the frontend's job, not the gateway's. func (s *Server) auditClaims(r *http.Request, what, result string) { who := "anonymous" if claims, ok := auth.ClaimsFromContext(r.Context()); ok { who = claims.Sub + ":" + string(claims.Role) } s.audit(r.Context(), who, what, result) } // audit emits one structured audit record on the gateway logger and persists it to // the configured AuditStore (falling back to an in-memory store when none is // injected). A persist failure is logged but never blocks the admin write, so a // broken audit store cannot take down the audit trail's primary job. func (s *Server) audit(ctx context.Context, who, what, result string) { s.log.Info("admin audit", "who", who, "what", what, "when", time.Now().UTC().Format(time.RFC3339), "result", result, ) if s.obs != nil && s.obs.audit != nil { if err := s.obs.audit.Append(ctx, who, what, result, time.Now()); err != nil { s.log.Error("admin audit persist", "err", err, "what", what) } } }