@agenthippo-ai/agenthippo 1.110.11 → 1.110.20

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 (534) 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 -302
  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 -1283
  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 +618 -564
  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 +127 -459
  61. package/out/scripts/analytics/agent-fleet-widget.js +18 -257
  62. package/out/scripts/analytics/agentide-litellm-otel.config.yaml +0 -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/token-cost-flamegraph-widget.js +4 -461
  70. package/out/scripts/analytics/token-cost-trend-widget.js +4 -534
  71. package/out/scripts/analytics/workflows-collector.cjs +4 -314
  72. package/out/scripts/analytics/workflows-daemon.mjs +9 -185
  73. package/out/scripts/analytics/workflows-widget.cjs +15 -159
  74. package/out/scripts/analytics/wow-model-widget.js +10 -120
  75. package/out/scripts/vendor-tools.mjs +2 -233
  76. package/out/skills/publish.js +3 -178
  77. package/out/store/github/setup.js +7 -212
  78. package/out/store/oramaIndex.js +2 -884
  79. package/out/sync.js +26 -1829
  80. package/out/terminalLogger.js +5 -358
  81. package/out/utils/pathSafety.js +2 -60
  82. package/out/utils/pythonRunner.js +4 -258
  83. package/out/utils/toolPath.js +2 -83
  84. package/out/workspaceFolders.js +2 -59
  85. package/package.json +10 -6
  86. package/out/agentpack/github.js +0 -547
  87. package/out/agentpack/index.js +0 -69
  88. package/out/agentpack/install.js +0 -297
  89. package/out/agentpack/manager.js +0 -441
  90. package/out/agentpack/manifest.js +0 -135
  91. package/out/agentpack/paths.js +0 -521
  92. package/out/agentpack/publish.js +0 -248
  93. package/out/agentpack/stores.js +0 -554
  94. package/out/analytics/dashboard/fleetStatusUtils.js +0 -30
  95. package/out/analytics/dashboard/fleetTitleUtils.js +0 -68
  96. package/out/analytics/dashboard/refreshPolicy.js +0 -16
  97. package/out/analytics/dashboard/scheduledFleetFingerprint.js +0 -22
  98. package/out/analytics/dashboard/scheduledFleetUtils.js +0 -22
  99. package/out/analytics/dashboard/sessionEventFleetStats.js +0 -118
  100. package/out/analytics/dashboard/viewsConfigMerge.js +0 -221
  101. package/out/analytics/dashboard/webview/codicon.ttf +0 -0
  102. package/out/analytics/identity.js +0 -0
  103. package/out/analytics/sessionEvents.js +0 -324
  104. package/out/auth/callbackUriParse.js +0 -59
  105. package/out/auth/types.js +0 -12
  106. package/out/auth-broker/config.js +0 -112
  107. package/out/auth-broker/jwt.js +0 -105
  108. package/out/auth-broker/pkce.js +0 -59
  109. package/out/auth-broker/server.js +0 -681
  110. package/out/auth-broker/store.js +0 -275
  111. package/out/authority/warrant.js +0 -206
  112. package/out/base-prompts/mcp-servers/.mcp.json +0 -13
  113. package/out/base-prompts/mcp-servers/langfuse-analytics/README.md +0 -142
  114. package/out/base-prompts/mcp-servers/langfuse-analytics/mcp.json +0 -13
  115. package/out/base-prompts/mcp-servers/langfuse-analytics/package-lock.json +0 -1192
  116. package/out/base-prompts/mcp-servers/langfuse-analytics/package.json +0 -23
  117. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/run-with-env.sh +0 -12
  118. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/sdk-test.js +0 -102
  119. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/simple-test.js +0 -137
  120. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/test-client.js +0 -118
  121. package/out/base-prompts/mcp-servers/langfuse-analytics/scripts/test-server.js +0 -209
  122. package/out/base-prompts/mcp-servers/langfuse-analytics/src/client.ts +0 -431
  123. package/out/base-prompts/mcp-servers/langfuse-analytics/src/index.ts +0 -270
  124. package/out/base-prompts/mcp-servers/langfuse-analytics/tsconfig.json +0 -18
  125. package/out/base-prompts/rules/AGENTS.md +0 -204
  126. package/out/base-prompts/skills/agent-browser/SKILL.md +0 -102
  127. package/out/base-prompts/skills/agent-builder/SKILL.md +0 -73
  128. package/out/base-prompts/skills/agent-builder/references/agent-pack.md +0 -63
  129. package/out/base-prompts/skills/agent-builder/references/crewai.md +0 -66
  130. package/out/base-prompts/skills/agent-builder/references/langchain.md +0 -60
  131. package/out/base-prompts/skills/agent-builder/references/raw-sdk.md +0 -73
  132. package/out/base-prompts/skills/agent-engine-creator/SKILL.md +0 -586
  133. package/out/base-prompts/skills/agent-engine-installer/SKILL.md +0 -106
  134. package/out/base-prompts/skills/agent-engine-installer/scripts/install-engine.mjs +0 -259
  135. package/out/base-prompts/skills/agent-engine-installer/scripts/install-engine.ps1 +0 -189
  136. package/out/base-prompts/skills/agenthippo-cli/SKILL.md +0 -69
  137. package/out/base-prompts/skills/agenthippo-cli/scripts/install.sh +0 -63
  138. package/out/base-prompts/skills/agentpack-creator/SKILL.md +0 -375
  139. package/out/base-prompts/skills/agentpack-creator/references/agent-templates.md +0 -261
  140. package/out/base-prompts/skills/agentpack-creator/references/agents-md-guide.md +0 -195
  141. package/out/base-prompts/skills/agentpack-creator/scripts/init_pack.py +0 -391
  142. package/out/base-prompts/skills/agentpack-creator/scripts/init_pack_test.py +0 -294
  143. package/out/base-prompts/skills/agentpack-testbench/SKILL.md +0 -135
  144. package/out/base-prompts/skills/algorithmic-art/LICENSE.txt +0 -202
  145. package/out/base-prompts/skills/algorithmic-art/SKILL.md +0 -405
  146. package/out/base-prompts/skills/algorithmic-art/templates/generator_template.js +0 -223
  147. package/out/base-prompts/skills/algorithmic-art/templates/viewer.html +0 -599
  148. package/out/base-prompts/skills/debug-agent/SKILL.md +0 -83
  149. package/out/base-prompts/skills/desktop-automation/SKILL.md +0 -166
  150. package/out/base-prompts/skills/desktop-automation/references/agenthippo-ui-recipes.md +0 -441
  151. package/out/base-prompts/skills/desktop-automation/scripts/windows-desktop-uia.psm1 +0 -280
  152. package/out/base-prompts/skills/docx/LICENSE.txt +0 -30
  153. package/out/base-prompts/skills/docx/SKILL.md +0 -197
  154. package/out/base-prompts/skills/docx/docx-js.md +0 -350
  155. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  156. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  157. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  158. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  159. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  160. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  161. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  162. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  163. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  164. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  165. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  166. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  167. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  168. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  169. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  170. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  171. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  172. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  173. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  174. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  175. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  176. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  177. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  178. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  179. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  180. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  181. package/out/base-prompts/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  182. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  183. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  184. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  185. package/out/base-prompts/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  186. package/out/base-prompts/skills/docx/ooxml/schemas/mce/mc.xsd +0 -75
  187. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  188. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  189. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  190. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  191. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  192. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  193. package/out/base-prompts/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  194. package/out/base-prompts/skills/docx/ooxml/scripts/pack.py +0 -159
  195. package/out/base-prompts/skills/docx/ooxml/scripts/unpack.py +0 -29
  196. package/out/base-prompts/skills/docx/ooxml/scripts/validate.py +0 -69
  197. package/out/base-prompts/skills/docx/ooxml/scripts/validation/__init__.py +0 -15
  198. package/out/base-prompts/skills/docx/ooxml/scripts/validation/base.py +0 -951
  199. package/out/base-prompts/skills/docx/ooxml/scripts/validation/docx.py +0 -274
  200. package/out/base-prompts/skills/docx/ooxml/scripts/validation/pptx.py +0 -315
  201. package/out/base-prompts/skills/docx/ooxml/scripts/validation/redlining.py +0 -279
  202. package/out/base-prompts/skills/docx/ooxml.md +0 -610
  203. package/out/base-prompts/skills/docx/scripts/__init__.py +0 -1
  204. package/out/base-prompts/skills/docx/scripts/document.py +0 -1276
  205. package/out/base-prompts/skills/docx/scripts/templates/comments.xml +0 -3
  206. package/out/base-prompts/skills/docx/scripts/templates/commentsExtended.xml +0 -3
  207. package/out/base-prompts/skills/docx/scripts/templates/commentsExtensible.xml +0 -3
  208. package/out/base-prompts/skills/docx/scripts/templates/commentsIds.xml +0 -3
  209. package/out/base-prompts/skills/docx/scripts/templates/people.xml +0 -3
  210. package/out/base-prompts/skills/docx/scripts/utilities.py +0 -374
  211. package/out/base-prompts/skills/gateway-outbound/SKILL.md +0 -136
  212. package/out/base-prompts/skills/mcp-builder/LICENSE.txt +0 -202
  213. package/out/base-prompts/skills/mcp-builder/SKILL.md +0 -328
  214. package/out/base-prompts/skills/mcp-builder/reference/evaluation.md +0 -602
  215. package/out/base-prompts/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
  216. package/out/base-prompts/skills/mcp-builder/reference/node_mcp_server.md +0 -970
  217. package/out/base-prompts/skills/mcp-builder/reference/python_mcp_server.md +0 -719
  218. package/out/base-prompts/skills/mcp-builder/scripts/connections.py +0 -151
  219. package/out/base-prompts/skills/mcp-builder/scripts/evaluation.py +0 -373
  220. package/out/base-prompts/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
  221. package/out/base-prompts/skills/mcp-builder/scripts/requirements.txt +0 -2
  222. package/out/base-prompts/skills/openclaw/SKILL.md +0 -406
  223. package/out/base-prompts/skills/openclaw/scripts/run-smoke.sh +0 -61
  224. package/out/base-prompts/skills/pdf/LICENSE.txt +0 -30
  225. package/out/base-prompts/skills/pdf/SKILL.md +0 -294
  226. package/out/base-prompts/skills/pdf/forms.md +0 -205
  227. package/out/base-prompts/skills/pdf/reference.md +0 -612
  228. package/out/base-prompts/skills/pdf/scripts/check_bounding_boxes.py +0 -70
  229. package/out/base-prompts/skills/pdf/scripts/check_bounding_boxes_test.py +0 -226
  230. package/out/base-prompts/skills/pdf/scripts/check_fillable_fields.py +0 -12
  231. package/out/base-prompts/skills/pdf/scripts/convert_pdf_to_images.py +0 -35
  232. package/out/base-prompts/skills/pdf/scripts/create_validation_image.py +0 -41
  233. package/out/base-prompts/skills/pdf/scripts/extract_form_field_info.py +0 -152
  234. package/out/base-prompts/skills/pdf/scripts/fill_fillable_fields.py +0 -114
  235. package/out/base-prompts/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -108
  236. package/out/base-prompts/skills/pptx/LICENSE.txt +0 -30
  237. package/out/base-prompts/skills/pptx/SKILL.md +0 -484
  238. package/out/base-prompts/skills/pptx/html2pptx.md +0 -625
  239. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
  240. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
  241. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
  242. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
  243. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
  244. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
  245. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
  246. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
  247. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
  248. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
  249. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
  250. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
  251. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
  252. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
  253. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
  254. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
  255. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
  256. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
  257. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
  258. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
  259. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
  260. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
  261. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
  262. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
  263. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
  264. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
  265. package/out/base-prompts/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
  266. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
  267. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
  268. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
  269. package/out/base-prompts/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
  270. package/out/base-prompts/skills/pptx/ooxml/schemas/mce/mc.xsd +0 -75
  271. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
  272. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
  273. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
  274. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
  275. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
  276. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
  277. package/out/base-prompts/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
  278. package/out/base-prompts/skills/pptx/ooxml/scripts/pack.py +0 -159
  279. package/out/base-prompts/skills/pptx/ooxml/scripts/unpack.py +0 -29
  280. package/out/base-prompts/skills/pptx/ooxml/scripts/validate.py +0 -69
  281. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/__init__.py +0 -15
  282. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/base.py +0 -951
  283. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/docx.py +0 -274
  284. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/pptx.py +0 -315
  285. package/out/base-prompts/skills/pptx/ooxml/scripts/validation/redlining.py +0 -279
  286. package/out/base-prompts/skills/pptx/ooxml.md +0 -427
  287. package/out/base-prompts/skills/pptx/scripts/html2pptx.js +0 -984
  288. package/out/base-prompts/skills/pptx/scripts/inventory.py +0 -1020
  289. package/out/base-prompts/skills/pptx/scripts/rearrange.py +0 -231
  290. package/out/base-prompts/skills/pptx/scripts/replace.py +0 -385
  291. package/out/base-prompts/skills/pptx/scripts/thumbnail.py +0 -450
  292. package/out/base-prompts/skills/prompt-lab/SKILL.md +0 -149
  293. package/out/base-prompts/skills/prompt-lab/scripts/query-analytics.sh +0 -2551
  294. package/out/base-prompts/skills/skill-creator/LICENSE.txt +0 -202
  295. package/out/base-prompts/skills/skill-creator/SKILL.md +0 -371
  296. package/out/base-prompts/skills/skill-creator/references/output-patterns.md +0 -82
  297. package/out/base-prompts/skills/skill-creator/references/workflows.md +0 -28
  298. package/out/base-prompts/skills/skill-creator/scripts/init_skill.py +0 -303
  299. package/out/base-prompts/skills/skill-creator/scripts/package_skill.py +0 -110
  300. package/out/base-prompts/skills/skill-creator/scripts/quick_validate.py +0 -95
  301. package/out/base-prompts/skills/skill-installer/SKILL.md +0 -251
  302. package/out/base-prompts/skills/skill-installer/references/store-api.md +0 -219
  303. package/out/base-prompts/skills/spotlight-dashboard/SKILL.md +0 -83
  304. package/out/base-prompts/skills/spotlight-insights/SKILL.md +0 -101
  305. package/out/base-prompts/skills/spotlight-optimize/SKILL.md +0 -93
  306. package/out/base-prompts/skills/spotlight-optimize/scripts/query-analytics.sh +0 -2551
  307. package/out/base-prompts/skills/spotlight-query/SKILL.md +0 -314
  308. package/out/base-prompts/skills/spotlight-query/references/otel-schema.md +0 -163
  309. package/out/base-prompts/skills/spotlight-query/scripts/query-analytics.sh +0 -2551
  310. package/out/base-prompts/skills/spotlight-query/scripts/query-analytics.test.sh +0 -744
  311. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/sessions/sess-test-1.jsonl +0 -14
  312. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/traces/.duckdb-index.json +0 -7
  313. package/out/base-prompts/skills/spotlight-query/scripts/test-fixtures/analytics/traces/sample.jsonl +0 -5
  314. package/out/base-prompts/skills/spotlight-report/SKILL.md +0 -86
  315. package/out/base-prompts/skills/spotlight-visualize/SKILL.md +0 -92
  316. package/out/base-prompts/skills/spotlight-visualize/scripts/query-analytics.sh +0 -2551
  317. package/out/base-prompts/skills/xlsx/LICENSE.txt +0 -30
  318. package/out/base-prompts/skills/xlsx/SKILL.md +0 -289
  319. package/out/base-prompts/skills/xlsx/recalc.py +0 -178
  320. package/out/branding.js +0 -49
  321. package/out/cli/commands/anywhere.js +0 -66
  322. package/out/cli/commands/ask.js +0 -246
  323. package/out/cli/commands/auth-broker.js +0 -24
  324. package/out/cli/commands/auth.js +0 -219
  325. package/out/cli/commands/chat.js +0 -357
  326. package/out/cli/commands/conformance.js +0 -249
  327. package/out/cli/commands/data-plane.js +0 -151
  328. package/out/cli/commands/deploy.js +0 -263
  329. package/out/cli/commands/gateway.js +0 -218
  330. package/out/cli/commands/idp.js +0 -85
  331. package/out/cli/commands/pack.js +0 -399
  332. package/out/cli/commands/probe-custom-engine.js +0 -82
  333. package/out/cli/commands/sandbox.js +0 -351
  334. package/out/cli/commands/serve.js +0 -1950
  335. package/out/cli/commands/store.js +0 -927
  336. package/out/cli/credential-context.js +0 -108
  337. package/out/cli/data-plane/broker.js +0 -78
  338. package/out/cli/data-plane/connector-host.js +0 -121
  339. package/out/cli/data-plane/egress.js +0 -189
  340. package/out/cli/data-plane/gateway.js +0 -218
  341. package/out/cli/data-plane/index.js +0 -153
  342. package/out/cli/data-plane/registry.js +0 -89
  343. package/out/cli/data-plane/remote.js +0 -106
  344. package/out/cli/data-plane/sidecar.js +0 -225
  345. package/out/cli/deploy/blueprints/registry.js +0 -84
  346. package/out/cli/deploy/layers/identity.js +0 -175
  347. package/out/cli/deploy-init.js +0 -3023
  348. package/out/cli/deps.js +0 -342
  349. package/out/cli/idp-init.js +0 -338
  350. package/out/cli/pack-install-ref.js +0 -15
  351. package/out/cli/pack-loader.js +0 -418
  352. package/out/cli/pack-runtime.js +0 -61
  353. package/out/cli/runtime.js +0 -450
  354. package/out/cli/serve-hardening.js +0 -776
  355. package/out/cli/state-sync.js +0 -424
  356. package/out/cli/utils.js +0 -231
  357. package/out/engines/base.js +0 -188
  358. package/out/engines/claude.js +0 -1254
  359. package/out/engines/codex.js +0 -862
  360. package/out/engines/custom.js +0 -680
  361. package/out/engines/customEngineIpc.js +0 -95
  362. package/out/engines/customEngineRunnerEmbed.js +0 -107
  363. package/out/engines/customRegistry.js +0 -274
  364. package/out/engines/embeddedCustomEngineRunner.generated.js +0 -9
  365. package/out/engines/engineApiKey.js +0 -138
  366. package/out/engines/install.js +0 -372
  367. package/out/engines/persistentEngineWorker.js +0 -320
  368. package/out/engines/publish.js +0 -341
  369. package/out/evidence/sessionShip.js +0 -643
  370. package/out/gateway/bridge.js +0 -843
  371. package/out/gateway/cli-agent-id.js +0 -36
  372. package/out/gateway/client.js +0 -336
  373. package/out/gateway/client.test.js +0 -395
  374. package/out/gateway/gateway-scope-errors.js +0 -14
  375. package/out/gateway/gatewayBackup.js +0 -76
  376. package/out/gateway/installSource.js +0 -68
  377. package/out/gateway/lifecycle.js +0 -3190
  378. package/out/gateway/openclaw-channel-routing.js +0 -317
  379. package/out/gateway/outboundHandles.js +0 -373
  380. package/out/gateway/outboundPaths.js +0 -75
  381. package/out/gateway/outboundSend.js +0 -254
  382. package/out/gateway/protocol.js +0 -48
  383. package/out/gateway/secretsPreflight.js +0 -90
  384. package/out/gateway/sessionRouting.js +0 -77
  385. package/out/headless/index.js +0 -546
  386. package/out/headless/sync.js +0 -473
  387. package/out/live-e2e/mcp-demo/server.mjs +0 -32
  388. package/out/live-probe/connector.mjs +0 -8
  389. package/out/live-probe/env-report.mjs +0 -8
  390. package/out/mcp.js +0 -654
  391. package/out/pack/caps.js +0 -271
  392. package/out/pack/governor.js +0 -326
  393. package/out/pack/lease-schema.js +0 -273
  394. package/out/pack/lease.js +0 -682
  395. package/out/pack/reconcile.js +0 -217
  396. package/out/pack/signature.js +0 -839
  397. package/out/permissions.js +0 -108
  398. package/out/permissions.mapping.yaml +0 -68
  399. package/out/registry/index.js +0 -332
  400. package/out/runner/host.js +0 -141
  401. package/out/runner/protocol.js +0 -128
  402. package/out/runner/remoteEngine.js +0 -166
  403. package/out/runtime/interfaces/config-provider.js +0 -32
  404. package/out/runtime/interfaces/edit-tracker.js +0 -24
  405. package/out/runtime/interfaces/index.js +0 -29
  406. package/out/runtime/interfaces/logger.js +0 -40
  407. package/out/runtime/interfaces/permission-handler.js +0 -66
  408. package/out/runtime/interfaces/session-store.js +0 -342
  409. package/out/runtime/vscode/vscode-session-store.js +0 -22
  410. package/out/sandbox/containerDriver.js +0 -572
  411. package/out/sandbox/processDriver.js +0 -318
  412. package/out/sandbox/sandboxRunner.js +0 -303
  413. package/out/sandbox/support.js +0 -301
  414. package/out/sandbox/types.js +0 -55
  415. package/out/scripts/analytics/fleet-local-adapter.js +0 -246
  416. package/out/scripts/analytics/live-fleet-4-collector.cjs +0 -315
  417. package/out/scripts/analytics/live-fleet-4-daemon.mjs +0 -134
  418. package/out/scripts/analytics/live-fleet-4-widget.cjs +0 -433
  419. package/out/scripts/gateway/Dockerfile.serve +0 -45
  420. package/out/scripts/gateway/docker-serve.sh +0 -248
  421. package/out/scripts/gateway/setup-gateway-server.ps1 +0 -953
  422. package/out/scripts/gateway/setup-gateway-server.sh +0 -935
  423. package/out/session.js +0 -272
  424. package/out/shared/agentEngines.js +0 -170
  425. package/out/shared/index.js +0 -109
  426. package/out/shared/models.js +0 -136
  427. package/out/shared/providers.js +0 -205
  428. package/out/spotlight/install.js +0 -345
  429. package/out/spotlight/publish.js +0 -544
  430. package/out/spotlight/yaml.js +0 -31
  431. package/out/store/index.js +0 -786
  432. package/out/store/shared.js +0 -241
  433. package/out/test/agentEnvFile.test.js +0 -97
  434. package/out/test/agentYaml.test.js +0 -373
  435. package/out/test/agentpack.test.js +0 -639
  436. package/out/test/analytics-lifecycle.test.js +0 -174
  437. package/out/test/analytics.test.js +0 -756
  438. package/out/test/auth-baseurl.test.js +0 -132
  439. package/out/test/auth-bootstrapApply.test.js +0 -123
  440. package/out/test/auth-broker-hardening.test.js +0 -227
  441. package/out/test/auth-broker.test.js +0 -541
  442. package/out/test/auth-callback.test.js +0 -62
  443. package/out/test/blueprint-registry.test.js +0 -105
  444. package/out/test/branding.test.js +0 -242
  445. package/out/test/caps-governor.test.js +0 -460
  446. package/out/test/cli-agent-id.test.js +0 -55
  447. package/out/test/codex-new-file-survival.test.js +0 -119
  448. package/out/test/configuration-scopes.test.js +0 -131
  449. package/out/test/credential-context.test.js +0 -160
  450. package/out/test/custom-env-layering.test.js +0 -151
  451. package/out/test/customEngineInstall.test.js +0 -100
  452. package/out/test/customRegistry.test.js +0 -122
  453. package/out/test/data-plane-engine-wiring.test.js +0 -282
  454. package/out/test/data-plane.test.js +0 -624
  455. package/out/test/deploy-init.test.js +0 -860
  456. package/out/test/deps-auto-install.test.js +0 -81
  457. package/out/test/egress-broker.test.js +0 -172
  458. package/out/test/engine-integration.test.js +0 -297
  459. package/out/test/enginePaths.test.js +0 -195
  460. package/out/test/enginePublish.test.js +0 -82
  461. package/out/test/fleetDisplayUtils.test.js +0 -100
  462. package/out/test/gateway-client.test.js +0 -409
  463. package/out/test/gateway-install-source.test.js +0 -111
  464. package/out/test/gateway-lifecycle.test.js +0 -608
  465. package/out/test/gateway-outbound.test.js +0 -538
  466. package/out/test/gateway-reset-mappings.test.js +0 -221
  467. package/out/test/gateway-route-index.test.js +0 -235
  468. package/out/test/gateway-secrets-preflight.test.js +0 -127
  469. package/out/test/gateway-session-routing.test.js +0 -65
  470. package/out/test/gateway-session-store.test.js +0 -216
  471. package/out/test/github.test.js +0 -232
  472. package/out/test/governor-hardening.test.js +0 -222
  473. package/out/test/headless-sync.test.js +0 -301
  474. package/out/test/helpers/manifest-fixtures.js +0 -27
  475. package/out/test/idp-init.test.js +0 -151
  476. package/out/test/lease-signature.test.js +0 -357
  477. package/out/test/lease-trust-root.test.js +0 -273
  478. package/out/test/lease-validation.test.js +0 -224
  479. package/out/test/lease.test.js +0 -114
  480. package/out/test/localFleetAdapter.test.js +0 -91
  481. package/out/test/mcp-obo.test.js +0 -107
  482. package/out/test/mcp.test.js +0 -389
  483. package/out/test/model-routing.test.js +0 -133
  484. package/out/test/openclaw-channel-routing.test.js +0 -191
  485. package/out/test/pack-admission.test.js +0 -216
  486. package/out/test/pack-digest-parity.test.js +0 -140
  487. package/out/test/pack-reconcile.test.js +0 -183
  488. package/out/test/pack-signature-artifact.test.js +0 -103
  489. package/out/test/pack-signature.test.js +0 -176
  490. package/out/test/pack-trust-root.test.js +0 -202
  491. package/out/test/pathSafety.test.js +0 -63
  492. package/out/test/permissions.test.js +0 -175
  493. package/out/test/persistent-engine-worker.test.js +0 -220
  494. package/out/test/refreshPolicy.test.js +0 -60
  495. package/out/test/registry.test.js +0 -351
  496. package/out/test/remote-trust.test.js +0 -242
  497. package/out/test/runner-protocol.test.js +0 -249
  498. package/out/test/runtime.test.js +0 -349
  499. package/out/test/sandbox-driver.test.js +0 -553
  500. package/out/test/sandbox-hardening.test.js +0 -406
  501. package/out/test/sandbox-runner.test.js +0 -343
  502. package/out/test/sandbox-scope.test.js +0 -449
  503. package/out/test/scheduledFleetStorage.test.js +0 -72
  504. package/out/test/serve-cron-acceptance.test.js +0 -370
  505. package/out/test/serve-gateway-turn.test.js +0 -389
  506. package/out/test/serve-hardening.test.js +0 -591
  507. package/out/test/serveClient.test.js +0 -209
  508. package/out/test/sessionJsonlFleet.test.js +0 -78
  509. package/out/test/sessionShip.test.js +0 -618
  510. package/out/test/shared.test.js +0 -173
  511. package/out/test/skills-mcp.test.js +0 -299
  512. package/out/test/spotlightPublish.test.js +0 -327
  513. package/out/test/spotlightYaml.test.js +0 -58
  514. package/out/test/state-sync-peer.test.js +0 -156
  515. package/out/test/store-install-safe.test.js +0 -69
  516. package/out/test/store.test.js +0 -331
  517. package/out/test/stores.test.js +0 -504
  518. package/out/test/sync-switch.test.js +0 -251
  519. package/out/test/teamViewDiscovery.test.js +0 -90
  520. package/out/test/tls-bypass.test.js +0 -90
  521. package/out/test/toolPath.test.js +0 -120
  522. package/out/test/utils.test.js +0 -308
  523. package/out/test/viewsConfigMerge.test.js +0 -180
  524. package/out/test/warrant.test.js +0 -138
  525. package/out/test/windows-command-line.test.js +0 -75
  526. package/out/utils/agentEnvFile.js +0 -131
  527. package/out/utils/binary.js +0 -175
  528. package/out/utils/index.js +0 -37
  529. package/out/utils/network.js +0 -74
  530. package/out/utils/paths.js +0 -116
  531. package/out/utils/pid.js +0 -180
  532. package/out/utils/resolveNodeBinary.js +0 -168
  533. package/out/utils/windowsCommandLine.js +0 -29
  534. 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
- }