rea-agents 1.7.0 → 2.1.0

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 (333) hide show
  1. package/README.md +112 -59
  2. package/bridge/ghidra/ReaGhidraBridge.java +96 -11
  3. package/dist/application/ArtifactExtraction.js +1 -1
  4. package/dist/application/ArtifactInventory/classify.js +42 -0
  5. package/dist/application/ArtifactInventory/hash.js +43 -0
  6. package/dist/application/ArtifactInventory/reader.js +41 -0
  7. package/dist/application/ArtifactInventory/scanCanonical.js +155 -0
  8. package/dist/application/ArtifactInventory/scanReader.js +124 -0
  9. package/dist/application/ArtifactInventory/types.js +10 -0
  10. package/dist/application/ArtifactInventory.js +9 -351
  11. package/dist/application/AuthorizedArtifactInventory.js +2 -2
  12. package/dist/application/BinarySession.js +47 -270
  13. package/dist/application/BinarySessionExecution.js +28 -0
  14. package/dist/application/BinarySessionOpen.js +39 -0
  15. package/dist/application/BinarySessionRecords.js +149 -0
  16. package/dist/application/BinarySessionStatus.js +75 -0
  17. package/dist/application/CapabilityInventory.js +42 -2
  18. package/dist/application/ClientRegistrationStatus.js +1 -1
  19. package/dist/application/CrossVersionInventory.js +8 -2
  20. package/dist/application/CrossVersionInvestigation.js +11 -29
  21. package/dist/application/CrossVersionInvestigationCollections.js +23 -0
  22. package/dist/application/DirectAnalysis.js +47 -44
  23. package/dist/application/Doctor.js +165 -197
  24. package/dist/application/DoctorDiagnostics.js +180 -0
  25. package/dist/application/ElectronBoundaryAnalysis.js +112 -0
  26. package/dist/application/ElectronBoundaryGraph.js +9 -0
  27. package/dist/application/ElectronBoundaryGraphContext.js +62 -0
  28. package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
  29. package/dist/application/ElectronBoundaryGraphNative.js +86 -0
  30. package/dist/application/ElectronBoundaryGraphWindows.js +223 -0
  31. package/dist/application/EnhancedToolPagination.js +22 -0
  32. package/dist/application/EnhancedToolTypes.js +4 -0
  33. package/dist/application/EnhancedTools.js +58 -50
  34. package/dist/application/InstrumentedJavaScriptReplayHost.js +36 -0
  35. package/dist/application/InvestigationProviders.js +30 -0
  36. package/dist/application/InvestigationWorkspaceStore.js +24 -10
  37. package/dist/application/JavaScriptApplicationEvidence.js +26 -0
  38. package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
  39. package/dist/application/JavaScriptApplicationService.js +74 -0
  40. package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
  41. package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
  42. package/dist/application/JavaScriptArtifactAnalysis.js +52 -7
  43. package/dist/application/JavaScriptArtifactFiles.js +6 -2
  44. package/dist/application/JavaScriptArtifactGraphBuilder.js +82 -17
  45. package/dist/application/JavaScriptArtifactGraphBundlers.js +225 -0
  46. package/dist/application/JavaScriptArtifactGraphContext.js +37 -36
  47. package/dist/application/JavaScriptArtifactGraphDocuments.js +27 -4
  48. package/dist/application/JavaScriptArtifactGraphEvidence.js +24 -14
  49. package/dist/application/JavaScriptArtifactGraphFindings.js +54 -8
  50. package/dist/application/JavaScriptArtifactGraphStructure.js +29 -101
  51. package/dist/application/JavaScriptArtifactPathResolution.js +269 -0
  52. package/dist/application/JavaScriptArtifactReconstruction.js +4 -1
  53. package/dist/application/JavaScriptArtifactReconstructionInput.js +2 -83
  54. package/dist/application/JavaScriptJsonModules.js +39 -0
  55. package/dist/application/JavaScriptModuleRelationships.js +262 -0
  56. package/dist/application/JavaScriptReplayPermission.js +16 -0
  57. package/dist/application/JavaScriptReplayPlanning.js +201 -0
  58. package/dist/application/JavaScriptReplayService.js +292 -0
  59. package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
  60. package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
  61. package/dist/application/LinuxHopper.js +10 -0
  62. package/dist/application/MacHopper.js +22 -11
  63. package/dist/application/ManagedApplicationGraphService.js +55 -0
  64. package/dist/application/ManagedMemberComparisonService.js +122 -0
  65. package/dist/application/ManagedNativeVerificationService.js +39 -0
  66. package/dist/application/ManagedReconstructionService.js +58 -0
  67. package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
  68. package/dist/application/NodeRuntimeCharacterizationService.js +196 -0
  69. package/dist/application/PermissionAuthority.js +106 -63
  70. package/dist/application/ProcessCaptureCapability.js +1 -1
  71. package/dist/application/ProcessCapturePermission.js +13 -0
  72. package/dist/application/ProcessCli.js +2 -12
  73. package/dist/application/ProcessHarness.js +1 -1
  74. package/dist/application/ProcessSampling.js +15 -11
  75. package/dist/application/ProjectPermissionStore.js +49 -9
  76. package/dist/application/RealHopperAssertions.js +76 -0
  77. package/dist/application/ReconstructionCoverageService.js +69 -0
  78. package/dist/application/ReconstructionCoverageWorkspaceStore.js +31 -0
  79. package/dist/application/RuntimeExecutableDiagnostics.js +172 -0
  80. package/dist/application/Setup.js +147 -259
  81. package/dist/application/SetupClientConfiguration.js +220 -0
  82. package/dist/application/SetupClients.js +24 -2
  83. package/dist/application/SetupPlan.js +123 -12
  84. package/dist/application/SetupSkill.js +26 -12
  85. package/dist/application/SupportedClients.js +1 -0
  86. package/dist/application/Uninstall.js +6 -3
  87. package/dist/application/WindowsCapabilities.js +86 -0
  88. package/dist/application/runtime.js +2 -0
  89. package/dist/artifacts/AsarArtifactReader.js +11 -0
  90. package/dist/browser/BrowserProcessStartup.js +88 -0
  91. package/dist/browser/CdpCaptureDocuments.js +12 -8
  92. package/dist/browser/CdpCaptureEventBodyShapes.js +75 -0
  93. package/dist/browser/CdpCaptureEventHandlers.js +336 -0
  94. package/dist/browser/CdpCaptureEventHelpers.js +71 -0
  95. package/dist/browser/CdpCaptureEventState.js +1 -0
  96. package/dist/browser/CdpCaptureEventTypes.js +1 -0
  97. package/dist/browser/CdpCaptureEvents.js +46 -464
  98. package/dist/browser/CdpElectronInspection.js +106 -162
  99. package/dist/browser/CdpElectronProvider.js +5 -1
  100. package/dist/browser/CdpElectronScriptEvents.js +69 -0
  101. package/dist/browser/CdpElectronScripts.js +94 -0
  102. package/dist/browser/CdpElectronWorkers.js +56 -0
  103. package/dist/browser/CdpObservationSession.js +51 -8
  104. package/dist/browser/CdpPageCapture.js +12 -129
  105. package/dist/browser/CdpPageCaptureScripts.js +97 -0
  106. package/dist/browser/CdpPageCaptureWorkers.js +46 -0
  107. package/dist/browser/CdpWebMcpDiscovery.js +38 -14
  108. package/dist/browser/PngVisualDiff.js +9 -2
  109. package/dist/catalogIdentity.js +8 -1
  110. package/dist/cli/artifactCommands.js +82 -0
  111. package/dist/cli/coreAnalysisCommands.js +232 -0
  112. package/dist/cli/managedCommands.js +397 -0
  113. package/dist/cli/managedProjectGraphCommand.js +24 -0
  114. package/dist/cli/options.js +9 -0
  115. package/dist/cli/setupCommands.js +108 -0
  116. package/dist/cli/types.js +1 -0
  117. package/dist/cli/utilityCommands.js +122 -0
  118. package/dist/cli.js +13 -383
  119. package/dist/cliApplicationCommands.js +176 -0
  120. package/dist/cliBrowserAdvancedCommands.js +73 -16
  121. package/dist/cliBrowserCommands.js +39 -115
  122. package/dist/cliCommandNames.js +17 -0
  123. package/dist/cliElectronCommands.js +100 -27
  124. package/dist/cliEvidenceCommands.js +13 -2
  125. package/dist/cliInvestigationCommands.js +53 -10
  126. package/dist/cliJsonInput.js +54 -0
  127. package/dist/cliObservationOptions.js +137 -0
  128. package/dist/cliPolicyCommands.js +80 -46
  129. package/dist/cliSetup.js +289 -0
  130. package/dist/config/environment.js +107 -0
  131. package/dist/config/parseConfig.js +228 -0
  132. package/dist/config/parsers.js +68 -0
  133. package/dist/config/permissions.js +30 -0
  134. package/dist/config/types.js +1 -0
  135. package/dist/config.js +1 -292
  136. package/dist/contracts/applicationToolContracts.js +225 -0
  137. package/dist/contracts/artifactToolContracts.js +5 -9
  138. package/dist/contracts/browserToolContracts.js +14 -62
  139. package/dist/contracts/electronToolContracts.js +45 -19
  140. package/dist/contracts/errorSchemas.js +1 -0
  141. package/dist/contracts/investigationExamples.js +0 -6
  142. package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
  143. package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
  144. package/dist/contracts/managedToolContracts.js +153 -0
  145. package/dist/contracts/managedWorkflowExamples.js +346 -0
  146. package/dist/contracts/managedWorkflowToolContracts.js +203 -0
  147. package/dist/contracts/nativeToolContracts.js +2 -6
  148. package/dist/contracts/promptContracts.js +18 -2
  149. package/dist/contracts/providerSelection.js +2 -0
  150. package/dist/contracts/toolContractExamples.js +10 -25
  151. package/dist/contracts/toolContracts.js +49 -47
  152. package/dist/contracts/toolEffects.js +174 -0
  153. package/dist/contracts/toolOutputSchemaGroups.js +232 -0
  154. package/dist/contracts/toolOutputSchemaPrimitives.js +327 -0
  155. package/dist/contracts/toolOutputSchemas.js +2 -535
  156. package/dist/doctorRuntime.js +42 -1
  157. package/dist/domain/analysisErrorPresentation.js +234 -0
  158. package/dist/domain/analysisErrorProjection.js +284 -0
  159. package/dist/domain/artifactComparison.js +37 -19
  160. package/dist/domain/binaryTarget.js +87 -37
  161. package/dist/domain/browserObservation.js +1 -282
  162. package/dist/domain/browserObservationSchemas.js +286 -0
  163. package/dist/domain/bundleComparison.js +4 -4
  164. package/dist/domain/electronObservation.js +13 -0
  165. package/dist/domain/electronStaticAnalysis.js +9 -0
  166. package/dist/domain/electronStaticAnalysisBrowser.js +206 -0
  167. package/dist/domain/electronStaticAnalysisIpc.js +171 -0
  168. package/dist/domain/electronStaticAnalysisNative.js +164 -0
  169. package/dist/domain/electronStaticAnalysisTypes.js +1 -0
  170. package/dist/domain/electronStaticAnalysisValues.js +103 -0
  171. package/dist/domain/errors.js +32 -448
  172. package/dist/domain/functionComparison.js +4 -165
  173. package/dist/domain/functionComparisonDimensions.js +164 -0
  174. package/dist/domain/functionComparisonSchemas.js +3 -8
  175. package/dist/domain/inputIssueProjection.js +52 -0
  176. package/dist/domain/javascriptApplicationAnalysis.js +155 -0
  177. package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
  178. package/dist/domain/javascriptApplicationEvidenceSchemas.js +18 -0
  179. package/dist/domain/javascriptApplicationGraph.js +2 -1
  180. package/dist/domain/javascriptApplicationGraphSchemas.js +7 -0
  181. package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
  182. package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
  183. package/dist/domain/javascriptApplicationVersionItems.js +233 -0
  184. package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
  185. package/dist/domain/javascriptExportInstrumentation.js +97 -0
  186. package/dist/domain/javascriptFeatureSeed.js +140 -0
  187. package/dist/domain/javascriptFeatureTrace.js +232 -0
  188. package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
  189. package/dist/domain/javascriptFeatureTraversal.js +100 -0
  190. package/dist/domain/javascriptNativeHandoff.js +85 -0
  191. package/dist/domain/javascriptReplay.js +361 -0
  192. package/dist/domain/javascriptRuntimeLoadState.js +106 -0
  193. package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
  194. package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
  195. package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
  196. package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
  197. package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
  198. package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
  199. package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
  200. package/dist/domain/javascriptRuntimeStaticCandidates.js +193 -0
  201. package/dist/domain/javascriptSemanticAnalysis.js +386 -0
  202. package/dist/domain/javascriptSemanticIr.js +30 -0
  203. package/dist/domain/javascriptSemanticProjection.js +366 -0
  204. package/dist/domain/javascriptSemanticState.js +40 -0
  205. package/dist/domain/javascriptSemanticTraversal.js +22 -0
  206. package/dist/domain/javascriptSemanticValues.js +352 -0
  207. package/dist/domain/javascriptStaticAnalysis.js +26 -254
  208. package/dist/domain/javascriptStaticAnalysisBundler.js +209 -0
  209. package/dist/domain/javascriptStaticAnalysisCalls.js +180 -0
  210. package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
  211. package/dist/domain/javascriptStaticAnalysisHelpers.js +81 -2
  212. package/dist/domain/javascriptStaticAnalysisState.js +6 -0
  213. package/dist/domain/knownPageCoverage.js +21 -0
  214. package/dist/domain/managedApplicationGraph.js +206 -0
  215. package/dist/domain/managedApplicationGraphCoverage.js +170 -0
  216. package/dist/domain/managedApplicationGraphNodeCoverage.js +6 -0
  217. package/dist/domain/managedApplicationGraphNodes.js +336 -0
  218. package/dist/domain/managedArtifact.js +452 -0
  219. package/dist/domain/managedMemberComparison.js +211 -0
  220. package/dist/domain/managedMemberComparisonCoverage.js +72 -0
  221. package/dist/domain/managedMemberComparisonMatch.js +356 -0
  222. package/dist/domain/managedNativeVerification.js +46 -0
  223. package/dist/domain/managedNativeVerificationMatch.js +272 -0
  224. package/dist/domain/managedNativeVerificationSchemas.js +141 -0
  225. package/dist/domain/managedReconstruction.js +196 -0
  226. package/dist/domain/managedRuntimeCorrelation.js +184 -0
  227. package/dist/domain/nodeRuntimeCharacterization.js +66 -0
  228. package/dist/domain/permissionPolicy.js +2 -0
  229. package/dist/domain/reconstructionCoverage.js +387 -0
  230. package/dist/domain/reconstructionCoverageEvaluation.js +212 -0
  231. package/dist/domain/reconstructionVerificationSchemas.js +9 -3
  232. package/dist/domain/runtimeCharacterization.js +85 -0
  233. package/dist/domain/webBundleAnalyzer.js +3 -409
  234. package/dist/domain/webBundleAnalyzerAst.js +77 -0
  235. package/dist/domain/webBundleAnalyzerInspection.js +307 -0
  236. package/dist/domain/webBundleAnalyzerResult.js +120 -0
  237. package/dist/dotnet/ManagedArtifactInspector.js +339 -0
  238. package/dist/dotnet/ManagedMemberInspector.js +153 -0
  239. package/dist/dotnet/ManagedMemberInspectorCore.js +297 -0
  240. package/dist/dotnet/ManagedMemberInstructionDecoder.js +427 -0
  241. package/dist/dotnet/ManagedMemberRows.js +120 -0
  242. package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
  243. package/dist/dotnet/ManagedMetadataInventory.js +104 -0
  244. package/dist/dotnet/ManagedMetadataInventoryRows.js +292 -0
  245. package/dist/dotnet/ManagedMetadataLayout.js +259 -0
  246. package/dist/dotnet/ManagedMetadataRowSizes.js +54 -0
  247. package/dist/dotnet/ManagedMethodBodyReader.js +143 -0
  248. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +311 -0
  249. package/dist/dotnet/ManagedNativeBoundaryInspector.js +143 -0
  250. package/dist/dotnet/ManagedPeReader.js +188 -0
  251. package/dist/dotnet/ManagedReaderFailure.js +10 -0
  252. package/dist/dotnet/ManagedStaticProvider.js +203 -0
  253. package/dist/generatedPackageMetadata.js +2 -2
  254. package/dist/ghidra/GhidraClient.js +76 -91
  255. package/dist/ghidra/GhidraClientStartup.js +29 -0
  256. package/dist/ghidra/GhidraClientWire.js +34 -0
  257. package/dist/ghidra/GhidraDefaults.js +1 -1
  258. package/dist/ghidra/GhidraDiagnostics.js +6 -1
  259. package/dist/ghidra/GhidraInstallation.js +20 -15
  260. package/dist/ghidra/GhidraLauncher.js +93 -29
  261. package/dist/ghidra/GhidraProvider.js +67 -161
  262. package/dist/ghidra/GhidraProviderCapabilities.js +173 -0
  263. package/dist/ghidra/GhidraSessionValues.js +2 -0
  264. package/dist/ghidra/GhidraSocketConnection.js +44 -7
  265. package/dist/ghidra/GhidraTargetSnapshot.js +30 -0
  266. package/dist/ghidra/GhidraTransport.js +71 -0
  267. package/dist/identity.js +3 -2
  268. package/dist/main/messages.js +5 -0
  269. package/dist/main/reload.js +49 -0
  270. package/dist/main/shutdown.js +25 -0
  271. package/dist/main/startup.js +14 -0
  272. package/dist/main/state.js +26 -0
  273. package/dist/main/transport.js +61 -0
  274. package/dist/main/types.js +1 -0
  275. package/dist/main.js +35 -132
  276. package/dist/process/PrivateRuntimeRoot.js +3 -2
  277. package/dist/process/ProcessOwnership.js +35 -0
  278. package/dist/process/ProviderProcess.js +2 -0
  279. package/dist/replay/JavaScriptReplayWorker.js +300 -0
  280. package/dist/replay/LinuxJavaScriptReplayRunner.js +217 -0
  281. package/dist/replay/LinuxJavaScriptReplaySandbox.js +140 -0
  282. package/dist/replay/LinuxRuntimeClosure.js +46 -0
  283. package/dist/replay/LinuxSeccompPolicy.js +40 -0
  284. package/dist/replay/ReplayOutcome.js +95 -0
  285. package/dist/replay/ReplayProcessLifecycle.js +71 -0
  286. package/dist/replay/ReplayWorkerProtocol.js +55 -0
  287. package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
  288. package/dist/server/ProcessCaptureElicitation.js +157 -0
  289. package/dist/server/createServer.js +158 -41
  290. package/dist/server/registerApplicationTools/characterization.js +57 -0
  291. package/dist/server/registerApplicationTools/compareVersions.js +34 -0
  292. package/dist/server/registerApplicationTools/controlledReplay.js +38 -0
  293. package/dist/server/registerApplicationTools/coverage.js +84 -0
  294. package/dist/server/registerApplicationTools/helpers.js +42 -0
  295. package/dist/server/registerApplicationTools/traceFeature.js +26 -0
  296. package/dist/server/registerApplicationTools/types.js +1 -0
  297. package/dist/server/registerApplicationTools.js +13 -0
  298. package/dist/server/registerArtifactComparisonTool.js +16 -9
  299. package/dist/server/registerBrowserTools.js +61 -60
  300. package/dist/server/registerBundleComparisonTool.js +17 -20
  301. package/dist/server/registerElectronTools.js +39 -12
  302. package/dist/server/registerEnhancedTools.js +52 -15
  303. package/dist/server/registerEvidenceResources.js +54 -0
  304. package/dist/server/registerEvidenceTools.js +5 -1
  305. package/dist/server/registerFunctionComparisonTool.js +14 -7
  306. package/dist/server/registerInvestigationTools/helpers.js +74 -0
  307. package/dist/server/registerInvestigationTools/types.js +1 -0
  308. package/dist/server/registerInvestigationTools.js +103 -132
  309. package/dist/server/registerManagedTools.js +6 -0
  310. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +65 -0
  311. package/dist/server/registerManagedWorkflowTools/contract.js +8 -0
  312. package/dist/server/registerManagedWorkflowTools/evidence.js +43 -0
  313. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +39 -0
  314. package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +39 -0
  315. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +52 -0
  316. package/dist/server/registerManagedWorkflowTools/types.js +1 -0
  317. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +75 -0
  318. package/dist/server/registerManagedWorkflowTools.js +13 -0
  319. package/dist/server/registerOfficialTools.js +81 -67
  320. package/dist/server/registerProcessComparisonTool.js +25 -47
  321. package/dist/server/registerSessionRecordTools.js +137 -0
  322. package/dist/server/registerSessionStatusTool.js +9 -8
  323. package/dist/server/registerSessionTools.js +77 -216
  324. package/dist/server/sessionAvailabilityPolicy.js +10 -0
  325. package/dist/server/sessionEvidence.js +14 -19
  326. package/dist/server/toolInputValidation.js +77 -0
  327. package/dist/server/toolRegistrationOptions.js +177 -2
  328. package/dist/server/toolResult.js +30 -17
  329. package/package.json +21 -14
  330. package/scripts/rea.mjs +1 -1
  331. package/skills/{rea-analysis → reverse-engineer-anything}/SKILL.md +75 -6
  332. package/scripts/prepare-node-pty.mjs +0 -35
  333. package/scripts/rebuild-native.mjs +0 -22
@@ -0,0 +1,184 @@
1
+ import { createHash } from "node:crypto";
2
+ import canonicalize from "canonicalize";
3
+ import { z } from "zod";
4
+ import { evidenceSchema, parseEvidence } from "./evidence.js";
5
+ import { cliMetadataGuidSchema, managedMemberInspectionSchema, } from "./managedArtifact.js";
6
+ const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u);
7
+ const evidenceIdSchema = z.string().regex(/^ev_[a-f0-9]{64}$/u);
8
+ const tokenSchema = z.string().regex(/^0x[0-9a-f]{8}$/u);
9
+ const boundedTextSchema = z.string().min(1).max(4_096);
10
+ const managedRuntimeEffectSchema = z.enum([
11
+ "attach",
12
+ "load",
13
+ "debugger",
14
+ "reflection",
15
+ "instrumentation",
16
+ ]);
17
+ const managedRuntimeHostSchema = z.strictObject({
18
+ os: z.enum(["linux", "macos", "windows"]),
19
+ clr_family: z.enum(["dotnet", "dotnet-framework", "mono", "unknown"]),
20
+ architecture: z.enum(["x86", "x86_64", "arm", "arm64"]),
21
+ });
22
+ const managedRuntimeBoundsSchema = z.strictObject({
23
+ timeout_ms: z.number().int().min(1).max(60_000).default(5_000),
24
+ max_threads: z.number().int().min(1).max(256).default(32),
25
+ max_output_bytes: z.number().int().min(0).max(1_048_576).default(65_536),
26
+ allow_network: z.literal(false).default(false),
27
+ allow_ui: z.literal(false).default(false),
28
+ });
29
+ export const managedRuntimeCorrelationInputSchema = z.strictObject({
30
+ static_members: evidenceSchema,
31
+ method: z.strictObject({
32
+ token: tokenSchema,
33
+ signature_sha256: digestSchema,
34
+ normalized_il_sha256: digestSchema.nullable(),
35
+ }),
36
+ requested_effect: managedRuntimeEffectSchema,
37
+ host: managedRuntimeHostSchema,
38
+ bounds: managedRuntimeBoundsSchema.default({
39
+ timeout_ms: 5_000,
40
+ max_threads: 32,
41
+ max_output_bytes: 65_536,
42
+ allow_network: false,
43
+ allow_ui: false,
44
+ }),
45
+ unknown_registry_approved: z.literal(true).optional(),
46
+ });
47
+ export const managedRuntimeCorrelationResultSchema = z.strictObject({
48
+ schema_version: z.literal(1),
49
+ correlation_id: z.string().regex(/^mrc_[a-f0-9]{64}$/u),
50
+ phase: z.literal("admission-plan"),
51
+ executed: z.literal(false),
52
+ authority_model: z.strictObject({
53
+ capability: z.literal("managed_runtime"),
54
+ permission_grant_id: z.string().min(1),
55
+ default_enabled: z.literal(false),
56
+ per_call_approval_required: z.literal(true),
57
+ }),
58
+ static_observation: z.strictObject({
59
+ evidence_id: evidenceIdSchema,
60
+ artifact_sha256: digestSchema,
61
+ artifact_path: z.string().min(1),
62
+ byte_length: z.number().int().min(0),
63
+ module_name: z.string().nullable(),
64
+ mvid: cliMetadataGuidSchema.nullable(),
65
+ metadata_status: z.enum(["absent", "complete", "partial", "malformed"]),
66
+ }),
67
+ method_lock: z.strictObject({
68
+ token: tokenSchema,
69
+ declaring_type: z.string().nullable(),
70
+ name: z.string(),
71
+ signature_sha256: digestSchema,
72
+ normalized_il_sha256: digestSchema.nullable(),
73
+ body_sha256: digestSchema.nullable(),
74
+ il_size: z.number().int().min(0),
75
+ body_status: z.enum([
76
+ "present",
77
+ "partial",
78
+ "absent",
79
+ "malformed",
80
+ "too-large",
81
+ ]),
82
+ exact_build_required: z.literal(true),
83
+ }),
84
+ requested_runtime: z.strictObject({
85
+ effect: managedRuntimeEffectSchema,
86
+ host: managedRuntimeHostSchema,
87
+ executable_path: z.string().min(1),
88
+ network: z.literal("none"),
89
+ filesystem: z.literal("owned-artifacts-only"),
90
+ }),
91
+ effect_taxonomy: z.strictObject({
92
+ attaches_process: z.boolean(),
93
+ loads_target: z.boolean(),
94
+ uses_debugger: z.boolean(),
95
+ uses_reflection: z.boolean(),
96
+ instruments_code: z.boolean(),
97
+ invokes_target_code: z.literal(false),
98
+ }),
99
+ bounds: managedRuntimeBoundsSchema,
100
+ unsupported_until_executor_exists: z.literal(true),
101
+ evidence_links: z.array(evidenceIdSchema).length(1),
102
+ limitations: z.array(boundedTextSchema).max(1_000),
103
+ });
104
+ const sha256 = (value) => {
105
+ const serialized = canonicalize(value);
106
+ if (serialized === undefined)
107
+ throw new TypeError("Managed runtime correlation canonicalization failed");
108
+ return createHash("sha256").update(serialized).digest("hex");
109
+ };
110
+ /** Authenticate static managed Evidence and build a non-executing runtime plan. */
111
+ export const planManagedRuntimeCorrelation = (input, executablePath, permissionGrantId) => {
112
+ const staticEvidence = parseEvidence(input.static_members);
113
+ if (staticEvidence.operation !== "inspect_managed_members")
114
+ throw new TypeError("Evidence operation is not inspect_managed_members");
115
+ const members = managedMemberInspectionSchema.parse(staticEvidence.normalized_result);
116
+ const method = members.methods.items.find((item) => item.token === input.method.token &&
117
+ item.signature.raw_sha256 === input.method.signature_sha256 &&
118
+ item.body.status === "present" &&
119
+ item.body.normalized_il_sha256 !== null &&
120
+ input.method.normalized_il_sha256 !== null &&
121
+ item.body.normalized_il_sha256 === input.method.normalized_il_sha256);
122
+ if (method === undefined)
123
+ throw new TypeError("Requested method lock does not match a static managed member observation");
124
+ const withoutId = {
125
+ schema_version: 1,
126
+ phase: "admission-plan",
127
+ executed: false,
128
+ authority_model: {
129
+ capability: "managed_runtime",
130
+ permission_grant_id: permissionGrantId,
131
+ default_enabled: false,
132
+ per_call_approval_required: true,
133
+ },
134
+ static_observation: {
135
+ evidence_id: staticEvidence.evidence_id,
136
+ artifact_sha256: members.artifact.sha256,
137
+ artifact_path: members.artifact.path,
138
+ byte_length: members.artifact.byte_length,
139
+ module_name: members.module?.name ?? null,
140
+ mvid: members.module?.mvid ?? null,
141
+ metadata_status: members.metadata.status,
142
+ },
143
+ method_lock: {
144
+ token: method.token,
145
+ declaring_type: method.declaring_type,
146
+ name: method.name,
147
+ signature_sha256: method.signature.raw_sha256,
148
+ normalized_il_sha256: method.body.normalized_il_sha256,
149
+ body_sha256: method.body.il_sha256,
150
+ il_size: method.body.il_size,
151
+ body_status: method.body.status,
152
+ exact_build_required: true,
153
+ },
154
+ requested_runtime: {
155
+ effect: input.requested_effect,
156
+ host: input.host,
157
+ executable_path: executablePath,
158
+ network: "none",
159
+ filesystem: "owned-artifacts-only",
160
+ },
161
+ effect_taxonomy: effectTaxonomy(input.requested_effect),
162
+ bounds: input.bounds,
163
+ unsupported_until_executor_exists: true,
164
+ evidence_links: [staticEvidence.evidence_id],
165
+ limitations: [
166
+ "This operation admits and records a runtime-correlation plan only; it did not attach, load, debug, reflect, instrument, invoke, or execute target code.",
167
+ "Runtime agreement would be a separate runtime observation and would not retroactively turn static inference into a byte observation.",
168
+ "The exact artifact SHA-256, MVID, method signature, and normalized IL shape must match before any future executor can run.",
169
+ "Network and UI effects are not admitted by this contract.",
170
+ ],
171
+ };
172
+ return managedRuntimeCorrelationResultSchema.parse({
173
+ ...withoutId,
174
+ correlation_id: `mrc_${sha256(withoutId)}`,
175
+ });
176
+ };
177
+ const effectTaxonomy = (effect) => ({
178
+ attaches_process: effect === "attach",
179
+ loads_target: effect === "load" || effect === "reflection",
180
+ uses_debugger: effect === "debugger",
181
+ uses_reflection: effect === "reflection",
182
+ instruments_code: effect === "instrumentation",
183
+ invokes_target_code: false,
184
+ });
@@ -0,0 +1,66 @@
1
+ import { z } from "zod";
2
+ import { controlledReplayInputSchema, controlledReplayOutputSchema, } from "./javascriptReplay.js";
3
+ import { javascriptExportInstrumentationInputSchema, javascriptExportTransformationManifestSchema, } from "./javascriptExportInstrumentation.js";
4
+ import { runtimeCharacterizationPlanSchema } from "./runtimeCharacterization.js";
5
+ import { evidenceRecordSchema } from "./evidence.js";
6
+ const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u);
7
+ export const nodeCharacterizationPreparationInputSchema = z
8
+ .strictObject({
9
+ preparation_approved: z.literal(true),
10
+ selected_alias: z.string().min(1).max(200),
11
+ expected_effect: z.enum(["pure", "observation-only"]),
12
+ instrumentation: javascriptExportInstrumentationInputSchema,
13
+ replay: controlledReplayInputSchema,
14
+ })
15
+ .superRefine((input, context) => {
16
+ if (input.replay.mode !== "plan")
17
+ context.addIssue({
18
+ code: "custom",
19
+ path: ["replay", "mode"],
20
+ message: "Characterization preparation requires replay plan mode",
21
+ });
22
+ const selected = input.replay.left.modules.filter(({ alias }) => alias === input.selected_alias);
23
+ if (selected.length !== 1 ||
24
+ selected[0]?.path !== input.instrumentation.artifact_path ||
25
+ selected[0]?.format !== "commonjs-factory")
26
+ context.addIssue({
27
+ code: "custom",
28
+ path: ["selected_alias"],
29
+ message: "Selected alias must identify exactly one commonjs-factory instrumented artifact",
30
+ });
31
+ if (input.replay.left.entry_alias !== input.selected_alias)
32
+ context.addIssue({
33
+ code: "custom",
34
+ path: ["replay", "left", "entry_alias"],
35
+ message: "Instrumented alias must be the characterization entry",
36
+ });
37
+ if (input.replay.left.entry_export !==
38
+ input.instrumentation.selection.export_name)
39
+ context.addIssue({
40
+ code: "custom",
41
+ path: ["replay", "left", "entry_export"],
42
+ message: "Replay entry export must match the instrumented export",
43
+ });
44
+ });
45
+ export const nodeCharacterizationExecutionInputSchema = z.strictObject({
46
+ execution_approved: z.literal(true),
47
+ approved_plan_sha256: digestSchema,
48
+ preparation: nodeCharacterizationPreparationInputSchema,
49
+ });
50
+ export const nodeCharacterizationPreparationOutputSchema = z.strictObject({
51
+ schema_version: z.literal(1),
52
+ phase: z.literal("preparation"),
53
+ plan: runtimeCharacterizationPlanSchema,
54
+ transformation: javascriptExportTransformationManifestSchema,
55
+ transformation_evidence: evidenceRecordSchema,
56
+ replay: controlledReplayOutputSchema,
57
+ });
58
+ export const nodeCharacterizationExecutionOutputSchema = z.strictObject({
59
+ schema_version: z.literal(1),
60
+ phase: z.literal("execution"),
61
+ plan: runtimeCharacterizationPlanSchema,
62
+ transformation: javascriptExportTransformationManifestSchema,
63
+ transformation_evidence: evidenceRecordSchema,
64
+ evidence: evidenceRecordSchema,
65
+ replay: controlledReplayOutputSchema,
66
+ });
@@ -65,6 +65,8 @@ export const evaluatePermission = (policy, request, now = new Date()) => {
65
65
  missing: missingFromScopes(normalized, candidates),
66
66
  };
67
67
  };
68
+ /** Test whether one exact request is wholly contained by one ceiling. */
69
+ export const isPermissionRequestWithinCeiling = (request, ceiling) => !hasMissing(missingFromScopes(normalizeRequest(request), [ceiling]));
68
70
  /** Consume an allowed one-shot decision; longer-lived grants are unchanged. */
69
71
  export const consumePermission = (policy, decision) => decision.lifetime === "once"
70
72
  ? {
@@ -0,0 +1,387 @@
1
+ import { createHash } from "node:crypto";
2
+ import canonicalize from "canonicalize";
3
+ import { z } from "zod";
4
+ import { evidenceBundleSchema, parseEvidenceBundle } from "./evidenceBundle.js";
5
+ import { evaluateReconstructionClaims, evaluateReconstructionPackageProofs, evaluateReconstructionSurfaces, evaluateReconstructionWorkspaceRisks, recommendedReconstructionProbes, } from "./reconstructionCoverageEvaluation.js";
6
+ const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u);
7
+ const evidenceIdSchema = z.string().regex(/^ev_[a-f0-9]{64}$/u);
8
+ const stableIdSchema = z.string().regex(/^[A-Za-z][A-Za-z0-9._:/-]{0,199}$/u);
9
+ const boundedTextSchema = z.string().trim().min(1).max(4_096);
10
+ const authoritySchema = z.enum([
11
+ "observed",
12
+ "derived",
13
+ "inferred",
14
+ "historical",
15
+ "external",
16
+ ]);
17
+ const artifactSchema = z.strictObject({
18
+ artifact_id: stableIdSchema,
19
+ artifact_sha256: digestSchema,
20
+ version: z.string().trim().min(1).max(500),
21
+ environment_sha256: digestSchema,
22
+ evidence_ids: z.array(evidenceIdSchema).min(1).max(1_000),
23
+ });
24
+ const surfaceSchema = z.strictObject({
25
+ surface_id: stableIdSchema,
26
+ family: z.string().trim().min(1).max(100),
27
+ artifact_id: stableIdSchema,
28
+ occurrence_id: z.string().trim().min(1).max(500).nullable(),
29
+ location: boundedTextSchema,
30
+ authority: authoritySchema,
31
+ dependency_surface_ids: z.array(stableIdSchema).max(1_000),
32
+ evidence_ids: z.array(evidenceIdSchema).min(1).max(1_000),
33
+ });
34
+ const implementationOwnerSchema = z.strictObject({
35
+ disposition: z.literal("implemented"),
36
+ owner_path: boundedTextSchema,
37
+ owner_export: z.string().trim().min(1).max(500).nullable(),
38
+ owner_sha256: digestSchema,
39
+ path_state: z.enum(["present", "missing", "unknown"]),
40
+ package_state: z.enum(["distributed", "missing", "unknown"]),
41
+ authority_route: z.enum(["none", "detected", "unknown"]),
42
+ });
43
+ const externalOwnerSchema = z.strictObject({
44
+ disposition: z.enum(["external", "non-goal"]),
45
+ rationale: boundedTextSchema,
46
+ });
47
+ const ownerSchema = z.strictObject({
48
+ surface_id: stableIdSchema,
49
+ ownership: z.discriminatedUnion("disposition", [
50
+ implementationOwnerSchema,
51
+ externalOwnerSchema,
52
+ ]),
53
+ });
54
+ const claimSchema = z.strictObject({
55
+ claim_id: stableIdSchema,
56
+ title: z.string().trim().min(1).max(500),
57
+ kind: z.string().trim().min(1).max(100),
58
+ surface_ids: z.array(stableIdSchema).min(1).max(1_000),
59
+ required_dimensions: z.array(stableIdSchema).min(1).max(100),
60
+ required_authority: z.enum([
61
+ "shipped-artifact",
62
+ "controlled-replay",
63
+ "live-observation",
64
+ "external",
65
+ ]),
66
+ });
67
+ const verifierContractBaseSchema = z.strictObject({
68
+ verifier_id: stableIdSchema,
69
+ claim_ids: z.array(stableIdSchema).min(1).max(1_000),
70
+ dimensions: z.array(stableIdSchema).min(1).max(100),
71
+ authority: z.enum([
72
+ "shipped-artifact",
73
+ "controlled-replay",
74
+ "live-observation",
75
+ "external",
76
+ ]),
77
+ max_age_ms: z.number().int().min(1).max(Number.MAX_SAFE_INTEGER),
78
+ minimum_repeats: z.number().int().min(1).max(1_000),
79
+ normalization_sha256: digestSchema,
80
+ normalization_removes_dimensions: z.literal(false),
81
+ });
82
+ const verifierContractSchema = verifierContractBaseSchema.extend({
83
+ contract_sha256: digestSchema,
84
+ });
85
+ const verifierResultSchema = z.strictObject({
86
+ verifier_id: stableIdSchema,
87
+ contract_sha256: digestSchema,
88
+ observed_at: z.string().datetime({ offset: true }),
89
+ status: z.enum([
90
+ "pass",
91
+ "fail",
92
+ "unknown",
93
+ "unsupported",
94
+ "truncated",
95
+ "skipped",
96
+ ]),
97
+ covered_claim_ids: z.array(stableIdSchema).min(1).max(1_000),
98
+ covered_dimensions: z.array(stableIdSchema).min(1).max(100),
99
+ artifact_sha256s: z.array(digestSchema).min(1).max(1_000),
100
+ owner_sha256s: z.array(digestSchema).max(1_000),
101
+ normalization_sha256: digestSchema,
102
+ repeats: z.number().int().min(1).max(1_000),
103
+ evidence_ids: z.array(evidenceIdSchema).min(1).max(1_000),
104
+ });
105
+ const contradictionSchema = z.strictObject({
106
+ contradiction_id: stableIdSchema,
107
+ status: z.enum(["active", "resolved"]),
108
+ surface_ids: z.array(stableIdSchema).max(1_000),
109
+ claim_ids: z.array(stableIdSchema).max(1_000),
110
+ evidence_ids: z.array(evidenceIdSchema).min(2).max(1_000),
111
+ });
112
+ const packageProofSchema = z.strictObject({
113
+ proof_id: stableIdSchema,
114
+ kind: z.enum([
115
+ "build",
116
+ "clean-install",
117
+ "package-contents",
118
+ "runtime-routing",
119
+ "authority-independence",
120
+ ]),
121
+ status: z.enum(["pass", "fail", "unknown", "unsupported", "skipped"]),
122
+ artifact_sha256s: z.array(digestSchema).min(1).max(1_000),
123
+ evidence_ids: z.array(evidenceIdSchema).min(1).max(1_000),
124
+ });
125
+ const boundarySchema = z.strictObject({
126
+ boundary_id: stableIdSchema,
127
+ title: z.string().trim().min(1).max(500),
128
+ required_surface_ids: z.array(stableIdSchema).min(1).max(10_000),
129
+ required_claim_ids: z.array(stableIdSchema).min(1).max(10_000),
130
+ required_package_proof_kinds: z
131
+ .array(packageProofSchema.shape.kind)
132
+ .min(1)
133
+ .max(5),
134
+ allowed_dispositions: z.array(z.enum(["external", "non-goal"])).max(2),
135
+ allowed_unknown_ids: z.array(stableIdSchema).max(1_000),
136
+ });
137
+ const workspaceSemanticSchema = z.strictObject({
138
+ schema_version: z.literal(1),
139
+ workspace_id: z.string().regex(/^rcw_[a-f0-9]{64}$/u),
140
+ name: z.string().trim().min(1).max(200),
141
+ revision: z.number().int().min(1),
142
+ previous_revision_sha256: digestSchema.nullable(),
143
+ evidence_bundle: evidenceBundleSchema,
144
+ artifacts: z.array(artifactSchema).max(1_000),
145
+ surfaces: z.array(surfaceSchema).max(10_000),
146
+ owners: z.array(ownerSchema).max(10_000),
147
+ claims: z.array(claimSchema).max(10_000),
148
+ verifier_contracts: z.array(verifierContractSchema).max(10_000),
149
+ verifier_results: z.array(verifierResultSchema).max(100_000),
150
+ residual_unknown_ids: z.array(stableIdSchema).max(10_000),
151
+ contradictions: z.array(contradictionSchema).max(10_000),
152
+ package_proofs: z.array(packageProofSchema).max(10_000),
153
+ boundaries: z.array(boundarySchema).max(1_000),
154
+ });
155
+ export const reconstructionCoverageWorkspaceSchema = workspaceSemanticSchema.extend({ revision_sha256: digestSchema });
156
+ const closureReasonSchema = z.strictObject({
157
+ code: z.enum([
158
+ "surface-missing",
159
+ "owner-missing",
160
+ "owner-duplicate",
161
+ "owner-path-missing",
162
+ "owner-path-unknown",
163
+ "owner-undistributed",
164
+ "owner-distribution-unknown",
165
+ "authority-routing-detected",
166
+ "authority-routing-unknown",
167
+ "disposition-not-allowed",
168
+ "dependency-surface-missing",
169
+ "claim-missing",
170
+ "verifier-missing",
171
+ "verifier-duplicate",
172
+ "verifier-result-missing",
173
+ "verifier-result-stale",
174
+ "verifier-result-incompatible",
175
+ "verifier-failed",
176
+ "verifier-unknown",
177
+ "active-unknown",
178
+ "active-contradiction",
179
+ "package-proof-missing",
180
+ "package-proof-failed",
181
+ "package-proof-unknown",
182
+ ]),
183
+ subject_id: stableIdSchema,
184
+ detail: boundedTextSchema,
185
+ });
186
+ export const reconstructionClosureResultSchema = z.strictObject({
187
+ boundary_id: stableIdSchema,
188
+ status: z.enum(["partial", "failed", "unknown", "ready"]),
189
+ workspace_revision_sha256: digestSchema,
190
+ summary: z.strictObject({
191
+ required_surfaces: z.number().int().min(0),
192
+ required_claims: z.number().int().min(0),
193
+ reasons: z.number().int().min(0),
194
+ }),
195
+ reasons: z.array(closureReasonSchema).max(100_000),
196
+ recommended_probes: z
197
+ .array(z.strictObject({
198
+ operation: stableIdSchema,
199
+ subject_id: stableIdSchema,
200
+ rationale: boundedTextSchema,
201
+ }))
202
+ .max(100_000),
203
+ evidence_ids: z.array(evidenceIdSchema).max(100_000),
204
+ });
205
+ /** Build a verifier contract whose digest prevents retrospective coverage edits. */
206
+ export const createReconstructionVerifierContract = (input) => {
207
+ const parsed = verifierContractBaseSchema.parse(input);
208
+ return verifierContractSchema.parse({
209
+ ...parsed,
210
+ contract_sha256: digest(parsed),
211
+ });
212
+ };
213
+ /** Build one canonical immutable coverage-workspace revision. */
214
+ export const createReconstructionCoverageWorkspace = (input) => {
215
+ const semanticInput = {
216
+ schema_version: 1,
217
+ workspace_id: `rcw_${digest({ schema: "rea.reconstruction-coverage-workspace/v1", name: input.name })}`,
218
+ ...input,
219
+ };
220
+ const semantic = canonicalWorkspace(workspaceSemanticSchema.parse(semanticInput));
221
+ validateWorkspaceReferences(semantic);
222
+ return reconstructionCoverageWorkspaceSchema.parse({
223
+ ...semantic,
224
+ revision_sha256: digest(semantic),
225
+ });
226
+ };
227
+ /** Parse persisted coverage state and verify canonical order, references, and digests. */
228
+ export const parseReconstructionCoverageWorkspace = (input) => {
229
+ const parsed = reconstructionCoverageWorkspaceSchema.parse(input);
230
+ const rebuilt = createReconstructionCoverageWorkspace({
231
+ name: parsed.name,
232
+ revision: parsed.revision,
233
+ previous_revision_sha256: parsed.previous_revision_sha256,
234
+ evidence_bundle: parsed.evidence_bundle,
235
+ artifacts: parsed.artifacts,
236
+ surfaces: parsed.surfaces,
237
+ owners: parsed.owners,
238
+ claims: parsed.claims,
239
+ verifier_contracts: parsed.verifier_contracts,
240
+ verifier_results: parsed.verifier_results,
241
+ residual_unknown_ids: parsed.residual_unknown_ids,
242
+ contradictions: parsed.contradictions,
243
+ package_proofs: parsed.package_proofs,
244
+ boundaries: parsed.boundaries,
245
+ });
246
+ if (parsed.workspace_id !== rebuilt.workspace_id ||
247
+ parsed.revision_sha256 !== rebuilt.revision_sha256 ||
248
+ JSON.stringify(parsed) !== JSON.stringify(rebuilt))
249
+ throw new TypeError("Reconstruction coverage workspace is not canonical");
250
+ return rebuilt;
251
+ };
252
+ /** Serialize one validated coverage revision as byte-stable canonical JSON. */
253
+ export const serializeReconstructionCoverageWorkspace = (workspace) => {
254
+ const encoded = canonicalize(parseReconstructionCoverageWorkspace(workspace));
255
+ if (encoded === undefined)
256
+ throw new TypeError("Reconstruction coverage workspace is not canonical JSON");
257
+ return encoded;
258
+ };
259
+ /** Evaluate one named completion boundary without inferring undiscovered coverage. */
260
+ export const evaluateReconstructionClosure = (workspaceInput, boundaryId, nowEpochMs) => {
261
+ const workspace = parseReconstructionCoverageWorkspace(workspaceInput);
262
+ const boundary = workspace.boundaries.find(({ boundary_id: id }) => id === boundaryId);
263
+ if (boundary === undefined)
264
+ throw new TypeError(`Unknown reconstruction boundary: ${boundaryId}`);
265
+ const context = {
266
+ workspace,
267
+ boundary,
268
+ nowEpochMs,
269
+ reasons: [],
270
+ evidenceIds: new Set(),
271
+ };
272
+ evaluateReconstructionSurfaces(context);
273
+ evaluateReconstructionClaims(context);
274
+ evaluateReconstructionWorkspaceRisks(context);
275
+ evaluateReconstructionPackageProofs(context);
276
+ const reasons = [...context.reasons].sort(reasonOrder);
277
+ return reconstructionClosureResultSchema.parse({
278
+ boundary_id: boundary.boundary_id,
279
+ status: closureStatus(reasons),
280
+ workspace_revision_sha256: workspace.revision_sha256,
281
+ summary: {
282
+ required_surfaces: boundary.required_surface_ids.length,
283
+ required_claims: boundary.required_claim_ids.length,
284
+ reasons: reasons.length,
285
+ },
286
+ reasons,
287
+ recommended_probes: recommendedReconstructionProbes(reasons),
288
+ evidence_ids: [...context.evidenceIds].sort(),
289
+ });
290
+ };
291
+ const validateWorkspaceReferences = (workspace) => {
292
+ const evidenceBundle = parseEvidenceBundle(workspace.evidence_bundle);
293
+ const evidenceIds = new Set(evidenceBundle.records.map(({ evidence_id: id }) => id));
294
+ const unknownIds = new Set(evidenceBundle.unknowns.map(({ unknown_id: id }) => id));
295
+ const artifacts = assertUnique(workspace.artifacts, "artifact_id");
296
+ const surfaces = assertUnique(workspace.surfaces, "surface_id");
297
+ const claims = assertUnique(workspace.claims, "claim_id");
298
+ const contracts = assertUnique(workspace.verifier_contracts, "verifier_id");
299
+ assertUnique(workspace.contradictions, "contradiction_id");
300
+ assertUnique(workspace.package_proofs, "proof_id");
301
+ assertUnique(workspace.boundaries, "boundary_id");
302
+ for (const contract of workspace.verifier_contracts) {
303
+ const { contract_sha256: contractSha256, ...base } = contract;
304
+ if (contractSha256 !== digest(verifierContractBaseSchema.parse(base)))
305
+ throw new TypeError(`Verifier contract digest is invalid: ${contract.verifier_id}`);
306
+ }
307
+ for (const surface of workspace.surfaces)
308
+ if (!artifacts.has(surface.artifact_id))
309
+ throw new TypeError(`Surface artifact is missing: ${surface.surface_id}`);
310
+ for (const owner of workspace.owners)
311
+ if (!surfaces.has(owner.surface_id))
312
+ throw new TypeError(`Owner surface is missing: ${owner.surface_id}`);
313
+ for (const claim of workspace.claims)
314
+ if (claim.surface_ids.some((id) => !surfaces.has(id)))
315
+ throw new TypeError(`Claim surface is missing: ${claim.claim_id}`);
316
+ for (const contract of workspace.verifier_contracts)
317
+ if (contract.claim_ids.some((id) => !claims.has(id)))
318
+ throw new TypeError(`Verifier claim is missing: ${contract.verifier_id}`);
319
+ for (const result of workspace.verifier_results)
320
+ if (!contracts.has(result.verifier_id))
321
+ throw new TypeError(`Verifier result contract is missing: ${result.verifier_id}`);
322
+ const referencedEvidenceIds = [
323
+ ...workspace.artifacts.flatMap(({ evidence_ids: ids }) => ids),
324
+ ...workspace.surfaces.flatMap(({ evidence_ids: ids }) => ids),
325
+ ...workspace.verifier_results.flatMap(({ evidence_ids: ids }) => ids),
326
+ ...workspace.contradictions.flatMap(({ evidence_ids: ids }) => ids),
327
+ ...workspace.package_proofs.flatMap(({ evidence_ids: ids }) => ids),
328
+ ];
329
+ const danglingEvidence = referencedEvidenceIds.find((id) => !evidenceIds.has(id));
330
+ if (danglingEvidence !== undefined)
331
+ throw new TypeError(`Coverage workspace Evidence is missing: ${danglingEvidence}`);
332
+ const danglingUnknown = workspace.residual_unknown_ids.find((id) => !unknownIds.has(id));
333
+ if (danglingUnknown !== undefined)
334
+ throw new TypeError(`Coverage workspace residual unknown is missing: ${danglingUnknown}`);
335
+ };
336
+ const canonicalWorkspace = (workspace) => ({
337
+ ...workspace,
338
+ artifacts: sorted(workspace.artifacts, "artifact_id"),
339
+ surfaces: sorted(workspace.surfaces, "surface_id"),
340
+ owners: [...workspace.owners].sort((left, right) => left.surface_id.localeCompare(right.surface_id)),
341
+ claims: sorted(workspace.claims, "claim_id"),
342
+ verifier_contracts: sorted(workspace.verifier_contracts, "verifier_id"),
343
+ verifier_results: [...workspace.verifier_results].sort((left, right) => `${left.verifier_id}:${left.observed_at}`.localeCompare(`${right.verifier_id}:${right.observed_at}`)),
344
+ residual_unknown_ids: [...new Set(workspace.residual_unknown_ids)].sort(),
345
+ contradictions: sorted(workspace.contradictions, "contradiction_id"),
346
+ package_proofs: sorted(workspace.package_proofs, "proof_id"),
347
+ boundaries: sorted(workspace.boundaries, "boundary_id"),
348
+ });
349
+ const sorted = (items, key) => [...items].sort((left, right) => left[key].localeCompare(right[key]));
350
+ const assertUnique = (items, key) => {
351
+ const values = items.map((item) => item[key]);
352
+ if (new Set(values).size !== values.length)
353
+ throw new TypeError(`Duplicate reconstruction coverage ${String(key)}`);
354
+ return new Set(values);
355
+ };
356
+ const closureStatus = (reasons) => {
357
+ if (reasons.length === 0)
358
+ return "ready";
359
+ if (reasons.some(({ code }) => [
360
+ "verifier-failed",
361
+ "active-contradiction",
362
+ "authority-routing-detected",
363
+ "owner-path-missing",
364
+ "owner-undistributed",
365
+ "package-proof-failed",
366
+ ].includes(code)))
367
+ return "failed";
368
+ if (reasons.some(({ code }) => [
369
+ "verifier-result-stale",
370
+ "verifier-result-incompatible",
371
+ "verifier-unknown",
372
+ "active-unknown",
373
+ "owner-path-unknown",
374
+ "owner-distribution-unknown",
375
+ "authority-routing-unknown",
376
+ "package-proof-unknown",
377
+ ].includes(code)))
378
+ return "unknown";
379
+ return "partial";
380
+ };
381
+ const reasonOrder = (left, right) => `${left.code}:${left.subject_id}`.localeCompare(`${right.code}:${right.subject_id}`);
382
+ const digest = (value) => {
383
+ const encoded = canonicalize(value);
384
+ if (encoded === undefined)
385
+ throw new TypeError("Reconstruction coverage value is not canonical JSON");
386
+ return createHash("sha256").update(encoded).digest("hex");
387
+ };