runtime: rule labels metadata processing follow-ups (#8613)

 We now parse rego metadata annotations by default.

Rule annotations now support a `labels` field. During policy eval,
labels from all successfully evaluated rules are collected and included
in each decision log entry as a top-level `rule_labels` array. Each
element preserves the label map from one evaluated rule. Exact
duplicates are omitted.

```rego
# METADATA
# labels:
#   severity: low
#   team: platform
allow if input.role == "admin"
```

The resulting decision log entry will contain:

```json
{"rule_labels": [{"severity": "low", "team": "platform"}]}
```

---------

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
This commit is contained in:
Stephan Renatus
2026-05-08 17:00:26 +02:00
committed by GitHub
parent 81987eebe4
commit cb54e9c14f
32 changed files with 661 additions and 728 deletions
+4 -4
View File
@@ -42,12 +42,12 @@ func CreatePathWatcher(rootPaths []string) (*fsnotify.Watcher, error) {
// ProcessWatcherUpdate handles an occurrence of a watcher event
func ProcessWatcherUpdate(ctx context.Context, paths []string, removed string, store storage.Store, filter loader.Filter, asBundle bool, bundleLazyLoadingMode bool,
f func(context.Context, storage.Transaction, *initload.LoadPathsResult) error) error {
return ProcessWatcherUpdateForRegoVersion(ctx, ast.DefaultRegoVersion, paths, removed, store, filter, asBundle, bundleLazyLoadingMode, f)
return ProcessWatcherUpdateForRegoVersion(ctx, ast.ParserOptions{RegoVersion: ast.DefaultRegoVersion, ProcessAnnotation: true}, paths, removed, store, filter, asBundle, bundleLazyLoadingMode, f)
}
func ProcessWatcherUpdateForRegoVersion(ctx context.Context, regoVersion ast.RegoVersion, paths []string, removed string, store storage.Store, filter loader.Filter, asBundle bool, bundleLazyLoadingMode bool,
func ProcessWatcherUpdateForRegoVersion(ctx context.Context, popts ast.ParserOptions, paths []string, removed string, store storage.Store, filter loader.Filter, asBundle bool, bundleLazyLoadingMode bool,
f func(context.Context, storage.Transaction, *initload.LoadPathsResult) error) error {
loaded, err := initload.LoadPathsForRegoVersion(regoVersion, paths, filter, asBundle, nil, true, bundleLazyLoadingMode, false, false, nil, nil)
loaded, err := initload.LoadPathsForRegoVersion(popts, paths, filter, asBundle, nil, true, bundleLazyLoadingMode, false, nil)
if err != nil {
return err
}
@@ -75,7 +75,7 @@ func ProcessWatcherUpdateForRegoVersion(ctx context.Context, regoVersion ast.Reg
if err != nil {
return err
}
module, err := ast.ParseModuleWithOpts(id, string(bs), ast.ParserOptions{RegoVersion: regoVersion})
module, err := ast.ParseModuleWithOpts(id, string(bs), popts)
if err != nil {
return err
}
+1 -1
View File
@@ -95,7 +95,7 @@ func TestProcessWatcherUpdateForRegoVersion(t *testing.T) {
t.Fatal(err)
}
err = ProcessWatcherUpdateForRegoVersion(t.Context(), regoVersion, paths, "", store, filter, false, false, f)
err = ProcessWatcherUpdateForRegoVersion(t.Context(), ast.ParserOptions{RegoVersion: regoVersion, ProcessAnnotation: true}, paths, "", store, filter, false, false, f)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
+7 -8
View File
@@ -143,21 +143,20 @@ func LoadPaths(paths []string,
processAnnotations bool,
caps *ast.Capabilities,
fsys fs.FS) (*LoadPathsResult, error) {
return LoadPathsForRegoVersion(ast.RegoV0, paths, filter, asBundle, bvc, skipVerify, bundleLazyLoading, processAnnotations, false, caps, fsys)
return LoadPathsForRegoVersion(ast.ParserOptions{RegoVersion: ast.RegoV0, ProcessAnnotation: processAnnotations, Capabilities: caps}, paths, filter, asBundle, bvc, skipVerify, bundleLazyLoading, false, fsys)
}
func LoadPathsForRegoVersion(regoVersion ast.RegoVersion,
func LoadPathsForRegoVersion(popts ast.ParserOptions,
paths []string,
filter loader.Filter,
asBundle bool,
bvc *bundle.VerificationConfig,
skipVerify bool,
bundleLazyLoading bool,
processAnnotations bool,
followSymlinks bool,
caps *ast.Capabilities,
fsys fs.FS) (*LoadPathsResult, error) {
caps := popts.Capabilities
if caps == nil {
caps = ast.CapabilitiesForThisVersion()
}
@@ -180,9 +179,9 @@ func LoadPathsForRegoVersion(regoVersion ast.RegoVersion,
WithSkipBundleVerification(skipVerify).
WithBundleLazyLoadingMode(bundleLazyLoading).
WithFilter(filter).
WithProcessAnnotation(processAnnotations).
WithProcessAnnotation(popts.ProcessAnnotation).
WithCapabilities(caps).
WithRegoVersion(regoVersion).
WithRegoVersion(popts.RegoVersion).
WithFollowSymlinks(followSymlinks).
AsBundle(path)
if err != nil {
@@ -198,9 +197,9 @@ func LoadPathsForRegoVersion(regoVersion ast.RegoVersion,
files, err := loader.NewFileLoader().
WithFS(fsys).
WithBundleLazyLoadingMode(bundleLazyLoading).
WithProcessAnnotation(processAnnotations).
WithProcessAnnotation(popts.ProcessAnnotation).
WithCapabilities(caps).
WithRegoVersion(regoVersion).
WithRegoVersion(popts.RegoVersion).
Filtered(nonBundlePaths, filter)
if err != nil {