Skip to content

Install/upgrade network extension on system wake - #810

Merged
mlw merged 2 commits into
mainfrom
mlw/netext-install-on-wake
Feb 24, 2026
Merged

Install/upgrade network extension on system wake#810
mlw merged 2 commits into
mainfrom
mlw/netext-install-on-wake

Conversation

@mlw

@mlw mlw commented Feb 24, 2026

Copy link
Copy Markdown
Contributor

This adds support for automatic install/upgrade of the network extension when the system wakes up.

Part of SNT-261

@mlw mlw added this to the 2026.2 milestone Feb 24, 2026
@mlw
mlw requested a review from a team as a code owner February 24, 2026 05:02
@github-actions github-actions Bot added comp/santad Issues or PRs related to the daemon lang/objc++ PRs modifying files in ObjC++ size/m Size: medium labels Feb 24, 2026
@coderabbitai

coderabbitai Bot commented Feb 24, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds a forced/conditional network-extension install API and an upgrade-check for the network extension, exposes additional build dependencies, and wires a PowerMonitor callback in the daemon to trigger installation on system wake and first launch after boot.

Changes

Cohort / File(s) Summary
Build config
Source/santad/BUILD
Added public dependencies: //Source/common:SNTCommonEnums, //Source/common:SNTFileInfo (for SNTNetworkExtensionQueue) and //Source/common:PowerMonitor (for Santad).
Daemon control
Source/santad/SNTDaemonControlController.h, Source/santad/SNTDaemonControlController.mm
New RPC method -installNetworkExtensionForce:reply: that delegates install requests to Santad and returns BOOL result; respects authorization and force semantics.
Network extension queue
Source/santad/SNTNetworkExtensionQueue.h, Source/santad/SNTNetworkExtensionQueue.mm
New method -networkExtensionNeedsUpgrade implemented: reads on-disk version (SNTFileInfo), fetches loaded version with timeout, compares versions, and logs outcomes; imports SNTCommonEnums and SNTFileInfo.
Daemon main
Source/santad/Santad.mm
Introduced PowerMonitor usage and a centralized install block; triggers install on first launch after boot and on power wake (kHasPoweredOn); added PowerMonitor instance and updated logging.

Sequence Diagram(s)

sequenceDiagram
    participant System as System
    participant PowerMon as PowerMonitor
    participant Santad as Santad Daemon
    participant NEQueue as SNTNetworkExtensionQueue
    participant NetExt as Network Extension

    System->>PowerMon: System powers on / wakes (kHasPoweredOn)
    PowerMon->>Santad: invoke wake callback
    Santad->>NEQueue: installNetworkExtension(reason="System woke up")
    NEQueue->>NEQueue: shouldInstallNetworkExtension?
    alt Installation allowed
        NEQueue->>NetExt: install/upgrade extension
        NetExt-->>NEQueue: success/failure
        NEQueue-->>Santad: reply(success/false)
    else Installation not allowed
        NEQueue-->>Santad: reply(false)
    end
Loading
sequenceDiagram
    participant Client as External Controller
    participant DCC as SNTDaemonControlController
    participant Santad as Santad Daemon
    participant NEQueue as SNTNetworkExtensionQueue

    Client->>DCC: RPC installNetworkExtensionForce(force=BOOL)
    DCC->>Santad: request install (forward)
    Santad->>NEQueue: shouldInstallNetworkExtension / networkExtensionNeedsUpgrade (if not forced)
    alt Installation allowed or forced
        NEQueue->>NEQueue: perform install
        NEQueue-->>Santad: result YES
    else Denied / not needed
        NEQueue-->>Santad: result NO
    end
    Santad-->>DCC: return result
    DCC-->>Client: reply(result)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Install/upgrade network extension on system wake' directly and clearly summarizes the main change: adding support for network extension installation/upgrade triggered by system wake events.
Description check ✅ Passed The description accurately describes the changeset: it states the PR adds automatic install/upgrade of the network extension when the system wakes up, which aligns with the code changes shown in the raw summary.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mlw/netext-install-on-wake

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
Source/santad/SNTDaemonControlController.mm (1)

735-748: Minor: shouldInstallNetworkExtension is checked twice in the call chain.

installNetworkExtensionForce checks shouldInstallNetworkExtension (line 737) and then delegates to installNetworkExtension:reply:, which redundantly rechecks it (line 707). If the state flips between the two checks, the "not authorized" LOGI in installNetworkExtension:reply: fires despite having already passed the check here.

♻️ Proposed fix – pass `reply` directly to the internal helper

Either extract the body of installNetworkExtension:reply: (after the authorization check) into a shared helper, or skip the authorization re-check inside installNetworkExtension:reply: when called via the Force path. The simplest approach is to introduce a private _installNetworkExtensionWithReply: that skips the authorization guard, letting both public entry points call it after performing their own checks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Source/santad/SNTDaemonControlController.mm` around lines 735 - 748,
installNetworkExtensionForce redundantly checks shouldInstallNetworkExtension
before calling installNetworkExtension:reply: which repeats the same guard;
create a private helper _installNetworkExtensionWithReply: that contains the
installation logic without the authorization check, update
installNetworkExtension:reply: to keep its existing
shouldInstallNetworkExtension guard and call _installNetworkExtensionWithReply:
when authorized, and change installNetworkExtensionForce:reply: to perform its
authorization/force checks and then call _installNetworkExtensionWithReply:
directly so the "not authorized" LOGI inside installNetworkExtension:reply: no
longer fires erroneously.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Source/santad/SNTDaemonControlController.h`:
- Around line 44-47: Update the doc comment for
-installNetworkExtensionForce:reply: to accurately state that when force is YES
it bypasses the on-disk vs loaded version comparison but does not
unconditionally call -installNetworkExtension:; the method still respects the
shouldInstallNetworkExtension check and will short-circuit with reply(NO) if
shouldInstallNetworkExtension returns NO. Mention both behaviors (bypasses
version comparison; still consults shouldInstallNetworkExtension and may return
NO instead of invoking -installNetworkExtension:).

In `@Source/santad/SNTNetworkExtensionQueue.h`:
- Around line 56-60: Update the documentation for -[SNTNetworkExtensionQueue
networkExtensionNeedsUpgrade] to mention that the call performs a blocking XPC
check with a 5-second timeout and that if the XPC call times out it will return
YES; specifically, add a sentence to the existing comment clarifying the
5-second timeout behavior and that a timeout is treated the same as "extension
not connected" (i.e., returns YES) so readers understand the blocking/fallback
semantics for networkExtensionNeedsUpgrade.

---

Nitpick comments:
In `@Source/santad/SNTDaemonControlController.mm`:
- Around line 735-748: installNetworkExtensionForce redundantly checks
shouldInstallNetworkExtension before calling installNetworkExtension:reply:
which repeats the same guard; create a private helper
_installNetworkExtensionWithReply: that contains the installation logic without
the authorization check, update installNetworkExtension:reply: to keep its
existing shouldInstallNetworkExtension guard and call
_installNetworkExtensionWithReply: when authorized, and change
installNetworkExtensionForce:reply: to perform its authorization/force checks
and then call _installNetworkExtensionWithReply: directly so the "not
authorized" LOGI inside installNetworkExtension:reply: no longer fires
erroneously.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 202fd5c and 7933557.

📒 Files selected for processing (6)
  • Source/santad/BUILD
  • Source/santad/SNTDaemonControlController.h
  • Source/santad/SNTDaemonControlController.mm
  • Source/santad/SNTNetworkExtensionQueue.h
  • Source/santad/SNTNetworkExtensionQueue.mm
  • Source/santad/Santad.mm

Comment thread Source/santad/SNTDaemonControlController.h
Comment thread Source/santad/SNTNetworkExtensionQueue.h

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
Source/santad/SNTDaemonControlController.h (1)

44-47: ⚠️ Potential issue | 🟡 Minor

Doc comment still exposes an internal method name and omits the version-check bypass.

The addition of "as long as installation is authorized" correctly addresses the past concern about the comment implying an unconditional call. Two small gaps remain:

  1. delegates to installNetworkExtension: is an implementation detail and shouldn't appear in a public API doc.
  2. The comment doesn't state that force=YES bypasses the version-comparison check, which is the defining behavioral difference from force=NO.
📝 Suggested correction
-/// Install the network extension, optionally checking whether an upgrade is needed first.
-/// When force is YES, delegates to installNetworkExtension: as long as installation is authorized.
-/// When force is NO, skips install if the loaded version already matches the on-disk version.
+/// Installs or upgrades the network extension if authorized.
+/// Always skips installation when the network extension is not authorized
+/// (i.e., sync v2 is disabled or enable is not set in sync settings).
+/// When force is YES, bypasses the version check and triggers installation directly.
+/// When force is NO, skips install if the loaded version already matches the on-disk version.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Source/santad/SNTDaemonControlController.h` around lines 44 - 47, Update the
doc comment for -installNetworkExtensionForce:reply: to avoid exposing internal
implementation details and to explicitly state the behavioral difference when
force is YES; remove the phrase "delegates to installNetworkExtension:" and
replace it with a neutral description of the behavior, and add a sentence that
when force is YES the method bypasses the on-disk vs loaded version comparison
(i.e., installation proceeds if authorized), whereas when force is NO the method
skips installation if the loaded version already matches the on-disk version;
ensure the method name -installNetworkExtensionForce:reply: is referenced only
as the API symbol being documented.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@Source/santad/SNTDaemonControlController.h`:
- Around line 44-47: Update the doc comment for
-installNetworkExtensionForce:reply: to avoid exposing internal implementation
details and to explicitly state the behavioral difference when force is YES;
remove the phrase "delegates to installNetworkExtension:" and replace it with a
neutral description of the behavior, and add a sentence that when force is YES
the method bypasses the on-disk vs loaded version comparison (i.e., installation
proceeds if authorized), whereas when force is NO the method skips installation
if the loaded version already matches the on-disk version; ensure the method
name -installNetworkExtensionForce:reply: is referenced only as the API symbol
being documented.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7933557 and ad89a5e.

📒 Files selected for processing (1)
  • Source/santad/SNTDaemonControlController.h

Comment thread Source/santad/Santad.mm
@mlw
mlw merged commit ab1e421 into main Feb 24, 2026
7 checks passed
@mlw
mlw deleted the mlw/netext-install-on-wake branch February 24, 2026 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/santad Issues or PRs related to the daemon lang/objc++ PRs modifying files in ObjC++ size/m Size: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants