Canonicalize policy posture ordering

This commit is contained in:
rcourtman
2026-03-19 02:16:26 +00:00
parent bc99a27fd3
commit b0cbc45864
6 changed files with 39 additions and 12 deletions
@@ -187,6 +187,9 @@ runtime uses for prompt export and context rendering.
That posture snapshot must render redaction labels through the canonical
unified-resource hint order, not alphabetically, so the AI summary, drawer,
and any future policy surfaces all present the same redaction precedence.
Its sensitivity and routing counts must also follow the canonical
unified-resource order, so both the backend summary and the frontend policy
card stay aligned on the same presentation sequence.
The resource-intelligence payload used by the resource drawer also carries
the same canonical policy posture snapshot, so the detail surface can show
governed posture context without inventing a second posture contract.
@@ -404,6 +404,9 @@ re-described independently per surface.
Those helpers now own the canonical redaction-hint order and count-to-label
projection, so the AI summary and any other backend policy posture surface do
not re-sort redaction labels locally.
They also own the canonical sensitivity and routing order used to format
policy-posture counts, so the AI summary and frontend policy card both read
the same presentation sequence from the shared resource model.
Canonical resources now carry first-class graph-expansion fields: `Capabilities`
(bounded action definitions with approval levels), `Relationships` (typed
inter-resource links with direction and confidence), and `RecentChanges` (typed
+13 -11
View File
@@ -123,17 +123,19 @@ func (s *Service) buildUnifiedResourceContextForModel(destinationModel string) s
}
if policyPosture != nil && policyPosture.TotalResources > 0 {
sections = append(sections, "\n### Data Governance")
sections = append(sections, fmt.Sprintf("- Sensitivity: %d public, %d internal, %d sensitive, %d restricted",
sensitivityCounts[unifiedresources.ResourceSensitivityPublic],
sensitivityCounts[unifiedresources.ResourceSensitivityInternal],
sensitivityCounts[unifiedresources.ResourceSensitivitySensitive],
sensitivityCounts[unifiedresources.ResourceSensitivityRestricted],
))
sections = append(sections, fmt.Sprintf("- Routing: %d cloud-summary, %d local-first, %d local-only",
routingCounts[unifiedresources.ResourceRoutingScopeCloudSummary],
routingCounts[unifiedresources.ResourceRoutingScopeLocalFirst],
routingCounts[unifiedresources.ResourceRoutingScopeLocalOnly],
))
sensitivityParts := make([]string, 0, len(unifiedresources.ResourceSensitivityOrder))
for _, sensitivity := range unifiedresources.ResourceSensitivityOrder {
sensitivityParts = append(sensitivityParts, fmt.Sprintf("%d %s",
sensitivityCounts[sensitivity], sensitivity))
}
sections = append(sections, fmt.Sprintf("- Sensitivity: %s", strings.Join(sensitivityParts, ", ")))
routingParts := make([]string, 0, len(unifiedresources.ResourceRoutingScopeOrder))
for _, scope := range unifiedresources.ResourceRoutingScopeOrder {
routingParts = append(routingParts, fmt.Sprintf("%d %s",
routingCounts[scope], scope))
}
sections = append(sections, fmt.Sprintf("- Routing: %s", strings.Join(routingParts, ", ")))
sections = append(sections, fmt.Sprintf("- Local-only resources: %d", localOnlyCount))
if redactionLabels := policyPostureRedactionLabels(policyPosture); len(redactionLabels) > 0 {
sections = append(sections, "\n### Policy Redaction Hints")
+1 -1
View File
@@ -225,7 +225,7 @@ func TestBuildUnifiedResourceContext_FullContext(t *testing.T) {
assertContains("Sensitivity: 0 public, 5 internal, 6 sensitive, 0 restricted")
assertContains("Routing: 5 cloud-summary, 6 local-first, 0 local-only")
assertContains("Policy Redaction Hints")
assertContains("Redactions in use: Alias, Hostname, IP Address, Platform ID")
assertContains("Redactions in use: Hostname, IP Address, Platform ID, Alias")
assertContains("Proxmox VE Nodes")
assertContains("HAS AGENT")
assertContains("NO AGENT")
@@ -272,6 +272,8 @@ func TestResourcePolicyPresentationUsesCanonicalLabels(t *testing.T) {
source := string(data)
requiredSnippets := []string{
"ResourceSensitivityOrder",
"ResourceRoutingScopeOrder",
"ResourceRedactionHintOrder",
"ResourceSensitivityLabel(",
"ResourceRoutingScopeLabel(",
@@ -2,6 +2,23 @@ package unifiedresources
import "sort"
// ResourceSensitivityOrder captures the canonical presentation order for
// sensitivity counts across policy surfaces.
var ResourceSensitivityOrder = []ResourceSensitivity{
ResourceSensitivityPublic,
ResourceSensitivityInternal,
ResourceSensitivitySensitive,
ResourceSensitivityRestricted,
}
// ResourceRoutingScopeOrder captures the canonical presentation order for
// routing counts across policy surfaces.
var ResourceRoutingScopeOrder = []ResourceRoutingScope{
ResourceRoutingScopeCloudSummary,
ResourceRoutingScopeLocalFirst,
ResourceRoutingScopeLocalOnly,
}
// ResourceRedactionHintOrder captures the canonical presentation order for
// redaction hints across backend and frontend policy surfaces.
var ResourceRedactionHintOrder = []ResourceRedactionHint{