4. Smoke test
Owner: IT
Pick one user with a device in the pilot device group, install the agent on their device, and confirm it reaches the backend cleanly before scoping to the wider fleet.
Pick the test user
Section titled “Pick the test user”The user should have a device already enrolled in Intune and sitting in the pilot device group from Steps 2 and 3. Note the device serial number; you’ll use it when verifying captures arrived at the backend.
The test user must be signed into a session backed by an Entra-joined or Hybrid-joined device, since the agent acquires its Entra token through WAM against the device’s Primary Refresh Token. The tenant must also have granted admin consent for the Arbium app reg (Step 1).
Trigger the install
Section titled “Trigger the install”The policy and MSI will install on the next MDM check-in (~15 minutes). To skip the wait, open Company Portal on the device and choose “Sync this device” — or from Intune: Devices > <device> > Sync.
Verify on the device
Section titled “Verify on the device”# Process checkGet-Process -Name "Roots"
# Version(Get-Item "C:\Program Files\Roots\Roots.exe").VersionInfo.FileVersion
# Config deliveredTest-Path 'C:\ProgramData\Roots\config.json'Get-Content 'C:\ProgramData\Roots\config.json' | ConvertFrom-JsonVerify the JSON output matches what you set in Step 2 (correct endpoint, tenant, client ID, scope).
The Windows agent sends telemetry to Sentry (when SentryDsn is configured). In the Sentry Logs UI, filter by the device’s release (e.g. release:roots-win@0.1.15.0) and look for:
status.type: ready— the agent loaded its config and is running.status.type: uploadwithstatus.inserted/status.assigned— captures are being uploaded to ChainDB.
If you see no Roots process, the per-user logon-triggered scheduled task probably hasn’t fired yet. The MSI registers an Active Setup stub that runs in each user’s context on their next interactive sign-in — if the test user was already signed in when Intune delivered the package, the stub will not have run yet. Sign them out and back in (or, for a hands-on smoke test only, run & 'C:\Program Files\Roots\register-task.ps1' once as that user) to create the task and start the agent.
Verify on the backend
Section titled “Verify on the backend”These queries run against the deployed ChainDB Postgres. Cloud Ops can run them and confirm; IT does not need direct database access.
-- The user identity was provisioned on first captureSELECT user_id, email, last_seen_atFROM public.auth_identitiesWHERE email = '<test user UPN>';
-- Captures are landing for that userSELECT id, app_name, window_key, to_timestamp(created_at / 1000.0) AS created_atFROM public.capturesWHERE user_id = ( SELECT user_id FROM public.auth_identities WHERE email = '<test user UPN>')ORDER BY created_at DESCLIMIT 10;Healthy state:
- A row in
public.auth_identitiesfor the test UPN,last_seen_atupdated within the last few minutes. - Rows arriving in
public.capturesevery minute or two,created_atclose to now (the column is a Unix-millis bigint).
Confirm Sentry isn’t flagging errors from the device’s host.
If something is off
Section titled “If something is off”-
Test-Path 'C:\ProgramData\Roots\config.json'returns False — the platform script from Step 2 hasn’t run yet. Force a sync; if it still doesn’t appear, checkDevices > Scripts and remediations > Platform scripts > Roots windows - write config.json > Device statusfor errors. -
MsalUiRequiredException/WAM cannot acquire a Roots token silently— the device or user is not Entra-joined / Hybrid-joined, so WAM has no Primary Refresh Token to mint against. Confirm withdsregcmd /statuson the device thatAzureAdJoined : YESandAzureAdPrt : YES. -
MsalServiceException: WAM_provider_error_... / IncorrectConfiguration— one of three Entra app-reg knobs is missing. The MSAL message text points only at “invalid redirect URI” but the same error fires for all three. Verify each in the Entra admin center (App registrations > <your app> > Authentication):- Redirect URI
ms-appx-web://microsoft.aad.brokerplugin/<client-id>exists under the Mobile and desktop applications card (not “Web”). - Advanced settings → Allow public client flows is Yes.
- API permissions → Grant admin consent for
has been clicked (status column green checks, not yellow warnings). See Step 1 for the canonical setup.
- Redirect URI
-
Upload rejected by ChainDB: ...(server-side rejection) — the agent acquired a token but the backend’s OIDC verifier rejected it. Almost always one of: the backendOIDC_ISSUER_URL/OIDC_AUDIENCEdoesn’t match the values from Step 1, orrequestedAccessTokenVersionis not2in the Entra app manifest (which would make Entra mint v1 tokens with the wrong issuer + audience format). Re-check the values you sent to Cloud Ops. -
type=readyshows in Sentry but no follow-uptype=upload— the device may not be able to reach the capture or privacy-rules endpoint, or capture may be paused by the customer control. The agent holds captures until it has current or cached privacy rules. Confirm egress tohttps://arbium.<customer-domain>/functions/v1/health, then ask Cloud Ops to check the customer capture switch and the/functions/v1/blocklistendpoint. -
No row in
public.auth_identities— same root cause as above, or the Entra tokens are minting against a different tenant than the one Cloud Ops seeded.
Admin UI (only if enabled)
Section titled “Admin UI (only if enabled)”Skip this section if Cloud Ops did not enable the fleet console in this deployment.
The smoke test for the admin UI is just: sign in, confirm the dashboard loads, confirm a non-admin lands on /forbidden. There is no per-device setup — admins use a browser.
- Pick two test users in the customer tenant. One who is a member of a SCIM-provisioned Admins security group from Step 1, and one who is not. Both must exist in the tenant where the
Arbium Adminapp registration lives, and provisioning must have synced the admin user and Admins group before the admin should be allowed. - Open the admin URL Cloud Ops sent you (e.g.
https://arbium.<customer-domain>/admin) in a private browser window. The page should redirect to Microsoft sign-in. - Sign in as the admin. After consent, you land on the dashboard, which shows enrolled users (from Microsoft Graph), enrolled devices (from Intune Graph), and live capture counts (from the Arbium backend).
- Sign in as the non-admin (different private window). You should land on
/forbidden, not the dashboard.
If anything is off, match the symptom and report the specifics to Cloud Ops — they have the matching server-side diagnoses in their Step 4:
AADSTS50011“reply URL does not match” on the Microsoft sign-in page — the Redirect URI you registered does not byte-matchhttps://arbium.<customer-domain>/admin/api/auth/callback. Re-check Step 1’s admin-UI section 1 and confirm with Cloud Ops whatingress.hostresolved to.AADSTS65001consent_required— admin consent was not granted on the admin Entra app’s API permissions. Go back to Step 1’s admin-UI section 4 and click Grant admin consent for<tenant>.invalid_client— the client secret expired or the wrong client ID landed in the Helm values. Mint a new secret (Step 1’s admin-UI section 3), forward the value to Cloud Ops.- Sign-in succeeds, every admin lands on
/forbidden— either SCIM provisioning has not synced the user/group yet, the user is not actually in a provisioned Admins security group, or Cloud Ops loaded the wrong Object ID intoscim.scimAdminGroupIds. Confirm provisioning status and group membership in Entra, then ask Cloud Ops to read backSCIM_ADMIN_GROUP_IDSfrom the running pod. - Sign-in succeeds, dashboard shows
Failed to load users/devices— same root cause asconsent_required. The two*.Alldelegated scopes need admin consent. Re-check Step 1’s admin-UI section 4.
When the smoke test is green
Section titled “When the smoke test is green”The pipeline is proven end-to-end for one user: policy and MSI installed, agent acquired an Entra token, captures landing in the backend, UPN attribution correct. If the Admin UI was enabled, an admin can sign in and a non-admin is correctly blocked.
Expand the device group scope in Intune from the pilot group to the broader rollout group. Same policy, same MSI, same config — they just apply to more devices. Watch the public.captures table for a few days to confirm the wider rollout stays healthy.