Security + upstream fixes

- Network core moves to a root-only folder; BroV talks to a narrow root helper (netctl.py) over a user-only socket; install script verifies the mihomo SHA256 and migrates keys (scripts/netcore)
- Hardened runtime, no get-task-allow; bypassPermissions removed from the chat; concealed clipboard items are not restored; DangerCheck knows core, LaunchAgents and hook paths; dropped-file copies expire after 7 days
- Ported from upstream Coucou: 1h crash fix (d05f22b), safe settings.json writes (918d30e), Escape/fold for pending approvals (6012900, 40e3ba8), auto-close delay + reopen (74984f2, ea244a7), full AskUserQuestion (52b1562)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
maksarsanjeev
2026-10-07 23:49:11 +03:00
parent dc47247340
commit 52e1e8288b
21 changed files with 1070 additions and 188 deletions
@@ -15,6 +15,7 @@ final class IslandWindowController: NSWindowController {
private var frameTimer: Timer?
private var keyMonitor: Any?
private var viewSubscription: AnyCancellable?
private var autoCloseSubscription: AnyCancellable?
// Confused recovery timer (set by handleDizzy)
private var confusedRecoveryTimer: DispatchWorkItem?
@@ -163,6 +164,11 @@ final class IslandWindowController: NSWindowController {
// MARK: - FSM wiring
private func wireFSM() {
// Apply the persisted auto-close preference immediately and keep live edits in sync.
autoCloseSubscription = state.$autoCloseInterval.sink { [weak self] delay in
self?.fsm.homeToPetitDelay = delay
}
fsm.onTransition = { [weak self] from, to in
guard let self else { return }
switch to {
@@ -387,15 +393,19 @@ final class IslandWindowController: NSWindowController {
state.lastActivity = .now
}
/// `byUser`: the ⌃ button or the toggle hotkey — folds a chat/terminal tab away too;
/// only a pending approval still keeps the island open.
func collapse(byUser: Bool = false) {
if byUser {
guard state.pendingApproval == nil else { return }
} else {
/// `byUser`: the ⌃ button or the toggle hotkey — folds a chat/terminal tab away too.
/// `allowPendingApproval`: the notch's own Escape, jump-to-terminal — may fold the
/// approval card (but not a chat/terminal tab).
/// Folding a pending approval never answers it: the request stays pending, the island
/// stays compact (held open) and a click or ⌃⌥A brings the card back.
func collapse(byUser: Bool = false, allowPendingApproval: Bool = false) {
let onTallTab = state.mode == .expanded && state.view.isTall
let keepsApprovalPending = state.pendingApproval != nil
&& (byUser || (allowPendingApproval && !onTallTab))
if !byUser && !keepsApprovalPending {
guard fsm.isHeldOpen?() != true else { return }
}
state.isPinned = false
if !keepsApprovalPending { state.isPinned = false }
finishedPinTimer?.cancel()
// Keep the FSM in step with what is on screen (home/coucou → petit now).
fsm.collapse()
@@ -418,6 +428,7 @@ final class IslandWindowController: NSWindowController {
collapse(byUser: true)
} else {
islandPanel.makeKey()
fsm.openedExternally()
expand(to: defaultView())
}
@@ -428,6 +439,7 @@ final class IslandWindowController: NSWindowController {
case .goToAlert:
if state.pendingApproval != nil {
islandPanel.makeKey()
fsm.openedExternally()
expand(to: .approval)
} else if state.pendingQuestion != nil {
islandPanel.makeKey()
@@ -535,8 +547,9 @@ final class IslandWindowController: NSWindowController {
// ⎋ Escape — focused views (.onExitCommand) have first crack; fall back to collapse
if event.keyCode == 53 && raw.isEmpty {
let consumed = NSApp.sendAction(Selector(("cancelOperation:")), to: nil, from: nil)
if !consumed && state.mode == .expanded && !state.isPinned {
collapse()
let canCollapse = !state.isPinned || state.pendingApproval != nil
if !consumed && state.mode == .expanded && canCollapse {
collapse(allowPendingApproval: true)
}
return true
}
@@ -590,7 +603,7 @@ final class IslandWindowController: NSWindowController {
NSWorkspace.shared.open(
URL(fileURLWithPath: "/System/Applications/Utilities/Terminal.app"))
}
collapse()
collapse(allowPendingApproval: true)
}
private func performAttachFrontWindow() {
@@ -615,6 +628,8 @@ final class IslandWindowController: NSWindowController {
Task { @MainActor in
guard let self = self else { return }
if event.keyCode == 53 { // Escape
// Escape typed in another app (Claude Code's own interrupt, an editor…)
// never folds a pending approval away: only Escape in the notch does.
if self.state.mode == .expanded && !self.state.isPinned {
self.collapse()
}
@@ -1187,6 +1202,10 @@ func islandSize(mode: IslandMode, view: IslandView,
let layout = IslandConst.viewLayouts[view]!
// BroV: the chat has its own width (Settings → Чат).
if view.isTall { return (AppState.shared.chatWidth, layout.height) }
// The question card grows to fit the full question and option descriptions.
if view == .question, let h = QuestionLayout.height {
return (IslandConst.expandedWidth, h)
}
return (IslandConst.expandedWidth, layout.height)
}
}