summaryrefslogtreecommitdiff
path: root/DomainDig/Models.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 /DomainDig/Models.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 'DomainDig/Models.swift')
-rw-r--r--DomainDig/Models.swift94
1 files changed, 94 insertions, 0 deletions
diff --git a/DomainDig/Models.swift b/DomainDig/Models.swift
index f872aab..54bea10 100644
--- a/DomainDig/Models.swift
+++ b/DomainDig/Models.swift
@@ -176,6 +176,26 @@ enum CertificateWarningLevel: String, Codable {
}
}
+enum DomainHealth: String, Codable, Sendable, CaseIterable {
+ case healthy
+ case warning
+ case critical
+
+ var title: String {
+ rawValue.capitalized
+ }
+}
+
+struct PortfolioSnapshot: Codable, Sendable {
+ var totalDomains: Int
+ var healthyCount: Int
+ var warningCount: Int
+ var criticalCount: Int
+ var changedLast24h: Int
+ var expiringSoonCount: Int
+ var unreachableCount: Int
+}
+
struct DomainChangeSummary: Codable, Equatable {
let hasChanges: Bool
let changedSections: [String]
@@ -656,6 +676,80 @@ enum WatchlistSortOption: String, CaseIterable, Identifiable {
}
}
+enum PortfolioFilterOption: String, CaseIterable, Identifiable {
+ case all
+ case healthy
+ case warning
+ case critical
+ case changed
+ case expiring
+ case unreachable
+
+ var id: String { rawValue }
+
+ var title: String {
+ switch self {
+ case .all:
+ return "All"
+ case .healthy:
+ return "Healthy"
+ case .warning:
+ return "Warning"
+ case .critical:
+ return "Critical"
+ case .changed:
+ return "Changed"
+ case .expiring:
+ return "Expiring"
+ case .unreachable:
+ return "Unreachable"
+ }
+ }
+}
+
+extension DomainHealth {
+ static func classify(
+ certificateExpiryState: CertificateWarningLevel,
+ isReachable: Bool,
+ recentMonitoringFailureCount: Int,
+ hasRecentDNSChange: Bool,
+ instabilityScore: Int,
+ hasRecentCriticalChange: Bool,
+ hasInvalidTLS: Bool
+ ) -> DomainHealth {
+ if !isReachable
+ || hasInvalidTLS
+ || certificateExpiryState == .critical
+ || recentMonitoringFailureCount >= 2
+ || instabilityScore >= 70
+ || hasRecentCriticalChange {
+ return .critical
+ }
+
+ if certificateExpiryState == .warning
+ || recentMonitoringFailureCount == 1
+ || hasRecentDNSChange
+ || instabilityScore >= 35 {
+ return .warning
+ }
+
+ return .healthy
+ }
+
+ static func instabilityScore(
+ recentChangeCount: Int,
+ recentFailureCount: Int,
+ pendingAlertCount: Int,
+ hasRecentDNSChange: Bool
+ ) -> Int {
+ let rawScore = (recentChangeCount * 12)
+ + (recentFailureCount * 24)
+ + (pendingAlertCount * 8)
+ + (hasRecentDNSChange ? 14 : 0)
+ return min(rawScore, 100)
+ }
+}
+
enum PremiumCapability: String, Codable {
case unlimitedTrackedDomains
case automatedMonitoring