51723 Commits

Author SHA1 Message Date
Douglas Teles abba87d061 ES + units: corrigir warnings do systemd-analyze e localizar .mo
systemd-analyze verify reclamava em 3 frentes:

1. StartLimitIntervalSec / StartLimitBurst em [Service] são
   silenciosamente ignorados, eles têm que ficar em [Unit].
   emustation.service e essway.service tinham os dois na seção errada,
   então a proteção contra restart-flood (Restart=always) nunca era
   aplicada. avahi-daemon.service tinha um StartLimitInterval (alias
   antigo, sem 'Sec') também na seção errada. Movidos para [Unit] em
   todos os três e renomeados para o key canônico.

2. sixaxis@.service é um template — instâncias são spawnadas sob
   demanda por udev (99-sixaxis.rules põe SYSTEMD_WANTS=sixaxis@%E
   {DEVNAME}). enable_service criava um symlink do template puro em
   multi-user.target.wants/, dangling porque template sem instância
   não roda. Removido o enable_service.

3. emulationstation procurava traduções em /usr/share/locale mas o
   ArchR embarca os .mo em /usr/config/locale via userconfig rsync,
   então o ES nunca encontrava emulationstation2.mo. Patch no fork ES
   (commits 8125fdf, 715ea4b no archr-linux/emulationstation-next):
   - main.cpp: prefere /usr/config/locale quando ele existe;
   - Platform.cpp: getArchString() lê HW_DEVICE do env (já exportado
     pelo profile.d/999-export) em vez de /usr/share/batocera/
     batocera.arch que nunca embarcamos;
   - Scripting.cpp: aceita /run/emulationstation/scripts além do
     legado /var/run/emulationstation/scripts.

archr-fhs-bridges.conf cria /run/emulationstation/scripts vazio em
todo boot para usuário poder dropar hooks (game-start, game-end,
system-selected, ...) sem mkdir manual após cada reset do tmpfs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-24 10:18:44 -03:00
Douglas Teles fcc56ec635 archr-config: corrigir paths Batocera no comando audio output
audio output X gravava o .asoundrc em /userdata/system/, herdado do
Batocera. Em ArchR a homedir de root é /storage, e o ALSA carrega
$HOME/.asoundrc, então o arquivo nunca chegava em lugar útil. Move
para /storage/.asoundrc.

A linha aplay tentava reproduzir /usr/share/sounds/Mallet.wav, que
não embarcamos. Trocar pelo launch.ogg dos retroarch-assets (já no
rootfs) e silenciar o erro com 2>/dev/null para não derrubar o
comando se a saída de áudio acabou de mudar e o aplay falha.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-24 09:58:46 -03:00
Douglas Teles d06e18a2ad gaps: ampla varredura de bugs herdados + pré-pacman repo-stable
A varredura via SSH no R36S rodando a 20260624 expôs várias
divergências entre rootfs estagiado e tmpfs/runtime. Cada arquivo
deste commit resolve um gap encontrado na investigação.

archr/tmpfiles.d/z_02_archr-fhs-bridges.conf (NEW):
  /var é tmpfs (busybox/system.d/var.mount), então todos os bridges
  FHS instalados como symlinks no rootfs eram apagados pelo mount.
  Republicar a estrutura via systemd-tmpfiles após var.mount. Resolve
  /var/lib/pacman, /var/cache/archr/*, /var/lib/archr/{config,data,
  games,backup}, /var/lib/{samba/private,tailscale,bluetooth},
  /var/spool/cron, /var/cache/pacman/pkg. Inclui também os targets em
  /storage (cron, locpath, tailscale, samba, .local/share, fstrim.run,
  journald.conf.d, request-key.d) que estavam ausentes.

ui/emulationstation/package.mk:
  ln -sf usava \${INSTALL}/usr/config/... como alvo, vazando o caminho
  absoluto do builder para o symlink /etc/emulationstation/es_systems.cfg
  no SO final. Trocar pelo path do target.

archr/system.d/timers.target.wants/{rocknix→archr}-report-stats.timer:
  Symlink apontava para um arquivo inexistente (rocknix-report-stats);
  o timer real chama-se archr-report-stats. Renome.

misc/modules/sources/images/install-{rocknix→archr}.svg:
  gamelist.xml já referenciava install-archr.svg; o arquivo se chamava
  install-rocknix.svg, quebrando o asset.

emulators/.../gamepads/ROCKNIX→ArchR Gamepad.cfg:
  Conteúdo já estava com input_device="ArchR Gamepad"; rename casa o
  nome de arquivo com a string de matching.

archr/package.mk + profile.d/005-locale:
  LANG="" no SO rodando, todas LC_*=POSIX. glibc gera en_US.UTF-8.
  Criar /etc/locale.conf e profile.d que source-a para shells de login
  e SSH (que não herdam LANG via systemd env).

sysutils/systemd/scripts/userconfig-setup + freej2me-lr/freej2me.sh:
  /storage/jdk caiu como arquivo vazio em algumas builds antigas e
  transforma o symlink /opt/jdk em "Not a directory". Saneamento
  duplo: a cada boot e antes do download do JDK.

devel/crossguid/package.mk + standalone/hypseus-singe/package.mk:
  cmake_install.cmake / crossguid-config.cmake embutiam o BUILD path
  do host. Remover dos pacotes target (não rodam em runtime).

tools/pyFDT/package.mk + network/samba/package.mk:
  setuptools e waf escrevem o python3 do TOOLCHAIN no shebang dos
  entry-points (pydtc, samba-gpupdate). Reescrever pra /usr/bin/python3.

sysutils/systemd/package.mk:
  systemd-sysroot-fstab-check é um symlink para
  systemd-fstab-generator, que removemos para fora dos generators.
  Apagar o link junto. Strip também a regra do legacy.conf que cria
  /var/log/README apontando para /usr/share/doc (não embarcamos docs).

sysutils/udevil/package.mk:
  /etc/udevil/udevil-user-root.conf é symlink para
  /storage/.config/udevil.conf que nunca era populado. Copiar a conf
  também para /usr/config/udevil.conf, daí o rsync do userconfig-setup
  o semeia no primeiro boot.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-24 02:44:45 -03:00
Douglas Teles 199e9a5ee4 security: bump gnupg to 2.4.8, add libksba/npth/pinentry deps
Live diagnostic on a R36S running the 20260624 image showed:

  archr:~ # gpg --version | head -1
  gpg (GnuPG) 1.4.23
  archr:~ # gpg --list-packets /usr/share/pacman/keyrings/archr.gpg
  :public key packet:
      ...
      unknown algorithm 22

GPG 1.4 is the "classic" branch, frozen before Ed25519 (algorithm 22)
was added in 2.1.x (2014). pacman-key 7.x also calls into gpg with
--check-signatures, a 2.x-only flag. With the ArchR master subkey
being Ed25519 the legacy 1.4 binary can neither parse nor verify the
keyring, so pacman -Sy fails with "no valid user IDs" and "signature
... is invalid" no matter how the user populates the keyring.

Fix the build, not the key. JELOS-era pacman packages cap GnuPG at
1.4.23 because that's the minimal-deps branch; ArchR is now an
Arch-family distro that ships pacman 7 as the user-facing update path,
so it has to ship the modern GnuPG runtime that pacman expects.

New packages:
- libksba 1.8.0
- npth 1.8
- pinentry 1.3.2 (built with --enable-pinentry-tty/curses only;
  the GUI variants would pull GTK/Qt that the handheld doesn't have)

Updated:
- gnupg 1.4.23 -> 2.4.8 (latest LTS branch)
  Configure trims to the bits pacman uses: gpg + gpgsm + gpgconf.
  scdaemon, dirmngr, tofu, wks, gpg-card and the historical 1.4-era
  ciphers (idea/cast5/md5/rmd160) are disabled to keep the image lean.
  pinentry-tty is the configured pinentry program, since the handheld
  has no graphical desktop session to use the other variants.

libassuan, libgcrypt and libgpg-error already live in projects/ArchR/
packages/security/ from earlier work — no new dep tree there.

This unblocks the pacman pipeline on R36S: archr-keyring populate will
parse the Ed25519 master, signature verification will accept the
ArchR-signed archr.db, and pacman -Sy lands at the package list.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-24 01:59:24 -03:00
Douglas Teles cceafdaca0 pacman: rewrite /usr/sbin/bash shebangs to /usr/bin/bash
Upstream pacman ships pacman-key, makepkg, vercmp and friends as bash
scripts whose shebang is built against the configured sbindir (/usr/sbin
on Arch). Arch ships /usr/sbin as a symlink to /usr/bin via the usrmerge
package, so the shebang resolves fine. ArchR (LibreELEC heritage)
does NOT merge sbin: /usr/sbin is a real directory and bash lives at
/usr/bin/bash only. Result on a fresh boot:

  archr:~ # pacman-key --init
  -sh: /usr/bin/pacman-key: /usr/sbin/bash: bad interpreter: No such
  file or directory

which also makes the pacman-init.service silently miss the keyring
populate step.

Post-install pass that rewrites every "#!/usr/sbin/bash" first line
to "#!/usr/bin/bash" anywhere under ${INSTALL}/usr fixes the lot in
one shot. The pkg.tar.zst we ship in the repo will need the same
treatment, but that's handled at build time too because gen-pacman-repo
packages whatever install_pkg holds.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-24 01:51:41 -03:00
Douglas Teles 6ce926d537 pacman: install /var/lib/pacman as symlink, not dir + child symlink
User reported on a freshly flashed R36S:

    archr:~ # pacman
    error: failed to initialize alpm library:
    (root: /, dbpath: /var/lib/pacman/)
    could not find or read directory

The package.mk created /var/lib/pacman as a real directory in
post_makeinstall_target (mkdir -p), then in post_install ran
`ln -sf /storage/.pacman/db ${INSTALL}/var/lib/pacman`. When LINK is
an existing directory, ln -sf does not replace it — it creates
LINK/$(basename TARGET). So the installed image ended up with:

  /var/lib/pacman/                ← real, empty dir (rootfs, ro)
  /var/lib/pacman/db -> /storage/.pacman/db   ← child symlink

Pacman reads dbpath=/var/lib/pacman/ from pacman.conf, looks for
local/ and sync/ inside it, finds nothing, and bails.

Fix: install /var/lib/pacman directly as a symlink to
/storage/.pacman/db in one shot, no intermediate mkdir. Same for
/var/cache/pacman/pkg. Move both into post_makeinstall_target so the
file layout is decided in one place; post_install now only enables
the pacman-init service.

Runtime escape hatch on already-installed systems (since the rootfs
is squashfs-ro and can't be patched):

    mount --bind /storage/.pacman/db /var/lib/pacman
    mount --bind /storage/.pacman/cache /var/cache/pacman/pkg

This commit fixes the build so the next image flashes correctly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-24 01:30:02 -03:00
Douglas Teles 2bb9ebb50a gen-pacman-repo: fall back to dirname when PKG_VERSION is a shell expr
awk -F'"' '/^PKG_VERSION/ ...' pulls the literal string out of the
package.mk, but a handful of packages set their version dynamically:

    PKG_VERSION="$(get_pkg_version gstreamer)"

The build system resolves that at build time and the install_pkg dir
ends up correctly named (gst-libav-1.27.1/). The packager, though, was
storing the raw "$(get_pkg_version gstreamer)" string, which then
went through the charset filter and became ".get_pkg_version.gstreamer."
in the asset name. Five packages slipped through in the first
repo-dev release with broken names (gst-libav, gst-plugins-good,
vitaquake2-{rogue,xatrix,zaero}-lr).

Detect any '$(' or '${' in the version string and treat it as
"unresolved", which trips the existing dirname-suffix fallback.
27 ArchR packages use this pattern; the fix covers all of them.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-24 00:32:18 -03:00
Douglas Teles 190469075f docs: 2.1 marked complete after the first repo-dev release
repo-dev now exists on archr-linux/archr-repo with all 543 assets
(535 packages + 8 db artifacts) signed via the master subkey we
generated yesterday. SigLevel PackageOptional DatabaseRequired
matches the SteamOS/EndeavourOS/Arch-ARM model.

Open follow-ups noted in the entry:
- CI hook so the publish is no longer a manual one-hour job after
  every build.
- Channel promotion (dev -> next -> stable) when v2.0 final lands.
- gen-pacman-repo version parser fails on 5 packages whose
  package.mk uses a placeholder (gstreamer family, vitaquake2-lr
  variants); not a runtime blocker but the dirnames are ugly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-24 00:27:34 -03:00
Douglas Teles 7addeb691a pacman: drop per-package signing, sign only the repo db
First repo-dev release uploaded 1000/1078 assets before hitting
GitHub's documented per-release limit of 1000 assets. The cap is
hit because every package shipped a paired .sig, doubling the
count without adding meaningful security.

The trust path now flows entirely through the database:
  - archr-keyring ships the master public key.
  - archr.db.sig proves the db came from the maintainer.
  - The db records the SHA256 of every package; pacman re-hashes
    after download and refuses mismatches.

To compromise a package the attacker would have to publish a
modified db that lists their hash, which requires the signing
subkey. The per-package .sig was redundant against this attack.

This is the same model Arch Linux ARM, EndeavourOS and SteamOS
use in production.

pacman.conf SigLevel flips from "Required DatabaseOptional" to
"PackageOptional DatabaseRequired"; comment expanded so a future
reader sees the why.

gen-pacman-repo drops the `gpg --detach-sign` step inside
build_one_pkg(); repo-add --sign still signs the db at the end.
Asset count shrinks from 1078 to 543 (535 packages + 8 db
artifacts), which fits comfortably in a single GitHub Release.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 23:27:27 -03:00
Douglas Teles be19e9ec47 mali-bifrost: revert 003 patch to the pre-sync ArchR version
The ROCKNIX-sourced rewrite of 003-midgard-refactor-power-init-and-
fixed-unbalanced-run.patch (picked up in 5805267f90) targets a
different kbase tree: it patches platform/devicetree/mali_kbase_runtime_pm.c
expecting `else if (!regulator_is_enabled(...))` on line 38.
Our mali_kbase pin (github.com/archr-linux/mali_kbase @ 422e192b)
does not have that line, so the hunk rejects and mali-bifrost:target
fails to install.

Restore the original 199-line patch that targets platform/meson/
mali_kbase_runtime_pm.c, which is the path that exists in our tree.
This was the file as of commit 5805267f90^ — the working pre-sync
state.

The ROCKNIX cleanup will become applicable when (and if) we move to
the same kbase revision they ship, which would itself be a bigger
upgrade.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 21:03:58 -03:00
Douglas Teles 70fb40de43 archr: drop F7 hatari/openbor bridges, fall through umbrellas
In F7 I added explicit bridge symlinks for hatari and openbor:
  ln -sf /storage/.hatari /var/lib/archr/data/hatari
  ln -sf /storage/openbor /var/lib/archr/games/openbor

That breaks the build at install time. The F5/F6 umbrella bridges
already turn /var/lib/archr/data and /var/lib/archr/games into
symlinks (-> /storage/.local/share and /storage/roms). When the
hatari ln -sf tries to create a child node under
/var/lib/archr/data, it follows the umbrella symlink, hits
/storage/.local/share which does not exist on the rootfs at build
time, and aborts with "No such file or directory".

Resolution: rely on the umbrella alone. /var/lib/archr/data/hatari
resolves to /storage/.local/share/hatari at runtime through the
umbrella; start_hatari.sh and start_OpenBOR.sh already mkdir -p the
final dir on first launch, so the dir materializes when needed.

Keep the /opt/jdk bridge because there is no /opt umbrella to fall
through.

This is the second clean-build fix on top of the wayland patch
rebase (7eff5d02a6).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 20:27:23 -03:00
Douglas Teles 7eff5d02a6 wayland: rebase pkgconfig patch for 1.25.0
The 00-fix-wayland-scanner-pkgconfig.patch was anchored on a context
line ('bindir=' + join_paths(...)) that Wayland removed between 1.24
and 1.25. After our F0 bump to 1.25.0 the unpack step rejected the
patch and aborted the build_compat arm pass.

Pull the rebased patch from ROCKNIX (commit a9e464274a in their
graphics/display sync) where the same context shift was already
resolved: the bindir line is gone, the filebase line stays.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 17:59:44 -03:00
Douglas Teles 41d376a029 gen-pacman-repo: fix package layout for pacman 7 repo-add
Three bugs caught while smoke-testing against an existing
build.ArchR-RK3326.aarch64/install_pkg tree:

1. BUILD_DIR auto-detection glob did not include the trailing arch
   suffix, so build.ArchR-RK3326.aarch64 never matched. Now matches
   build.*-RK3326*aarch64*.

2. Version sanitization used `echo | tr -c '[charset]' '.'` which
   turns the trailing newline into a stray '.', producing versions
   like "1.0.8." that pacman refuses. Swapped to printf.

3. Package layout was wrong for pacman 7 repo-add:
   - .PKGINFO must be the FIRST entry in the tar (pacman streams it).
   - No "./" prefix on file names (matches makepkg output).
   - .PKGINFO needs `pkgbase` and `xdata = pkgtype=pkg` lines, not
     just `pkgname`.
   Rewrote the packing block to assemble an explicit file list with
   .PKGINFO first, then tar -T.

Also: install_pkg name extraction is more robust now — sed strips
both 40-char git hashes and semver suffixes to recover the real
package name, and the package.mk lookup uses find rather than
literal globbing so packages nested at any depth are found.

Smoke test confirms repo-add accepts the resulting archive, signs
archr.db with the configured signer, and emits the expected
symlinks archr.db -> archr.db.tar.gz.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 17:43:08 -03:00
Douglas Teles 43e464525f archr-keyring: ship the production ArchR master public key
Master generated 2026-06-23 offline (ed25519 cert-only with ed25519
sign subkey expiring 2028-06-23). Private master lives on encrypted
cold storage; the signer subkey is on the build workstation only.
Revocation certificate kept offline in two physical locations.

Fingerprint: 0CB282379EBB394EF380AEB98A762D5706C602A1

archr.gpg is the binary public keyring that pacman-key --populate archr
walks; archr-trusted gives the master full ownertrust (level 4) so
packages signed by its subkey are accepted; archr-revoked stays empty
until a key is actually revoked.

archr-keyring/package.mk already auto-detects these files (instead of
the empty placeholders it shipped before) and includes them in the
image. With the keyring populated, the next gen-pacman-repo run with
SIGNER set will produce a properly signed archr.db and per-package
.sig files that ArchR clients can verify.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 17:35:06 -03:00
Douglas Teles b6ceea9347 2.1: pacman as real update mechanism (client side)
Decision: pacman repo lives on GitHub Releases at
archr-linux/archr-repo. No VPS, no repo.arch-r.io. Google Drive stays
out of runtime (backup/archive only). Cloudflare R2 fallback deferred.
Detail in docs/release-policy.md.

archr-update rewritten end-to-end:
- 188 lines of dead POST-to-update.arch-r.io code replaced by an
  87-line wrapper around pacman -Syu. The POST endpoint never existed
  so there is no legacy compat to preserve.
- subcommands: check, update, info. system.cfg "updates.branch" maps
  to repo-stable / repo-next / repo-dev tags on archr-linux/archr-repo;
  the mirrorlist is rewritten on every invocation so channel switches
  are immediate.

pacman.conf rebuilt around a single [archr] repo (Arch Linux ARM
upstream removed). SigLevel starts at "Required DatabaseOptional"
during bootstrap; will tighten to "Required" once the production
master key signs the .db.

pacman-init reachability test points at github.com and the keyring
populate target is "archr" instead of "archlinuxarm".

archr-keyring repurposed: the three archlinuxarm keyring files are
removed; package.mk now expects archr.gpg / archr-trusted /
archr-revoked under keys/ and ships empty placeholders until the real
ArchR master key is generated.

scripts/repo/gen-pacman-repo + README: take the build.*-RK3326 tree
that "make docker-RK3326" leaves behind, package each install_pkg/<x>
as a .pkg.tar.zst with synthesized .PKGINFO, run repo-add to build
archr.db, optionally GPG-sign everything. Emits a `gh release create`
command for the publish step. CI hook left as a follow-up.

docs/improvements.md 2.1 marked partial: client and build script are
ready; what blocks the first usable release is generating the GPG
master key, creating archr-linux/archr-repo on GitHub, and one manual
publish for the repo-dev tag to validate the end-to-end loop.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 17:03:35 -03:00
Douglas Teles 3beb86f3d4 docs: close Arch-ification 2.5 in improvements.md
Quirks pruning done in 7644ce26d3 (352 files, 8037 lines). Splash
rename and runemu.sh refactor reclassified as organic follow-ups:
- splash sed stays until upstream archr-splash repo finishes the
  internal rename.
- runemu.sh is 578 lines (not 1500+ as the original entry guessed);
  refactor still pays in maintainability but is not a blocker.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 16:34:37 -03:00
Douglas Teles 7644ce26d3 2.5 KISS: prune dead-platform and dead-device quirks
projects/ArchR/packages/hardware/quirks/ shipped 50 device dirs and
10 platform dirs inherited from JELOS/ROCKNIX. ArchR only ever
supports RK3326 (one platform), and the per-device quirks are
selected at runtime by reading /sys/firmware/devicetree/base/archr,device_switch/this
— a name that can only match a DTB we compiled in. The 42 device
dirs without a matching DTB and the 9 platform dirs for SoCs we
don't have (H700, RK3399, RK3566, RK3588, S922X, SDM845, SM8250,
SM8550, SM8650) were unreachable code.

Keep: 14 device dirs and 1 platform (RK3326). All correspond to a
DTS file in projects/ArchR/devices/RK3326/linux/dts/rockchip/ so
they can actually be selected at boot.

Cross-references to the dead platforms in other scripts (case
${DEVICE} in RK3399) ...; case ${DEVICE} in SM8250) ...) stay
as harmless dead branches that never trigger when DEVICE=RK3326;
cleaning those up is in scope for a follow-up sweep.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 16:32:36 -03:00
Douglas Teles 54a79b99aa docs: mark Arch-ification 2.2 (FHS) closed in improvements.md
Section 2.2 now reflects what shipped: auditoria + 22 bridges + 7 vars
+ man page + 7 phases all marked done. Open item left explicit: the
1625 hardcoded /storage refs in legacy scripts continue to work via
compat and refactor organically.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 16:28:33 -03:00
Douglas Teles d10869a802 FHS F7: Class Z + migration complete
Three concrete Class Z migrations land via bridges in the archr meta-
package plus single-line script tweaks:
- /storage/jdk -> /opt/jdk (runemu.sh JAVA_HOME, freej2me.sh JDKDEST)
- /storage/.hatari -> /var/lib/archr/data/hatari (start_hatari.sh
  HATARI_DIR_HOME; the pre-baked Atari-ST .cfg files keep working
  through the symlink because both addresses resolve to the same
  overlay dir).
- /storage/openbor -> /var/lib/archr/games/openbor (start_OpenBOR.sh
  CONFIGDIR).

Other Class Z paths fall out cleanly:
- /storage/.opt was already covered by /opt -> /storage/.opt symlink
  in virtual/image/package.mk.
- /storage/.emulationstation already gets redirected to
  /storage/.config/emulationstation by emulationstation's autostart,
  which is in turn covered by the umbrella bridge F5.
- /storage/psvita/vita3k/ux0/app and /storage/.nfs-mount are
  low-traffic top-level paths; no bridge added.

docs/fhs-mapping.md: Fase 7 detail + system-wide audit summary. 17
umbrella bridges in archr meta-package + 5 modular (openssh, iwd,
bluez, connman, fontconfig). All seven ARCHR_* variables resolve to
Arch-friendly paths. The remaining 1625 hardcoded /storage refs in
projects/ArchR continue to work through compat (both paths reach the
same storage overlay); refactoring those is left as an organic
follow-up.

Status header marks the FHS migration complete. Section 2.2 of the
Arch-ification roadmap is now closed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 16:27:58 -03:00
Douglas Teles 917988587a FHS F6: Class E via umbrella bridge
Same playbook as F5, applied to user data. /storage/roms appears in
117 files in projects/ArchR and refactoring every reference in one
shot would be a huge diff over the directory where the user's games
library lives. Bad risk-reward.

Two new umbrella bridges in the archr meta-package:
  /var/lib/archr/games  -> /storage/roms
  /var/lib/archr/backup -> /storage/backup

ARCHR_GAMES flipped to the FHS path; man page mirrors it.

The other Class E paths (screenshots, recordings, downloads, music,
pictures, videos, tvshows) audit as zero references in
projects/ArchR; they are LibreELEC top-level heritage and not used at
ArchR runtime.

/storage/.ssh stays as is. busybox/package.mk sets the root user's
HOME to /storage, so /storage/.ssh is literally $HOME/.ssh — FHS
already. Moving to /root/.ssh would require flipping the HOME of root
to /root first, which has knock-on effects (cd ~, every script that
assumes cwd at login, etc) outside the FHS scope.

No data migration script: nothing on disk moves. ROMs and saves keep
exactly the same bytes; the FHS path is just another way to address
them.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 16:25:04 -03:00
Douglas Teles 4a6cb841db FHS F5: Class B via umbrella bridge
Original F5 plan was "one commit per emulator, refactor every
hardcoded /storage/.config/<emu> reference". Audit showed that path
appears across 22+ device quirk files, multiple start scripts and a
handful of compiled-in patches per emulator. Mass refactor would be a
huge diff with real regression risk and zero FHS gain on the running
system because, with the bridge installed, the FHS path already
resolves correctly.

Pivot: install two umbrella bridges in the archr meta-package:
  /var/lib/archr/config -> /storage/.config
  /var/lib/archr/data   -> /storage/.local/share

Flip the ARCHR_CONFIG and ARCHR_DATA exports in 010-archr-fhs to the
FHS paths so downstream scripts that already use the variables get
the Arch-friendly surface for free. Update archr(7) ENVIRONMENT
section: both variables now describe the FHS location as the actual
address, with /storage/... noted as the rw-overlay substrate.

Net effect: every /var/lib/archr/config/<emu> and
/var/lib/archr/data/<emu> path exists at runtime and is writable.
Inspection tools see a normal Arch layout. Hardcoded /storage/.config
references in JELOS-inherited quirks and start scripts keep working
because the symlink resolves both ways — writes through either path
land in the same overlay file. Per-emulator refactors stay possible
later, as incremental PRs, without a single big-bang.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 16:23:05 -03:00
Douglas Teles a20ecf72b9 docs: FHS F4 closing notes
Fase 4 in fhs-mapping.md gets the breakdown: 9 state dirs bridged in
the four F4.x commits (ssh, iwd, bluez, services, samba, connman,
wireguard, tailscale, cron), pacman db/cache and rfkill noted as
no-op (already bridged upstream), .local/share moved to F5 (it is
per-emulator data and stays with each emulator's config migration),
overlayfs upperdirs documented as permanent no-op for the same
constraint that pinned the F3 workdirs, .pacman/build deferred to
section 2.1 when pacman gets wired into userland.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 16:19:28 -03:00
Douglas Teles 3c589686be FHS F4.3: service enable flags + samba/connman/tailscale/cron state
Wider Class D batch. Every state directory referenced by a systemd
unit or runtime script now lives at an Arch-conventional path with a
bridge symlink into /storage:

service enable/disable flags
  /storage/.cache/services -> /var/lib/archr/services
  ConsumerS: 099-networkservices, archr-report-stats.timer, and the
  12 unit files that gate themselves on .conf / .disabled sentinels
  (avahi-daemon, avahi-defaults, sshd, nmbd, smbd, simple-http-server,
  syncthing, tailscaled, zerotier-one, cron, cron-defaults). The
  systemd-scripts/usercache-setup migration helper updated too.

samba passdb
  /storage/.cache/samba -> /var/lib/samba/private (Arch standard).
  smb.conf passdb line + 007-rootpw boot init script updated.

connman + wireguard
  /storage/.cache/connman -> /var/lib/connman
  /storage/.config/wireguard -> /etc/wireguard (vpn_storagedir)
  Bridges installed by the connman package; connman-setup script
  follows the bridge.

tailscale
  /storage/.cache/tailscale -> /var/lib/tailscale.
  tailscaled --state= flag flipped to the FHS path; bridge in archr
  meta-package.

cron
  /storage/.cache/cron -> /var/spool/cron (Arch convention; busybox
  crond reads spool/<user>). cron.service ExecStartPre updated.

archr meta-package now ships seven Class D bridge symlinks alongside
the five Class C bridges from earlier phases. Everything else stays
on the storage overlay; nothing on disk moved.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 16:17:55 -03:00
Douglas Teles 918e3158e9 FHS F4.2: bluez storage to /var/lib/bluetooth
bluez configure storagedir flipped to /var/lib/bluetooth (Arch
convention for paired-device state). post_makeinstall_target plants
the bridge symlink to /storage/.cache/bluetooth so pairings persist
on the rw overlay across reboots.

archr-config forgetBT helper and backuptool default list also point
at the FHS path.

tmpfiles z_05_bluez.conf intentionally keeps creating
/storage/.cache/bluetooth as the real overlay dir.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 16:14:04 -03:00
Douglas Teles cd87193b86 FHS F4.1: ssh host keys + iwd state to /var/lib (credentials)
Two security-sensitive state dirs migrated to Arch-standard locations.

openssh:
- --with-keydir flipped from /storage/.cache/ssh to /var/lib/sshd.
- post_install plants a bridge symlink /var/lib/sshd ->
  /storage/.cache/ssh so keys persist on the rw overlay.
- sshd.service updates all three ExecStartPre paths.
- tmpfiles z_04_openssh.conf keeps creating /storage/.cache/ssh as
  the real overlay dir.

iwd:
- Environment STATE_DIRECTORY in iwd.service now /var/lib/iwd.
- post_makeinstall_target adds the /var/lib/iwd ->
  /storage/.cache/iwd bridge symlink.
- wifictl (IWD_DIR, IWD_AP_CFG_DIR), post-update copy target and
  userconfig-setup all flipped to /var/lib/iwd.
- tmpfiles z_03_iwd.conf keeps creating the backing dirs.

Both follow the same bridge pattern as F2/F3: FHS surface, storage
overlay substrate. SSH host keys and wifi credentials survive the
migration because the underlying bytes never move (symlink swap).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 16:12:39 -03:00