Ran a doc-vs-filesystem crosscheck: extracted every backtick-quoted path with a file extension or known directory prefix from docs/*.md and verified each exists. After filtering false positives (placeholder paths, config keys mistaken for paths, paths inside docs that already have historical-status banners), found 4 real broken references — 3 fixed in docs, 1 fixed by creating the missing file: docs/HOW_TO_RUN_TESTS.md:339 - Claimed ".github/workflows/tests.yml" exists and runs pytest on multiple Python versions in CI. There is no such workflow. The only GitHub Actions file is security-audit.yml (bandit + semgrep). - Pytest runs locally but is NOT gated on PRs. - Replaced the fictional CI section with the actual state and a note explaining how someone could contribute a real test workflow. docs/MIGRATION_GUIDE.md:92 - Referenced scripts/fix_perms/README.md "(if exists)" — the hedge betrays that the writer wasn't sure. The README didn't exist. The 6 scripts in scripts/fix_perms/ were never documented. - Created the missing scripts/fix_perms/README.md from scratch with one-line descriptions of all 6 scripts (fix_assets, fix_cache, fix_plugin, fix_web, fix_nhl_cache, safe_plugin_rm) + when-to-use-each guidance + usage examples. - Updated MIGRATION_GUIDE link to drop the "(if exists)" hedge since the file now exists. docs/FONT_MANAGER.md:376 - "See test/font_manager_example.py for a complete working example" — that file does not exist. Verified by listing test/ directory. - Replaced with a pointer to src/font_manager.py itself and the existing scoreboard base classes in src/base_classes/ that actually use the font manager API in production. Path-existence check methodology: - Walked docs/ recursively, regex-extracted backtick-quoted paths matching either /\.(py|sh|json|yml|yaml|md|txt|service|html|js|css|ttf|bdf|png)/ or paths starting with known directory prefixes (scripts/, src/, config/, web_interface/, systemd/, assets/, docs/, test/, etc.) - Filtered out URLs, absolute paths (placeholders), and paths without slashes (likely not relative refs). - Checked existence relative to project root. - Out of 80 unique relative paths in docs/, 32 didn't exist on disk. Most were false positives (configkeys mistaken for paths, example placeholders like 'assets/myfont.ttf', historical references inside docs that already have status banners). The 4 above were genuine broken refs. This pattern is reusable for future iterations and worth wiring into CI (link checker like lychee, scoped to fenced code paths rather than just markdown links, would catch the same class). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Permission Fix Scripts
This directory contains shell scripts for repairing file/directory permissions on a LEDMatrix installation. They're typically only needed when something has gone wrong — for example, after running parts of the install as the wrong user, after a manual file copy that didn't preserve ownership, or after a permissions-related error from the display or web service.
Most of these scripts require sudo since they touch directories
owned by the ledmatrix service user or by root.
Scripts
-
fix_assets_permissions.sh— Fixes ownership and write permissions on theassets/tree so plugins can download and cache team logos, fonts, and other static content. -
fix_cache_permissions.sh— Fixes permissions on every cache directory the project may use (/var/cache/ledmatrix/,~/.cache/ledmatrix/,/opt/ledmatrix/cache/, project-localcache/). Also creates placeholder logo subdirectories used by the sports plugins. -
fix_plugin_permissions.sh— Fixes ownership on the plugins directory so both the root display service and the web service user can read and write plugin files (manifests, configs, requirements installs). -
fix_web_permissions.sh— Fixes permissions on log files, systemd journal access, and the sudoers entries the web interface needs to control the display service. -
fix_nhl_cache.sh— Targeted fix for NHL plugin cache issues (clears the NHL cache and restarts the display service). -
safe_plugin_rm.sh— Validates that a plugin removal path is inside an allowed base directory before deleting it. Used by the web interface (via sudo) when a user clicks Uninstall on a plugin — prevents path-traversal abuse from the web UI.
When to use these
Most users never need to run these directly. The first-time installer
(first_time_install.sh) sets up permissions correctly, and the web
interface manages plugin install/uninstall through the sudoers entries
the installer creates.
Run these scripts only when:
- You see "Permission denied" errors in
journalctl -u ledmatrixor the web UI Logs tab. - You manually copied files into the project directory as the wrong user.
- You restored from a backup that didn't preserve ownership.
- You moved the LEDMatrix directory and need to re-anchor permissions.
Usage
# Run from the project root
sudo ./scripts/fix_perms/fix_cache_permissions.sh
sudo ./scripts/fix_perms/fix_assets_permissions.sh
sudo ./scripts/fix_perms/fix_plugin_permissions.sh
sudo ./scripts/fix_perms/fix_web_permissions.sh
If you're not sure which one you need, run fix_cache_permissions.sh
first — it's the most commonly needed and creates several directories
the other scripts assume exist.