补齐证书任务创建人归属

传递已认证操作者上下文,关联证书任务审计,并同步四份整改清单进度。
This commit is contained in:
xuans 2026-09-30 02:40:41 +08:00
parent 4cf9fb6076
commit 5fecd05d46
8 changed files with 100 additions and 5 deletions

View File

@ -65,7 +65,8 @@ func (w *certificateTaskWorkflow) run(ctx context.Context, id, taskType, stage s
task := repository.Task{
ID: domain.NewID(), DomainID: id, TaskType: taskType,
Status: "running", Stage: stage, Message: "正在执行证书工作流",
StartedAt: &started, CreatedAt: started,
OperatorID: repository.TaskOperatorFromContext(ctx),
StartedAt: &started, CreatedAt: started,
}
if err := w.tasks.CreateTask(ctx, task); err != nil {
return result, err
@ -84,7 +85,8 @@ func (w *certificateTaskWorkflow) run(ctx context.Context, id, taskType, stage s
auditErr := w.audit.CreateAuditLog(finishCtx, repository.AuditLog{
TaskID: task.ID,
Action: taskType, ResourceType: "domain", ResourceID: id,
Status: status, Message: message,
OperatorID: task.OperatorID,
Status: status, Message: message,
})
if auditErr != nil {
status, message = certificateTaskOutcome(result, auditErr)
@ -99,7 +101,8 @@ func (w *certificateTaskWorkflow) run(ctx context.Context, id, taskType, stage s
if err := w.audit.CreateAuditLog(taskCtx, repository.AuditLog{
TaskID: task.ID,
Action: taskType, ResourceType: "domain", ResourceID: id,
Status: "running", Message: "开始执行证书工作流",
OperatorID: task.OperatorID,
Status: "running", Message: "开始执行证书工作流",
}); err != nil {
return result, err
}

View File

@ -92,6 +92,40 @@ func TestCertificateTasksRecordSuccessFailureAndCancellation(t *testing.T) {
}
}
func TestCertificateTasksRecordOperatorFromWorkflowContext(t *testing.T) {
w, a := newCertificateTaskFixture(t)
ctx := repository.WithTaskOperator(t.Context(), "operator-1")
_, err := w.run(ctx, "task-domain", "certificate_validate", "certificate_validate", 1, 0, func(context.Context, string) (CertificateWorkflowResult, error) {
return CertificateWorkflowResult{}, nil
})
if err != nil {
t.Fatalf("带操作者的证书任务执行失败:%v", err)
}
items, err := a.Tasks.ListTasks(t.Context(), "task-domain", 10)
if err != nil || len(items) != 1 || items[0].OperatorID != "operator-1" {
t.Fatalf("任务创建人记录错误:%+v %v", items, err)
}
var operators []string
rows, err := a.Database.DB.QueryContext(t.Context(), "SELECT operator_id FROM audit_logs WHERE task_id = ? ORDER BY created_at, id", items[0].ID)
if err != nil {
t.Fatalf("读取任务审计失败:%v", err)
}
defer rows.Close()
for rows.Next() {
var operator string
if err := rows.Scan(&operator); err != nil {
t.Fatalf("读取任务审计操作者失败:%v", err)
}
operators = append(operators, operator)
}
if err := rows.Err(); err != nil {
t.Fatalf("遍历任务审计失败:%v", err)
}
if len(operators) != 2 || operators[0] != "operator-1" || operators[1] != "operator-1" {
t.Fatalf("任务审计创建人记录错误:%v", operators)
}
}
func TestCertificateTasksKeepRetriesInOneTask(t *testing.T) {
w, a := newCertificateTaskFixture(t)
calls := 0

View File

@ -242,10 +242,11 @@ func (s *Server) unregisterTaskCancel(taskID string) {
}
func (s *Server) taskWorkflowContext(c *gin.Context) context.Context {
return repository.WithTaskCancellationHooks(c.Request.Context(), repository.TaskCancellationHooks{
ctx := repository.WithTaskCancellationHooks(c.Request.Context(), repository.TaskCancellationHooks{
Register: s.registerTaskCancel,
Unregister: s.unregisterTaskCancel,
})
return repository.WithTaskOperator(ctx, s.currentOperatorID(c))
}
func taskRepositoryUnavailable(tasks repository.TaskRepository) bool {

View File

@ -1,6 +1,9 @@
package repository
import "context"
import (
"context"
"strings"
)
type TaskCancellationHooks struct {
Register func(string, context.CancelFunc)
@ -8,6 +11,7 @@ type TaskCancellationHooks struct {
}
type taskCancellationHooksContextKey struct{}
type taskOperatorContextKey struct{}
func WithTaskCancellationHooks(ctx context.Context, hooks TaskCancellationHooks) context.Context {
return context.WithValue(ctx, taskCancellationHooksContextKey{}, hooks)
@ -20,3 +24,14 @@ func TaskCancellationHooksFromContext(ctx context.Context) (TaskCancellationHook
}
return hooks, true
}
// WithTaskOperator 将当前已认证操作者绑定到任务工作流上下文。
func WithTaskOperator(ctx context.Context, operatorID string) context.Context {
return context.WithValue(ctx, taskOperatorContextKey{}, strings.TrimSpace(operatorID))
}
// TaskOperatorFromContext 读取任务工作流的创建人;后台调度任务没有操作者时返回空字符串。
func TaskOperatorFromContext(ctx context.Context) string {
operatorID, _ := ctx.Value(taskOperatorContextKey{}).(string)
return strings.TrimSpace(operatorID)
}

View File

@ -2,6 +2,17 @@
## 最新执行摘要(2026-09-29 继续开发)
总体验收位置继续保持 **P0-03 完成,待复审**;本轮继续先开发、后统一测试,不进入远端生产验收。
- [x] 已为证书任务工作流增加操作者上下文;HTTP 发起的证书部署、导入、恢复、校验任务会记录当前创建人。
- [x] 已将证书任务开始与完成审计关联到同一创建人;后台续期调度没有登录操作者时保持为空,避免伪造身份。
- [x] 已新增创建人及审计归属回归测试;`go test ./internal/app ./internal/httpapi ./internal/repository` 和 `git diff --check` 已通过。
- [~] P0-10 其余任务的崩溃恢复、DNS 验证任务、批量部署结果及跨入口归属仍需继续审查。
- [ ] 三数据库矩阵、浏览器清缓存、密码 SSH、远端部署和生产验收仍未执行。
- [!] 不升级总体验收位置;当前仍为 **P0-03 完成,待复审**,本轮没有新增 `[✓]` 复审通过项。
## 最新执行摘要(2026-09-29 继续开发)
本轮继续保持总体验收位置为 **P0-03 完成,待复审**,没有新增复审通过项;当前仍按“先开发、后统一测试”执行。
- [x] 已提交证书导入、恢复、校验任务入口接入代码:`b899751`;远程推送因仓库认证失败未成功,未阻塞本地继续开发。

View File

@ -2,6 +2,17 @@
## 最新任务批次(2026-09-29 继续开发)
总体验收仍保持 **P0-03 完成,待复审**;本批只补齐 P0-10 任务创建人和审计归属,不代表生产部署验收通过。
- [x] HTTP 证书工作流上下文已传递当前已认证操作者;证书部署、导入、恢复、校验任务不再默认丢失创建人。
- [x] 任务开始、完成审计已写入任务创建人;后台续期无认证操作者时保持空值,不使用请求身份以外的信息填充。
- [x] 创建人归属回归测试已通过;专项测试为 `go test ./internal/app ./internal/httpapi ./internal/repository`,并通过 `git diff --check`。
- [~] P0-10 仍需继续审查 DNS 验证任务、批量部署 `partial_success`、崩溃恢复、重试和其他同步长耗时入口。
- [ ] P0-12、三数据库实库矩阵、浏览器、密码 SSH、远端部署和生产验收尚未执行。
- [!] 总体验收位置不变:**P0-03 完成,待复审**。
## 最新任务批次(2026-09-29 继续开发)
总体验收仍保持 **P0-03 完成,待复审**;本批代码已完成,统一测试已完成本地自动化部分。
- [x] 证书导入、恢复、校验入口已接入应用任务工作流,提交 `b899751`。

View File

@ -2,6 +2,16 @@
## 最新进度摘要(2026-09-29 继续开发)
**总体验收位置仍为 P0-03 完成,待复审。** 本轮只推进 P0-10 任务归属链,不把局部代码或专项测试结果视为整项复审通过。
- [x] 任务工作流从认证请求上下文读取创建人,并写入证书任务的 `operator_id`。
- [x] 任务开始和完成审计使用任务自身的创建人;后台调度任务继续保留空操作者边界。
- [x] 创建人和审计归属专项测试通过;尚未执行三数据库、浏览器、密码 SSH、远端部署和生产门禁。
- [~] P0-10 其余任务链、DNS 验证、批量部署、崩溃恢复、重试幂等和 P0-12 仍未完成。
- [!] 不新增 `[✓]` 复审通过项,总体验收继续停在 **P0-03 完成,待复审**。
## 最新进度摘要(2026-09-29 继续开发)
**总体验收位置仍为 P0-03 完成,待复审。** 本轮只推进 P0-10 任务工作流,不把局部代码完成或专项测试通过视为生产验收通过。
- [x] 证书导入、恢复、校验任务入口接入应用层,提交 `b899751`。

View File

@ -2,6 +2,16 @@
## 最新执行与补充约束(2026-09-29 继续开发)
总体验收位置继续保持 **P0-03 完成,待复审**。本轮补充 P0-10 任务归属不变量,不改变原始 44 项范围,也不提前进入生产验收。
- [x] 证书工作流通过上下文记录已认证请求的任务创建人,后台调度任务不得伪造登录操作者。
- [x] 证书任务开始、完成审计必须与任务的 `operator_id` 一致;任务资源范围仍由域名项目归属服务端确定。
- [x] 创建人归属专项测试通过;完整后端、三数据库实库、浏览器、密码 SSH、远端部署和生产门禁仍未完成。
- [~] DNS 验证任务、批量部署结果、崩溃恢复、重试和其他长耗时入口仍需继续补齐。
- [!] 本轮不得将总体验收升级为复审通过,当前仍为 **P0-03 完成,待复审**。
## 最新执行与补充约束(2026-09-29 继续开发)
总体验收位置继续保持 **P0-03 完成,待复审**。本轮开发不改变原始 44 项范围,也不提前进入生产验收。
- [x] 证书导入、恢复、校验已接入统一任务工作流,提交 `b899751`。