Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/uipath/runtime/governance/_audit/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ def emit_rule_evaluation(
"""Convenience method to emit a rule evaluation event.
``enforcement_mode`` travels on the event so sinks don't have to
read a process-global. With instance-scoped loaders the global
read a process-global. With instance-scoped runtimes the global
wouldn't be authoritative anyway — parallel runtimes can run in
different modes simultaneously.
"""
Expand Down Expand Up @@ -599,7 +599,7 @@ def emit_session_start(
Same ``enforcement_mode: EnforcementMode`` contract as
:meth:`emit_rule_evaluation` and :meth:`emit_hook_summary`
— every governance event carries the per-loader mode so sinks
— every governance event carries the per-runtime mode so sinks
don't depend on a process-global.
"""
self.emit(
Expand Down
11 changes: 6 additions & 5 deletions src/uipath/runtime/governance/_audit/traces.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,10 @@ def _resolve_mode(event: AuditEvent) -> EnforcementMode:
"""Read the enforcement mode the evaluator stamped on the event.

Mode travels with the event (set by :meth:`AuditManager.emit_rule_evaluation`
/ :meth:`emit_hook_summary` from the loader's per-instance mode) so
the sink doesn't read a process-global that wouldn't be authoritative
in a parallel-runtime setup.
/ :meth:`emit_hook_summary` from the per-runtime
:attr:`GovernanceRuntime.enforcement_mode`) so the sink doesn't
read a process-global that wouldn't be authoritative in a
parallel-runtime setup.

Falls back to ``AUDIT`` only when the field is missing — that's a
contract violation by the emitter (every governance event must carry
Expand Down Expand Up @@ -212,7 +213,7 @@ def _emit_hook_span(self, event: AuditEvent) -> None:
# multiple SDKs / governance backends co-exist.
span.set_attribute(f"{NS}.source", GOVERNANCE_SOURCE)
# Hook summary attributes. Mode comes from the event — the
# evaluator stamps it from the per-loader instance, so the
# evaluator stamps it from the per-runtime instance, so the
# sink is correct for parallel runtimes running different
# modes.
mode = _resolve_mode(event)
Expand Down Expand Up @@ -272,7 +273,7 @@ def _emit_rule_span(self, event: AuditEvent) -> None:

# Derive the spec-vocabulary verdict pair from the raw
# (matched, configured action, mode) tuple. Mode comes
# from the event (per-loader instance) so parallel
# from the event (per-runtime instance) so parallel
# runtimes running different modes don't cross-contaminate.
# Single source of truth for the emitted attributes below
# AND the verbosityLevel/Status decision further down.
Expand Down
45 changes: 45 additions & 0 deletions src/uipath/runtime/governance/native/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""Native UiPath governance policy evaluator.

YAML-defined rules evaluated in-process at each agent lifecycle hook.
The host fetches the policy pack via the
:class:`GovernancePolicyProvider` protocol and compiles it into a
:class:`PolicyIndex` with :func:`build_policy_index_from_yaml` *before*
constructing :class:`GovernanceRuntime` — so the runtime layer never
performs I/O at construction time.

This subpackage owns:

- :class:`GovernanceEvaluator` – the evaluator implementation.
- :func:`build_policy_index_from_yaml` – pure YAML → :class:`PolicyIndex`
compiler.
- The native policy model: :class:`Rule`, :class:`Check`,
:class:`Condition`, :class:`PolicyIndex`.

Shared output types (``Action``, ``AuditRecord``, …) live in
:mod:`uipath.core.governance`.
"""

from ._yaml_to_index import build_policy_index_from_yaml
from .evaluator import GovernanceEvaluator
from .models import (
Check,
CheckContext,
Condition,
PolicyIndex,
PolicyPack,
Rule,
Severity,
)

__all__ = [
"GovernanceEvaluator",
"build_policy_index_from_yaml",
# Native policy model
"Check",
"CheckContext",
"Condition",
"PolicyIndex",
"PolicyPack",
"Rule",
"Severity",
]
11 changes: 6 additions & 5 deletions src/uipath/runtime/governance/native/_yaml_to_index.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"""Runtime YAML → PolicyIndex parser.

Mirrors the shape produced by ``packs/compile_packs.py`` but builds the
PolicyIndex directly from parsed YAML data rather than generating Python
source. Used by :mod:`uipath.runtime.governance.native.loader` to
compile the YAML body returned by the registered policy provider into
an in-memory index at startup.
Mirrors the shape produced by ``packs/compile_packs.py`` but builds
the :class:`PolicyIndex` directly from parsed YAML data rather than
generating Python source. The platform host calls this to compile the
YAML body returned by :meth:`GovernancePolicyProvider.get_policy_async`
into an in-memory index, then hands the index to
:class:`GovernanceRuntime`.

Accepts either a single YAML document (one pack) or a multi-document
stream (``---``-separated packs). Unknown check types and malformed
Expand Down
Loading
Loading