Skip to content

feat: display activity log on device user page#45678

Open
Piccirello wants to merge 1 commit into
fleetdm:mainfrom
PostHog:tom/host-activity-log
Open

feat: display activity log on device user page#45678
Piccirello wants to merge 1 commit into
fleetdm:mainfrom
PostHog:tom/host-activity-log

Conversation

@Piccirello
Copy link
Copy Markdown

@Piccirello Piccirello commented May 17, 2026

The device user page now display an activity log of past and future events. It does not yet support displaying MDM commands.

Related issue: Partially addresses #22491

Checklist for submitter

If some of the following don't apply, delete the relevant line.

  • Changes file added for user-visible changes in changes/, orbit/changes/ or ee/fleetd-chrome/changes.
    See Changes files for more information.

  • Input data is properly validated, SELECT * is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters.

  • Timeouts are implemented and retries are limited to avoid infinite loops

  • If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes

Testing

Summary by CodeRabbit

  • New Features

    • Activity panel on the My Device page with Past and Upcoming tabs, pagination, and Install Details modal for installed‑software entries.
  • Behavior Changes

    • “Show info” controls hidden for admin‑only activity types on My Device.
    • Upcoming tab disabled for Android hosts.
  • Tests

    • Added unit and integration tests covering device‑authenticated past/upcoming activity endpoints and UI behavior.

Review Change Stack

@Piccirello Piccirello requested review from a team as code owners May 17, 2026 06:07
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 17, 2026

Codecov Report

❌ Patch coverage is 60.84906% with 83 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.78%. Comparing base (ad5bb8a) to head (0cd815d).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...es/hosts/details/DeviceUserPage/DeviceUserPage.tsx 38.20% 52 Missing and 3 partials ⚠️
server/service/devices.go 66.66% 6 Missing and 5 partials ⚠️
server/service/activities.go 82.60% 4 Missing and 4 partials ⚠️
frontend/services/entities/activities.ts 75.00% 4 Missing ⚠️
server/activity/internal/service/service.go 71.42% 1 Missing and 1 partial ⚠️
...nd/pages/hosts/details/cards/Activity/Activity.tsx 0.00% 1 Missing ⚠️
...rds/Activity/PastActivityFeed/PastActivityFeed.tsx 0.00% 1 Missing ⚠️
...vity/UpcomingActivityFeed/UpcomingActivityFeed.tsx 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #45678      +/-   ##
==========================================
+ Coverage   66.75%   66.78%   +0.02%     
==========================================
  Files        2745     2745              
  Lines      219361   219564     +203     
  Branches    10839    10893      +54     
==========================================
+ Hits       146435   146627     +192     
  Misses      59697    59697              
- Partials    13229    13240      +11     
Flag Coverage Δ
backend 68.58% <76.13%> (+<0.01%) ⬆️
backend-activity 86.13% <42.85%> (-0.22%) ⬇️
frontend 55.80% <50.00%> (+0.20%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 17, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds an Activity panel to the My Device page and implements device-authenticated support end-to-end: frontend endpoint builders and client calls, isMyDevicePage prop threading, DeviceUserPage queries and modals, MSW handlers and tests; backend activity API and service extensions for device callers, device HTTP routes, mocks, and unit/integration tests.

Possibly related PRs

  • fleetdm/fleet#38555: Adds core host past-activities read operation extended here for device-auth callers.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: display activity log on device user page' clearly and concisely describes the main change—adding an activity log to the device user page.
Description check ✅ Passed The description covers the main objectives and includes a completed checklist addressing validation, testing, and endpoint compatibility requirements.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

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

🤖 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 `@frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx`:
- Around line 989-990: The pagination handlers currently close over
activityPage; update onNextPage and onPreviousPage to use the functional form of
setActivityPage to avoid stale state and ensure pages never go negative—for
example, call setActivityPage(prev => prev + 1) for the next handler and
setActivityPage(prev => Math.max(0, prev - 1)) for the previous handler; change
the callbacks wired to onNextPage and onPreviousPage in DeviceUserPage to use
these functional updates (identify the setActivityPage state setter and the
onNextPage/onPreviousPage handlers).

In `@server/service/activities.go`:
- Around line 71-81: The device-auth path in ListHostPastActivities silently
overwrites the requested hostID with the host from context; instead, when
svc.authz.IsAuthenticatedWith(...)
(AuthnDeviceToken/AuthnDeviceCertificate/AuthnDeviceURL) and
hostctx.FromContext(ctx) returns h, compare the requested hostID variable to
h.ID and if they differ return an auth/validation error (similar to
ListHostPastActivitiesForDevice) rather than replacing hostID; update the branch
around hostctx.FromContext usage in activities.go to reject mismatches and
return an appropriate fleet.NewAuthRequiredError or authorization error.
🪄 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: a80de226-cd2a-425c-8404-b5935b3fed5e

📥 Commits

Reviewing files that changed from the base of the PR and between ad5bb8a and 04388a0.

📒 Files selected for processing (25)
  • changes/my-device-activity-panel
  • frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tests.tsx
  • frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx
  • frontend/pages/hosts/details/cards/Activity/Activity.tsx
  • frontend/pages/hosts/details/cards/Activity/ActivityConfig.tsx
  • frontend/pages/hosts/details/cards/Activity/ActivityItems/FailedEnrollmentProfileRenewalActivityItem/FailedEnrollmentProfileRenewalActivityItem.tsx
  • frontend/pages/hosts/details/cards/Activity/ActivityItems/RanScriptActivityItem/RanScriptActivityItem.tsx
  • frontend/pages/hosts/details/cards/Activity/PastActivityFeed/PastActivityFeed.tsx
  • frontend/pages/hosts/details/cards/Activity/UpcomingActivityFeed/UpcomingActivityFeed.tsx
  • frontend/services/entities/activities.ts
  • frontend/test/handlers/device-handler.ts
  • frontend/utilities/endpoints.ts
  • server/activity/api/list_host_past_activities.go
  • server/activity/api/service.go
  • server/activity/internal/service/handler_test.go
  • server/activity/internal/service/service.go
  • server/fleet/activities.go
  • server/fleet/service.go
  • server/mock/activity_mock.go
  • server/mock/service/service_mock.go
  • server/service/activities.go
  • server/service/devices.go
  • server/service/devices_test.go
  • server/service/handler.go
  • server/service/integration_desktop_test.go

Comment on lines +989 to +990
onNextPage={() => setActivityPage(activityPage + 1)}
onPreviousPage={() => setActivityPage(activityPage - 1)}
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Harden activity pagination updates against stale state and negative pages.

Line 989 and Line 990 should use functional updates, and previous-page should clamp at 0 to avoid invalid page values.

Suggested fix
-                  onNextPage={() => setActivityPage(activityPage + 1)}
-                  onPreviousPage={() => setActivityPage(activityPage - 1)}
+                  onNextPage={() => setActivityPage((prev) => prev + 1)}
+                  onPreviousPage={() =>
+                    setActivityPage((prev) => Math.max(0, prev - 1))
+                  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onNextPage={() => setActivityPage(activityPage + 1)}
onPreviousPage={() => setActivityPage(activityPage - 1)}
onNextPage={() => setActivityPage((prev) => prev + 1)}
onPreviousPage={() =>
setActivityPage((prev) => Math.max(0, prev - 1))
}
🤖 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 `@frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx` around lines
989 - 990, The pagination handlers currently close over activityPage; update
onNextPage and onPreviousPage to use the functional form of setActivityPage to
avoid stale state and ensure pages never go negative—for example, call
setActivityPage(prev => prev + 1) for the next handler and setActivityPage(prev
=> Math.max(0, prev - 1)) for the previous handler; change the callbacks wired
to onNextPage and onPreviousPage in DeviceUserPage to use these functional
updates (identify the setActivityPage state setter and the
onNextPage/onPreviousPage handlers).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Uses same logic as existing HostDetailsPage. Also the handlers are inline arrow functions recreated on every render, so they always close over the current activityPage.

Comment thread server/service/activities.go Outdated
@Piccirello Piccirello force-pushed the tom/host-activity-log branch 3 times, most recently from 19f10a2 to 4c12fdf Compare May 17, 2026 16:29
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: 2

🤖 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 `@frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx`:
- Around line 297-307: The device-scoped react-query calls (query key
["device-past-activities", deviceAuthToken, activityPage] and the other similar
device-scoped query around lines 320-330 that call
activitiesAPI.getDeviceHostPastActivities) must not use keepPreviousData: true
because that causes the previous device's feed to flash when deviceAuthToken
changes; override DEFAULT_USE_QUERY_OPTIONS and set keepPreviousData: false for
these queries (or remove the flag) so the cache doesn't persist another device's
activities across token changes, and apply the same change to the other
device-scoped query that uses deviceAuthToken.
- Around line 334-336: refetchExtensions currently only calls
refetchDeviceCertificates, leaving the Activity card stale; update the function
so that when deviceCertificates is truthy it calls both
refetchDeviceCertificates() and requestRefetch(), and add requestRefetch to the
useCallback dependency array so the activity data is refreshed alongside
certificates after self-service actions.
🪄 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: 9e2dfaed-4caf-4dd5-903e-fa0386f8c74e

📥 Commits

Reviewing files that changed from the base of the PR and between 19f10a2 and 4c12fdf.

📒 Files selected for processing (25)
  • changes/my-device-activity-panel
  • frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tests.tsx
  • frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx
  • frontend/pages/hosts/details/cards/Activity/Activity.tsx
  • frontend/pages/hosts/details/cards/Activity/ActivityConfig.tsx
  • frontend/pages/hosts/details/cards/Activity/ActivityItems/FailedEnrollmentProfileRenewalActivityItem/FailedEnrollmentProfileRenewalActivityItem.tsx
  • frontend/pages/hosts/details/cards/Activity/ActivityItems/RanScriptActivityItem/RanScriptActivityItem.tsx
  • frontend/pages/hosts/details/cards/Activity/PastActivityFeed/PastActivityFeed.tsx
  • frontend/pages/hosts/details/cards/Activity/UpcomingActivityFeed/UpcomingActivityFeed.tsx
  • frontend/services/entities/activities.ts
  • frontend/test/handlers/device-handler.ts
  • frontend/utilities/endpoints.ts
  • server/activity/api/list_host_past_activities.go
  • server/activity/api/service.go
  • server/activity/internal/service/handler_test.go
  • server/activity/internal/service/service.go
  • server/fleet/activities.go
  • server/fleet/service.go
  • server/mock/activity_mock.go
  • server/mock/service/service_mock.go
  • server/service/activities.go
  • server/service/devices.go
  • server/service/devices_test.go
  • server/service/handler.go
  • server/service/integration_desktop_test.go
✅ Files skipped from review due to trivial changes (2)
  • changes/my-device-activity-panel
  • server/mock/service/service_mock.go
🚧 Files skipped from review as they are similar to previous changes (20)
  • frontend/pages/hosts/details/cards/Activity/PastActivityFeed/PastActivityFeed.tsx
  • server/activity/api/service.go
  • frontend/utilities/endpoints.ts
  • frontend/pages/hosts/details/cards/Activity/ActivityConfig.tsx
  • frontend/pages/hosts/details/cards/Activity/UpcomingActivityFeed/UpcomingActivityFeed.tsx
  • frontend/pages/hosts/details/cards/Activity/ActivityItems/FailedEnrollmentProfileRenewalActivityItem/FailedEnrollmentProfileRenewalActivityItem.tsx
  • frontend/services/entities/activities.ts
  • frontend/pages/hosts/details/cards/Activity/ActivityItems/RanScriptActivityItem/RanScriptActivityItem.tsx
  • server/service/handler.go
  • frontend/pages/hosts/details/cards/Activity/Activity.tsx
  • server/activity/api/list_host_past_activities.go
  • server/service/devices.go
  • server/fleet/service.go
  • server/service/integration_desktop_test.go
  • frontend/test/handlers/device-handler.ts
  • server/fleet/activities.go
  • server/activity/internal/service/service.go
  • server/service/devices_test.go
  • server/activity/internal/service/handler_test.go
  • server/service/activities.go

Comment on lines +297 to +307
["device-past-activities", deviceAuthToken, activityPage],
() =>
activitiesAPI.getDeviceHostPastActivities(
deviceAuthToken,
activityPage,
DEVICE_ACTIVITY_PAGE_SIZE
),
{
...DEFAULT_USE_QUERY_OPTIONS,
enabled: !!deviceAuthToken,
keepPreviousData: true,
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't retain another device's activity feed across token changes.

These device-scoped queries use keepPreviousData: true, so if device_auth_token changes without a remount, the new page can briefly render the previous device's activities/counts until the new requests finish. On a My Device route, that's a host-isolation leak.

Possible safe fix
     {
       ...DEFAULT_USE_QUERY_OPTIONS,
       enabled: !!deviceAuthToken,
-      keepPreviousData: true,
+      keepPreviousData: false,
     }
   );
@@
     {
       ...DEFAULT_USE_QUERY_OPTIONS,
       enabled: !!deviceAuthToken,
-      keepPreviousData: true,
+      keepPreviousData: false,
     }
   );

Also applies to: 320-330

🤖 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 `@frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx` around lines
297 - 307, The device-scoped react-query calls (query key
["device-past-activities", deviceAuthToken, activityPage] and the other similar
device-scoped query around lines 320-330 that call
activitiesAPI.getDeviceHostPastActivities) must not use keepPreviousData: true
because that causes the previous device's feed to flash when deviceAuthToken
changes; override DEFAULT_USE_QUERY_OPTIONS and set keepPreviousData: false for
these queries (or remove the flag) so the cache doesn't persist another device's
activities across token changes, and apply the same change to the other
device-scoped query that uses deviceAuthToken.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

All other queries on this page have the same property.

Comment thread frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx Outdated
@Piccirello Piccirello force-pushed the tom/host-activity-log branch from 4c12fdf to 8a2c81d Compare May 17, 2026 16:42
The device user page now display an activity log of past and future events. It does not yet support displaying MDM commands.
@Piccirello Piccirello force-pushed the tom/host-activity-log branch from 8a2c81d to 0cd815d Compare May 17, 2026 16:54
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