Add iPad support, auto-pinning, and comprehensive logging

- Adaptive iPhone/iPad layout with NavigationSplitView sidebar
- Auto-detect SSL-pinned domains, fall back to passthrough
- Certificate install via local HTTP server (Safari profile flow)
- App Group-backed CA, per-domain leaf cert LRU cache
- DB-backed config repository, Darwin notification throttling
- Rules engine, breakpoint rules, pinned domain tracking
- os.Logger instrumentation across tunnel/proxy/mitm/capture/cert/rules/db/ipc/ui
- Fix dyld framework embed, race conditions, thread safety
This commit is contained in:
Trey t
2026-04-11 12:52:18 -05:00
parent c77e506db5
commit 148bc3887c
77 changed files with 6710 additions and 847 deletions

View File

@@ -1,14 +1,23 @@
import Foundation
import GRDB
import os
private let log = Logger(subsystem: "com.treyt.proxyapp", category: "db")
public final class DatabaseManager: Sendable {
public let dbPool: DatabasePool
public static let shared: DatabaseManager = {
let url = FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: "group.com.treyt.proxyapp")!
.appendingPathComponent("proxy.sqlite")
return try! DatabaseManager(path: url.path)
let url = AppGroupPaths.containerURL.appendingPathComponent("proxy.sqlite")
log.info("DB path: \(url.path)")
do {
let mgr = try DatabaseManager(path: url.path)
log.info("DatabaseManager initialized OK")
return mgr
} catch {
log.fault("DatabaseManager FATAL: \(error.localizedDescription)")
fatalError("[DatabaseManager] Failed to initialize database at \(url.path): \(error)")
}
}()
public init(path: String) throws {
@@ -129,6 +138,65 @@ public final class DatabaseManager: Sendable {
}
}
migrator.registerMigration("v2_create_proxy_configuration") { db in
try db.create(table: "proxy_configuration") { t in
t.column("id", .integer).primaryKey(onConflict: .replace)
t.column("sslProxyingEnabled", .boolean).notNull().defaults(to: false)
t.column("blockListEnabled", .boolean).notNull().defaults(to: false)
t.column("breakpointEnabled", .boolean).notNull().defaults(to: false)
t.column("noCachingEnabled", .boolean).notNull().defaults(to: false)
t.column("dnsSpoofingEnabled", .boolean).notNull().defaults(to: false)
t.column("hideSystemTraffic", .boolean).notNull().defaults(to: false)
t.column("updatedAt", .double).notNull()
}
try db.execute(
sql: """
INSERT INTO proxy_configuration (
id, sslProxyingEnabled, blockListEnabled, breakpointEnabled,
noCachingEnabled, dnsSpoofingEnabled, hideSystemTraffic, updatedAt
) VALUES (1, 0, 0, 0, 0, 0, 0, ?)
""",
arguments: [Date().timeIntervalSince1970]
)
}
migrator.registerMigration("v3_create_proxy_runtime_status") { db in
try db.create(table: "proxy_runtime_status") { t in
t.column("id", .integer).primaryKey(onConflict: .replace)
t.column("tunnelState", .text).notNull().defaults(to: ProxyRuntimeState.stopped.rawValue)
t.column("proxyHost", .text)
t.column("proxyPort", .integer)
t.column("caFingerprint", .text)
t.column("lastProxyError", .text)
t.column("lastMITMError", .text)
t.column("lastConnectError", .text)
t.column("lastSuccessfulMITMDomain", .text)
t.column("lastSuccessfulMITMAt", .double)
t.column("lastExtensionStartAt", .double)
t.column("lastExtensionStopAt", .double)
t.column("updatedAt", .double).notNull()
}
try db.execute(
sql: """
INSERT INTO proxy_runtime_status (
id, tunnelState, updatedAt
) VALUES (1, ?, ?)
""",
arguments: [ProxyRuntimeState.stopped.rawValue, Date().timeIntervalSince1970]
)
}
migrator.registerMigration("v4_create_pinned_domains") { db in
try db.create(table: "pinned_domains") { t in
t.autoIncrementedPrimaryKey("id")
t.column("domain", .text).notNull().unique()
t.column("reason", .text)
t.column("detectedAt", .double).notNull()
}
}
try migrator.migrate(dbPool)
}
}