Files
break 5e552d99bc 收口审计治理与套餐任务进展
Constraint: 在线热修前必须保存当前迭代分支全部有效代码进展
Confidence: medium
Scope-risk: broad
Directive: 后续修改需保持审计事件与业务事务边界一致
Tested: git diff --cached --check
Not-tested: 未运行全量测试,提交用于切换分支前保存既有工作
2026-08-05 14:30:54 +08:00

92 lines
2.9 KiB
Go

package audit
import (
"context"
"crypto/sha256"
"fmt"
"strconv"
"gorm.io/gorm"
"github.com/break/junhong_cmp_fiber/pkg/constants"
pkgerrors "github.com/break/junhong_cmp_fiber/pkg/errors"
)
// TaskInput 描述导入、批购、失效或导出任务的安全审计事实。
type TaskInput struct {
EventID string
ActionCode string
Summary string
TaskID uint
TaskNo string
DisplayName string
Actor ActorInput
Source string
ScopeType string
ScopeID string
ScopeName string
Result string
ErrorCode string
ErrorSummary string
CorrelationID string
ParentEventID string
BatchTotal int
SuccessCount int
FailCount int
IdentitySnapshot map[string]any
BeforeData map[string]any
AfterData map[string]any
Metadata map[string]any
}
// WriteTask 将任务状态与批量统计写入对应的注册任务资源。
func (w *Writer) WriteTask(ctx context.Context, tx *gorm.DB, input TaskInput) error {
if w == nil || w.registry == nil {
return pkgerrors.New(pkgerrors.CodeInvalidStatus, "任务统一审计 Writer 未正确配置")
}
action, ok := w.registry.Action(input.ActionCode)
if !ok {
return pkgerrors.New(pkgerrors.CodeInvalidParam, "任务审计动作未注册")
}
if input.TaskNo == "" {
return pkgerrors.New(pkgerrors.CodeInvalidParam, "任务审计缺少稳定任务编号")
}
var taskID *string
if input.TaskID != 0 {
value := strconv.FormatUint(uint64(input.TaskID), 10)
taskID = &value
}
displayName := input.DisplayName
if displayName == "" {
displayName = input.TaskNo
}
return w.Append(ctx, tx, AppendInput{
EventID: input.EventID, ActionCode: input.ActionCode, Summary: input.Summary,
Actor: input.Actor, Source: input.Source,
ScopeType: input.ScopeType, ScopeID: input.ScopeID, ScopeName: input.ScopeName,
Result: input.Result, ErrorCode: input.ErrorCode, ErrorSummary: input.ErrorSummary,
CorrelationID: input.CorrelationID, ParentEventID: input.ParentEventID,
BatchTotal: input.BatchTotal, SuccessCount: input.SuccessCount, FailCount: input.FailCount,
Metadata: input.Metadata,
Resources: []ResourceInput{{
Type: action.PrimaryResource, ID: taskID, Key: input.TaskNo, DisplayName: displayName,
Relation: constants.AuditResourceRelationPrimary, Role: constants.AuditResourceRoleBatchTask,
IdentitySnapshot: input.IdentitySnapshot, BeforeData: input.BeforeData, AfterData: input.AfterData,
SubjectVisibility: constants.AuditSubjectInternalOnly,
}},
})
}
// TaskEventID 返回可重试任务阶段的稳定审计事件 ID。
func TaskEventID(resourceType string, taskID uint, phase string) string {
if taskID == 0 || phase == "" {
return ""
}
value := fmt.Sprintf("task:%s:%d:%s", resourceType, taskID, phase)
if len(value) <= 64 {
return value
}
digest := sha256.Sum256([]byte(value))
return fmt.Sprintf("task:%x", digest[:16])
}