回应 Fasthei 复审(PR #53 CHANGES_REQUESTED): 1. 事件 payload 脱敏:swarmEventView 经 sanitizeSwarmPayload —— 递归剔除 secret_ref/credentials/token/api_key/private_key/access_key/password 及 plan/payload/ permission_manifest/env 大字段,再跑 RedactText 兜底。绝不下发 azkv:// secret_ref 或 sk-/Bearer(approval.requested 等 envelope 携带的凭据引用)。加 TestSanitizeSwarmPayload_*。 2. user 作用域:model.ListSwarmCallbackEventsAfter 增加 userID 参数 + WHERE user_id, controller 传入当前用户;防 runtime_swarm_id/deployment_id 碰撞或误写导致跨用户事件泄漏。 测试补 user 隔离用例。 3. stop 不伪造成功:移除「开关打开返回 accepted:true」路径;未启用→POLICY_REJECTED, 启用也→NOT_IMPLEMENTED(未转发运行时),直到 agent_swarm#2 冻结接上真实 stop。 文档 §5.2 同步(脱敏 / user 作用域 / stop 语义)。go build/vet 干净,controller+model 全回归通过。 Affects: Manager only(只读查询脱敏 + 写端点安全语义)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
51 lines
1.8 KiB
Go
51 lines
1.8 KiB
Go
package model
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// #45: events?after 游标 + user 作用域 —— 按 deployment_id/swarm_id 过滤,id>after 增量,oldest-first;
|
|
// 传入 userID 时按 user_id 收口(防跨用户泄漏,复审 #3)。
|
|
func TestListSwarmCallbackEventsAfter(t *testing.T) {
|
|
require.NoError(t, LOG_DB.Where("1 = 1").Delete(&AgentCallbackEvent{}).Error)
|
|
mk := func(eventID, uid, dep, swarm, etype string) {
|
|
_, err := InsertAgentCallbackEvent(&AgentCallbackEvent{
|
|
EventID: eventID, UserID: uid, DeploymentID: dep, SwarmID: swarm, EventType: etype,
|
|
})
|
|
require.NoError(t, err)
|
|
}
|
|
mk("e1", "7", "dep_A", "swarm_A", "deployment.status_changed")
|
|
mk("e2", "7", "dep_A", "swarm_A", "task.created")
|
|
mk("e3", "7", "dep_A", "swarm_A", "artifact.produced")
|
|
mk("e4", "7", "dep_B", "swarm_B", "task.created") // 另一个 run
|
|
mk("e5", "9", "dep_A", "swarm_A", "task.created") // 同 dep/swarm 但别的用户 → 不应泄漏给 user 7
|
|
|
|
// user 7 + dep_A:3 条(e5 属 user 9,被排除),oldest-first
|
|
all, err := ListSwarmCallbackEventsAfter("7", "dep_A", "swarm_A", 0, 100)
|
|
require.NoError(t, err)
|
|
require.Len(t, all, 3)
|
|
require.Equal(t, "e1", all[0].EventID)
|
|
for _, e := range all {
|
|
require.NotEqual(t, "e5", e.EventID, "不得返回别的用户的事件")
|
|
}
|
|
|
|
// 游标:after = 第一条 id → 其后 2 条
|
|
rest, err := ListSwarmCallbackEventsAfter("7", "dep_A", "swarm_A", all[0].Id, 100)
|
|
require.NoError(t, err)
|
|
require.Len(t, rest, 2)
|
|
require.Equal(t, "e2", rest[0].EventID)
|
|
|
|
// user 9 只看到自己的 e5
|
|
u9, err := ListSwarmCallbackEventsAfter("9", "dep_A", "swarm_A", 0, 100)
|
|
require.NoError(t, err)
|
|
require.Len(t, u9, 1)
|
|
require.Equal(t, "e5", u9[0].EventID)
|
|
|
|
// 空标识 → 空
|
|
none, err := ListSwarmCallbackEventsAfter("7", "", "", 0, 100)
|
|
require.NoError(t, err)
|
|
require.Empty(t, none)
|
|
}
|