github open-policy-agent/opa v1.16.0

4 hours ago

This release contains a mix of new features, performance improvements, and bugfixes. Notably:

  • New uri.parse and uri.is_valid built-in functions
  • Data API Request/Response Metadata
  • Prometheus metrics exported via OTLP
  • Formatter improvements

NOTE:

In v1.15.x, OPA was dropping logs for bundle downloads, print() calls and other plugin-originated logs.
Users are advised to update, v1.16.0 fixes this bug in (#8544).

New uri.parse and uri.is_valid built-in functions (#8263)

Two new built-in functions have been added: uri.parse for parsing a given URI, and uri.is_valid for verifying the structure of a given URI.

uri.parse

Parses a URI and returns an object containing its components according to RFC 3986. Empty components are omitted.

package example

test_uri if {
	uri.parse("https://example.com:8080/api?q=1#top") == {
		"scheme": "https",
		"hostname": "example.com",
		"port": "8080",
		"path": "/api",
		"raw_path": "/api",
		"raw_query": "q=1",
		"fragment": "top",
	}
}

uri.is_valid

Returns true if the input can be parsed as a URI, false otherwise.

package example

deny contains "invalid URI" if {
    not uri.is_valid("http://[invalid")
}

Authored by @charlieegan3 reported by @anivar

Data API Request/Response Metadata (#8570)

Wrapping projects can now attach custom metadata to Data API requests and have evaluation produce response metadata.

Two distinct metadata paths are introduced:

  • Request metadata: parsed from extra top-level keys in the request body, made available to builtins via BuiltinContext.RequestMetadata. Logged in the decision log under Custom["request_metadata"].

  • Response metadata: a separate map (BuiltinContext.ResponseMetadata) that builtins can populate during evaluation. Only included in the API response and decision log if non-empty.

In vanilla OPA, no builtins write response metadata, so responses are unchanged. The request metadata map is only allocated when the request carries extra fields; the response map is one empty map per request.

To avoid conflicts with future OPA top-level keys, callers should use a namespaced key: {"input": {...}, "com.example.opa/md": {...}}.

Request with metadata:

curl -H 'Content-Type: application/json' \
  -d '{"input": {"user": "alice"}, "com.example.opa/metadata": {"corp-id": "acme-42"}}' \
  http://localhost:8181/v1/data/example/allow

Response (response metadata included if, for example, set by a custom builtin):

{
  "decision_id": "04789f85-de5a-477b-8aa5-6d59d7742135",
  "result": true,
  "com.example.opa/response": {
    "snapshot_version": "v3"
  }
}

Decision log entry:

{
  "custom": {
    "request_metadata": {
      "com.example.opa/metadata": {
        "corp-id": "acme-42"
      }
    },
    "response_metadata": {
      "com.example.opa/response": {
        "snapshot_version": "v3"
      }
    }
  },
  "decision_id": "04789f85-de5a-477b-8aa5-6d59d7742135",
  "input": { "user": "alice" },
  "msg": "Decision Log",
  "path": "example/allow",
  "result": true
}

Authored by @srenatus

Runtime, SDK, Tooling

  • distributedtracing: Export Prometheus metrics via OTLP (#7591) reported and authored by @Munken
  • cmd,tester: Update opa test to stream test case results (#3676) authored by @sspaink reported by @tsandall
  • cmd,tester: Show full errors when test fails and using --coverage (#8438) authored by @grosser
  • format: Add new line between METADATA blocks (#8483) authored by @sspaink
  • format: Allow indenting all withs in expression (#8508) authored by @anderseknert
  • format: Fix dropping comments after handling unexpectedCommentError (#8553) authored by @sspaink
  • format: Preserve location of trailing comments inside every body (#8558) authored by @johanfylling
  • format: Prevent opa fmt from formatting single attribute objects with comments (#7565) authored by @sspaink reported by @anderseknert
  • logging: Keep forwarding from BufferedLogger after Flush() (#8544) authored by @srenatus reported by @annieyhuang
  • plugins/logs: Fix logBuffer eviction loop only dropping one element (#8543) authored by @sspaink
  • plugins/logs: Fix out-of-order plugin status notifications (#8009) authored by @sspaink reported by @Pushpalanka
  • plugins/rest: Carry over all of *tls.Config (#8473) authored by @srenatus reported by @ashu2496
  • server: Drop HTML index page query form (#8477) authored by @johanfylling reported by @srenatus and @r0binak
  • server: Skip chmod for abstract Unix domain sockets (#8536) authored by @bakayolo
  • storage/inmem: Avoid allocations from Read() in MakeDir() (#8561) authored by @srenatus
  • tester: Add method to match tests by ref prefixes (#6696) authored by @anderseknert
    Note: Experimental.

Compiler, Topdown and Rego

Docs, Website, Ecosystem

Miscellaneous

  • build: Exclude domains that cause false positives (#8533) (#8495) authored by @charlieegan3
  • e2e/cli: Add test for debug print() logging (#8567) authored by @srenatus
  • e2e/cli: Start CLI E2E tests (#8545) authored by @srenatus
  • github: declare formatted rego as rego (#8564) authored by @srenatus
  • Security policy update (#8479) authored by @anderseknert
  • Dependency updates; notably:
    • build: bump go 1.26.2 (#8497) authored by @sspaink
    • build(deps): bump wasmtime-go from v39.0.1 to v43.0.2
    • build(deps): bump go.opentelemetry.io deps from 1.40.0/0.65.0 to 1.43.0/0.68.0
    • build(deps): bump github.com/containerd/containerd/v2 from 2.2.1 to 2.2.3
    • build(deps): bump ithub.com/huandu/go-sqlbuilder from 1.39.1 to 1.40.2
    • build(deps): bump golang.org/x/net from 0.51.0 to 0.53.0
    • build(deps): bump golang.org/x/text from 0.34.0 to 0.36.0

Don't miss a new opa release

NewReleases is sending notifications on new releases.