feat(workflow): namespace task keys without breaking old instances

Published manifests now use bd_/pm_/tm_/sw_ prefixes so workflows cannot share a doc id. Frozen instances keep the old keys; lookup, templates, and duty checks treat the two names as the same task.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weichen
2026-09-19 10:50:25 +00:00
co-authored by Cursor
parent 2a0f8b4549
commit dba8139d56
36 changed files with 544 additions and 190 deletions
@@ -88,7 +88,7 @@ func TestPG_ActivateOfficialWorkflowRuntimeMetadata(t *testing.T) {
SELECT dti.executor_key
FROM project_doc_task_instances dti
JOIN project_stage_instances si ON si.id = dti.stage_instance_id
WHERE si.workflow_instance_id = $1 AND dti.task_key = 'intake'
WHERE si.workflow_instance_id = $1 AND dti.task_key IN ('intake', 'bd_intake')
`, activated.Instance.ID).Scan(&executorKey)
if err != nil {
t.Fatalf("query runtime metadata: %v", err)
@@ -96,7 +96,7 @@ func TestPG_ActivationAndStageAdvance(t *testing.T) {
}
for i := range plan.Stages {
for j := range plan.Stages[i].DocTasks {
if plan.Stages[i].DocTasks[j].TaskKey == "intake" {
if plan.Stages[i].DocTasks[j].TaskKey == "intake" || plan.Stages[i].DocTasks[j].TaskKey == "bd_intake" {
plan.Stages[i].DocTasks[j].Duties = projectinstance.DocDuty{
AuthorUserID: 2, ReviewerUserID: 3, ApproverUserID: 4,
}
+17 -8
View File
@@ -2,15 +2,17 @@ package projectinstance
import (
"context"
"chat-agent-system/internal/workflowdef"
)
// StageAccess 用户在某项目实例下可访问的阶段与文档任务范围。
type StageAccess struct {
Restricted bool `json:"restricted"`
ActiveStageKey string `json:"active_stage_key,omitempty"`
AllowedStageKeys map[string]bool `json:"allowed_stage_keys,omitempty"`
AllowedTaskKeys map[string]bool `json:"allowed_task_keys,omitempty"`
ViewableTaskKeys map[string]bool `json:"viewable_task_keys,omitempty"`
Restricted bool `json:"restricted"`
ActiveStageKey string `json:"active_stage_key,omitempty"`
AllowedStageKeys map[string]bool `json:"allowed_stage_keys,omitempty"`
AllowedTaskKeys map[string]bool `json:"allowed_task_keys,omitempty"`
ViewableTaskKeys map[string]bool `json:"viewable_task_keys,omitempty"`
}
// ResolveStageAccess 基于治理实例与三权指派计算阶段 ABAC 范围。
@@ -129,7 +131,14 @@ func (a *StageAccess) TaskKeyAllowed(taskKey string) bool {
if a == nil || !a.Restricted {
return true
}
return a.AllowedTaskKeys[taskKey]
return mapHasTaskKey(a.AllowedTaskKeys, taskKey)
}
func mapHasTaskKey(keys map[string]bool, taskKey string) bool {
if keys[taskKey] || keys[workflowdef.CanonicalTaskKey(taskKey)] || keys[workflowdef.ImplementationTaskKey(taskKey)] {
return true
}
return false
}
// TaskKeyVisible 判断文档是否对项目成员可见(view 豁免阶段收窄)。
@@ -138,9 +147,9 @@ func (a *StageAccess) TaskKeyVisible(taskKey string) bool {
return true
}
if len(a.ViewableTaskKeys) == 0 {
return a.AllowedTaskKeys[taskKey]
return mapHasTaskKey(a.AllowedTaskKeys, taskKey)
}
return a.ViewableTaskKeys[taskKey]
return mapHasTaskKey(a.ViewableTaskKeys, taskKey)
}
// StageKeyAllowed 判断 stage_key 是否在允许范围内。