feat(gateway): 敏感操作审计日志(T4.B)

- store.AuditLog 表(sundynix_audit_log) + AppendAudit/ListAudit
- middleware.Audit(db):只审计变更类(POST/PUT/DELETE/PATCH),收尾 best-effort
  落库(独立超时 ctx,失败静默不拖垮主流程);挂管理组 + prompt 激活/撤销 + HITL 审批
- GET /api/v1/admin/audit:倒序审计流(limit/offset 翻页)
- live:PUT pricing / POST prompts/deactivate 留痕(actor/path/status/ip),GET 不记
- DEPTH_ROADMAP T4.B:overview + audit 打勾

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-07-02 09:19:52 +08:00
parent 30e80c0eed
commit 16c67dcb4f
7 changed files with 122 additions and 9 deletions
@@ -5,6 +5,7 @@ import (
"context"
"encoding/json"
"net/http"
"strconv"
"strings"
"time"
@@ -16,6 +17,34 @@ import (
"github.com/sundynix/sundynix-shared/secrets"
)
// AuditList: GET /api/v1/admin/audit?limit=&offset= —— 敏感操作审计流(倒序,供运维溯源)。
func (h *Handler) AuditList(c *gin.Context) {
limit, offset := 50, 0
if v := c.Query("limit"); v != "" {
if n, err := strconv.Atoi(v); err == nil {
limit = n
}
}
if v := c.Query("offset"); v != "" {
if n, err := strconv.Atoi(v); err == nil {
offset = n
}
}
rows, err := h.db.ListAudit(c.Request.Context(), limit, offset)
if err != nil {
c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
return
}
out := make([]gin.H, 0, len(rows))
for _, a := range rows {
out = append(out, gin.H{
"id": a.ID, "actor": a.Actor, "action": a.Action, "route": a.Route,
"path": a.Path, "status": a.Status, "ip": a.IP, "detail": a.Detail, "at": a.CreatedAt,
})
}
c.JSON(http.StatusOK, gin.H{"logs": out})
}
// AdminOverview: GET /api/v1/admin/overview —— 管理端系统级聚合(控制塔口径)。
// 区别于 stats/overview(桌面端个人工作台):这里一律系统级——全平台用户/任务/评测/
// 模型配置态/提示词控制面态/服务健康。Task/Eval 表无 owner 即全量;用户/KB/Doc 走全局计数。