feat(governance): add Governance getPolicyTraces service#464
Conversation
Review summary - 1 bug (2 locations)
Fix: use |
Review summary — 1 new finding
The governance service calls Previously raised threads (TraceId casing in unit tests) remain open — the current diff already shows |
|
✅ No issues found. Checked for bugs and CLAUDE.md compliance. |
Review summary — 1 new finding + 1 re-opened threadRe-opened: The previous thread requesting a New:
|
|
✅ No issues found. Checked for bugs and CLAUDE.md compliance. |
ninja-shreyash
left a comment
There was a problem hiding this comment.
Pls address open claude comments
I have resolved now. already addressed required ones. |
Review summary — 1 new finding
The mock imports |
Review summary — 1 new finding + 1 re-opened threadRe-opened: Thread PRRT_kwDOOpObr86FBK-R (originally from @ninja-shreyash) asked to remove New: CLAUDE.md flags this as a "Critical constraint": cursor and jumpToPage are mutually exclusive. When both options are passed the |
Review summary — 1 new finding
The |
Review summary — 1 new finding + 1 re-opened threadRe-opened: Thread PRRT_kwDOOpObr86Fmu9u requested removing the internal BE span name New: The |
Review summary — 1 new finding
The description has two near-identical sentences:
The second sentence is a redundant restatement and should be removed (suggestion posted inline). This appears to be a side-effect of applying the previous fix for internal span names — the suggested replacement text was added but the original duplicate sentence wasn't deleted. |
Per code review feedback, shorten the public method name. Inside the `governance` namespace, `getTraces` reads naturally. Cascades the rename through the type system to keep everything symmetric: getPolicyEvaluationTraces -> getTraces PolicyEvaluationTrace -> Trace PolicyEvaluationTracesGetAllOptions -> TracesGetAllOptions RawPolicyEvaluationTraceItem -> RawTraceItem RawPolicyEvaluationTracesResponse -> RawTracesResponse `PolicyEvaluationResult` (the filter enum) is unchanged — its values are owned by the AuthZ contract package, not by the SDK naming. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per follow-up review feedback, `getPolicyTraces` is the agreed name — shorter than the original `getPolicyEvaluationTraces` but still carries the 'policy' qualifier so it (a) doesn't collide with the OpenTelemetry meaning of 'trace' (each row already exposes a `traceId` field) and (b) leaves room for symmetric `getPolicySummary` / `getOperationSummary` naming on the remaining two governance endpoints. Cascades the rename through the type system to keep the surface symmetric: getTraces -> getPolicyTraces Trace -> PolicyTrace TracesGetAllOptions -> PolicyTracesGetAllOptions RawTraceItem -> RawPolicyTraceItem RawTracesResponse -> RawPolicyTracesResponse `PolicyEvaluationResult` (filter enum) and PascalCase `TraceId` assertions in tests are unchanged — the former is owned by the AuthZ contract, the latter is a literal API field name we intentionally assert is absent. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The mock used `EVALUATION_RESULT_ACTIVE_DENY: 'Active_Deny'`, which is the *Snowflake column key* (per the request → SQL mapping in the spec), not anything the API actually returns in the response. The C# DTO is `string?` with no enum constraint, and the OpenAPI response schema is just `type: string` with no documented values — so the response value is genuinely unknown until we can pull live data. Renames the one used constant to `EVALUATION_RESULT_DENY: 'Deny'`, which is the most plausible response shape (matches the request-side `PolicyEvaluationResult` enum that the API does document). Removes the unused `EVALUATION_RESULT_ACTIVE_ALLOW` constant (zero references). No assertions depend on this value — the change is cosmetic and removes a misleading breadcrumb for future readers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pull endTime and fullOrganization into a shared GovernanceFilterOptions interface so other governance endpoints can reuse them, and compose it into PolicyTracesGetAllOptions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…GetAllOptions
Use the singular entity prefix to match the SDK options-type convention
({Entity}GetAllOptions), consistent with TaskGetAllOptions and QueueGetAllOptions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Align the mock with the service after removing the named envelope type;
createMockRawPolicyTracesResponse now returns the inline { items } shape.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… helper Replace hand-rolled offset pagination in getPolicyTraces with PaginationHelpers.getAll(), adding a zeroBased offset option to the shared OFFSET path for 0-based page-number APIs. Type the response cast as the declared return type instead of `as any`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the hardcoded POLICY_TRACE_BODY_KEYS list with Object.keys(apiOptions) so every non-OData body field is exempt from the $ prefix automatically, with no list to keep in sync. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Describe per-policy row semantics and result ordering, and tighten the finalEnforcement/policyStatus field docs. Keep service-class and ServiceModel JSDoc in sync. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ontract The API contract defines policyEvaluationResult as a free-form string, so typing the PolicyTrace response field as the PolicyEvaluationResult enum over-asserted a shape the contract does not guarantee. The enum is retained for the evaluationResult filter input, where the constrained value set is appropriate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
getPolicyTraces passes no transformFn to PaginationHelpers.getAll, so items flow through untouched (the governance API already returns camelCase). - Remove the "should transform API fields" integration test: it asserted PascalCase absence, which passed trivially off the API's native shape rather than any SDK transform. The honestly-named unit test already covers the real guarantee (camelCase preserved, no transform). - Rename three validation unit tests from "should throw ValidationError" to "should throw error" for pageSize/jumpToPage/cursor — those are thrown as a plain Error by the pagination helper, not ValidationError. Only the startTime check throws a real ValidationError, matching the convention in tests/unit/utils/pagination/helpers.test.ts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ce, clarify fullOrganization Namespace the governance surface consistently: - PolicyTrace -> GovernancePolicyTrace (public) - PolicyTraceGetAllOptions -> GovernancePolicyTraceGetAllOptions (public) - RawPolicyTraceItem -> RawGovernancePolicyTraceItem (internal) - createMockRawPolicyTrace -> createMockRawGovernancePolicyTrace (test mock) - createMockRawPolicyTracesResponse -> createMockRawGovernancePolicyTracesResponse (test mock) Also expand the fullOrganization JSDoc to document the tenant-scoped default and the org-admin/403 behavior for each value (omitted / false / true). The renamed public types are unreleased (service still in review), so no backward-compat shim is needed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a reference from the GovernanceServiceModel docs to the Automation Ops "Define governance policies" guide so users can see how the policies the service inspects are configured. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Document the default value (false — tenant-scoped) with a @default tag so it renders as a Default Value entry on the GovernanceFilterOptions docs page. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5ef8916 to
fdf3c0d
Compare
|
|
✅ No issues found. Checked for bugs and CLAUDE.md compliance. |



Method Added
governance.getPolicyTraces()getPolicyTraces<T extends PolicyTraceGetAllOptions>(startTime: Date, options?: T): Promise<T extends HasPaginationOptions<T> ? PaginatedResponse<PolicyTrace> : NonPaginatedResponse<PolicyTrace>>Endpoint Called
getPolicyTraces()insightsrtm_/Governance/policy/tracesInsights.RealTimeData Insights OR.Folders.ReadGovernanceservice — extendsBaseService. All methods require the caller to be an organization administrator.@uipath/uipath-typescript/governance.startTimeis a required positionalDate; all filters and pagination live in the optionaloptionsobject.PaginationHelpers.getAll(). The API is 0-based, so the SDK's 1-based page number is sent aspageNumber - 1(newzeroBasedoption on the shared OFFSET path). The API returns no total count, sohasNextPageis inferred from whether the current page is full.Example Usage
API Response vs SDK Response
Transform pipeline
No transform. The API already returns camelCase keys, so trace rows are passed through unchanged — no
pascalToCamelCaseKeys, no field-rename map, no value mapping. Date inputs (startTime,endTime) are serialized to ISO 8601 on the request side only.Field mapping
policyEvaluationResultis typed as thePolicyEvaluationResultenum. Live data confirms the response only ever returnsAllow/Deny(simulation is tracked separately inpolicyStatus); theSimulatedAllow/SimulatedDenyenum members apply to the request-sideevaluationResultfilter, which the server maps to its composite verdict keys.Sample SDK Response
getPolicyTraces(){ "items": [ { "tenantId": "e367ca54-053b-4b86-89a2-6b9e89e85e7a", "startTime": "2026-04-15T16:55:41.794", "finalEnforcement": "NoOp", "policyId": "9f99cf09-ba63-472e-858e-e80bee3b66fb", "policyEnforcement": "NoOp", "policyEvaluationResult": "Allow", "policyName": "ghcbxvb", "policyStatus": "Simulated", "policyEvaluationDetails": "[]", "actorProcessId": "e0bdb365-defb-45eb-9105-abe5748df6bb", "actorProcessType": "Flow", "actorIdentityId": "", "resourceId": "615068c4-3b66-4d33-b2c4-3df5807e1903", "resourceType": "Agent", "folderKey": "5ff02b94-316c-404d-ab56-301834767f63", "traceId": "2351eee9-cb4f-43af-a877-dde65c2ee116", "processKey": "e0bdb365-defb-45eb-9105-abe5748df6bb", "jobKey": "" }, { "tenantId": "e367ca54-053b-4b86-89a2-6b9e89e85e7a", "startTime": "2026-04-15T16:55:41.794", "finalEnforcement": "NoOp", "policyId": "a7c68eea-4d11-4f08-81ba-f391b9a8c45d", "policyEnforcement": "NoOp", "policyEvaluationResult": "Allow", "policyName": "hjytj", "policyStatus": "Simulated", "policyEvaluationDetails": "[]", "actorProcessId": "e0bdb365-defb-45eb-9105-abe5748df6bb", "actorProcessType": "Flow", "actorIdentityId": "", "resourceId": "615068c4-3b66-4d33-b2c4-3df5807e1903", "resourceType": "Agent", "folderKey": "5ff02b94-316c-404d-ab56-301834767f63", "traceId": "2351eee9-cb4f-43af-a877-dde65c2ee116", "processKey": "e0bdb365-defb-45eb-9105-abe5748df6bb", "jobKey": "" } ] }Truncated to 2 items — full response returns one row per policy evaluated within each governance enforcement event.
Files
src/utils/constants/endpoints/governance.ts,src/utils/constants/endpoints/index.tssrc/models/governance/governance.types.ts,src/models/governance/governance.internal-types.tssrc/utils/constants/common.tssrc/models/governance/governance.models.ts,src/models/governance/index.tssrc/services/governance/governance.ts,src/services/governance/index.tssrc/services/base.ts,src/utils/pagination/helpers.ts,src/utils/pagination/internal-types.tspackage.json,rollup.config.jssrc/index.tstests/unit/services/governance/governance.test.ts(16 tests)tests/integration/shared/governance/governance.integration.test.ts(5 tests),tests/integration/config/unified-setup.tstests/utils/constants/governance.ts,tests/utils/constants/index.ts,tests/utils/mocks/governance.ts,tests/utils/mocks/index.tsdocs/oauth-scopes.md,docs/pagination.md,mkdocs.yml🤖 Auto-generated using onboarding skills