opencode-secrets-obfuscation 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1 -31
  3. package/package.json +29 -23
  4. package/plugin.mjs +3841 -0
  5. package/.editorconfig +0 -12
  6. package/.github/workflows/ci.yml +0 -75
  7. package/.github/workflows/release.yml +0 -50
  8. package/.node-version +0 -1
  9. package/AGENTS.md +0 -23
  10. package/INSTALL.md +0 -104
  11. package/docs/checkpoint.md +0 -68
  12. package/docs/history/1-spec-review.md +0 -233
  13. package/docs/history/10-p0-launch-prerequisites-review.md +0 -186
  14. package/docs/history/11-p0-job-containment-review.md +0 -188
  15. package/docs/history/12-p0-api-client.md +0 -15
  16. package/docs/history/13-p0-status-review.md +0 -122
  17. package/docs/history/14-p0-containment-final-review.md +0 -84
  18. package/docs/history/15-config-source-implementation.md +0 -27
  19. package/docs/history/16-sanitizer-implementation.md +0 -65
  20. package/docs/history/17-store-policy-implementation.md +0 -36
  21. package/docs/history/18-pure-mvp-review.md +0 -182
  22. package/docs/history/19-pure-mvp-re-review.md +0 -142
  23. package/docs/history/2-p0-runtime-prerequisites.md +0 -163
  24. package/docs/history/20-pure-mvp-final-review.md +0 -116
  25. package/docs/history/21-pure-mvp-review-final.md +0 -109
  26. package/docs/history/22-pure-mvp-signoff-review.md +0 -113
  27. package/docs/history/23-pure-mvp-signoff-review.md +0 -75
  28. package/docs/history/24-owned-tools-implementation.md +0 -27
  29. package/docs/history/25-v2-plugin-integration.md +0 -53
  30. package/docs/history/26-owned-tools-review.md +0 -138
  31. package/docs/history/27-owned-tools-final-review.md +0 -93
  32. package/docs/history/28-owned-tools-signoff.md +0 -98
  33. package/docs/history/3-p0-harness-foundation.md +0 -105
  34. package/docs/history/4-p0-source-opening.md +0 -78
  35. package/docs/history/5-qualification-gate-review.md +0 -133
  36. package/docs/history/6-p0-infrastructure-review.md +0 -275
  37. package/docs/history/7-p0-job-containment.md +0 -29
  38. package/docs/history/8-p0-evidence-support.md +0 -52
  39. package/docs/history/9-p0-launch-plan.md +0 -88
  40. package/docs/spec/design.md +0 -111
  41. package/docs/spec/intent.md +0 -81
  42. package/docs/spec/plan.md +0 -78
  43. package/docs/testing.md +0 -157
  44. package/scripts/build-plugin.mjs +0 -84
  45. package/scripts/install-opencode-ci.ps1 +0 -39
  46. package/scripts/install-opencode-ci.sh +0 -27
  47. package/scripts/smoke.mjs +0 -105
  48. package/scripts/verify-package.mjs +0 -18
  49. package/src/README.md +0 -22
  50. package/src/budgets/index.ts +0 -49
  51. package/src/config/README.md +0 -4
  52. package/src/config/options.ts +0 -76
  53. package/src/diagnostics/README.md +0 -4
  54. package/src/opencode/v2/filter.ts +0 -350
  55. package/src/opencode/v2/index.ts +0 -86
  56. package/src/opencode/v2/runtime.ts +0 -207
  57. package/src/opencode/v2/transports/README.md +0 -5
  58. package/src/runtime/http-transport.ts +0 -20
  59. package/src/sanitize/README.md +0 -4
  60. package/src/sanitize/index.ts +0 -454
  61. package/src/sources/README.md +0 -5
  62. package/src/sources/dotenv.ts +0 -133
  63. package/src/sources/native/README.md +0 -5
  64. package/src/store/index.ts +0 -64
  65. package/tests/README.md +0 -26
  66. package/tests/contract/plugin-v2.test.ts +0 -29
  67. package/tests/fixtures/README.md +0 -9
  68. package/tests/fixtures/job-child.mjs +0 -18
  69. package/tests/fixtures/plugins/README.md +0 -8
  70. package/tests/fixtures/process-child.mjs +0 -20
  71. package/tests/fixtures/services/README.md +0 -10
  72. package/tests/integration/components.test.ts +0 -5
  73. package/tests/integration/transparent-runtime.test.ts +0 -97
  74. package/tests/integration/windows-job.test.ts +0 -71
  75. package/tests/p0-host/README.md +0 -24
  76. package/tests/p0-host/linux-job.sh +0 -61
  77. package/tests/p0-host/windows-job.ps1 +0 -51
  78. package/tests/p0-native/README.md +0 -33
  79. package/tests/p0-native/windows-handle-loader.tests.ps1 +0 -191
  80. package/tests/scaffold/repository.test.ts +0 -105
  81. package/tests/smoke/README.md +0 -37
  82. package/tests/smoke/cases.json +0 -17
  83. package/tests/smoke/qualification.json +0 -20
  84. package/tests/smoke/runtime-candidate.json +0 -111
  85. package/tests/support/README.md +0 -32
  86. package/tests/support/child-process.ts +0 -235
  87. package/tests/support/host-api.ts +0 -123
  88. package/tests/support/opencode-environment.ts +0 -239
  89. package/tests/support/qualification.ts +0 -154
  90. package/tests/support/recording-endpoint.ts +0 -242
  91. package/tests/support/run-directory.ts +0 -179
  92. package/tests/support/smoke-cases.ts +0 -289
  93. package/tests/unit/budgets.test.ts +0 -35
  94. package/tests/unit/config.test.ts +0 -40
  95. package/tests/unit/dotenv.test.ts +0 -72
  96. package/tests/unit/filter-size.test.ts +0 -132
  97. package/tests/unit/harness.test.ts +0 -228
  98. package/tests/unit/host-api.test.ts +0 -122
  99. package/tests/unit/opencode-environment.test.ts +0 -161
  100. package/tests/unit/qualification.test.ts +0 -128
  101. package/tests/unit/recording-endpoint.test.ts +0 -188
  102. package/tests/unit/sanitize.test.ts +0 -159
  103. package/tests/unit/smoke-cases.test.ts +0 -20
  104. package/tsconfig.json +0 -20
@@ -1,191 +0,0 @@
1
- $ErrorActionPreference = 'Stop'
2
-
3
- # P0-C feasibility fixture. This is intentionally test-only and emits no fixture
4
- # path, source content, ACL text, or native error detail.
5
- if (-not $IsWindows) { Write-Error 'P0-C-WINDOWS-ONLY'; exit 2 }
6
-
7
- $native = @'
8
- using System;
9
- using System.ComponentModel;
10
- using System.IO;
11
- using System.Runtime.InteropServices;
12
-
13
- public static class P0WindowsNative {
14
- [StructLayout(LayoutKind.Sequential)] public struct UNICODE_STRING { public ushort Length; public ushort MaximumLength; public IntPtr Buffer; }
15
- [StructLayout(LayoutKind.Sequential)] public struct OBJECT_ATTRIBUTES { public int Length; public IntPtr RootDirectory; public IntPtr ObjectName; public uint Attributes; public IntPtr SecurityDescriptor; public IntPtr SecurityQualityOfService; }
16
- [StructLayout(LayoutKind.Sequential)] public struct IO_STATUS_BLOCK { public IntPtr Status; public UIntPtr Information; }
17
- [StructLayout(LayoutKind.Sequential)] public struct BY_HANDLE_FILE_INFORMATION { public uint FileAttributes; public System.Runtime.InteropServices.ComTypes.FILETIME CreationTime; public System.Runtime.InteropServices.ComTypes.FILETIME LastAccessTime; public System.Runtime.InteropServices.ComTypes.FILETIME LastWriteTime; public uint VolumeSerialNumber; public uint FileSizeHigh; public uint FileSizeLow; public uint NumberOfLinks; public uint FileIndexHigh; public uint FileIndexLow; }
18
- [StructLayout(LayoutKind.Sequential)] public struct ACL_SIZE_INFORMATION { public uint AceCount; public uint AclBytesInUse; public uint AclBytesFree; }
19
- [DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)] static extern IntPtr CreateFileW(string name, uint access, uint share, IntPtr security, uint disposition, uint flags, IntPtr template);
20
- [DllImport("kernel32.dll", SetLastError=true)] static extern bool GetFileInformationByHandle(IntPtr h, out BY_HANDLE_FILE_INFORMATION info);
21
- [DllImport("kernel32.dll", SetLastError=true)] static extern bool ReadFile(IntPtr h, byte[] buffer, uint count, out uint read, IntPtr overlapped);
22
- [DllImport("kernel32.dll", SetLastError=true)] static extern bool SetFilePointerEx(IntPtr h, long distance, out long moved, uint method);
23
- [DllImport("kernel32.dll", SetLastError=true)] static extern bool CloseHandle(IntPtr h);
24
- [DllImport("advapi32.dll", SetLastError=true)] static extern uint GetSecurityInfo(IntPtr h, uint objectType, uint securityInfo, out IntPtr owner, out IntPtr group, out IntPtr dacl, out IntPtr sacl, out IntPtr descriptor);
25
- [DllImport("advapi32.dll", SetLastError=true)] static extern bool GetSecurityDescriptorOwner(IntPtr descriptor, out IntPtr owner, out bool defaulted);
26
- [DllImport("advapi32.dll", SetLastError=true)] static extern bool GetSecurityDescriptorDacl(IntPtr descriptor, out bool present, out IntPtr dacl, out bool defaulted);
27
- [DllImport("advapi32.dll", SetLastError=true)] static extern bool GetAclInformation(IntPtr acl, out ACL_SIZE_INFORMATION info, uint length, uint kind);
28
- [DllImport("advapi32.dll", SetLastError=true)] static extern bool GetAce(IntPtr acl, uint index, out IntPtr ace);
29
- [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)] static extern bool ConvertSidToStringSidW(IntPtr sid, out IntPtr stringSid);
30
- [DllImport("kernel32.dll")] static extern IntPtr LocalFree(IntPtr value);
31
- [DllImport("ntdll.dll")] static extern int NtCreateFile(out IntPtr h, uint access, ref OBJECT_ATTRIBUTES oa, out IO_STATUS_BLOCK iosb, IntPtr allocation, uint attributes, uint share, uint disposition, uint options, IntPtr ea, uint ealen);
32
- [DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)] static extern bool GetVolumeInformationByHandleW(IntPtr h, System.Text.StringBuilder name, uint nameLength, out uint serial, out uint maxComponent, out uint flags, System.Text.StringBuilder fs, uint fsLength);
33
- [DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)] static extern bool CreateHardLinkW(string link, string existing, IntPtr security);
34
- [DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)] static extern bool CreateSymbolicLinkW(string link, string target, uint flags);
35
- [DllImport("kernel32.dll", SetLastError=true)] static extern bool DeviceIoControl(IntPtr h, uint code, byte[] input, uint inputLength, byte[] output, uint outputLength, out uint returned, IntPtr overlapped);
36
- const uint GENERIC_READ=0x80000000, FILE_SHARE_READ=1, FILE_SHARE_WRITE=2, FILE_SHARE_DELETE=4, OPEN_EXISTING=3;
37
- const uint FILE_FLAG_BACKUP_SEMANTICS=0x02000000, FILE_FLAG_OPEN_REPARSE_POINT=0x00200000;
38
- const uint FILE_DIRECTORY_FILE=1, FILE_NON_DIRECTORY_FILE=0x40, FILE_OPEN=1, FILE_SYNCHRONOUS_IO_NONALERT=0x20;
39
- const uint OBJ_CASE_INSENSITIVE=0x40, OBJ_DONT_REPARSE=0x1000, STATUS_SUCCESS=0, FILE_ATTRIBUTE_REPARSE_POINT=0x400;
40
- const uint FSCTL_SET_REPARSE_POINT=0x000900A4, FSCTL_DELETE_REPARSE_POINT=0x000900AC, IO_REPARSE_TAG_MOUNT_POINT=0xA0000003;
41
- const uint SE_FILE_OBJECT=1, OWNER_SECURITY_INFORMATION=1, DACL_SECURITY_INFORMATION=4, ACCESS_ALLOWED_ACE_TYPE=0, ACCESS_DENIED_ACE_TYPE=1, INHERITED_ACE=0x10, FILE_READ_DATA=1, FILE_ADD_FILE=2, FILE_ADD_SUBDIRECTORY=4, DELETE_CHILD=0x40;
42
- static void Check(IntPtr h) { if (h == IntPtr.Zero || h == new IntPtr(-1)) throw new IOException("open-failed"); }
43
- static IntPtr Unicode(string s, out GCHandle pin, out UNICODE_STRING us) { char[] c=(s+"\0").ToCharArray(); pin=GCHandle.Alloc(c, GCHandleType.Pinned); us=new UNICODE_STRING(); us.Length=(ushort)(s.Length*2); us.MaximumLength=(ushort)((s.Length+1)*2); us.Buffer=pin.AddrOfPinnedObject(); return us.Buffer; }
44
- public static IntPtr OpenDirectory(string path) { IntPtr h=CreateFileW(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT, IntPtr.Zero); Check(h); return h; }
45
- public static IntPtr OpenRelative(IntPtr root, string component, bool directory) {
46
- GCHandle pin; UNICODE_STRING us; Unicode(component, out pin, out us);
47
- GCHandle usp=GCHandle.Alloc(us, GCHandleType.Pinned); OBJECT_ATTRIBUTES oa=new OBJECT_ATTRIBUTES(); oa.Length=Marshal.SizeOf(typeof(OBJECT_ATTRIBUTES)); oa.RootDirectory=root; oa.ObjectName=usp.AddrOfPinnedObject(); oa.Attributes=OBJ_CASE_INSENSITIVE|OBJ_DONT_REPARSE;
48
- IO_STATUS_BLOCK io; IntPtr h; uint options=(directory?FILE_DIRECTORY_FILE:FILE_NON_DIRECTORY_FILE)|FILE_SYNCHRONOUS_IO_NONALERT|0x00200000;
49
- int status=NtCreateFile(out h, 0x00120089U, ref oa, out io, IntPtr.Zero, 0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, options, IntPtr.Zero, 0);
50
- usp.Free(); pin.Free(); if ((uint)status != STATUS_SUCCESS) throw new IOException("relative-open-rejected-"+((uint)status).ToString("X8")); BY_HANDLE_FILE_INFORMATION info; if(!GetFileInformationByHandle(h,out info)) { CloseHandle(h); throw new IOException("identity-failed-"+Marshal.GetLastWin32Error().ToString()); } if((info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { CloseHandle(h); throw new IOException("relative-reparse-rejected"); } return h;
51
- }
52
- public static byte[] ReadAll(IntPtr h, int max) { byte[] b=new byte[max]; uint n; if(!ReadFile(h,b,(uint)b.Length,out n,IntPtr.Zero)) throw new IOException("read-failed"); Array.Resize(ref b,(int)n); return b; }
53
- public static void Rewind(IntPtr h) { long moved; if(!SetFilePointerEx(h,0,out moved,0)) throw new IOException("seek-failed-"+Marshal.GetLastWin32Error().ToString()); }
54
- public static string Identity(IntPtr h) { BY_HANDLE_FILE_INFORMATION i; if(!GetFileInformationByHandle(h,out i)) throw new IOException("identity-failed-"+Marshal.GetLastWin32Error().ToString()); return i.VolumeSerialNumber.ToString("X8")+":"+i.FileIndexHigh.ToString("X8")+i.FileIndexLow.ToString()+":"+i.NumberOfLinks.ToString(); }
55
- public static string Volume(IntPtr h) { uint serial, max, flags; System.Text.StringBuilder fs=new System.Text.StringBuilder(64); System.Text.StringBuilder name=new System.Text.StringBuilder(64); if(!GetVolumeInformationByHandleW(h,name,(uint)name.Capacity,out serial,out max,out flags,fs,(uint)fs.Capacity)) throw new IOException("volume-failed-"+Marshal.GetLastWin32Error().ToString()); return fs.ToString(); }
56
- static string Sid(IntPtr sid) { IntPtr p; if(sid==IntPtr.Zero || !ConvertSidToStringSidW(sid,out p)) return ""; try { return Marshal.PtrToStringUni(p); } finally { LocalFree(p); } }
57
- public static int Policy(IntPtr h, string currentSid, bool ancestor) {
58
- BY_HANDLE_FILE_INFORMATION fi; if(!GetFileInformationByHandle(h,out fi)) return 90; if(fi.NumberOfLinks != 1) return 6;
59
- IntPtr owner, group, dacl, sacl, sd; uint e=GetSecurityInfo(h,SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION,out owner,out group,out dacl,out sacl,out sd); if(e!=0) return 90+(int)e;
60
- try {
61
- IntPtr ownerSid; bool ownerDefault; if(!GetSecurityDescriptorOwner(sd,out ownerSid,out ownerDefault)) return 91; string os=Sid(ownerSid); if(os!=currentSid && os!="S-1-5-32-544") return 7;
62
- bool present, daclDefault; if(!GetSecurityDescriptorDacl(sd,out present,out dacl,out daclDefault) || !present || dacl==IntPtr.Zero) return 8;
63
- ACL_SIZE_INFORMATION ai; if(!GetAclInformation(dacl,out ai,(uint)Marshal.SizeOf(typeof(ACL_SIZE_INFORMATION)),2)) return 92;
64
- bool currentAccess=false;
65
- for(uint i=0;i<ai.AceCount;i++) { IntPtr ace; if(!GetAce(dacl,i,out ace)) return 93; byte type=Marshal.ReadByte(ace,0); byte flags=Marshal.ReadByte(ace,1); uint mask=(uint)Marshal.ReadInt32(ace,4); if(type==ACCESS_DENIED_ACE_TYPE) return 9; if(type!=ACCESS_ALLOWED_ACE_TYPE) return 9; string sid=Sid(IntPtr.Add(ace,8)); bool trusted=sid==currentSid || sid=="S-1-5-18" || sid=="S-1-5-32-544"; if(!trusted) return 3; if((flags & INHERITED_ACE)!=0 && !trusted) return 4; if(sid==currentSid) { uint needed=ancestor ? (FILE_ADD_FILE|FILE_ADD_SUBDIRECTORY|DELETE_CHILD) : FILE_READ_DATA; if((mask & needed)==needed) currentAccess=true; } }
66
- return currentAccess ? 0 : 10;
67
- } finally { if(sd!=IntPtr.Zero) LocalFree(sd); }
68
- }
69
- public static int HardLink(string link, string existing) { if(CreateHardLinkW(link,existing,IntPtr.Zero)) return 0; return Marshal.GetLastWin32Error(); }
70
- public static int SymbolicLink(string link, string target) { if(CreateSymbolicLinkW(link,target,0)) return 0; return Marshal.GetLastWin32Error(); }
71
- public static int Junction(string path, string target) {
72
- IntPtr h=CreateFileW(path,0x40000000U,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,IntPtr.Zero,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT,IntPtr.Zero); if(h==IntPtr.Zero || h==new IntPtr(-1)) return Marshal.GetLastWin32Error();
73
- string sub="\\??\\"+target.TrimEnd('\\')+"\\"; string print=target.TrimEnd('\\')+"\\"; byte[] s=System.Text.Encoding.Unicode.GetBytes(sub); byte[] p=System.Text.Encoding.Unicode.GetBytes(print); byte[] b=new byte[16+s.Length+p.Length]; BitConverter.GetBytes(IO_REPARSE_TAG_MOUNT_POINT).CopyTo(b,0); BitConverter.GetBytes((ushort)(8+s.Length+p.Length)).CopyTo(b,4); BitConverter.GetBytes((ushort)0).CopyTo(b,8); BitConverter.GetBytes((ushort)s.Length).CopyTo(b,10); BitConverter.GetBytes((ushort)s.Length).CopyTo(b,12); BitConverter.GetBytes((ushort)p.Length).CopyTo(b,14); Array.Copy(s,0,b,16,s.Length); Array.Copy(p,0,b,16+s.Length,p.Length); uint n; bool ok=DeviceIoControl(h,FSCTL_SET_REPARSE_POINT,b,(uint)b.Length,null,0,out n,IntPtr.Zero); int e=ok?0:Marshal.GetLastWin32Error(); CloseHandle(h); return e;
74
- }
75
- public static int RemoveJunction(string path) { IntPtr h=CreateFileW(path,0x40000000U,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,IntPtr.Zero,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT,IntPtr.Zero); if(h==IntPtr.Zero || h==new IntPtr(-1)) return Marshal.GetLastWin32Error(); byte[] b=new byte[8]; BitConverter.GetBytes(IO_REPARSE_TAG_MOUNT_POINT).CopyTo(b,0); uint n; bool ok=DeviceIoControl(h,FSCTL_DELETE_REPARSE_POINT,b,8,null,0,out n,IntPtr.Zero); int e=ok?0:Marshal.GetLastWin32Error(); CloseHandle(h); return e; }
76
- public static void Close(IntPtr h) { CloseHandle(h); }
77
- }
78
- public static class P0WindowsNativeTest {
79
- }
80
- '@
81
- Add-Type -TypeDefinition $native -Language CSharp
82
-
83
- function Assert([bool] $condition, [string] $code) { if (-not $condition) { throw $code } }
84
- $root = Join-Path ([IO.Path]::GetTempPath()) ('p0-c-' + [Guid]::NewGuid().ToString('N'))
85
- try {
86
- $gaps = @()
87
- $junctionRejected = $false
88
- [IO.Directory]::CreateDirectory($root) | Out-Null
89
- # Harden before any synthetic source bytes are created.
90
- $dirAcl = Get-Acl $root
91
- $dirAcl.SetAccessRuleProtection($true, $false)
92
- $me = [Security.Principal.WindowsIdentity]::GetCurrent().User
93
- $dirAcl.SetOwner($me)
94
- $dirAcl.Access | ForEach-Object { $dirAcl.RemoveAccessRule($_) | Out-Null }
95
- $dirAcl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule($me,'FullControl','ContainerInherit,ObjectInherit','None','Allow')))
96
- $dirAcl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule('NT AUTHORITY\SYSTEM','FullControl','ContainerInherit,ObjectInherit','None','Allow')))
97
- $dirAcl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule('BUILTIN\Administrators','FullControl','ContainerInherit,ObjectInherit','None','Allow')))
98
- Set-Acl $root $dirAcl
99
- $source = Join-Path $root 'source.env'
100
- [IO.File]::WriteAllText($source, "P0_SYNTHETIC_CANARY=not-logged`r`n")
101
- $hard=Join-Path $root 'hard.env'
102
- $hardError=[P0WindowsNative]::HardLink($hard,$source)
103
- if ($hardError -ne 0) { $gaps += ('hardlink-create-' + $hardError) }
104
- $single=Join-Path $root 'single.env'
105
- [IO.File]::WriteAllText($single, "P0_SYNTHETIC_SINGLE=not-logged`r`n")
106
- $fileAcl = Get-Acl $source
107
- $fileAcl.SetAccessRuleProtection($true, $false); $fileAcl.SetOwner($me)
108
- $fileAcl.Access | ForEach-Object { $fileAcl.RemoveAccessRule($_) | Out-Null }
109
- $fileAcl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule($me,'Read','None','None','Allow')))
110
- $fileAcl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule('NT AUTHORITY\SYSTEM','Read','None','None','Allow')))
111
- $fileAcl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule('BUILTIN\Administrators','Read','None','None','Allow')))
112
- Set-Acl $source $fileAcl
113
- $singleAcl=Get-Acl $single
114
- $singleAcl.SetAccessRuleProtection($true, $false); $singleAcl.SetOwner($me)
115
- $singleAcl.Access | ForEach-Object { $singleAcl.RemoveAccessRule($_) | Out-Null }
116
- $singleAcl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule($me,'Read','None','None','Allow')))
117
- $singleAcl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule('NT AUTHORITY\SYSTEM','Read','None','None','Allow')))
118
- $singleAcl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule('BUILTIN\Administrators','Read','None','None','Allow')))
119
- Set-Acl $single $singleAcl
120
-
121
- $rootH=[P0WindowsNative]::OpenDirectory($root)
122
- $volume=[P0WindowsNative]::Volume($rootH)
123
- Assert ($volume -eq 'NTFS') 'P0-C-WIN-VOLUME-IDENTITY'
124
- Assert (([P0WindowsNative]::Policy($rootH,$me.Value,$true)) -eq 0) 'P0-C-WIN-ANCESTOR-POLICY'
125
- $fileH=[P0WindowsNative]::OpenRelative($rootH,'single.env',$false)
126
- $id=[P0WindowsNative]::Identity($fileH)
127
- Assert (($id -match ':1$')) 'P0-C-WIN-SINGLE-LINK-COUNT'
128
- Assert (([P0WindowsNative]::Policy($fileH,$me.Value,$false)) -eq 0) 'P0-C-WIN-SOURCE-POLICY'
129
- $bytes=[P0WindowsNative]::ReadAll($fileH,4096)
130
- Assert ($bytes.Length -gt 0) 'P0-C-WIN-SAME-HANDLE-READ'
131
- $rotated=Join-Path $root 'single.rotated'; [IO.File]::Move($single,$rotated); [IO.File]::WriteAllText($single, "P0_SYNTHETIC_REPLACEMENT=not-logged`r`n")
132
- $idAfter=[P0WindowsNative]::Identity($fileH); Assert ($idAfter -eq $id) 'P0-C-WIN-POST-SWAP-IDENTITY'
133
- [P0WindowsNative]::Rewind($fileH)
134
- $bytesAfter=[P0WindowsNative]::ReadAll($fileH,4096); Assert ($bytesAfter.Length -gt 0) 'P0-C-WIN-POST-SWAP-READ'
135
- [P0WindowsNative]::Close($fileH); [P0WindowsNative]::Close($rootH)
136
-
137
- if ($hardError -eq 0) {
138
- $rootH=[P0WindowsNative]::OpenDirectory($root); $hardH=[P0WindowsNative]::OpenRelative($rootH,'hard.env',$false)
139
- Assert (([P0WindowsNative]::Policy($hardH,$me.Value,$false)) -eq 6) 'P0-C-WIN-MULTI-LINK-ACCEPTED'
140
- [P0WindowsNative]::Close($hardH); [P0WindowsNative]::Close($rootH)
141
- }
142
-
143
- # Reparse points are rejected at the component open, not followed by a path read.
144
- $link=Join-Path $root 'link.env'
145
- try {
146
- $symbolicError=[P0WindowsNative]::SymbolicLink($link,$source)
147
- if ($symbolicError -ne 0) { $gaps += ('reparse-create-' + $symbolicError); throw 'P0-C-REPARSE-SETUP-GAP' }
148
- $rootH=[P0WindowsNative]::OpenDirectory($root)
149
- $reparseRejected=$false; try { [P0WindowsNative]::OpenRelative($rootH,'link.env',$false) | Out-Null; throw 'P0-C-WIN-REPARSE-FOLLOWED' } catch { $reparseRejected=$_.Exception.ToString().Contains('relative-reparse-rejected') }; Assert $reparseRejected 'P0-C-WIN-REPARSE-UNEXPECTED'
150
- [P0WindowsNative]::Close($rootH)
151
- } catch { if ($_.Exception.Message -ne 'P0-C-REPARSE-SETUP-GAP') { throw } }
152
-
153
- # Hard links are observable on the opened object and therefore rejectable.
154
- if ($hardError -eq 0) {
155
- $rootH=[P0WindowsNative]::OpenDirectory($root); $hardH=[P0WindowsNative]::OpenRelative($rootH,'hard.env',$false)
156
- Assert (([P0WindowsNative]::Identity($hardH) -match ':2$')) 'P0-C-WIN-HARDLINK-NOT-OBSERVED'
157
- [P0WindowsNative]::Close($hardH); [P0WindowsNative]::Close($rootH)
158
- }
159
- $broadDir=Join-Path $root 'broad-parent'; New-Item -ItemType Directory -Path $broadDir | Out-Null
160
- $broadAcl=Get-Acl $broadDir
161
- $broadAcl.SetAccessRuleProtection($true, $false); $broadAcl.SetOwner($me)
162
- $broadAcl.Access | ForEach-Object { $broadAcl.RemoveAccessRule($_) | Out-Null }
163
- $broadAcl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule($me,'FullControl','ContainerInherit,ObjectInherit','None','Allow')))
164
- $broadAcl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule('NT AUTHORITY\SYSTEM','FullControl','ContainerInherit,ObjectInherit','None','Allow')))
165
- $broadAcl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule('BUILTIN\Administrators','FullControl','ContainerInherit,ObjectInherit','None','Allow')))
166
- $broadAcl.AddAccessRule((New-Object Security.AccessControl.FileSystemAccessRule('BUILTIN\Users','Read','ContainerInherit,ObjectInherit','None','Allow')))
167
- Set-Acl $broadDir $broadAcl
168
- $broadFile=Join-Path $broadDir 'broad.env'; [IO.File]::WriteAllText($broadFile, "P0_SYNTHETIC_BROAD=not-logged`r`n")
169
- $rootH=[P0WindowsNative]::OpenDirectory($root); $broadH=[P0WindowsNative]::OpenRelative($rootH,'broad-parent',$true)
170
- Assert (([P0WindowsNative]::Policy($broadH,$me.Value,$true)) -eq 3) 'P0-C-WIN-BROAD-ANCESTOR-ACCEPTED'
171
- $broadFileH=[P0WindowsNative]::OpenRelative($broadH,'broad.env',$false)
172
- Assert (([P0WindowsNative]::Policy($broadFileH,$me.Value,$false)) -eq 3) 'P0-C-WIN-BROAD-FILE-ACCEPTED'
173
- [P0WindowsNative]::Close($broadFileH); [P0WindowsNative]::Close($broadH); [P0WindowsNative]::Close($rootH)
174
- $junction=Join-Path $root 'ancestor-junction'; New-Item -ItemType Directory -Path $junction | Out-Null
175
- $junctionError=[P0WindowsNative]::Junction($junction,$root)
176
- if ($junctionError -ne 0) {
177
- $gaps += ('junction-native-create-' + $junctionError)
178
- Remove-Item -LiteralPath $junction -Force
179
- try { New-Item -ItemType Junction -Path $junction -Target $root -ErrorAction Stop | Out-Null } catch { $gaps += 'junction-fallback-create'; $junction = $null }
180
- }
181
- if ($junction) {
182
- $rootH=[P0WindowsNative]::OpenDirectory($root)
183
- try { $reparseRejected=$false; try { $jH=[P0WindowsNative]::OpenRelative($rootH,'ancestor-junction',$true); throw 'P0-C-WIN-ANCESTOR-REPARSE-FOLLOWED' } catch { $reparseRejected=$_.Exception.ToString().Contains('relative-reparse-rejected') }; Assert $reparseRejected 'P0-C-WIN-ANCESTOR-REPARSE-UNEXPECTED'; $junctionRejected = $true } finally { [P0WindowsNative]::Close($rootH) }
184
- Assert (([P0WindowsNative]::RemoveJunction($junction)) -eq 0) 'P0-C-WIN-JUNCTION-CLEANUP'
185
- }
186
- Write-Output ('P0-C-WINDOWS: PARTIAL (NTFS/relative/identity/read/post-read/hardlink/junction-rejection=' + $junctionRejected + '; gaps=' + ($gaps -join ',') + ')')
187
- if ($gaps.Count -gt 0) { exit 2 }
188
- } finally {
189
- if ($junction) { [P0WindowsNative]::RemoveJunction($junction) | Out-Null }
190
- if (Test-Path $root) { Remove-Item -LiteralPath $root -Recurse -Force -ErrorAction SilentlyContinue }
191
- }
@@ -1,105 +0,0 @@
1
- import assert from "node:assert/strict"
2
- import { readFile } from "node:fs/promises"
3
- import { spawnSync } from "node:child_process"
4
- import { test } from "node:test"
5
- import { fileURLToPath } from "node:url"
6
-
7
- const root = new URL("../../", import.meta.url)
8
- const load = async (path: string): Promise<unknown> => JSON.parse(await readFile(new URL(path, root), "utf8"))
9
-
10
- interface Case {
11
- id: string
12
- phase: string
13
- profile: string
14
- expectation: string
15
- reviews: string[]
16
- status: string
17
- title: string
18
- }
19
-
20
- test("scaffold: package is private and exposes no pretend plugin entrypoint", async () => {
21
- const pkg = await load("package.json") as Record<string, unknown>
22
- assert.equal(pkg.private, true)
23
- assert.equal(pkg.exports, undefined)
24
- assert.equal(pkg.main, undefined)
25
- })
26
-
27
- test("scaffold: smoke inventory has unique IDs, honest states and R1-R8 coverage", async () => {
28
- const inventory = await load("tests/smoke/cases.json") as { schemaVersion: number; cases: Case[] }
29
- assert.equal(inventory.schemaVersion, 1)
30
- assert.ok(inventory.cases.length > 0)
31
- assert.equal(new Set(inventory.cases.map((item) => item.id)).size, inventory.cases.length)
32
- // Exactly these cases are implemented; flipping a status is a deliberate
33
- // contract edit tied to a bound handler in scripts/smoke.mjs.
34
- const implemented = new Set(["P5-TRANSPARENT-ROUNDTRIP", "P5-SINKS", "P5-BODIES"])
35
- const reviews = new Set<string>()
36
- for (const item of inventory.cases) {
37
- assert.match(item.id, /^P[056]-[A-Z-]+$/)
38
- assert.ok(["P0", "P5", "P6"].includes(item.phase))
39
- assert.ok(["active-only", "enforced"].includes(item.profile))
40
- assert.ok(["behavior", "protected", "denied", "expected-gap"].includes(item.expectation))
41
- assert.ok(["planned", "implemented"].includes(item.status))
42
- assert.equal(item.status, implemented.has(item.id) ? "implemented" : "planned", item.id)
43
- assert.ok(item.title.length > 0)
44
- if (item.expectation === "expected-gap") assert.equal(item.profile, "active-only")
45
- for (const review of item.reviews) {
46
- assert.match(review, /^R[1-8]$/)
47
- reviews.add(review)
48
- }
49
- }
50
- for (const id of [1, 2, 3, 5, 6, 7, 8]) assert.ok(reviews.has(`R${id}`))
51
- })
52
-
53
- test("scaffold: research commit is not represented as runtime qualification", async () => {
54
- const manifest = await load("tests/smoke/qualification.json") as {
55
- status: string; host: { version: unknown; artifacts: unknown[] }; evidence: unknown[]
56
- }
57
- assert.equal(manifest.status, "unqualified")
58
- assert.equal(manifest.host.version, null)
59
- assert.deepEqual(manifest.host.artifacts, [])
60
- assert.deepEqual(manifest.evidence, [])
61
- })
62
-
63
- const smokeInvocation = (args: readonly string[], cwd = fileURLToPath(root)) =>
64
- spawnSync(process.execPath, [fileURLToPath(new URL("scripts/smoke.mjs", root)), ...args], {
65
- cwd, encoding: "utf8", timeout: 10000,
66
- })
67
-
68
- test("smoke runner: without --run it refuses to execute anything", () => {
69
- for (const args of [[], ["--unsupported"], ["--run"], ["--run", "ALL", "--qualification", "--extra"]]) {
70
- const result = smokeInvocation(args)
71
- assert.equal(result.error, undefined, `args=${JSON.stringify(args)}`)
72
- assert.equal(result.status, 2, `args=${JSON.stringify(args)}`)
73
- assert.match(result.stderr, /SMOKE_INVALID_ARGUMENT/, `args=${JSON.stringify(args)}`)
74
- }
75
- })
76
-
77
- test("smoke runner: qualification execution stays refused until gates pass", () => {
78
- for (const args of [["--qualification"], ["--qualification", "--run", "all"]]) {
79
- const result = smokeInvocation(args)
80
- assert.equal(result.status, 2, `args=${JSON.stringify(args)}`)
81
- assert.match(result.stderr, /SMOKE_NOT_IMPLEMENTED/, `args=${JSON.stringify(args)}`)
82
- }
83
- })
84
-
85
- test("smoke runner: unknown or unimplemented case selections fail before any launch", () => {
86
- const unknown = smokeInvocation(["--run", "NO-SUCH-CASE"])
87
- assert.equal(unknown.status, 2)
88
- assert.match(unknown.stderr, /SMOKE_UNKNOWN_CASE/)
89
- const unimplemented = smokeInvocation(["--run", "P0-BOOT"])
90
- assert.equal(unimplemented.status, 2)
91
- assert.match(unimplemented.stderr, /SMOKE_CASE_NOT_IMPLEMENTED/)
92
- })
93
-
94
- test("scaffold: list mode is inventory-only and works outside the repo cwd", () => {
95
- const result = spawnSync(process.execPath, [fileURLToPath(new URL("scripts/smoke.mjs", root)), "--list"], {
96
- cwd: fileURLToPath(new URL("tests/", root)), encoding: "utf8", timeout: 10000,
97
- })
98
- assert.equal(result.error, undefined)
99
- assert.equal(result.status, 0)
100
- assert.match(result.stdout, /P0-BOOT \[planned\]/)
101
- assert.match(result.stdout, /P5-TRANSPARENT-ROUNDTRIP \[implemented\]/)
102
- assert.match(result.stdout, /P5-SINKS \[implemented\]/)
103
- assert.match(result.stdout, /P5-BODIES \[implemented\]/)
104
- assert.match(result.stdout, /No smoke tests executed/)
105
- })
@@ -1,37 +0,0 @@
1
- '# Real OpenCode smoke tests
2
-
3
- `cases.json` is the stable-ID inventory. `P5-TRANSPARENT-ROUNDTRIP` is the
4
- implemented case and is bound explicitly in `scripts/smoke.mjs`; the previous
5
- `P5-ROUNDTRIP` tool-broker experiment is retained as planned history only.
6
- `qualification.json` deliberately contains **null pins**. A passing smoke case
7
- is sandbox evidence, not release qualification.
8
-
9
- The runner launches the actual pinned V2 host with private config/data/cache/home,
10
- a scripted loopback provider and an allowlisted environment. The plugin adds no
11
- model-visible tools and starts no network request of its own.
12
-
13
- `P5-TRANSPARENT-ROUNDTRIP` installs `dist/plugin.mjs` as `index.js`, drives one
14
- `opencode run` conversation, and asserts exit 0, an opaque `secret-<uuid>`
15
- replacement in existing provider traffic, no raw canary in provider bodies or
16
- public output, and no plugin-owned request. P0 native-loader cases run real OS operations alongside'
17
- host qualification and must state the tested filesystem. Unsupported OS cases
18
- are **unqualified**, not silently passing skips.
19
-
20
- Standing rules for handlers:
21
-
22
- - Require explicit artifact paths and verified versions/checksums from the
23
- manifest before claiming qualification; a case run records what it actually
24
- used.
25
- - Use a dedicated service, private config/data/cache/home and allowlisted child
26
- environment. Never attach to or restart the user's shared service.
27
- - Record real provider bytes, events, database/state and spill files privately;
28
- stdout and ordinary CI artifacts contain safe case IDs/counts only.
29
- - Bound startup, calls, buffers and teardown. Kill the run's owned processes
30
- (by sandbox path and by managed-service port); validate the run-directory
31
- marker before exact-path cleanup.
32
- - Run a zero-egress/zero-resolution oracle for denial cases, not just text scans.
33
- - Distinguish `expected-gap` evidence from `protected`/`denied` evidence. It
34
- cannot qualify an enforced profile. Unexpected fixes/regressions require
35
- review of the evidence; do not simply invert assertions to keep tests green.
36
- - Qualification must reject missing/TODO/skipped required cases, unknown pins,
37
- empty case selection, unsupported platforms and unavailable mandatory gates.
@@ -1,17 +0,0 @@
1
- {
2
- "schemaVersion": 1,
3
- "cases": [
4
- { "id": "P0-BOOT", "phase": "P0", "profile": "active-only", "expectation": "behavior", "reviews": [], "status": "planned", "title": "Boot an isolated pinned V2 host and verify plugin/artifact identity" },
5
- { "id": "P0-HOOKS", "phase": "P0", "profile": "active-only", "expectation": "behavior", "reviews": ["R1", "R6"], "status": "planned", "title": "Probe prompt, context, model and HTTP hook ordering and serialization" },
6
- { "id": "P0-ABORT", "phase": "P0", "profile": "active-only", "expectation": "denied", "reviews": ["R6"], "status": "planned", "title": "Unsafe or unverifiable provider publication fails before transmission" },
7
- { "id": "P0-SOURCE-LINUX", "phase": "P0", "profile": "active-only", "expectation": "denied", "reviews": ["R8"], "status": "planned", "title": "Qualify Linux source opening, replacement and link behavior" },
8
- { "id": "P0-SOURCE-WINDOWS", "phase": "P0", "profile": "active-only", "expectation": "denied", "reviews": ["R8"], "status": "planned", "title": "Qualify Windows source opening, replacement and reparse behavior" },
9
- { "id": "P0-QUOTAS", "phase": "P0", "profile": "active-only", "expectation": "behavior", "reviews": ["R7"], "status": "planned", "title": "Prove bounded source, traversal and activation accounting" },
10
- { "id": "P5-TRANSPARENT-ROUNDTRIP", "phase": "P5", "profile": "active-only", "expectation": "protected", "reviews": ["R1", "R2", "R6"], "status": "implemented", "title": "Substitute configured secrets behind the scenes in existing provider traffic" },
11
- { "id": "P5-SINKS", "phase": "P5", "profile": "active-only", "expectation": "protected", "reviews": ["R1", "R2"], "status": "implemented", "title": "Protect outgoing provider requests and returned provider text" },
12
- { "id": "P5-BODIES", "phase": "P5", "profile": "active-only", "expectation": "protected", "reviews": ["R1", "R2", "R3", "R6"], "status": "implemented", "title": "Protect provider headers, bodies, errors and final serialized bytes" },
13
- { "id": "P5-LIFECYCLE-GAP", "phase": "P5", "profile": "active-only", "expectation": "expected-gap", "reviews": ["R5", "R6"], "status": "planned", "title": "Observe plugin unload, late overlays and stale activation behavior" },
14
- { "id": "P5-EXPANSION", "phase": "P5", "profile": "active-only", "expectation": "denied", "reviews": ["R7"], "status": "planned", "title": "Exercise expansion, cancellation and concurrency bounds" },
15
- { "id": "P5-PACKAGING", "phase": "P5", "profile": "active-only", "expectation": "behavior", "reviews": [], "status": "planned", "title": "Install the packed artifact in a clean environment and restart" }
16
- ]
17
- }
@@ -1,20 +0,0 @@
1
- {
2
- "schemaVersion": 1,
3
- "status": "unqualified",
4
- "researchCommit": "e9def88a7790efc6abace15b67f3625ff4d66237",
5
- "host": {
6
- "version": null,
7
- "sourceCommit": null,
8
- "artifacts": []
9
- },
10
- "pluginApiVersion": null,
11
- "effectVersion": null,
12
- "provider": {
13
- "package": null,
14
- "version": null,
15
- "protocol": null
16
- },
17
- "platforms": [],
18
- "trustedPluginOrder": [],
19
- "evidence": []
20
- }
@@ -1,111 +0,0 @@
1
- {
2
- "schemaVersion": 1,
3
- "status": "unqualified",
4
- "profile": "active-only-mvp-candidate",
5
- "host": {
6
- "version": "2.0.28",
7
- "sourceTag": "v2.0.28",
8
- "sourceCommit": "026b106bc5d41b679ffc413264229c340871e4d3",
9
- "sourceAssociation": "official Git tag; binary build provenance and reproducible-build equality are not established",
10
- "distribution": {
11
- "package": "@opencode/cli",
12
- "version": "2.0.28",
13
- "tarball": "https://registry.npmjs.org/@opencode/cli/-/cli-2.0.28.tgz",
14
- "npmIntegrity": "sha512-nKStJJVG6to58gSPv5AuzNQZhYtou6b1jfI5EIckshWT9w8teesSLgP3gH/iSA/madUhvkNqsFjUFuD3NRne9Q==",
15
- "platformPackages": [
16
- {
17
- "package": "@opencode/cli-linux-x64@2.0.28",
18
- "tarball": "https://registry.npmjs.org/@opencode/cli-linux-x64/-/cli-linux-x64-2.0.28.tgz",
19
- "tarballSha256": "76F8505BAAF56965ED28F305B74C526B54ECCD18FE78C81621A4090CC026C9F9",
20
- "npmIntegrity": "sha512-HdgQ2c9FrER88w3Alm/UGdzU55lCc0FXxSm+VNMXUz+Yyv03uLc0Z+PxSnEBysmYNKcFvcnxdT7e0xGPoytrNg==",
21
- "member": "package/bin/opencode",
22
- "memberSha256": "20D305D0140BFE04DF7264A4ECB014402B74B6AC0A0F6456EE07EF3325FB4A85"
23
- },
24
- {
25
- "package": "@opencode/cli-windows-arm64@2.0.28",
26
- "tarball": "https://registry.npmjs.org/@opencode/cli-windows-arm64/-/cli-windows-arm64-2.0.28.tgz",
27
- "tarballSha256": "5DD7944A1EE879E7D9794263D945386B706F404F3EEE885CB599E81ABC5E59EF",
28
- "npmIntegrity": "sha512-9HXcqjQa2ghY6tgqjRqaVCZfBuP10b55ffo2QdgHESzsItTwL0yKWaorzj91q96dqmQJ6MOvpl31PdhJnhuJ4g==",
29
- "member": "package/bin/opencode.exe",
30
- "memberSha256": "65F0E7ACCC7D5FD77CA7380FDE87E3289D0CF27687851E5240BBDE6CAA7BDB66",
31
- "peMachine": "AA64"
32
- },
33
- {
34
- "package": "@opencode/cli-windows-x64@2.0.28",
35
- "tarball": "https://registry.npmjs.org/@opencode/cli-windows-x64/-/cli-windows-x64-2.0.28.tgz",
36
- "tarballSha256": "A5A212125E497726A95D6F9C3CDCFE6F1FA35CA61F3F263E6575D557747FEAE2",
37
- "npmIntegrity": "sha512-1/pyMMi61RHsROPJbLUsO8U2hIUMwzNQvY/XUlF5IgxXvIVd9oNI8kxmZcD72rta3s17doKAEB+MKdsnmeFxQ==",
38
- "member": "package/bin/opencode.exe",
39
- "memberSha256": "9C59FCD39AA9C611AEDA04711BAB9D668CE3145FA5CDE9868F69C31ADCCFD3E3",
40
- "peMachine": "8664"
41
- }
42
- ]
43
- },
44
- "privateArtifact": {
45
- "archiveMember": "package/bin/opencode.exe",
46
- "sha256": "65F0E7ACCC7D5FD77CA7380FDE87E3289D0CF27687851E5240BBDE6CAA7BDB66",
47
- "format": "PE32+ Windows executable",
48
- "peMachine": "AA64",
49
- "executed": false
50
- }
51
- },
52
- "pluginApiVersion": "2.0.28",
53
- "effectVersion": "4.0.1",
54
- "provider": {
55
- "runtimePackage": "@opencode/ai@2.0.28",
56
- "package": "@opencode/ai/providers/openai-compatible",
57
- "version": "2.0.28",
58
- "protocol": "OpenAI-compatible HTTP; exact fixture endpoint/model remains unselected"
59
- },
60
- "platforms": [
61
- {
62
- "os": "linux",
63
- "arch": "x64",
64
- "status": "candidate-only",
65
- "note": "Linux x64 native artifact; runtime/containment remain unqualified"
66
- },
67
- {
68
- "os": "win32",
69
- "arch": "arm64",
70
- "status": "candidate-only",
71
- "note": "Windows ARM64 native artifact; runtime/containment remain unqualified"
72
- },
73
- {
74
- "os": "win32",
75
- "arch": "x64",
76
- "status": "candidate-only",
77
- "note": "Windows x64 native artifact; runtime/containment remain unqualified"
78
- }
79
- ],
80
- "startupIsolation": {
81
- "status": "source-verified-controls-not-runtime-proven",
82
- "mode": "standalone or foreground serve; never shared service",
83
- "allowlistRequired": true,
84
- "environmentControls": [
85
- "XDG_DATA_HOME",
86
- "XDG_CACHE_HOME",
87
- "XDG_CONFIG_HOME",
88
- "XDG_STATE_HOME",
89
- "TEMP",
90
- "TMP",
91
- "ProgramData",
92
- "OPENCODE_CONFIG_DIR",
93
- "OPENCODE_CONFIG_PROJECT_DISABLE=1",
94
- "OPENCODE_CONFIG_CONTENT",
95
- "OPENCODE_DB=<private-root>/data/opencode.db",
96
- "OPENCODE_PASSWORD=<run-owned-random-password>"
97
- ],
98
- "sharedService": "must not be discovered, attached to, stopped, or restarted"
99
- },
100
- "evidence": [
101
- "https://github.com/anomalyco/opencode/tree/v2.0.28",
102
- "https://api.github.com/repos/anomalyco/opencode/git/ref/tags/v2.0.28",
103
- "https://opencode.ai/v2/docs/",
104
- "https://opencode.ai/v2/docs/cli"
105
- ],
106
- "qualificationBlockers": [
107
- "P0-BOOT has not executed the candidate host",
108
- "startup filesystem/service isolation has not been runtime-proven",
109
- "Windows ARM64 execution of the x64 artifact is not qualified"
110
- ]
111
- }
@@ -1,32 +0,0 @@
1
- # P0 test-harness support
2
-
3
- Current helpers (test-only; none constitutes real-host qualification):
4
-
5
- - `qualification.ts`: bounded case-evidence bookkeeping. Validates input shapes
6
- and rejects missing/TODO/stale/mixed-profile records. It does not verify capture
7
- truth, hashes, authoritative case selection, or actual execution.
8
- - `recording-endpoint.ts`: bounded scripted loopback HTTP recorder for synthetic
9
- traffic. Owns its sockets and in-memory captures. It is not a model protocol
10
- implementation, HTTPS connector, or a firewall. Parsed-request and connection
11
- counters are distinct; request counts alone cannot prove zero network egress.
12
- - `run-directory.ts` and `child-process.ts`: local synthetic fixture support under
13
- active review. Do not use them to start OpenCode until the documented privacy,
14
- artifact identity and whole-process-tree prerequisites pass.
15
-
16
- Implement these test facilities before production code:
17
-
18
- 1. Run-directory lifecycle: private OS permissions, exact owned-path cleanup,
19
- validated safe output. Store beneath ignored `.artifacts/` or an explicitly
20
- approved private test root. Git ignore alone is not access control.
21
- 2. Process harness: explicit pinned binary, allowlisted environment, isolated
22
- service/config/data/cache/home, bounded startup and teardown, tracked PIDs.
23
- 3. Recording provider and controlled HTTPS adapter fixtures; generated synthetic
24
- credentials only, independent expected outcomes and call counters.
25
- 4. Sink-byte, overlap-interval, authorization, destination, revision and quota
26
- oracles. Do not import a production sanitizer to decide whether it leaked.
27
- 5. Evidence writer: safe case IDs/status/counts on stdout, private raw captures,
28
- explicit profile/build/OS/request-kind and expectation type.
29
-
30
- The real-host orchestration and evidence store are not implemented. Do not read
31
- the operator's real credentials/config, attach to the shared service, or kill
32
- arbitrary OpenCode processes to make a test pass.