Skip to content

feat: Rego WASM governance evaluator (v2)#147

Draft
evanbijoy251 wants to merge 3 commits into
mainfrom
feat/rego-evaluator-v2
Draft

feat: Rego WASM governance evaluator (v2)#147
evanbijoy251 wants to merge 3 commits into
mainfrom
feat/rego-evaluator-v2

Conversation

@evanbijoy251

@evanbijoy251 evanbijoy251 commented Jul 10, 2026

Copy link
Copy Markdown

Summary

  • Ports the Rego/WASM governance evaluator from the old feat/rego-evaluator branch, rebased on main's DI-first architecture (no globals, no FF checks inside the class)
  • Adds feature signal extractors (governance/features/) shared between native and Rego evaluators
  • Adds RegoEvaluator — one OPAPolicy engine per LifecycleHook, receives AuditManager and EnforcementMode via DI constructor params
  • Adds build_rego_evaluator_async(service) for platform-service-driven bootstrap — single async call, no background threads at startup, mirrors native evaluator bootstrap pattern exactly
  • Integrates into UiPathGovernedRuntime via the existing rego_evaluator kwarg and sequential-merge pattern (both evaluators run per hook; first GovernanceBlockException raised)

Commits

  • feat: port Rego evaluator to feat/rego-evaluator-v2 — full port of evaluator, features, bundle cache, api client, loader
  • fix: remove native policy loading files — native policy loading moved to uipath-python under uipath-platform
  • feat: add build_rego_evaluator_async to rego loader — async bootstrap builder; bumps to 0.12.3

Dependencies

Depends on UiPath/uipath-python#feat/rego-evaluator for:

  • HookBundle / AllPoliciesResponse wire models (uipath.core.governance)
  • GovernanceService.retrieve_all_policies_async() / download_bundle_async()
  • REGO_FEATURE_FLAG / is_rego_enabled()

Test plan

  • uv run pytest passes
  • UIPATH_FEATURE_EnablePythonGovernanceRegoEvaluator=true with a valid bundle triggers Rego evaluation
  • Missing bundles → fail-open (agent runs without Rego evaluation, warning logged)
  • GovernanceBlockException from Rego returns FAULTED result with Governance.PolicyViolation code

Generated with Claude Code

Development Package

  • Add this package as a dependency in your pyproject.toml:
[project]
dependencies = [
  # Exact version:
  "uipath-runtime==0.12.3.dev1001470623",

  # Any version from PR
  "uipath-runtime>=0.12.3.dev1001470000,<0.12.3.dev1001480000"
]

[[tool.uv.index]]
name = "testpypi"
url = "https://test.pypi.org/simple/"
publish-url = "https://test.pypi.org/legacy/"
explicit = true

[tool.uv.sources]
uipath-runtime = { index = "testpypi" }

evanbijoy251 and others added 3 commits July 9, 2026 15:20
Adds WASM-based Rego evaluation alongside the native (YAML/regex)
evaluator, aligned with main's DI-first, FF-free architecture:

- governance/features/ — shared NLP/regex signal extractors (moved from
  rego/features/ so both evaluators can reuse them); commitment, encoding,
  incident, sentiment, text_stats extractors registered via @register()
- governance/rego/ — RegoEvaluator (opa-wasmtime), bundle cache, api_client,
  loader with ETag-driven disk cache + 30s background refresh
- governance/native/ — backend_client, policy_api_client, _yaml_to_index,
  loader (prefetch + background load, no FF gating)
- governance/config.py — re-exports EnforcementMode from uipath.core.governance,
  keeps get/set/reset_enforcement_mode for process-level state
- governance/delegation_guard.py — ASI-02 recursion depth guard
- governance/_audit/console.py — human-readable logging sink
- governance/_audit/factory.py — add "console" sink registration

Architecture alignment with main:
- RegoEvaluator accepts audit_manager + enforcement_mode via DI (no globals)
- emit_rule_evaluation uses policy_id= (main API), enforcement_mode as object
- No FF gating anywhere; enable/disable is server-side via EnforcementMode
- sequential-merge: both evaluators run, violations collected before raise

runtime.py changes:
- rego_evaluator kwarg added to UiPathGovernedRuntime
- _fire_before/after_agent: sequential-merge pattern (native then rego)
- execute()/stream(): catch GovernanceBlockException → FAULTED result
  with error code Governance.PolicyViolation
- _find_governance_block(): walks __cause__/__context__ chain to unwrap
  framework-wrapped GovernanceBlockExceptions

Tests updated: two tests now assert FAULTED result instead of raised exception.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
The /runtime/policy fetch (YAML policy loading, PolicyIndex
construction) lives in uipath-python under platform, not here.
Removes native/loader.py, native/policy_api_client.py, and
native/_yaml_to_index.py that were incorrectly ported.

native/backend_client.py stays — rego/api_client.py uses it for
URL building and headers when fetching WASM bundles from
/all-policies.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Adds build_rego_evaluator_async(service) — a single async call that
fetches /all-policies metadata via the injected platform service,
downloads changed bundles to disk, and returns a RegoEvaluator or
None. Mirrors the native evaluator bootstrap pattern (no background
threads at startup). Bumps version to 0.12.3.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
3.5% Coverage on New Code (required ≥ 90%)
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

💡 Need a hand with PR review? Try Gitar by Sonar!

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant