258 lines
16 KiB
Markdown
258 lines
16 KiB
Markdown
# Connexion Labfy / Mosaic / QuickShell — V2
|
||
|
||
État du lot : **READY_FOR_EXPLICIT_INSTALL_APPROVAL**. Aucune installation ni
|
||
activation. Ce document complète la V1 de [SESSION_SELECTOR](SESSION_SELECTOR.md)
|
||
et conserve sa recette historique. Le greeter installé utilise encore
|
||
`uwsm start default` ; le sélecteur source V1 n'est pas installé.
|
||
|
||
## Périmètre et conservation
|
||
|
||
LAB privé 0700 : `/var/tmp/labfy-greeter-mosaic-login-v2-0dvus1y_/`.
|
||
Les journaux bruts et rc sont sous `logs/` et `results.jsonl`. Le snapshot initial,
|
||
le diff V1, ses sources et 293 081 empreintes contrôlées hors paquet greeter sont
|
||
sous `audit/`. Aucun écart de contenu/mode/propriétaire/lien n'a été trouvé hors
|
||
`greetd/`. Le dépôt Mosaic reste propre à `7216eb55`, sans modification.
|
||
|
||
V1 est reprise, sans réécrire le runtime : `src/greetd_ipc.py`, `src/auth.py`,
|
||
`src/labfy_greeter.py` et `style/labfy-greeter.css` restent byte-identiques aux
|
||
sources V1 initiales. Un test ajoute le refus Mosaic puis une nouvelle tentative
|
||
PAM Stable. `session-update.py` ajoute une relecture après publication avant de
|
||
certifier son journal, et une barrière complète de durabilité avant mutation. Les autres nouveaux fichiers sont des candidats, outils,
|
||
tests et documents sous `greetd/`, pas des services déployés par Stow.
|
||
|
||
Le source candidat du lanceur, ses wrappers/configuration de référence et le
|
||
manifeste sont sous `mosaic-login-v2/launcher/`. Seuls `session.py`,
|
||
`manifest.json` et le nouveau `quickshell-guard.py` sont destinés à publication.
|
||
Les wrappers, l'entrée desktop, la configuration Mosaic, les drop-ins existants,
|
||
le binaire CORE-C V2 et wlroots restent inchangés.
|
||
|
||
## Sélecteur et autorité PAM
|
||
|
||
| Choix visible avant saisie | Commande exacte transmise après PAM, avec `env=[]` |
|
||
| --- | --- |
|
||
| SwayFX — Stable, défaut à chaque ouverture | `["/usr/bin/uwsm", "start", "sway.desktop"]` |
|
||
| SwayFX Mosaic — Expérimental, choix explicite | `["/usr/bin/uwsm", "start", "swayfx-mosaic-test.desktop"]` |
|
||
|
||
Liste immuable ; aucune interpolation, commande libre ou exécution UWSM dans GTK.
|
||
Le compte et la sélection sont figés pour la conversation. Les contrôles sont
|
||
gelés pendant une requête ; changer compte/session entre invites annule PAM.
|
||
Un refus de lancement consomme l'authentification et ne déclenche aucun repli.
|
||
L'aperçu désactive PAM, alimentation et écriture de luminosité.
|
||
|
||
`default-id` vaut actuellement `sway.desktop`, SHA256
|
||
`7936c31cdc80c790ebb9c08f20ddd2e52f7a1fe82d46e1a44a0b395137dc141e`.
|
||
La valeur V1 « déjà Mosaic » est une observation historique antérieure ; elle
|
||
ne décrit plus l'état V2. Aucun test V2 ne modifie cette préférence réelle.
|
||
Le test `stable` utilise une préférence factice dans le LAB, sans binaire Mosaic.
|
||
|
||
## Cause attestée et correctif du lanceur
|
||
|
||
Le journal du 15 octobre 2026 à **16:50:10 +02:00** contient :
|
||
`MOSAIC REFUSÉ : Isolation swayidle/autostart non chargée`.
|
||
Le nom XDG autostart dans `systemctl --user show ... -p Conflicts` est entre
|
||
guillemets, avec les antislashs de `\x2d` doublés. `.split()` conserve ce codage ;
|
||
le test reproduit le faux négatif sur la sortie réelle, pas une chaîne inventée.
|
||
|
||
`systemd_words()` valide une grammaire bornée puis décode via `shlex.split`,
|
||
sans shell. Les échappements inconnus, tokens concaténés, contrôles et noms
|
||
invalides sont rejetés. `validate_isolation()` exige l'Id exact, `LoadState=loaded`,
|
||
les chemins exacts des deux drop-ins chargés et chaque conflit d'exclusion.
|
||
Le vrai manager chargé passe en lecture seule. Les négatifs retirent chacun des
|
||
conflits et altèrent identité, LoadState et DropInPaths. Aucune garde logind,
|
||
seat/VT, cgroup, notify, parent graphique, LD ou empreinte n'est supprimée.
|
||
Les alias Stow systemd/QuickShell sont vérifiés littéralement ; les lectures et
|
||
publications visent ensuite leurs chemins canoniques sans traverser ces liens.
|
||
|
||
## QuickShell propre à Mosaic
|
||
|
||
Source : `mosaic-login-v2/systemd/quickshell-labfy-mosaic.service`, avec son
|
||
lien `.target.wants/` relatif conservé dans le même répertoire de sources.
|
||
La cible est exactement `wayland-session@swayfx\x2dmosaic\x2dtest.desktop.target`.
|
||
`WantedBy` ne vise qu'elle ; `PartOf` et `BindsTo` attachent l'arrêt au target.
|
||
`After` et `Requisite` visent target et WM. Le WM UWSM est `Type=notify` : son
|
||
`uwsm finalize` existant exporte les sockets avant `READY=1`. Aucun `exec qs`
|
||
n'est ajouté à la configuration du compositeur. Commande :
|
||
`/usr/bin/qs -c labfy-sway --no-color`. `Restart=no`, arrêt borné à 5 secondes.
|
||
|
||
L'ExecStartPre valide les états, MainPID, cgroup, SHA du processus, mapping
|
||
wlroots, contexte logind/VT et propriété des **deux sockets** par le processus.
|
||
Un autre WM, un QuickShell existant ou un serveur de notifications fait refuser
|
||
le démarrage. Aucun `Conflicts` n'arrête QuickShell Stable pour le remplacer.
|
||
Le service Stable et son lien d'activation sont byte-identiques aux originaux.
|
||
|
||
Le manager partagé contient actuellement un SWAYSOCK ancien (PID 5630), alors
|
||
que le WM Stable réel est PID 12197. Aucun correctif de la session active n'a
|
||
été tenté. La nouvelle garde empêche précisément cette confusion sur Mosaic.
|
||
|
||
Le seul adaptateur QML est une garde dans `SessionV2Service.run()` :
|
||
`LABFY_MOSAIC_SMOKE=1`, fourni uniquement au service Mosaic, refuse les opérations
|
||
V2 avant démarrage du backend. Stable garde son comportement lorsque ce drapeau
|
||
est absent. Le candidat est isolé sous `mosaic-login-v2/quickshell/`, et n'a pas
|
||
été copié dans le QML actif. Après installation approuvée, la publication de ce
|
||
QML partagé peut provoquer sa détection/relecture par QuickShell Stable ; aucun
|
||
changement de service ni redémarrage explicite n'est déclenché par les outils.
|
||
|
||
L'audit des QML trouve un PolkitAgent et le NotificationServer existants dans
|
||
labfy-sway, ainsi que les accès Sway via l'environnement SWAYSOCK. Les adaptateurs
|
||
WiFi/Bluetooth restent ceux de Quickshell. Aucun nouveau daemon/agent ou lock
|
||
n'est introduit. L'autostart XDG, swayidle, wlsunset et les collecteurs clipboard
|
||
restent exclus par les drop-ins actuels. Session Restore V2 reste désactivé dans
|
||
le smoke Mosaic, y compris ses actions manuelles. La barre réelle, les services
|
||
D-Bus, la sortie physique et les fonctions interactives restent **NOT_RUN**.
|
||
|
||
## Matrice de validation
|
||
|
||
| Contrôle | Résultat effectif |
|
||
| --- | --- |
|
||
| Suite V1 initiale | PASS : 19 recensés, 17 exécutés, 2 GTK ignorés |
|
||
| Suite greeter V2 complète avec Wayland explicite | PASS : 21/21, rc=0 |
|
||
| Même suite sans GTK | PASS : 19 exécutés, 2 ignorés, rc=0 |
|
||
| Suite lanceur/garde/publications/coordination V2 | PASS : 29/29, rc=0 |
|
||
| Ancien parser sur vraie propriété | Faux négatif reproduit ; nouveau parser PASS |
|
||
| Négatifs isolation, contexte, PID Stable, SHA, symlink et `stable` sans LAB | PASS dans tests réels/factices explicités |
|
||
| Deux `uwsm start -n <id>.desktop` | PASS, rc=0 ; aucune écriture ni démarrage |
|
||
| `systemd-analyze --user --generators=no verify` unité candidate | PASS, rc=0 |
|
||
| Relations WantedBy/After/Requisite/PartOf/BindsTo, source `.wants` | PASS, modèle statique ; manager privé non nécessaire |
|
||
| Qt6 qmllint avec vrais modules et copie candidate de 86 sources | rc=0 ; mêmes 17 avertissements qu'en baseline, aucun nouveau |
|
||
| AST + py_compile, pycache LAB | PASS, 18 fichiers Python |
|
||
| Aperçus GTK natifs, fenêtre seule, 1131 × 853 | PASS : Stable initial et Mosaic, aucun PAM |
|
||
| Root : erreur d'écriture, vraie mort après deux rename, reprise | PASS sur cibles factices, suite greeter |
|
||
| User : mort après chacun des six rename, rollback et idempotence | PASS sur cibles factices, six points d'interruption |
|
||
| Coordination : mort après user et après root, reprise des deux lots | PASS sur cibles factices, deux frontières |
|
||
| Barrières complètes : ordre fsync/publication, défauts outils/métadonnées/parents | PASS sur fixtures ; aucun fichier actif publié si échec |
|
||
| Garde complète PID/maps/inodes/autre QuickShell/logind | PASS sur fixture isolée et sockets factices ; aucun compositeur lancé |
|
||
| Préflight global du nouveau bundle | PASS, aucune publication active |
|
||
| Installation/rollback réels root/user, daemon-reload | NOT_RUN |
|
||
| Login VT1, Mosaic autonome, barre réelle, sortie et retour greeter | NOT_RUN |
|
||
|
||
Échecs initiaux conservés dans les logs : constructeur Selection convertissant
|
||
`None` en Path (corrigé) ; premier GTK sans WAYLAND_DISPLAY (socket identifié en
|
||
lecture seule puis fourni explicitement) ; préflight refusant le parent symlink
|
||
Stow (chemins canoniques corrigés) ; ConfigParser du test refusant deux lignes
|
||
Environment (une ligne équivalente, verify systemd passant). Aucun échec brut
|
||
n'est converti en PASS. PyGObject émet des avertissements de dépréciation asyncio.
|
||
Les captures sont `captures/preview-stable.png` et `captures/preview-mosaic.png`
|
||
dans le LAB ; la date affichée en anglais vient de la locale de cet aperçu.
|
||
Aucune qualification fullscreen/VT1 ou daily-driver Mosaic n'en découle.
|
||
|
||
## Audit final et correction bornée
|
||
|
||
L'audit final unique du snapshot **bundle-r1 reste FAIL** : un BLOCKING de
|
||
barrière de durabilité complète, et une limite NON_BLOCKING de couverture du
|
||
parcours positif `verify_process()`. Le bundle r1 est conservé et supersédé,
|
||
jamais promu en PASS rétroactivement.
|
||
|
||
La réparation ajoute les deux barrières complètes décrites ci-dessous, teste
|
||
leur ordre avant le premier rename et injecte des erreurs sur les outils,
|
||
métadonnées et parents : zéro cible changée. La fixture positive de la garde
|
||
et ses mutations maps/inodes/autre QuickShell/logind passent également.
|
||
Ces corrections appartiennent à une seule chaîne bornée après audit. La revue
|
||
bornée indépendante du delta et du bundle **r2** est **PASS**, sans finding
|
||
restant. La validation indépendante finale confirme **21/21 tests GTK greeter**
|
||
et **29/29 tests V2**, les 23 empreintes du bundle et le préflight global.
|
||
Inventaire r2 SHA256 :
|
||
`d4c1c393e5217ec583c1c1ac30b7b6c7841c659dfcd3a385325b3b0d19d8aa3d`.
|
||
Les tests de mort de processus ne constituent pas une coupure électrique réelle,
|
||
qui reste **NOT TESTED** ; la garantie de durabilité repose sur les fsync ordonnés
|
||
et les garanties du système de fichiers, pas sur une simulation de panne machine.
|
||
|
||
## Installation proposée — après approbation explicite uniquement
|
||
|
||
Le bundle courant examiné est `bundle-r2/` dans le LAB : sous-lots `root/` et
|
||
`user/`, inventaire `SHA256.json`. Ne jamais réutiliser les `.new` V1 ou les
|
||
premières préparations intermédiaires `staging/`. `prepare-login-recovery.py`
|
||
reconstruit les deux sous-lots depuis les sources courantes, copie les outils et
|
||
scelle les fichiers user dans le sous-lot root. Le préflight global vérifie
|
||
également default-id, Stable, les scripts greeter, config.toml et le couple
|
||
binaire/wlroots exact. Un changement impose nouvelle préparation/revue.
|
||
|
||
Les commandes ci-dessous sont **préparées, NON EXÉCUTÉES**. Avant de les autoriser,
|
||
examiner diff, captures, SHA et résultats. Les répertoires durables doivent être
|
||
neufs ; `mkdir` refuse de remplacer un lot déjà installé. Ne pas ouvrir une
|
||
nouvelle connexion pendant la courte publication des fichiers.
|
||
|
||
```sh
|
||
# UNIQUEMENT APRÈS APPROBATION — préparation durable sans activation
|
||
login_v2_bundle=/var/tmp/labfy-greeter-mosaic-login-v2-0dvus1y_/bundle-r2
|
||
python3 -I -B "$login_v2_bundle/root/login-recovery-update.py" check \
|
||
"$login_v2_bundle/root" "$login_v2_bundle/user"
|
||
mkdir -p -m 0700 /home/fy59/.local/state/labfy-greeter-mosaic-login-v2
|
||
mkdir -m 0700 /home/fy59/.local/state/labfy-greeter-mosaic-login-v2/v2
|
||
install -m 0600 "$login_v2_bundle/user/"* \
|
||
/home/fy59/.local/state/labfy-greeter-mosaic-login-v2/v2/
|
||
sudo mkdir -m 0700 /var/lib/labfy-greeter/login-recovery-v2
|
||
sudo install -o root -g root -m 0600 "$login_v2_bundle/root/"* \
|
||
/var/lib/labfy-greeter/login-recovery-v2/
|
||
sudo python3 -I -B /var/lib/labfy-greeter/login-recovery-v2/login-recovery-update.py check
|
||
# Commande de publication complète, seulement après accord explicite :
|
||
sudo python3 -I -B /var/lib/labfy-greeter/login-recovery-v2/login-recovery-update.py apply
|
||
# Toujours après approbation ; recharge seulement, sans démarrer de service :
|
||
systemctl --user daemon-reload
|
||
```
|
||
|
||
Le lot user publie trois fichiers lanceur, le service et son lien dédié, et le
|
||
seul adaptateur QML canonique. Le lot root publie ensuite les quatre fichiers
|
||
V1 autorisés. Les deux bundles complets sont synchronisés avant toute mutation : sauvegardes,
|
||
manifestes, outils autonomes, coordinateur, seals/protected et journaux existants,
|
||
puis bundle et chaque ancêtre jusqu’à `/`. Le coordinateur exécute la barrière
|
||
user sous UID/verrou user avant son premier journal global. Une erreur de cette
|
||
barrière interdit toute publication et ne déclenche aucun rollback mutateur.
|
||
Les transactions autonomes possèdent également leur barrière. Verrou root
|
||
global, verrou user et journaux permettent la reprise. Chaque fichier est publié
|
||
par rename puis relu ; le lot multi-fichiers n'est pas une opération atomique
|
||
unique. Une erreur ordinaire restaure les deux sous-lots dans l'ordre inverse ;
|
||
si une restauration est empêchée, les deux sont tentées et le journal reste
|
||
`rolling-back`. Après arrêt brutal, le prochain apply restaure et s'arrête pour
|
||
vérification/nouvel essai. Aucun outil ne recharge/redémarre greetd, ne ferme une
|
||
session ou ne démarre UWSM/QuickShell. Conserver les copies durables jusqu'à
|
||
validation physique puis décision explicite de suppression ; le LAB peut alors
|
||
être archivé séparément. Une panne peut laisser un temporaire caché dans une
|
||
cible ; il n'est jamais un module chargé et exige inspection avant suppression.
|
||
|
||
## Premier essai et secours indépendant
|
||
|
||
Après installation approuvée : sauvegarder le travail, fermer volontairement
|
||
SwayFX au moment choisi, retrouver Labfy, garder Stable ou choisir explicitement
|
||
Mosaic avant le mot de passe. L'essai attendu est Mosaic autonome + QuickShell
|
||
+ Kitty de récupération. Vérifier alors barre, notifications, identité des
|
||
sockets, puis quitter Mosaic avec Super+Shift+E et choisir Stable sur Labfy.
|
||
Ce parcours complet est **NOT_RUN**. Ne pas verrouiller l'écran pendant ce smoke.
|
||
|
||
En cas de panne : Ctrl+Alt+F2, login console. Après fermeture de la session
|
||
graphique défaillante, un retour Stable explicite ne dépend ni du launcher
|
||
Mosaic ni de la préférence ni d'un ancien socket :
|
||
|
||
```sh
|
||
# Procédure manuelle APRÈS approbation, depuis console sans parent graphique :
|
||
exec /usr/bin/uwsm start sway.desktop
|
||
```
|
||
|
||
Si les fichiers publiés doivent être restaurés, depuis TTY2 et sans nouvelle
|
||
connexion concurrente :
|
||
|
||
```sh
|
||
sudo python3 -I -B /var/lib/labfy-greeter/login-recovery-v2/login-recovery-update.py rollback
|
||
systemctl --user daemon-reload
|
||
```
|
||
|
||
Le rollback n'exige ni binaire/LAB Mosaic ni IPC, et ne change pas default-id.
|
||
Si le sous-lot utilisateur est divergent/inaccessible, le secours greeter reste
|
||
indépendant :
|
||
|
||
```sh
|
||
sudo python3 -I -B /var/lib/labfy-greeter/login-recovery-v2/session-update.py \
|
||
rollback /var/lib/labfy-greeter/login-recovery-v2
|
||
# Restauration user indépendante, sans importer le lanceur Mosaic :
|
||
python3 -I -B /home/fy59/.local/state/labfy-greeter-mosaic-login-v2/v2/mosaic-user-update.py \
|
||
rollback /home/fy59/.local/state/labfy-greeter-mosaic-login-v2/v2
|
||
```
|
||
|
||
L'ancien greeter restauré utilise `start default` ; pour un secours indépendant
|
||
de cette préférence, utiliser la commande Stable explicite ci-dessus. Aucun
|
||
redémarrage greetd ou du PC n'est automatique ; une action de récupération
|
||
supplémentaire doit être décidée par l'utilisateur. Aucun secours ne dépend
|
||
du dépôt source ou de `/var/tmp` après promotion durable.
|
||
|
||
Aucun commit/push. Aucune modification du dépôt Mosaic, du moteur, PAM, config
|
||
Sway Stable, unité QuickShell Stable ou préférence UWSM. Le candidat temporaire
|
||
CORE-C V2 reste expérimental et refuse son lancement si sa copie disparaît.
|