Problem
Minder's Rego evaluator unconditionally compiles all policies with ast.RegoV0, even on OPA v1.14+ where the recommended default is V1. This blocks users from writing modern Rego policies using if, import rego.v1, every, etc., and it means we have no foundation for a gradual V1 migration.
See parent issue: #5262 -- Rego V1 Support
Approach
Instead of a big-bang migration, this phase of the plan establishes the necessary infrastructure by:
- Per-rule-type version storage -- adds a
rego_version column to the rule_type table (defaulting to 'v0') so each rule type carries an explicit version marker.
- Parse-attempt detection -- on every
CreateRuleType / UpdateRuleType, the server attempts to parse the Rego definition with the V1 parser first. If it succeeds, rego_version = 'v1' is stored; otherwise 'v0' is stored. No user action required.
- Dual-parse validation -- the protobuf
Validate() path now tries V1 first and falls back to V0, so valid V1 or V0 policies both pass validation.
- Feature-flag-gated evaluation -- when
rego_v1_dual_parse is enabled, the Rego evaluator reads the stored version and passes it via rego.SetRegoVersion() rather than hardcoding V0.
Changes
| Area |
File(s) |
What changed |
| DB migration |
database/migrations/000117_rule_type_rego_version.{up,down}.sql |
Adds rego_version TEXT NOT NULL DEFAULT 'v0' to rule_type |
| SQL / sqlc |
database/query/rule_types.sql, internal/db/models.go, internal/db/rule_types.sql.go |
rego_version wired through Create/Update queries; regenerated |
| Mock |
database/mock/store.go |
Regenerated via mockgen |
| Version helpers |
internal/engine/eval/rego/version.go |
DetectRegoVersion(), VersionToString(), VersionFromString() |
| Evaluator |
internal/engine/eval/rego/eval.go |
WithRegoVersion option + evaluator stores/uses version |
| Cache |
internal/engine/rtengine/cache.go |
Reads stored version behind rego_v1_dual_parse flag |
| Service |
pkg/ruletypes/service.go |
Calls DetectRegoVersion() on create/update |
| Validator |
pkg/api/protobuf/go/minder/v1/validators.go |
Dual-parse (try V1, fall back V0) |
| Feature flag |
pkg/flags/constants.go |
RegoV1DualParse experiment constant |
| Tests |
internal/engine/eval/rego/version_test.go |
12 unit tests for detection + roundtrip |
Out of scope (future phases)
- Backfilling existing rule types via a migration job
- Per-rule-type rego_version surface in the API / CLI
- V0 deprecation warnings (
rego_v1_warn_v0 flag)
- V0 refusal (
rego_v1_refuse_v0 flag)
Problem
Minder's Rego evaluator unconditionally compiles all policies with
ast.RegoV0, even on OPA v1.14+ where the recommended default is V1. This blocks users from writing modern Rego policies usingif,import rego.v1,every, etc., and it means we have no foundation for a gradual V1 migration.See parent issue: #5262 -- Rego V1 Support
Approach
Instead of a big-bang migration, this phase of the plan establishes the necessary infrastructure by:
rego_versioncolumn to therule_typetable (defaulting to'v0') so each rule type carries an explicit version marker.CreateRuleType/UpdateRuleType, the server attempts to parse the Rego definition with the V1 parser first. If it succeeds,rego_version = 'v1'is stored; otherwise'v0'is stored. No user action required.Validate()path now tries V1 first and falls back to V0, so valid V1 or V0 policies both pass validation.rego_v1_dual_parseis enabled, the Rego evaluator reads the stored version and passes it viarego.SetRegoVersion()rather than hardcoding V0.Changes
database/migrations/000117_rule_type_rego_version.{up,down}.sqlrego_version TEXT NOT NULL DEFAULT 'v0'torule_typedatabase/query/rule_types.sql,internal/db/models.go,internal/db/rule_types.sql.gorego_versionwired through Create/Update queries; regenerateddatabase/mock/store.gointernal/engine/eval/rego/version.goDetectRegoVersion(),VersionToString(),VersionFromString()internal/engine/eval/rego/eval.goWithRegoVersionoption + evaluator stores/uses versioninternal/engine/rtengine/cache.gorego_v1_dual_parseflagpkg/ruletypes/service.goDetectRegoVersion()on create/updatepkg/api/protobuf/go/minder/v1/validators.gopkg/flags/constants.goRegoV1DualParseexperiment constantinternal/engine/eval/rego/version_test.goOut of scope (future phases)
rego_v1_warn_v0flag)rego_v1_refuse_v0flag)