Problem
Rule types have no declared, up-front way to say "I require an implementation of API Y." Today, provider-specific scoping either:
- doesn't exist (rule type just assumes a shape and may fail/behave oddly against a provider that doesn't implement the API it needs), or
- gets pushed into CEL profile selectors, which evaluate per-entity and return
ErrEvaluationSkipped on mismatch. This isn't silent — it shows up in evaluation status/history — but it does mean every non-matching entity generates skip noise instead of the rule type simply not applying.
This is currently blocking osps-ac-03-02 (branch deletion protection), since GitHub and GitLab branch-protection semantics/APIs differ enough that a single generic rule type can't cleanly cover both.
Framing (important distinction)
The field declares "this rule type requires API Y," not "this rule type is for provider class X." In some cases (git, OCI) API Y is standardized and multiple providers can implement it. In other cases the API is specific to a single company/provider class (GitHub management API, Docker management API, various cloud provider APIs) — that looks like "this rule is for provider class X," but it's really "only this provider
currently implements API Y." The distinction matters for how the field should be understood and extended as more providers implement overlapping APIs.
Proposed direction
Add a provider_traits field to the rule type schema, checked by rtengine before evaluation — the same way entity-type gating already works today — rather than relying on profile selectors. This reuses the existing ProviderType/CanImplement trait vocabulary (pkg/providers/v1/providers.go), so a rule type declares which trait(s) it needs (e.g. github-api, git, oci), not a specific named provider registration — a single rule type can apply across multiple provider instances that implement the same trait.
Sub-issues
Context
Design discussed with @evankanderson — reusing the existing ProviderType/CanImplement trait pattern rather than introducing a new capability abstraction, since GitHub/GitLab branch protection differ enough in shape that a boolean "supports X" capability flag would hide more than it clarifies. Naming settled on provider_traits over required_traits since the latter doesn't make clear who/what is doing the requiring (rule type vs. entity vs. policy). Open to a better name before this ships if one comes up.
Problem
Rule types have no declared, up-front way to say "I require an implementation of API Y." Today, provider-specific scoping either:
ErrEvaluationSkippedon mismatch. This isn't silent — it shows up in evaluation status/history — but it does mean every non-matching entity generates skip noise instead of the rule type simply not applying.This is currently blocking
osps-ac-03-02(branch deletion protection), since GitHub and GitLab branch-protection semantics/APIs differ enough that a single generic rule type can't cleanly cover both.Framing (important distinction)
The field declares "this rule type requires API Y," not "this rule type is for provider class X." In some cases (git, OCI) API Y is standardized and multiple providers can implement it. In other cases the API is specific to a single company/provider class (GitHub management API, Docker management API, various cloud provider APIs) — that looks like "this rule is for provider class X," but it's really "only this provider
currently implements API Y." The distinction matters for how the field should be understood and extended as more providers implement overlapping APIs.
Proposed direction
Add a
provider_traitsfield to the rule type schema, checked by rtengine before evaluation — the same way entity-type gating already works today — rather than relying on profile selectors. This reuses the existingProviderType/CanImplementtrait vocabulary (pkg/providers/v1/providers.go), so a rule type declares which trait(s) it needs (e.g.github-api,git,oci), not a specific named provider registration — a single rule type can apply across multiple provider instances that implement the same trait.Sub-issues
provider_traitsfield to rule type proto/schemaprovider_traitsbefore evalprovider_traitsto unblockosps-ac-03-02provider_traitsfor rule type authorsContext
Design discussed with @evankanderson — reusing the existing
ProviderType/CanImplementtrait pattern rather than introducing a new capability abstraction, since GitHub/GitLab branch protection differ enough in shape that a boolean "supports X" capability flag would hide more than it clarifies. Naming settled onprovider_traitsoverrequired_traitssince the latter doesn't make clear who/what is doing the requiring (rule type vs. entity vs. policy). Open to a better name before this ships if one comes up.