summaryrefslogtreecommitdiff
path: root/DomainReportBuilder.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-04-25 00:03:59 -0500
committerChristian Cleberg <[email protected]>2026-04-25 00:03:59 -0500
commitfd34553ab0e63b4d3bc22532b61f4fef32846f34 (patch)
tree1317656b64970b113e195dcb29d71e443eb4354d /DomainReportBuilder.swift
parent3f0b7746b1bee4c2f626eb805e3fd13c5f2f5d22 (diff)
downloaddomain-dig-fd34553ab0e63b4d3bc22532b61f4fef32846f34.tar.gz
domain-dig-fd34553ab0e63b4d3bc22532b61f4fef32846f34.tar.bz2
domain-dig-fd34553ab0e63b4d3bc22532b61f4fef32846f34.zip
DomainDig v3.9.0 — Portfolio Dashboard
* Portfolio summary cards * Recent activity feed across tracked domains * Attention-required queue prioritized by severity * Certificate expiry visibility and expiring-soon section * Quick portfolio filters for triage * Deterministic per-domain health scoring * Local portfolio search * Apex-domain grouping for tracked assets
Diffstat (limited to 'DomainReportBuilder.swift')
-rw-r--r--DomainReportBuilder.swift34
1 files changed, 33 insertions, 1 deletions
diff --git a/DomainReportBuilder.swift b/DomainReportBuilder.swift
index e48b673..afed9db 100644
--- a/DomainReportBuilder.swift
+++ b/DomainReportBuilder.swift
@@ -34,6 +34,11 @@ struct DomainReport: Codable {
let riskAssessment: DomainRiskAssessment
let insights: [String]
let changeSummary: DomainChangeSummary?
+ let lastChangeDate: Date?
+ let health: DomainHealth
+ let lastMonitoringFailure: Date?
+ let instabilityScore: Int
+ let certificateExpiryState: CertificateWarningLevel
let workflowContext: DomainWorkflowContext?
let metadata: DomainReportMetadata
}
@@ -223,7 +228,29 @@ struct DomainReportBuilder {
primaryIP: String?,
changeSummary: DomainChangeSummary?
) -> DomainReport {
- DomainReport(
+ let certificateExpiryState = DomainDiffService.certificateWarningLevel(for: snapshot)
+ let recentChangeCount = changeSummary?.hasChanges == true ? 1 : 0
+ let instabilityScore = DomainHealth.instabilityScore(
+ recentChangeCount: recentChangeCount,
+ recentFailureCount: 0,
+ pendingAlertCount: 0,
+ hasRecentDNSChange: changeSummary?.changedSections.contains(where: { $0.localizedCaseInsensitiveContains("dns") }) == true
+ )
+ let hasInvalidTLS = snapshot.sslInfo == nil && snapshot.sslError != nil
+ let isReachable = !snapshot.reachabilityResults.isEmpty
+ ? snapshot.reachabilityResults.contains(where: \.reachable)
+ : snapshot.reachabilityError == nil
+ let health = DomainHealth.classify(
+ certificateExpiryState: certificateExpiryState,
+ isReachable: isReachable,
+ recentMonitoringFailureCount: 0,
+ hasRecentDNSChange: changeSummary?.changedSections.contains(where: { $0.localizedCaseInsensitiveContains("dns") }) == true,
+ instabilityScore: instabilityScore,
+ hasRecentCriticalChange: changeSummary?.impactClassification == .critical,
+ hasInvalidTLS: hasInvalidTLS
+ )
+
+ return DomainReport(
domain: snapshot.domain,
timestamp: snapshot.timestamp,
provenance: DomainReportProvenance(
@@ -309,6 +336,11 @@ struct DomainReportBuilder {
riskAssessment: analysis.riskAssessment,
insights: analysis.insights,
changeSummary: changeSummary,
+ lastChangeDate: changeSummary?.hasChanges == true ? snapshot.timestamp : nil,
+ health: health,
+ lastMonitoringFailure: nil,
+ instabilityScore: instabilityScore,
+ certificateExpiryState: certificateExpiryState,
workflowContext: workflowContext,
metadata: DomainReportMetadata(
schemaVersion: "3.7.0",