@@ -2857,19 +2857,52 @@ class GatewayCreate(BaseModelWithConfigDict):
28572857 auth_query_param_key : Optional [str ] = Field (
28582858 None ,
28592859 description = "Query parameter name for authentication (e.g., 'api_key', 'tavilyApiKey')" ,
2860- pattern = r"^[a-zA-Z_][a-zA-Z0-9_\-]*$" ,
28612860 )
28622861 auth_query_param_value : Optional [SecretStr ] = Field (
28632862 None ,
28642863 description = "Query parameter value (API key). Stored encrypted." ,
28652864 )
28662865
2866+ @field_validator ("auth_query_param_key" )
2867+ @classmethod
2868+ def validate_auth_query_param_key (cls , v : Optional [str ]) -> Optional [str ]:
2869+ """Validate query param key format only if provided and non-empty.
2870+
2871+ Args:
2872+ v: Query parameter key to validate
2873+
2874+ Returns:
2875+ The validated query parameter key
2876+
2877+ Raises:
2878+ ValueError: If the key format is invalid
2879+ """
2880+ if v is not None and v != "" :
2881+ if not re .match (r"^[a-zA-Z_][a-zA-Z0-9_\-]*$" , v ):
2882+ raise ValueError ("Query parameter key must start with a letter or underscore, " "followed by letters, numbers, underscores, or hyphens" )
2883+ return v
2884+
28672885 # Adding `auth_value` as an alias for better access post-validation
28682886 auth_value : Optional [str ] = Field (None , validate_default = True )
28692887
28702888 # One time auth - do not store the auth in gateway flag
28712889 one_time_auth : Optional [bool ] = Field (default = False , description = "The authentication should be used only once and not stored in the gateway" )
28722890
2891+ @field_validator ("auth_type" , mode = "before" )
2892+ @classmethod
2893+ def normalize_auth_type (cls , v : Any ) -> Optional [str ]:
2894+ """Normalize auth_type: convert string 'none' or 'None' to None.
2895+
2896+ Args:
2897+ v: The auth_type value (may be string "none" or "None")
2898+
2899+ Returns:
2900+ None if v is "none" or "None", otherwise returns v unchanged
2901+ """
2902+ if isinstance (v , str ) and v .lower () == "none" :
2903+ return None
2904+ return v
2905+
28732906 tags : Optional [List [Union [str , Dict [str , str ]]]] = Field (default_factory = list , description = "Tags for categorizing the gateway" )
28742907
28752908 # Team scoping fields for resource organization
@@ -3143,7 +3176,11 @@ def _process_auth_fields(info: ValidationInfo) -> Optional[str]:
31433176 # Validation is handled by model_validator
31443177 return None
31453178
3146- raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, or query_param." )
3179+ # Handle no authentication (None or already normalized from "none")
3180+ if auth_type is None :
3181+ return None
3182+
3183+ raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, query_param, or none." )
31473184
31483185 @model_validator (mode = "after" )
31493186 def validate_query_param_auth (self ) -> "GatewayCreate" :
@@ -3207,6 +3244,21 @@ class GatewayUpdate(BaseModelWithConfigDict):
32073244 # Adding `auth_value` as an alias for better access post-validation
32083245 auth_value : Optional [str ] = Field (None , validate_default = True )
32093246
3247+ @field_validator ("auth_type" , mode = "before" )
3248+ @classmethod
3249+ def normalize_auth_type (cls , v : Any ) -> Optional [str ]:
3250+ """Normalize auth_type: convert string 'none' or 'None' to None.
3251+
3252+ Args:
3253+ v: The auth_type value (may be string "none" or "None")
3254+
3255+ Returns:
3256+ None if v is "none" or "None", otherwise returns v unchanged
3257+ """
3258+ if isinstance (v , str ) and v .lower () == "none" :
3259+ return None
3260+ return v
3261+
32103262 # OAuth 2.0 configuration
32113263 oauth_config : Optional [Dict [str , Any ]] = Field (
32123264 None , description = "OAuth 2.0 configuration including grant_type, client_id, encrypted client_secret, URLs, scopes, audience (for Atlassian/Auth0), and resource (RFC 8707)"
@@ -3216,13 +3268,31 @@ class GatewayUpdate(BaseModelWithConfigDict):
32163268 auth_query_param_key : Optional [str ] = Field (
32173269 None ,
32183270 description = "Query parameter name for authentication" ,
3219- pattern = r"^[a-zA-Z_][a-zA-Z0-9_\-]*$" ,
32203271 )
32213272 auth_query_param_value : Optional [SecretStr ] = Field (
32223273 None ,
32233274 description = "Query parameter value (API key)" ,
32243275 )
32253276
3277+ @field_validator ("auth_query_param_key" )
3278+ @classmethod
3279+ def validate_auth_query_param_key (cls , v : Optional [str ]) -> Optional [str ]:
3280+ """Validate query param key format only if provided and non-empty.
3281+
3282+ Args:
3283+ v: Query parameter key to validate
3284+
3285+ Returns:
3286+ The validated query parameter key
3287+
3288+ Raises:
3289+ ValueError: If the key format is invalid
3290+ """
3291+ if v is not None and v != "" :
3292+ if not re .match (r"^[a-zA-Z_][a-zA-Z0-9_\-]*$" , v ):
3293+ raise ValueError ("Query parameter key must start with a letter or underscore, " "followed by letters, numbers, underscores, or hyphens" )
3294+ return v
3295+
32263296 # One time auth - do not store the auth in gateway flag
32273297 one_time_auth : Optional [bool ] = Field (default = False , description = "The authentication should be used only once and not stored in the gateway" )
32283298
@@ -3460,7 +3530,11 @@ def _process_auth_fields(info: ValidationInfo) -> Optional[str]:
34603530 # Validation is handled by model_validator
34613531 return None
34623532
3463- raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, or query_param." )
3533+ # Handle no authentication (None or already normalized from "none")
3534+ if auth_type is None :
3535+ return None
3536+
3537+ raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, query_param, or none." )
34643538
34653539 @model_validator (mode = "after" )
34663540 def validate_query_param_auth (self ) -> "GatewayUpdate" :
@@ -4661,6 +4735,22 @@ class A2AAgentCreate(BaseModel):
46614735
46624736 # Adding `auth_value` as an alias for better access post-validation
46634737 auth_value : Optional [str ] = Field (None , validate_default = True )
4738+
4739+ @field_validator ("auth_type" , mode = "before" )
4740+ @classmethod
4741+ def normalize_auth_type (cls , v : Any ) -> Optional [str ]:
4742+ """Normalize auth_type: convert string 'none' or 'None' to None.
4743+
4744+ Args:
4745+ v: The auth_type value (may be string "none" or "None")
4746+
4747+ Returns:
4748+ None if v is "none" or "None", otherwise returns v unchanged
4749+ """
4750+ if isinstance (v , str ) and v .lower () == "none" :
4751+ return None
4752+ return v
4753+
46644754 tags : List [str ] = Field (default_factory = list , description = "Tags for categorizing the agent" )
46654755
46664756 # Team scoping fields
@@ -4909,7 +4999,11 @@ def _process_auth_fields(info: ValidationInfo) -> Optional[str]:
49094999 # Validation is handled by model_validator
49105000 return None
49115001
4912- raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, or query_param." )
5002+ # Handle no authentication (None or already normalized from "none")
5003+ if auth_type is None :
5004+ return None
5005+
5006+ raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, query_param, or none." )
49135007
49145008 @model_validator (mode = "after" )
49155009 def validate_query_param_auth (self ) -> "A2AAgentCreate" :
@@ -5002,6 +5096,24 @@ class A2AAgentUpdate(BaseModelWithConfigDict):
50025096 version : Optional [str ] = Field (default = None , description = "Agent version for UAID generation" )
50035097 uaid_native_id_override : Optional [str ] = Field (None , description = "Override nativeId in UAID for cross-gateway routing (defaults to endpoint_url if not provided)" )
50045098
5099+ @field_validator ("auth_type" )
5100+ @classmethod
5101+ def normalize_auth_type (cls , v : Any ) -> Optional [str ]:
5102+ """Normalize auth_type by converting string 'none' or 'None' to Python None.
5103+
5104+ This allows the UI to send "none" as a string value which gets converted
5105+ to Python None for proper handling throughout the system.
5106+
5107+ Args:
5108+ v: The auth_type value (can be str or None)
5109+
5110+ Returns:
5111+ The normalized auth_type (None if input was "none"/"None", otherwise unchanged)
5112+ """
5113+ if isinstance (v , str ) and v .lower () == "none" :
5114+ return None
5115+ return v
5116+
50055117 @field_validator ("tags" )
50065118 @classmethod
50075119 def validate_tags (cls , v : Optional [List [str ]]) -> Optional [List [str ]]:
@@ -5239,7 +5351,11 @@ def _process_auth_fields(info: ValidationInfo) -> Optional[str]:
52395351 # Validation is handled by model_validator
52405352 return None
52415353
5242- raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, or query_param." )
5354+ # Handle no authentication (None or already normalized from "none")
5355+ if auth_type is None :
5356+ return None
5357+
5358+ raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, query_param, or none." )
52435359
52445360 @model_validator (mode = "after" )
52455361 def validate_query_param_auth (self ) -> "A2AAgentUpdate" :
0 commit comments