Skip to content

feat: store and detect Rego language version per rule type (Phase 1)#6317

Open
dakshhhhh16 wants to merge 1 commit intomindersec:mainfrom
dakshhhhh16:feat/rego-v1-dual-parse
Open

feat: store and detect Rego language version per rule type (Phase 1)#6317
dakshhhhh16 wants to merge 1 commit intomindersec:mainfrom
dakshhhhh16:feat/rego-v1-dual-parse

Conversation

@dakshhhhh16
Copy link
Copy Markdown
Contributor

Parent Issue #5262
Sub-issue #6316

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 (if, import rego.v1, every, etc.) and means there is no foundation for a gradual V1 migration.

Approach

Instead of a big-bang migration, this phase establishes the necessary infrastructure:

  1. Per-rule-type version storage -- adds a rego_version column to the rule_type table (default 'v0').
  2. Parse-attempt detection -- on CreateRuleType / UpdateRuleType, the server tries the V1 parser first. If it succeeds, stores 'v1'; otherwise stores 'v0'. No user action required.
  3. Dual-parse validation -- Validate() tries V1 first and falls back to V0, so both syntaxes pass.
  4. Feature-flag-gated evaluation -- when rego_v1_dual_parse is enabled, the evaluator reads the stored version instead of hardcoding V0.

No existing behaviour changes without the feature flag.

Out of scope (future phases)

  • Backfilling existing rule types
  • Surfacing rego_version in the API / CLI
  • V0 deprecation warnings (rego_v1_warn_v0)
  • V0 refusal (rego_v1_refuse_v0)

@dakshhhhh16 dakshhhhh16 requested a review from a team as a code owner April 9, 2026 18:13
@coveralls
Copy link
Copy Markdown

coveralls commented Apr 9, 2026

Coverage Status

Coverage is 59.353%dakshhhhh16:feat/rego-v1-dual-parse into mindersec:main. No base build found for mindersec:main.

Copy link
Copy Markdown
Member

@evankanderson evankanderson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is looking pretty close, though I'll want to do some manual testing with flag on/off if you haven't already. I suspect that this is a one-way flag -- once you've enabled "allow rego v1 dual-parse", some (enumerable but not easily known) set of your ruletypes in the Minder database will stop evaluating correctly when the flag is disabled.

@@ -313,7 +313,7 @@ func TestRuleType_Definition_Eval_Rego_Validate(t *testing.T) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change the name of this test to something like "valid v1 rego expression"?

@dakshhhhh16 dakshhhhh16 force-pushed the feat/rego-v1-dual-parse branch from 38914ef to 148f6cd Compare April 10, 2026 10:20
@dakshhhhh16
Copy link
Copy Markdown
Contributor Author

Damn! Even the security check didn't fail this time!.

Comment on lines 254 to 264
// Try parsing as Rego V1 first; if that fails, fall back to V0.
// This allows both V0 and V1 policies to pass validation.
_, err := ast.ParseModuleWithOpts("minder-ruletype-def.rego", rego.Def,
ast.ParserOptions{RegoVersion: ast.RegoV0})
ast.ParserOptions{RegoVersion: ast.RegoV1})
if err != nil {
_, err = ast.ParseModuleWithOpts("minder-ruletype-def.rego", rego.Def,
ast.ParserOptions{RegoVersion: ast.RegoV0})
}
if err != nil {
return fmt.Errorf("%w: rego definition is invalid: %s", ErrInvalidRuleTypeDefinition, err)
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should move this validation to ruletypes/service.go, rather than having it happen on the client as well as the server.

Both CreateRuleType and UpdateRuleType should return an error if the rego_v1_dual_parse flag is false and the user supplies a string that can only be parsed in the V1 dialect. (We should add a test for this, either in ruletypes/services_test.go or in controlplane/handlers_ruletype_test.go)

We want to move the validation of the rego language out of the protobuf validator, because doing the validation on the client as well as the server means that users will need to update their minder binary to take advantage of new features -- we'd prefer to simply be able to light them up from the server side. (We've had this problem before for other features, like not needing to specify def: {} on each rule in a policy.)

@dakshhhhh16 dakshhhhh16 force-pushed the feat/rego-v1-dual-parse branch 2 times, most recently from 748c2bb to a8fd600 Compare April 11, 2026 00:22
…ec#5262)

Phase 1 of the Rego V1 migration plan:

- Add rego_version column to rule_type table (migration 000117)
- Implement DetectRegoVersion() using parse-attempt detection
  (try V1 parser first, fall back to V0)
- Store detected version in DB on rule type create/update
- Wire stored version into Rego evaluator via WithRegoVersion option
- Update validators to dual-parse (accept both V0 and V1 syntax)
- Add rego_v1_dual_parse feature flag for gated rollout
- Add comprehensive unit tests for version detection

Signed-off-by: Daksh Pathak <daksh.pathak.ug24@nsut.ac.in>
Signed-off-by: dakshhhhh16 <daksh.pathak.ug24@nsut.ac.in>
@dakshhhhh16 dakshhhhh16 force-pushed the feat/rego-v1-dual-parse branch from a8fd600 to 7893de6 Compare April 11, 2026 00:32
@dakshhhhh16
Copy link
Copy Markdown
Contributor Author

Updated!

Copy link
Copy Markdown
Member

@evankanderson evankanderson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably deserves a quick manual end-to-end test pass. Feel free to either post results, or ask me to run it when I get sufficient connectivity. (Beginning of next week -- I'm on a camping trip this week.)

@@ -400,3 +456,5 @@ func getAvailableDataSources(

return datasources, nil
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lint is complaining about an extra trailing newline.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants