diff --git a/apps/app/src/app/(app)/[orgId]/people/all/components/MemberRow.test.tsx b/apps/app/src/app/(app)/[orgId]/people/all/components/MemberRow.test.tsx
index ea25585a7..b0a6c75f0 100644
--- a/apps/app/src/app/(app)/[orgId]/people/all/components/MemberRow.test.tsx
+++ b/apps/app/src/app/(app)/[orgId]/people/all/components/MemberRow.test.tsx
@@ -90,9 +90,11 @@ describe('MemberRow device status', () => {
expect(screen.getByText('Not Installed').className).toContain('text-muted-foreground');
});
- it('shows "Not Installed" by default when deviceStatus is omitted', () => {
+ it('shows dash when deviceStatus is omitted (no compliance obligation)', () => {
renderMemberRow();
- expect(screen.getByText('Not Installed')).toBeInTheDocument();
+ expect(screen.queryByText('Not Installed')).not.toBeInTheDocument();
+ expect(screen.queryByText('Compliant')).not.toBeInTheDocument();
+ expect(screen.queryByText('Non-Compliant')).not.toBeInTheDocument();
});
it('shows "Compliant" with green dot when deviceStatus is compliant', () => {
@@ -177,4 +179,58 @@ describe('MemberRow device status', () => {
const redDot = c3.querySelector('.bg-red-400');
expect(redDot).toBeInTheDocument();
});
+
+ it('does not show device status for member without compliance obligation (e.g. auditor)', () => {
+ const auditorMember = {
+ ...baseMember,
+ role: 'auditor',
+ } as unknown as MemberWithUser;
+
+ render(
+
,
+ );
+
+ expect(screen.queryByText('Not Installed')).not.toBeInTheDocument();
+ expect(screen.queryByText('Compliant')).not.toBeInTheDocument();
+ expect(screen.queryByText('Non-Compliant')).not.toBeInTheDocument();
+ });
+
+ it('still shows device status for member with compliance obligation', () => {
+ const employeeMember = {
+ ...baseMember,
+ role: 'employee',
+ } as unknown as MemberWithUser;
+
+ render(
+ ,
+ );
+
+ expect(screen.getByText('Compliant')).toBeInTheDocument();
+ });
});
diff --git a/apps/app/src/app/(app)/[orgId]/people/all/components/MemberRow.tsx b/apps/app/src/app/(app)/[orgId]/people/all/components/MemberRow.tsx
index 72fef1ac1..655b5b6ae 100644
--- a/apps/app/src/app/(app)/[orgId]/people/all/components/MemberRow.tsx
+++ b/apps/app/src/app/(app)/[orgId]/people/all/components/MemberRow.tsx
@@ -95,7 +95,7 @@ export function MemberRow({
isCurrentUserOwner,
customRoles = [],
taskCompletion,
- deviceStatus = 'not-installed',
+ deviceStatus,
}: MemberRowProps) {
const { orgId } = useParams<{ orgId: string }>();
@@ -233,7 +233,7 @@ export function MemberRow({
{/* DEVICE */}
- {isPlatformAdmin || isDeactivated ? (
+ {isPlatformAdmin || isDeactivated || !deviceStatus ? (
—
@@ -321,7 +321,7 @@ export function MemberRow({
)}
{!isDeactivated &&
- (member.fleetDmLabelId || deviceStatus !== 'not-installed') &&
+ (member.fleetDmLabelId || (deviceStatus && deviceStatus !== 'not-installed')) &&
isCurrentUserOwner && (
{
diff --git a/apps/app/src/app/(app)/[orgId]/people/all/components/TeamMembersClient.tsx b/apps/app/src/app/(app)/[orgId]/people/all/components/TeamMembersClient.tsx
index 64d62ef87..ac9b88e7b 100644
--- a/apps/app/src/app/(app)/[orgId]/people/all/components/TeamMembersClient.tsx
+++ b/apps/app/src/app/(app)/[orgId]/people/all/components/TeamMembersClient.tsx
@@ -470,7 +470,7 @@ export function TeamMembersClient({
isCurrentUserOwner={isCurrentUserOwner}
customRoles={customRoles}
taskCompletion={taskCompletionMap[(item as MemberWithUser).id]}
- deviceStatus={deviceStatusMap[(item as MemberWithUser).id] ?? 'not-installed'}
+ deviceStatus={deviceStatusMap[(item as MemberWithUser).id]}
/>
) : (
= {};
+ const complianceMemberIds = new Set(employees.map((m) => m.id));
+
+ // Default all compliance members to "not-installed" — device data below overrides
+ for (const id of complianceMemberIds) {
+ deviceStatusMap[id] = 'not-installed';
+ }
// Device-agent devices: compliant only if ALL of a member's devices pass
const agentComplianceByMember = new Map();
for (const d of agentDevices) {
- if (!d.memberId) continue;
+ if (!d.memberId || !complianceMemberIds.has(d.memberId)) continue;
const prev = agentComplianceByMember.get(d.memberId);
agentComplianceByMember.set(d.memberId, (prev ?? true) && d.isCompliant);
}
@@ -173,12 +183,13 @@ export default async function PeoplePage({ params }: { params: Promise<{ orgId:
// Fleet-only devices: use the same merged policy data the chart uses
// (Fleet API automated checks + DB manual overrides, already combined by getFleetHosts)
for (const host of filteredFleetDevices) {
- if (!host.member_id) continue;
+ if (!host.member_id || !complianceMemberIds.has(host.member_id)) continue;
// If already set by device-agent, skip (agent takes priority)
if (agentComplianceByMember.has(host.member_id)) continue;
const isCompliant = host.policies.every((p) => p.response === 'pass');
- // If multiple fleet devices for same member, non-compliant if ANY device fails
- if (!isCompliant || !deviceStatusMap[host.member_id]) {
+ // If multiple fleet devices for same member, non-compliant if ANY device fails.
+ // Once non-compliant, a later compliant device cannot upgrade it back.
+ if (deviceStatusMap[host.member_id] !== 'non-compliant') {
deviceStatusMap[host.member_id] = isCompliant ? 'compliant' : 'non-compliant';
}
}