[ADD] electron: own shell, portable Windows exe built under podman
The deliverable is a single-file portable executable whose Electron the
project updates itself. The shell keeps context isolation on, Node
integration off and the page sandboxed; one IPC channel returns the
folder the portable launcher publishes. The build runs in a no-Wine image
pinned by digest, relays no host variable, refuses to overwrite a built
number, removes what a failed build leaves, and accepts only the name
version.json gives. The spec stops claiming the portable target needs
Wine.
Checked: exe built in 86 s, resource FileVersion 2026.1005.1.0 and
© 2026 TechnoLibre; 109 node tests pass; two end-of-build mutations fail.
--- FR ---
[ADD] electron : coquille propre, exécutable portable construit sous podman
Le livrable est un exécutable portable à fichier unique, dont le projet
met lui-même Electron à jour. La coquille garde l'isolation de contexte,
coupe l'intégration de Node et isole la page ; un seul canal IPC rend le
dossier que publie le lanceur portable. La construction s'exécute dans
une image sans Wine épinglée par empreinte, ne relaie aucune variable de
l'hôte, refuse d'écraser un numéro construit, retire ce qu'un échec
laisse, et n'accepte que le nom que donne version.json. Le spec cesse
d'affirmer que la cible portable exige Wine.
Vérifié : exécutable construit en 86 s, ressource FileVersion
2026.1005.1.0 et © 2026 TechnoLibre ; 109 épreuves node passent ; deux
mutations du contrôle de fin échouent.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:32 -04:00
// © 2026 TechnoLibre (http://www.technolibre.ca)
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
// Le livrable tel qu'electron-builder.config.cjs le décrit : son nom (§ 18.2),
// sa forme (§ 16), ce qu'il emporte (§ 14.15) et l'identité inscrite dans sa
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
// ressource de version ; et le nom de l'application, un seul pour Electron,
// pour Capacitor et pour le titre de la fenêtre (§ 18.6). La configuration se
// charge ici comme electron-builder la charge, par require.
[ADD] electron: own shell, portable Windows exe built under podman
The deliverable is a single-file portable executable whose Electron the
project updates itself. The shell keeps context isolation on, Node
integration off and the page sandboxed; one IPC channel returns the
folder the portable launcher publishes. The build runs in a no-Wine image
pinned by digest, relays no host variable, refuses to overwrite a built
number, removes what a failed build leaves, and accepts only the name
version.json gives. The spec stops claiming the portable target needs
Wine.
Checked: exe built in 86 s, resource FileVersion 2026.1005.1.0 and
© 2026 TechnoLibre; 109 node tests pass; two end-of-build mutations fail.
--- FR ---
[ADD] electron : coquille propre, exécutable portable construit sous podman
Le livrable est un exécutable portable à fichier unique, dont le projet
met lui-même Electron à jour. La coquille garde l'isolation de contexte,
coupe l'intégration de Node et isole la page ; un seul canal IPC rend le
dossier que publie le lanceur portable. La construction s'exécute dans
une image sans Wine épinglée par empreinte, ne relaie aucune variable de
l'hôte, refuse d'écraser un numéro construit, retire ce qu'un échec
laisse, et n'accepte que le nom que donne version.json. Le spec cesse
d'affirmer que la cible portable exige Wine.
Vérifié : exécutable construit en 86 s, ressource FileVersion
2026.1005.1.0 et © 2026 TechnoLibre ; 109 épreuves node passent ; deux
mutations du contrôle de fin échouent.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:32 -04:00
import assert from 'node:assert/strict' ;
import { copyFileSync , mkdirSync , mkdtempSync , readdirSync , readFileSync , rmSync , writeFileSync } from 'node:fs' ;
import { createRequire , isBuiltin } from 'node:module' ;
import { tmpdir } from 'node:os' ;
import { dirname , join , relative , resolve , sep } from 'node:path' ;
import { fileURLToPath } from 'node:url' ;
import { deriver } from '../scripts/version.js' ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
import { titreAvecVersion } from '../src/interface/libelles.js' ;
import { VERSION } from '../src/version.genere.js' ;
import { chargements } from './chargements.js' ;
[ADD] electron: own shell, portable Windows exe built under podman
The deliverable is a single-file portable executable whose Electron the
project updates itself. The shell keeps context isolation on, Node
integration off and the page sandboxed; one IPC channel returns the
folder the portable launcher publishes. The build runs in a no-Wine image
pinned by digest, relays no host variable, refuses to overwrite a built
number, removes what a failed build leaves, and accepts only the name
version.json gives. The spec stops claiming the portable target needs
Wine.
Checked: exe built in 86 s, resource FileVersion 2026.1005.1.0 and
© 2026 TechnoLibre; 109 node tests pass; two end-of-build mutations fail.
--- FR ---
[ADD] electron : coquille propre, exécutable portable construit sous podman
Le livrable est un exécutable portable à fichier unique, dont le projet
met lui-même Electron à jour. La coquille garde l'isolation de contexte,
coupe l'intégration de Node et isole la page ; un seul canal IPC rend le
dossier que publie le lanceur portable. La construction s'exécute dans
une image sans Wine épinglée par empreinte, ne relaie aucune variable de
l'hôte, refuse d'écraser un numéro construit, retire ce qu'un échec
laisse, et n'accepte que le nom que donne version.json. Le spec cesse
d'affirmer que la cible portable exige Wine.
Vérifié : exécutable construit en 86 s, ressource FileVersion
2026.1005.1.0 et © 2026 TechnoLibre ; 109 épreuves node passent ; deux
mutations du contrôle de fin échouent.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:32 -04:00
import { describe , test } from './lanceur.js' ;
import { versionVoisine } from './version_voisine.js' ;
const RACINE = fileURLToPath ( new URL ( '..' , import . meta . url ) ) ;
const CONFIGURATION = 'electron-builder.config.cjs' ;
const lireJson = ( racine , chemin ) => JSON . parse ( readFileSync ( join ( racine , chemin ) , 'utf8' ) ) ;
const charger = ( racine ) => {
const chemin = join ( racine , CONFIGURATION ) ;
return createRequire ( chemin ) ( chemin ) ;
} ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
// Fichiers d'electron/ sous une racine, à toute profondeur, en chemins
// absolus.
const fichiersDElectron = ( racine ) =>
readdirSync ( join ( racine , 'electron' ) , { recursive : true , withFileTypes : true } )
[ADD] electron: own shell, portable Windows exe built under podman
The deliverable is a single-file portable executable whose Electron the
project updates itself. The shell keeps context isolation on, Node
integration off and the page sandboxed; one IPC channel returns the
folder the portable launcher publishes. The build runs in a no-Wine image
pinned by digest, relays no host variable, refuses to overwrite a built
number, removes what a failed build leaves, and accepts only the name
version.json gives. The spec stops claiming the portable target needs
Wine.
Checked: exe built in 86 s, resource FileVersion 2026.1005.1.0 and
© 2026 TechnoLibre; 109 node tests pass; two end-of-build mutations fail.
--- FR ---
[ADD] electron : coquille propre, exécutable portable construit sous podman
Le livrable est un exécutable portable à fichier unique, dont le projet
met lui-même Electron à jour. La coquille garde l'isolation de contexte,
coupe l'intégration de Node et isole la page ; un seul canal IPC rend le
dossier que publie le lanceur portable. La construction s'exécute dans
une image sans Wine épinglée par empreinte, ne relaie aucune variable de
l'hôte, refuse d'écraser un numéro construit, retire ce qu'un échec
laisse, et n'accepte que le nom que donne version.json. Le spec cesse
d'affirmer que la cible portable exige Wine.
Vérifié : exécutable construit en 86 s, ressource FileVersion
2026.1005.1.0 et © 2026 TechnoLibre ; 109 épreuves node passent ; deux
mutations du contrôle de fin échouent.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:32 -04:00
. filter ( ( entree ) => entree . isFile ( ) )
. map ( ( entree ) => join ( entree . parentPath , entree . name ) ) ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
// Raison de refuser le chargement que demande un fichier du répertoire
// electron donné, ou null quand il reste dans le paquet : electron, un module
// de Node hors du lanceur d'épreuves, ou un fichier de ce répertoire. Le
// paquet n'emporte ni node_modules ni rien de test/ : un chargement qui en
// sort échoue au démarrage de l'exécutable. Un chargement calculé ne se
// vérifie pas d'ici.
function raisonDeRefus ( electron , { fichier , specificateur , argument } ) {
[ADD] electron: own shell, portable Windows exe built under podman
The deliverable is a single-file portable executable whose Electron the
project updates itself. The shell keeps context isolation on, Node
integration off and the page sandboxed; one IPC channel returns the
folder the portable launcher publishes. The build runs in a no-Wine image
pinned by digest, relays no host variable, refuses to overwrite a built
number, removes what a failed build leaves, and accepts only the name
version.json gives. The spec stops claiming the portable target needs
Wine.
Checked: exe built in 86 s, resource FileVersion 2026.1005.1.0 and
© 2026 TechnoLibre; 109 node tests pass; two end-of-build mutations fail.
--- FR ---
[ADD] electron : coquille propre, exécutable portable construit sous podman
Le livrable est un exécutable portable à fichier unique, dont le projet
met lui-même Electron à jour. La coquille garde l'isolation de contexte,
coupe l'intégration de Node et isole la page ; un seul canal IPC rend le
dossier que publie le lanceur portable. La construction s'exécute dans
une image sans Wine épinglée par empreinte, ne relaie aucune variable de
l'hôte, refuse d'écraser un numéro construit, retire ce qu'un échec
laisse, et n'accepte que le nom que donne version.json. Le spec cesse
d'affirmer que la cible portable exige Wine.
Vérifié : exécutable construit en 86 s, ressource FileVersion
2026.1005.1.0 et © 2026 TechnoLibre ; 109 épreuves node passent ; deux
mutations du contrôle de fin échouent.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:32 -04:00
if ( specificateur === undefined ) return ` argument calculé, ${ argument } : il ne se vérifie pas ` ;
if ( /^(?:vitest|node:test)(?:\/|$)|^@vitest\// . test ( specificateur ) ) return "lanceur d'épreuves" ;
if ( specificateur === 'electron' || isBuiltin ( specificateur ) ) return null ;
if ( /^\.{1,2}(?:\/|$)/ . test ( specificateur ) ) {
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
return resolve ( dirname ( fichier ) , specificateur ) . startsWith ( ` ${ electron } ${ sep } ` ) ? null : "hors d'electron/" ;
[ADD] electron: own shell, portable Windows exe built under podman
The deliverable is a single-file portable executable whose Electron the
project updates itself. The shell keeps context isolation on, Node
integration off and the page sandboxed; one IPC channel returns the
folder the portable launcher publishes. The build runs in a no-Wine image
pinned by digest, relays no host variable, refuses to overwrite a built
number, removes what a failed build leaves, and accepts only the name
version.json gives. The spec stops claiming the portable target needs
Wine.
Checked: exe built in 86 s, resource FileVersion 2026.1005.1.0 and
© 2026 TechnoLibre; 109 node tests pass; two end-of-build mutations fail.
--- FR ---
[ADD] electron : coquille propre, exécutable portable construit sous podman
Le livrable est un exécutable portable à fichier unique, dont le projet
met lui-même Electron à jour. La coquille garde l'isolation de contexte,
coupe l'intégration de Node et isole la page ; un seul canal IPC rend le
dossier que publie le lanceur portable. La construction s'exécute dans
une image sans Wine épinglée par empreinte, ne relaie aucune variable de
l'hôte, refuse d'écraser un numéro construit, retire ce qu'un échec
laisse, et n'accepte que le nom que donne version.json. Le spec cesse
d'affirmer que la cible portable exige Wine.
Vérifié : exécutable construit en 86 s, ressource FileVersion
2026.1005.1.0 et © 2026 TechnoLibre ; 109 épreuves node passent ; deux
mutations du contrôle de fin échouent.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:32 -04:00
}
return "hors du paquet, qui n'emporte aucun node_modules" ;
}
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
// Chargements refusés des fichiers d'electron/ sous une racine, par fichier
// puis dans l'ordre du texte : chacun est { fichier, specificateur, raison }
// ou { fichier, argument, raison }, fichier relatif à la racine. Lève quand
// electron/ n'a aucun fichier, ou quand ses fichiers ne demandent aucun
// chargement.
function refusDElectron ( racine ) {
const electron = join ( racine , 'electron' ) ;
const fichiers = fichiersDElectron ( racine ) . sort ( ) ;
assert . ok ( fichiers . length > 0 , 'electron/ ne contient aucun fichier' ) ;
const demandes = fichiers . flatMap ( ( fichier ) =>
chargements ( readFileSync ( fichier , 'utf8' ) ) . map ( ( { specificateur , argument } ) =>
specificateur === undefined ? { fichier , argument } : { fichier , specificateur } ,
) ,
) ;
assert . ok ( demandes . length > 0 , 'aucun chargement relevé dans electron/' ) ;
return demandes
. map ( ( demande ) => ( { ... demande , fichier : relative ( racine , demande . fichier ) , raison : raisonDeRefus ( electron , demande ) } ) )
. filter ( ( { raison } ) => raison !== null ) ;
}
[ADD] electron: own shell, portable Windows exe built under podman
The deliverable is a single-file portable executable whose Electron the
project updates itself. The shell keeps context isolation on, Node
integration off and the page sandboxed; one IPC channel returns the
folder the portable launcher publishes. The build runs in a no-Wine image
pinned by digest, relays no host variable, refuses to overwrite a built
number, removes what a failed build leaves, and accepts only the name
version.json gives. The spec stops claiming the portable target needs
Wine.
Checked: exe built in 86 s, resource FileVersion 2026.1005.1.0 and
© 2026 TechnoLibre; 109 node tests pass; two end-of-build mutations fail.
--- FR ---
[ADD] electron : coquille propre, exécutable portable construit sous podman
Le livrable est un exécutable portable à fichier unique, dont le projet
met lui-même Electron à jour. La coquille garde l'isolation de contexte,
coupe l'intégration de Node et isole la page ; un seul canal IPC rend le
dossier que publie le lanceur portable. La construction s'exécute dans
une image sans Wine épinglée par empreinte, ne relaie aucune variable de
l'hôte, refuse d'écraser un numéro construit, retire ce qu'un échec
laisse, et n'accepte que le nom que donne version.json. Le spec cesse
d'affirmer que la cible portable exige Wine.
Vérifié : exécutable construit en 86 s, ressource FileVersion
2026.1005.1.0 et © 2026 TechnoLibre ; 109 épreuves node passent ; deux
mutations du contrôle de fin échouent.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:32 -04:00
describe ( 'livrable : nom' , ( ) => {
test ( 'le nom est celui que deriver calcule depuis version.json (§ 18.2)' , ( ) => {
const { version } = lireJson ( RACINE , 'version.json' ) ;
assert . equal ( charger ( RACINE ) . artifactName , deriver ( version ) . nomFichier ) ;
} ) ;
test ( "le nom suit version.json : la configuration ne l'écrit pas elle-même" , ( ) => {
// Un arbre où version.json porte la version voisine. La configuration et
// scripts/version.js y sont recopiés tels quels.
const { version } = lireJson ( RACINE , 'version.json' ) ;
const autre = versionVoisine ( version ) ;
const arbre = mkdtempSync ( join ( tmpdir ( ) , 'livrable-' ) ) ;
try {
for ( const chemin of [ CONFIGURATION , 'scripts/version.js' , 'package.json' , 'capacitor.config.json' ] ) {
mkdirSync ( dirname ( join ( arbre , chemin ) ) , { recursive : true } ) ;
copyFileSync ( join ( RACINE , chemin ) , join ( arbre , chemin ) ) ;
}
writeFileSync ( join ( arbre , 'version.json' ) , ` ${ JSON . stringify ( { version : autre } )} \n ` ) ;
const nom = charger ( arbre ) . artifactName ;
assert . equal ( nom , deriver ( autre ) . nomFichier ) ;
assert . notEqual ( nom , deriver ( version ) . nomFichier ) ;
} finally {
rmSync ( arbre , { recursive : true , force : true } ) ;
}
} ) ;
} ) ;
describe ( 'livrable : forme et contenu' , ( ) => {
test ( 'un exécutable portable à fichier unique, pour Windows x64 : jamais un installateur (§ 16)' , ( ) => {
assert . deepEqual ( charger ( RACINE ) . win , { target : [ { target : 'portable' , arch : [ 'x64' ] } ] } ) ;
} ) ;
test ( "sortie dans dist-electron/ ; le paquet n'emporte que la page, la coquille et package.json" , ( ) => {
const configuration = charger ( RACINE ) ;
assert . deepEqual ( configuration . directories , { output : 'dist-electron' } ) ;
assert . deepEqual ( configuration . files , [ 'www/**' , 'electron/**' , 'package.json' ] ) ;
} ) ;
test ( "la configuration n'a pas d'autre clé que celles que ces épreuves examinent (§ 14.15, § 18.1)" , ( ) => {
// Une clé de plus change ce que le paquet emporte (extraResources,
// extraFiles, asar) ou la version qu'il porte (buildVersion, buildNumber),
// et aucune épreuve ne la lirait : elle échoue ici jusqu'à sa revue. Les
// épreuves de chaque clé comparent sa valeur entière, si bien qu'une clé
// ajoutée plus bas, sous win ou directories, échoue aussi.
assert . deepEqual ( Object . keys ( charger ( RACINE ) ) . sort ( ) , [
'appId' ,
'artifactName' ,
'copyright' ,
'directories' ,
'files' ,
'productName' ,
'win' ,
] ) ;
} ) ;
test ( "electron/, que le paquet emporte en entier, ne contient aucune épreuve (§ 14.15)" , ( ) => {
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
const fichiers = fichiersDElectron ( RACINE ) ;
[ADD] electron: own shell, portable Windows exe built under podman
The deliverable is a single-file portable executable whose Electron the
project updates itself. The shell keeps context isolation on, Node
integration off and the page sandboxed; one IPC channel returns the
folder the portable launcher publishes. The build runs in a no-Wine image
pinned by digest, relays no host variable, refuses to overwrite a built
number, removes what a failed build leaves, and accepts only the name
version.json gives. The spec stops claiming the portable target needs
Wine.
Checked: exe built in 86 s, resource FileVersion 2026.1005.1.0 and
© 2026 TechnoLibre; 109 node tests pass; two end-of-build mutations fail.
--- FR ---
[ADD] electron : coquille propre, exécutable portable construit sous podman
Le livrable est un exécutable portable à fichier unique, dont le projet
met lui-même Electron à jour. La coquille garde l'isolation de contexte,
coupe l'intégration de Node et isole la page ; un seul canal IPC rend le
dossier que publie le lanceur portable. La construction s'exécute dans
une image sans Wine épinglée par empreinte, ne relaie aucune variable de
l'hôte, refuse d'écraser un numéro construit, retire ce qu'un échec
laisse, et n'accepte que le nom que donne version.json. Le spec cesse
d'affirmer que la cible portable exige Wine.
Vérifié : exécutable construit en 86 s, ressource FileVersion
2026.1005.1.0 et © 2026 TechnoLibre ; 109 épreuves node passent ; deux
mutations du contrôle de fin échouent.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:32 -04:00
assert . ok ( fichiers . length > 0 , 'electron/ ne contient aucun fichier' ) ;
assert . deepEqual ( fichiers . filter ( ( chemin ) => / \ . test \ . [ cm ] ? js$ / . test ( chemin ) ) , [ ] ) ;
} ) ;
test ( "electron/ ne charge qu'electron, Node et ses propres fichiers : ni épreuve, ni lanceur, ni dépendance (§ 14.9)" , ( ) => {
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
assert . deepEqual ( refusDElectron ( RACINE ) , [ ] ) ;
} ) ;
test ( "la garde d'electron/ relève chaque chargement refusé, import à commentaire entre ses accolades compris, et admet electron, Node et les fichiers d'electron/" , ( ) => {
const arbre = mkdtempSync ( join ( tmpdir ( ) , 'livrable-' ) ) ;
try {
mkdirSync ( join ( arbre , 'electron' ) ) ;
writeFileSync ( join ( arbre , 'electron' , 'main.js' ) , [
"import { app } from 'electron';" ,
"import { join } from 'node:path';" ,
'import {' ,
" // l'API des épreuves" ,
' test,' ,
"} from 'vitest';" ,
'import {' ,
" // l'aide d'à côté" ,
' aide,' ,
"} from '../test/aide.js';" ,
"import { voisin } from './voisin.js';" ,
"const prechargement = require('./preload.cjs');" ,
'const module = require(chemin);' ,
"const { mount } = await import('svelte');" ,
] . join ( '\n' ) ) ;
writeFileSync ( join ( arbre , 'electron' , 'preload.cjs' ) , "const { contextBridge } = require('electron');\n" ) ;
assert . deepEqual ( refusDElectron ( arbre ) , [
{ fichier : join ( 'electron' , 'main.js' ) , specificateur : 'vitest' , raison : "lanceur d'épreuves" } ,
{ fichier : join ( 'electron' , 'main.js' ) , specificateur : '../test/aide.js' , raison : "hors d'electron/" } ,
{ fichier : join ( 'electron' , 'main.js' ) , argument : 'chemin' , raison : 'argument calculé, chemin : il ne se vérifie pas' } ,
{ fichier : join ( 'electron' , 'main.js' ) , specificateur : 'svelte' , raison : "hors du paquet, qui n'emporte aucun node_modules" } ,
] ) ;
writeFileSync ( join ( arbre , 'electron' , 'main.js' ) , '// Aucun chargement.\n' ) ;
writeFileSync ( join ( arbre , 'electron' , 'preload.cjs' ) , '' ) ;
assert . throws ( ( ) => refusDElectron ( arbre ) , /aucun chargement relevé dans electron\// ) ;
} finally {
rmSync ( arbre , { recursive : true , force : true } ) ;
}
[ADD] electron: own shell, portable Windows exe built under podman
The deliverable is a single-file portable executable whose Electron the
project updates itself. The shell keeps context isolation on, Node
integration off and the page sandboxed; one IPC channel returns the
folder the portable launcher publishes. The build runs in a no-Wine image
pinned by digest, relays no host variable, refuses to overwrite a built
number, removes what a failed build leaves, and accepts only the name
version.json gives. The spec stops claiming the portable target needs
Wine.
Checked: exe built in 86 s, resource FileVersion 2026.1005.1.0 and
© 2026 TechnoLibre; 109 node tests pass; two end-of-build mutations fail.
--- FR ---
[ADD] electron : coquille propre, exécutable portable construit sous podman
Le livrable est un exécutable portable à fichier unique, dont le projet
met lui-même Electron à jour. La coquille garde l'isolation de contexte,
coupe l'intégration de Node et isole la page ; un seul canal IPC rend le
dossier que publie le lanceur portable. La construction s'exécute dans
une image sans Wine épinglée par empreinte, ne relaie aucune variable de
l'hôte, refuse d'écraser un numéro construit, retire ce qu'un échec
laisse, et n'accepte que le nom que donne version.json. Le spec cesse
d'affirmer que la cible portable exige Wine.
Vérifié : exécutable construit en 86 s, ressource FileVersion
2026.1005.1.0 et © 2026 TechnoLibre ; 109 épreuves node passent ; deux
mutations du contrôle de fin échouent.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:32 -04:00
} ) ;
test ( "package.json ne déclare aucune dépendance d'exécution : le paquet n'emporte aucun node_modules" , ( ) => {
const paquet = lireJson ( RACINE , 'package.json' ) ;
assert . equal ( paquet . dependencies , undefined ) ;
assert . equal ( paquet . optionalDependencies , undefined ) ;
assert . match ( paquet . devDependencies ? . electron ? ? '' , /^\^44(\.|$)/ ) ;
assert . match ( paquet . devDependencies ? . [ 'electron-builder' ] ? ? '' , /^\^26(\.|$)/ ) ;
assert . equal ( paquet . main , 'electron/main.js' ) ;
} ) ;
} ) ;
describe ( 'livrable : identité' , ( ) => {
test ( "l'identifiant est celui de Capacitor, le nom de produit celui de package.json" , ( ) => {
const configuration = charger ( RACINE ) ;
assert . equal ( configuration . appId , lireJson ( RACINE , 'capacitor.config.json' ) . appId ) ;
assert . equal ( configuration . productName , lireJson ( RACINE , 'package.json' ) . productName ) ;
// Une source muette rend undefined des deux côtés de l'égalité, et
// electron-builder retombe alors sur ses valeurs par défaut : chaque
// valeur a aussi sa forme.
assert . match ( configuration . appId ? ? '' , /^[a-z][a-z0-9]*(\.[a-z][a-z0-9]*)+$/ ) ;
assert . ok (
typeof configuration . productName === 'string' && configuration . productName . trim ( ) !== '' ,
` productName vide : ${ configuration . productName } ` ,
) ;
} ) ;
test ( 'le titulaire entre dans la ressource de version, champ LegalCopyright' , ( ) => {
assert . equal ( charger ( RACINE ) . copyright , '© 2026 TechnoLibre' ) ;
} ) ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
test ( "le nom de l'application est un seul : productName de package.json, appName de Capacitor, celui du titre de la fenêtre (§ 18.6)" , ( ) => {
// electron-builder nomme l'application d'après productName, Capacitor
// d'après appName, et la page pose le titre de la fenêtre par
// titreAvecVersion : le nom suivi de la version affichée, que l'épreuve
// retire pour lire le nom.
const titre = titreAvecVersion ( VERSION . affichee ) ;
const suite = ` — ${ VERSION . affichee } ` ;
assert . ok ( titre . endsWith ( suite ) , ` le titre « ${ titre } » ne finit pas sur « ${ suite } » ` ) ;
const nom = titre . slice ( 0 , - suite . length ) ;
assert . ok ( nom . trim ( ) !== '' , ` le titre « ${ titre } » ne porte aucun nom ` ) ;
assert . deepEqual (
{
productName : lireJson ( RACINE , 'package.json' ) . productName ,
appName : lireJson ( RACINE , 'capacitor.config.json' ) . appName ,
} ,
{ productName : nom , appName : nom } ,
) ;
} ) ;
[ADD] electron: own shell, portable Windows exe built under podman
The deliverable is a single-file portable executable whose Electron the
project updates itself. The shell keeps context isolation on, Node
integration off and the page sandboxed; one IPC channel returns the
folder the portable launcher publishes. The build runs in a no-Wine image
pinned by digest, relays no host variable, refuses to overwrite a built
number, removes what a failed build leaves, and accepts only the name
version.json gives. The spec stops claiming the portable target needs
Wine.
Checked: exe built in 86 s, resource FileVersion 2026.1005.1.0 and
© 2026 TechnoLibre; 109 node tests pass; two end-of-build mutations fail.
--- FR ---
[ADD] electron : coquille propre, exécutable portable construit sous podman
Le livrable est un exécutable portable à fichier unique, dont le projet
met lui-même Electron à jour. La coquille garde l'isolation de contexte,
coupe l'intégration de Node et isole la page ; un seul canal IPC rend le
dossier que publie le lanceur portable. La construction s'exécute dans
une image sans Wine épinglée par empreinte, ne relaie aucune variable de
l'hôte, refuse d'écraser un numéro construit, retire ce qu'un échec
laisse, et n'accepte que le nom que donne version.json. Le spec cesse
d'affirmer que la cible portable exige Wine.
Vérifié : exécutable construit en 86 s, ressource FileVersion
2026.1005.1.0 et © 2026 TechnoLibre ; 109 épreuves node passent ; deux
mutations du contrôle de fin échouent.
Assisted-by: Claude Opus 5.5
2026-10-05 13:13:32 -04:00
} ) ;