Skip to content

sync: support batched mode for sync state and handle clean sync#944

Merged
sharvilshah merged 9 commits into
mainfrom
sbs/snt-357
May 15, 2026
Merged

sync: support batched mode for sync state and handle clean sync#944
sharvilshah merged 9 commits into
mainfrom
sbs/snt-357

Conversation

@sharvilshah
Copy link
Copy Markdown
Contributor

@sharvilshah sharvilshah commented May 11, 2026

Support batched mode for sync state and handle clean sync

Fixes SNT-357

@github-actions github-actions Bot added configurator Issues or PRs related to the configurator / Santa configuration comp/santad Issues or PRs related to the daemon comp/santasyncservice Issues or PRs related to the sync protocol lang/objc++ PRs modifying files in ObjC++ comp/common size/l Size: large labels May 11, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: daaadff0-72f5-47f7-8906-8bc0e09759fc

📥 Commits

Reviewing files that changed from the base of the PR and between 758b76d and 636c1f2.

📒 Files selected for processing (5)
  • Source/common/SNTConfigurator.h
  • Source/common/SNTConfigurator.mm
  • Source/common/SNTConfiguratorTest.mm
  • Source/santad/SNTDaemonControlController.mm
  • Source/santad/TemporaryMonitorMode.mm
🚧 Files skipped from review as they are similar to previous changes (5)
  • Source/santad/TemporaryMonitorMode.mm
  • Source/common/SNTConfigurator.h
  • Source/common/SNTConfiguratorTest.mm
  • Source/common/SNTConfigurator.mm
  • Source/santad/SNTDaemonControlController.mm

📝 Walkthrough

Walkthrough

Adds a persisted clearSyncStateBeforeApply callback to SNTConfigBundle, implements performSyncStateBatch: in SNTConfigurator to buffer and atomically commit sync-state (single KVO + single disk write), updates daemon to apply sync updates inside a batch and defer CEL cache flush until after commit, and adds tests for these behaviors.

Changes

Sync-State Atomic Batching and Clear Flow

Layer / File(s) Summary
Config bundle API & serialization
Source/common/SNTConfigBundle.h, Source/common/SNTConfigBundle.mm
Adds exported callback setter -clearSyncStateBeforeApply:(void (^)(BOOL))block, private NSNumber *clearSyncStateBeforeApply storage, NSCoding encode/decode of the field, and an accessor that invokes the block with a BOOL.
Config bundle tests
Source/common/SNTConfigBundleTest.mm
Test category exposes test-only clearSyncStateBeforeApply and adds testClearSyncStateBeforeApplyRoundTrips to assert NSKeyedArchiver round-trip and accessor invocation behavior.
Configurator API docs
Source/common/SNTConfigurator.h
Declares - (BOOL)performSyncStateBatch:(nonnull void(NS_NOESCAPE ^)(void))block; with docs describing in-memory batching, single KVO commit, single atomic disk write, nesting and failure semantics.
Configurator batching implementation
Source/common/SNTConfigurator.mm
Adds batchedSyncState working dictionary; updateSyncStateForKey:value: writes to batch when active; implements performSyncStateBatch: to seed batch from syncState, run block on main thread, commit batch to syncState, persist once via saveSyncStateToDisk and clear batch; saveSyncStateToDisk now returns BOOL and respects authorizer; clearSyncState is main-thread aware and batch-aware (clears batch or resets syncState and removes on-disk plist).
Configurator tests
Source/common/SNTConfiguratorTest.mm
Adds helper to create configurator with a test plist path and KVO counter; tests: single KVO notification for a batch of updates; batch returns NO on disk-write failure while applying in-memory/KVO; clear+write within batch removes stale on-disk keys; clear outside batch removes plist; clear is idempotent on missing file; authorizer-denied path still clears in-memory and removes file.
Daemon controller integration
Source/santad/SNTDaemonControlController.mm
updateSyncSettings snapshots serialized CEL fallback rules before batch, applies settings inside performSyncStateBatch:, moves mode-transition enforcement to post-commit while persisting only the server-side transition inside the batch, reserializes CEL after commit and flushes CEL caches only if serialized rules changed; fixes ruleSyncLastSuccess wiring.
Sync bundle creation
Source/santasyncservice/SNTSyncConfigBundle.mm
PostflightConfigBundle sets clearSyncStateBeforeApply = YES when syncState.syncType is not SNTSyncTypeNormal and populates pushTokenChain only when both JWTs present.
Sync bundle tests (unit & integration)
Source/santasyncservice/SNTSyncConfigBundleTest.mm, Source/santasyncservice/SNTSyncTest.mm
Adds test-only property exposures and tests asserting PostflightConfigBundle sets clear flag only for Clean/CleanAll (fires with YES), verifies pushTokenChain population/omission, and integration tests capture postflight bundles to confirm flag behavior for Clean/CleanAll vs Normal.
Temporary monitor mode enforcement
Source/santad/TemporaryMonitorMode.mm
NewModeTransitionReceived now performs revoke-only enforcement (no non-revoke configurator writes) and RevokeLocked avoids redundant writes when already revoked.

Sequence Diagram(s)

sequenceDiagram
  participant SNTSyncPostflight as SNTSyncPostflight
  participant SNTConfigBundle as SNTConfigBundle
  participant SNTDaemonControlController as DaemonController
  participant SNTConfigurator as Configurator
  participant Disk as Disk

  SNTSyncPostflight->>SNTConfigBundle: create PostflightConfigBundle (may set clearSyncStateBeforeApply)
  DaemonController->>SNTConfigurator: performSyncStateBatch(block)
  SNTConfigurator->>SNTConfigurator: seed batchedSyncState from syncState
  DaemonController->>SNTConfigurator: apply multiple syncState updates (writes go to batchedSyncState)
  alt bundle requests clear before apply
    SNTConfigBundle->>SNTConfigurator: invoke clearSyncStateBeforeApply(YES) -> clears persisted state (batch-aware)
  end
  SNTConfigurator->>SNTConfigurator: commit batchedSyncState -> syncState (single KVO)
  SNTConfigurator->>Disk: atomic write sync-state plist
  DaemonController->>SNTConfigurator: run post-commit mode transition enforcement
  DaemonController->>DaemonController: serialize new CEL rules and flush caches if changed
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • northpolesec/santa#847: Overlaps with daemon CEL fallback cache-flush timing changes; both modify updateSyncSettings CEL flush logic.
  • northpolesec/santa#838: Related updates to CEL fallback expressions/wiring that interact with the deferred CEL flush and batching timing.
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main changes: adding batched mode support for sync state and handling clean sync operations.
Description check ✅ Passed The description is directly related to the changeset, referencing the feature (batched mode for sync state and clean sync handling) and linking to the issue (SNT-357).

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sbs/snt-357

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Source/common/SNTConfigurator.mm`:
- Around line 1986-1998: Wrap the call to block() in an Objective-C
`@try/`@finally (and optional `@catch` to log) so that self.batchedSyncState is
always cleared on exit: set self.batchedSyncState = self.syncState.mutableCopy
before the try, call block() inside `@try`, move the assignments self.syncState =
self.batchedSyncState and [self saveSyncStateToDisk] into the normal path, and
in `@finally` set self.batchedSyncState = nil (and if you add `@catch`, log the
exception with LOGE and rethrow). This ensures performSyncStateBatch:, and the
properties batchedSyncState/syncState and method saveSyncStateToDisk, do not
leave a stale batchedSyncState after an exception.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2b90c4dc-7963-4d56-9c96-c41dfadca770

📥 Commits

Reviewing files that changed from the base of the PR and between 4a0f326 and efd35df.

📒 Files selected for processing (10)
  • Source/common/SNTConfigBundle.h
  • Source/common/SNTConfigBundle.mm
  • Source/common/SNTConfigBundleTest.mm
  • Source/common/SNTConfigurator.h
  • Source/common/SNTConfigurator.mm
  • Source/common/SNTConfiguratorTest.mm
  • Source/santad/SNTDaemonControlController.mm
  • Source/santasyncservice/SNTSyncConfigBundle.mm
  • Source/santasyncservice/SNTSyncConfigBundleTest.mm
  • Source/santasyncservice/SNTSyncTest.mm

Comment thread Source/common/SNTConfigurator.mm Outdated
Comment thread Source/common/SNTConfigurator.h Outdated
@sharvilshah sharvilshah marked this pull request as ready for review May 11, 2026 15:14
@sharvilshah sharvilshah requested a review from a team as a code owner May 11, 2026 15:14
@sharvilshah sharvilshah added this to the 2026.4 milestone May 11, 2026
Builds on #944. Three connected changes:

1. Pull modeTransition persistence into performSyncStateBatch so it
commits atomically with the rest of sync-derived state. TMM's
enforcement side effects (Revoke + GUI notify) run after the batch via
NewModeTransitionReceived so Available(nil) reads consistent post-commit
state.

To avoid a second syncState KVO fire on the Revoke path, RevokeLocked
skips its own setSyncServerModeTransition: when the current transition
is already a revoke. Other Revoke entry points (sync URL change, etc.)
keep their existing behavior.

2. performSyncStateBatch: and saveSyncStateToDisk return BOOL so callers
can gate post-commit work on durable persistence. Used to skip the CEL
cache flush on disk failure. Removed the @try/@finally wrapper around
the batch block; runtime exceptions are fatal by design.

3. Drop the syncStateAccessAuthorizerBlock guard from clearSyncState.
The production authorizer requires syncBaseURL != nil, but SNTSyncdQueue
invokes clearSyncState precisely when syncBaseURL went to nil. Gating
cleanup there would make it unreachable.

Tests cover the BOOL return on disk failure and lock in clearSyncState's
authorizer bypass.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
Source/common/SNTConfiguratorTest.mm (1)

377-380: ⚡ Quick win

Assert performSyncStateBatch: succeeds in the clear-path test.

This test validates disk/in-memory post-clear state, but it does not assert the API contract (YES on successful durable commit) for this path.

Suggested test tightening
-  [cfg performSyncStateBatch:^{
+  BOOL committed = [cfg performSyncStateBatch:^{
     [cfg clearSyncState];
     [cfg setSyncServerClientMode:SNTClientModeMonitor];
   }];
+  XCTAssertTrue(committed, @"Batch with clear + post-clear writes should commit successfully");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Source/common/SNTConfiguratorTest.mm` around lines 377 - 380, The test calls
[cfg performSyncStateBatch:^{ ... }] but does not assert its return value;
update the test to capture the BOOL result of performSyncStateBatch: and assert
it equals YES to verify the durable commit succeeded (i.e. call
performSyncStateBatch: and XCTAssertTrue(result) or equivalent). Ensure you
reference performSyncStateBatch:, clearSyncState, and
setSyncServerClientMode:SNTClientModeMonitor when adding the assertion so the
success of that batch operation is enforced in the clear-path test.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@Source/common/SNTConfiguratorTest.mm`:
- Around line 377-380: The test calls [cfg performSyncStateBatch:^{ ... }] but
does not assert its return value; update the test to capture the BOOL result of
performSyncStateBatch: and assert it equals YES to verify the durable commit
succeeded (i.e. call performSyncStateBatch: and XCTAssertTrue(result) or
equivalent). Ensure you reference performSyncStateBatch:, clearSyncState, and
setSyncServerClientMode:SNTClientModeMonitor when adding the assertion so the
success of that batch operation is enforced in the clear-path test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ca786f6e-921e-4311-8ea7-819a5592e70a

📥 Commits

Reviewing files that changed from the base of the PR and between 758b76d and f2d1fdc.

📒 Files selected for processing (5)
  • Source/common/SNTConfigurator.h
  • Source/common/SNTConfigurator.mm
  • Source/common/SNTConfiguratorTest.mm
  • Source/santad/SNTDaemonControlController.mm
  • Source/santad/TemporaryMonitorMode.mm
🚧 Files skipped from review as they are similar to previous changes (2)
  • Source/santad/SNTDaemonControlController.mm
  • Source/common/SNTConfigurator.mm

Copy link
Copy Markdown
Member

@pmarkowsky pmarkowsky left a comment

Choose a reason for hiding this comment

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

LGTM.

@sharvilshah sharvilshah merged commit dac0f63 into main May 15, 2026
8 checks passed
@sharvilshah sharvilshah deleted the sbs/snt-357 branch May 15, 2026 06:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/common comp/santad Issues or PRs related to the daemon comp/santasyncservice Issues or PRs related to the sync protocol configurator Issues or PRs related to the configurator / Santa configuration lang/objc++ PRs modifying files in ObjC++ size/l Size: large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants