Skip to content

feat(scanners): coverage gaps — 57 sub-tasks, 16 scanners, 492 tests#3

Merged
wgordon17 merged 14 commits intogordon-code:mainfrom
wgordon17:feat/scanner-coverage-gaps
Mar 13, 2026
Merged

feat(scanners): coverage gaps — 57 sub-tasks, 16 scanners, 492 tests#3
wgordon17 merged 14 commits intogordon-code:mainfrom
wgordon17:feat/scanner-coverage-gaps

Conversation

@wgordon17
Copy link
Member

Summary

  • Implement all 57 sub-tasks from the scanner coverage gaps plan across 16 scanners
  • Add 17 new Pydantic model classes, modify 19 existing models
  • Create new library_audit scanner for ~/Library and /Library directory auditing
  • Enhance all 15 existing scanners with expanded discovery capabilities
  • Add 273 new tests (219 → 492), all passing with ruff and pyright clean

Implement all scanner coverage gaps from the comprehensive plan:

- 17 new model classes, 19 modified models
- New library_audit scanner (~/Library + /Library audit)
- Enhanced all 15 existing scanners with expanded discovery
- 273 new tests (219→492), all passing

Key additions per scanner:
- preferences: SyncedPreferences, cfprefsd-only domains, source tracking
- dotfiles: discovery mode, XDG support, sensitive paths, manager detection
- shell: conf.d, completions, source following, frameworks, eval detection
- app_config: Containers, recursive os.walk, volume safeguards
- applications: PATH binaries, dev tool versions, Xcode/CLT
- launch_agents: raw plist capture, sensitive env redaction, typed fields
- homebrew: services, pinned formulae, prefix
- cron: schedule parsing with trigger types, env vars
- network: IPv6, VPN, SOCKS/FTP proxy, WiFi list, locations
- security: firewall rules, Touch ID sudo, custom certificates
- system: macOS version, hardware, Time Machine, sleep, printers, etc.
- display: Night Shift, refresh rate, color profile, True Tone
- audio: full volume settings parsing
- fonts: font collections
- library_audit: directory audit, content capture, workflow/keybinding handlers
- Rename _convert_datetimes → convert_datetimes (used cross-module)
- Use brew services list --json instead of fragile text parsing
- Tighten _classify_binary_source path matching to avoid false positives
- Remove unused brew_names parameter from _get_path_binaries
- Consolidate dirnames pruning in library_audit _capture_uncovered_dir
- Remove unused _SYSTEM_COVERED_DIRS constant
- Clarify Night Shift UUID-keyed plist fallback with comment
- Fix extra blank line in preferences.py
@wgordon17 wgordon17 force-pushed the feat/scanner-coverage-gaps branch from f07302b to 3dc330c Compare March 11, 2026 18:50
Implement 4 new scanners detecting non-macOS-native package management:

- nix_state: Nix installation, profiles, nix-darwin, home-manager,
  channels, flakes, registries, config, devbox/devenv/direnv
- version_managers: asdf, mise, nvm, pyenv, rbenv, jenv, sdkman
- package_managers: MacPorts, Conda/Mamba
- containers: Docker, Podman, Colima, OrbStack, Lima

Also extends existing scanners:
- system_scanner: Rosetta 2, System Extensions, iCloud, MDM detection
- applications: 9 new BinarySource values + 19 path patterns

New models in package_managers.py (27 models). SystemConfig extended
with rosetta_installed, system_extensions, icloud, mdm_enrolled.
SystemState wired with 4 new domain fields. 19 total scanners.

242 new tests (734 total), ruff clean, pyright 0 errors.
@wgordon17 wgordon17 force-pushed the feat/scanner-coverage-gaps branch from 3dc330c to fb93925 Compare March 11, 2026 18:55
Crashes fixed:
- preferences: catch AttributeError from malformed plist dates
- library_audit: guard _redact_sensitive_keys with isinstance(dict)
- _utils: handle plistlib.UID in convert_datetimes, fix return type

Wrong data fixed:
- display: retina detection via spdisplays_pixelresolution + display_type
- display: parse refresh_rate from resolution string as fallback
- system: system_extensions parser no longer skips *-prefixed data lines
- system: parse [activated enabled] bracket state format
- homebrew: parse stdout even on non-zero exit (broken cask refs)
- shell: extract only path arg from fish_add_path, skip flags
- containers: validate podman --version output isnt Docker shim

Silently missing data fixed:
- system: NTP fallback via launchctl + /etc/ntp.conf
- system: sleep_settings fallback via pmset -g
- version_managers: require binary for pyenv/rbenv/jenv detection
- applications: detect Homebrew cask apps via Caskroom directory
- display: night shift/true tone fallback via defaults export
- network: VPN regex now matches real scutil --nc list format with
  colons/dots in protocol field and optional service type between
  UUID and name
- network: is_active uses ifconfig status: line instead of UP flag,
  correctly marks disconnected interfaces as inactive
- system: NTP detection uses pgrep timed instead of launchctl user
  domain check (timed runs in system domain)
- shell: sourced files now parsed for aliases/env vars (one level),
  previously only tracked as file paths without reading content
- homebrew: cask versions populated from Caskroom directory structure,
  previously only queried formula versions via brew list --versions
- applications: check Wrapper/App.app/Info.plist for iOS apps that lack
  Contents/Info.plist (Apollo, Authy, WiFiman now have versions)
- security: touch_id_sudo returns False (not None) when pam files were
  readable but pam_tid.so was not configured
TCC permissions require Full Disk Access to read and cannot be set via
nix-darwin configuration. The field was always empty in practice and
provided no actionable data for config generation.
TOML single-quoted strings are literal — '\\.py$' produced the regex
\\.py$ (literal backslash + any char + py) instead of \.py$ (dot + py).
The Python lint and format hooks have been silently skipping since the
project was created.
@wgordon17 wgordon17 merged commit 907d149 into gordon-code:main Mar 13, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant