@agenthippo-ai/agenthippo 1.110.9 → 1.110.19

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 (533) hide show
  1. package/out/agentpack/types.js +2 -5
  2. package/out/analytics/dashboard/artifactManager.js +2 -439
  3. package/out/analytics/dashboard/fleetDisplayUtils.js +2 -162
  4. package/out/analytics/dashboard/fleetOrchestrator.js +3 -142
  5. package/out/analytics/dashboard/fleetRegistry.js +2 -79
  6. package/out/analytics/dashboard/fleetRowDefaults.js +2 -87
  7. package/out/analytics/dashboard/fleetScriptAdapter.js +2 -146
  8. package/out/analytics/dashboard/fleetTypes.js +2 -29
  9. package/out/analytics/dashboard/index.js +2 -17
  10. package/out/analytics/dashboard/indexingService.js +2 -422
  11. package/out/analytics/dashboard/localFleetAdapter.js +2 -222
  12. package/out/analytics/dashboard/performanceMonitor.js +5 -76
  13. package/out/analytics/dashboard/processManager.js +2 -209
  14. package/out/analytics/dashboard/provider.js +38 -3817
  15. package/out/analytics/dashboard/queryRunner.js +62 -750
  16. package/out/analytics/dashboard/scheduledFleetStorage.js +2 -241
  17. package/out/analytics/dashboard/sessionJsonlFleet.js +3 -204
  18. package/out/analytics/dashboard/teamViewDiscovery.js +2 -106
  19. package/out/analytics/dashboard/webview/panel.js +34 -2318
  20. package/out/analytics/dashboard/webview/runtime-bridge.js +2 -82
  21. package/out/analytics/lifecycle.js +2 -43
  22. package/out/analytics/service.js +8 -1277
  23. package/out/auth/authBaseUrl.js +2 -59
  24. package/out/auth/bootstrapApply.js +2 -71
  25. package/out/auth/brokerClient.js +2 -160
  26. package/out/auth/callbackUri.js +2 -59
  27. package/out/auth/githubStoreGate.js +2 -70
  28. package/out/auth/loopbackAuthServer.js +4 -159
  29. package/out/auth/onboardingPrompt.js +2 -112
  30. package/out/auth/pkce.js +2 -9
  31. package/out/auth/provider.js +2 -226
  32. package/out/auth/sessionStore.js +2 -156
  33. package/out/auth/signInFlow.js +2 -183
  34. package/out/cli/index.js +619 -551
  35. package/out/cli/run-custom-engine-runner.js +3 -318
  36. package/out/cli/vscode-shim.js +2 -86
  37. package/out/engines/factory.js +2 -45
  38. package/out/engines/types.js +2 -17
  39. package/out/examples/run-headless-repl.js +6 -286
  40. package/out/examples/run-headless.js +2 -187
  41. package/out/extension.js +32 -4473
  42. package/out/gateway/gatewayRouteIndex.js +6 -371
  43. package/out/gateway/gatewaySessionStore.js +3 -243
  44. package/out/gateway/index.js +2 -31
  45. package/out/gateway/resetMappings.js +2 -52
  46. package/out/gateway/service.js +5 -1249
  47. package/out/mcp/publish.js +2 -143
  48. package/out/remote/handleRemoteChat.js +2 -169
  49. package/out/remote/remotePackStatusBar.js +3 -103
  50. package/out/remote/remoteTrust.js +6 -277
  51. package/out/remote/serveClient.js +4 -277
  52. package/out/remoteSkills.js +3 -191
  53. package/out/runtime/index.js +2 -32
  54. package/out/runtime/vscode/index.js +2 -20
  55. package/out/runtime/vscode/vscode-config-provider.js +2 -77
  56. package/out/runtime/vscode/vscode-edit-tracker.js +2 -122
  57. package/out/runtime/vscode/vscode-logger.js +2 -30
  58. package/out/runtime/vscode/vscode-permission-handler.js +2 -72
  59. package/out/scripts/agentide-litellm.sh +0 -1
  60. package/out/scripts/agentide_litellm_hooks_v1.py +170 -418
  61. package/out/scripts/analytics/agent-fleet-widget.js +18 -257
  62. package/out/scripts/analytics/agentide-litellm-otel.config.yaml +4 -4
  63. package/out/scripts/analytics/duckdbLocator.js +2 -28
  64. package/out/scripts/analytics/generate-default-charts.py +43 -323
  65. package/out/scripts/analytics/hotspot-analysis-widget.js +4 -430
  66. package/out/scripts/analytics/index-traces.py +78 -1036
  67. package/out/scripts/analytics/session-comparison-widget.js +26 -472
  68. package/out/scripts/analytics/session-timeline-widget.js +25 -846
  69. package/out/scripts/analytics/setup-analytics.ps1 +8 -1
  70. package/out/scripts/analytics/setup-analytics.sh +13 -2
  71. package/out/scripts/analytics/token-cost-flamegraph-widget.js +4 -461
  72. package/out/scripts/analytics/token-cost-trend-widget.js +4 -534
  73. package/out/scripts/analytics/workflows-collector.cjs +4 -314
  74. package/out/scripts/analytics/workflows-daemon.mjs +9 -185
  75. package/out/scripts/analytics/workflows-widget.cjs +15 -159
  76. package/out/scripts/analytics/wow-model-widget.js +10 -120
  77. package/out/scripts/vendor-tools.mjs +2 -233
  78. package/out/skills/publish.js +3 -178
  79. package/out/store/github/setup.js +7 -212
  80. package/out/store/oramaIndex.js +2 -884
  81. package/out/sync.js +26 -1829
  82. package/out/terminalLogger.js +5 -358
  83. package/out/utils/pathSafety.js +2 -60
  84. package/out/utils/pythonRunner.js +4 -258
  85. package/out/utils/toolPath.js +2 -83
  86. package/out/workspaceFolders.js +2 -59
  87. package/package.json +1 -1
  88. package/out/agentpack/github.js +0 -547
  89. package/out/agentpack/index.js +0 -67
  90. package/out/agentpack/install.js +0 -297
  91. package/out/agentpack/manager.js +0 -441
  92. package/out/agentpack/manifest.js +0 -135
  93. package/out/agentpack/paths.js +0 -498
  94. package/out/agentpack/publish.js +0 -248
  95. package/out/agentpack/stores.js +0 -554
  96. package/out/analytics/dashboard/fleetStatusUtils.js +0 -30
  97. package/out/analytics/dashboard/fleetTitleUtils.js +0 -68
  98. package/out/analytics/dashboard/refreshPolicy.js +0 -16
  99. package/out/analytics/dashboard/scheduledFleetFingerprint.js +0 -22
  100. package/out/analytics/dashboard/scheduledFleetUtils.js +0 -22
  101. package/out/analytics/dashboard/sessionEventFleetStats.js +0 -118
  102. package/out/analytics/dashboard/viewsConfigMerge.js +0 -221
  103. package/out/analytics/dashboard/webview/codicon.ttf +0 -0
  104. package/out/analytics/identity.js +0 -0
  105. package/out/analytics/sessionEvents.js +0 -323
  106. package/out/auth/callbackUriParse.js +0 -59
  107. package/out/auth/types.js +0 -12
  108. package/out/auth-broker/config.js +0 -112
  109. package/out/auth-broker/jwt.js +0 -105
  110. package/out/auth-broker/pkce.js +0 -59
  111. package/out/auth-broker/server.js +0 -677
  112. package/out/auth-broker/store.js +0 -275
  113. package/out/authority/warrant.js +0 -206
  114. package/out/base-prompts/mcp-servers/.mcp.json +0 -13
  115. package/out/base-prompts/mcp-servers/langfuse-analytics/README.md +0 -142
  116. package/out/base-prompts/mcp-servers/langfuse-analytics/mcp.json +0 -13
  117. package/out/base-prompts/mcp-servers/langfuse-analytics/package-lock.json +0 -1192
  118. package/out/base-prompts/mcp-servers/langfuse-analytics/package.json +0 -23
  119. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/run-with-env.sh +0 -12
  120. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/sdk-test.js +0 -102
  121. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/simple-test.js +0 -137
  122. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/test-client.js +0 -118
  123. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/test-server.js +0 -209
  124. package/out/base-prompts/mcp-servers/langfuse-analytics/src/client.ts +0 -431
  125. package/out/base-prompts/mcp-servers/langfuse-analytics/src/index.ts +0 -270
  126. package/out/base-prompts/mcp-servers/langfuse-analytics/tsconfig.json +0 -18
  127. package/out/base-prompts/rules/AGENTS.md +0 -204
  128. package/out/base-prompts/skills/agent-browser/SKILL.md +0 -102
  129. package/out/base-prompts/skills/agent-builder/SKILL.md +0 -73
  130. package/out/base-prompts/skills/agent-builder/references/agent-pack.md +0 -63
  131. package/out/base-prompts/skills/agent-builder/references/crewai.md +0 -66
  132. package/out/base-prompts/skills/agent-builder/references/langchain.md +0 -60
  133. package/out/base-prompts/skills/agent-builder/references/raw-sdk.md +0 -73
  134. package/out/base-prompts/skills/agent-engine-creator/SKILL.md +0 -586
  135. package/out/base-prompts/skills/agent-engine-installer/SKILL.md +0 -106
  136. package/out/base-prompts/skills/agent-engine-installer/scripts/install-engine.mjs +0 -259
  137. package/out/base-prompts/skills/agent-engine-installer/scripts/install-engine.ps1 +0 -189
  138. package/out/base-prompts/skills/agenthippo-cli/SKILL.md +0 -69
  139. package/out/base-prompts/skills/agenthippo-cli/scripts/install.sh +0 -63
  140. package/out/base-prompts/skills/agentpack-creator/SKILL.md +0 -375
  141. package/out/base-prompts/skills/agentpack-creator/references/agent-templates.md +0 -261
  142. package/out/base-prompts/skills/agentpack-creator/references/agents-md-guide.md +0 -195
  143. package/out/base-prompts/skills/agentpack-creator/scripts/init_pack.py +0 -391
  144. package/out/base-prompts/skills/agentpack-creator/scripts/init_pack_test.py +0 -294
  145. package/out/base-prompts/skills/agentpack-testbench/SKILL.md +0 -135
  146. package/out/base-prompts/skills/algorithmic-art/LICENSE.txt +0 -202
  147. package/out/base-prompts/skills/algorithmic-art/SKILL.md +0 -405
  148. package/out/base-prompts/skills/algorithmic-art/templates/generator_template.js +0 -223
  149. package/out/base-prompts/skills/algorithmic-art/templates/viewer.html +0 -599
  150. package/out/base-prompts/skills/debug-agent/SKILL.md +0 -83
  151. package/out/base-prompts/skills/desktop-automation/SKILL.md +0 -166
  152. package/out/base-prompts/skills/desktop-automation/references/agenthippo-ui-recipes.md +0 -441
  153. package/out/base-prompts/skills/desktop-automation/scripts/windows-desktop-uia.psm1 +0 -280
  154. package/out/base-prompts/skills/docx/LICENSE.txt +0 -30
  155. package/out/base-prompts/skills/docx/SKILL.md +0 -197
  156. package/out/base-prompts/skills/docx/docx-js.md +0 -350
  157. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  158. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  159. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  160. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  161. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  162. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  163. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  164. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  165. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  166. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  167. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  168. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  169. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  170. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  171. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  172. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  173. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  174. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  175. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  176. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  177. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  178. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  179. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  180. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  181. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  182. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  183. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  184. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  185. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  186. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  187. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  188. package/out/base-prompts/skills/docx/ooxml/schemas/mce/mc.xsd +0 -75
  189. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  190. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  191. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  192. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  193. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  194. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  195. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  196. package/out/base-prompts/skills/docx/ooxml/scripts/pack.py +0 -159
  197. package/out/base-prompts/skills/docx/ooxml/scripts/unpack.py +0 -29
  198. package/out/base-prompts/skills/docx/ooxml/scripts/validate.py +0 -69
  199. package/out/base-prompts/skills/docx/ooxml/scripts/validation/__init__.py +0 -15
  200. package/out/base-prompts/skills/docx/ooxml/scripts/validation/base.py +0 -951
  201. package/out/base-prompts/skills/docx/ooxml/scripts/validation/docx.py +0 -274
  202. package/out/base-prompts/skills/docx/ooxml/scripts/validation/pptx.py +0 -315
  203. package/out/base-prompts/skills/docx/ooxml/scripts/validation/redlining.py +0 -279
  204. package/out/base-prompts/skills/docx/ooxml.md +0 -610
  205. package/out/base-prompts/skills/docx/scripts/__init__.py +0 -1
  206. package/out/base-prompts/skills/docx/scripts/document.py +0 -1276
  207. package/out/base-prompts/skills/docx/scripts/templates/comments.xml +0 -3
  208. package/out/base-prompts/skills/docx/scripts/templates/commentsExtended.xml +0 -3
  209. package/out/base-prompts/skills/docx/scripts/templates/commentsExtensible.xml +0 -3
  210. package/out/base-prompts/skills/docx/scripts/templates/commentsIds.xml +0 -3
  211. package/out/base-prompts/skills/docx/scripts/templates/people.xml +0 -3
  212. package/out/base-prompts/skills/docx/scripts/utilities.py +0 -374
  213. package/out/base-prompts/skills/gateway-outbound/SKILL.md +0 -136
  214. package/out/base-prompts/skills/mcp-builder/LICENSE.txt +0 -202
  215. package/out/base-prompts/skills/mcp-builder/SKILL.md +0 -328
  216. package/out/base-prompts/skills/mcp-builder/reference/evaluation.md +0 -602
  217. package/out/base-prompts/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
  218. package/out/base-prompts/skills/mcp-builder/reference/node_mcp_server.md +0 -970
  219. package/out/base-prompts/skills/mcp-builder/reference/python_mcp_server.md +0 -719
  220. package/out/base-prompts/skills/mcp-builder/scripts/connections.py +0 -151
  221. package/out/base-prompts/skills/mcp-builder/scripts/evaluation.py +0 -373
  222. package/out/base-prompts/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
  223. package/out/base-prompts/skills/mcp-builder/scripts/requirements.txt +0 -2
  224. package/out/base-prompts/skills/openclaw/SKILL.md +0 -406
  225. package/out/base-prompts/skills/openclaw/scripts/run-smoke.sh +0 -61
  226. package/out/base-prompts/skills/pdf/LICENSE.txt +0 -30
  227. package/out/base-prompts/skills/pdf/SKILL.md +0 -294
  228. package/out/base-prompts/skills/pdf/forms.md +0 -205
  229. package/out/base-prompts/skills/pdf/reference.md +0 -612
  230. package/out/base-prompts/skills/pdf/scripts/check_bounding_boxes.py +0 -70
  231. package/out/base-prompts/skills/pdf/scripts/check_bounding_boxes_test.py +0 -226
  232. package/out/base-prompts/skills/pdf/scripts/check_fillable_fields.py +0 -12
  233. package/out/base-prompts/skills/pdf/scripts/convert_pdf_to_images.py +0 -35
  234. package/out/base-prompts/skills/pdf/scripts/create_validation_image.py +0 -41
  235. package/out/base-prompts/skills/pdf/scripts/extract_form_field_info.py +0 -152
  236. package/out/base-prompts/skills/pdf/scripts/fill_fillable_fields.py +0 -114
  237. package/out/base-prompts/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -108
  238. package/out/base-prompts/skills/pptx/LICENSE.txt +0 -30
  239. package/out/base-prompts/skills/pptx/SKILL.md +0 -484
  240. package/out/base-prompts/skills/pptx/html2pptx.md +0 -625
  241. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  242. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  243. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  244. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  245. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  246. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  247. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  248. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  249. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  250. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  251. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  252. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  253. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  254. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  255. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  256. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  257. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  258. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  259. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  260. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  261. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  262. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  263. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  264. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  265. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  266. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  267. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  268. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  269. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  270. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  271. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  272. package/out/base-prompts/skills/pptx/ooxml/schemas/mce/mc.xsd +0 -75
  273. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  274. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  275. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  276. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  277. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  278. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  279. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  280. package/out/base-prompts/skills/pptx/ooxml/scripts/pack.py +0 -159
  281. package/out/base-prompts/skills/pptx/ooxml/scripts/unpack.py +0 -29
  282. package/out/base-prompts/skills/pptx/ooxml/scripts/validate.py +0 -69
  283. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/__init__.py +0 -15
  284. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/base.py +0 -951
  285. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/docx.py +0 -274
  286. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/pptx.py +0 -315
  287. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/redlining.py +0 -279
  288. package/out/base-prompts/skills/pptx/ooxml.md +0 -427
  289. package/out/base-prompts/skills/pptx/scripts/html2pptx.js +0 -984
  290. package/out/base-prompts/skills/pptx/scripts/inventory.py +0 -1020
  291. package/out/base-prompts/skills/pptx/scripts/rearrange.py +0 -231
  292. package/out/base-prompts/skills/pptx/scripts/replace.py +0 -385
  293. package/out/base-prompts/skills/pptx/scripts/thumbnail.py +0 -450
  294. package/out/base-prompts/skills/prompt-lab/SKILL.md +0 -149
  295. package/out/base-prompts/skills/prompt-lab/scripts/query-analytics.sh +0 -2551
  296. package/out/base-prompts/skills/skill-creator/LICENSE.txt +0 -202
  297. package/out/base-prompts/skills/skill-creator/SKILL.md +0 -371
  298. package/out/base-prompts/skills/skill-creator/references/output-patterns.md +0 -82
  299. package/out/base-prompts/skills/skill-creator/references/workflows.md +0 -28
  300. package/out/base-prompts/skills/skill-creator/scripts/init_skill.py +0 -303
  301. package/out/base-prompts/skills/skill-creator/scripts/package_skill.py +0 -110
  302. package/out/base-prompts/skills/skill-creator/scripts/quick_validate.py +0 -95
  303. package/out/base-prompts/skills/skill-installer/SKILL.md +0 -251
  304. package/out/base-prompts/skills/skill-installer/references/store-api.md +0 -219
  305. package/out/base-prompts/skills/spotlight-dashboard/SKILL.md +0 -83
  306. package/out/base-prompts/skills/spotlight-insights/SKILL.md +0 -101
  307. package/out/base-prompts/skills/spotlight-optimize/SKILL.md +0 -93
  308. package/out/base-prompts/skills/spotlight-optimize/scripts/query-analytics.sh +0 -2551
  309. package/out/base-prompts/skills/spotlight-query/SKILL.md +0 -314
  310. package/out/base-prompts/skills/spotlight-query/references/otel-schema.md +0 -163
  311. package/out/base-prompts/skills/spotlight-query/scripts/query-analytics.sh +0 -2551
  312. package/out/base-prompts/skills/spotlight-query/scripts/query-analytics.test.sh +0 -744
  313. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/sessions/sess-test-1.jsonl +0 -14
  314. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/traces/.duckdb-index.json +0 -7
  315. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/traces/sample.jsonl +0 -5
  316. package/out/base-prompts/skills/spotlight-report/SKILL.md +0 -86
  317. package/out/base-prompts/skills/spotlight-visualize/SKILL.md +0 -92
  318. package/out/base-prompts/skills/spotlight-visualize/scripts/query-analytics.sh +0 -2551
  319. package/out/base-prompts/skills/xlsx/LICENSE.txt +0 -30
  320. package/out/base-prompts/skills/xlsx/SKILL.md +0 -289
  321. package/out/base-prompts/skills/xlsx/recalc.py +0 -178
  322. package/out/branding.js +0 -49
  323. package/out/cli/commands/anywhere.js +0 -66
  324. package/out/cli/commands/ask.js +0 -246
  325. package/out/cli/commands/auth-broker.js +0 -24
  326. package/out/cli/commands/auth.js +0 -219
  327. package/out/cli/commands/chat.js +0 -357
  328. package/out/cli/commands/conformance.js +0 -249
  329. package/out/cli/commands/data-plane.js +0 -67
  330. package/out/cli/commands/deploy.js +0 -263
  331. package/out/cli/commands/gateway.js +0 -218
  332. package/out/cli/commands/idp.js +0 -85
  333. package/out/cli/commands/pack.js +0 -399
  334. package/out/cli/commands/probe-custom-engine.js +0 -82
  335. package/out/cli/commands/sandbox.js +0 -332
  336. package/out/cli/commands/serve.js +0 -1758
  337. package/out/cli/commands/store.js +0 -927
  338. package/out/cli/credential-context.js +0 -91
  339. package/out/cli/data-plane/broker.js +0 -78
  340. package/out/cli/data-plane/connector-host.js +0 -121
  341. package/out/cli/data-plane/egress.js +0 -189
  342. package/out/cli/data-plane/gateway.js +0 -218
  343. package/out/cli/data-plane/index.js +0 -152
  344. package/out/cli/data-plane/registry.js +0 -89
  345. package/out/cli/data-plane/remote.js +0 -106
  346. package/out/cli/data-plane/sidecar.js +0 -161
  347. package/out/cli/deploy/blueprints/registry.js +0 -84
  348. package/out/cli/deploy/layers/identity.js +0 -172
  349. package/out/cli/deploy-init.js +0 -3023
  350. package/out/cli/deps.js +0 -342
  351. package/out/cli/idp-init.js +0 -338
  352. package/out/cli/pack-install-ref.js +0 -15
  353. package/out/cli/pack-loader.js +0 -418
  354. package/out/cli/pack-runtime.js +0 -61
  355. package/out/cli/runtime.js +0 -450
  356. package/out/cli/serve-hardening.js +0 -607
  357. package/out/cli/state-sync.js +0 -424
  358. package/out/cli/utils.js +0 -231
  359. package/out/engines/base.js +0 -188
  360. package/out/engines/claude.js +0 -1254
  361. package/out/engines/codex.js +0 -862
  362. package/out/engines/custom.js +0 -674
  363. package/out/engines/customEngineIpc.js +0 -95
  364. package/out/engines/customEngineRunnerEmbed.js +0 -107
  365. package/out/engines/customRegistry.js +0 -274
  366. package/out/engines/embeddedCustomEngineRunner.generated.js +0 -9
  367. package/out/engines/engineApiKey.js +0 -138
  368. package/out/engines/install.js +0 -372
  369. package/out/engines/persistentEngineWorker.js +0 -320
  370. package/out/engines/publish.js +0 -341
  371. package/out/evidence/sessionShip.js +0 -610
  372. package/out/gateway/bridge.js +0 -843
  373. package/out/gateway/cli-agent-id.js +0 -36
  374. package/out/gateway/client.js +0 -336
  375. package/out/gateway/client.test.js +0 -395
  376. package/out/gateway/gateway-scope-errors.js +0 -14
  377. package/out/gateway/gatewayBackup.js +0 -76
  378. package/out/gateway/installSource.js +0 -68
  379. package/out/gateway/lifecycle.js +0 -3190
  380. package/out/gateway/openclaw-channel-routing.js +0 -317
  381. package/out/gateway/outboundHandles.js +0 -373
  382. package/out/gateway/outboundPaths.js +0 -75
  383. package/out/gateway/outboundSend.js +0 -254
  384. package/out/gateway/protocol.js +0 -48
  385. package/out/gateway/secretsPreflight.js +0 -90
  386. package/out/gateway/sessionRouting.js +0 -77
  387. package/out/headless/index.js +0 -539
  388. package/out/headless/sync.js +0 -473
  389. package/out/live-e2e/mcp-demo/server.mjs +0 -32
  390. package/out/live-probe/connector.mjs +0 -8
  391. package/out/live-probe/env-report.mjs +0 -8
  392. package/out/mcp.js +0 -654
  393. package/out/pack/caps.js +0 -271
  394. package/out/pack/governor.js +0 -309
  395. package/out/pack/lease-schema.js +0 -270
  396. package/out/pack/lease.js +0 -640
  397. package/out/pack/reconcile.js +0 -217
  398. package/out/pack/signature.js +0 -839
  399. package/out/permissions.js +0 -108
  400. package/out/permissions.mapping.yaml +0 -68
  401. package/out/registry/index.js +0 -332
  402. package/out/runner/host.js +0 -131
  403. package/out/runner/protocol.js +0 -108
  404. package/out/runner/remoteEngine.js +0 -130
  405. package/out/runtime/interfaces/config-provider.js +0 -32
  406. package/out/runtime/interfaces/edit-tracker.js +0 -24
  407. package/out/runtime/interfaces/index.js +0 -29
  408. package/out/runtime/interfaces/logger.js +0 -40
  409. package/out/runtime/interfaces/permission-handler.js +0 -66
  410. package/out/runtime/interfaces/session-store.js +0 -342
  411. package/out/runtime/vscode/vscode-session-store.js +0 -22
  412. package/out/sandbox/containerDriver.js +0 -570
  413. package/out/sandbox/processDriver.js +0 -315
  414. package/out/sandbox/sandboxRunner.js +0 -191
  415. package/out/sandbox/support.js +0 -301
  416. package/out/sandbox/types.js +0 -55
  417. package/out/scripts/analytics/fleet-local-adapter.js +0 -246
  418. package/out/scripts/analytics/live-fleet-4-collector.cjs +0 -315
  419. package/out/scripts/analytics/live-fleet-4-daemon.mjs +0 -134
  420. package/out/scripts/analytics/live-fleet-4-widget.cjs +0 -433
  421. package/out/scripts/gateway/Dockerfile.serve +0 -45
  422. package/out/scripts/gateway/docker-serve.sh +0 -248
  423. package/out/scripts/gateway/setup-gateway-server.ps1 +0 -953
  424. package/out/scripts/gateway/setup-gateway-server.sh +0 -935
  425. package/out/session.js +0 -272
  426. package/out/shared/agentEngines.js +0 -170
  427. package/out/shared/index.js +0 -109
  428. package/out/shared/models.js +0 -136
  429. package/out/shared/providers.js +0 -205
  430. package/out/spotlight/install.js +0 -345
  431. package/out/spotlight/publish.js +0 -544
  432. package/out/spotlight/yaml.js +0 -31
  433. package/out/store/index.js +0 -786
  434. package/out/store/shared.js +0 -241
  435. package/out/test/agentEnvFile.test.js +0 -97
  436. package/out/test/agentYaml.test.js +0 -373
  437. package/out/test/agentpack.test.js +0 -639
  438. package/out/test/analytics-lifecycle.test.js +0 -174
  439. package/out/test/analytics.test.js +0 -756
  440. package/out/test/auth-baseurl.test.js +0 -132
  441. package/out/test/auth-bootstrapApply.test.js +0 -123
  442. package/out/test/auth-broker-hardening.test.js +0 -227
  443. package/out/test/auth-broker.test.js +0 -541
  444. package/out/test/auth-callback.test.js +0 -62
  445. package/out/test/blueprint-registry.test.js +0 -105
  446. package/out/test/branding.test.js +0 -242
  447. package/out/test/caps-governor.test.js +0 -455
  448. package/out/test/cli-agent-id.test.js +0 -55
  449. package/out/test/codex-new-file-survival.test.js +0 -119
  450. package/out/test/configuration-scopes.test.js +0 -131
  451. package/out/test/credential-context.test.js +0 -160
  452. package/out/test/custom-env-layering.test.js +0 -151
  453. package/out/test/customEngineInstall.test.js +0 -100
  454. package/out/test/customRegistry.test.js +0 -122
  455. package/out/test/data-plane-engine-wiring.test.js +0 -250
  456. package/out/test/data-plane.test.js +0 -311
  457. package/out/test/deploy-init.test.js +0 -854
  458. package/out/test/deps-auto-install.test.js +0 -81
  459. package/out/test/egress-broker.test.js +0 -172
  460. package/out/test/engine-integration.test.js +0 -297
  461. package/out/test/enginePaths.test.js +0 -195
  462. package/out/test/enginePublish.test.js +0 -82
  463. package/out/test/fleetDisplayUtils.test.js +0 -100
  464. package/out/test/gateway-client.test.js +0 -409
  465. package/out/test/gateway-install-source.test.js +0 -111
  466. package/out/test/gateway-lifecycle.test.js +0 -608
  467. package/out/test/gateway-outbound.test.js +0 -538
  468. package/out/test/gateway-reset-mappings.test.js +0 -221
  469. package/out/test/gateway-route-index.test.js +0 -235
  470. package/out/test/gateway-secrets-preflight.test.js +0 -127
  471. package/out/test/gateway-session-routing.test.js +0 -65
  472. package/out/test/gateway-session-store.test.js +0 -216
  473. package/out/test/github.test.js +0 -232
  474. package/out/test/governor-hardening.test.js +0 -217
  475. package/out/test/headless-sync.test.js +0 -301
  476. package/out/test/helpers/manifest-fixtures.js +0 -27
  477. package/out/test/idp-init.test.js +0 -151
  478. package/out/test/lease-signature.test.js +0 -357
  479. package/out/test/lease-trust-root.test.js +0 -273
  480. package/out/test/lease-validation.test.js +0 -169
  481. package/out/test/lease.test.js +0 -114
  482. package/out/test/mcp-obo.test.js +0 -107
  483. package/out/test/mcp.test.js +0 -389
  484. package/out/test/model-routing.test.js +0 -133
  485. package/out/test/openclaw-channel-routing.test.js +0 -191
  486. package/out/test/pack-admission.test.js +0 -216
  487. package/out/test/pack-digest-parity.test.js +0 -140
  488. package/out/test/pack-reconcile.test.js +0 -183
  489. package/out/test/pack-signature-artifact.test.js +0 -103
  490. package/out/test/pack-signature.test.js +0 -176
  491. package/out/test/pack-trust-root.test.js +0 -202
  492. package/out/test/pathSafety.test.js +0 -63
  493. package/out/test/permissions.test.js +0 -175
  494. package/out/test/persistent-engine-worker.test.js +0 -220
  495. package/out/test/refreshPolicy.test.js +0 -60
  496. package/out/test/registry.test.js +0 -351
  497. package/out/test/remote-trust.test.js +0 -242
  498. package/out/test/runner-protocol.test.js +0 -249
  499. package/out/test/runtime.test.js +0 -349
  500. package/out/test/sandbox-driver.test.js +0 -553
  501. package/out/test/sandbox-hardening.test.js +0 -395
  502. package/out/test/sandbox-runner.test.js +0 -343
  503. package/out/test/scheduledFleetStorage.test.js +0 -72
  504. package/out/test/serve-gateway-turn.test.js +0 -267
  505. package/out/test/serve-hardening.test.js +0 -418
  506. package/out/test/serveClient.test.js +0 -209
  507. package/out/test/sessionJsonlFleet.test.js +0 -78
  508. package/out/test/sessionShip.test.js +0 -560
  509. package/out/test/shared.test.js +0 -173
  510. package/out/test/skills-mcp.test.js +0 -299
  511. package/out/test/spotlightPublish.test.js +0 -327
  512. package/out/test/spotlightYaml.test.js +0 -58
  513. package/out/test/state-sync-peer.test.js +0 -156
  514. package/out/test/store-install-safe.test.js +0 -69
  515. package/out/test/store.test.js +0 -331
  516. package/out/test/stores.test.js +0 -504
  517. package/out/test/sync-switch.test.js +0 -251
  518. package/out/test/teamViewDiscovery.test.js +0 -90
  519. package/out/test/tls-bypass.test.js +0 -90
  520. package/out/test/toolPath.test.js +0 -120
  521. package/out/test/utils.test.js +0 -308
  522. package/out/test/viewsConfigMerge.test.js +0 -180
  523. package/out/test/warrant.test.js +0 -138
  524. package/out/test/windows-command-line.test.js +0 -75
  525. package/out/utils/agentEnvFile.js +0 -131
  526. package/out/utils/binary.js +0 -175
  527. package/out/utils/index.js +0 -37
  528. package/out/utils/network.js +0 -74
  529. package/out/utils/paths.js +0 -116
  530. package/out/utils/pid.js +0 -180
  531. package/out/utils/resolveNodeBinary.js +0 -168
  532. package/out/utils/windowsCommandLine.js +0 -29
  533. package/out/utils.js +0 -968
@@ -1,839 +0,0 @@
1
- "use strict";
2
- /*---------------------------------------------------------------------------------------------
3
- * Copyright (c) AgentHippo.ai. All rights reserved.
4
- *--------------------------------------------------------------------------------------------*/
5
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- var desc = Object.getOwnPropertyDescriptor(m, k);
8
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
- desc = { enumerable: true, get: function() { return m[k]; } };
10
- }
11
- Object.defineProperty(o, k2, desc);
12
- }) : (function(o, m, k, k2) {
13
- if (k2 === undefined) k2 = k;
14
- o[k2] = m[k];
15
- }));
16
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
- Object.defineProperty(o, "default", { enumerable: true, value: v });
18
- }) : function(o, v) {
19
- o["default"] = v;
20
- });
21
- var __importStar = (this && this.__importStar) || (function () {
22
- var ownKeys = function(o) {
23
- ownKeys = Object.getOwnPropertyNames || function (o) {
24
- var ar = [];
25
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
- return ar;
27
- };
28
- return ownKeys(o);
29
- };
30
- return function (mod) {
31
- if (mod && mod.__esModule) return mod;
32
- var result = {};
33
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
- __setModuleDefault(result, mod);
35
- return result;
36
- };
37
- })();
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.PACK_FULL_REVERIFY_INTERVAL_MS = exports.PACK_PROBE_INTERVAL_MS = exports.LEASE_JWKS_PINS_ENV = exports.LEASE_JWKS_URL_ENV = exports.LEASE_SIGNING_KEYS_ENV = exports.ALLOW_INSECURE_TRUST_ROOT_ENV = exports.PACK_JWKS_PINS_ENV = exports.PACK_JWKS_URL_ENV_LEGACY = exports.PACK_JWKS_URL_ENV = exports.ALLOW_UNSIGNED_PACK_ENV = exports.DIGEST_EXCLUDED_SEGMENTS = exports.PACK_SIGNATURE_FILE = void 0;
40
- exports.isDigestExcluded = isDigestExcluded;
41
- exports.computePackDigestFromFiles = computePackDigestFromFiles;
42
- exports.computePackDigest = computePackDigest;
43
- exports.packTreeProbe = packTreeProbe;
44
- exports.signPack = signPack;
45
- exports.readPackSignature = readPackSignature;
46
- exports.verifyPack = verifyPack;
47
- exports.verifyPackFromFiles = verifyPackFromFiles;
48
- exports.requireSignedPack = requireSignedPack;
49
- exports.resolveRequireSignedPack = resolveRequireSignedPack;
50
- exports.allowUnsignedPackFromEnv = allowUnsignedPackFromEnv;
51
- exports.describePackRefusal = describePackRefusal;
52
- exports.publicKeyThumbprints = publicKeyThumbprints;
53
- exports.parseJwksPins = parseJwksPins;
54
- exports.assertSecureTrustUrl = assertSecureTrustUrl;
55
- exports.loadPackTrustRoot = loadPackTrustRoot;
56
- exports.loadLeaseTrustRoot = loadLeaseTrustRoot;
57
- exports.selectLeaseSigningKeys = selectLeaseSigningKeys;
58
- exports.loadPackSigningKeys = loadPackSigningKeys;
59
- exports.createPackVerifier = createPackVerifier;
60
- /**
61
- * Pack signing — the gate that has to exist before a control plane may ever FETCH an artifact.
62
- *
63
- * A reconcile loop that pulls a pack and runs it is a remote-code-execution feature until a
64
- * signature decides what it is allowed to run. So this lands first, on its own, and the pull
65
- * comes after: verification with no fetch is merely unused; a fetch with no verification is a
66
- * vulnerability.
67
- *
68
- * Shape, and why:
69
- *
70
- * digest — sha256 over the pack's files, path AND content, sorted, each length-prefixed.
71
- * Length prefixes matter: without them `a/b` + `c` and `a/bc` + `''` hash the same,
72
- * so a rename could be laundered into an identical digest.
73
- * signature — a compact JWS (ES256) whose payload names the pack, the version, and that digest.
74
- * Binding all three is what stops a valid signature being replayed onto a different
75
- * pack or a different version of the same one — a bare content signature would let
76
- * an attacker who can place files claim any name they like.
77
- * keys — verified with PUBLIC halves only, distributed by the control plane's existing
78
- * JWKS endpoint (which refuses private material). Whoever verifies cannot sign,
79
- * which is the same asymmetry the inference warrants rely on.
80
- *
81
- * Deliberately NOT expiring: a warrant is turn-short because it authorises spend, but a pack
82
- * signature attests to content that does not rot. An expiry here would ground a fleet on a
83
- * calendar boundary for no security gain.
84
- */
85
- const crypto = __importStar(require("node:crypto"));
86
- const fs = __importStar(require("node:fs"));
87
- const path = __importStar(require("node:path"));
88
- const warrant_1 = require("../authority/warrant");
89
- /** Written at the pack root. Excluded from the digest — it cannot cover itself. */
90
- exports.PACK_SIGNATURE_FILE = 'pack.sig';
91
- /**
92
- * Path segments never hashed, at ANY depth: VCS metadata and installed dependencies.
93
- *
94
- * This list used to also carry `.claude`, `.codex`, `.agent-hippo` and `.DS_Store`, and the walk
95
- * tested it on every directory entry rather than only at the top level — despite a comment
96
- * claiming "top-level". The result was a hole big enough to drive a payload through:
97
- * `.claude/settings.json` is where Claude Code reads its HOOKS from, i.e. arbitrary shell commands
98
- * that run around every tool call. A pack with an injected `PreToolUse` hook verified clean, and
99
- * `agenthippo pack verify` printed OK. The same was true of `.codex/` and `.agent-hippo/`.
100
- *
101
- * Executable content is now IN the digest. The cost is real and accepted: anything that writes
102
- * into a pack directory after signing (including macOS writing `.DS_Store` when someone opens the
103
- * folder in Finder) invalidates the signature, and the pack must be re-signed. That is the correct
104
- * direction to fail — "the tree changed since it was signed" is exactly what the signature is for,
105
- * and the failure says so.
106
- *
107
- * `.git` and `node_modules` remain excluded at every depth because they are not pack content: a
108
- * checkout's git objects differ per clone, and dependencies are installed, not authored. Excluding
109
- * them at every depth (rather than only the top level) is deliberate — a nested `node_modules`
110
- * from a workspace install is the same non-content.
111
- */
112
- exports.DIGEST_EXCLUDED_SEGMENTS = new Set(['.git', 'node_modules']);
113
- /**
114
- * The ONE predicate both digest paths use.
115
- *
116
- * `computePackDigest` (directory walk) and `computePackDigestFromFiles` (fetched artifact) MUST
117
- * agree for identical trees, or a locally-signed pack can never verify through the store path —
118
- * which is precisely what happened when the walk excluded seven names and the file list excluded
119
- * one. There is a test asserting the two agree on a tree containing every excluded and formerly
120
- * excluded name.
121
- *
122
- * @param relPosixPath path RELATIVE to the pack root, `/`-separated.
123
- */
124
- function isDigestExcluded(relPosixPath) {
125
- if (relPosixPath === exports.PACK_SIGNATURE_FILE) {
126
- return true;
127
- }
128
- return relPosixPath.split('/').some((seg) => exports.DIGEST_EXCLUDED_SEGMENTS.has(seg));
129
- }
130
- /**
131
- * The single hashing routine. Sorted so two checkouts agree regardless of readdir order, and
132
- * length-prefixed so no combination of names and contents can be rearranged into the same hash.
133
- *
134
- * Symlinks are hashed as their TARGET STRING rather than followed (following them would let a link
135
- * resolving differently on another host produce the same digest for different bytes) and carry an
136
- * `L:` domain tag so a symlink `a → b` cannot be swapped for a regular file `a` containing `b`.
137
- * Regular-file framing is unchanged, so signatures over packs without symlinks still verify.
138
- */
139
- function hashEntries(entries) {
140
- const hash = crypto.createHash('sha256');
141
- const sorted = [...entries].sort((a, b) => (a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0));
142
- for (const entry of sorted) {
143
- if (entry.link) {
144
- hash.update('L:');
145
- }
146
- const rel = Buffer.from(entry.rel);
147
- // length-prefix both halves — see the header note on rename laundering
148
- hash.update(`${rel.length}:`);
149
- hash.update(rel);
150
- hash.update(`${entry.body.length}:`);
151
- hash.update(entry.body);
152
- }
153
- return hash.digest('hex');
154
- }
155
- /**
156
- * Hash an artifact file list (a store download, or a materialised tree read back).
157
- *
158
- * Uses `isDigestExcluded`, exactly like the directory walk. It previously excluded only `pack.sig`
159
- * while the walk excluded seven names, so any pack containing `.claude/`, `.codex/` or
160
- * `.agent-hippo/` produced two different digests and could never verify through the store path.
161
- */
162
- function computePackDigestFromFiles(files) {
163
- const entries = [];
164
- for (const f of files) {
165
- const rel = f.path.replace(/\\/g, '/');
166
- if (isDigestExcluded(rel)) {
167
- continue;
168
- }
169
- entries.push({ rel, body: f.content, link: f.link });
170
- }
171
- return hashEntries(entries);
172
- }
173
- /** Deterministic digest of a pack directory. */
174
- function computePackDigest(packDir) {
175
- const entries = [];
176
- const walk = (dir, prefix) => {
177
- for (const name of fs.readdirSync(dir)) {
178
- const rel = prefix ? `${prefix}/${name}` : name;
179
- if (isDigestExcluded(rel)) {
180
- continue;
181
- }
182
- const abs = path.join(dir, name);
183
- const st = fs.lstatSync(abs);
184
- if (st.isSymbolicLink()) {
185
- entries.push({ rel, body: Buffer.from(fs.readlinkSync(abs)), link: true });
186
- }
187
- else if (st.isDirectory()) {
188
- walk(abs, rel);
189
- }
190
- else if (st.isFile()) {
191
- entries.push({ rel, body: fs.readFileSync(abs) });
192
- }
193
- // Sockets, fifos and devices are not pack content; ignoring them keeps the digest
194
- // stable across environments that happen to leave one behind.
195
- }
196
- };
197
- walk(packDir, '');
198
- return hashEntries(entries);
199
- }
200
- /**
201
- * A CHEAP probe of a pack tree, for deciding whether a full re-verify is needed.
202
- *
203
- * Not a security boundary on its own — see `createPackVerifier`, which pairs it with a periodic
204
- * unconditional re-verify. This walks the tree with `lstat` only: no file is read and nothing is
205
- * hashed, so the cost is O(entries) syscalls rather than O(bytes) of SHA-256. On a typical pack
206
- * (tens to low hundreds of files) that is sub-millisecond, which is what makes it acceptable on
207
- * the turn path where a full digest is not.
208
- *
209
- * Covers: content edits (mtime + size), whole-file replacement (inode), permission changes (mode),
210
- * and any addition or removal (the entry list itself).
211
- */
212
- function packTreeProbe(packDir) {
213
- const parts = [];
214
- const walk = (dir, prefix) => {
215
- let names;
216
- try {
217
- names = fs.readdirSync(dir).sort();
218
- }
219
- catch {
220
- parts.push(`${prefix}/?unreadable`);
221
- return;
222
- }
223
- for (const name of names) {
224
- const rel = prefix ? `${prefix}/${name}` : name;
225
- if (isDigestExcluded(rel)) {
226
- continue;
227
- }
228
- const abs = path.join(dir, name);
229
- let st;
230
- try {
231
- st = fs.lstatSync(abs);
232
- }
233
- catch {
234
- parts.push(`${rel}|gone`);
235
- continue;
236
- }
237
- if (st.isDirectory()) {
238
- walk(abs, rel);
239
- continue;
240
- }
241
- parts.push(`${rel}|${st.size}|${st.mtimeMs}|${st.ino}|${st.mode}`);
242
- }
243
- };
244
- try {
245
- walk(packDir, '');
246
- }
247
- catch {
248
- return 'unwalkable';
249
- }
250
- return crypto.createHash('sha256').update(parts.join('\n')).digest('hex');
251
- }
252
- /** Sign a pack in place: computes the digest and writes `pack.sig` at the pack root. */
253
- function signPack(input) {
254
- const digest = computePackDigest(input.packDir);
255
- const claims = {
256
- pack: input.pack,
257
- packVersion: input.packVersion,
258
- digest,
259
- iat: input.nowSeconds ?? Math.floor(Date.now() / 1000),
260
- };
261
- const signature = (0, warrant_1.signCompactJws)({ typ: 'JWT', kid: input.kid }, claims, input.privateKeyPem);
262
- fs.writeFileSync(path.join(input.packDir, exports.PACK_SIGNATURE_FILE), `${signature}\n`);
263
- return { signature, digest };
264
- }
265
- function readPackSignature(packDir) {
266
- try {
267
- const raw = fs.readFileSync(path.join(packDir, exports.PACK_SIGNATURE_FILE), 'utf8').trim();
268
- return raw || undefined;
269
- }
270
- catch {
271
- return undefined;
272
- }
273
- }
274
- /**
275
- * Verify a pack against public keys only.
276
- *
277
- * Every failure is a refusal with a stated reason rather than a thrown error, because the caller
278
- * is an admission decision: it needs to log precisely why a pack was rejected, and "unknown kid"
279
- * and "content changed after signing" are very different operational problems.
280
- */
281
- function verifyPack(token, publicKeysByKid, input) {
282
- return verifyPackAgainst(token, publicKeysByKid, input.pack, input.packVersion, () => computePackDigest(input.packDir));
283
- }
284
- /**
285
- * Verify a downloaded artifact against its signature using the fetched file list, not a directory
286
- * walk. Both paths hash through `isDigestExcluded`, so a tree and the file list it was built from
287
- * produce the SAME digest — the property `pack-digest-parity.test.ts` pins.
288
- */
289
- function verifyPackFromFiles(token, publicKeysByKid, pack, packVersion, files) {
290
- return verifyPackAgainst(token, publicKeysByKid, pack, packVersion, () => computePackDigestFromFiles(files));
291
- }
292
- /** The shared body of both verify paths — identity binding, then digest. */
293
- function verifyPackAgainst(token, publicKeysByKid, pack, packVersion, actualDigest) {
294
- if (Object.keys(publicKeysByKid).length === 0) {
295
- // Distinct from every other refusal, and with a distinct remedy: nothing is wrong with the
296
- // pack, this instance simply has nothing to check it against. Verifying against an empty
297
- // keyring would otherwise report success for any signature at all.
298
- return { ok: false, kind: 'no-trust-root', reason: 'no trusted pack-signing keys are configured on this instance' };
299
- }
300
- // alg pinning, kid-must-be-known and the raw R||S encoding all live in verifyCompactJws.
301
- const jws = (0, warrant_1.verifyCompactJws)(token, publicKeysByKid);
302
- if (!jws.ok) {
303
- if (jws.reason === 'unknown kid') {
304
- // Never trusted-on-first-use: accepting a key because it arrived with the artifact would
305
- // let anyone who can write the pack also choose who vouches for it.
306
- const kid = readUnverifiedKid(token);
307
- return { ok: false, kind: 'unknown-key', reason: `unknown signing key ${kid ?? '(none named)'}` };
308
- }
309
- if (jws.reason === 'bad signature') {
310
- return { ok: false, kind: 'bad-signature', reason: 'signature does not verify' };
311
- }
312
- if (jws.reason === 'malformed') {
313
- return { ok: false, kind: 'malformed', reason: 'malformed signature' };
314
- }
315
- if (jws.reason === 'unparseable') {
316
- return { ok: false, kind: 'malformed', reason: 'unreadable signature' };
317
- }
318
- return { ok: false, kind: 'malformed', reason: jws.reason };
319
- }
320
- const claims = jws.payload;
321
- // Identity binding is checked BEFORE the digest: a signature that verifies cryptographically
322
- // but names a different pack is an attempted replay, and saying so is more useful than
323
- // reporting a digest mismatch.
324
- if (claims.pack !== pack) {
325
- return { ok: false, kind: 'identity-mismatch', reason: `signature is for pack ${claims.pack}, not ${pack}` };
326
- }
327
- if (claims.packVersion !== packVersion) {
328
- return { ok: false, kind: 'identity-mismatch', reason: `signature is for ${claims.pack}@${claims.packVersion}, not @${packVersion}` };
329
- }
330
- if (typeof claims.digest !== 'string' || !claims.digest) {
331
- return { ok: false, kind: 'malformed', reason: 'signature carries no digest' };
332
- }
333
- if (!(0, warrant_1.timingSafeEqualString)(actualDigest(), claims.digest)) {
334
- return { ok: false, kind: 'digest-mismatch', reason: 'pack contents changed after signing' };
335
- }
336
- return { ok: true, claims };
337
- }
338
- /** The `kid` a token CLAIMS, for error messages only — never for a trust decision. */
339
- function readUnverifiedKid(token) {
340
- try {
341
- const header = JSON.parse(Buffer.from(token.split('.')[0], 'base64url').toString('utf8'));
342
- return header.kid;
343
- }
344
- catch {
345
- return undefined;
346
- }
347
- }
348
- /**
349
- * Signature requirement, merged tighten-only.
350
- *
351
- * Either side may demand signed packs; neither may waive the other's demand. Same rule as caps,
352
- * and for the same reason: a requirement an instance can switch off by editing its own flags is
353
- * decorative, and this one gates code execution.
354
- */
355
- function requireSignedPack(leaseValue, localValue) {
356
- return Boolean(leaseValue) || Boolean(localValue);
357
- }
358
- /** Escape hatch for local development. Loud on every boot; the lease can still override it. */
359
- exports.ALLOW_UNSIGNED_PACK_ENV = 'AGENTHIPPO_ALLOW_UNSIGNED_PACK';
360
- /**
361
- * Is a verified signature REQUIRED for this pack to run?
362
- *
363
- * **Default: yes.** This flipped from opt-in. `requireSignedPack` used to be off unless an operator
364
- * turned it on, so the shipped default was warn-and-run: serve logged
365
- * `[Pack] unsigned or unverifiable — …` and then executed the pack anyway. A gate that logs and
366
- * proceeds is not a gate, and the commit message "verify before run, fail closed" was not true of
367
- * the default shape.
368
- *
369
- * Tighten-only is preserved exactly: the LEASE's demand is checked first and cannot be waived, so
370
- * an instance can never opt out of a requirement the control plane made. The escape hatch only
371
- * relaxes the instance's OWN default.
372
- */
373
- function resolveRequireSignedPack(opts) {
374
- if (requireSignedPack(opts.lease, opts.localRequire)) {
375
- return true;
376
- }
377
- return !opts.localAllowUnsigned;
378
- }
379
- /** Reads the escape hatch from the environment. `1`/`true`/`yes` enable it; anything else does not. */
380
- function allowUnsignedPackFromEnv(env = process.env) {
381
- const raw = env[exports.ALLOW_UNSIGNED_PACK_ENV]?.trim().toLowerCase();
382
- return raw === '1' || raw === 'true' || raw === 'yes';
383
- }
384
- /**
385
- * The operator-facing refusal.
386
- *
387
- * Written out longhand on purpose. Flipping the default to refuse WILL stop deployments that ran
388
- * unsigned packs, and the difference between a good and a terrible version of that change is
389
- * entirely in this function: an operator must learn from the message alone what is wrong, how to
390
- * fix it properly, and how to get moving again right now.
391
- */
392
- function describePackRefusal(ctx) {
393
- const id = ctx.packVersion ? `${ctx.pack}@${ctx.packVersion}` : ctx.pack;
394
- const lines = [`refusing to run ${id}: ${ctx.detail}`];
395
- switch (ctx.kind) {
396
- case 'unsigned':
397
- lines.push(` The pack directory has no ${exports.PACK_SIGNATURE_FILE}${ctx.packDir ? ` at ${ctx.packDir}` : ''}.`, ` Sign it: agenthippo pack sign ${ctx.pack} --key <private-key.pem> --kid <key-id>`, ' (generate a key with: agenthippo pack keygen -o key.pem, then publish its public half to JWKS)');
398
- break;
399
- case 'no-trust-root':
400
- lines.push(' This is NOT a problem with the pack — this instance has no keys to check it against.', ' Configure ONE of:', ' AGENTHIPPO_PACK_SIGNING_KEYS inline JSON {"<kid>":"<public PEM>"} (air-gapped installs)', ` ${exports.PACK_JWKS_URL_ENV} https URL of the JWKS document publishing your signing keys`, ` ${exports.PACK_JWKS_PINS_ENV} optional, comma-separated sha256 thumbprints to pin those keys to`);
401
- break;
402
- case 'trust-root-unavailable':
403
- lines.push(' A trust root IS configured but could not be loaded, so no signature can be checked.', ` ${ctx.trustRootHint ?? ''}`.trimEnd(), ' This is deliberately an error and not an empty keyring: "cannot reach the trust root" and', ' "no trust root configured" have different causes and different fixes.');
404
- break;
405
- case 'unknown-key':
406
- lines.push(' The pack IS signed, but by a key this fleet does not trust.', ' Either publish that key to your JWKS / AGENTHIPPO_PACK_SIGNING_KEYS, or re-sign the pack', ' with a key that is already trusted. A key is never trusted just because it arrived with the pack.');
407
- break;
408
- case 'digest-mismatch':
409
- lines.push(' The signature is valid but the pack tree no longer matches it — something changed after signing.', ' Note that .claude/, .codex/ and .agent-hippo/ are now INSIDE the digest (they carry hooks and', ' other executable content), so edits there invalidate a signature that used to survive them.', ` Re-sign after reviewing the diff: agenthippo pack sign ${ctx.pack} --key <private-key.pem> --kid <key-id>`);
410
- break;
411
- case 'identity-mismatch':
412
- lines.push(' The signature is valid but names a different pack or version — a replayed signature, not this artifact.');
413
- break;
414
- case 'malformed':
415
- case 'bad-signature':
416
- lines.push(` ${exports.PACK_SIGNATURE_FILE} is present but unusable. Re-sign the pack; do not hand-edit it.`);
417
- break;
418
- case 'no-pack':
419
- break;
420
- }
421
- lines.push(` To run unsigned packs anyway (LOCAL DEVELOPMENT ONLY), set ${exports.ALLOW_UNSIGNED_PACK_ENV}=1.`, ' A lease that sets requireSignedPack overrides that escape hatch — the control plane\'s demand cannot be waived locally.');
422
- return lines.join('\n');
423
- }
424
- // ---------------------------------------------------------------------------------------------
425
- // Trust root
426
- // ---------------------------------------------------------------------------------------------
427
- /** Dedicated JWKS URL. Pins the trust root INDEPENDENTLY of wherever the lease happens to live. */
428
- exports.PACK_JWKS_URL_ENV = 'AGENTHIPPO_PACK_JWKS_URL';
429
- /** Legacy name for the same thing; still honoured. */
430
- exports.PACK_JWKS_URL_ENV_LEGACY = 'AGENTHIPPO_PACK_SIGNING_JWKS_URL';
431
- /** Comma-separated sha256 thumbprints. Any key not matching one of these is refused. */
432
- exports.PACK_JWKS_PINS_ENV = 'AGENTHIPPO_PACK_JWKS_PINS';
433
- /** Local-dev escape hatch allowing a plaintext-http trust root / lease origin. Logs loudly. */
434
- exports.ALLOW_INSECURE_TRUST_ROOT_ENV = 'AGENTHIPPO_ALLOW_INSECURE_TRUST_ROOT';
435
- /**
436
- * The LEASE trust root — the same three knobs, named the same way, one word different.
437
- *
438
- * Deliberately parallel to the pack names so an operator who has configured one can guess the
439
- * other. They must be separate keyrings, not one: the control plane publishes the lease public key
440
- * under purpose `lease-signing` and REFUSES to register a single kid under two purposes, so a
441
- * correctly-configured plane and a serve that verified leases against the pack keyring could never
442
- * agree on a key — and `requireSignedLease` is sticky with no plane-side undo, so that disagreement
443
- * latches an instance into refusing turns. Separating the roots is also the right shape on its own:
444
- * a lease-signing key that lives in the pack keyring is a key that can authorise code execution.
445
- */
446
- exports.LEASE_SIGNING_KEYS_ENV = 'AGENTHIPPO_LEASE_SIGNING_KEYS';
447
- exports.LEASE_JWKS_URL_ENV = 'AGENTHIPPO_LEASE_JWKS_URL';
448
- exports.LEASE_JWKS_PINS_ENV = 'AGENTHIPPO_LEASE_JWKS_PINS';
449
- /**
450
- * sha256 thumbprints of a public key, in both forms an operator is likely to have.
451
- *
452
- * jwk — RFC 7638 JWK thumbprint, base64url. What `openssl`-free tooling and most JWKS
453
- * publishers produce, and what a `kid` is conventionally derived from.
454
- * spki — sha256 over the DER SPKI, hex. What `openssl pkey -pubout -outform der | sha256sum`
455
- * gives, which is what an operator with a PEM in hand will reach for first.
456
- *
457
- * A pin matching EITHER is accepted, with or without a `sha256:` prefix, case-insensitively.
458
- * Publishing both costs nothing and removes an entire class of "my pin doesn't match" tickets.
459
- */
460
- function publicKeyThumbprints(publicKeyPem) {
461
- const key = crypto.createPublicKey(publicKeyPem);
462
- const jwk = key.export({ format: 'jwk' });
463
- // RFC 7638: lexicographically ordered, whitespace-free JSON of the REQUIRED members only.
464
- const required = jwk.kty === 'EC'
465
- ? { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y }
466
- : jwk.kty === 'RSA'
467
- ? { e: jwk.e, kty: jwk.kty, n: jwk.n }
468
- : { kty: jwk.kty };
469
- return {
470
- jwk: crypto.createHash('sha256').update(JSON.stringify(required)).digest('base64url'),
471
- spki: crypto.createHash('sha256').update(key.export({ type: 'spki', format: 'der' })).digest('hex'),
472
- };
473
- }
474
- const normalisePin = (p) => p.trim().replace(/^sha256:/i, '').toLowerCase();
475
- /** Parse the pin list. Empty/blank ⇒ no pinning. */
476
- function parseJwksPins(raw) {
477
- return (raw ?? '').split(',').map(normalisePin).filter((p) => p.length > 0);
478
- }
479
- /**
480
- * Is this URL safe to fetch a TRUST ROOT from?
481
- *
482
- * The keyring that decides which code may run must not be fetched over a channel any on-path
483
- * device can rewrite. https is required; the escape hatch exists because a local control plane on
484
- * `http://localhost` is a real development shape, and it is deliberately loud.
485
- */
486
- function assertSecureTrustUrl(url, what, env = process.env) {
487
- let parsed;
488
- try {
489
- parsed = new URL(url);
490
- }
491
- catch {
492
- return { ok: false, reason: `${what} is not a valid URL: ${url}` };
493
- }
494
- if (parsed.protocol === 'https:') {
495
- return { ok: true, warnings: [] };
496
- }
497
- const allowed = (env[exports.ALLOW_INSECURE_TRUST_ROOT_ENV] ?? '').trim().toLowerCase();
498
- if (allowed === '1' || allowed === 'true' || allowed === 'yes') {
499
- return {
500
- ok: true,
501
- warnings: [
502
- `INSECURE: ${what} is ${parsed.protocol}//${parsed.host} (not https) and ` +
503
- `${exports.ALLOW_INSECURE_TRUST_ROOT_ENV} is set. Anyone on the path between this instance and that ` +
504
- 'host can choose which packs it will run and whether the kill switch is honoured. ' +
505
- 'This must never be set outside local development.',
506
- ],
507
- };
508
- }
509
- return {
510
- ok: false,
511
- reason: `${what} must be https (got ${parsed.protocol}//${parsed.host}). ` +
512
- `Set ${exports.ALLOW_INSECURE_TRUST_ROOT_ENV}=1 to allow plaintext for LOCAL DEVELOPMENT ONLY.`,
513
- };
514
- }
515
- const PACK_TRUST_ROOT_SPEC = {
516
- label: 'pack',
517
- purpose: 'pack-signing',
518
- inlineEnv: 'AGENTHIPPO_PACK_SIGNING_KEYS',
519
- urlEnvs: [exports.PACK_JWKS_URL_ENV, exports.PACK_JWKS_URL_ENV_LEGACY],
520
- pinsEnv: exports.PACK_JWKS_PINS_ENV,
521
- derivedRisk: 'chooses which packs this instance will run',
522
- };
523
- const LEASE_TRUST_ROOT_SPEC = {
524
- label: 'lease',
525
- purpose: 'lease-signing',
526
- inlineEnv: exports.LEASE_SIGNING_KEYS_ENV,
527
- urlEnvs: [exports.LEASE_JWKS_URL_ENV],
528
- pinsEnv: exports.LEASE_JWKS_PINS_ENV,
529
- derivedRisk: "chooses whether this instance's kill switch is ever honoured",
530
- };
531
- /**
532
- * Public halves used to verify one class of signature.
533
- *
534
- * Three sources, in precedence order:
535
- * 1. `<…>_SIGNING_KEYS` — inline kid→PEM JSON. Air-gapped installs; no network at all.
536
- * 2. `<…>_JWKS_URL` (plus, for packs, the legacy `…_SIGNING_JWKS_URL`) — an EXPLICIT trust root.
537
- * 3. `/.well-known/jwks.json?purpose=<purpose>` on the lease origin — back-compat, reported weaker.
538
- *
539
- * (3) is why this function exists in this shape. The whole governance story — kill switch, deny
540
- * rules, caps, version pin, pack signing — was rooted in an origin named by `AGENTHIPPO_LEASE_URL`
541
- * and fetched with a bare `fetch()`: no scheme check, no pinning, and nothing signing the key
542
- * document. Whoever could answer that URL could hand the fleet its trust root. Now: https is
543
- * required unless explicitly opted out of, the trust root can be pinned independently of the lease,
544
- * and thumbprint pins let an operator refuse any key the plane did not previously publish.
545
- *
546
- * And a load FAILURE is no longer an empty keyring (finding A4). "No trust root configured" and
547
- * "trust root configured but unreachable" are different states with different remedies; collapsing
548
- * them into `{}` meant a 503 during a rolling restart looked exactly like an unmanaged deployment.
549
- *
550
- * NOT re-fetched once `configured` — that is the caller's job (`serve` retries only while a root is
551
- * missing), so key rotation still needs the documented restart and a compromised plane cannot swap
552
- * a trust root under a running instance mid-flight. Both roots behave identically here.
553
- */
554
- async function loadTrustRoot(spec, opts) {
555
- const env = opts.env ?? process.env;
556
- const warnings = [];
557
- const pins = parseJwksPins(env[spec.pinsEnv]);
558
- const inline = env[spec.inlineEnv]?.trim();
559
- const explicit = spec.urlEnvs.map((name) => env[name]).find((v) => v !== undefined && v.trim() !== '')?.trim();
560
- // Read BEFORE any early return: `unavailable` still has to say whether an operator asked for it.
561
- const explicitlyConfigured = Boolean(inline) || Boolean(explicit);
562
- const applyPins = (keys, source, url) => {
563
- if (pins.length === 0) {
564
- return Object.keys(keys).length === 0
565
- ? { status: 'unavailable', keys: {}, source, url, warnings, explicitlyConfigured, reason: 'the trust root published no usable ES256 keys' }
566
- : { status: 'configured', keys, source, url, warnings, explicitlyConfigured };
567
- }
568
- const kept = {};
569
- for (const [kid, pem] of Object.entries(keys)) {
570
- let tp;
571
- try {
572
- tp = publicKeyThumbprints(pem);
573
- }
574
- catch {
575
- warnings.push(`${spec.label} trust root: key ${kid} is unreadable and was dropped`);
576
- continue;
577
- }
578
- const matched = pins.some((p) => (0, warrant_1.timingSafeEqualString)(p, tp.jwk.toLowerCase()) || (0, warrant_1.timingSafeEqualString)(p, tp.spki));
579
- if (matched) {
580
- kept[kid] = pem;
581
- }
582
- else {
583
- warnings.push(`${spec.label} trust root: key ${kid} does not match any pin in ${spec.pinsEnv} and was REFUSED ` +
584
- `(its thumbprints are jwk=${tp.jwk} spki=${tp.spki})`);
585
- }
586
- }
587
- if (Object.keys(kept).length === 0) {
588
- return {
589
- status: 'unavailable', keys: {}, source, url, warnings, explicitlyConfigured,
590
- reason: `every key offered by the trust root failed the ${spec.pinsEnv} pin check`,
591
- };
592
- }
593
- return { status: 'configured', keys: kept, source, url, warnings, explicitlyConfigured };
594
- };
595
- if (inline) {
596
- let parsed;
597
- try {
598
- parsed = JSON.parse(inline);
599
- }
600
- catch (err) {
601
- // Previously `{}` — i.e. a typo in an env var silently became "unmanaged".
602
- return {
603
- status: 'unavailable', keys: {}, source: 'inline', warnings, explicitlyConfigured,
604
- reason: `${spec.inlineEnv} is set but is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,
605
- };
606
- }
607
- return applyPins(parsed, 'inline');
608
- }
609
- let url = explicit;
610
- let derivedFromLease = false;
611
- if (!url && opts.leaseUrl) {
612
- // `?purpose=…` because the bare path's meaning belongs to the plane: it used to return every
613
- // key it held, and a control plane that separates keys by purpose may now default it to
614
- // something else entirely. Asking for the purpose we actually need makes this fallback survive
615
- // that change — an older plane ignores the query string and returns the same document it
616
- // always did, so this is safe in both directions.
617
- //
618
- // The plane also publishes `/.well-known/lease-jwks.json` as an alias for
619
- // `?purpose=lease-signing`. The query form is used for BOTH roots on purpose: one derivation
620
- // rule, one thing to reason about, and it is the form that already survives a plane changing
621
- // what the bare path defaults to.
622
- try {
623
- url = new URL(`/.well-known/jwks.json?purpose=${spec.purpose}`, opts.leaseUrl).toString();
624
- }
625
- catch {
626
- return { status: 'unavailable', keys: {}, warnings, explicitlyConfigured, reason: `AGENTHIPPO_LEASE_URL is not a valid URL: ${opts.leaseUrl}` };
627
- }
628
- derivedFromLease = true;
629
- }
630
- if (!url) {
631
- return { status: 'unconfigured', keys: {}, warnings, explicitlyConfigured };
632
- }
633
- const secure = assertSecureTrustUrl(url, `the ${spec.purpose} JWKS URL`, env);
634
- if (!secure.ok) {
635
- return { status: 'unavailable', keys: {}, source: 'jwks', url, warnings, reason: secure.reason, derivedFromLease, explicitlyConfigured };
636
- }
637
- warnings.push(...secure.warnings);
638
- if (derivedFromLease && pins.length === 0) {
639
- warnings.push(`${spec.label} trust root is derived from AGENTHIPPO_LEASE_URL (${url}) and is not pinned. Whoever can answer ` +
640
- `that origin ${spec.derivedRisk}. Pin it with ${spec.urlEnvs[0]} and ` +
641
- `${spec.pinsEnv}.`);
642
- }
643
- try {
644
- const res = await (opts.fetchImpl ?? fetch)(url);
645
- if (!res.ok) {
646
- return { status: 'unavailable', keys: {}, source: 'jwks', url, warnings, reason: `JWKS fetch returned HTTP ${res.status}`, derivedFromLease, explicitlyConfigured };
647
- }
648
- const doc = (await res.json());
649
- const keys = jwksToPems(doc);
650
- if (!keys.ok) {
651
- return { status: 'unavailable', keys: {}, source: 'jwks', url, warnings, reason: keys.reason, derivedFromLease, explicitlyConfigured };
652
- }
653
- const result = applyPins(keys.pems, 'jwks', url);
654
- return { ...result, derivedFromLease };
655
- }
656
- catch (err) {
657
- return {
658
- status: 'unavailable', keys: {}, source: 'jwks', url, warnings, derivedFromLease, explicitlyConfigured,
659
- reason: `JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`,
660
- };
661
- }
662
- }
663
- /** Public halves used to verify PACKS — i.e. which code this fleet is allowed to execute. */
664
- async function loadPackTrustRoot(opts) {
665
- return loadTrustRoot(PACK_TRUST_ROOT_SPEC, opts);
666
- }
667
- /**
668
- * Public halves used to verify signed LEASE envelopes — i.e. which policy this instance obeys.
669
- *
670
- * Separate from the pack root because the control plane refuses to register one kid under two
671
- * purposes, so there is no key that can serve both. See `LEASE_SIGNING_KEYS_ENV`.
672
- *
673
- * A caller with no lease root configured must fall back to the pack root and say so: that is what
674
- * every deployment signing leases today is doing, and `requireSignedLease` is sticky with no
675
- * plane-side undo, so a hard cutover here is unrecoverable from the plane. `explicitlyConfigured`
676
- * is what makes that fallback decidable — a DERIVED lease root that comes back `unavailable`
677
- * (a plane publishing no lease key) must not be read as "the operator has moved over".
678
- */
679
- async function loadLeaseTrustRoot(opts) {
680
- return loadTrustRoot(LEASE_TRUST_ROOT_SPEC, opts);
681
- }
682
- /**
683
- * Which keyring verifies a signed lease — and whether that answer is the back-compat fallback.
684
- *
685
- * A lease root named OUTRIGHT (`AGENTHIPPO_LEASE_JWKS_URL` / `AGENTHIPPO_LEASE_SIGNING_KEYS`) is
686
- * the whole answer: the pack keyring is not consulted, so a lease-signing key cannot be smuggled in
687
- * through the root that decides which code runs, and an operator who has moved over gets the
688
- * separation they asked for.
689
- *
690
- * With nothing named, the pack keyring stays in play. That is not laziness — it is every deployment
691
- * that signs leases today, whose lease key necessarily sits in its PACK trust root because until
692
- * now that was the only keyring serve consulted. `requireSignedLease` latches per instance and the
693
- * control plane has no undo, so an instance that stopped recognising its own lease key would refuse
694
- * turns and could not be talked out of it from the console. The derived lease keys are unioned in
695
- * (and win a kid collision) so a rollover has both halves live at once.
696
- *
697
- * `packFallback` is returned rather than logged here: the caller owns the "warn exactly once, and
698
- * only when a signed lease is actually being verified" part.
699
- */
700
- function selectLeaseSigningKeys(leaseTrust, packTrust) {
701
- if (leaseTrust.explicitlyConfigured) {
702
- return { keys: leaseTrust.keys, packFallback: false };
703
- }
704
- return { keys: { ...packTrust.keys, ...leaseTrust.keys }, packFallback: true };
705
- }
706
- /**
707
- * Accept both shapes: this codebase's `{pemsByKid}` and a standard JWKS `{keys:[…]}` — the latter
708
- * is exactly what `authority/warrant.ts:jwks()` publishes, so the pack trust root and the warrant
709
- * trust root can be the same document.
710
- *
711
- * ES256 only, matching the alg pinning in the verifier. An RSA or symmetric entry in a JWKS is not
712
- * something to quietly skip past — it means the document is not what this verifier expects.
713
- */
714
- function jwksToPems(doc) {
715
- if (doc.pemsByKid && typeof doc.pemsByKid === 'object') {
716
- return { ok: true, pems: doc.pemsByKid };
717
- }
718
- if (!Array.isArray(doc.keys)) {
719
- return { ok: false, reason: 'JWKS document has neither `pemsByKid` nor a `keys` array' };
720
- }
721
- const pems = {};
722
- for (const jwk of doc.keys) {
723
- if (!jwk || typeof jwk !== 'object') {
724
- continue;
725
- }
726
- if (jwk.kty !== 'EC' || jwk.crv !== 'P-256') {
727
- continue;
728
- }
729
- if (jwk.alg !== undefined && jwk.alg !== 'ES256') {
730
- continue;
731
- }
732
- if (typeof jwk.kid !== 'string' || !jwk.kid) {
733
- continue;
734
- }
735
- try {
736
- pems[jwk.kid] = crypto.createPublicKey({ key: jwk, format: 'jwk' })
737
- .export({ type: 'spki', format: 'pem' }).toString();
738
- }
739
- catch { /* an unreadable entry is dropped; an empty result is reported as unavailable */ }
740
- }
741
- if (Object.keys(pems).length === 0) {
742
- return { ok: false, reason: 'JWKS document published no usable ES256 (P-256) keys' };
743
- }
744
- return { ok: true, pems };
745
- }
746
- /**
747
- * Back-compat shim. Returns just the keys, `{}` on any failure.
748
- *
749
- * Prefer `loadPackTrustRoot`: this signature cannot express "configured but unavailable", which is
750
- * the distinction finding A4 is about.
751
- *
752
- * @deprecated
753
- */
754
- async function loadPackSigningKeys(opts) {
755
- return (await loadPackTrustRoot(opts)).keys;
756
- }
757
- // ---------------------------------------------------------------------------------------------
758
- // Re-verification on the turn path
759
- // ---------------------------------------------------------------------------------------------
760
- /** How long a verified result is reused without even probing the tree. */
761
- exports.PACK_PROBE_INTERVAL_MS = 1_000;
762
- /** How long a verified result is reused without a FULL digest, however clean the probe looks. */
763
- exports.PACK_FULL_REVERIFY_INTERVAL_MS = 30_000;
764
- /**
765
- * Verify-per-turn with a cheap change probe.
766
- *
767
- * The signature used to be computed ONCE at boot and the boolean cached for the life of the
768
- * process. In the DEFAULT deployment shape (no `--sandbox`) the engine runs IN THIS PROCESS with
769
- * `fileAccess: full`, so an agent can edit its own pack directory — including, before the digest
770
- * fix above, dropping a `PreToolUse` hook into `.claude/` — and every subsequent turn would still
771
- * pass on the boot-time boolean. "Verified before run" has to mean before each run.
772
- *
773
- * Why this shape rather than a per-turn digest, or a plain interval:
774
- *
775
- * - A full digest reads and hashes every byte of the pack. On the turn path that is a filesystem
776
- * walk plus O(bytes) of SHA-256 per turn, for a fact that is usually unchanged. Not measured,
777
- * therefore not put on a hot path — which is exactly what the original comment said and why it
778
- * cached, so replacing one unmeasured choice with another would be no better.
779
- * - `packTreeProbe` is `lstat` only: no reads, no hashing. It catches edits, replacements,
780
- * additions and removals, and it is what makes the common case (nothing changed) cheap.
781
- * - The probe alone is NOT sufficient: an attacker inside the process can restore mtime and size
782
- * after editing a file of identical length. So a full re-verify also runs unconditionally every
783
- * `PACK_FULL_REVERIFY_INTERVAL_MS`, which bounds that window rather than leaving it open for
784
- * the life of the process. Lowering that constant trades CPU for a shorter window.
785
- *
786
- * Residual, stated plainly: within one full-reverify interval, an in-process agent that edits its
787
- * pack while preserving size and mtime is not detected. The structural fix for that is `--sandbox`
788
- * (the engine cannot reach the pack directory at all); this bounds the exposure for the default
789
- * shape rather than eliminating it.
790
- */
791
- function createPackVerifier(opts = {}) {
792
- const probeEvery = opts.probeIntervalMs ?? exports.PACK_PROBE_INTERVAL_MS;
793
- const fullEvery = opts.fullReverifyIntervalMs ?? exports.PACK_FULL_REVERIFY_INTERVAL_MS;
794
- let cached;
795
- let cachedKey = '';
796
- let cachedProbe = '';
797
- let lastProbeAt = 0;
798
- let lastFullAt = 0;
799
- let fullCount = 0;
800
- const identity = (i) => `${i.packDir}${i.pack}${i.packVersion}${Object.keys(i.keys).sort().join(',')}`;
801
- const full = (input, nowMs) => {
802
- fullCount += 1;
803
- cachedKey = identity(input);
804
- cachedProbe = packTreeProbe(input.packDir);
805
- lastProbeAt = nowMs;
806
- lastFullAt = nowMs;
807
- const token = readPackSignature(input.packDir);
808
- // "Unsigned" is reported ahead of "no trust root": the first step is the same either way
809
- // (sign the pack), and an operator who is told about a missing keyring while their pack has
810
- // no signature at all will configure the keyring and land right back here.
811
- cached = token
812
- ? verifyPack(token, input.keys, { packDir: input.packDir, pack: input.pack, packVersion: input.packVersion })
813
- : { ok: false, kind: 'unsigned', reason: `${input.pack} is not signed (no ${exports.PACK_SIGNATURE_FILE} at the pack root)` };
814
- return cached;
815
- };
816
- return {
817
- fullVerifications: () => fullCount,
818
- refresh(input, nowMs = Date.now()) { return full(input, nowMs); },
819
- verify(input, nowMs = Date.now()) {
820
- // Any change of pack, version or keyring invalidates outright — none of those are the
821
- // kind of thing to reuse a cached verdict across.
822
- if (!cached || cachedKey !== identity(input)) {
823
- return full(input, nowMs);
824
- }
825
- if (nowMs - lastFullAt >= fullEvery) {
826
- return full(input, nowMs);
827
- }
828
- if (nowMs - lastProbeAt < probeEvery) {
829
- return cached;
830
- }
831
- lastProbeAt = nowMs;
832
- const probe = packTreeProbe(input.packDir);
833
- if (probe === cachedProbe) {
834
- return cached;
835
- }
836
- return full(input, nowMs);
837
- },
838
- };
839
- }