import CoreGraphics
import Foundation
import NucleicMDM
import Security

/// Guest execution target for MDM orchestration. Base-maintenance VMs are intentionally absent from
/// the ordinary `live` registry, so Mode A must be able to address their instance directly.
private enum MDMGuestTarget: Sendable {
    case registered(name: String)
    #if arch(arm64)
    case instance(MacVMInstance, name: String)
    #endif

    var name: String {
        switch self {
        case .registered(let name): return name
        #if arch(arm64)
        case .instance(_, let name): return name
        #endif
        }
    }

    #if arch(arm64)
    /// The direct maintenance instance behind a Mode A base target, if any. Mode A can power-cycle it
    /// to trigger the login-time MDM sync; a Mode B `.registered` live clone has no such handle (and
    /// must not be rebooted out from under a user's session).
    var maintenanceInstance: MacVMInstance? {
        if case .instance(let instance, _) = self { return instance }
        return nil
    }
    #endif
}

// Host-side orchestration for the Nucleic MDM plane (docs/MACOS_VM_MDM.md §4). These are the reusable
// building blocks the provisioning flow (Mode A) and the live-clone push path (Mode B) call. The MDM
// *protocol* server, CA, and artifact generation live in the `NucleicMDM` module; this file wires them
// to a running guest via the existing vsock exec transport (registered clone or direct maintenance
// instance), and the `MacVMSurfaceHost` for GUI approval. Everything here is Darwin-only in
// effect (it drives `NucleicMDMServer`, which is `#if canImport(Network)`).
//
// NOT unit-testable without a live guest — the guest-side enroll, the UAMDM GUI approval, and the
// no-APNs drain are the P0 hardware spike (§8). The pieces they compose (CA, PKCS#12, the protocol
// server + queue) ARE covered by `NucleicMDMTests`.
extension MacVMEngine {
    /// Outcome of an enrollment or push attempt, with a captured log for the provisioning STATUS line
    /// and the settings panel.
    public struct MDMOutcome: Sendable {
        public var enrolled: Bool
        public var profilesInstalled: Int
        public var log: [String]
    }

    enum BaseMDMPolicyAction: Equatable {
        case enroll
        case update
        case orphanedEnrollment
    }

    /// Decide without mutating host state. In particular, an enrolled guest with no persisted identity
    /// must be rejected before `loadOrCreateMDMController` could write an unrelated replacement CA.
    static func baseMDMPolicyAction(
        guestEnrolled: Bool, persistedStateExists: Bool
    ) -> BaseMDMPolicyAction {
        if guestEnrolled { return persistedStateExists ? .update : .orphanedEnrollment }
        return .enroll
    }

    /// The only UI states Mode A is allowed to act on. Every actionable case carries a bounding box
    /// produced from the current framebuffer; `unknown` means no input may be sent.
    ///
    /// `authenticate` carries only the password *field* box — it is answered by clicking that field,
    /// typing, and pressing **Return** to activate the default button, rather than OCR-matching a
    /// specific button label. Live runs showed Vision mangling both the field placeholder
    /// ("Password" → "Peseword") and the button ("Update Settings" → "Updale Settings"), so keying on
    /// exact labels was the core fragility; Return-to-submit removes the button dependency, and the
    /// field is found by fuzzy match (see ``passwordFieldBox``).
    enum UAMDMApprovalAction: Equatable {
        case openEnrollmentProfile(CGRect)
        case install(CGRect)
        /// `sheet` identifies WHICH authorization sheet this is, so each gets its own retry budget.
        case authenticate(sheet: String, passwordField: CGRect)
        case installed
        /// macOS put a *failure* alert on screen ("Profile installation failed. The certificate could
        /// not be verified"). Previously unrecognized: the loop idled past it to its 300 s deadline
        /// and reported a generic timeout, discarding the one screen that named the fault.
        case installFailed(String)
        case unknown
    }

    /// The vocabulary these approval screens are built from, lowercased and single-word.
    ///
    /// Handed to Vision as `customWords` so language correction has this flow's proper nouns and UI
    /// labels in its prior, and used to choose between the alternate readings Vision returns for a
    /// line (``bestCandidate(among:lexicon:)``). It is a *preference*, never a rewrite: a word not in
    /// here is recognized exactly as before.
    ///
    /// Single words on purpose — `customWords` is matched at the word-recognition stage, so a phrase
    /// entry would never match anything.
    static let approvalLexicon: Set<String> = [
        // What the profile and this flow are called.
        "nucleic", "mdm", "enrollment", "enroll", "agent", "device", "management",
        // The Device Management pane and its row states.
        "profile", "profiles", "install", "installed", "downloaded", "verified", "settings",
        "setting", "configuration", "remote", "supervision", "work", "school", "account",
        // The SecurityAgent authorization sheets.
        "password", "passcode", "certificate", "trust", "system", "modify", "authenticate",
        "administrator", "unlock",
        // Buttons the loop must either press or scrupulously avoid.
        "continue", "cancel", "ignore", "allow", "deny", "update", "review", "done",
    ]

    /// A stable slug for the authorization sheet on screen. The enroll flow raises several in
    /// sequence — System certificate trust, then the MDM enrollment itself — and a single shared retry
    /// budget spent on the first leaves the last one unanswered, which is exactly how a live run
    /// stalled on "Device Management is trying to enroll you…" after exhausting its attempts upstream.
    static func authSheetKey(in joined: String) -> String {
        func has(_ s: String) -> Bool { fuzzyContains(joined, s) }
        if has("Certificate Trust") || has("System Certificate") { return "certificate-trust" }
        if has("remote management") || has("enroll you in") { return "mdm-enroll" }
        if has("modify your system settings") { return "modify-settings" }
        if has("configuration profile") || has("install a new") { return "profile-install" }
        return "generic"
    }

    /// Levenshtein distance, bounded use — for tolerating OCR substitutions in short UI labels.
    static func editDistance(_ a: String, _ b: String) -> Int {
        let s = Array(a), t = Array(b)
        if s.isEmpty { return t.count }
        if t.isEmpty { return s.count }
        var prev = Array(0...t.count)
        var curr = [Int](repeating: 0, count: t.count + 1)
        for i in 1...s.count {
            curr[0] = i
            for j in 1...t.count {
                let cost = s[i - 1] == t[j - 1] ? 0 : 1
                curr[j] = min(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + cost)
            }
            swap(&prev, &curr)
        }
        return prev[t.count]
    }

    /// Glyphs Vision interchanges on rendered UI text, folded onto one representative. Small and
    /// deliberate: every entry is a pair that is genuinely ambiguous at a body-label size (`I`/`l`/`1`
    /// share a stroke, `O`/`0` an outline), and each merge slightly increases the chance that two
    /// *different* words compare equal, so speculative additions cost accuracy rather than buying it.
    private static let ocrConfusables: [Character: Character] = [
        "1": "l", "i": "l", "|": "l", "!": "l",
        "0": "o",
        "5": "s",
    ]

    /// Fold a recognized string into the form all comparisons happen in: lowercased, glyph-confusions
    /// merged (``ocrConfusables``), punctuation reduced to spaces, and whitespace collapsed.
    ///
    /// This is the layer that was missing. Everything below matched OCR output *exactly* —
    /// `text == "Enroll"`, `contains("Enrollment")` — while the one place that didn't
    /// (``passwordFieldBox``) was fuzzy precisely because a live run proved Vision mangles these
    /// labels. So a single wrong glyph in the button meant the classifier returned `.unknown`, the
    /// loop treated a perfectly good review sheet as nothing to act on, and the pass burned its
    /// deadline re-navigating panes. Folding first, then allowing a bounded edit distance, makes every
    /// match as forgiving as the password field's already was.
    static func ocrFold(_ s: String) -> String {
        var out = ""
        out.reserveCapacity(s.count)
        var pendingSpace = false
        for character in s.lowercased() {
            let folded = ocrConfusables[character] ?? character
            if folded.isLetter || folded.isNumber {
                if pendingSpace, !out.isEmpty { out.append(" ") }
                pendingSpace = false
                out.append(folded)
            } else {
                // Punctuation and whitespace alike become ONE separator: "Double-click" and "Double
                // click" must fold together, and a stray recognized comma must not split a phrase.
                pendingSpace = true
            }
        }
        return out
    }

    /// How many folded characters may differ before two strings are considered different things.
    /// Roughly one damaged glyph in eight, floored at one.
    ///
    /// Tuned against what the recognizer actually does now that it reads a native-resolution capture:
    /// isolated substitutions, not wholesale garbage. Being generous here is not free — `fuzzyContains`
    /// searches every window of the joined screen text, so a large tolerance on a short phrase starts
    /// finding matches in unrelated chrome.
    static func ocrTolerance(for folded: String) -> Int { max(1, folded.count / 8) }

    /// Whether a recognized line reads as `label` — folded equality, else a bounded edit distance.
    /// The length guard is what keeps "Don't Install" from reading as the "Install" button.
    static func fuzzyEquals(_ line: String, _ label: String) -> Bool {
        let a = ocrFold(line), b = ocrFold(label)
        if a == b { return true }
        let tolerance = ocrTolerance(for: b)
        guard abs(a.count - b.count) <= tolerance else { return false }
        return editDistance(a, b) <= tolerance
    }

    /// Whether `haystack` contains a passage that reads as `needle`.
    ///
    /// Approximate substring search: ordinary edit-distance DP, but with the match free to *begin* at
    /// any word boundary and to *end* at any word boundary, so an OCR slip inside a wrapped sentence
    /// no longer hides the whole phrase.
    ///
    /// The word-boundary anchoring is not a refinement — a free-floating version of this is wrong.
    /// Allowing a match to start mid-word lets "Nucleic MDM Enrollme**nt Installed**" read as "not
    /// installed" for one insertion, which is exactly the negation the `.installed` classification
    /// checks: a *successfully installed* profile classified as not-installed, and the loop clicking
    /// a row that had nothing left to do. Real UI phrases always start and end on word boundaries, so
    /// requiring that costs nothing and removes a whole class of coincidental hit.
    static func fuzzyContains(_ haystack: String, _ needle: String) -> Bool {
        let n = Array(ocrFold(needle)), h = Array(ocrFold(haystack))
        guard !n.isEmpty else { return true }
        guard !h.isEmpty else { return false }
        let tolerance = ocrTolerance(for: String(n))
        // Folding leaves a single space as the only separator, so a boundary is exactly a space.
        func isWordStart(_ j: Int) -> Bool { j == 0 || h[j - 1] == " " }
        func isWordEnd(_ j: Int) -> Bool { j == h.count || h[j] == " " }
        // Larger than any reachable distance, so an ineligible start can never win the `min`.
        let unreachable = h.count + n.count + 1
        var prev = (0...h.count).map { isWordStart($0) ? 0 : unreachable }
        var curr = [Int](repeating: 0, count: h.count + 1)
        for i in 1...n.count {
            curr[0] = i
            for j in 1...h.count {
                let cost = n[i - 1] == h[j - 1] ? 0 : 1
                curr[j] = min(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + cost)
            }
            swap(&prev, &curr)
        }
        return (0...h.count).contains { isWordEnd($0) && prev[$0] <= tolerance }
    }

    /// Locate the password field's click target in a recognized SecurityAgent sheet, tolerant of OCR
    /// noise. macOS renders "Password" as the placeholder *inside* the field, so its box center is the
    /// click point; but OCR frequently corrupts the word, so match any short token within edit distance
    /// 2 of "password" (e.g. "Peseword"). When several match, take the lowest on screen (the field sits
    /// below the account row). `nil` when no plausible field is visible — the caller then does nothing.
    /// Placeholder spellings a password field may present. Matched fuzzily, so this only needs to cover
    /// genuinely different words rather than every way OCR can mangle one.
    static let passwordPlaceholders = ["password", "passcode", "pin"]

    /// Whether one recognized line is Device Management's installed-profile subtitle — `1 setting`,
    /// `3 settings`. Matched as a whole line on purpose: the bare substring " setting" also occurs in
    /// "System Settings", which is present in the menu bar of every screen this loop inspects.
    static func isSettingsCountLine(_ text: String) -> Bool {
        let parts = text.trimmingCharacters(in: .whitespacesAndNewlines)
            .lowercased()
            .split(separator: " ", omittingEmptySubsequences: true)
        guard parts.count == 2,
              parts[0].allSatisfy(\.isNumber), !parts[0].isEmpty,
              parts[1] == "setting" || parts[1] == "settings"
        else { return false }
        return true
    }

    static func passwordFieldBox(in lines: [(text: String, box: CGRect)]) -> CGRect? {
        let candidates = lines.compactMap { line -> CGRect? in
            let token = ocrFold(line.text)
            guard !token.isEmpty, token.count <= 14 else { return nil }
            // Tolerance scales with the word: a fixed distance of 2 is generous on "pin" and stingy on
            // "password". Roughly a quarter of the characters may be wrong, which covers the observed
            // OCR damage ("Peseword") without letting unrelated short words in.
            let matched = passwordPlaceholders.map(ocrFold).contains { candidate in
                guard abs(token.count - candidate.count) <= 2 else { return false }
                let tolerance = max(1, candidate.count / 4)
                return editDistance(token, candidate) <= tolerance
            }
            return matched ? line.box : nil
        }
        // Lowest on screen: the password field sits below the account row, and on a sheet that shows
        // both, the lower one is the field we must type into.
        return candidates.min { $0.midY < $1.midY }
    }

    /// Classify OCR lines from System Settings / SecurityAgent into the one action, if any, that is
    /// safe to take. Two robustness rules learned from live macOS 27 runs:
    ///
    ///  * **Context phrases match the lines joined in reading order**, not line by line — Vision emits
    ///    one observation per rendered line, so a sheet's sentence wraps across several and a per-line
    ///    substring test misses it.
    ///  * **Any Apple authorization password sheet is answerable**, detected by the stable phrase
    ///    "Enter your password" plus a fuzzily-located Password field — not by a sheet-specific label.
    ///    In the sealed base build the only password sheets are our own provisioning prompts, and the
    ///    only secret typed is the machine's own agent password, so a generic detector is both safe and
    ///    far less brittle than matching exact wording that OCR corrupts. A locale without the English
    ///    phrase yields `unknown` rather than speculative input.
    /// A profile the surface is driving through Device Management. `keyword` is a short, distinctive
    /// fragment of the profile's display name — matched case-insensitively as a substring so ordinary
    /// OCR noise elsewhere in the row cannot hide it.
    struct ProfileTarget: Sendable, Equatable {
        let displayName: String
        let keyword: String

        static let enrollment = ProfileTarget(
            displayName: "Nucleic MDM Enrollment", keyword: "Enrollment")
    }

    static func uamdmApprovalAction(
        in lines: [(text: String, box: CGRect)],
        profile: ProfileTarget = .enrollment
    ) -> UAMDMApprovalAction {
        let normalized = lines.map {
            (text: $0.text.trimmingCharacters(in: .whitespacesAndNewlines), box: $0.box)
        }
        // Every matcher below is fuzzy (``ocrFold`` + a bounded edit distance). Exact comparison is
        // what made this classifier the flow's weakest link: one substituted glyph in a six-letter
        // button label was the difference between pressing Enroll and classifying the review sheet as
        // `.unknown`.
        func labelled(_ text: String) -> [CGRect] {
            normalized.filter { fuzzyEquals($0.text, text) }.map(\.box)
        }
        let joined = normalized.map(\.text).joined(separator: " ")
        func contains(_ fragment: String) -> Bool {
            fuzzyContains(joined, fragment)
        }
        func lowest(_ boxes: [CGRect]) -> CGRect? {
            boxes.min { $0.midY < $1.midY }
        }

        // Row/context matching is keyed to the profile currently being driven, so the same loop can
        // install the CA root first and the enrollment profile afterwards.
        func rowBoxes() -> [CGRect] {
            normalized
                .filter { fuzzyContains($0.text, profile.keyword) }
                .map(\.box)
        }
        // Checked FIRST: a failure alert sits on top of the Device Management pane, so every later
        // rule would still match the row underneath it and the loop would keep "working" against a
        // dead screen. Matched on fragments that survive OCR damage and cannot plausibly appear on a
        // healthy screen in this flow.
        for fragment in ["installation failed", "could not be verified", "failed to install"]
        where contains(fragment) {
            return .installFailed(joined)
        }

        // A HINT that the profile has landed — never the answer. macOS 27's Device Management renders
        // an installed profile as its display name over an "<n> settings" subtitle and never prints
        // the word "Installed", so that word alone cannot detect a completed install.
        //
        // The subtitle is matched as a WHOLE LINE (`3 settings`), not as a substring of the joined
        // text. Substring matching was a live regression: " setting" occurs inside "System Settings"
        // in the menu bar of every screen this loop ever sees, so the hint fired constantly — a run
        // classified twenty consecutive frames as `.installed` while the row on them read "Profile not
        // installed. Double-click to review", and the loop never clicked it.
        //
        // The explicit-negation guard is belt-and-braces for the same failure: whatever else is on
        // screen, a row that says it is NOT installed is not installed.
        if contains(profile.keyword), !contains("not installed"),
           !labelled("Installed").isEmpty || contains("This profile is installed")
            || normalized.contains(where: { Self.isSettingsCountLine($0.text) })
        {
            return .installed
        }

        // Any Apple authorization password sheet (trust settings, profile install, unlock, …). The
        // canonical SecurityAgent line is stable even when the rest of the sheet wraps or mis-OCRs; a
        // located password field is the only other requirement, and Return submits.
        if contains("Enter your password") || contains("enter password"),
           let password = Self.passwordFieldBox(in: normalized)
        {
            return .authenticate(
                sheet: Self.authSheetKey(in: joined), passwordField: password)
        }

        // The profile-review sheet ("Are you sure you want to install this device profile?") confirms
        // with an **Enroll** button on macOS 27, not "Install" — a live run stalled because the
        // classifier only knew "Install". Accept both in a Nucleic context. The "Install…"/"Install..."
        // variants need no entries of their own: `ocrFold` drops trailing punctuation, so an ellipsis
        // (however Vision renders it) folds onto the bare label.
        let enrollmentContext = contains(profile.keyword)
            || contains("Nucleic Device Management")
            || contains("install this device profile")
            || (contains("Device Management") && contains("Nucleic"))
        if enrollmentContext,
           let install = lowest(labelled("Enroll") + labelled("Install"))
        {
            return .install(install)
        }
        if let row = lowest(rowBoxes()) {
            return .openEnrollmentProfile(row)
        }
        return .unknown
    }

    public enum MDMOrchestrationError: Error, CustomStringConvertible {
        case guestCommandFailed(String)
        case enrollmentNotApproved(String)
        case missingPolicyAssets([String])
        case invalidPolicyProfile(String)
        case orphanedEnrollment(String)
        case policyCommandsFailed([String: String])
        case profilesMissing([String])
        case drainTimedOut(pending: Int)
        case preflightFailed(String)
        case profileInstallRejected(String)
        /// The host cannot read the guest's screen at all, so no GUI approval is possible. Raised
        /// **before** the approval loop by its self-test rather than after a five-minute timeout that
        /// blamed the guest.
        case textRecognitionUnavailable(String)
        public var description: String {
            switch self {
            case .guestCommandFailed(let s): return "MDM guest step failed: \(s)"
            case .enrollmentNotApproved(let s): return "MDM enrollment not approved: \(s)"
            case .missingPolicyAssets(let names):
                return "required MDM policy assets are missing: \(names.joined(separator: ", "))"
            case .invalidPolicyProfile(let detail):
                return "invalid MDM policy profile: \(detail)"
            case .orphanedEnrollment(let detail):
                return "the guest MDM enrollment has no matching host identity: \(detail)"
            case .policyCommandsFailed(let statuses):
                let summary = statuses.keys.sorted().map { "\($0)=\(statuses[$0]!)" }
                    .joined(separator: ", ")
                return "MDM policy commands did not all acknowledge: \(summary)"
            case .profilesMissing(let identifiers):
                return "MDM reported success but required profiles are missing: "
                    + identifiers.joined(separator: ", ")
            case .drainTimedOut(let p): return "MDM command drain timed out with \(p) still queued"
            case .profileInstallRejected(let screen):
                return "macOS rejected the enrollment profile at install time. On-screen: \(screen). "
                    + "The ManagedClient log in this attempt's diagnostics names the failing "
                    + "validation step."
            case .textRecognitionUnavailable(let detail):
                return "the host cannot read the guest's screen, so the MDM approval cannot be "
                    + "driven: \(detail). Every step of this pass (opening the profile, pressing "
                    + "Enroll, answering the password sheet) is driven by recognizing text in the "
                    + "framebuffer, so this is fatal rather than degraded."
            case .preflightFailed(let detail):
                return "MDM pre-flight failed — the guest cannot complete this enrollment "
                    + "(reach=server reachable at all [required], profile=staged profile parses as "
                    + "plist or cms [required], ssl=CA in the system trust store [advisory — the "
                    + "profile pins its own CA instead], tls=curl/LibreSSL handshake [advisory]): "
                    + "\(detail)"
            }
        }
    }

    /// Profiles that make the ordinary VM-agent path non-interactive. Keep this list small: these
    /// policies are installed into every golden base, unlike optional semantic-AX declarations.
    static let builtInMDMPolicyProfileNames = [
        "nucleic-vmagent-fda.mobileconfig",
        "nucleic-suppress-notifications.mobileconfig",
    ]

    /// Resolve the complete built-in policy set from a packaged app first, then the source tree for
    /// SwiftPM/development runs. A partial set is never accepted: silently omitting one policy would
    /// turn a deterministic build failure back into a GUI prompt later in provisioning.
    static func builtInMDMPolicyProfileURLs(
        bundleResourceURL: URL?, devRepoRoot: URL?
    ) -> [URL]? {
        let fm = FileManager.default
        let candidateDirectories = [
            bundleResourceURL?.appendingPathComponent("macvm", isDirectory: true),
            devRepoRoot?.appendingPathComponent("scripts/macos-notification-fix", isDirectory: true),
        ]
        for directory in candidateDirectories.compactMap({ $0 }) {
            let urls = builtInMDMPolicyProfileNames.map { directory.appendingPathComponent($0) }
            if urls.allSatisfy({ fm.isReadableFile(atPath: $0.path) }) { return urls }
        }
        return nil
    }

    /// Extract the top-level identifiers that must appear in the guest's configuration inventory.
    /// Payload UUIDs and nested payload identifiers are intentionally not accepted as substitutes.
    static func configurationProfileIdentifiers(in profiles: [Data]) throws -> [String] {
        try profiles.enumerated().map { index, data in
            let dictionary: [String: Any]
            do { dictionary = try MDMPlist.parse(data) }
            catch {
                throw MDMOrchestrationError.invalidPolicyProfile(
                    "profile \(index + 1) is not a property-list dictionary: \(error)")
            }
            guard dictionary["PayloadType"] as? String == "Configuration",
                  let identifier = dictionary["PayloadIdentifier"] as? String,
                  !identifier.isEmpty
            else {
                throw MDMOrchestrationError.invalidPolicyProfile(
                    "profile \(index + 1) has no top-level Configuration PayloadIdentifier")
            }
            return identifier
        }
    }

    /// Rewrite PPPC entries to the designated requirement of the exact agent bundle this build will
    /// install. Release agents retain their stable Developer ID chain; ad-hoc development agents get
    /// their actual requirement instead of silently receiving a profile for an unrelated Team ID.
    static func policyProfiles(
        _ profiles: [Data], agentCodeRequirement: String
    ) throws -> [Data] {
        var replacements = 0
        let rewritten = try profiles.map { data -> Data in
            var root = try MDMPlist.parse(data)
            guard var content = root["PayloadContent"] as? [[String: Any]] else { return data }
            var changed = false
            for payloadIndex in content.indices {
                guard content[payloadIndex]["PayloadType"] as? String
                        == "com.apple.TCC.configuration-profile-policy",
                      var services = content[payloadIndex]["Services"] as? [String: Any]
                else { continue }
                for service in ["SystemPolicyAllFiles", "SystemPolicyNetworkVolumes"] {
                    guard var entries = services[service] as? [[String: Any]] else { continue }
                    for entryIndex in entries.indices
                    where entries[entryIndex]["Identifier"] as? String
                        == "xyz.blakeslee.nucleic.vmagent"
                    {
                        entries[entryIndex]["CodeRequirement"] = agentCodeRequirement
                        replacements += 1
                        changed = true
                    }
                    services[service] = entries
                }
                content[payloadIndex]["Services"] = services
            }
            guard changed else { return data }
            root["PayloadContent"] = content
            return try PropertyListSerialization.data(
                fromPropertyList: root, format: .xml, options: 0)
        }
        guard replacements == 2 else {
            throw MDMOrchestrationError.invalidPolicyProfile(
                "expected exactly two VM-agent PPPC entries, rewrote \(replacements)")
        }
        return rewritten
    }

    /// Read the same designated requirement TCC evaluates, directly from the staged code object.
    /// Using Security.framework avoids spawning and scraping `codesign`, which can be unavailable to
    /// the packaged app even though its own nested agent has a valid signature.
    static func designatedRequirement(forAgentAt app: URL) -> String? {
        let flags = SecCSFlags(rawValue: 0)
        var staticCode: SecStaticCode?
        guard SecStaticCodeCreateWithPath(app as CFURL, flags, &staticCode) == errSecSuccess,
              let staticCode
        else { return nil }

        var requirement: SecRequirement?
        guard SecCodeCopyDesignatedRequirement(staticCode, flags, &requirement) == errSecSuccess,
              let requirement
        else { return nil }

        var text: CFString?
        guard SecRequirementCopyString(requirement, flags, &text) == errSecSuccess,
              let text
        else { return nil }
        let value = text as String
        return value.isEmpty ? nil : value
    }

    /// The **compiled** designated-requirement blob TCC stores in `access.csreq`, read straight from the
    /// staged code object — the Lane B (docs/MACOS_VM_POLICY_ALTERNATIVE.md) sibling of
    /// ``designatedRequirement(forAgentAt:)``. Same `SecStaticCode` → `SecRequirement` chain that the
    /// PPPC rewrite uses for the requirement *string*, but ending in `SecRequirementCopyData` for the
    /// binary blob a direct `TCC.db` row needs (a PPPC profile takes the string; a TCC row takes this).
    ///
    /// So a Developer-ID and an ad-hoc dev build both authorize the binary actually installed —
    /// identical to the current template rewrite. `nil` when the app has no derivable requirement (an
    /// unsigned/ad-hoc build without a stable identity); the caller then writes a `csreq`-NULL row,
    /// which TCC still honors by bundle id alone on current builds, and logs the durability caveat.
    static func designatedRequirementData(forAgentAt app: URL) -> Data? {
        let flags = SecCSFlags(rawValue: 0)
        var staticCode: SecStaticCode?
        guard SecStaticCodeCreateWithPath(app as CFURL, flags, &staticCode) == errSecSuccess,
              let staticCode
        else { return nil }

        var requirement: SecRequirement?
        guard SecCodeCopyDesignatedRequirement(staticCode, flags, &requirement) == errSecSuccess,
              let requirement
        else { return nil }

        var data: CFData?
        guard SecRequirementCopyData(requirement, flags, &data) == errSecSuccess,
              let data
        else { return nil }
        let blob = data as Data
        return blob.isEmpty ? nil : blob
    }

    /// Load the exact policy payloads to queue during Mode A enrollment, bound to the actual agent.
    func resolveBuiltInMDMPolicyProfiles() throws -> [Data] {
        guard let urls = Self.builtInMDMPolicyProfileURLs(
            bundleResourceURL: Bundle.main.resourceURL,
            devRepoRoot: Self.devRepoRoot())
        else {
            throw MDMOrchestrationError.missingPolicyAssets(Self.builtInMDMPolicyProfileNames)
        }
        guard let agent = resolveVMAgentApp(),
              let requirement = Self.designatedRequirement(forAgentAt: agent),
              !requirement.isEmpty
        else {
            throw MDMOrchestrationError.invalidPolicyProfile(
                "could not derive the staged VM agent's designated code requirement")
        }
        return try Self.policyProfiles(
            urls.map { try Data(contentsOf: $0) }, agentCodeRequirement: requirement)
    }

    /// Load the identity already associated with this base, or create it exactly once. A corrupt or
    /// unsupported state file is fatal: replacing it would orphan the enrollment baked into the VM.
    func loadOrCreateMDMController(for bundle: MacVMBundle) throws -> MDMServerController {
        if FileManager.default.fileExists(atPath: bundle.mdmStateURL.path) {
            return try MDMServerController.loadPersistedState(from: bundle.mdmStateURL)
        }
        let controller = try MDMServerController.makeFresh()
        try controller.writePersistedState(to: bundle.mdmStateURL)
        return controller
    }

    // MARK: - Mode A — enroll the base at build time

    #if arch(arm64)
    /// Install or update the base policy without ever enrolling twice. Guest enrollment status is the
    /// source of truth; persisted host state is mandatory before updating an existing enrollment.
    func applyBaseMDMPolicies(
        instance: MacVMInstance,
        name: String,
        bundle: MacVMBundle,
        shareDir: URL,
        hostBindAddress: String? = nil,
        profiles: [Data],
        surface: any MacVMSurfaceHost,
        approvalTimeout: TimeInterval = 300
    ) async throws -> MDMOutcome {
        let target = MDMGuestTarget.instance(instance, name: name)
        let bindAddress: String
        if let hostBindAddress {
            bindAddress = hostBindAddress
        } else {
            bindAddress = try await discoverMDMHostBindAddress(target: target)
        }
        let stateExists = FileManager.default.fileExists(atPath: bundle.mdmStateURL.path)
        let enrolled = await verifyEnrolled(target: target)
        switch Self.baseMDMPolicyAction(
            guestEnrolled: enrolled, persistedStateExists: stateExists)
        {
        case .orphanedEnrollment:
            throw MDMOrchestrationError.orphanedEnrollment(
                "the guest reports User Approved, but \(bundle.mdmStateURL.path) is absent; "
                    + "refusing to replace its CA or attempt a second enrollment")
        case .update:
            let controller = try loadOrCreateMDMController(for: bundle)
            return try await pushProfiles(
                target: target, profiles: profiles, controller: controller,
                hostBindAddress: bindAddress, timeout: approvalTimeout, baseBundle: bundle)
        case .enroll:
            let controller = try loadOrCreateMDMController(for: bundle)
            return try await enrollBaseInMDM(
                target: target, bundle: bundle, shareDir: shareDir,
                hostBindAddress: bindAddress, profiles: profiles, surface: surface,
                controller: controller, approvalTimeout: approvalTimeout)
        }
    }
    #endif

    private func enrollBaseInMDM(
        target: MDMGuestTarget,
        bundle: MacVMBundle,
        shareDir: URL,
        hostBindAddress: String,
        profiles: [Data],
        surface: any MacVMSurfaceHost,
        controller: MDMServerController?,
        approvalTimeout: TimeInterval
    ) async throws -> MDMOutcome {
        var log: [String] = []
        let controller = try controller ?? loadOrCreateMDMController(for: bundle)
        // One evidence directory for the whole attempt. Every step note below is mirrored into its
        // transcript alongside the server's protocol lines, so a failure can be read as one ordered
        // story instead of correlating an error string against the unified log by hand.
        let recorder = MDMDiagnosticsRecorder(bundle: bundle, label: "enroll")
        func step(_ line: String) {
            log.append(line)
            recorder?.note(line)
        }

        // Stage artifacts into the share and pre-queue the profiles.
        try controller.stageArtifacts(into: shareDir)
        let commandUUIDs = await controller.queueInstallProfiles(profiles)
        step("staged MDM artifacts into \(shareDir.lastPathComponent); queued \(profiles.count) profile(s)")

        // Start the server on the vmnet-facing address (+ IP SAN so the cert also matches the raw IP).
        let server = controller.makeServer(
            debug: recorder?.serverDebugLog,
            log: recorder?.protocolLogSink ?? Self.mdmUnifiedLogSink)
        let ipSANs = hostBindAddress == "127.0.0.1" ? [] : [hostBindAddress]
        _ = try await server.start(host: hostBindAddress, ipSANs: ipSANs)
        defer { Task { await server.stop() } }
        step("MDM server listening on \(hostBindAddress):\(controller.config.port)")

        // Run the guest enroll step (root; trusts the CA, pins /etc/hosts, opens the profile). This
        // runs through the agent on a normally-booted guest, where the provision share is reachable at
        // its automount path. Mode A addresses the maintenance instance directly because base VMs
        // deliberately never enter the ordinary session registry.
        let scriptGuestPath =
            Self.guestSharePath(os: .macOS, name: Self.provisionShareName)
            + "/\(MDMServerController.Artifact.enrollScript)"
        // Run the enroll script as the console (agent) user, NOT under `sudo bash`: `open` must
        // register the profile for the console user's System Settings, and its privileged steps
        // self-elevate via passwordless sudo (see MDMServerController.enrollScript).
        let enroll = try await runMDMGuest(
            target, command: "/bin/bash \(Self.shQuote(scriptGuestPath))")
        // The enroll script narrates its progress (gateway discovery, hosts pin, CA trust) on stdout,
        // so a failure message built from stderr alone discards the half that says how far it got —
        // and the "exit 0 but no marker" case discards all of it.
        recorder?.note(
            "mdm-enroll.sh exit \(enroll.exitCode)\n"
                + Self.indentedGuestOutput(stdout: enroll.stdout, stderr: enroll.stderr))
        guard enroll.exitCode == 0, enroll.stdout.contains("MDM_ENROLL_STAGED") else {
            throw MDMOrchestrationError.guestCommandFailed(
                "mdm-enroll.sh exit \(enroll.exitCode) (marker "
                    + "\(enroll.stdout.contains("MDM_ENROLL_STAGED") ? "present" : "absent")): "
                    + Self.boundedGuestOutput(stdout: enroll.stdout, stderr: enroll.stderr))
        }
        step("guest enroll staged (/etc/hosts pinned, CA root profile queued)")

        // Can the guest resolve, connect to, and TLS-validate the MDM server? Recorded around each
        // phase: the host listener only logs requests that actually arrive, so without this a guest
        // that never connects is indistinguishable from one the server rejected.
        func recordReachability(_ phase: String) async {
            let trusted = await probeCATrusted(target: target, controller: controller)
            let reach = await probeMDMReachability(target: target, controller: controller)
            recorder?.note("[\(phase)] guest CA trust: \(trusted)")
            recorder?.note("[\(phase)] guest → MDM server reachability: \(reach)")
        }

        // ── Pre-flight: let macOS answer, before any GUI is involved, whether this can work at all.
        //
        // Every failure in this pass so far has surfaced as an unactionable alert in the guest ("the
        // certificate could not be verified") whose real cause was three layers down. The three
        // questions below are the ones that actually decide the outcome, and the guest's own tools
        // answer all of them in one exec — so a broken enrollment is now named on the host, in the
        // transcript, instead of being inferred from a screenshot.
        do {
            try await preflightEnrollment(
                target: target, controller: controller, recorder: recorder)
        } catch {
            await captureGuestMDMState(target: target, recorder: recorder, label: "pre-flight")
            preserveStagedArtifacts(from: shareDir, recorder: recorder)
            throw error
        }
        step("pre-flight passed: server reachable and the staged profile parses")

        // ── Queue and install the ENROLLMENT profile.
        let openEnrollment = controller.openEnrollmentProfileCommand(
            guestShareDirectory: Self.guestSharePath(os: .macOS, name: Self.provisionShareName))
        let opened = try await runMDMGuest(target, command: openEnrollment)
        guard opened.stdout.contains("MDM_ENROLL_PROFILE_OPENED") else {
            await captureGuestMDMState(target: target, recorder: recorder, label: "open-profile")
            preserveStagedArtifacts(from: shareDir, recorder: recorder)
            throw MDMOrchestrationError.guestCommandFailed(
                "could not open the enrollment profile: "
                    + Self.boundedGuestOutput(stdout: opened.stdout, stderr: opened.stderr))
        }
        step("queued the enrollment profile")
        // Baseline: what the guest's MDM state looks like BEFORE the install is driven, so the
        // post-install capture can be diffed against something rather than read in isolation.
        await captureGuestMDMState(target: target, recorder: recorder, label: "before-install")

        // Every exit from here on — success or failure — leaves the guest's own view in the
        // transcript. A 15-minute build must never have to be repeated just to learn where it stopped.
        func failing(_ phase: String, _ error: Error) async -> Error {
            await captureGuestMDMState(target: target, recorder: recorder, label: phase)
            preserveStagedArtifacts(from: shareDir, recorder: recorder)
            recorder?.note("FAILED at \(phase): \(error)")
            return error
        }

        do {
            try await installProfileViaComputerUse(
                target: target, bundle: bundle, surface: surface, recorder: recorder,
                profile: .enrollment, approvalTimeout: approvalTimeout,
                isComplete: { await self.verifyEnrolled(target: target) })
        } catch {
            await recordReachability("after-enrollment-profile")
            throw await failing("enrollment-approval", error)
        }
        await recordReachability("after-enrollment-profile")
        await captureGuestMDMState(target: target, recorder: recorder, label: "profile-installed")
        step("drove System Settings enrollment approval")

        // Drain the queue WITHOUT APNs. `TokenUpdate` never arrives on macOS 27 (apsd cannot obtain a
        // push token in a VZ guest — see docs/APPLE_FEEDBACK_APNS_VM.md), so the device never polls
        // `/server` on its own. The old approach — kickstart the already-running daemon on a cadence —
        // is a proven no-op (a running on-demand daemon ignores `kickstart`). Instead escalate through
        // triggers that actually make an enrolled, tokenless guest connect: a cold daemon start, then a
        // reboot into the auto-login session (macOS runs a login-time Idle/Acknowledged sync against
        // the MDM server with no push — Apple, "Managing devices and users in macOS"). The server stays
        // listening across the reboot (its `defer`-stop is scoped to this whole function).
        let drained = await drainQueueForModeA(
            target: target, controller: controller, recorder: recorder,
            drainTimeout: Self.drainRebootDrainSeconds)
        guard drained else {
            let pending = await controller.queue.pendingCount
            recorder?.note("drain timed out with \(pending) command(s) still queued")
            throw await failing(
                "queue-drain", MDMOrchestrationError.drainTimedOut(pending: pending))
        }
        let installed: Int
        do {
            installed = try await acknowledgedProfileCount(
                commandUUIDs: commandUUIDs, controller: controller)
        } catch {
            throw await failing("command-acknowledgement", error)
        }
        step("acknowledged \(installed) InstallProfile command(s)")

        // Verify enrollment + exact installed profile identifiers from the guest's own view.
        let enrolled = await verifyEnrolled(target: target)
        guard enrolled else {
            throw await failing(
                "enrollment-verification",
                MDMOrchestrationError.enrollmentNotApproved(
                    "`profiles status -type enrollment` did not report User Approved"))
        }
        step("profiles status: User Approved")
        let requiredIdentifiers = try Self.configurationProfileIdentifiers(in: profiles)
        let missingIdentifiers = try await missingInstalledProfileIdentifiers(
            target: target, requiredIdentifiers: requiredIdentifiers)
        guard missingIdentifiers.isEmpty else {
            throw await failing(
                "profile-inventory", MDMOrchestrationError.profilesMissing(missingIdentifiers))
        }
        step("verified installed profiles: \(requiredIdentifiers.joined(separator: ", "))")
        // Persist identifiers only after both MDM acknowledgements and the guest inventory agree.
        try controller.withProfileIdentifiers(requiredIdentifiers)
            .writePersistedState(to: bundle.mdmStateURL)
        return MDMOutcome(enrolled: true, profilesInstalled: installed, log: log)
    }

    // MARK: - Mode B — push to a live clone

    private func pushProfiles(
        target: MDMGuestTarget,
        profiles: [Data],
        controller: MDMServerController,
        hostBindAddress: String,
        timeout: TimeInterval,
        baseBundle: MacVMBundle?
    ) async throws -> MDMOutcome {
        var log: [String] = []
        // A base-policy update records evidence beside the base like enrollment does; a Mode B push to
        // a live clone has no base bundle to write into, so it keeps the unified-log-only sink.
        let recorder = baseBundle.flatMap { MDMDiagnosticsRecorder(bundle: $0, label: "push") }
        func step(_ line: String) {
            log.append(line)
            recorder?.note(line)
        }
        let commandUUIDs = await controller.queueInstallProfiles(profiles)

        let server = controller.makeServer(
            debug: recorder?.serverDebugLog,
            log: recorder?.protocolLogSink ?? Self.mdmUnifiedLogSink)
        let ipSANs = hostBindAddress == "127.0.0.1" ? [] : [hostBindAddress]
        _ = try await server.start(host: hostBindAddress, ipSANs: ipSANs)
        defer { Task { await server.stop() } }

        // Re-pin the stable server name to this boot's gateway before nudging mdmclient.
        let pin = """
            GW=$(route -n get default 2>/dev/null | awk '/gateway:/{print $2}'); \
            sudo sed -i '' "/[[:space:]]\(controller.config.serverDNSName)$/d" /etc/hosts 2>/dev/null; \
            printf '%s %s\\n' "$GW" "\(controller.config.serverDNSName)" | sudo tee -a /etc/hosts >/dev/null
            """
        let pinResult = try await runMDMGuest(target, command: pin)
        guard pinResult.exitCode == 0 else {
            throw MDMOrchestrationError.guestCommandFailed(
                "could not re-pin the MDM server: \(pinResult.stderr.suffix(400))")
        }
        step("re-pinned \(controller.config.serverDNSName) to the guest gateway")

        // Mode B addresses a live session clone, which must not be rebooted out from under a user, so
        // the only lever here is a cold mdmclient start (the reboot escalation is Mode A's). Its own
        // status is advisory — the drain wait below is the authority — so a non-clean start is not a
        // hard failure on its own.
        let nudge = await coldStartMDMClient(target: target)
        step("mdmclient cold start: \(nudge)")

        let drained = await waitForDrain(controller: controller, timeout: timeout)
        guard drained else {
            throw MDMOrchestrationError.drainTimedOut(pending: await controller.queue.pendingCount)
        }
        let installed = try await acknowledgedProfileCount(
            commandUUIDs: commandUUIDs, controller: controller)
        step("acknowledged \(installed) InstallProfile command(s)")

        let requiredIdentifiers = try Self.configurationProfileIdentifiers(in: profiles)
        let missingIdentifiers = try await missingInstalledProfileIdentifiers(
            target: target, requiredIdentifiers: requiredIdentifiers)
        guard missingIdentifiers.isEmpty else {
            throw MDMOrchestrationError.profilesMissing(missingIdentifiers)
        }
        step("verified installed profiles: \(requiredIdentifiers.joined(separator: ", "))")
        if let baseBundle {
            try controller.withProfileIdentifiers(requiredIdentifiers)
                .writePersistedState(to: baseBundle.mdmStateURL)
        }
        return MDMOutcome(enrolled: true, profilesInstalled: installed, log: log)
    }

    // MARK: - Diagnostic formatting

    /// The fallback protocol sink for a push with no base bundle to record into: unified log only.
    static let mdmUnifiedLogSink: @Sendable (String) -> Void = { line in NSLog("[mdm] %@", line) }

    /// Both guest streams, labelled and bounded, for a surfaced error message. A guest step that
    /// narrates on stdout and fails on stderr needs both halves to be diagnosable.
    static func boundedGuestOutput(
        stdout: String, stderr: String, limit: Int = 600
    ) -> String {
        var parts: [String] = []
        let out = stdout.trimmingCharacters(in: .whitespacesAndNewlines)
        let err = stderr.trimmingCharacters(in: .whitespacesAndNewlines)
        if !out.isEmpty { parts.append("stdout: \(out.suffix(limit))") }
        if !err.isEmpty { parts.append("stderr: \(err.suffix(limit))") }
        return parts.isEmpty ? "no output" : parts.joined(separator: "; ")
    }

    /// The same two streams, unbounded and indented, for the transcript.
    static func indentedGuestOutput(stdout: String, stderr: String) -> String {
        func block(_ label: String, _ text: String) -> String? {
            let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
            guard !trimmed.isEmpty else { return nil }
            let body = trimmed.split(separator: "\n", omittingEmptySubsequences: false)
                .map { "    " + $0 }.joined(separator: "\n")
            return "  \(label):\n\(body)"
        }
        let blocks = [block("stdout", stdout), block("stderr", stderr)].compactMap { $0 }
        return blocks.isEmpty ? "  (no output)" : blocks.joined(separator: "\n")
    }

    // MARK: - Guest-side helpers

    /// Accept exactly one ordinary IPv4 address reported as the guest's default gateway. The MDM
    /// listener must bind the host-side NAT address the guest can reach; accepting shell fragments,
    /// loopback, an unspecified address, or multicast here would make the enrollment path either
    /// unreachable or unsafe to interpolate into diagnostics and policy state.
    static func validatedMDMGateway(_ output: String) -> String? {
        let candidate = output.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !candidate.isEmpty,
              candidate.rangeOfCharacter(from: .whitespacesAndNewlines) == nil
        else { return nil }
        let components = candidate.split(separator: ".", omittingEmptySubsequences: false)
        guard components.count == 4 else { return nil }
        var octets: [Int] = []
        for component in components {
            guard !component.isEmpty, component.allSatisfy(\.isNumber),
                  let octet = Int(component), (0...255).contains(octet)
            else { return nil }
            octets.append(octet)
        }
        guard octets[0] != 0, octets[0] != 127, octets[0] < 224,
              octets != [255, 255, 255, 255]
        else { return nil }
        return octets.map(String.init).joined(separator: ".")
    }

    /// Ask the running guest which NAT gateway it actually received instead of assuming bridge100's
    /// usual 192.168.64.1. Virtualization.framework may select a different private subnet when the
    /// default one conflicts, and the HTTPS listener has to bind that exact host-facing address.
    private func discoverMDMHostBindAddress(target: MDMGuestTarget) async throws -> String {
        let result = try await runMDMGuest(
            target,
            command: "/sbin/route -n get default 2>/dev/null "
                + "| /usr/bin/awk '/gateway:/{print $2; exit}'")
        guard result.exitCode == 0,
              let address = Self.validatedMDMGateway(result.stdout)
        else {
            let detail = (result.stdout + result.stderr).trimmingCharacters(
                in: .whitespacesAndNewlines)
            throw MDMOrchestrationError.guestCommandFailed(
                "could not discover a usable IPv4 NAT gateway"
                    + (detail.isEmpty ? "" : ": \(detail.prefix(400))"))
        }
        return address
    }

    /// Ask the GUEST whether it can reach and TLS-validate the MDM server — the exact thing macOS is
    /// complaining about when profile installation fails with "The certificate could not be verified
    /// (authentication error)", which surfaces at the moment `mdmclient` first contacts the ServerURL.
    ///
    /// This is the missing link in every failed run so far: the host listener logs "listening" and then
    /// never records a single request, so it has never been established whether the guest fails at DNS,
    /// at TCP, or at certificate validation. `curl`'s exit code separates them precisely — 6 unresolved
    /// host, 7 connection refused, 28 timeout, 35/60 TLS/certificate failure — and the same command run
    /// with `--insecure` distinguishes "cannot connect at all" from "connects but distrusts our CA".
    private func probeMDMReachability(
        target: MDMGuestTarget, controller: MDMServerController
    ) async -> String {
        let url = controller.config.checkInURL
        let quoted = Self.shQuote(url)
        let command = """
            S=$(/usr/bin/curl -sS -o /dev/null -m 10 -w '%{http_code}' \(quoted) 2>&1); \
            RC=$?; \
            I=$(/usr/bin/curl -sS -k -o /dev/null -m 10 -w '%{http_code}' \(quoted) 2>&1); \
            IRC=$?; \
            printf 'verified: rc=%s out=%s | insecure: rc=%s out=%s | hosts-pins=%s' \
              "$RC" "$S" "$IRC" "$I" \
              "$(/usr/bin/grep -c \(Self.shQuote(controller.config.serverDNSName)) /etc/hosts)"
            """
        guard let result = try? await runMDMGuest(target, command: command) else {
            return "reachability probe could not run"
        }
        let text = (result.stdout + " " + result.stderr)
            .trimmingCharacters(in: .whitespacesAndNewlines)
        return text.isEmpty ? "reachability probe produced no output" : text
    }

    /// Whether the guest currently trusts our CA root, asked of the guest's own trust store. Answers
    /// the question the trust sentinel alone cannot: `add-trusted-cert` may exit 0 while the resulting
    /// trust setting is not what TLS evaluation actually uses.
    private func probeCATrusted(
        target: MDMGuestTarget, controller: MDMServerController
    ) async -> String {
        // Presence and trust are different questions, and only the second one matters. The earlier
        // version of this probe counted `find-certificate` hits — which reports 1 for a root sitting
        // in the System keychain with its SSL trust unset, the exact state that cannot enrol. It is
        // reported alongside the verdict now so "installed but untrusted" is legible at a glance.
        let caPath = Self.shQuote(
            Self.guestSharePath(os: .macOS, name: Self.provisionShareName)
                + "/\(MDMServerController.Artifact.caCert)")
        let command = """
            N=$(/usr/bin/security find-certificate -a -c \(Self.shQuote("Nucleic MDM Root CA")) \
              /Library/Keychains/System.keychain 2>/dev/null | /usr/bin/grep -c 'labl' || true)
            SSL=no; /usr/bin/security verify-cert -c \(caPath) -p ssl >/dev/null 2>&1 && SSL=yes
            BASIC=no; /usr/bin/security verify-cert -c \(caPath) -p basic >/dev/null 2>&1 && BASIC=yes
            printf 'in System keychain=%s, trusted for ssl=%s, for basic=%s' "$N" "$SSL" "$BASIC"
            """
        guard let result = try? await runMDMGuest(target, command: command) else {
            return "CA-trust probe could not run"
        }
        let text = (result.stdout + result.stderr)
            .trimmingCharacters(in: .whitespacesAndNewlines)
        return text.isEmpty ? "CA-trust probe produced no output" : text
    }

    /// Cold-start the on-demand `mdmclient` daemon so a freshly-started instance checks in and polls
    /// `/server`. Restart it if it is already running (`kickstart -k`), otherwise start it from stopped
    /// (plain `kickstart` — `-k` errors on a service that isn't running). A live run
    /// (`run-push-e3d6a047`) proved a cold start makes an enrolled, tokenless guest drain its queue,
    /// whereas a `kickstart` of the *already-running* post-enrollment daemon is a no-op — which is why
    /// nudging on a cadence right after enrollment moved nothing. The status is advisory; the drain
    /// wait is the authority.
    private func coldStartMDMClient(target: MDMGuestTarget) async -> String {
        let command =
            "sudo /bin/launchctl kickstart -k system/com.apple.mdmclient.daemon 2>/dev/null "
            + "|| sudo /bin/launchctl kickstart system/com.apple.mdmclient.daemon"
        guard let result = try? await runMDMGuest(target, command: command) else {
            return "could not run"
        }
        let text = (result.stdout + result.stderr)
            .trimmingCharacters(in: .whitespacesAndNewlines)
            .replacingOccurrences(of: "\n", with: " ⏎ ")
        return result.exitCode == 0
            ? "ok" : "exit \(result.exitCode)\(text.isEmpty ? "" : ": \(text)")"
    }

    /// Drain the queued policy commands for Mode A (base enrollment) with no APNs, escalating through
    /// triggers of increasing cost, each strictly more forceful than the last:
    ///  1. a brief passive wait — the device occasionally polls on its own right after enrollment;
    ///  2. a cold `mdmclient` start — the proven trigger, cheap, no reboot;
    ///  3. a guest reboot — the auto-login session runs a login-time Idle sync against the (still
    ///     listening) server, which is Apple's documented push-free drain.
    /// Returns as soon as the queue drains; a `false` return means every trigger was exhausted.
    private func drainQueueForModeA(
        target: MDMGuestTarget, controller: MDMServerController,
        recorder: MDMDiagnosticsRecorder?, drainTimeout: TimeInterval
    ) async -> Bool {
        func note(_ line: String) { recorder?.note(line) }

        note("drain: waiting up to \(Int(Self.drainQuietSeconds))s for a natural post-enrollment check-in")
        if await waitForDrain(controller: controller, timeout: Self.drainQuietSeconds) {
            note("drain: queue drained with no intervention")
            return true
        }

        let cold = await coldStartMDMClient(target: target)
        note("drain: mdmclient cold start (\(cold)); waiting up to \(Int(Self.drainColdStartSeconds))s")
        if await waitForDrain(controller: controller, timeout: Self.drainColdStartSeconds) {
            note("drain: queue drained after the mdmclient cold start")
            return true
        }

        #if arch(arm64)
        if let instance = target.maintenanceInstance {
            note("drain: rebooting the guest to trigger the login-time MDM sync")
            do {
                await shutdownBaseGuest(instance)
                try await instance.start()
                try await awaitAgentReady(onInstance: instance, label: target.name)
            } catch {
                note("drain: reboot/agent-ready failed: \(error)")
                return await controller.queue.isDrained
            }
            note("drain: guest back up; waiting up to \(Int(drainTimeout))s for the login-sync drain")
            return await waitForDrain(controller: controller, timeout: drainTimeout)
        }
        #endif
        note("drain: no maintenance instance to reboot; giving up")
        return await controller.queue.isDrained
    }

    /// Return required top-level profile identifiers absent from the guest's machine-level profile
    /// inventory. The XML form is requested so matching stable identifiers is locale-independent.
    private func missingInstalledProfileIdentifiers(
        target: MDMGuestTarget, requiredIdentifiers: [String]
    ) async throws -> [String] {
        let result = try await runMDMGuest(
            target, command: "sudo profiles show -type configuration -output stdout-xml")
        guard result.exitCode == 0 else {
            throw MDMOrchestrationError.guestCommandFailed(
                "profiles inventory exit \(result.exitCode): \(result.stderr.suffix(400))")
        }
        let inventory = result.stdout + result.stderr
        return requiredIdentifiers.filter { !inventory.contains($0) }
    }

    private func verifyEnrolled(target: MDMGuestTarget) async -> Bool {
        guard let result = try? await runMDMGuest(
            target, command: "profiles status -type enrollment")
        else { return false }
        let text = (result.stdout + result.stderr).lowercased()
        return text.contains("user approved") || text.contains("mdm enrollment: yes")
    }

    /// Execute one bounded housekeeping command through either the ordinary registry path or the
    /// direct base-maintenance instance. Direct execution reuses the same vsock/nash transport.
    private func runMDMGuest(
        _ target: MDMGuestTarget, command: String
    ) async throws -> (exitCode: Int32, stdout: String, stderr: String) {
        switch target {
        case .registered(let name):
            return try await run(
                name: name, command: command, workdir: nil,
                timeoutNanos: 60 * 1_000_000_000)
        #if arch(arm64)
        case .instance(let instance, let name):
            let channel = try await openExecChannel(
                instance: instance, label: name, workdir: nil, env: [:], remoteBody: command)
            async let stdout = Self.drainLines(channel.stdoutLines)
            async let stderr = Self.drainLines(channel.stderrLines)
            let outcome = await Self.awaitExit(channel, timeoutNanos: 60 * 1_000_000_000)
            let output = await stdout
            let errors = await stderr
            return Self.finalize(
                outcome, stdout: output, stderr: errors,
                timeoutNanos: 60 * 1_000_000_000)
        #endif
        }
    }

    /// Require every command in this exact enqueue batch to finish as `Acknowledged`. A queue can be
    /// drained after an `Error`, so drain alone is not a policy-installation success signal.
    private func acknowledgedProfileCount(
        commandUUIDs: [String], controller: MDMServerController
    ) async throws -> Int {
        let completed = await controller.queue.completionStatuses(for: commandUUIDs)
        let statuses = Dictionary(uniqueKeysWithValues: commandUUIDs.map { uuid in
            (uuid, completed[uuid] ?? "Missing")
        })
        guard statuses.values.allSatisfy({ $0 == "Acknowledged" }) else {
            throw MDMOrchestrationError.policyCommandsFailed(statuses)
        }
        return statuses.count
    }

    /// Poll the queue until it drains or the deadline passes. The trigger that makes the guest connect
    /// is applied by the caller (``drainQueueForModeA`` / the Mode B cold start) before entering this
    /// wait; here we only observe the queue.
    private func waitForDrain(
        controller: MDMServerController, timeout: TimeInterval
    ) async -> Bool {
        let deadline = Date().addingTimeInterval(timeout)
        while Date() < deadline {
            if await controller.queue.isDrained { return true }
            try? await Task.sleep(nanoseconds: 500_000_000)
        }
        return await controller.queue.isDrained
    }

    /// System Settings pane identifiers that reach Device Management, newest first. macOS 27 renamed
    /// the pane; the pre-Ventura `com.apple.preferences.configurationprofiles` id no longer navigates
    /// there (finding 2). The approval loop cycles these when nothing actionable is on screen and
    /// records which one surfaced the profile, so §8.3 can be closed with a fact instead of a guess.
    static let deviceManagementPaneCandidates = [
        "x-apple.systempreferences:com.apple.Profiles-Settings.extension",
        "x-apple.systempreferences:com.apple.settings.PrivacySecurity.extension",
        "x-apple.systempreferences:com.apple.preferences.configurationprofiles",
    ]

    /// Drive the System Settings ▸ Device Management profile-install approval with a bounded OCR state
    /// machine. It types the password only into a recognized Apple authorization sheet with a located
    /// password field, and submits with Return.
    ///
    /// Two password sheets appear in sequence — the CA-trust sheet raised by the detached
    /// `add-trusted-cert`, then the profile-install sheet — so the budget covers both with headroom for
    /// a retry. A sheet is re-answered only once it has persisted past ``reAuthDelaySeconds`` (a
    /// correct answer dismisses it within a second, so a still-present sheet means the last attempt
    /// failed — a dropped keystroke, say). A `cmd+a` precedes the password so a re-type replaces rather
    /// than appends. The loop is time-bounded rather than iteration-bounded, since the trust step's
    /// latency plus a cold System Settings launch and the install can exceed the old ~20 s budget
    /// (finding 3). It cycles ``deviceManagementPaneCandidates`` only while nothing enrollment-related
    /// is on screen; a SecurityAgent modal always stays on top, so opening a pane behind it never
    /// dismisses a prompt.
    static let maxAuthAttempts = 5
    static let reAuthDelaySeconds: TimeInterval = 6
    /// Bounds for re-clicking a control that is still on screen (the enrollment row, the Enroll
    /// button). A click that worked changes the screen within a second or two, so a state that
    /// persists past ``reClickDelaySeconds`` means the click missed and is worth one more try.
    static let maxControlClicks = 4
    static let reClickDelaySeconds: TimeInterval = 4
    /// How often the loop asks the guest whether the profile has landed. Every frame would be one
    /// guest exec per ~0.5 s for no benefit; a few seconds is well inside the time an install takes,
    /// and the `.installed` screen short-circuits the wait when the pixels suggest we are already done.
    static let completionPollSeconds: TimeInterval = 3

    /// Mode A drain windows (docs/MACOS_VM_PROVISIONING_REPAIR_PLAN.md D.2), escalating in cost:
    /// a short passive wait for a natural post-enrollment check-in; a longer wait after the cheap
    /// cold-daemon start; and the authoritative window after the reboot's login-time sync, which must
    /// cover a cold boot, auto-login, and the guest's Idle/Acknowledged exchange for every command.
    static let drainQuietSeconds: TimeInterval = 90
    static let drainColdStartSeconds: TimeInterval = 150
    static let drainRebootDrainSeconds: TimeInterval = 420

    /// Whether to (re)act on a control that is still showing: at most `maxControlClicks` times, and
    /// never twice inside `reClickDelaySeconds`. Mutates the caller's counters.
    static func shouldReact(now: Date, last: inout Date?, count: inout Int) -> Bool {
        let elapsed = last.map { now.timeIntervalSince($0) } ?? .greatestFiniteMagnitude
        guard count < maxControlClicks, elapsed >= reClickDelaySeconds else { return false }
        count += 1
        last = now
        return true
    }
    /// Ask macOS, in the guest, whether this enrollment can possibly succeed — before a single pixel
    /// is clicked. Throws with the failing check named.
    ///
    /// The predecessor of this check asked `security find-certificate`, which proves only that the
    /// certificate is *present in a keychain*. Presence is not trust: since macOS Ventura a root can
    /// sit in the System keychain with its SSL trust unset, which is exactly the state a manually
    /// installed root profile leaves behind. A presence test therefore passes on precisely the guests
    /// that cannot enrol.
    ///
    ///  * **reach** — can the guest open a TLS connection to the check-in URL *at all* (`curl -k`)?
    ///    This is the required one: it covers the `/etc/hosts` pin, the route to the vmnet gateway,
    ///    and the listener actually being up. Any HTTP status counts — a 400 from our own server is a
    ///    completed handshake, which is the question.
    ///  * **ssl** — `verify-cert -p ssl`, the guest's system-trust evaluation. **Advisory.** It was
    ///    the gate until the profile began pinning its own CA; `mdmclient` now anchors on the root
    ///    carried in the profile, so a `0` here is expected and not a failure.
    ///  * **profile** — the staged profile parses, as `plist` (unsigned) or `cms` (signed). Required,
    ///    but it must accept BOTH: gating on `security cms -D` alone failed every build the moment the
    ///    profile stopped being signed, because that tool cannot decode a plain plist. It is a
    ///    well-formedness check only — a live run showed `cms -D` succeeding with the CA untrusted, so
    ///    it never carried any trust meaning.
    ///  * **tls** — `curl` to the check-in URL without `--insecure`. **Advisory only.** macOS's
    ///    `/usr/bin/curl` is LibreSSL-backed and validates against `/etc/ssl/cert.pem` rather than the
    ///    keychain, so it can fail on a chain the system trusts. Useful as a reachability signal (its
    ///    `--insecure` twin in the failure dump separates "cannot connect" from "distrusts the CA"),
    ///    not as a trust verdict.
    ///
    /// No probe here can exercise the *pinned* path: pinning is evaluated by `mdmclient` against a
    /// certificate payload inside the profile, and no CLI can stand in for that. The authoritative
    /// answer is therefore the enrollment itself — which is why this pre-flight now checks only the
    /// things that are prerequisites for it rather than trying to predict its verdict.
    /// Snapshot the guest's own view of MDM into the transcript. Called before **every** failure this
    /// pass can propagate, and after each milestone, so a run explains itself without a second run.
    ///
    /// The load-bearing part is the last section. macOS records the real reason a profile install
    /// failed — which payload, which validation step — in the `ManagedClient`/`mdmclient` logs; the
    /// on-screen alert says only "the certificate could not be verified". That log was previously
    /// captured *only* when the approval loop timed out, so a run that failed with a visible alert
    /// (the common case) recorded nothing, and its cause had to be inferred from the absence of a
    /// server connection. Inference is what wasted the runs this log documents.
    ///
    /// Every command is read-only and `|| true`-guarded: this must never be the reason a pass fails,
    /// and it must never hang — `runMDMGuest` bounds the whole bundle at 60 s.
    fileprivate func captureGuestMDMState(
        target: MDMGuestTarget, recorder: MDMDiagnosticsRecorder?, label: String
    ) async {
        let share = Self.guestSharePath(os: .macOS, name: Self.provisionShareName)
        // `ProfileHelper` and `ProfilesSettingsExt` are separate processes from `System Settings` and do
        // the actual staging and payload validation; `securityd`/`trustd` are where the *reason* lands.
        // Run 21's `-323` was caught only because ProfilesSettingsExt happens to log under the
        // ManagedClient subsystem, while the line that named the cause — a CSSM
        // `-25264 MAC verification failed during PKCS12 import` from the certificate payload's
        // SecItemImport call — was filtered out, which cost several runs of guessing.
        let predicate =
            "subsystem == \"com.apple.ManagedClient\" OR process == \"mdmclient\" "
            + "OR process == \"profiles\" OR process == \"ManagedClient\" "
            + "OR process == \"System Settings\" OR process == \"ProfileHelper\" "
            + "OR process == \"ProfilesSettingsExt\" OR process == \"securityd\" "
            // `apsd` owns the APNs registration whose token `TokenUpdate` carries. Without it in the
            // predicate, "why did the device never send TokenUpdate?" is unanswerable from the capture —
            // which is exactly where the first drain-timeout investigation ran out of evidence.
            + "OR process == \"trustd\" OR process == \"apsd\""
        let command = """
            echo '── profiles status -type enrollment ──'
            /usr/bin/profiles status -type enrollment 2>&1 || true
            echo '── installed configuration profiles ──'
            sudo /usr/bin/profiles show -type configuration -output stdout-xml 2>&1 \
              | /usr/bin/grep -E 'PayloadIdentifier|PayloadDisplayName' | /usr/bin/head -40 || true
            echo '── staged share ──'
            /bin/ls -l \(Self.shQuote(share)) 2>&1 || true
            echo '── frontmost app ──'
            /usr/bin/lsappinfo front 2>&1 || true
            echo '── ManagedClient / mdmclient / profiles log (last 5m, info+debug) ──'
            # `--info --debug` is not optional here. Without them `log show` emits only Default-level
            # messages, and a live run captured the top-level failure —
            #   Error Domain=ConfigProfilePluginDomain Code=-323 "The certificate could not be
            #   verified (authentication error)."
            # — without the payload-level lines that say WHICH certificate failed, which is the one
            # thing needed to act on it. The tail is widened to match the extra volume.
            sudo /usr/bin/log show --last 5m --info --debug --style compact \
              --predicate \(Self.shQuote(predicate)) 2>&1 | /usr/bin/tail -c 40000 || true
            echo '── profile-install errors only ──'
            sudo /usr/bin/log show --last 5m --info --debug --style compact \
              --predicate \(Self.shQuote(predicate)) 2>&1 \
              | /usr/bin/grep -iE 'error|fail|denied|invalid|verif|cert|payload|scep|identity' \
              | /usr/bin/tail -c 20000 || true
            """
        guard let result = try? await runMDMGuest(target, command: command) else {
            recorder?.note("[\(label)] guest MDM state: probe could not run")
            return
        }
        recorder?.note(
            "[\(label)] guest MDM state:\n"
                + Self.indentedGuestOutput(stdout: result.stdout, stderr: result.stderr))
    }

    /// Copy the exact artifacts that were staged into the guest beside this attempt's transcript, so a
    /// failure can be inspected against the real bytes instead of regenerated ones (a regenerated
    /// profile has fresh UUIDs, a fresh identity, and a fresh signature, so it is not the same file).
    /// Host-only and 0700, alongside `mdm-state.json`, which already holds the CA private key.
    func preserveStagedArtifacts(from shareDir: URL, recorder: MDMDiagnosticsRecorder?) {
        guard let directory = recorder?.directory else { return }
        let fm = FileManager.default
        let destination = directory.appendingPathComponent("staged", isDirectory: true)
        do {
            try fm.createDirectory(at: destination, withIntermediateDirectories: true)
            try fm.setAttributes([.posixPermissions: 0o700], ofItemAtPath: destination.path)
            for name in try fm.contentsOfDirectory(atPath: shareDir.path) {
                let target = destination.appendingPathComponent(name)
                try? fm.removeItem(at: target)
                try? fm.copyItem(at: shareDir.appendingPathComponent(name), to: target)
            }
            recorder?.note("preserved the staged artifacts into staged/")
        } catch {
            recorder?.note("could not preserve staged artifacts: \(error)")
        }
    }

    private func preflightEnrollment(
        target: MDMGuestTarget, controller: MDMServerController,
        recorder: MDMDiagnosticsRecorder?
    ) async throws {
        let share = Self.guestSharePath(os: .macOS, name: Self.provisionShareName)
        let caPath = Self.shQuote("\(share)/\(MDMServerController.Artifact.caCert)")
        let profilePath = Self.shQuote("\(share)/\(MDMServerController.Artifact.profile)")
        let checkIn = Self.shQuote(controller.config.checkInURL)
        let command = """
            SSL=0; PROF=0; TLS=0; REACH=0
            /usr/bin/security verify-cert -c \(caPath) -p ssl >/dev/null 2>&1 && SSL=1
            # Accept EITHER form. The staged profile is an unsigned plist today, but was CMS-signed
            # until run 19 and could be again; a check that only understood one of them would fail the
            # build on the other. (It did: `cms -D` cannot decode a plain plist, so gating on it
            # rejected every build the moment the profile stopped being signed.)
            if /usr/bin/plutil -lint \(profilePath) >/dev/null 2>&1; then
              PROF=plist
            elif /usr/bin/security cms -D -i \(profilePath) >/dev/null 2>&1; then
              PROF=cms
            fi
            /usr/bin/curl -sS -o /dev/null -m 15 \(checkIn) >/dev/null 2>&1 && TLS=1
            /usr/bin/curl -sS -k -o /dev/null -m 15 \(checkIn) >/dev/null 2>&1 && REACH=1
            # Does THIS guest's importer accept the staged device identity? `security import` drives
            # SecItemImport — the same CDSA-backed API /usr/libexec/mdmclient links (`nm -u`) and
            # therefore the one that decides whether the profile installs. Its absence is why a
            # PKCS#12 with modern crypto blocked enrollment for eleven runs behind an opaque
            # "The certificate could not be verified (authentication error)": nothing host-side or
            # guest-side ever ran the identity through the importer the guest actually uses. A throwaway
            # keychain under /tmp keeps this out of the login and System keychains.
            IDENT=skip; IMPORT=; IRC=0
            # The temp file MUST end in .p12: `security import` picks its parser from the filename
            # extension, and on an extensionless file it answers "Unknown format in import" no matter how
            # well-formed the blob is. That cost a build — the probe failed a PKCS#12 this same host
            # imported fine one directory over. An explicit `-f pkcs12` also works but suppresses the
            # "N identity imported" line this classifier reads, so the extension is the right lever.
            IDDIR="$(/usr/bin/mktemp -d /tmp/nucleic-ident-XXXXXX 2>/dev/null || true)"
            if [ -n "$IDDIR" ]; then
              P12="$IDDIR/identity.p12"
              IDX=
              for i in 0 1 2 3 4 5; do
                T="$(/usr/bin/plutil -extract "PayloadContent.$i.PayloadType" raw -o - \\
                  \(profilePath) 2>/dev/null || true)"
                if [ "$T" = "com.apple.security.pkcs12" ]; then IDX="$i"; break; fi
              done
              if [ -n "$IDX" ]; then
                IDPW="$(/usr/bin/plutil -extract "PayloadContent.$IDX.Password" raw -o - \\
                  \(profilePath) 2>/dev/null || true)"
                if /usr/bin/plutil -extract "PayloadContent.$IDX.PayloadContent" raw -o - \\
                     \(profilePath) 2>/dev/null | /usr/bin/base64 -D -o "$P12" 2>/dev/null \\
                   && [ -s "$P12" ]; then
                  KC="$IDDIR/probe.keychain"
                  /usr/bin/security create-keychain -p nucleic-probe "$KC" >/dev/null 2>&1
                  IMPORT="$(/usr/bin/security import "$P12" -k "$KC" -P "$IDPW" -A -x 2>&1)"; IRC=$?
                  case "$IMPORT" in
                    *"identity imported"*) IDENT=ok ;;
                    # A certificate with no key means an unencrypted key bag: the importer drops the
                    # key, so IdentityCertificateUUID would resolve to nothing.
                    *"certificate imported"*) IDENT=certonly ;;
                    # Unrecognised output: trust the exit status rather than fail the build on a
                    # message this classifier does not know. Only a non-zero exit is a real rejection —
                    # a gate that guesses "fail" from silence blocks good builds.
                    *) if [ "$IRC" -eq 0 ]; then IDENT=ok; else IDENT=fail; fi ;;
                  esac
                  /usr/bin/security delete-keychain "$KC" >/dev/null 2>&1
                fi
              fi
              /bin/rm -rf "$IDDIR" 2>/dev/null
            fi
            printf 'PREFLIGHT reach=%s profile=%s ssl=%s tls=%s identity=%s\\n' \\
              "$REACH" "$PROF" "$SSL" "$TLS" "$IDENT"
            if [ "$IDENT" != ok ] && [ "$IDENT" != skip ]; then
              echo '── security import (SecItemImport, the importer mdmclient uses) ──'
              echo "$IMPORT"
              echo '   -25264 = errSecPkcs12VerifyFailure: the MacData is not SHA-1.'
              echo '   "Unknown format in import": the key bag is not an RFC 7292 v1 PBE.'
              echo '   Either one installs as ConfigProfilePluginDomain -323.'
            fi
            if [ "$REACH" != 1 ] || [ "$PROF" = 0 ]; then
              echo '── verify-cert -p ssl ──'
              /usr/bin/security verify-cert -c \(caPath) -p ssl 2>&1
              echo '── plutil -lint ──'
              /usr/bin/plutil -lint \(profilePath) 2>&1
              echo '── cms -D ──'
              /usr/bin/security cms -D -i \(profilePath) 2>&1 | /usr/bin/head -c 400
              echo
              echo '── curl (verified) ──'
              /usr/bin/curl -sS -o /dev/null -m 15 -w 'http=%{http_code}\\n' \(checkIn) 2>&1
              echo '── curl (insecure, to separate reachability from trust) ──'
              /usr/bin/curl -sS -k -o /dev/null -m 15 -w 'http=%{http_code}\\n' \(checkIn) 2>&1
              echo '── /etc/hosts pin ──'
              /usr/bin/grep \(Self.shQuote(controller.config.serverDNSName)) /etc/hosts 2>&1
            fi
            """
        let result = try await runMDMGuest(target, command: command)
        let output = result.stdout + result.stderr
        recorder?.note("pre-flight:\n" + Self.indentedGuestOutput(stdout: result.stdout, stderr: result.stderr))
        // Gate on REACHABILITY and a well-formed profile — deliberately NOT on system trust.
        //
        // `ssl` was a gate until the enrollment profile began pinning its own CA
        // (`ServerURLPinningCertificateUUIDs`). `mdmclient` now evaluates our server against the root
        // carried in the profile rather than against the system trust store, so requiring the root to
        // ALSO be in that store would reject the very configuration that works. Both `ssl` and `tls`
        // stay in the report — they are the cheapest way to see which trust regime a guest is in, and
        // `tls` is doubly weak as a verdict because macOS's `/usr/bin/curl` is LibreSSL-backed and
        // validates against `/etc/ssl/cert.pem` rather than the keychain.
        // `profile=` reports WHICH form was recognized (`plist` or `cms`), so the transcript records
        // what was actually staged rather than just that something parsed. Only `0` is a failure.
        guard output.contains("PREFLIGHT reach=1 profile=plist")
            || output.contains("PREFLIGHT reach=1 profile=cms")
        else {
            throw MDMOrchestrationError.preflightFailed(
                Self.boundedGuestOutput(stdout: result.stdout, stderr: result.stderr))
        }
        // `identity=` IS a gate, unlike `ssl`/`tls`, because it measures the guest's own verdict on the
        // exact bytes the profile carries, using the exact API the install path uses. `fail`/`certonly`
        // mean the install is going to end in -323 five GUI-driven minutes from now, so stop here and
        // say why. `skip` (the payload could not be extracted — e.g. a CMS-signed profile) stays
        // advisory: an unprobeable profile is not evidence of a broken one.
        guard !output.contains("identity=fail"), !output.contains("identity=certonly") else {
            throw MDMOrchestrationError.preflightFailed(
                Self.boundedGuestOutput(stdout: result.stdout, stderr: result.stderr))
        }
    }

    private func installProfileViaComputerUse(
        target: MDMGuestTarget, bundle: MacVMBundle, surface: any MacVMSurfaceHost,
        recorder: MDMDiagnosticsRecorder?, profile: ProfileTarget,
        approvalTimeout: TimeInterval,
        isComplete: @escaping () async -> Bool
    ) async throws {
        let password = try resolveAgentPassword()

        // Prove the recognizer works in THIS process before anything depends on it, and warm Vision's
        // models while the clock is not running. Every action this loop takes is downstream of OCR, so
        // a recognizer that cannot run makes the whole pass a five-minute no-op that then blames the
        // guest — which is exactly what a live run did. Checked BEFORE the deadline is taken: the cold
        // model load is measured in tens of seconds and must not come out of the approval budget.
        if let failure = await Self.verifyTextRecognition() {
            recorder?.note("text recognition self-test FAILED: \(failure)")
            throw MDMOrchestrationError.textRecognitionUnavailable(failure)
        }
        recorder?.note("text recognition self-test passed (Vision models warm)")

        let deadline = Date().addingTimeInterval(approvalTimeout)

        var lastCapture: Data?
        /// Frames that produced real capture bytes but no recognized text — the signature of a broken
        /// recognizer rather than a blank screen, and the difference the final message must state.
        var capturedButUnread = 0
        var lastRecognitionFailure: String?
        var lastLines: [(text: String, box: CGRect)] = []
        var rowClicks = 0, installClicks = 0
        var lastRowClickAt: Date?, lastInstallClickAt: Date?
        var authAttempts: [String: Int] = [:]
        var lastAuthAt: [String: Date] = [:]
        var paneIndex = 0
        var nextPaneOpen = Date()  // surface the pane on the first idle capture
        var reachedEnrollmentUI = false
        var nextCompletionCheck = Date()  // ask the guest on the very first capture

        while Date() < deadline {
            // The RECOGNITION capture, not the normalized screenshot: full guest resolution, no lossy
            // compression. Halving the glyphs and then JPEG-ringing their edges is what turned
            // "Password" into "Peseword" and "Update Settings" into "Updale Settings" on live runs,
            // and every missed control downstream started as a misread character here.
            guard let capture = await surface.captureForRecognition(name: target.name) else {
                // A capture the surface can't produce at all is itself evidence — distinct from one
                // that renders but recognizes nothing — so it gets a frame rather than a silent skip.
                recorder?.recordFrame(capture: nil, lines: [], state: "no-capture", acted: false)
                try? await Task.sleep(nanoseconds: 500_000_000)
                continue
            }
            lastCapture = capture
            let recognition = await Self.recognizeTextLines(
                inCapture: capture, lexicon: Self.approvalLexicon)
            let lines = recognition.lines
            if let failure = recognition.failure, failure != lastRecognitionFailure {
                // Once per distinct failure, not once per frame: a broken recognizer would otherwise
                // write hundreds of identical lines and bury everything else in the transcript.
                lastRecognitionFailure = failure
                recorder?.note("text recognition failure: \(failure)")
            }
            if lines.isEmpty { capturedButUnread += 1 }
            lastLines = lines
            let action = Self.uamdmApprovalAction(in: lines, profile: profile)
            // Once the ENROLLMENT UI (profile row / review sheet / installed) has appeared, stop
            // re-opening Device Management panes: a review sheet can momentarily read as `.unknown`,
            // and re-navigating then would dismiss it. Deliberately NOT latched by a password sheet —
            // the CA-trust sheet appears *before* the profile is queued, so latching on it would stop
            // pane cycling before the profile row was ever surfaced.
            switch action {
            case .openEnrollmentProfile, .install, .installed, .installFailed:
                reachedEnrollmentUI = true
            case .authenticate, .unknown: break
            }
            // The guest's own state is the authority, and it is asked on EVERY frame (on a cadence),
            // not only when the screen is unrecognized. A profile that has finished installing leaves
            // its row on screen, and that row keeps classifying as "there is a row to open" — so the
            // loop never reached `.unknown` after a SUCCESSFUL install and therefore never asked
            // whether it was done. It re-clicked the row until its click budget ran out, then idled to
            // the deadline and failed. That is the exact shape of the observed stall: the CA root
            // profile was installed and selected on screen while the pass reported it never happened.
            if Date() >= nextCompletionCheck {
                nextCompletionCheck = Date().addingTimeInterval(Self.completionPollSeconds)
                if await isComplete() {
                    recorder?.recordFrame(
                        capture: capture, lines: lines.map(\.text),
                        state: "complete-\(Self.stateLabel(action))", acted: false)
                    recorder?.note(
                        "\(profile.displayName): confirmed complete by guest state "
                            + "(screen read as \(Self.stateLabel(action)))")
                    return
                }
            }
            var acted = false
            switch action {
            case .openEnrollmentProfile(let box):
                // Re-click on a cadence rather than once per distinct OCR fingerprint: incidental text
                // noise (a clock tick) used to grant an extra click while a genuinely stuck screen with
                // stable text got none. Bounded, and only while the same state persists.
                if Self.shouldReact(now: Date(), last: &lastRowClickAt, count: &rowClicks) {
                    acted = true
                    // Vision's box is normalized, so it maps into the surface's INPUT space directly.
                    // It must NOT be scaled by the capture's pixel size: the recognition capture is
                    // the guest's native panel (2× the input space on each axis), so measuring the
                    // frame would send every click to twice its coordinates — off the screen.
                    let point = Self.clickPoint(forNormalizedBox: box, in: Self.surfaceInputSize)
                    recorder?.note("double-click enrollment row at (\(point.x), \(point.y))")
                    await surface.send(
                        name: target.name,
                        .click(x: point.x, y: point.y, button: .left, count: 2))
                }
            case .install(let box):
                if Self.shouldReact(now: Date(), last: &lastInstallClickAt, count: &installClicks) {
                    acted = true
                    let point = Self.clickPoint(forNormalizedBox: box, in: Self.surfaceInputSize)
                    recorder?.note("click Enroll/Install at (\(point.x), \(point.y))")
                    // TWO clicks, for the same reason `.authenticate` below uses two: the review sheet
                    // can come up without being key, and the first click on a non-key window is spent
                    // activating it rather than pressing the button under it. A single click made this
                    // step "work if lucky" — it landed once, then a later run sat on the sheet through
                    // nine clicks over four minutes with the pointer on the right pixel (the Enroll box
                    // was located correctly every frame; the press just never reached the button).
                    // Both clicks target the same box, so the extra one cannot hit another control, and
                    // if the first did press Enroll the sheet is gone before the second is sent.
                    await surface.send(
                        name: target.name,
                        .click(x: point.x, y: point.y, button: .left, count: 1))
                    try? await Task.sleep(nanoseconds: 1_200_000_000)
                    await surface.send(
                        name: target.name,
                        .click(x: point.x, y: point.y, button: .left, count: 1))
                }
            case .authenticate(let sheet, let passwordField):
                // Budget is PER SHEET: the flow raises several authorization sheets in sequence, and a
                // shared counter spent retrying the first leaves the last unanswered.
                let attempts = authAttempts[sheet, default: 0]
                let sinceLast = lastAuthAt[sheet].map { Date().timeIntervalSince($0) }
                    ?? .greatestFiniteMagnitude
                if attempts < Self.maxAuthAttempts, sinceLast >= Self.reAuthDelaySeconds {
                    acted = true
                    authAttempts[sheet] = attempts + 1
                    lastAuthAt[sheet] = Date()
                    let field = Self.clickPoint(
                        forNormalizedBox: passwordField, in: Self.surfaceInputSize)
                    recorder?.note(
                        "answer \"\(sheet)\" sheet (attempt \(attempts + 1)): "
                            + "focus+click field at (\(field.x), \(field.y))")
                    // TWO clicks, deliberately. A SecurityAgent sheet often appears without becoming
                    // key, and the first click on a non-key window is consumed activating it — so a
                    // single click leaves the caret unplaced and the keystrokes go nowhere (observed
                    // live: the sheet sat untouched until a human clicked it, after which the very same
                    // automation completed it). The first click foregrounds; the second places the
                    // caret. Both target the field, so neither can hit another control. The activation
                    // click is given a generous settle — this step is intermittent ("works if lucky"),
                    // which is the signature of racing the window becoming key.
                    await surface.send(
                        name: target.name,
                        .click(x: field.x, y: field.y, button: .left, count: 1))
                    try? await Task.sleep(nanoseconds: 1_200_000_000)
                    await surface.send(
                        name: target.name,
                        .click(x: field.x, y: field.y, button: .left, count: 1))
                    try? await Task.sleep(nanoseconds: 500_000_000)
                    await surface.send(name: target.name, .text(password))

                    // VERIFY before submitting, rather than firing blind. A secure text field replaces
                    // its placeholder with bullets once it holds text, so the placeholder's continued
                    // presence is direct evidence the keystrokes never reached the guest — the exact
                    // failure that stalled a run for 397 frames while five attempts reported success.
                    // Return is only sent once the password is known to be in the field; otherwise the
                    // attempt is recorded as landed=false and the retry cadence tries again.
                    try? await Task.sleep(nanoseconds: 700_000_000)
                    var landed = false
                    if let check = await surface.captureForRecognition(name: target.name) {
                        let after = await Self.recognizeTextLines(
                            inCapture: check, lexicon: Self.approvalLexicon)
                        // A recognition FAILURE must not read as "the placeholder is gone" — that
                        // would submit into a field we never confirmed was filled.
                        landed = after.failure == nil && !after.lines.isEmpty
                            && Self.passwordFieldBox(in: after.lines) == nil
                    }
                    recorder?.note(
                        "\"\(sheet)\" attempt \(attempts + 1): password landed in field=\(landed)")
                    if landed {
                        await surface.send(name: target.name, .key(chord: "return"))
                    } else {
                        // Do not submit an empty field: it dismisses nothing, and on some sheets a
                        // failed submit is what re-arms the "shake" that costs another attempt.
                        recorder?.note(
                            "\"\(sheet)\": keystrokes did not reach the field — the sheet is likely not "
                                + "key. Retrying rather than submitting empty.")
                    }
                }
            case .installFailed(let screen):
                // Stop immediately and say why. Continuing would burn the remaining budget clicking
                // behind a modal alert and then report a timeout, which is what made the real cause
                // invisible before. The guest-state capture below carries the ManagedClient log entry
                // that names the actual validation failure.
                recorder?.recordFrame(
                    capture: capture, lines: lines.map(\.text), state:"install-failed", acted: false)
                recorder?.note("\(profile.displayName): macOS reported an install failure on screen")
                await captureGuestMDMState(
                    target: target, recorder: recorder, label: "install-failed")
                _ = await recordMDMApprovalDiagnostic(
                    bundle: bundle, target: target, capture: capture, lines: lines,
                    reason: "macOS showed an install-failure alert", recorder: recorder)
                throw MDMOrchestrationError.profileInstallRejected(
                    Self.boundedGuestOutput(stdout: screen, stderr: ""))
            case .installed:
                // Deliberately does NOT return. The screen saying "installed" is a reason to ask the
                // guest again right now, not a success signal in its own right — a row can read as
                // installed while `profiles status` still reports no enrollment, and acting on the
                // pixels there would hand the caller a false success.
                recorder?.recordFrame(
                    capture: capture, lines: lines.map(\.text), state:"installed", acted: false)
                recorder?.note("\(profile.displayName): shown as installed — re-asking the guest")
                nextCompletionCheck = .distantPast
            case .unknown:
                // Nothing to act on: surface the Device Management pane so the queued profile becomes
                // visible, cycling candidate ids on a cadence — but only until the enrollment UI has
                // first appeared (after that, re-navigating would dismiss a review/install sheet).
                if !reachedEnrollmentUI, Date() >= nextPaneOpen {
                    let pane = Self.deviceManagementPaneCandidates[
                        paneIndex % Self.deviceManagementPaneCandidates.count]
                    _ = try? await runMDMGuest(target, command: "open \(Self.shQuote(pane))")
                    recorder?.note("opened Device Management pane candidate: \(pane)")
                    paneIndex += 1
                    nextPaneOpen = Date().addingTimeInterval(20)
                }
            }
            // Recorded AFTER the action so the frame's `acted` flag reflects what this screen caused;
            // the password itself is never written — only the classified state and recognized text.
            recorder?.recordFrame(
                capture: capture, lines: lines.map(\.text), state: Self.stateLabel(action),
                acted: acted)
            // Sample often so an element is acted on promptly after it appears. A frame we just acted on
            // gets a slightly longer settle for the UI to react before the next capture.
            try? await Task.sleep(nanoseconds: acted ? 900_000_000 : 400_000_000)
        }

        // Three different faults used to share one sentence, and it named the wrong one. "Recognized
        // nothing" was reported as *"the guest framebuffer appears blank"* — but a run that hit it had
        // captured 566 sharp, text-filled screenshots; the recognizer was what had failed. Blaming the
        // framebuffer sent the investigation to the capture path, which was working.
        //
        // So the three are now separated by what the run actually observed: no capture at all, capture
        // bytes that no text could be read from, or a screen that was read and not understood.
        let blind = recorder?.onlyBlankFrames(atLeast: 4) ?? false
        let reason: String
        if blind, capturedButUnread > 0 {
            let measured: String = lastCapture
                .flatMap { Self.imageSize(ofCapture: $0) }
                .map { " (\(Int($0.width))×\(Int($0.height))px)" } ?? ""
            let attribution: String
            if let failure = lastRecognitionFailure {
                attribution = " — \(failure)"
            } else {
                attribution = " — it reported no error, so the frames may genuinely be blank; "
                    + "compare frame-*.jpg here, which are the exact bytes it was given"
            }
            reason = "text recognition read nothing from \(capturedButUnread) captured frame(s) "
                + "that did contain image data\(measured). The framebuffer is being captured; the "
                + "RECOGNIZER is the failing part\(attribution)"
        } else if blind {
            reason = "every approval capture came back empty — the guest framebuffer appears blank "
                + "to the host surface rather than showing an unrecognized screen"
        } else {
            let answered: String = authAttempts.isEmpty
                ? "none"
                : authAttempts.sorted { $0.key < $1.key }
                    .map { "\($0.key)×\($0.value)" }.joined(separator: ", ")
            reason = "expected Device Management approval state was not reached "
                + "(password sheets answered: \(answered))"
        }
        let diagnostic = await recordMDMApprovalDiagnostic(
            bundle: bundle, target: target, capture: lastCapture, lines: lastLines,
            reason: reason, recorder: recorder)
        throw MDMOrchestrationError.enrollmentNotApproved(
            reason
                + (diagnostic.map { "; diagnostic: \($0.deletingLastPathComponent().path)" }
                    ?? "; diagnostic capture also failed"))
    }

    /// Short, stable label for one classified approval screen — the transcript's state column.
    static func stateLabel(_ action: UAMDMApprovalAction) -> String {
        switch action {
        case .openEnrollmentProfile: return "open-enrollment-profile"
        case .install: return "install"
        case .authenticate(let sheet, _): return "authenticate-\(sheet)"
        case .installed: return "installed"
        case .installFailed: return "install-failed"
        case .unknown: return "unknown"
        }
    }

    private struct MDMApprovalDiagnostic: Codable {
        var capturedAt: String
        var reason: String
        var recognizedText: [String]
        var frontmostUI: String
        var tccAttribution: String
        /// The guest's own profile-installation log. When an install fails with a message like "The
        /// certificate could not be verified", this is the only place the *reason* (which certificate,
        /// which validation step) is recorded — the on-screen alert says nothing actionable.
        var profileInstallLog: String
        var screenshotFile: String?
    }

    /// Preserve enough evidence to diagnose a changed/foreign modal without recording credentials.
    /// The guest queries use non-interactive command-line tools; failures are themselves recorded.
    private func recordMDMApprovalDiagnostic(
        bundle: MacVMBundle, target: MDMGuestTarget, capture: Data?,
        lines: [(text: String, box: CGRect)], reason: String,
        recorder: MDMDiagnosticsRecorder?
    ) async -> URL? {
        let fm = FileManager.default
        // Co-locate with this attempt's transcript and frames when we have one, so a failure is one
        // directory to read rather than a JSON here and a transcript there.
        let directory = recorder?.directory ?? bundle.mdmDiagnosticsURL
        do {
            try fm.createDirectory(at: directory, withIntermediateDirectories: true)
            try fm.setAttributes([.posixPermissions: 0o700], ofItemAtPath: directory.path)
            let screenshotURL = directory.appendingPathComponent("approval-final.jpg")
            if let capture {
                // Same transcode as the per-frame evidence: the recognizer's capture is a lossless
                // full-resolution image, and this file is for a human to look at.
                try (Self.evidenceJPEG(from: capture) ?? capture)
                    .write(to: screenshotURL, options: .atomic)
                try fm.setAttributes([.posixPermissions: 0o600], ofItemAtPath: screenshotURL.path)
            }
            let frontmost = (try? await runMDMGuest(
                target, command: "/usr/bin/lsappinfo front"))
            let tcc = (try? await runMDMGuest(
                target,
                command: "sudo /usr/bin/log show --last 2m --style compact --predicate "
                    + Self.shQuote("subsystem == \"com.apple.TCC\"")))
            // Why a profile install failed lives here, not on screen: ManagedClient/mdmclient/profiles
            // record the failing certificate and validation step.
            let installLog = (try? await runMDMGuest(
                target,
                command: "sudo /usr/bin/log show --last 10m --style compact --predicate "
                    + Self.shQuote(
                        "subsystem == \"com.apple.ManagedClient\" "
                            + "OR process == \"mdmclient\" OR process == \"profiles\"")))
            let record = MDMApprovalDiagnostic(
                capturedAt: ISO8601DateFormatter().string(from: Date()), reason: reason,
                recognizedText: lines.map(\.text),
                frontmostUI: frontmost.map { $0.stdout + $0.stderr } ?? "unavailable",
                tccAttribution: tcc.map { String(($0.stdout + $0.stderr).suffix(16_000)) }
                    ?? "unavailable",
                profileInstallLog: installLog.map { String(($0.stdout + $0.stderr).suffix(24_000)) }
                    ?? "unavailable",
                screenshotFile: capture == nil ? nil : screenshotURL.lastPathComponent)
            recorder?.note("approval failed: \(reason)")
            let metadataURL = directory.appendingPathComponent("approval.json")
            let encoder = JSONEncoder()
            encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
            try encoder.encode(record).write(to: metadataURL, options: .atomic)
            try fm.setAttributes([.posixPermissions: 0o600], ofItemAtPath: metadataURL.path)
            return metadataURL
        } catch {
            return nil
        }
    }
}
