Reported by semotech in #bugs (Discord, message 1534625902045167667).
Report (PII-redacted):
Reporting a small UI bug in Operations / Device Groups - Setting up a Dynamic Group Type for Intel Macs. Created condition for "Architecture" to match "X64" and even pressed "Refresh" but count just shows 0! Same with "X86" even tho there are machines enrolled that match all 3 criteria. Only option that does work and shows a machines list is "Arm64"!
Filed automatically by @breeze-discord triage. Verify and add labels/repro as needed.
Triage analysis
The reported behavior is real: dynamic-group filtering on the Architecture field is broken for x64/x86 because of a naming mismatch between what agents report and what the dynamic-group enum expects. The Go agent reports runtime.GOARCH verbatim as the device's architecture (agent/internal/collectors/hardware.go:37-48), which yields amd64 on Intel/x64 machines and arm64 on Apple Silicon/ARM machines — Go never emits x64 or x86. The enrollment handler stores that raw value into devices.architecture with no translation (apps/api/src/routes/agents/enrollment.ts:646, 689). Meanwhile the dynamic-group filter field definition advertises enum values x64, x86, arm64 (apps/api/src/services/filterEngine.ts:90) and the filter engine resolves the architecture field straight to the raw devices.architecture column with no value mapping (filterEngine.ts:160-170, getColumnForField). So a condition like architecture equals x64 is compared against a column literally containing amd64 and never matches (0 devices), while architecture equals arm64 happens to match by coincidence because Go's arm64 spelling is identical to the enum's. There is an existing helper, normalizeAgentArchitecture (apps/api/src/routes/agents/helpers.ts:187-197), that maps amd64/x86_64/x64 → amd64 and arm64/aarch64 → arm64, but it's only used for agent-binary version matching in heartbeat.ts, not applied when writing/filtering the device's own architecture field. Windows agents likely have the same issue for 32-bit (386 vs enum x86).
Affected code
agent/internal/collectors/hardware.go:32-48 — Agent reports raw runtime.GOARCH (amd64/arm64) as architecture; never emits 'x64' or 'x86'.
apps/api/src/routes/agents/enrollment.ts:634-703 — data.architecture is stored verbatim into devices.architecture on enroll/re-enroll with no normalization to the UI enum values.
apps/api/src/services/filterEngine.ts:90 — Dynamic-group field definition declares enum values x64/x86/arm64, which don't match the stored raw GOARCH strings.
apps/api/src/services/filterEngine.ts:160-170 — getColumnForField maps 'architecture' straight to the devices.architecture column with no value translation before comparison.
apps/api/src/routes/agents/helpers.ts:187-197 — normalizeAgentArchitecture already maps amd64/x86_64/x64 -> amd64 and arm64/aarch64 -> arm64, but is only used for agent-binary pinning, not applied to the device's stored architecture or in the filter engine.
Potential fix
Normalize architecture to the documented enum (x64/x86/arm64, or pick one canonical convention and update docs) either when persisting devices.architecture at enrollment/heartbeat time, or in filterEngine's getColumnForField/applyOperator for the 'architecture' field by mapping amd64<->x64 and 386<->x86 before comparing.
Triage analysis, affected code, and fix sketch above were produced by automated investigation (@breeze-discord). Verify before relying on them.
Reported by semotech in #bugs (Discord, message 1534625902045167667).
Report (PII-redacted):
Reporting a small UI bug in Operations / Device Groups - Setting up a Dynamic Group Type for Intel Macs. Created condition for "Architecture" to match "X64" and even pressed "Refresh" but count just shows 0! Same with "X86" even tho there are machines enrolled that match all 3 criteria. Only option that does work and shows a machines list is "Arm64"!
Filed automatically by @breeze-discord triage. Verify and add labels/repro as needed.
Triage analysis
The reported behavior is real: dynamic-group filtering on the Architecture field is broken for x64/x86 because of a naming mismatch between what agents report and what the dynamic-group enum expects. The Go agent reports
runtime.GOARCHverbatim as the device's architecture (agent/internal/collectors/hardware.go:37-48), which yieldsamd64on Intel/x64 machines andarm64on Apple Silicon/ARM machines — Go never emitsx64orx86. The enrollment handler stores that raw value intodevices.architecturewith no translation (apps/api/src/routes/agents/enrollment.ts:646, 689). Meanwhile the dynamic-group filter field definition advertises enum valuesx64,x86,arm64(apps/api/src/services/filterEngine.ts:90) and the filter engine resolves thearchitecturefield straight to the rawdevices.architecturecolumn with no value mapping (filterEngine.ts:160-170,getColumnForField). So a condition likearchitecture equals x64is compared against a column literally containingamd64and never matches (0 devices), whilearchitecture equals arm64happens to match by coincidence because Go's arm64 spelling is identical to the enum's. There is an existing helper,normalizeAgentArchitecture(apps/api/src/routes/agents/helpers.ts:187-197), that mapsamd64/x86_64/x64→amd64andarm64/aarch64→arm64, but it's only used for agent-binary version matching in heartbeat.ts, not applied when writing/filtering the device's own architecture field. Windows agents likely have the same issue for 32-bit (386vs enumx86).Affected code
agent/internal/collectors/hardware.go:32-48— Agent reports raw runtime.GOARCH (amd64/arm64) as architecture; never emits 'x64' or 'x86'.apps/api/src/routes/agents/enrollment.ts:634-703— data.architecture is stored verbatim into devices.architecture on enroll/re-enroll with no normalization to the UI enum values.apps/api/src/services/filterEngine.ts:90— Dynamic-group field definition declares enum values x64/x86/arm64, which don't match the stored raw GOARCH strings.apps/api/src/services/filterEngine.ts:160-170— getColumnForField maps 'architecture' straight to the devices.architecture column with no value translation before comparison.apps/api/src/routes/agents/helpers.ts:187-197— normalizeAgentArchitecture already maps amd64/x86_64/x64 -> amd64 and arm64/aarch64 -> arm64, but is only used for agent-binary pinning, not applied to the device's stored architecture or in the filter engine.Potential fix
Normalize architecture to the documented enum (x64/x86/arm64, or pick one canonical convention and update docs) either when persisting devices.architecture at enrollment/heartbeat time, or in filterEngine's getColumnForField/applyOperator for the 'architecture' field by mapping amd64<->x64 and 386<->x86 before comparing.
Triage analysis, affected code, and fix sketch above were produced by automated investigation (@breeze-discord). Verify before relying on them.