@@ -17,6 +17,10 @@ func setIFCLabel(r *mcp.CallToolResult, label ifc.SecurityLabel) {
1717 r .Meta ["ifc" ] = label
1818}
1919
20+ func shouldAttachIFCLabel (ctx context.Context , deps ToolDependencies , r * mcp.CallToolResult ) bool {
21+ return r != nil && ! r .IsError && deps .IsFeatureEnabled (ctx , FeatureFlagIFCLabels )
22+ }
23+
2024// attachStaticIFCLabel attaches a fixed IFC label to a successful tool result
2125// when IFC labels are enabled. It is used by tools whose label does not depend
2226// on any repository visibility lookup (e.g. security alerts, global
@@ -25,7 +29,7 @@ func setIFCLabel(r *mcp.CallToolResult, label ifc.SecurityLabel) {
2529// Error results are left untouched, and the label is omitted entirely when the
2630// IFC feature flag is disabled.
2731func attachStaticIFCLabel (ctx context.Context , deps ToolDependencies , r * mcp.CallToolResult , label ifc.SecurityLabel ) * mcp.CallToolResult {
28- if r == nil || r . IsError || ! deps . IsFeatureEnabled (ctx , FeatureFlagIFCLabels ) {
32+ if ! shouldAttachIFCLabel (ctx , deps , r ) {
2933 return r
3034 }
3135 setIFCLabel (r , label )
@@ -49,7 +53,7 @@ func attachRepoVisibilityIFCLabel(
4953 r * mcp.CallToolResult ,
5054 labelFn func (isPrivate bool ) ifc.SecurityLabel ,
5155) * mcp.CallToolResult {
52- if r == nil || r . IsError || ! deps . IsFeatureEnabled (ctx , FeatureFlagIFCLabels ) {
56+ if ! shouldAttachIFCLabel (ctx , deps , r ) {
5357 return r
5458 }
5559 isPrivate , err := FetchRepoIsPrivate (ctx , client , owner , repo )
@@ -86,7 +90,7 @@ func attachRepoVisibilityIFCLabelLazy(
8690 r * mcp.CallToolResult ,
8791 labelFn func (isPrivate bool ) ifc.SecurityLabel ,
8892) * mcp.CallToolResult {
89- if r == nil || r . IsError || ! deps . IsFeatureEnabled (ctx , FeatureFlagIFCLabels ) {
93+ if ! shouldAttachIFCLabel (ctx , deps , r ) {
9094 return r
9195 }
9296 client , err := deps .GetClient (ctx )
@@ -97,26 +101,39 @@ func attachRepoVisibilityIFCLabelLazy(
97101}
98102
99103// attachJoinedIFCLabel attaches an IFC label computed by joining a set of
100- // per-item visibilities (true == private for repositories, true == public for
101- // gists) when IFC labels are enabled. joinFn is the lattice join for the
102- // relevant item kind (e.g. ifc.LabelSearchIssues or ifc.LabelGistList). The
103- // visibility slice is cheap to build from an already-fetched response, so
104- // callers may construct it unconditionally and let this helper own the
105- // feature-flag gate.
104+ // per-item visibilities (true == private) when IFC labels are enabled. joinFn
105+ // is the lattice join for the relevant item kind (e.g. ifc.LabelSearchIssues or
106+ // ifc.LabelProjectList). The visibility slice is cheap to build from an
107+ // already-fetched response, so callers may construct it unconditionally and let
108+ // this helper own the feature-flag gate.
106109func attachJoinedIFCLabel (
107110 ctx context.Context ,
108111 deps ToolDependencies ,
109112 r * mcp.CallToolResult ,
110113 visibilities []bool ,
111114 joinFn func ([]bool ) ifc.SecurityLabel ,
112115) * mcp.CallToolResult {
113- if r == nil || r . IsError || ! deps . IsFeatureEnabled (ctx , FeatureFlagIFCLabels ) {
116+ if ! shouldAttachIFCLabel (ctx , deps , r ) {
114117 return r
115118 }
116119 setIFCLabel (r , joinFn (visibilities ))
117120 return r
118121}
119122
123+ func attachProjectVisibilityIFCLabel (
124+ ctx context.Context ,
125+ deps ToolDependencies ,
126+ r * mcp.CallToolResult ,
127+ isPrivate bool ,
128+ labelFn func (isPrivate bool ) ifc.SecurityLabel ,
129+ ) * mcp.CallToolResult {
130+ if ! shouldAttachIFCLabel (ctx , deps , r ) {
131+ return r
132+ }
133+ setIFCLabel (r , labelFn (isPrivate ))
134+ return r
135+ }
136+
120137// newRepoVisibilityIFCLabeler returns a closure that attaches a repo-visibility
121138// IFC label to a tool result, for handlers that have several return paths and
122139// want to label each one. The returned function owns the feature-flag gate (so
0 commit comments