Skip to content

Intune User History PR Review

Ed Mozley edited this page Nov 14, 2026 · 1 revision

Every primary user a device has had, and assets that follow it - PR review

PR #338 by vsc55 Β· Closes #335 Β· Follows #334 (review) Β· Verdict: merge, with fixes Β· 5.3.0

The Intune sync overwrote each device's primary user, and Assign assets to their primary user only ever fills a gap. So once an asset had a holder, a laptop handed on in Intune was neither recorded nor followed: Intune said user 1, then 2, then 3; FreeITSM still said user 1, with no trace of 2 or 3. vsc55's design keeps the whole history, can move an asset on to its device's new primary user - but only a holder Intune put there itself - and lists the assets where Intune and FreeITSM disagree. User pages: Assets, Importing people from Entra ID, System β†’ Maintenance. Internals: Asset reconciliation - Developer Guide Β§6c.

What was checked

Question Result
Is a change recorded before the device row is overwritten? Yes - intuneRecordUserChange() is called from intuneUpsertDevice() and compares with the last history row, so a device seen with the same user writes nothing
Is the person matched the same way as everywhere else? Yes - by Entra object id against user_sso_identities.source_ref of an OIDC source, never by name or email
Can "Follow" move a holder somebody chose? No - only an assignment assetAssignedByIntuneSql() says Intune made: assigned_source = 'intune', or, for a row from before the column, no analyst and Intune's own custody note
Can a request name the source of an assignment? Not after the merge - AssetAssignmentSource::resolve() honours only the enum, never a string (fix 1)
The rules a move must pass Exactly one holder, put there by Intune; the new person current (not a leaver) and in the asset's company; the asset's devices agree; the asset not retired
Is a move an ordinary handover? Yes - AssetsService::unassignUser() then assignUser() as ActorContext::system('Intune'), in one transaction per asset: custody trail, asset history and asset workflows all see it
Before Database Verification? Nothing is recorded and nothing moves; nothing fails (fix 2)
The asset merge Moves the history rows too (tests/asset-merge.php checks every asset reference)

On the test install: tests/intune-user-history.php 27 checks (20 in the PR as submitted), always rolled back; vsc55 also reported tests/intune-primary-user.php 13/13, tests/asset-merge.php 26/26, tests/system-maintenance.php 27/27 and the System search suite 358/358.

What was changed on merge

  1. An assignment's source comes only from code that names it. AssetAssignmentSource::resolve() accepted a string as well as the enum. The assign endpoints and the REST API hand their request body to AssetsService, so a body saying "source": "intune" could have made a hand-made assignment one that Follow changes of primary user may move. It now takes only the enum; anything else falls back to the actor's own source (TRAP: comment on it).
  2. Nothing moves before Database Verification. intuneFollowPrimaryUsers() returns at once until users_assets.assigned_source exists - without the column there is no telling an Intune holder from a hand-made one, and its query would fail.
  3. The asset's Intune tab checks the asset's company like its neighbours on the asset page (get_asset_users.php).
  4. Assets whose Intune user differs lists one row per asset, as its count does - an asset with two linked devices was listed twice. Its empty state uses the --success-border theme colour.
  5. Tests: tests/intune-user-history.php 19 β†’ 27 checks.
  6. Changelog ids renumbered to #2928 (the feature) and #2929 (the merge fixes) - the PR's #2925 had been taken on main since.
  7. Translations of the new strings into the eight maintained languages; this write-up, the user pages, the developer guide, a Feature Bingo card and vsc55's entry on the Contributors page.

Decided

  • Follow changes of primary user is off by default, on top of Assign assets to their primary user - it moves people's custody records, so an install chooses it (Ed, 2026-11-14).
  • Only a holder Intune put there is ever moved. A holder chosen in FreeITSM, or set through the API, is never moved; the change is recorded, the asset says the two disagree, and a person decides (Ed, 2026-11-14).

Worth knowing

  • Where an assignment came from is now on every users_assets row (assigned_source: analyst, intune, api, system). Rows from before the column stay NULL, except Intune's own, which Database Verification fills in as intune by their custody note (assetAssignmentSourceBackfill()). A NULL holder is never moved.
  • History starts at the first sync after the upgrade. The first row for each device is its current primary user, marked First seen with this user; changes before 5.3.0 were never kept anywhere and cannot be recovered.
  • An Entra import follows changes too, as #334 made it assign - whichever of the two syncs runs first.
  • The disagreement list is every company's, because System β†’ Maintenance is administrators'.

FreeITSM

Getting Started

Modules

Multi-tenancy (planned)

Responses to feedback

Blue sky thinking

Bugs resolved

Pull requests

Links

Clone this wiki locally