diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 65f0ff1..bec3001 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,8 +5,12 @@ on: pull_request: jobs: build: - runs-on: macos-14 + # Needs a Swift 6 toolchain: the codebase relies on region-based isolation + # (weak-self captures inside @MainActor Tasks) that Swift 5.10 rejects. + runs-on: macos-15 steps: - uses: actions/checkout@v4 - name: Build (release) run: swift build -c release + - name: Test + run: swift test diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b267600 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,51 @@ +# Changelog + +All notable changes to Curtain are documented here. The format follows +[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow +[Semantic Versioning](https://semver.org/). + +## [Unreleased] + +### Added +- Three-signal session detection: the `CGSSessionScreenIsCaptured` capture key + (primary, transport-independent), an ESTABLISHED inbound TCP connection on + port 5900 (standard Screen Sharing), and a peered UDP socket on 5900-5902 + (High-Performance Screen Sharing). +- Diagnostic probe (`Scripts/probe-detection.swift`) that reports every raw + detection signal once per second and diffs the full CGSession dictionary. +- Per-signal diagnostic logging on every detection transition. +- Password box placement on a specific display, chosen from a picker of + connected displays. +- Activation notification: a real notification banner when the curtain rises. +- Emergency escape: Control + Option + Command + U force-deactivates without + Accessibility. + +### Changed +- Idle detection honors its source setting; the default is now remote session + activity, so the idle timer tracks the remote operator rather than the desk. +- Cover scope is a two-mode model: all displays (default) or per-display Cover + toggles. Legacy scope values migrate automatically. +- The aerial cover style shares one video decoder across all displays. +- "Refuse to arm" (Accessibility missing) is enforced at the master switch. +- Release script: signing failures abort the build; the bundle version number + increases monotonically with the repository history. + +### Fixed +- Session detection: the network probe pointed at a nonexistent netstat path, + which silently disabled the TCP activator. +- The per-display Cover toggle had no effect in the default scope and inverted + meaning in one legacy scope. +- A curtain preview test could drop the cover of a live session after the + preview delay. +- The desk password buffer is zeroed on successful unlock and on dismissal. +- A stale aerial playability check could tear down a rebuilt video player. +- The menu deactivate no longer refuses when the input tap is unavailable and + the on-cover password box cannot receive keys. + +## [1.0.0] — unreleased (pending live verification and notarization) + +Initial release: menu-bar privacy curtain for macOS Screen Sharing hosts. +Covers all displays and blocks physical input during an inbound session; +desk password reveal; idle and end-of-session actions (disconnect, lock, +displays off, deactivate); configurable cover styles; optional privileged +disconnect helper; open-at-login. diff --git a/Sources/Curtain/Settings.swift b/Sources/Curtain/Settings.swift index 02a4647..ec3228b 100644 --- a/Sources/Curtain/Settings.swift +++ b/Sources/Curtain/Settings.swift @@ -318,7 +318,7 @@ enum Settings { private static func legacySHA256(_ s: String, salt: String) -> String { var out = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) let data = Array((salt + s).utf8) - data.withUnsafeBufferPointer { CC_SHA256($0.baseAddress, CC_LONG($0.count), &out) } + data.withUnsafeBufferPointer { _ = CC_SHA256($0.baseAddress, CC_LONG($0.count), &out) } return hex(out) }