mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-11 14:00:29 +00:00
Canonicalize policy posture ordering
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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{
|
||||
|
||||
Reference in New Issue
Block a user