Centralize policy routing decision labels

This commit is contained in:
rcourtman 2026-03-19 08:45:38 +00:00
parent 2e934262c0
commit 5cb333d256
6 changed files with 21 additions and 2 deletions

View file

@ -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

View file

@ -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

View file

@ -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<ResourceDetailDrawerProps> = (props) => {
<div class="flex items-center justify-between gap-2">
<span class="text-muted">Cloud Summary</span>
<span class="font-medium text-base-content">
{props.resource.policy?.routing.allowCloudSummary ? 'Allowed' : 'Blocked'}
{getResourcePolicyRoutingDecisionLabel(
props.resource.policy?.routing.allowCloudSummary,
)}
</span>
</div>
<div class="flex items-center justify-between gap-2">
<span class="text-muted">Raw Signals</span>
<span class="font-medium text-base-content">
{props.resource.policy?.routing.allowCloudRawSignals ? 'Allowed' : 'Blocked'}
{getResourcePolicyRoutingDecisionLabel(
props.resource.policy?.routing.allowCloudRawSignals,
)}
</span>
</div>
</Show>

View file

@ -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(

View file

@ -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');
});

View file

@ -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';