# rebuild_bootpack_full_seedbox_v1.1.ps1 # Objet : REGENERER COMPLETEMENT bootpack.txt (SEEDBOX). PREVIEW=no-touch. WRITE=SAFE-WRITE. # SEEDBOX_MANAGER (scripts /bin/sh ASCII-only }); annexes Windows .ps1 en UTF-8 BOM # Invariants L0 : GOV_SCRIPT_GATE v1.4 ; SAFE-WRITE v1.1 ; TXT-ONLY v1.0 ; SYNC-MEM-ARCHIVE-RULE v1.0 ; SYNC-GUARD v1.1 param([switch]$Preview,[switch]$Write) function New-Nonce([int]$n=10){ $a=(48..57+65..90+97..122); $s=''; 1..$n|%{ $s+=[char]($a|Get-Random) }; $s } function Write-NoBOM([string]$Path,[string]$Text){ $enc=New-Object System.Text.UTF8Encoding($false); [IO.File]::WriteAllText($Path,$Text,$enc) } function Append-NoBOM([string]$Path,[string]$Text){ $enc=New-Object System.Text.UTF8Encoding($false); [IO.File]::AppendAllText($Path,$Text,$enc) } function Read-FileText([string]$p){ if(Test-Path $p){ [IO.File]::ReadAllText($p,[Text.UTF8Encoding]::new($true)) } else { '' } } function Get-FileSHA256([string]$Path){ if(Test-Path $Path){ (Get-FileHash -Algorithm SHA256 -LiteralPath $Path).Hash } else { '' } } function Compute-TextSHA256([string]$Text){ $sha=[Security.Cryptography.SHA256]::Create(); $bytes=[Text.Encoding]::UTF8.GetBytes($Text); ($sha.ComputeHash($bytes)|%{ $_.ToString('x2') }) -join '' } function Ensure-Parent([string]$Path){ $p=Split-Path -Parent $Path; if($p -and !(Test-Path $p)){ New-Item -ItemType Directory -Force -Path $p|Out-Null } } function Safe-ReplaceFile([string]$Target,[string]$Text){ Ensure-Parent $Target $ts=Get-Date -Format 'yyyyMMdd_HHmmss' $tmp="$Target.$ts.tmp"; $bak="$Target.bak_$ts" Write-NoBOM $tmp $Text $shaTmp=(Get-FileHash -Algorithm SHA256 -LiteralPath $tmp).Hash if(Test-Path $Target){ Copy-Item -LiteralPath $Target -Destination $bak -Force } Move-Item -LiteralPath $tmp -Destination $Target -Force $shaFinal=(Get-FileHash -Algorithm SHA256 -LiteralPath $Target).Hash @{Bak=$bak;ShaTmp=$shaTmp;ShaFinal=$shaFinal} } function Count-KBEntries([string]$kbPath){ $raw=Read-FileText $kbPath $i=$raw.LastIndexOf(']}'); if($i -gt 0){ $raw=$raw.Substring(0,$i+2) } try{ (($raw|ConvertFrom-Json).entries).Count } catch { ([regex]::Matches($raw,'"id"\s*:')).Count } } $Root='\\DS-918\chatgpt\ChatGPT-Gouvernance-Projets\_registry' $BootPack="$Root\bootpack\bootpack.txt" $KBPointerPath="$Root\bootpack\bootpack_paste.txt" $Snapshot="$Root\snapshots\snapshot_{0}.json" -f (Get-Date -Format 'yyyy-MM-dd') $ProfileFile="$Root\profiles\project\SEEDBOX\PROJECT_PROFILE.txt" $LogFile="$Root\logs\registry_activity.log" $L0=@('GOV_SCRIPT_GATE v1.4','SAFE-WRITE v1.1','TXT-ONLY v1.0','SYNC-MEM-ARCHIVE-RULE v1.0','SYNC-GUARD v1.1') if(!(Test-Path $KBPointerPath)){ throw "[BLOCKING] bootpack_paste.txt introuvable : $KBPointerPath" } $kbSha=Get-FileSHA256 $KBPointerPath $kbEntries=Count-KBEntries $KBPointerPath $kbSize=0; if(Test-Path $KBPointerPath){ $kbSize=(Get-Item $KBPointerPath).Length } $kbUpdated=(Get-Item $KBPointerPath).LastWriteTimeUtc.ToString('yyyy-MM-ddTHH:mm:ssZ') $hasSnap=Test-Path $Snapshot $snapSha= if($hasSnap){ Get-FileSHA256 $Snapshot } else { 'MISSING' } $profileTxt=[string]::Join("`r`n", @( 'PROJECT=SEEDBOX_MANAGER', 'RUNTIME=POSIX_sh', 'ENCODING=.sh=ASCII_only ; .ps1=UTF8_BOM (annexes Windows)', 'CONSTRAINTS=NoAdmin ; UNC ; OneDrivePersonalSeparate' )) $hasProfile = Test-Path $ProfileFile $profilePlannedSha = Compute-TextSHA256 $profileTxt $profileSha = if($hasProfile){ Get-FileSHA256 $ProfileFile } else { "PLANNED:$profilePlannedSha" } $refFiles=@("$Root\REGLES_GOUVERNANCE.txt","$Root\SAFE-WRITE-RULE_v1.1.txt","$Root\GOV_SCRIPT_GATE_v1.4.txt","$Root\TXT-ONLY-POLICY_v1.0.txt") $lines=@(); foreach($f in $refFiles){ $h=Get-FileSHA256 $f; if(!$h){ $h='MISSING' }; $lines += " $f = $h" } $filesShaBlock=($lines -join "`r`n") $memId=(Get-Date).ToString('yyyy-MM-ddTHH:mm:ssK') $nonce=New-Nonce 10 $syncCore=[string]::Join("`r`n", @( 'MEM_SYNC_ID: $memId', 'RULESET_ACTIVE: $($L0 -join '' ; '')', 'SNAPSHOT_FILE: $Snapshot', 'SNAPSHOT_SHA256: $snapSha', 'FILES_SHA256:', '$filesShaBlock', 'NONCE: $nonce' )).Trim() $manifestSha=Compute-TextSHA256 $syncCore $syncBody="$syncCore`r`nMANIFEST_SHA256: $manifestSha" $bootpackText=[string]::Join("`r`n", @( '[BOOT-PACK]', 'PROJECT: SEEDBOX_MANAGER', 'ROOT: $Root', 'DOCS_FORMAT: TXT-ONLY', 'ENCODING: UTF-8 (no BOM)', '', '[POLICY]', '$($L0 -join "`r`n")', '', '[PROJECT_PROFILE_REF]', 'PROFILE_FILE: $ProfileFile', 'PROFILE_SHA256: $profileSha', '', '[SYNC_MANIFEST]', '$syncBody', '', '[BUG_KB_JSON_POINTER]', 'Path: $KBPointerPath', 'SHA256: $kbSha', 'Entries: $kbEntries', 'SizeBytes: $kbSize', 'Updated: $kbUpdated', '', '[KB_GUARD_ASSERTS]', 'KB-AUTO-ps-5-1-operateur-ternaire-non-supporte-20251018_135633 = covered_by: RULE_PS51_NO_TERNARY v1.0', 'KB-AUTO-ps-5-1-select-string-sans-recurse-boucler-fichiers-20251018_160307 = covered_by: RULE_SEARCH_NO_RECURSE v1.0', 'KB-AUTO-join-path-ne-pas-passer-un-tableau-en-childpath-20251018_161141 = covered_by: RULE_SAFE_JOINPATH v1.0', 'KB-AUTO-safe-write-creer-repertoires-avant-tmp-20251018_160648 = covered_by: RULE_SAFE_WRITE_ENSURE_PARENT v1.0', 'KB-AUTO-ps-5-1-ps1-en-utf-8-avec-bom-ou-ascii-strict-20251018_162239 = covered_by: RULE_PS1_UTF8_BOM v1.0', 'KB-AUTO-executionpolicy-allsigned-sur-unc-utiliser-bypass-20251018_165000 = covered_by: RULE_CMD_WRAPPER_BYPASS v1.0' )).TrimEnd() $plan=[string]::Join("`r`n", @( '== PREVIEW :: REBUILD BOOTPACK (SEEDBOX) ==', 'Target BootPack : $BootPack', 'PROFILE_FILE : $ProfileFile (SHA=$profileSha)', 'KB Pointer : $KBPointerPath (SHA=$kbSha, Entries=$kbEntries, Size=$kbSize, Updated=$kbUpdated)', 'SNAPSHOT_FILE : $Snapshot (SHA=$snapSha)', 'RULESET_ACTIVE : $($L0 -join '' ; '')', 'MEM_SYNC_ID : $memId', 'MANIFEST_SHA256 : $manifestSha' )) Write-Host $plan if(-not $Write){ Write-Host "Mode PREVIEW : aucune ?criture effectu?e." exit 0 } if(-not $hasSnap){ Ensure-Parent $Snapshot; Write-NoBOM $Snapshot "{}`r`n"; $snapSha=Get-FileSHA256 $Snapshot } if(-not $hasProfile){ Ensure-Parent $ProfileFile; Write-NoBOM $ProfileFile $profileTxt; $profileSha=Get-FileSHA256 $ProfileFile } $memId=(Get-Date).ToString('yyyy-MM-ddTHH:mm:ssK') $syncCore=[string]::Join("`r`n", @( 'MEM_SYNC_ID: $memId', 'RULESET_ACTIVE: $($L0 -join '' ; '')', 'SNAPSHOT_FILE: $Snapshot', 'SNAPSHOT_SHA256: $snapSha', 'FILES_SHA256:', '$filesShaBlock', 'NONCE: $nonce' )).Trim() $manifestSha=Compute-TextSHA256 $syncCore $syncBody="$syncCore`r`nMANIFEST_SHA256: $manifestSha" $footer="; DOC-VERSION-FOOTER: rebuild_bootpack_full_seedbox_v1.1.ps1 | "+(Get-Date -Format 'yyyy-MM-dd')+" | SHA="+(Compute-TextSHA256 $bootpackText) $final=($bootpackText.Replace("[SYNC_MANIFEST]", "[SYNC_MANIFEST]`r`n$syncBody").TrimEnd()+"`r`n"+$footer+"`r`n") $result=Safe-ReplaceFile -Target $BootPack -Text $final Write-Host ("Backup : {0}" -f $result.Bak) Write-Host ("SHA tmp/final: {0} / {1}" -f $result.ShaTmp,$result.ShaFinal) $LogFile="$Root\logs\registry_activity.log"; Ensure-Parent $LogFile $logLine=("{0} | action=rebuild_bootpack | project=SEEDBOX | mem_sync_id={1} | manifest_sha={2} | bootpack_sha={3}" -f (Get-Date -Format s), $memId, $manifestSha, $result.ShaFinal) Append-NoBOM $LogFile ($logLine+"`r`n") Write-Host ("SYNC-COMMIT-OK - MEM_SYNC_ID={0}" -f $memId)