Skip to content

Add recovery lock password status#41322

Merged
mostlikelee merged 97 commits intomainfrom
40657-status
Mar 17, 2026
Merged

Add recovery lock password status#41322
mostlikelee merged 97 commits intomainfrom
40657-status

Conversation

@mostlikelee
Copy link
Contributor

@mostlikelee mostlikelee commented Mar 10, 2026

Related issue: Resolves #40657

  • Adds recovery key password to host details and Controls > OS Settings > Summary

Summary by CodeRabbit

  • New Features
    • Added recovery lock password status visibility for macOS devices with MDM enabled. Status tracking now displays pending, verified, verifying, or failed states along with detailed information for each host.

Base automatically changed from 40656-mdm-refactor to main March 12, 2026 12:06
mostlikelee and others added 2 commits March 17, 2026 08:21
The sqlJoinRecoveryLockStatus() function was missing a `deleted = 0`
filter, which could cause soft-deleted recovery lock records to affect
the OS settings summary counts incorrectly.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds TestHostDetailsRecoveryLockPasswordStatus with two subtests:
- Verifies recovery lock password status populates correctly for macOS hosts
- Verifies the status function is not called for non-macOS platforms

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@mostlikelee
Copy link
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 17, 2026

✅ Actions performed

Full review triggered.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 17, 2026

Walkthrough

This pull request adds recovery lock password status retrieval for MDM-managed macOS hosts. It introduces a new GetHostRecoveryLockPasswordStatus datastore method to query recovery lock password status and detail information, integrates recovery lock status into MDM Apple status calculations via SQL joins, and populates this status information in the host details API response for macOS hosts. The changes include updates to the datastore interface, MySQL implementation with new SQL joins, host data structures, mock implementations, and comprehensive test coverage across multiple test files.

Possibly related PRs

  • Set recovery lock password - mdm commands #41217: Implements broader recovery lock password functionality with corresponding datastore and mock changes for recovery lock password status handling that complement this PR's status retrieval logic.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is incomplete. Missing required checklist items including changes files, testing details, and database migration verification. Complete the PR description by checking applicable boxes in the provided template (changes files, testing, database migrations) and ensure all required sections are addressed.
Docstring Coverage ⚠️ Warning Docstring coverage is 68.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change by clearly identifying the addition of recovery lock password status functionality.
Linked Issues check ✅ Passed The PR implementation aligns with issue #40657 requirements: recovery lock password status added to host details API and profile summary via datastore, service layer, and UI updates.
Out of Scope Changes check ✅ Passed All changes are directly related to issue #40657 objectives: datastore queries, service layer retrieval, mock updates, and comprehensive test coverage for recovery lock password status.

✏️ 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
  • Commit unit tests in branch 40657-status
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Tip

You can make CodeRabbit's review stricter and more nitpicky using the `assertive` profile, if that's what you prefer.

Change the reviews.profile setting to assertive to make CodeRabbit's nitpick more issues in your PRs.

Copy link
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: 2

🧹 Nitpick comments (1)
server/service/hosts_test.go (1)

813-817: Tighten the test by asserting the host UUID and failing fast on unexpected non-macOS calls.

Right now invocation is tracked, but asserting the UUID improves correctness, and a fail-fast callback gives clearer diagnostics if the non-macOS guard regresses.

Suggested test hardening
 		ds.GetHostRecoveryLockPasswordStatusFunc = func(ctx context.Context, hostUUID string) (*fleet.HostMDMRecoveryLockPassword, error) {
+			require.Equal(t, "test-uuid", hostUUID)
 			return &fleet.HostMDMRecoveryLockPassword{
 				Status: &failedStatus,
 				Detail: "SetRecoveryLock command failed",
 			}, nil
 		}
@@
 		ds.GetHostRecoveryLockPasswordStatusFuncInvoked = false
 		ds.GetHostRecoveryLockPasswordStatusFunc = func(ctx context.Context, hostUUID string) (*fleet.HostMDMRecoveryLockPassword, error) {
-			return nil, nil
+			t.Fatalf("GetHostRecoveryLockPasswordStatus should not be called for non-macOS hosts (uuid=%s)", hostUUID)
+			return nil, nil
 		}

Also applies to: 835-837

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

In `@server/service/hosts_test.go` around lines 813 - 817, Update the test doubles
for GetHostRecoveryLockPasswordStatusFunc to assert the received host UUID
equals the expected test host UUID and fail fast on any unexpected invocation:
inside the stub for ds.GetHostRecoveryLockPasswordStatusFunc (and the other
occurrence around lines 835-837), compare the hostUUID argument to the expected
UUID and call t.Fatalf (or t.Fatalf equivalent) if it differs or if the stub is
called in a non-macOS/otherwise-unexpected path so the test fails immediately
and gives a clear diagnostic instead of silently recording the call.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/datastore/mysql/apple_mdm.go`:
- Around line 3656-3669: The rl_pending aggregate currently only marks rows
where status == pending, causing retryable recovery-lock rows to be excluded;
update the SELECT that computes rl_pending (from host_recovery_key_passwords) to
treat retryable statuses as pending as well (e.g., change the MAX(IF(status =
pending, 1, 0)) expression to include retryable via an IN or OR check) so
ClearRecoveryLockPendingStatus's retry window still shows rl_pending; modify the
condition that builds rl_pending in the SQL fragment referencing
host_recovery_key_passwords and rl_pending accordingly.
- Around line 7345-7363: GetHostRecoveryLockPasswordStatus reads a nullable
status so when ClearRecoveryLockPendingStatus sets status to NULL the API
returns Status: nil and hides an outstanding retry; update
GetHostRecoveryLockPasswordStatus to coalesce a nil row.Status into a concrete
"retry/pending" MDMDeliveryStatus before returning (e.g., if row.Status == nil
set the returned Status to the existing retry/pending constant on
fleet.MDMDeliveryStatus, or add such a constant if it doesn't exist) so the host
details always indicate an outstanding recovery-lock retry; refer to the
GetHostRecoveryLockPasswordStatus function and the
ClearRecoveryLockPendingStatus behavior when making the change.

---

Nitpick comments:
In `@server/service/hosts_test.go`:
- Around line 813-817: Update the test doubles for
GetHostRecoveryLockPasswordStatusFunc to assert the received host UUID equals
the expected test host UUID and fail fast on any unexpected invocation: inside
the stub for ds.GetHostRecoveryLockPasswordStatusFunc (and the other occurrence
around lines 835-837), compare the hostUUID argument to the expected UUID and
call t.Fatalf (or t.Fatalf equivalent) if it differs or if the stub is called in
a non-macOS/otherwise-unexpected path so the test fails immediately and gives a
clear diagnostic instead of silently recording the call.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bbb56a11-5fc3-4001-b116-c9656654bf8a

📥 Commits

Reviewing files that changed from the base of the PR and between 9715ee9 and 079b837.

📒 Files selected for processing (11)
  • cmd/fleetctl/fleetctl/testing_utils/testing_utils.go
  • server/datastore/mysql/apple_mdm.go
  • server/datastore/mysql/apple_mdm_test.go
  • server/datastore/mysql/hosts.go
  • server/datastore/mysql/labels.go
  • server/fleet/datastore.go
  • server/fleet/hosts.go
  • server/mock/datastore_mock.go
  • server/service/apple_mdm_test.go
  • server/service/hosts.go
  • server/service/hosts_test.go

mostlikelee and others added 2 commits March 17, 2026 08:47
Match the pattern used by sqlJoinMDMAppleProfilesStatus() where NULL
status is treated as pending. This ensures hosts in the retry state
(status cleared to NULL after failed enqueue) are correctly counted
as pending in the OS settings summary.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When ClearRecoveryLockPendingStatus sets status to NULL (retry state),
the API now returns "pending" instead of null. This ensures the frontend
displays the recovery lock row in the OS settings table for hosts in
retry state, matching the behavior of the summary counts which already
treat NULL as pending.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@mostlikelee mostlikelee marked this pull request as ready for review March 17, 2026 17:02
@mostlikelee mostlikelee requested a review from a team as a code owner March 17, 2026 17:02
Copilot AI review requested due to automatic review settings March 17, 2026 17:02
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds Recovery Lock password delivery status to host details for macOS devices (MDM-enabled), and incorporates that status into the existing OS Settings/macOS Settings status aggregation used by filtering and summaries.

Changes:

  • Extend HostMDMOSSettings with a recovery_lock_password status+detail payload and populate it in getHostDetails for macOS hosts.
  • Add GetHostRecoveryLockPasswordStatus to the datastore interface + MySQL implementation, and include recovery lock status in the SQL used to derive Apple OS Settings/macOS Settings status.
  • Update mocks and add service/datastore tests covering the new status behavior.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
server/service/hosts.go Populate recovery lock password status in host details for macOS hosts.
server/fleet/hosts.go Add RecoveryLockPassword to HostMDMOSSettings and define the status payload struct.
server/fleet/datastore.go Extend datastore interface with GetHostRecoveryLockPasswordStatus.
server/datastore/mysql/apple_mdm.go Implement status fetch + incorporate recovery lock into Apple status SQL and joins.
server/datastore/mysql/hosts.go Add recovery lock join when OS Settings/macOS Settings filters are active.
server/datastore/mysql/labels.go Add recovery lock join when OS Settings/macOS Settings filters are active for label queries.
server/mock/datastore_mock.go Add mock plumbing for GetHostRecoveryLockPasswordStatus.
server/service/hosts_test.go Add/adjust service tests and mocks for host details recovery lock status behavior.
server/service/apple_mdm_test.go Add required mock stub for new datastore method in existing host details test.
server/datastore/mysql/apple_mdm_test.go Add MySQL datastore test coverage for GetHostRecoveryLockPasswordStatus.
cmd/fleetctl/fleetctl/testing_utils/testing_utils.go Stub new datastore method in fleetctl server test helper.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +3657 to +3670
-- recovery lock statuses grouped by host uuid
-- NULL status is treated as pending (retry state after failed enqueue)
SELECT
host_uuid,
MAX(IF(status IS NULL OR status = ` + pending + `, 1, 0)) AS rl_pending,
MAX(IF(status = ` + failed + `, 1, 0)) AS rl_failed,
MAX(IF(status = ` + verifying + `, 1, 0)) AS rl_verifying,
MAX(IF(status = ` + verified + `, 1, 0)) AS rl_verified
FROM
host_recovery_key_passwords
WHERE
deleted = 0
GROUP BY
host_uuid) hrlp ON h.uuid = hrlp.host_uuid
Copy link
Member

@getvictor getvictor left a comment

Choose a reason for hiding this comment

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

Looks good

host.MDM.PopulateOSSettingsAndMacOSSettings(profs, mobileconfig.FleetFileVaultPayloadIdentifier)

// populate recovery lock password status for macOS hosts
if host.Platform == "darwin" {
Copy link
Member

Choose a reason for hiding this comment

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

Nit. Isn't there a constant for this?

@mostlikelee mostlikelee merged commit e28cc2f into main Mar 17, 2026
57 checks passed
@mostlikelee mostlikelee deleted the 40657-status branch March 17, 2026 21:15
mostlikelee added a commit that referenced this pull request Mar 18, 2026
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.

Set password: Host details status

4 participants