Installe l'archive self-contained publiée en release du dépôt du code, amd64 ou arm64 selon la machine. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
182 lines
9.1 KiB
TOML
182 lines
9.1 KiB
TOML
#:schema https://raw.githubusercontent.com/YunoHost/apps/master/schemas/manifest.v2.schema.json
|
|
|
|
packaging_format = 2
|
|
|
|
id = "mabibli"
|
|
name = "MaBibli"
|
|
description.fr = "Gestion de bibliothèque personnelle : catalogue, prêts et scan ISBN"
|
|
description.en = "Personal library manager: catalogue, loans and ISBN scanning"
|
|
|
|
version = "1.0.0~ynh1"
|
|
|
|
maintainers = ["mathieu"]
|
|
|
|
[upstream]
|
|
license = "AGPL-3.0-or-later"
|
|
code = "https://git.akbar.nohost.me/mathieu/mabibli"
|
|
|
|
[integration]
|
|
yunohost = ">= 12.1.38"
|
|
helpers_version = "2.1"
|
|
|
|
# ⚠️ Une architecture déclarée ici DOIT avoir son archive dans la release : YunoHost
|
|
# choisit `<arch>.url` d'après la machine, et une URL manquante échoue chez celui qui
|
|
# installe, dans `ynh_setup_source`. `build/publier.sh` compile les deux à chaque
|
|
# publication, précisément pour qu'aucune des deux ne puisse être oubliée.
|
|
#
|
|
# armhf (32 bits) n'est PAS déclarée : .NET ne la prend plus en charge.
|
|
architectures = ["amd64", "arm64"]
|
|
|
|
# Une seule instance : la bibliothèque est commune au foyer (CLAUDE.md, « Portée des
|
|
# données »). Deux instances voudraient dire deux collections étanches, ce qui est
|
|
# exactement ce que le projet a écarté.
|
|
multi_instance = false
|
|
|
|
# L'application ne parle pas à LDAP : elle lit l'identité dans les en-têtes que
|
|
# SSOwat injecte. C'est bien une intégration SSO, mais pas une intégration LDAP.
|
|
ldap = false
|
|
sso = true
|
|
|
|
# ~170 Mo de publish self-contained (runtime .NET embarqué), plus la base et la marge
|
|
# de décompression de l'archive.
|
|
disk = "500M"
|
|
|
|
# ⚠️ `ram.build` ne désigne AUCUNE compilation : rien n'est compilé sur le serveur, c'est
|
|
# tout l'intérêt du self-contained. Il couvre le téléchargement et la décompression de
|
|
# l'archive de 69 Mo. Ne pas aller chercher la valeur du côté d'un build .NET.
|
|
ram.build = "50M"
|
|
|
|
# Mesuré sur le serveur le 2026-08-22, service en marche :
|
|
# cat /sys/fs/cgroup/system.slice/mabibli.service/memory.peak -> 208 793 600 o
|
|
# soit 199,1 Mio de pic, contre 200M déclarés jusqu'ici : 0,4 % de marge, c'est-à-dire
|
|
# aucune. Porté à 256M.
|
|
#
|
|
# ⚠️ `systemctl show -p MemoryPeak` ne renvoie RIEN sur ce serveur — la commande réussit
|
|
# en silence et l'on croit lire un pic là où l'on ne lit rien. Passer par le cgroup.
|
|
#
|
|
# ⚠️ Le chiffre MAJORE le besoin : `memory.peak` compte le cache de fichiers, donc une
|
|
# part des 69 Mo de binaire mappé, récupérable sous pression — et le GC de .NET se serre
|
|
# sur une machine étroite. Mais YunoHost compare une déclaration statique à la RAM
|
|
# disponible, sans faire cette nuance. L'asymétrie tranche : un refus d'installation est
|
|
# visible et se contourne, un OOM survient plus tard, sous une opération lourde, sans que
|
|
# rien ne désigne la cause.
|
|
#
|
|
# ⚠️ Le pic n'est PAS le lookup ISBN, contrairement à l'intuition — une notice. C'est
|
|
# « Nouveautés » sur un auteur très réédité : jusqu'à dix pages de 100 notices SRU en
|
|
# parallèle, plus le catalogue entier chargé pour le rapprochement. Ce cas-là n'a pas
|
|
# encore été mesuré, et il croît avec la taille de la bibliothèque : à reprendre le jour
|
|
# où le fonds aura beaucoup grossi.
|
|
ram.runtime = "256M"
|
|
|
|
[install]
|
|
|
|
[install.domain]
|
|
type = "domain"
|
|
|
|
# Pas de question `path` : MaBibli s'installe sur un domaine entier.
|
|
#
|
|
# Ce n'est pas un oubli. Le client Blazor WebAssembly fige son `<base href="/">`
|
|
# et les empreintes de `service-worker-assets.js` **à la compilation**. Servir
|
|
# l'application sous un sous-chemin demanderait de réécrire `index.html` sur le
|
|
# serveur, ce qui invaliderait les empreintes d'intégrité du service worker et
|
|
# casserait le mode hors-ligne. Comme le paquet ne compile rien sur le serveur,
|
|
# la seule option honnête est le domaine entier.
|
|
#
|
|
# Conséquence côté YunoHost : `resources.permissions.main.url` étant une chaîne,
|
|
# le cœur classe l'app en « full_domain » et refusera un changement d'URL vers
|
|
# un sous-chemin.
|
|
|
|
# Pas de question `init_main_permission` : l'accès est fixé à `all_users` par la
|
|
# ressource `permissions` ci-dessous, et l'installation ne demande donc rien.
|
|
#
|
|
# Vérifié dans le cœur YunoHost (`src/utils/resources.py`) :
|
|
#
|
|
# init_allowed = infos["allowed"] or self.get_setting(f"init_{perm}_permission") or []
|
|
#
|
|
# `allowed` l'emporte sur la question ; garder la question l'aurait donc posée pour
|
|
# rien, en laissant croire que la réponse comptait.
|
|
#
|
|
# ⚠️ Ce code ne s'exécute qu'à la CRÉATION de la permission. Une montée de version ne
|
|
# réaligne rien : un accès élargi à la main le reste.
|
|
|
|
[resources]
|
|
|
|
[resources.sources.main]
|
|
# Archives **déjà compilées** (publish self-contained), produites par
|
|
# `build/publier.sh` et déposées en release sur le Gitea de l'utilisateur.
|
|
# Le SDK .NET n'est jamais installé sur le serveur : c'est tout l'intérêt du
|
|
# self-contained (CLAUDE.md, « Décisions techniques actées »).
|
|
#
|
|
# YunoHost retient la ligne correspondant à l'architecture de la machine.
|
|
#
|
|
# ⚠️ Ces quatre valeurs sont réécrites par `build/publier.sh`, jamais à la main.
|
|
amd64.url = "https://git.akbar.nohost.me/mathieu/mabibli/releases/download/v1.0.0/mabibli-1.0.0-linux-x64.tar.gz"
|
|
amd64.sha256 = "2a405d58fad19faf2860857de7305a37918f903f528fc190d71f6b150f5da332"
|
|
arm64.url = "https://git.akbar.nohost.me/mathieu/mabibli/releases/download/v1.0.0/mabibli-1.0.0-linux-arm64.tar.gz"
|
|
arm64.sha256 = "51de1819543389a431861ed25099738937092d5947e7ce54afc0f348968b9dfd"
|
|
|
|
# L'archive dépose ses fichiers à la racine, sans dossier intermédiaire.
|
|
in_subdir = false
|
|
|
|
# Pas d'`autoupdate` : les releases sont déposées à la main sur un Gitea privé,
|
|
# aucune stratégie amont connue de YunoHost ne s'y applique.
|
|
|
|
[resources.system_user]
|
|
|
|
[resources.install_dir]
|
|
# Le service tourne sous `mabibli` mais ne doit **pas** pouvoir réécrire ses
|
|
# propres binaires : propriétaire root, application en lecture seule. Cela va de
|
|
# pair avec `ProtectSystem=strict` dans l'unité systemd.
|
|
owner = "root:rwx"
|
|
group = "__APP__:rx"
|
|
|
|
[resources.data_dir]
|
|
# La base SQLite vit ici, et **pas** à côté du binaire : c'est ce qui permet à une
|
|
# mise à jour de remplacer intégralement `install_dir` sans toucher aux données.
|
|
owner = "__APP__:rwx"
|
|
group = "__APP__:rx"
|
|
|
|
[resources.permissions]
|
|
# Toute l'application derrière le SSO, `/api` compris : la bibliothèque est
|
|
# familiale, rien n'a vocation à être public. `auth_header` vaut `true` par
|
|
# défaut, c'est lui qui autorise SSOwat à injecter `YNH_USER` — sans quoi
|
|
# l'application ne saurait jamais qui la consulte.
|
|
main.url = "/"
|
|
main.auth_header = true
|
|
|
|
# ╔══════════════════════════════════════════════════════════════════════════════╗
|
|
# ║ ⚠️ MaBibli EST UNE APPLICATION PRIVÉE. NE JAMAIS L'OUVRIR AUX `visitors`. ║
|
|
# ╚══════════════════════════════════════════════════════════════════════════════╝
|
|
#
|
|
# Ce n'est pas une préférence de confidentialité, c'est une propriété du code, et
|
|
# elle vaut sur les DEUX moitiés de l'application :
|
|
#
|
|
# • L'application n'a AUCUNE authentification propre. Elle lit `YNH_USER`, un
|
|
# en-tête que SSOwat injecte, et fait confiance à ce qu'il contient. Ouverte aux
|
|
# visiteurs, il n'y a plus personne pour l'écraser : tout ce qui est PERSONNEL
|
|
# (statuts de lecture, liste d'envies) devient lisible et modifiable par le
|
|
# premier venu. C'est la même frontière que « le service n'écoute que sur
|
|
# 127.0.0.1 » — SSOwat n'est pas un confort, c'est la seule porte.
|
|
#
|
|
# • Il n'existe AUCUNE notion d'écriture réservée. Toute personne autorisée peut
|
|
# ajouter, modifier et SUPPRIMER n'importe quel livre du catalogue commun, ainsi
|
|
# que noter un prêt ou son retour. C'est délibéré — un foyer, pas un service
|
|
# public — et cela suppose que les personnes autorisées se connaissent.
|
|
#
|
|
# `all_users` est donc le plus large qui ait du sens : les comptes du serveur.
|
|
# Restreindre davantage (un groupe dédié) est légitime ; élargir ne l'est pas.
|
|
#
|
|
# ⚠️ Volontairement PAS `protected = true` : l'administrateur du serveur reste
|
|
# maître de ses permissions, et peut vouloir restreindre à un groupe. C'est
|
|
# l'élargissement qui est un contresens, pas le réglage lui-même.
|
|
main.allowed = "all_users"
|
|
|
|
[resources.ports]
|
|
# Port interne uniquement. `exposed` vaut `false` par défaut : le pare-feu reste
|
|
# fermé, et l'unité systemd n'écoute que sur 127.0.0.1.
|
|
|
|
[resources.apt]
|
|
# `sqlite3` sert aux sauvegardes : la base est en mode WAL (vérifié), un simple
|
|
# `cp` du fichier `.db` ne suffit pas. Voir `scripts/backup`.
|
|
packages = "sqlite3"
|