Files
3c4288ddea feat(issues): always allow creating custom statuses (MUL-6643) (#7503)
* feat(issues): always allow creating custom statuses (MUL-6643)

Custom issue statuses shipped behind a one-way rollout gate: creating one
minted a status key an older pod could not interpret, so creation stayed
closed until the whole fleet could read one. The fleet is there and the
feature has been dogfooded, so the gate goes away — creation now answers
to workspace role (owner/admin) alone.

The key keeps being published as `true` on /api/config. Installed desktop
clients v0.4.30-v0.4.32 gate their "New status" button on that decision
and fail closed on absence, which would hide an affordance the server now
accepts. Same compat treatment as settings_resource_labels.

Co-authored-by: multica-agent <[email protected]>

* fix(issues): keep custom_issue_statuses unpublished for old clients (MUL-6643)

Publishing the key as an always-on compat decision had it backwards.
v0.4.30 shipped the custom-status UI without the four fixes that landed
in v0.4.31: cards render in the wrong board column (MUL-6409), the
timeline glyph loses the status identity (MUL-6413), built-in colors are
wrong (MUL-6440), and the catalog does not sync over realtime (MUL-6458).

Those clients gate their "New status" button on this key and fail closed
on absence, so NOT publishing it is what keeps a client that cannot
render the result from producing one. Same shape as the deliberately
unpublished desktop_hang_stack_capture key.

Clients from v0.4.33 read no flag at all, so they get the button on
update and the key never has to be published again.

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: J <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-08-24 19:02:47 +08:00

38 lines
1002 B
Go

package handler
import (
"testing"
"github.com/multica-ai/multica/server/internal/featureflags"
"github.com/multica-ai/multica/server/pkg/featureflag"
)
func withComposioMCPAppsFlag(t *testing.T, h *Handler, enabled bool) {
withFeatureFlag(t, h, featureflags.ComposioMCPApps, enabled)
}
func withPluginsV1Flag(t *testing.T, h *Handler, enabled bool) {
withFeatureFlag(t, h, featureflags.PluginsV1, enabled)
}
func withFeatureFlag(t *testing.T, h *Handler, key string, enabled bool) {
t.Helper()
provider := featureflag.NewStaticProvider()
provider.Set(key, featureflag.Rule{Default: enabled})
flags := featureflag.NewService(provider)
origHandlerFlags := h.FeatureFlags
h.FeatureFlags = flags
var origTaskFlags *featureflag.Service
if h.TaskService != nil {
origTaskFlags = h.TaskService.FeatureFlags
h.TaskService.FeatureFlags = flags
}
t.Cleanup(func() {
h.FeatureFlags = origHandlerFlags
if h.TaskService != nil {
h.TaskService.FeatureFlags = origTaskFlags
}
})
}