@mostajs/licence-guard
v0.2.1
Published
La licence d'une application entre deux démarrages : range le document signé, rend un verdict HORS LIGNE, et ne coupe jamais rien. Complète @mostajs/licensing, qui ne persiste rien.
Downloads
275
Maintainers
Readme
@mostajs/licence-guard
Auteur : Dr Hamid MADANI [email protected] · AGPL-3.0-or-later
La licence d'une application entre deux démarrages.
@mostajs/licensing fait déjà tout le dialogue avec le serveur de licences — demander, télécharger,
vérifier la signature RSA, contrôler le projet et l'échéance, notifier l'activation. Il le dit
lui-même : « Ne persiste rien (à la charge de l'appelant). »
C'est cet appelant qui manquait. Sans lui, une instance activée redémarre en « non activée » : le droit est valide, le document est signé, et il a disparu avec le processus. Une université coupée du réseau ne pourrait plus jamais prouver le sien.
Ce module range la licence signée, rend un verdict hors ligne, et n'invente aucune règle :
le verdict est celui de checkLicense, donc du code que le serveur utilise lui-même.
Il ne peut pas couper l'application
Il rend un état. Il ne lève pas pour bloquer, ne quitte pas le processus, n'intercepte aucune
route. enforce n'est qu'un champ de cet état, que l'interface affiche — jamais un comportement
d'ici. Une garde qui pourrait couper finirait un jour par couper : une instance installée dans
une université porte des dossiers d'étudiants et des actes officiels, et l'arrêter pour un
différend administratif punirait l'étudiant.
Les trois gardes
1. On ne range jamais un document mal signé. Sans cela, un serveur usurpé (DNS détourné, faux certificat) ou simplement en panne remplacerait un cache valide par un refus — et l'instance resterait dessus, indéfiniment, y compris hors ligne. Un déni de service durable, obtenu sans casser la moindre signature.
2. Une révocation signée, elle, entre. Elle est re-signée par l'autorité, donc elle passe la garde n°1. C'est toute la différence entre « le serveur dit non » et « l'autorité a signé un non » — seul le second est opposable hors ligne.
3. Serveur injoignable ⇒ le cache reste en vigueur. Une coupure réseau n'est pas une perte de droit, et le message le dit au lieu de laisser croire le contraire.
Emploi
import { createLicenceGuard } from '@mostajs/licence-guard';
import { fileCache } from '@mostajs/licence-guard/file-cache';
const licence = createLicenceGuard({
baseUrl: process.env.LICENCE_SERVER, // https://licences.amia.fr
project: process.env.LICENCE_PROJECT, // le `project` SIGNÉ — la casse compte
publicKeyPem: readFileSync(process.env.LICENCE_PUBLIC_KEY_FILE, 'utf8'),
cache: fileCache('data/licence.signed.json'),
machineId: hostname(),
});
licence.status(); // { valid, status, reason, expiresAt, daysLeft, source, enforce, key, company }
await licence.activate(code) // télécharge, vérifie, range, notifie
await licence.refresh() // redemande le même document — c'est par là qu'une révocation arrive
licence.key() // la clé d'activation, pour s'authentifier auprès d'un centralL'état a exactement la forme qu'attend @mostajs/licensing-ui-html
(licenseStatusView, licenseBadge).
Le cache est un port, pas node:fs : le cœur du module n'écrit rien sur le disque, si bien
qu'aucun test ne peut hériter du fichier d'un autre. L'adaptateur disque est un point d'entrée
séparé — et il écrit atomiquement (fichier temporaire puis rename), parce qu'une coupure de
courant pendant l'écriture laisserait un demi-document, et l'instance repartirait en « aucune
licence » avec un droit pourtant intact.
npm test # 12 tests (@mostajs/mjs-unit)