1) { echo " Plusieurs candidats : " . implode(', ', array_map('basename', $candidates)) . "\n"; } continue; } } $size = filesize($zip); echo " [hash] $version : " . basename($zip) . " ($size octets)..."; $sha = hash_file('sha256', $zip); echo " sha256={$sha}\n"; $v['download']['sizeBytes'] = $size; $v['download']['sha256'] = $sha; $updated++; $hashedVersions[] = $version; } unset($v); // Met à jour automatiquement le champ `latest` avec la plus haute version // effectivement uploadée (celle pour laquelle on a calculé un hash). if (!empty($hashedVersions)) { usort($hashedVersions, function ($a, $b) { return version_compare($a, $b); }); $newLatest = end($hashedVersions); if (($manifest['latest'] ?? null) !== $newLatest) { echo " [latest] {$manifest['latest']} -> {$newLatest}\n"; $manifest['latest'] = $newLatest; } } // (v0.4) Signature Ed25519 du manifest $configPath = dirname(__DIR__) . '/api/config.php'; if (is_file($configPath)) { require_once dirname(__DIR__) . '/api/lib/Crypto.php'; $config = require $configPath; $sk = $config['ed25519']['private_key_hex'] ?? ''; if ($sk !== '' && strlen($sk) === 128) { // Retire signature précédente, encode canonical, signe, ré-injecte $manifest['signature'] = null; $payload = \PSLauncher\Crypto::canonicalJson($manifest); $manifest['signature'] = \PSLauncher\Crypto::signEd25519($payload, $sk); echo " [sign] manifest signed (Ed25519)\n"; } else { echo " [warn] ed25519.private_key_hex non configuré, manifest non signé\n"; } } else { echo " [warn] config.php absent, manifest non signé\n"; } file_put_contents( $manifestPath, json_encode($manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n" ); echo "Manifest mis à jour ({$updated} version(s)) : $manifestPath\n";