Skip to content

feat(governance): in-runtime policy evaluator, guardrail compensation, audit pipeline#140

Merged
viswa-uipath merged 1 commit into
mainfrom
feat/governance-foundation
Jul 1, 2026
Merged

feat(governance): in-runtime policy evaluator, guardrail compensation, audit pipeline#140
viswa-uipath merged 1 commit into
mainfrom
feat/governance-foundation

Conversation

@viswa-uipath

@viswa-uipath viswa-uipath commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Lands the full in-runtime governance stack on main. Wraps a runtime delegate with:

  • UiPathGovernedRuntime — thin wrapper that fires BEFORE_AGENT / AFTER_AGENT around the delegate, opens a single OTel root span per invocation (so runtime-side governance events correlate with framework-emitted spans under one trace_id), and exposes an opaque on_dispose: Callable[[], None] | None cleanup hook that runs in a finally after the delegate's own dispose.
  • In-runtime policy evaluator (native/evaluator.py) — rule / check / condition matching for regex, contains, entropy, encoding-concern, incident-concern, commitment-concern, VADER sentiment, and guardrail_fallback operators. Per-check action overrides, cross-rule aggregation (DENY > ESCALATE > AUDIT > ALLOW). Instance-scoped; no process-globals.
  • Guardrail compensation (native/guardrail_compensation.py) — synchronous dispatcher (no thread pool inside the runtime layer) that hands GovernRequests off to an injected GovernanceCompensationProvider. Stamps runtime identity (agent_framework, agent_type, runtime_version) onto the wire.
  • Audit pipeline (_audit/) — AuditManager fans events out to sinks; two shipped: TracesAuditSink (OTel → Orchestrator) and TrackEventAuditSink (host-injected Callable → App Insights). Both non-blocking-by-contract; the host wires whatever adapter it wants behind the callable.
  • Enforcement modesAUDIT, ENFORCE, DISABLED handled at the evaluator boundary. Deny short-circuits via GovernanceBlockException in ENFORCE; collapses to audit-only logging in AUDIT; short-circuits before any rule evaluates in DISABLED.

Architecture principles

  • Runtime stays sync/pure — no ThreadPoolExecutor, no atexit, no environment-variable reads in the governance layer. Async dispatch (if any) is the host's problem.
  • Callable over Protocol for single-method contractstrack_event and on_dispose are typed as Callable[..., None] / Callable[[], None]. The runtime never imports concrete platform classes.
  • Standard wire APIs used directly; proprietary APIs injected — traces sink uses OTel's global Tracer; track-event sink calls a host-supplied Callable.

Dependencies

Bumps floor to uipath-core>=0.5.28, <0.6.0 (needs GovernRequest.agent_framework / agent_type / runtime_version). Adds pyyaml, vaderSentiment, chardet for the native evaluator's YAML compilation + sentiment + encoding-integrity checks. Wheel Requires-Dist verified narrow-and-correct.

Verification

  • uv run pytest395 passed, 1 skipped
  • uv run ruff check . — clean
  • uv run mypy src/ — clean (51 source files)
  • Wheel metadata: Requires-Dist: uipath-core<0.6.0,>=0.5.28 — no testpypi pin baked in

Risk / rollout

Additive to the runtime surface: no removed symbols, no signature changes on existing classes. Framework consumers (uipath-integrations-python) don't import uipath.runtime.governance.* so they're unaffected. Host CLI wiring is a follow-up.

Follow-ups (not in this PR)

  • Host CLI wires LiveTrackEventDispatcher.dispatch from uipath-platform as the non-blocking track_event, and dispatcher.shutdown as the on_dispose.
  • Move vaderSentiment / chardet into [project.optional-dependencies].governance to reduce install footprint for non-governance consumers.

🤖 Generated with Claude Code

Development Package

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

  # Any version from PR
  "uipath-runtime>=0.11.6.dev1001400000,<0.11.6.dev1001410000"
]

[[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" }

@viswa-uipath viswa-uipath requested a review from a team as a code owner July 1, 2026 14:39
@viswa-uipath viswa-uipath force-pushed the feat/governance-foundation branch 4 times, most recently from abd0a0c to ff2a429 Compare July 1, 2026 15:55
…models, and dependencies

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@viswa-uipath viswa-uipath force-pushed the feat/governance-foundation branch from ff2a429 to 0a3e28f Compare July 1, 2026 16:54
@sonarqubecloud

sonarqubecloud Bot commented Jul 1, 2026

Copy link
Copy Markdown

@viswa-uipath viswa-uipath merged commit 0734fca into main Jul 1, 2026
175 of 176 checks passed
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.

3 participants