@@ -150,13 +150,15 @@ private static void AssignDeploymentType(Dictionary<object, object?> dictionary,
150150 applicableTo . Deployment = DeploymentApplicability . All ;
151151 else if ( deploymentType is string deploymentTypeString )
152152 {
153- var av = AppliesCollection . TryParse ( deploymentTypeString , diagnostics , out var a ) ? a : null ;
153+ var applies = AppliesCollection . TryParse ( deploymentTypeString , diagnostics , out var a ) ? a : null ;
154+ if ( applies is not null )
155+ ValidateApplicabilityCollection ( "ess" , applies , diagnostics ) ;
154156 applicableTo . Deployment = new DeploymentApplicability
155157 {
156- Ece = av ,
157- Eck = av ,
158- Ess = av ,
159- Self = av
158+ Ece = applies ,
159+ Eck = applies ,
160+ Ess = applies ,
161+ Self = applies
160162 } ;
161163 }
162164 else if ( deploymentType is Dictionary < object , object ? > deploymentDictionary )
@@ -193,12 +195,14 @@ private static void AssignServerless(Dictionary<object, object?> dictionary, App
193195 applicableTo . Serverless = ServerlessProjectApplicability . All ;
194196 else if ( serverless is string serverlessString )
195197 {
196- var av = AppliesCollection . TryParse ( serverlessString , diagnostics , out var a ) ? a : null ;
198+ var applies = AppliesCollection . TryParse ( serverlessString , diagnostics , out var a ) ? a : null ;
199+ if ( applies is not null )
200+ ValidateApplicabilityCollection ( "serverless" , applies , diagnostics ) ;
197201 applicableTo . Serverless = new ServerlessProjectApplicability
198202 {
199- Elasticsearch = av ,
200- Observability = av ,
201- Security = av
203+ Elasticsearch = applies ,
204+ Observability = applies ,
205+ Security = applies
202206 } ;
203207 }
204208 else if ( serverless is Dictionary < object , object ? > serverlessDictionary )
@@ -322,6 +326,9 @@ private static bool TryGetProductApplicability(Dictionary<object, object?> dicti
322326 return true ;
323327 }
324328
329+ private static readonly HashSet < string > VersionlessKeys =
330+ [ "ess" , "ech" , "serverless" , "elasticsearch" , "observability" , "security" ] ;
331+
325332 private static bool TryGetApplicabilityOverTime ( Dictionary < object , object ? > dictionary , string key , List < ( Severity , string ) > diagnostics ,
326333 out AppliesCollection ? availability )
327334 {
@@ -345,6 +352,15 @@ private static void ValidateApplicabilityCollection(string key, AppliesCollectio
345352 {
346353 var items = collection . ToList ( ) ;
347354
355+ // Rule: Versionless products cannot have version specifications
356+ if ( VersionlessKeys . Contains ( key ) )
357+ {
358+ if ( items . Any ( a => a . Version is not null && a . Version != AllVersionsSpec . Instance ) )
359+ diagnostics . Add ( ( Severity . Error ,
360+ $ "Can't specify a version for '{ key } ' because this product is not versioned. Remove the version, or use 'stack:' for version-specific requirements.") ) ;
361+ return ;
362+ }
363+
348364 // Rule: Only one version declaration per lifecycle
349365 var lifecycleGroups = items . GroupBy ( a => a . Lifecycle ) . ToList ( ) ;
350366 var lifecyclesWithMultipleVersions = lifecycleGroups
0 commit comments