@@ -532,6 +532,8 @@ export default function DashboardPage() {
532532 const tab = config . rememberLastTab ? viewState . lastActiveTab : config . defaultTab ;
533533 if ( tab === "tracked" && ! config . enableTracking ) return "issues" ;
534534 if ( tab === "jiraAssigned" && ! config . jira ?. enabled ) return "issues" ;
535+ if ( tab === "actions" && ! config . enableActions ) return "issues" ;
536+ if ( ! config . enableActions && ! isBuiltinTab ( tab ) && config . customTabs . find ( ( t ) => t . id === tab ) ?. baseType === "actions" ) return "issues" ;
535537 // Validate custom tab still exists; fall back to "issues" if stale
536538 if ( ! isBuiltinTab ( tab ) && ! config . customTabs . some ( ( t ) => t . id === tab ) ) return "issues" ;
537539 return tab ;
@@ -542,6 +544,10 @@ export default function DashboardPage() {
542544 function handleTabChange ( tab : TabId ) {
543545 // Reject invalid tab IDs to prevent persisting stale state
544546 if ( ! isBuiltinTab ( tab ) && ! config . customTabs . some ( ( t ) => t . id === tab ) ) return ;
547+ if ( ! config . enableActions ) {
548+ if ( tab === "actions" ) return ;
549+ if ( ! isBuiltinTab ( tab ) && config . customTabs . find ( ( t ) => t . id === tab ) ?. baseType === "actions" ) return ;
550+ }
545551 setActiveTab ( tab ) ;
546552 updateViewState ( { lastActiveTab : tab } ) ;
547553 }
@@ -569,6 +575,15 @@ export default function DashboardPage() {
569575 }
570576 } ) ;
571577
578+ // Redirect away from Actions tab (or actions-based custom tab) when Actions is disabled
579+ createEffect ( ( ) => {
580+ if ( ! config . enableActions ) {
581+ const tab = activeTab ( ) ;
582+ const isActionsTab = tab === "actions" || ( ! isBuiltinTab ( tab ) && config . customTabs . find ( ( t ) => t . id === tab ) ?. baseType === "actions" ) ;
583+ if ( isActionsTab ) handleTabChange ( "issues" ) ;
584+ }
585+ } ) ;
586+
572587 // Clear stale Jira data when auth is cleared (e.g., 401 during token refresh)
573588 createEffect ( ( ) => {
574589 if ( ! isJiraAuthenticated ( ) ) {
@@ -792,6 +807,7 @@ export default function DashboardPage() {
792807 const currentTabId = activeTab ( ) ;
793808 const result : Record < string , { issues : typeof dashboardData . issues ; pullRequests : typeof dashboardData . pullRequests ; workflowRuns : typeof dashboardData . workflowRuns } > = { } ;
794809 for ( const tab of config . customTabs ) {
810+ if ( ! config . enableActions && tab . baseType === "actions" ) continue ;
795811 if ( ! tab . exclusive && tab . id !== currentTabId ) continue ;
796812 const matchesScope = buildTabScopeMatcher ( tab ) ;
797813 result [ tab . id ] = {
@@ -866,6 +882,7 @@ export default function DashboardPage() {
866882 const users = allUsers ( ) ;
867883 const customCounts : Record < string , number > = { } ;
868884 for ( const tab of config . customTabs ) {
885+ if ( ! config . enableActions && tab . baseType === "actions" ) continue ;
869886 // customTabData skips non-exclusive inactive tabs (perf optimization),
870887 // so compute scope on demand for tabs absent from the memo.
871888 let data = customTabData ( ) [ tab . id ] ;
@@ -968,9 +985,9 @@ export default function DashboardPage() {
968985 pullRequests : visiblePullRequests ( ) . filter ( ( p ) =>
969986 isPrVisible ( p , { ignoredIds : ignoredPRs , globalFilter : builtinFilter } )
970987 ) . length ,
971- actions : visibleWorkflowRuns ( ) . filter ( ( w ) =>
988+ ... ( config . enableActions ? { actions : visibleWorkflowRuns ( ) . filter ( ( w ) =>
972989 isRunVisible ( w , { ignoredIds : ignoredRuns , showPrRuns : viewState . showPrRuns , globalFilter : builtinFilter } )
973- ) . length ,
990+ ) . length } : { } ) ,
974991 ...( config . enableTracking ? { tracked : viewState . trackedItems . length } : { } ) ,
975992 ...( config . jira ?. enabled ? ( ( ) => {
976993 const f = viewState . tabFilters . jiraAssigned ;
@@ -1053,6 +1070,14 @@ export default function DashboardPage() {
10531070 { defer : true }
10541071 ) ) ;
10551072
1073+ // When Actions is disabled, clear stale workflowRuns from the store so memos
1074+ // computing against empty workflowRuns don't process cached data (SEC-004).
1075+ createEffect ( ( ) => {
1076+ if ( ! config . enableActions ) {
1077+ setDashboardData ( produce ( ( d ) => { d . workflowRuns = [ ] ; } ) ) ;
1078+ }
1079+ } ) ;
1080+
10561081 // Push dashboard data into the MCP relay snapshot on each full refresh.
10571082 // Tracks lastRefreshedAt (always updated alongside data arrays in pollFetch).
10581083 // Hot poll updates are intentionally excluded — relay reflects full-refresh data only.
@@ -1064,6 +1089,7 @@ export default function DashboardPage() {
10641089 issues : d . issues ,
10651090 pullRequests : d . pullRequests ,
10661091 workflowRuns : d . workflowRuns ,
1092+ enableActions : config . enableActions ,
10671093 lastUpdatedAt : Date . now ( ) ,
10681094 } ) ;
10691095 } ) ;
@@ -1092,8 +1118,9 @@ export default function DashboardPage() {
10921118 onTabChange = { handleTabChange }
10931119 counts = { tabCounts ( ) }
10941120 enableTracking = { config . enableTracking }
1121+ enableActions = { config . enableActions }
10951122 enableJira = { ! ! config . jira ?. enabled }
1096- customTabs = { config . customTabs . map ( ( t ) => ( { id : t . id , name : t . name } ) ) }
1123+ customTabs = { config . customTabs . filter ( ( t ) => config . enableActions || t . baseType !== "actions" ) . map ( ( t ) => ( { id : t . id , name : t . name } ) ) }
10971124 onAddTab = { ( ) => setShowCustomTabModal ( true ) }
10981125 onEditTab = { ( id ) => { setEditingTabId ( id ) ; setShowCustomTabModal ( true ) ; } }
10991126 />
@@ -1156,7 +1183,7 @@ export default function DashboardPage() {
11561183 siteUrl = { config . jira ?. siteUrl ?? "" }
11571184 />
11581185 </ Match >
1159- < Match when = { activeTab ( ) === "actions" } >
1186+ < Match when = { activeTab ( ) === "actions" && config . enableActions } >
11601187 < ActionsTab
11611188 workflowRuns = { visibleWorkflowRuns ( ) }
11621189 loading = { dashboardData . loading }
@@ -1237,6 +1264,7 @@ export default function DashboardPage() {
12371264 editingTab = { editingTab ( ) }
12381265 availableOrgs = { [ ...new Set ( config . selectedRepos . map ( ( r ) => r . owner ) ) ] }
12391266 availableRepos = { config . selectedRepos }
1267+ enableActions = { config . enableActions }
12401268 />
12411269 </ div >
12421270
0 commit comments