Watch
1
0
Fork
You've already forked RedFlag
0
RedFlag/RAF/scanners/06-pacman-scanner.md
Fimeg ff2f30f47a v0.2.9.3: device classification + ARM support — Pixel 3 lands
DEVICE-002: ARM machine-ID fallback — device-tree model + /etc/machine-id
combo, then /proc/cpuinfo Serial (all-zero rejected), before the weak
hostname fallback. Hardware-bound IDs on DMI-less devices.

DEVICE-001: agent detects device_type (server/desktop/phone/tablet) from
/sys signals — system battery (scope=Device peripherals excluded, UPS
excluded), DRM connector state, framebuffer min-dimension for phone/tablet
split. Reports device_type/device_model/os_distro in registration and
system-info paths.

SERVER-001: migration 061 — device_type, device_type_manual (operator
override, never agent-written), device_model, os_distro on agents.
effective_device_type computed into every serialized agent.

SERVER-002: PUT /admin/agents/:id/device-type — set/clear override,
enum-validated, journaled.

WEB-001: device-type icons + fleet filter, device model in list, detail
header badge with reclassify dropdown, os_distro surfaced.

INSTALL-003: arm64 install path unblocked — helper (required manifest
component) now cross-built aarch64-unknown-linux-musl via rust-lld in the
server image, signed at boot (helperArches += arm64), listed in the release
manifest. Install template already handled uname -m and pacman.

Plus in-flight: desktop tray wiring, enrollment page polish, CI workflow
updates, RAF session-broker/pacman-scanner docs, native installer scaffold.
2026-07-06 18:21:23 -04:00

2.5 KiB

Pacman Scanner

Arch Linux package manager scanning via pacman-contrib's checkupdates.


Component Details

Property Value
Method checkupdates --color=never
Platform Linux (Arch, Manjaro, EndeavourOS)
Execution time ~5-15 seconds per scan
Output format pkgname oldver -> newver (one per line)
Failure modes pacman-contrib not installed, network timeout, database lock
Root required No (checkupdates uses a private db copy)

Implementation

File: agent/internal/scanner/pacman.go

Detection

func (s *PacmanScanner) IsAvailable() bool {
    // Requires both pacman and checkupdates (from pacman-contrib)
    if _, err := exec.LookPath("checkupdates"); err != nil {
        return false
    }
    _, err := exec.LookPath("pacman")
    return err == nil
}

Scanning

Uses DiscoveryRunner (same as apt/dnf) for sandboxed execution:

func (s *PacmanScanner) Scan() ([]client.UpdateReportItem, error) {
    runner, err := installer.NewDiscoveryRunner("pacman")
    // checkupdates --color=never
    result, err := runner.Run(context.Background(), "--color=never")
    // Parse "pkgname oldver -> newver" lines
}

Output Parsing

checkupdates output format:

fakeroot 1:1.37.2-1 -> 1:1.37.2-2
linux 6.14.6.arch1-1 -> 6.15.1.arch1-1

The current (installed) version is embedded in the output — no secondary query needed (unlike dnf which calls rpm -q).


Sudoers

The agent user needs checkupdates in sudoers. This is an unprivileged discovery command (no mutation). Example:

redflag-agent ALL=(ALL) NOPASSWD: /usr/bin/checkupdates

Known Limitations

  • Requires pacman-contribpacman alone is not sufficient. The checkupdates binary is in the pacman-contrib package, which may not be installed by default.
  • AUR packages not scannedcheckupdates only checks official repos. AUR helpers (yay, paru) have their own update checkers but are not integrated.
  • No dry-run for mutations — pacman's --print flag exists but is not used for hash resolution. Artifact hashing goes through the capability gate path when it lands for pacman.

Cross-References