1- import type { GatewayAuthorizerType } from '../../../../schema' ;
1+ import type { GatewayAuthorizerType , PolicyEngineMode } from '../../../../schema' ;
22import { GatewayNameSchema } from '../../../../schema' ;
33import { computeManagedOAuthCredentialName } from '../../../primitives/credential-utils' ;
44import {
@@ -20,6 +20,8 @@ import {
2020 AUTHORIZER_TYPE_OPTIONS ,
2121 EXCEPTION_LEVEL_ITEM_ID ,
2222 GATEWAY_STEP_LABELS ,
23+ NONE_SELECTION ,
24+ POLICY_ENGINE_MODE_OPTIONS ,
2325 SEMANTIC_SEARCH_ITEM_ID ,
2426} from './types' ;
2527import { useAddGatewayWizard } from './useAddGatewayWizard' ;
@@ -31,12 +33,19 @@ interface AddGatewayScreenProps {
3133 onExit : ( ) => void ;
3234 existingGateways : string [ ] ;
3335 unassignedTargets : string [ ] ;
36+ existingPolicyEngines : string [ ] ;
3437}
3538
3639const INITIAL_ADVANCED_SELECTED = [ SEMANTIC_SEARCH_ITEM_ID ] ;
3740
38- export function AddGatewayScreen ( { onComplete, onExit, existingGateways, unassignedTargets } : AddGatewayScreenProps ) {
39- const wizard = useAddGatewayWizard ( unassignedTargets . length ) ;
41+ export function AddGatewayScreen ( {
42+ onComplete,
43+ onExit,
44+ existingGateways,
45+ unassignedTargets,
46+ existingPolicyEngines,
47+ } : AddGatewayScreenProps ) {
48+ const wizard = useAddGatewayWizard ( unassignedTargets . length , existingPolicyEngines . length ) ;
4049
4150 // JWT config sub-step tracking (0=discoveryUrl, 1=audience, 2=clients, 3=scopes, 4=agentClientId, 5=agentClientSecret)
4251 const [ jwtSubStep , setJwtSubStep ] = useState ( 0 ) ;
@@ -64,10 +73,35 @@ export function AddGatewayScreen({ onComplete, onExit, existingGateways, unassig
6473 [ ]
6574 ) ;
6675
76+ // Policy engine sub-step: 0 = select engine, 1 = select mode
77+ // Reset when re-entering the step (e.g., after navigating back)
78+ const [ policyEngineSubStep , setPolicyEngineSubStep ] = useState ( 0 ) ;
79+ const [ selectedEngineName , setSelectedEngineName ] = useState ( '' ) ;
80+ React . useEffect ( ( ) => {
81+ if ( wizard . step === 'policy-engine' ) {
82+ setPolicyEngineSubStep ( 0 ) ;
83+ setSelectedEngineName ( '' ) ;
84+ }
85+ } , [ wizard . step ] ) ;
86+
87+ const policyEngineItems : SelectableItem [ ] = useMemo (
88+ ( ) => [
89+ { id : NONE_SELECTION , title : 'None' , description : 'No policy engine' } ,
90+ ...existingPolicyEngines . map ( name => ( { id : name , title : name } ) ) ,
91+ ] ,
92+ [ existingPolicyEngines ]
93+ ) ;
94+
95+ const policyEngineModeItems : SelectableItem [ ] = useMemo (
96+ ( ) => POLICY_ENGINE_MODE_OPTIONS . map ( o => ( { id : o . id , title : o . title , description : o . description } ) ) ,
97+ [ ]
98+ ) ;
99+
67100 const isNameStep = wizard . step === 'name' ;
68101 const isAuthorizerStep = wizard . step === 'authorizer' ;
69102 const isJwtConfigStep = wizard . step === 'jwt-config' ;
70103 const isIncludeTargetsStep = wizard . step === 'include-targets' ;
104+ const isPolicyEngineStep = wizard . step === 'policy-engine' ;
71105 const isAdvancedConfigStep = wizard . step === 'advanced-config' ;
72106 const isConfirmStep = wizard . step === 'confirm' ;
73107
@@ -87,6 +121,36 @@ export function AddGatewayScreen({ onComplete, onExit, existingGateways, unassig
87121 requireSelection : false ,
88122 } ) ;
89123
124+ const policyEngineNav = useListNavigation ( {
125+ items : policyEngineItems ,
126+ onSelect : item => {
127+ if ( item . id === NONE_SELECTION ) {
128+ wizard . skipPolicyEngine ( ) ;
129+ } else {
130+ setSelectedEngineName ( item . id ) ;
131+ setPolicyEngineSubStep ( 1 ) ;
132+ }
133+ } ,
134+ onExit : ( ) => {
135+ if ( policyEngineSubStep === 0 ) {
136+ wizard . goBack ( ) ;
137+ } else {
138+ setPolicyEngineSubStep ( 0 ) ;
139+ }
140+ } ,
141+ isActive : isPolicyEngineStep && policyEngineSubStep === 0 ,
142+ } ) ;
143+
144+ const policyEngineModeNav = useListNavigation ( {
145+ items : policyEngineModeItems ,
146+ onSelect : item => {
147+ wizard . setPolicyEngineConfig ( selectedEngineName , item . id as PolicyEngineMode ) ;
148+ setPolicyEngineSubStep ( 0 ) ;
149+ } ,
150+ onExit : ( ) => setPolicyEngineSubStep ( 0 ) ,
151+ isActive : isPolicyEngineStep && policyEngineSubStep === 1 ,
152+ } ) ;
153+
90154 const advancedNav = useMultiSelectNavigation ( {
91155 items : advancedConfigItems ,
92156 getId : item => item . id ,
@@ -172,7 +236,7 @@ export function AddGatewayScreen({ onComplete, onExit, existingGateways, unassig
172236 ? 'Space toggle · Enter confirm · Esc back'
173237 : isConfirmStep
174238 ? HELP_TEXT . CONFIRM_CANCEL
175- : isAuthorizerStep
239+ : isAuthorizerStep || isPolicyEngineStep
176240 ? HELP_TEXT . NAVIGATE_SELECT
177241 : HELP_TEXT . TEXT_INPUT ;
178242
@@ -234,6 +298,24 @@ export function AddGatewayScreen({ onComplete, onExit, existingGateways, unassig
234298 < Text dimColor > No unassigned targets available. Press Enter to continue.</ Text >
235299 ) ) }
236300
301+ { isPolicyEngineStep && policyEngineSubStep === 0 && (
302+ < WizardSelect
303+ title = "Select a policy engine"
304+ description = "Attach a Cedar policy engine to authorize tool calls on this gateway"
305+ items = { policyEngineItems }
306+ selectedIndex = { policyEngineNav . selectedIndex }
307+ />
308+ ) }
309+
310+ { isPolicyEngineStep && policyEngineSubStep === 1 && (
311+ < WizardSelect
312+ title = "Select enforcement mode"
313+ description = { `Policy engine: ${ selectedEngineName } ` }
314+ items = { policyEngineModeItems }
315+ selectedIndex = { policyEngineModeNav . selectedIndex }
316+ />
317+ ) }
318+
237319 { isAdvancedConfigStep && (
238320 < Box flexDirection = "column" >
239321 < Text bold > Advanced Configuration</ Text >
@@ -286,6 +368,12 @@ export function AddGatewayScreen({ onComplete, onExit, existingGateways, unassig
286368 } ,
287369 { label : 'Semantic Search' , value : wizard . config . enableSemanticSearch ? 'Enabled' : 'Disabled' } ,
288370 { label : 'Exception Level' , value : wizard . config . exceptionLevel === 'DEBUG' ? 'Debug' : 'None' } ,
371+ ...( wizard . config . policyEngineConfiguration
372+ ? [
373+ { label : 'Policy Engine' , value : wizard . config . policyEngineConfiguration . policyEngineName } ,
374+ { label : 'Enforcement Mode' , value : wizard . config . policyEngineConfiguration . mode } ,
375+ ]
376+ : [ ] ) ,
289377 ] }
290378 />
291379 ) }
0 commit comments