@@ -2855,19 +2855,52 @@ class GatewayCreate(BaseModelWithConfigDict):
28552855 auth_query_param_key : Optional [str ] = Field (
28562856 None ,
28572857 description = "Query parameter name for authentication (e.g., 'api_key', 'tavilyApiKey')" ,
2858- pattern = r"^[a-zA-Z_][a-zA-Z0-9_\-]*$" ,
28592858 )
28602859 auth_query_param_value : Optional [SecretStr ] = Field (
28612860 None ,
28622861 description = "Query parameter value (API key). Stored encrypted." ,
28632862 )
28642863
2864+ @field_validator ("auth_query_param_key" )
2865+ @classmethod
2866+ def validate_auth_query_param_key (cls , v : Optional [str ]) -> Optional [str ]:
2867+ """Validate query param key format only if provided and non-empty.
2868+
2869+ Args:
2870+ v: Query parameter key to validate
2871+
2872+ Returns:
2873+ The validated query parameter key
2874+
2875+ Raises:
2876+ ValueError: If the key format is invalid
2877+ """
2878+ if v is not None and v != "" :
2879+ if not re .match (r"^[a-zA-Z_][a-zA-Z0-9_\-]*$" , v ):
2880+ raise ValueError ("Query parameter key must start with a letter or underscore, " "followed by letters, numbers, underscores, or hyphens" )
2881+ return v
2882+
28652883 # Adding `auth_value` as an alias for better access post-validation
28662884 auth_value : Optional [str ] = Field (None , validate_default = True )
28672885
28682886 # One time auth - do not store the auth in gateway flag
28692887 one_time_auth : Optional [bool ] = Field (default = False , description = "The authentication should be used only once and not stored in the gateway" )
28702888
2889+ @field_validator ("auth_type" , mode = "before" )
2890+ @classmethod
2891+ def normalize_auth_type (cls , v : Any ) -> Optional [str ]:
2892+ """Normalize auth_type: convert string 'none' or 'None' to None.
2893+
2894+ Args:
2895+ v: The auth_type value (may be string "none" or "None")
2896+
2897+ Returns:
2898+ None if v is "none" or "None", otherwise returns v unchanged
2899+ """
2900+ if isinstance (v , str ) and v .lower () == "none" :
2901+ return None
2902+ return v
2903+
28712904 tags : Optional [List [Union [str , Dict [str , str ]]]] = Field (default_factory = list , description = "Tags for categorizing the gateway" )
28722905
28732906 # Team scoping fields for resource organization
@@ -3141,7 +3174,11 @@ def _process_auth_fields(info: ValidationInfo) -> Optional[str]:
31413174 # Validation is handled by model_validator
31423175 return None
31433176
3144- raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, or query_param." )
3177+ # Handle no authentication (None or already normalized from "none")
3178+ if auth_type is None :
3179+ return None
3180+
3181+ raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, query_param, or none." )
31453182
31463183 @model_validator (mode = "after" )
31473184 def validate_query_param_auth (self ) -> "GatewayCreate" :
@@ -3205,20 +3242,53 @@ class GatewayUpdate(BaseModelWithConfigDict):
32053242 # Adding `auth_value` as an alias for better access post-validation
32063243 auth_value : Optional [str ] = Field (None , validate_default = True )
32073244
3245+ @field_validator ("auth_type" , mode = "before" )
3246+ @classmethod
3247+ def normalize_auth_type (cls , v : Any ) -> Optional [str ]:
3248+ """Normalize auth_type: convert string 'none' or 'None' to None.
3249+
3250+ Args:
3251+ v: The auth_type value (may be string "none" or "None")
3252+
3253+ Returns:
3254+ None if v is "none" or "None", otherwise returns v unchanged
3255+ """
3256+ if isinstance (v , str ) and v .lower () == "none" :
3257+ return None
3258+ return v
3259+
32083260 # OAuth 2.0 configuration
32093261 oauth_config : Optional [Dict [str , Any ]] = Field (None , description = "OAuth 2.0 configuration including grant_type, client_id, encrypted client_secret, URLs, and scopes" )
32103262
32113263 # Query Parameter Authentication (INSECURE)
32123264 auth_query_param_key : Optional [str ] = Field (
32133265 None ,
32143266 description = "Query parameter name for authentication" ,
3215- pattern = r"^[a-zA-Z_][a-zA-Z0-9_\-]*$" ,
32163267 )
32173268 auth_query_param_value : Optional [SecretStr ] = Field (
32183269 None ,
32193270 description = "Query parameter value (API key)" ,
32203271 )
32213272
3273+ @field_validator ("auth_query_param_key" )
3274+ @classmethod
3275+ def validate_auth_query_param_key (cls , v : Optional [str ]) -> Optional [str ]:
3276+ """Validate query param key format only if provided and non-empty.
3277+
3278+ Args:
3279+ v: Query parameter key to validate
3280+
3281+ Returns:
3282+ The validated query parameter key
3283+
3284+ Raises:
3285+ ValueError: If the key format is invalid
3286+ """
3287+ if v is not None and v != "" :
3288+ if not re .match (r"^[a-zA-Z_][a-zA-Z0-9_\-]*$" , v ):
3289+ raise ValueError ("Query parameter key must start with a letter or underscore, " "followed by letters, numbers, underscores, or hyphens" )
3290+ return v
3291+
32223292 # One time auth - do not store the auth in gateway flag
32233293 one_time_auth : Optional [bool ] = Field (default = False , description = "The authentication should be used only once and not stored in the gateway" )
32243294
@@ -3456,7 +3526,11 @@ def _process_auth_fields(info: ValidationInfo) -> Optional[str]:
34563526 # Validation is handled by model_validator
34573527 return None
34583528
3459- raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, or query_param." )
3529+ # Handle no authentication (None or already normalized from "none")
3530+ if auth_type is None :
3531+ return None
3532+
3533+ raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, query_param, or none." )
34603534
34613535 @model_validator (mode = "after" )
34623536 def validate_query_param_auth (self ) -> "GatewayUpdate" :
@@ -4653,6 +4727,22 @@ class A2AAgentCreate(BaseModel):
46534727
46544728 # Adding `auth_value` as an alias for better access post-validation
46554729 auth_value : Optional [str ] = Field (None , validate_default = True )
4730+
4731+ @field_validator ("auth_type" , mode = "before" )
4732+ @classmethod
4733+ def normalize_auth_type (cls , v : Any ) -> Optional [str ]:
4734+ """Normalize auth_type: convert string 'none' or 'None' to None.
4735+
4736+ Args:
4737+ v: The auth_type value (may be string "none" or "None")
4738+
4739+ Returns:
4740+ None if v is "none" or "None", otherwise returns v unchanged
4741+ """
4742+ if isinstance (v , str ) and v .lower () == "none" :
4743+ return None
4744+ return v
4745+
46564746 tags : List [str ] = Field (default_factory = list , description = "Tags for categorizing the agent" )
46574747
46584748 # Team scoping fields
@@ -4901,7 +4991,11 @@ def _process_auth_fields(info: ValidationInfo) -> Optional[str]:
49014991 # Validation is handled by model_validator
49024992 return None
49034993
4904- raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, or query_param." )
4994+ # Handle no authentication (None or already normalized from "none")
4995+ if auth_type is None :
4996+ return None
4997+
4998+ raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, query_param, or none." )
49054999
49065000 @model_validator (mode = "after" )
49075001 def validate_query_param_auth (self ) -> "A2AAgentCreate" :
@@ -4992,6 +5086,24 @@ class A2AAgentUpdate(BaseModelWithConfigDict):
49925086 version : Optional [str ] = Field (default = None , description = "Agent version for UAID generation" )
49935087 uaid_native_id_override : Optional [str ] = Field (None , description = "Override nativeId in UAID for cross-gateway routing (defaults to endpoint_url if not provided)" )
49945088
5089+ @field_validator ("auth_type" )
5090+ @classmethod
5091+ def normalize_auth_type (cls , v : Any ) -> Optional [str ]:
5092+ """Normalize auth_type by converting string 'none' or 'None' to Python None.
5093+
5094+ This allows the UI to send "none" as a string value which gets converted
5095+ to Python None for proper handling throughout the system.
5096+
5097+ Args:
5098+ v: The auth_type value (can be str or None)
5099+
5100+ Returns:
5101+ The normalized auth_type (None if input was "none"/"None", otherwise unchanged)
5102+ """
5103+ if isinstance (v , str ) and v .lower () == "none" :
5104+ return None
5105+ return v
5106+
49955107 @field_validator ("tags" )
49965108 @classmethod
49975109 def validate_tags (cls , v : Optional [List [str ]]) -> Optional [List [str ]]:
@@ -5229,7 +5341,11 @@ def _process_auth_fields(info: ValidationInfo) -> Optional[str]:
52295341 # Validation is handled by model_validator
52305342 return None
52315343
5232- raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, or query_param." )
5344+ # Handle no authentication (None or already normalized from "none")
5345+ if auth_type is None :
5346+ return None
5347+
5348+ raise ValueError ("Invalid 'auth_type'. Must be one of: basic, bearer, oauth, authheaders, query_param, or none." )
52335349
52345350 @model_validator (mode = "after" )
52355351 def validate_query_param_auth (self ) -> "A2AAgentUpdate" :
0 commit comments