From 9fce6ee83064a132b6bade2fbb43c121a402ca26 Mon Sep 17 00:00:00 2001 From: codex Date: Thu, 6 Aug 2026 09:59:43 +0300 Subject: [PATCH] feat: expand controlled package lifecycle pilot evidence --- Launcher.Next.App/PackageLifecyclePilotCli.cs | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/Launcher.Next.App/PackageLifecyclePilotCli.cs b/Launcher.Next.App/PackageLifecyclePilotCli.cs index d3a8bb9..89425eb 100644 --- a/Launcher.Next.App/PackageLifecyclePilotCli.cs +++ b/Launcher.Next.App/PackageLifecyclePilotCli.cs @@ -1,4 +1,5 @@ using System.Security.Cryptography; +using System.Text; using System.Text.Json; using System.IO; using Launcher.Next.Core; @@ -8,22 +9,40 @@ namespace Launcher.Next.App; internal static class PackageLifecyclePilotCli { + private sealed class Fault(PackageLifecycleFaultPoint point) : IPackageLifecycleFaultInjector + { public void ThrowIfRequested(PackageLifecycleFaultPoint requested) { if(requested==point) throw new IOException($"INJECTED:{point}"); } } + public static async Task RunAsync(string[] args) { if (args.Length != 4 || args[0] != "--mode" || args[1] != "PackageLifecyclePilot" || args[2] != "--root") return 2; - ResolvedPackagePilotRoot pilotRoot; try { pilotRoot=new PathResolver().ResolvePackagePilotRoot(args[3]); } catch { return 2; } - var root=pilotRoot.Value; var id=Guid.NewGuid().ToString("N"); var evidenceDir=Path.Combine(root,"evidence",id); Directory.CreateDirectory(evidenceDir); + ResolvedPackageLifecycleRoots roots; try { roots=new PathResolver().ResolvePackageLifecycleRoots(args[3]); } catch { return 2; } + var id=Guid.NewGuid().ToString("N"); var started=DateTimeOffset.UtcNow; var evidenceDir=Path.Combine(roots.Evidence.Value,id); + Directory.CreateDirectory(evidenceDir); Directory.CreateDirectory(roots.Catalog.Value); Directory.CreateDirectory(Path.Combine(roots.Pilot.Value,"foreign-staging-fixture")); try { - var catalog=Path.Combine(root,"catalog"); Directory.CreateDirectory(catalog); var store=new LocalPackageStore(root,new Sha256FileHasher()); - async Task<(ImmutableLocalPackage,PackageManifest)> Materialize(string version,byte seed) - { var a=new[]{seed,(byte)(seed+1)}; var b=new[]{(byte)(seed+2)}; await File.WriteAllBytesAsync(Path.Combine(catalog,"entry.dll"),a); await File.WriteAllBytesAsync(Path.Combine(catalog,"payload.dat"),b); var manifest=new PackageManifest(1,"Pilot.Package",version,"Plant3D",2026,"x64","entry.dll",[new("entry.dll",a.Length,Convert.ToHexString(SHA256.HashData(a))),new("payload.dat",b.Length,Convert.ToHexString(SHA256.HashData(b)))],new("none",""),RolloutChannel:"pilot"); return (await store.MaterializeAsync(manifest,catalog,CancellationToken.None),manifest); } + var store=new LocalPackageStore(roots.Pilot.Value,new Sha256FileHasher()); + async Task<(ImmutableLocalPackage Package,PackageManifest Manifest)> Materialize(string version,byte seed,LocalPackageStore target) + { var a=new[]{seed,(byte)(seed+1)};var b=new[]{(byte)(seed+2)};await File.WriteAllBytesAsync(Path.Combine(roots.Catalog.Value,"entry.dll"),a);await File.WriteAllBytesAsync(Path.Combine(roots.Catalog.Value,"payload.dat"),b);var manifest=new PackageManifest(1,"Pilot.Package",version,"Plant3D",2026,"x64","entry.dll",[new("entry.dll",a.Length,Convert.ToHexString(SHA256.HashData(a))),new("payload.dat",b.Length,Convert.ToHexString(SHA256.HashData(b)))],new("none",""),RolloutChannel:"pilot");return(await target.MaterializeAsync(manifest,roots.Catalog.Value,CancellationToken.None),manifest); } PackageRequirement Req(string v)=>new("Pilot.Package","Plant3D",2026,"x64","pilot",v,"pilot-roster",true); - var (a,ma)=await Materialize("1.0.0",1); var pointersAfterA=await store.GetCurrentVersionAsync("Pilot.Package",CancellationToken.None); var aa=await store.ActivateImmutableAsync(a,Req("1.0.0"),CancellationToken.None); var repeat=await store.ActivateImmutableAsync(a,Req("1.0.0"),CancellationToken.None); - var (b,mb)=await Materialize("2.0.0",4); var beforeB=await store.GetCurrentVersionAsync("Pilot.Package",CancellationToken.None); var ab=await store.ActivateImmutableAsync(b,Req("2.0.0"),CancellationToken.None); var rollback=await store.RollbackAsync(ab.Receipt!,CancellationToken.None); var current=await store.GetCurrentVersionAsync("Pilot.Package",CancellationToken.None); - var evidence=new { schemaVersion=1,mode="PackageLifecyclePilot",operationId=id,terminalState=current=="1.0.0"?"Succeeded":"Blocked",sourceClassification="SyntheticLocal",rootFingerprint=Convert.ToHexString(SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(id+root))),packages=new[]{new{version=ma.Version,manifestSha256=Convert.ToHexString(SHA256.HashData(JsonSerializer.SerializeToUtf8Bytes(ma)))},new{version=mb.Version,manifestSha256=Convert.ToHexString(SHA256.HashData(JsonSerializer.SerializeToUtf8Bytes(mb)))}},pointers=new{afterMaterializeA=pointersAfterA,afterActivateA=aa.Outcome,repeatedA=repeat.Outcome,beforeActivateB=beforeB,afterActivateB=ab.Outcome,afterRollback=rollback.Outcome,current},sideEffects=new{corporateDfsUsed=false,corporateDfsWriteAttempted=false,autoCadLaunchAttempted=false,processLaunchAttempted=false,productionPointerMutationAttempted=false,productionProjectAccessed=false}}; - var final=Path.Combine(evidenceDir,"package-lifecycle-pilot.json"); var temp=final+".tmp"; await File.WriteAllTextAsync(temp,JsonSerializer.Serialize(evidence)); File.Move(temp,final,true); return current=="1.0.0"?0:2; + var initial=await store.GetCurrentVersionAsync("Pilot.Package",CancellationToken.None); + var (a,ma)=await Materialize("1.0.0",1,store); var afterMaterializeA=await store.GetCurrentVersionAsync("Pilot.Package",CancellationToken.None); await store.BindAsync(Req("1.0.0"),"1.0.0",CancellationToken.None); + var aa=await store.ActivateImmutableAsync(a,Req("1.0.0"),CancellationToken.None); var repeat=await store.ActivateImmutableAsync(a,Req("1.0.0"),CancellationToken.None); + var (b,mb)=await Materialize("2.0.0",4,store); var beforeB=await store.GetCurrentVersionAsync("Pilot.Package",CancellationToken.None); await store.BindAsync(Req("2.0.0"),"2.0.0",CancellationToken.None); + var ab=await store.ActivateImmutableAsync(b,Req("2.0.0"),CancellationToken.None); var rollback=await store.RollbackAsync(ab.Receipt!,CancellationToken.None); var current=await store.GetCurrentVersionAsync("Pilot.Package",CancellationToken.None); var lkg=await store.ResolveAsync(Req("1.0.0"),CancellationToken.None); + + async Task ExpectedFault(PackageLifecycleFaultPoint point,string version) + { try { await Materialize(version,9,new LocalPackageStore(roots.Pilot.Value,new Sha256FileHasher(),new Fault(point))); return "UnexpectedSuccess"; } catch { return "Blocked"; } } + var materializationFault=await ExpectedFault(PackageLifecycleFaultPoint.AfterPayloadCopyBeforeValidation,"9.0.0"); + string pointerFault; try { await new LocalPackageStore(roots.Pilot.Value,new Sha256FileHasher(),new Fault(PackageLifecycleFaultPoint.BeforePointerReplace)).ActivateImmutableAsync(b,Req("2.0.0"),CancellationToken.None);pointerFault="UnexpectedSuccess";}catch{pointerFault="Blocked";} + var foreign=Path.Combine(roots.Pilot.Value,"foreign-staging-fixture");var fake=new PackageStagingOwnership("foreign","Pilot.Package","0",foreign,DateTimeOffset.UtcNow,"foreign");var cleanup=(await store.CleanupOwnedStagingAsync(fake,CancellationToken.None)).Outcome; + var success=initial is null&&afterMaterializeA is null&&aa.Outcome=="Activated"&&repeat.Outcome=="AlreadyActiveExact"&&beforeB=="1.0.0"&&ab.Outcome=="Activated"&&rollback.Outcome=="RolledBack"&¤t=="1.0.0"&&lkg?.Version=="1.0.0"&&materializationFault=="Blocked"&&pointerFault=="Blocked"&&cleanup=="OwnershipUnknown"&&Directory.Exists(foreign); + object Package(PackageManifest m)=>new{exactIdentity=new{m.PackageId,m.Product,m.ProductYear,m.Architecture,m.RolloutChannel,m.Version},manifestSha256=Convert.ToHexString(SHA256.HashData(JsonSerializer.SerializeToUtf8Bytes(m))),payloadSetSha256=PayloadSet(m),payloadFiles=m.Files.Select(x=>new{x.Path,x.Length,x.Sha256})}; + var evidence=new { schemaVersion=2,launcherCommit=ThisCommit(),operationId=id,mode="PackageLifecyclePilot",startedUtc=started,endedUtc=DateTimeOffset.UtcNow,terminalState=success?"Succeeded":"Blocked",exitClassification=success?"CONTROLLED_FILESYSTEM_PILOT_VERIFIED":"BLOCKED",sourceClassification="SyntheticLocal",typedRoots=new[]{Role("Catalog",roots.Catalog.Value,id),Role("Staging",roots.Staging.Value,id),Role("VersionStore",roots.VersionStore.Value,id),Role("Active",roots.Active.Value,id),Role("Evidence",roots.Evidence.Value,id)},packages=new[]{Package(ma),Package(mb)},pointers=new{initial,afterMaterializeA,afterActivateA=aa.Outcome,generationA=aa.Receipt?.PointerGeneration,repeatedA=repeat.Outcome,beforeActivateB=beforeB,afterActivateB=ab.Outcome,generationB=ab.Receipt?.PointerGeneration,afterRollback=rollback.Outcome,current,contentBoundSchema=2},exactLkg=new{selected=lkg?.Version,directoryScanAttempted=false,exactBinding=lkg is not null},failureScenarios=new[]{new{faultPoint="AfterPayloadCopyBeforeValidation",actual=materializationFault,invariant=current=="1.0.0"},new{faultPoint="BeforePointerReplace",actual=pointerFault,invariant=(await store.GetCurrentVersionAsync("Pilot.Package",CancellationToken.None))=="1.0.0"},new{faultPoint="OwnershipMismatch",actual=cleanup,invariant=Directory.Exists(foreign)}},locking=new{scope="ProcessLocal",crossProcessSafety="NotVerified",networkShareSafety="NotSupported"},sideEffects=new{corporateDfsUsed=false,corporateDfsWriteAttempted=false,autoCadLaunchAttempted=false,processLaunchAttempted=false,productionPointerMutationAttempted=false,productionProjectAccessed=false,foundationUiCreated=false},claims=new{materializationIsolation="Verified",ownedStagingCleanup="Verified",immutableContentBinding="Verified",activation="Verified",activationIdempotency="Verified",receiptBoundRollback="Verified",deterministicFailureRecovery="Verified",exactLkg="Verified",processLocalConcurrency="Verified",corporateDfs="NotVerified",autoCadRuntime="NotVerified",productionAcceptance="NotVerified"}}; + var final=Path.Combine(evidenceDir,"package-lifecycle-pilot.json");var temp=final+"."+id+".tmp";await using(var stream=new FileStream(temp,FileMode.CreateNew,FileAccess.Write,FileShare.None)){await JsonSerializer.SerializeAsync(stream,evidence);await stream.FlushAsync();stream.Flush(true);}File.Move(temp,final);using var reread=JsonDocument.Parse(await File.ReadAllTextAsync(final));if(reread.RootElement.GetProperty("schemaVersion").GetInt32()!=2)return 10;return success?0:10; } catch { return 10; } } + private static object Role(string role,string path,string salt)=>new{role,localOnly=true,topologyValidated=true,reparseRejected=true,fingerprint=Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(salt+Path.GetFullPath(path))))}; + private static string PayloadSet(PackageManifest m)=>Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(string.Join("|",m.Files.OrderBy(x=>x.Path,StringComparer.Ordinal).Select(x=>$"{x.Path}:{x.Length}:{x.Sha256}"))))); + private static string ThisCommit()=>Environment.GetEnvironmentVariable("LAUNCHER_COMMIT")??"WORKTREE_BUILD"; }