diff --git a/apps/backend/internal/gateway/websocket/port_proxy_auth_test.go b/apps/backend/internal/gateway/websocket/port_proxy_auth_test.go index 1006b65f84..d9e94f037d 100644 --- a/apps/backend/internal/gateway/websocket/port_proxy_auth_test.go +++ b/apps/backend/internal/gateway/websocket/port_proxy_auth_test.go @@ -673,8 +673,16 @@ func TestPortProxyCapabilityRoundTrip(t *testing.T) { t.Fatal("capability validated for the wrong port") } - // Tampered payload: rejected. - tampered := cap[:len(cap)-2] + "00" + // Tampered payload: rejected. Flip the final byte to a value guaranteed to + // differ from the original, rather than a fixed literal: the mac suffix is + // hex, so appending a fixed "00" is a ~1/256 no-op whenever the genuine + // suffix already ends that way, which flaked this test in CI. + lastIdx := len(cap) - 1 + replacement := byte('0') + if cap[lastIdx] == '0' { + replacement = '1' + } + tampered := cap[:lastIdx] + string(replacement) if _, ok := handler.validateCapability(tampered, "sess-1", 5173); ok { t.Fatal("tampered capability validated") } diff --git a/apps/backend/internal/plugins/host_data_wire_test.go b/apps/backend/internal/plugins/host_data_wire_test.go index 1e5635ed50..dc53d9cc9b 100644 --- a/apps/backend/internal/plugins/host_data_wire_test.go +++ b/apps/backend/internal/plugins/host_data_wire_test.go @@ -437,6 +437,9 @@ func TestPluginHostData_Wire_WorkflowSteps_OnEnterActionTypes(t *testing.T) { OnEnter: []wfmodels.OnEnterAction{ {Type: wfmodels.OnEnterAutoStartAgent, Config: map[string]interface{}{"agent_profile_id": "profile-1"}}, {Type: wfmodels.OnEnterRunCodeReview}, + // Unknown types must remain available to plugin callers so they can + // apply their own forward-compatible handling. + {Type: wfmodels.OnEnterActionType("future_action")}, }, }, }, @@ -456,7 +459,7 @@ func TestPluginHostData_Wire_WorkflowSteps_OnEnterActionTypes(t *testing.T) { require.Len(t, steps, 2) require.Equal(t, "step-work", steps[0].ID) - require.Equal(t, []string{"auto_start_agent", "run_code_review"}, steps[0].OnEnterActionTypes) + require.Equal(t, []string{"auto_start_agent", "run_code_review", "future_action"}, steps[0].OnEnterActionTypes) require.Equal(t, "step-todo", steps[1].ID) require.Nil(t, steps[1].OnEnterActionTypes) diff --git a/apps/backend/pkg/pluginsdk/data_types.go b/apps/backend/pkg/pluginsdk/data_types.go index 70edceb1a9..c38c53740b 100644 --- a/apps/backend/pkg/pluginsdk/data_types.go +++ b/apps/backend/pkg/pluginsdk/data_types.go @@ -509,11 +509,8 @@ type WorkflowStep struct { WIPLimit int32 // 0 means unlimited AgentProfileID string // OnEnterActionTypes lists the on_enter action types configured on this - // step, as authored. This lists what is configured, not a guarantee that - // every listed type executes on every transition path. The ordinary move - // path handles auto_start_agent, configure_session, enable_plan_mode, - // set_session_mode and reset_agent_context. Other action types can run only - // on applicable workflow-engine paths. Config maps are deliberately not + // step, as authored. A type appearing here means it is configured, not a + // guarantee of when or whether it fires. Config maps are deliberately not // exposed. Nil when the step has no on_enter actions, never an empty // non-nil slice. Callers must ignore action types they do not recognize. OnEnterActionTypes []string