feat(events): register intent.plan contracts and table owners

Freeze the three fact events, intentflow allowlist, and plan table ownership so later units cannot invent producers or write paths outside app/intentflow.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weichen
2026-09-15 16:20:19 +00:00
co-authored by Cursor
parent bdccb4dbfe
commit aefb1e45a6
4 changed files with 71 additions and 10 deletions
+30
View File
@@ -65,6 +65,7 @@ imports:
- app/docflow
- app/docnotify
- app/docproject
- app/intentflow
- app/stageflow
- app/uow
- artifactvault
@@ -113,6 +114,10 @@ imports:
- docquery
- docrevision
- events
app/intentflow:
- app/uow
- events
- intent
app/uow: []
app/stageflow:
- bizdev
@@ -304,6 +309,12 @@ table_owners:
- dataset
dataset_destroy_requests:
- dataset
intent_plans:
- app/intentflow
intent_plan_steps:
- app/intentflow
intent_plan_decisions:
- app/intentflow
path_owners:
output.md:
@@ -348,6 +359,15 @@ event_producers:
- taskrun
fav.artifact_staged:
- app/docflow
intent.plan.awaiting_input:
- app/intentflow
- events
intent.plan.step_changed:
- app/intentflow
- events
intent.plan.completed:
- app/intentflow
- events
event_consumers:
outbox.notify:
@@ -371,6 +391,15 @@ event_consumers:
- notify
fav.artifact_staged:
- fav
intent.plan.awaiting_input:
- projection
- notify
intent.plan.step_changed:
- projection
- notify
intent.plan.completed:
- projection
- notify
unwrap_owners:
- docgov
@@ -380,6 +409,7 @@ unwrap_owners:
- events
- artifactvault
- ctxmgr
- app/intentflow
exceptions:
- kind: sql_write
+2 -2
View File
@@ -14,8 +14,8 @@ import (
const internalPrefix = "chat-agent-system/internal/"
var (
sqlWriteRe = regexp.MustCompile(`(?is)\b(INSERT\s+INTO|UPDATE|DELETE\s+FROM)\s+([a-zA-Z_][a-zA-Z0-9_]*)`)
eventNameRe = regexp.MustCompile(`document\.[a-z0-9_.]+`)
sqlWriteRe = regexp.MustCompile(`(?is)\b(INSERT\s+INTO|UPDATE|DELETE\s+FROM)\s+([a-zA-Z_][a-zA-Z0-9_]*)`)
eventNameRe = regexp.MustCompile(`(?:document|intent\.plan)\.[a-z0-9_.]+`)
)
type fileClass int
+14 -8
View File
@@ -12,14 +12,17 @@ const (
ConsumerWorkflowAdvance = "workflow_advance"
ConsumerFAV = "fav"
EventCandidateReady = "document.agent_candidate_ready"
EventVersionCommitted = "document.agent_version_committed"
EventDownstreamImpact = "document.downstream_impact_detected"
EventChangeReportDegraded = "document.change_report_degraded"
EventApproved = "document.approved"
EventTaskRunCompleted = "taskrun.completed"
EventTaskRunCancelled = "taskrun.cancelled"
EventFAVArtifactStaged = "fav.artifact_staged"
EventCandidateReady = "document.agent_candidate_ready"
EventVersionCommitted = "document.agent_version_committed"
EventDownstreamImpact = "document.downstream_impact_detected"
EventChangeReportDegraded = "document.change_report_degraded"
EventApproved = "document.approved"
EventTaskRunCompleted = "taskrun.completed"
EventTaskRunCancelled = "taskrun.cancelled"
EventFAVArtifactStaged = "fav.artifact_staged"
EventIntentPlanAwaiting = "intent.plan.awaiting_input"
EventIntentPlanStepChanged = "intent.plan.step_changed"
EventIntentPlanCompleted = "intent.plan.completed"
)
// Contract is the static allowlist row for one event name.
@@ -44,6 +47,9 @@ func StaticContracts() []Contract {
{EventName: EventTaskRunCompleted, SchemaVersion: 1, Enabled: true, Producers: []string{"taskrun"}, Consumers: []string{ConsumerNotify}, PayloadFields: []string{"run_id"}},
{EventName: EventTaskRunCancelled, SchemaVersion: 1, Enabled: true, Producers: []string{"taskrun"}, Consumers: []string{ConsumerNotify}, PayloadFields: []string{"run_id"}},
{EventName: EventFAVArtifactStaged, SchemaVersion: 1, Enabled: false, Producers: []string{"app/docflow"}, Consumers: []string{ConsumerFAV}, PayloadFields: []string{"doc_id", "snapshot_id"}},
{EventName: EventIntentPlanAwaiting, SchemaVersion: 1, Enabled: true, Producers: []string{"app/intentflow", "events"}, Consumers: []string{ConsumerProjection, ConsumerNotify}, PayloadFields: []string{"plan_id", "revision", "status", "environment", "project_id", "user_id", "session_id", "summary_ref"}},
{EventName: EventIntentPlanStepChanged, SchemaVersion: 1, Enabled: true, Producers: []string{"app/intentflow", "events"}, Consumers: []string{ConsumerProjection, ConsumerNotify}, PayloadFields: []string{"plan_id", "revision", "step_id", "status", "environment", "project_id", "user_id", "session_id", "summary_ref"}},
{EventName: EventIntentPlanCompleted, SchemaVersion: 1, Enabled: true, Producers: []string{"app/intentflow", "events"}, Consumers: []string{ConsumerProjection, ConsumerNotify}, PayloadFields: []string{"plan_id", "revision", "status", "environment", "project_id", "user_id", "session_id", "summary_ref"}},
}
}
+25
View File
@@ -49,6 +49,31 @@ func TestManifestJSONIncludesDisabledFAV(t *testing.T) {
}
}
func TestIntentPlanContractsOmitSensitivePayload(t *testing.T) {
forbidden := []string{"prompt", "slots", "permissions", "result", "input"}
for _, c := range StaticContracts() {
if !strings.HasPrefix(c.EventName, "intent.plan.") {
continue
}
if !c.Enabled {
t.Fatalf("%s must be enabled for U4 append", c.EventName)
}
if !containsName(c.Producers, "app/intentflow") || !containsName(c.Producers, "events") {
t.Fatalf("%s producers = %v", c.EventName, c.Producers)
}
if !containsName(c.Consumers, ConsumerProjection) || !containsName(c.Consumers, ConsumerNotify) {
t.Fatalf("%s consumers = %v", c.EventName, c.Consumers)
}
for _, field := range c.PayloadFields {
for _, bad := range forbidden {
if field == bad {
t.Fatalf("%s payload contains %s", c.EventName, field)
}
}
}
}
}
func TestRegistryParityWithYAML(t *testing.T) {
root := moduleRoot(t)
b, err := archtest.LoadBoundaries(archtest.DefaultBoundariesPath(root))