From 5cb333d2562289ff954452aca4eafcd4bc9d58c0 Mon Sep 17 00:00:00 2001 From: rcourtman Date: Thu, 19 Mar 2026 08:45:38 +0000 Subject: [PATCH] Centralize policy routing decision labels --- .../release-control/v6/internal/subsystems/ai-runtime.md | 3 +++ .../v6/internal/subsystems/unified-resources.md | 4 ++++ .../components/Infrastructure/ResourceDetailDrawer.tsx | 9 +++++++-- .../__tests__/frontendResourceTypeBoundaries.test.ts | 1 + .../utils/__tests__/resourcePolicyPresentation.test.ts | 3 +++ frontend-modern/src/utils/resourcePolicyPresentation.ts | 3 +++ 6 files changed, 21 insertions(+), 2 deletions(-) diff --git a/docs/release-control/v6/internal/subsystems/ai-runtime.md b/docs/release-control/v6/internal/subsystems/ai-runtime.md index b2b306548..43d439fb0 100644 --- a/docs/release-control/v6/internal/subsystems/ai-runtime.md +++ b/docs/release-control/v6/internal/subsystems/ai-runtime.md @@ -112,6 +112,9 @@ That governed context should also surface the canonical routing posture and redaction hints that were derived from the shared policy model, so prompts reflect the same sensitivity, routing, and scrub decisions that the runtime uses for export boundaries instead of rebuilding privacy posture locally. +The same shared policy presenter also owns the `Allowed`/`Blocked` routing +decision labels shown in the resource drawer, so the policy state wording +stays canonical instead of being rendered inline by the consumer. That same policy boundary now applies to chat structured-mention prefetch and resource-summary formatting: mention resolution must consume canonical unified-resource policy metadata, skip discovery fan-out when governed diff --git a/docs/release-control/v6/internal/subsystems/unified-resources.md b/docs/release-control/v6/internal/subsystems/unified-resources.md index 2e69e73a0..0a3f878b7 100644 --- a/docs/release-control/v6/internal/subsystems/unified-resources.md +++ b/docs/release-control/v6/internal/subsystems/unified-resources.md @@ -122,6 +122,10 @@ The canonical policy-posture aggregate now also lives in `internal/unifiedresources/policy_posture.go`, so AI summaries and resource context share the same sensitivity, routing, and redaction counts from the resource model instead of rebuilding governance posture in AI-local code. +The same policy presenter now also owns the `Allowed`/`Blocked` routing +decision labels shown in the resource detail drawer, so routing-state wording +stays canonical with the rest of the policy surface instead of being +rendered inline by the drawer. The backend AI and Patrol graph context renderers now derive their canonical relationship labels, direction, provenance, freshness, and metadata flags from `internal/unifiedresources/relationship_presentation.go`, so the graph diff --git a/frontend-modern/src/components/Infrastructure/ResourceDetailDrawer.tsx b/frontend-modern/src/components/Infrastructure/ResourceDetailDrawer.tsx index eea3d997a..12a2b0013 100644 --- a/frontend-modern/src/components/Infrastructure/ResourceDetailDrawer.tsx +++ b/frontend-modern/src/components/Infrastructure/ResourceDetailDrawer.tsx @@ -48,6 +48,7 @@ import { ResourceAPI } from '@/api/resources'; import { getResourcePolicyBadges, getResourcePolicyRedactionLabels, + getResourcePolicyRoutingDecisionLabel, getResourceRoutingScopeLabel, getResourceSensitivityLabel, } from '@/utils/resourcePolicyPresentation'; @@ -1063,13 +1064,17 @@ const DrawerContent: Component = (props) => {
Cloud Summary - {props.resource.policy?.routing.allowCloudSummary ? 'Allowed' : 'Blocked'} + {getResourcePolicyRoutingDecisionLabel( + props.resource.policy?.routing.allowCloudSummary, + )}
Raw Signals - {props.resource.policy?.routing.allowCloudRawSignals ? 'Allowed' : 'Blocked'} + {getResourcePolicyRoutingDecisionLabel( + props.resource.policy?.routing.allowCloudRawSignals, + )}
diff --git a/frontend-modern/src/utils/__tests__/frontendResourceTypeBoundaries.test.ts b/frontend-modern/src/utils/__tests__/frontendResourceTypeBoundaries.test.ts index 5591658a4..3dd78c105 100644 --- a/frontend-modern/src/utils/__tests__/frontendResourceTypeBoundaries.test.ts +++ b/frontend-modern/src/utils/__tests__/frontendResourceTypeBoundaries.test.ts @@ -1897,6 +1897,7 @@ describe('frontend resource type boundaries', () => { expect(resourceDetailDrawerSource).toContain('getResourceChangeKindPresentation'); expect(resourceDetailDrawerSource).toContain('getResourceChangeSourceTypePresentation'); expect(resourceDetailDrawerSource).toContain('getResourceChangeSourceAdapterPresentation'); + expect(resourceDetailDrawerSource).toContain('getResourcePolicyRoutingDecisionLabel'); expect(resourceChangeSummarySource).toContain('getResourceChangeKindPresentation'); expect(resourceChangeSummarySource).toContain('getResourceChangeSourceTypePresentation'); expect(resourceChangeSummarySource).toContain( diff --git a/frontend-modern/src/utils/__tests__/resourcePolicyPresentation.test.ts b/frontend-modern/src/utils/__tests__/resourcePolicyPresentation.test.ts index 010950828..800c674e4 100644 --- a/frontend-modern/src/utils/__tests__/resourcePolicyPresentation.test.ts +++ b/frontend-modern/src/utils/__tests__/resourcePolicyPresentation.test.ts @@ -8,6 +8,7 @@ import { getResourcePolicyRoutingSummaries, getResourcePolicySensitivitySummaries, getResourcePolicyRedactionLabels, + getResourcePolicyRoutingDecisionLabel, getResourceRedactionHintLabel, getResourceRoutingScopeLabel, getResourceSensitivityLabel, @@ -17,6 +18,8 @@ describe('resourcePolicyPresentation utils', () => { it('formats canonical policy labels', () => { expect(getResourceSensitivityLabel('restricted')).toBe('Restricted'); expect(getResourceRoutingScopeLabel('local-only')).toBe('Local Only'); + expect(getResourcePolicyRoutingDecisionLabel(true)).toBe('Allowed'); + expect(getResourcePolicyRoutingDecisionLabel(false)).toBe('Blocked'); expect(getResourceRedactionHintLabel('platform-id')).toBe('Platform ID'); }); diff --git a/frontend-modern/src/utils/resourcePolicyPresentation.ts b/frontend-modern/src/utils/resourcePolicyPresentation.ts index d9ea2b2e2..c5ec46ff9 100644 --- a/frontend-modern/src/utils/resourcePolicyPresentation.ts +++ b/frontend-modern/src/utils/resourcePolicyPresentation.ts @@ -107,6 +107,9 @@ export const getResourceSensitivityLabel = (sensitivity?: ResourceSensitivity): export const getResourceRoutingScopeLabel = (scope?: ResourceRoutingScope): string => scope ? routingPresentation[scope].label : 'Unrouted'; +export const getResourcePolicyRoutingDecisionLabel = (allowed?: boolean): string => + allowed ? 'Allowed' : 'Blocked'; + export const getResourceRedactionHintLabel = (hint?: ResourceRedactionHint): string => hint ? redactionLabels[hint] ?? hint : 'Unclassified';