mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-07 00:37:36 +00:00
114 lines
4 KiB
Go
114 lines
4 KiB
Go
package ai
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
unifiedresources "github.com/rcourtman/pulse-go-rewrite/internal/unifiedresources"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type unifiedResourceExportDigest struct {
|
|
OrgID string `json:"orgId"`
|
|
DestinationModel string `json:"destinationModel"`
|
|
Summary string `json:"summary"`
|
|
ResourceCount int `json:"resourceCount"`
|
|
InfrastructureCount int `json:"infrastructureCount"`
|
|
WorkloadCount int `json:"workloadCount"`
|
|
SensitivityFloor unifiedresources.DataSensitivity `json:"sensitivityFloor"`
|
|
RouteDecision unifiedresources.ModelRouteDecision `json:"routeDecision"`
|
|
}
|
|
|
|
func (s *Service) recordUnifiedResourceExport(destinationModel, summary string, stats unifiedresources.ResourceStats, sensitivityCounts map[unifiedresources.ResourceSensitivity]int, localOnlyCount int, redactionHints []unifiedresources.ResourceRedactionHint) {
|
|
destinationModel = strings.TrimSpace(destinationModel)
|
|
summary = strings.TrimSpace(summary)
|
|
if s == nil || destinationModel == "" || summary == "" {
|
|
return
|
|
}
|
|
|
|
s.mu.RLock()
|
|
store := s.resourceExportStore
|
|
orgID := strings.TrimSpace(s.orgID)
|
|
storeOrgID := strings.TrimSpace(s.resourceExportStoreOrgID)
|
|
s.mu.RUnlock()
|
|
|
|
if store == nil || (storeOrgID != "" && storeOrgID != orgID) {
|
|
return
|
|
}
|
|
|
|
redactions := unifiedresources.ResourceRedactionLabelsFromHints(redactionHints)
|
|
|
|
sensitivityFloor := unifiedresources.ExportSensitivityFloor(sensitivityCounts)
|
|
decision, reason := unifiedresources.ExportDecisionForContext(sensitivityFloor, localOnlyCount, len(redactions))
|
|
|
|
infraCount := stats.ByType[unifiedresources.ResourceTypeAgent] +
|
|
stats.ByType[unifiedresources.ResourceTypeK8sCluster] +
|
|
stats.ByType[unifiedresources.ResourceTypeK8sNode]
|
|
workloadCount := stats.ByType[unifiedresources.ResourceTypeVM] +
|
|
stats.ByType[unifiedresources.ResourceTypeSystemContainer] +
|
|
stats.ByType[unifiedresources.ResourceTypeAppContainer] +
|
|
stats.ByType[unifiedresources.ResourceTypePod] +
|
|
stats.ByType[unifiedresources.ResourceTypeK8sDeployment]
|
|
|
|
envelope := unifiedresources.ExportEnvelope{
|
|
DestinationModel: destinationModel,
|
|
DataPayload: map[string]any{
|
|
"summary": summary,
|
|
"resourceCount": stats.Total,
|
|
"infrastructureCount": infraCount,
|
|
"workloadCount": workloadCount,
|
|
"localOnlyCount": localOnlyCount,
|
|
},
|
|
RouteDecision: unifiedresources.ModelRouteDecision{
|
|
ResourceID: "unified-resource-context",
|
|
OriginalExport: unifiedresources.ExportAllowed,
|
|
FinalDecision: decision,
|
|
AppliedRedactions: redactions,
|
|
RoutingReason: reason,
|
|
},
|
|
SensitivityFloor: sensitivityFloor,
|
|
}
|
|
|
|
hashInput := unifiedResourceExportDigest{
|
|
OrgID: orgID,
|
|
DestinationModel: envelope.DestinationModel,
|
|
Summary: summary,
|
|
ResourceCount: stats.Total,
|
|
InfrastructureCount: infraCount,
|
|
WorkloadCount: workloadCount,
|
|
SensitivityFloor: envelope.SensitivityFloor,
|
|
RouteDecision: envelope.RouteDecision,
|
|
}
|
|
payload, err := json.Marshal(hashInput)
|
|
if err != nil {
|
|
log.Warn().
|
|
Err(err).
|
|
Str("orgID", orgID).
|
|
Str("destinationModel", destinationModel).
|
|
Msg("failed to hash unified resource export envelope")
|
|
return
|
|
}
|
|
|
|
sum := sha256.Sum256(payload)
|
|
record := unifiedresources.ExportAuditRecord{
|
|
ID: uuid.NewString(),
|
|
Timestamp: time.Now().UTC(),
|
|
Actor: fmt.Sprintf("ai-service:%s", orgID),
|
|
EnvelopeHash: hex.EncodeToString(sum[:]),
|
|
Decision: decision,
|
|
Destination: destinationModel,
|
|
Redactions: redactions,
|
|
}
|
|
if err := store.RecordExportAudit(record); err != nil {
|
|
log.Warn().
|
|
Err(err).
|
|
Str("orgID", orgID).
|
|
Str("destinationModel", destinationModel).
|
|
Msg("failed to persist unified resource export audit")
|
|
}
|
|
}
|