mirror of
https://github.com/RuoJi6/ARTEX.git
synced 2026-10-28 01:03:50 +08:00
feat: 资产拦截接入执行链,新增任务级拦截/允许规则
在 agent 下发意图(add_intent)与插入资产(insert_assets)两处接入资产闸门;
并新增任务级规则(拦截 block + 允许 allow 白名单),创建任务时录入、任务详情
总览里可编辑。
- 匹配/执行(db/asset_intercept_match.go):MatchAssetInterceptRules 纯匹配
(exact/fuzzy 的 域名·IP·URL + CIDR,URL host 会拆出归类);EvaluateAssetGate
「先拦截后允许」闸门——命中拦截即禁止;未命中但存在启用的允许规则且都不命中→
不允许测试;无启用允许规则则不启用白名单。附单元测试。
- 执行点:add_intent 命中即不下发意图;insert_assets 命中即跳过 Upsert 及
AddAutoScope 副作用。均合并 全局∪任务级 规则。
- 任务级规则:表 task_intercept_rules(task_id FK CASCADE + action block/allow,
幂等 ALTER 补旧库);db/task_intercept.go 提供 List/Split/CRUD/事务插入;
创建任务随 intercept_rules 提交;CRUD 路由 /api/tasks/{id}/intercept-rules。
- 前端:新建任务抽屉多行录入(拦截/允许 + 类型,用 NativeSelect 避免 Sheet 内
下拉 portal 导致误关抽屉);任务详情总览新增规则管理卡片(增删改+启用开关)。
This commit is contained in:
1 parent
dfc9d2fa2e
commit
d5359e1f04
14 files changed
+1234
No files matched your search
@@ -680,6 +680,12 @@ func (s *Server) Handler() http.Handler {
|
||||
mux.HandleFunc("GET /api/tasks/{id}", s.getTask)
|
||||
mux.HandleFunc("PATCH /api/tasks/{id}", s.updateTaskMetadata)
|
||||
mux.HandleFunc("PATCH /api/tasks/{id}/category", s.updateTaskCategory)
|
||||
// 任务级资产拦截/允许规则
|
||||
mux.HandleFunc("GET /api/tasks/{id}/intercept-rules", s.taskInterceptListRules)
|
||||
mux.HandleFunc("POST /api/tasks/{id}/intercept-rules", s.taskInterceptCreateRule)
|
||||
mux.HandleFunc("PUT /api/tasks/{id}/intercept-rules/{rid}", s.taskInterceptUpdateRule)
|
||||
mux.HandleFunc("DELETE /api/tasks/{id}/intercept-rules/{rid}", s.taskInterceptDeleteRule)
|
||||
mux.HandleFunc("POST /api/tasks/{id}/intercept-rules/{rid}/toggle", s.taskInterceptToggleRule)
|
||||
mux.HandleFunc("POST /api/tasks/control/batch", s.controlTasksBatch)
|
||||
mux.HandleFunc("GET /api/task-archives", s.listTaskArchives)
|
||||
mux.HandleFunc("GET /api/task-archives/{id}", s.getTaskArchive)
|
||||
@@ -1427,6 +1433,8 @@ type createTaskReq struct {
|
||||
PlanHeartbeatSeconds int `json:"plan_heartbeat_seconds"` // planner 心跳触发间隔(秒);0/省略=默认600(10min);下限=默认=600,低于自动抬到600
|
||||
SeedFirstIntent *bool `json:"seed_first_intent,omitempty"` // 创建时直接下发一条种子意图(内容=描述+目标),让 worker 免等首轮 planner 直接开跑;省略/null=默认关闭,走标准先规划再执行。显式传 true 才开(CTF 常一 work 解决时可省掉开跑前的 planner 轮)。
|
||||
CoverageEnabled *bool `json:"coverage_enabled,omitempty"` // 资产覆盖度功能;省略/null=默认开(true)。false=关闭覆盖度计算/展示/自动累积范围+隐藏 add_task_scope/list_untested_assets。company 关联不受影响。
|
||||
// InterceptRules 任务级资产拦截/允许规则(创建时录入,存 task_intercept_rules,不进全局表)。
|
||||
InterceptRules []taskInterceptRuleReq `json:"intercept_rules,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Server) createTask(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -1473,11 +1481,17 @@ func (s *Server) createTask(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
req.CompanyIDs = companyIDs
|
||||
interceptRules, err := buildTaskInterceptRules(req.InterceptRules)
|
||||
if err != nil {
|
||||
writeErr(w, 400, "任务级拦截规则无效:"+err.Error())
|
||||
return
|
||||
}
|
||||
t, err := s.m.CreateTaskWithOptions(req.Description, req.Goal, db.TaskCreateOptions{
|
||||
Name: strings.TrimSpace(req.Name), CategoryID: req.CategoryID,
|
||||
SourceTaskIDs: sourceIDs, CompanyIDs: req.CompanyIDs, LLMProfileIDs: req.LLMProfileIDs,
|
||||
TimeoutSeconds: req.TimeoutSeconds, PlanHeartbeatSeconds: req.PlanHeartbeatSeconds,
|
||||
CoverageEnabled: req.CoverageEnabled,
|
||||
InterceptRules: interceptRules,
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, db.ErrTaskCategoryInvalid) || errors.Is(err, db.ErrTaskCategoryNotFound) {
|
||||
|
||||
Reference in new issue
Block a user