Skip to content

Bug 1781629 - keep macOS notifications off test worker screens (safe re-land) - #1357

Open
rcurranmoz wants to merge 2 commits into
masterfrom
bug-1781629-disable-macos-notifications-v2
Open

Bug 1781629 - keep macOS notifications off test worker screens (safe re-land)#1357
rcurranmoz wants to merge 2 commits into
masterfrom
bug-1781629-disable-macos-notifications-v2

Conversation

@rcurranmoz

Copy link
Copy Markdown
Contributor

Second attempt at Bug 1781629, after #1354 was reverted in #1355. Staging roles only.

Why #1354 broke, precisely

It managed the Focus assertion files under ~/Library/DoNotDisturb, which is TCC protected. macos_tcc_perms grants kTCCServiceSystemPolicyAllFiles to /usr/sbin/sshd and /usr/libexec/sshd-keygen-wrapper (auth_value 2), but puppet's interpreter /opt/puppetlabs/puppet/bin/ruby is denied it (auth_value 0):

sudo sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" \
  'select client, auth_value from access where service="kTCCServiceSystemPolicyAllFiles";'

m4-277 (failed):   /opt/puppetlabs/puppet/bin/ruby|0
r8-109 (passed):   /usr/libexec/sshd-keygen-wrapper|2
                   /usr/sbin/sshd|2

I validated #1354 by running run-puppet.sh over SSH, which inherits sshd's Full Disk Access, so the protected write succeeded. The same catalog applied by org.mozilla.atboot_puppet has no such grant and fails with EPERM on a lock file. The staging validation was invalid by construction, not merely thin — it exercised a TCC context production never uses.

What made it look like something else during triage: the directory permissions are unremarkable (drwxr-xr-x cltbld:staff, no restricted flags) and sudo mkdir in that exact directory succeeds by hand — because that is over SSH too.

Granting puppet FDA would need an MDM PPPC payload, which is MDM-only and out of scope here. So the Focus path is abandoned rather than fixed.

What changed

  • No writes to any TCC protected path. The entire Monterey-and-later Focus branch is gone, with all four payload files (including the 0-byte Settings.sqlite that was truncating cltbld's real Focus database) and Assertions.json, now unreferenced. There is no DND layer above Big Sur. The agent disables are the actual fix and need no TCC grant.
  • Every script exits 0 in command mode. run-puppet.sh forces retval=1 on any ^Error: in the log and mails a failure report per host per boot, so on reboot-per-task pools one unlucky resource is a mail flood plus a fleet-wide false red in last_run_metadata.json. That amplification is what turned Bug 1781629 - keep macOS notifications off test worker screens #1354 from a no-op into an incident. Partial failures now warn and are retried next boot. The only non-zero exits are inside the --check / --count guard modes, where puppet requires them.
  • An unreadable notification store counts as nothing-to-do, not work-pending, so the macOS 13+ store being TCC protected cannot make the exec fire on every apply forever.
  • Staging roles only. Production roles are deliberately untouched until this has survived real reboots.

Retained from #1354, all verified on Catalina, Sonoma and Sequoia: resolving cltbld's uid at run time (it is not derivable from the OS version — 36, 555 and 1025 all occur), writing the launchd override plist so the disable survives the per-task reboot, accepting both spellings of launchctl's disabled value, and not killing cfprefsd after the DND write.

Testing

Puppet validate, puppet-lint and shellcheck green.

Validated by actual reboot on macmini-m4-113 (macOS 15.3, the OS that broke), reading /var/log/puppet/puppet.out from the atboot run. SSH-driven applies are no longer accepted as evidence for this module. Result posted as a comment below.

Follow-ups, not in this PR

  • Production roles, after staging soak.
  • macmini-r8-154 has a truncated Settings.sqlite from the old module. Nothing repairs it now that the file is unmanaged; needs a manual restore from a clean host.
  • macos_utils::suppress_keyboard_assistant maps OS major to cltbld's uid and is wrong on any host where it is 1025. Same class of silent bug.

🤖 Generated with Claude Code

rcurranmoz and others added 2 commits August 26, 2026 14:12
…re-land)

Second attempt. #1354 was reverted in #1355 because it managed the Focus
assertion files under ~/Library/DoNotDisturb, which the atboot puppet run
cannot write.

Root cause of that failure: puppet's ruby is denied
kTCCServiceSystemPolicyAllFiles, while macos_tcc_perms grants it to /usr/sbin/sshd
and /usr/libexec/sshd-keygen-wrapper. Running run-puppet.sh over ssh therefore
borrows sshd's Full Disk Access and the write succeeds; the same catalog applied
by org.mozilla.atboot_puppet has no such grant and fails with EPERM on a lock
file. The staging validation was invalid by construction, not merely
insufficient -- it exercised a TCC context production never uses. Granting
puppet FDA would need an MDM PPPC payload, which is out of scope here.

Changes from #1354:

- No writes to any TCC protected location. The whole Monterey-and-later Focus
  branch is gone, along with the four payload files. Assertions.json is dropped
  too, since nothing references it now. There is no DND layer above Big Sur;
  the agent disables are the actual fix and they need no TCC grant.
- Every script exits 0 in command mode. run-puppet.sh forces retval=1 on any
  "^Error:" in the log and mails a failure report per host per boot, so on
  reboot-per-task pools one unlucky resource is a mail flood plus a fleet-wide
  false red in last_run_metadata.json. Partial failures now warn and retry.
- clear_notification_store.sh treats an unreadable store as nothing-to-do
  rather than work-pending, so the macOS 13+ store being TCC protected cannot
  make the exec run on every apply forever.
- Wired to the three staging roles ONLY. Production roles are deliberately
  untouched until this has survived real reboots on staging.

Retained from #1354 (all verified on Catalina, Sonoma and Sequoia): resolving
cltbld's uid at run time, writing the launchd override plist so the disable
survives the per-task reboot, accepting both spellings of launchctl's disabled
value, and not killing cfprefsd after the DND write.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Puppet on these roles is not started by org.mozilla.atboot_puppet; nothing in
the gecko-t macOS roles installs that. It is started by the
org.mozilla.worker-runner LaunchDaemon, whose worker-runner.sh calls
run-puppet.sh and only then starts the worker.

No behaviour change. The TCC reasoning is unaffected -- worker-runner runs as
root with no Full Disk Access grant either -- and the ordering claim is actually
confirmed rather than weakened: puppet genuinely does run before the worker
starts, so restarting NotificationCenter cannot land mid-task.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@rcurranmoz

Copy link
Copy Markdown
Contributor Author

Validation result

Run on macmini-m4-114 (macOS 15.3 — the release #1354 broke on), driven by sudo launchctl kickstart -k system/org.mozilla.worker-runner, i.e. puppet started by the LaunchDaemon as root with no Full Disk Access. Not over SSH. Log read from /opt/worker/logs/stdout.log, truncated before each run.

run commit ^Error: Macos_notification_disabler changes result
1 f6b2e33c 0 4 update prefs, 3 script files, agent disable Applied catalog in 66.63s / succeeded
2 a57ca264 0 3 script files (comment-only edit in that commit) Applied catalog in 65.35s / succeeded
3 a57ca264 0 0 — converged Applied catalog in 64.93s / succeeded

last_run_metadata.json after run 3: ts=2026-08-26T18:24:26Z sha=a57ca264 success=True exit_code=0.

Run 2 is not an idempotency result — the three scripts legitimately changed because that commit edited their comments. Run 3, on the identical commit, is the convergence proof.

On-host state after run 1:

Focus DB untouched:  Settings.sqlite still 110592 bytes, DB dir contents unchanged
agents disabled:     uid=555 (resolved at run time), 5/5 in disabled.555.plist, 5/5 in launchctl print-disabled
--check exit:        0 (converged, so the exec is suppressed on subsequent applies)

The clear banked notifications and enable do not disturb execs correctly did not fire: nothing was banked, and the DND script no-ops above Big Sur.

Zero ^Error: across all three runs is the property that matters most here. run-puppet.sh forces retval=1 on any ^Error: and mails a failure report per host per boot, which is what escalated #1354 from an ineffective resource into a fleet-wide mail flood and a false red in last_run_metadata.json.

Two notes for reviewers

macmini-m4-114 is currently pinned to this branch via /opt/puppet_environments/ronin_settings and should be returned to master once this is done with.

Separately, and not caused by this change: the m4 staging pool is drifting. macmini-m4-113 has been failing git fetch since 2026-08-11 — on master, not just this branch — so it has not applied puppet in 15 days. m4-112 last applied Aug 5, m4-115 Jul 17. Nothing alerts on this, which also means a quiet staging soak is not by itself evidence that anything was exercised.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant