export type SecurityControlStatus = "ready" | "degraded"; export type SecurityControlPlaneSummary = { source_count: number; ready_source_count: number; unavailable_source_count: number; managed_asset_count: number; expected_asset_type_count: number; present_asset_type_count: number; asset_type_coverage_percent: number; scope_count: number; controlled_scope_count: number; unowned_asset_count: number; stale_asset_count: number; orphan_asset_count: number; relationship_count: number; automation_coverage_green_percent: number; automation_coverage_unknown_count: number; compliance_violation_count: number; compliance_unknown_count: number; nist_controlled_percent: number; security_program_domain_count: number; security_program_controlled_domain_count: number; security_program_controlled_percent: number; siem_stage_count: number; siem_observed_stage_count: number; siem_stage_coverage_percent: number; ai_loop_stage_count: number; ai_loop_observed_stage_count: number; ai_loop_stage_coverage_percent: number; verified_remediation_receipt_count_24h: number; active_work_item_count: number; }; export type SecurityControlPlaneFunction = { function_id: string; label: string; controlled_percent: number; status: string; }; export type SecurityControlPlaneStage = { stage_id: string; label: string; status: "observed" | "missing"; evidence_count_24h?: number; receipt_count_24h?: number; }; export type SecurityControlPlaneScope = { scope_id: string; label: string; managed_asset_count: number; expected_type_count: number; present_type_count: number; missing_type_count: number; type_coverage_percent: number; status: string; }; export type SecurityControlPlaneWorkItem = { work_item_id: string; priority: string; control_id: string; title: string; gap_count: number; status: string; next_action: string; }; export type SecurityAssetControlPlanePayload = { schema_version: "iwooos_security_asset_control_plane_v1"; generated_at: string; status: SecurityControlStatus; source_status: string; reason_code?: string; summary: SecurityControlPlaneSummary; discovery: { latest_status: string; latest_success_at: string | null; age_seconds: number | null; freshness_slo_seconds: number; fresh: boolean; }; asset_scopes: SecurityControlPlaneScope[]; nist_csf_functions: SecurityControlPlaneFunction[]; security_program_domains: Array<{ domain_id: string; label: string; controlled_percent: number; status: string; evidence_count: number; gap_code: string | null; }>; siem: { pipeline: SecurityControlPlaneStage[]; incident_total_24h?: number; open_incident_count_24h?: number; resolved_incident_count_24h?: number; noisy_rule_count?: number; mean_time_to_resolve_minutes_24h?: number | null; }; ai_automation: { stages: SecurityControlPlaneStage[]; aggregate_stage_coverage_percent: number; accepted_ai_trace_count: number; verified_remediation_receipt_count: number; rollback_receipt_count: number; failed_operation_count: number; same_run_closed_loop_proven: boolean; same_run_closed_loop_count: number; }; security_audit: { k8s_execution_audit_count_24h: number; k8s_execution_failure_count_24h: number; mcp_tool_audit_count_24h: number; mcp_tool_failure_count_24h: number; asset_change_event_count_24h: number; automation_operation_count_24h: number; automation_failure_count_24h: number; ai_trace_count_24h: number; accepted_ai_trace_count_24h: number; immutable_external_audit_store_evidenced: boolean; }; source_health: Array<{ source_id: string; status: "ready" | "unavailable"; reason_code: string | null; }>; work_items: SecurityControlPlaneWorkItem[]; boundaries: { aggregate_only: boolean; raw_asset_identity_returned: boolean; raw_event_payload_returned: boolean; secret_value_collection_allowed: boolean; live_scan_triggered: boolean; runtime_action_triggered: boolean; completion_requires_same_run_receipts: boolean; }; }; function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null && !Array.isArray(value); } export function isSecurityAssetControlPlanePayload( value: unknown ): value is SecurityAssetControlPlanePayload { if (!isRecord(value)) return false; if (value.schema_version !== "iwooos_security_asset_control_plane_v1") return false; if (!isRecord(value.summary) || !isRecord(value.boundaries)) return false; if ( !Array.isArray(value.asset_scopes) || !Array.isArray(value.nist_csf_functions) || !Array.isArray(value.security_program_domains) ) { return false; } if (!isRecord(value.siem) || !Array.isArray(value.siem.pipeline)) return false; if (!isRecord(value.ai_automation) || !Array.isArray(value.ai_automation.stages)) { return false; } return ( typeof value.summary.managed_asset_count === "number" && typeof value.summary.source_count === "number" && Array.isArray(value.source_health) && typeof value.summary.nist_controlled_percent === "number" && value.boundaries.aggregate_only === true && value.boundaries.raw_asset_identity_returned === false && value.boundaries.raw_event_payload_returned === false && value.boundaries.secret_value_collection_allowed === false && value.boundaries.live_scan_triggered === false && value.boundaries.runtime_action_triggered === false ); } export type SecurityControlPlaneTone = "healthy" | "warning" | "critical"; export function securityControlPlaneTone( payload: SecurityAssetControlPlanePayload ): SecurityControlPlaneTone { if (payload.status !== "ready" || !payload.discovery.fresh) return "critical"; if ( payload.summary.compliance_violation_count > 0 || payload.summary.nist_controlled_percent < 50 || payload.summary.siem_stage_coverage_percent < 50 || payload.summary.ai_loop_stage_coverage_percent < 50 ) { return "critical"; } if ( payload.summary.unowned_asset_count > 0 || payload.summary.orphan_asset_count > 0 || payload.summary.automation_coverage_unknown_count > 0 || payload.summary.compliance_unknown_count > 0 || !payload.ai_automation.same_run_closed_loop_proven ) { return "warning"; } return "healthy"; } export function topSecurityControlPlaneWorkItems( payload: SecurityAssetControlPlanePayload, limit = 3 ): SecurityControlPlaneWorkItem[] { const rank: Record = { P0: 0, P1: 1, P2: 2, P3: 3 }; return [...payload.work_items] .sort( (left, right) => (rank[left.priority] ?? 99) - (rank[right.priority] ?? 99) || left.work_item_id.localeCompare(right.work_item_id) ) .slice(0, Math.max(0, limit)); }