hammoc 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/README.md +422 -405
  2. package/bin/hammoc.js +0 -6
  3. package/package.json +100 -94
  4. package/packages/client/dist/assets/agentExampleHighlight-BgwTm15v.js +1 -0
  5. package/packages/client/dist/assets/commandTokenHighlight-BljHwnrK.js +1 -0
  6. package/packages/client/dist/assets/index-CjyjnXB8.css +32 -0
  7. package/packages/client/dist/assets/index-D3LxqW3f.js +2 -0
  8. package/packages/client/dist/assets/index-NqJdhlek.js +1498 -0
  9. package/packages/client/dist/assets/snippetTokenHighlight-DWsaQXX0.js +1 -0
  10. package/packages/client/dist/index.html +2 -2
  11. package/packages/client/dist/sw.js +1 -1
  12. package/packages/server/dist/app.d.ts.map +1 -1
  13. package/packages/server/dist/app.js +13 -21
  14. package/packages/server/dist/app.js.map +1 -1
  15. package/packages/server/dist/controllers/claudeMdController.d.ts +26 -0
  16. package/packages/server/dist/controllers/claudeMdController.d.ts.map +1 -0
  17. package/packages/server/dist/controllers/claudeMdController.js +158 -0
  18. package/packages/server/dist/controllers/claudeMdController.js.map +1 -0
  19. package/packages/server/dist/controllers/harnessAgentController.d.ts +28 -0
  20. package/packages/server/dist/controllers/harnessAgentController.d.ts.map +1 -0
  21. package/packages/server/dist/controllers/harnessAgentController.js +339 -0
  22. package/packages/server/dist/controllers/harnessAgentController.js.map +1 -0
  23. package/packages/server/dist/controllers/harnessCommandController.d.ts +28 -0
  24. package/packages/server/dist/controllers/harnessCommandController.d.ts.map +1 -0
  25. package/packages/server/dist/controllers/harnessCommandController.js +382 -0
  26. package/packages/server/dist/controllers/harnessCommandController.js.map +1 -0
  27. package/packages/server/dist/controllers/harnessController.d.ts +21 -0
  28. package/packages/server/dist/controllers/harnessController.d.ts.map +1 -0
  29. package/packages/server/dist/controllers/harnessController.js +176 -0
  30. package/packages/server/dist/controllers/harnessController.js.map +1 -0
  31. package/packages/server/dist/controllers/harnessHookController.d.ts +32 -0
  32. package/packages/server/dist/controllers/harnessHookController.d.ts.map +1 -0
  33. package/packages/server/dist/controllers/harnessHookController.js +363 -0
  34. package/packages/server/dist/controllers/harnessHookController.js.map +1 -0
  35. package/packages/server/dist/controllers/harnessLintController.d.ts +18 -0
  36. package/packages/server/dist/controllers/harnessLintController.d.ts.map +1 -0
  37. package/packages/server/dist/controllers/harnessLintController.js +72 -0
  38. package/packages/server/dist/controllers/harnessLintController.js.map +1 -0
  39. package/packages/server/dist/controllers/harnessMcpController.d.ts +28 -0
  40. package/packages/server/dist/controllers/harnessMcpController.d.ts.map +1 -0
  41. package/packages/server/dist/controllers/harnessMcpController.js +310 -0
  42. package/packages/server/dist/controllers/harnessMcpController.js.map +1 -0
  43. package/packages/server/dist/controllers/harnessPluginController.d.ts +17 -0
  44. package/packages/server/dist/controllers/harnessPluginController.d.ts.map +1 -0
  45. package/packages/server/dist/controllers/harnessPluginController.js +115 -0
  46. package/packages/server/dist/controllers/harnessPluginController.js.map +1 -0
  47. package/packages/server/dist/controllers/harnessShareScopeController.d.ts +15 -0
  48. package/packages/server/dist/controllers/harnessShareScopeController.d.ts.map +1 -0
  49. package/packages/server/dist/controllers/harnessShareScopeController.js +73 -0
  50. package/packages/server/dist/controllers/harnessShareScopeController.js.map +1 -0
  51. package/packages/server/dist/controllers/harnessSkillController.d.ts +32 -0
  52. package/packages/server/dist/controllers/harnessSkillController.d.ts.map +1 -0
  53. package/packages/server/dist/controllers/harnessSkillController.js +453 -0
  54. package/packages/server/dist/controllers/harnessSkillController.js.map +1 -0
  55. package/packages/server/dist/controllers/projectController.d.ts.map +1 -1
  56. package/packages/server/dist/controllers/projectController.js +11 -0
  57. package/packages/server/dist/controllers/projectController.js.map +1 -1
  58. package/packages/server/dist/controllers/snippetController.d.ts +35 -0
  59. package/packages/server/dist/controllers/snippetController.d.ts.map +1 -0
  60. package/packages/server/dist/controllers/snippetController.js +294 -0
  61. package/packages/server/dist/controllers/snippetController.js.map +1 -0
  62. package/packages/server/dist/handlers/websocket.d.ts +15 -0
  63. package/packages/server/dist/handlers/websocket.d.ts.map +1 -1
  64. package/packages/server/dist/handlers/websocket.js +79 -0
  65. package/packages/server/dist/handlers/websocket.js.map +1 -1
  66. package/packages/server/dist/index.js +5 -0
  67. package/packages/server/dist/index.js.map +1 -1
  68. package/packages/server/dist/locales/en/server.json +37 -4
  69. package/packages/server/dist/locales/es/server.json +0 -4
  70. package/packages/server/dist/locales/ja/server.json +0 -4
  71. package/packages/server/dist/locales/ko/server.json +0 -4
  72. package/packages/server/dist/locales/pt/server.json +0 -4
  73. package/packages/server/dist/locales/zh-CN/server.json +0 -4
  74. package/packages/server/dist/routes/harness.d.ts +8 -0
  75. package/packages/server/dist/routes/harness.d.ts.map +1 -0
  76. package/packages/server/dist/routes/harness.js +92 -0
  77. package/packages/server/dist/routes/harness.js.map +1 -0
  78. package/packages/server/dist/routes/projects.d.ts.map +1 -1
  79. package/packages/server/dist/routes/projects.js +5 -60
  80. package/packages/server/dist/routes/projects.js.map +1 -1
  81. package/packages/server/dist/routes/snippets.d.ts +14 -0
  82. package/packages/server/dist/routes/snippets.d.ts.map +1 -0
  83. package/packages/server/dist/routes/snippets.js +27 -0
  84. package/packages/server/dist/routes/snippets.js.map +1 -0
  85. package/packages/server/dist/services/bmadStatusService.d.ts +6 -2
  86. package/packages/server/dist/services/bmadStatusService.d.ts.map +1 -1
  87. package/packages/server/dist/services/bmadStatusService.js +88 -32
  88. package/packages/server/dist/services/bmadStatusService.js.map +1 -1
  89. package/packages/server/dist/services/chatService.d.ts +3 -0
  90. package/packages/server/dist/services/chatService.d.ts.map +1 -1
  91. package/packages/server/dist/services/chatService.js +27 -6
  92. package/packages/server/dist/services/chatService.js.map +1 -1
  93. package/packages/server/dist/services/claudeMdService.d.ts +48 -0
  94. package/packages/server/dist/services/claudeMdService.d.ts.map +1 -0
  95. package/packages/server/dist/services/claudeMdService.js +240 -0
  96. package/packages/server/dist/services/claudeMdService.js.map +1 -0
  97. package/packages/server/dist/services/commandService.d.ts +10 -0
  98. package/packages/server/dist/services/commandService.d.ts.map +1 -1
  99. package/packages/server/dist/services/commandService.js +129 -4
  100. package/packages/server/dist/services/commandService.js.map +1 -1
  101. package/packages/server/dist/services/fileWatcherService.d.ts +24 -0
  102. package/packages/server/dist/services/fileWatcherService.d.ts.map +1 -1
  103. package/packages/server/dist/services/fileWatcherService.js +192 -1
  104. package/packages/server/dist/services/fileWatcherService.js.map +1 -1
  105. package/packages/server/dist/services/harnessAgentService.d.ts +79 -0
  106. package/packages/server/dist/services/harnessAgentService.d.ts.map +1 -0
  107. package/packages/server/dist/services/harnessAgentService.js +933 -0
  108. package/packages/server/dist/services/harnessAgentService.js.map +1 -0
  109. package/packages/server/dist/services/harnessCommandService.d.ts +60 -0
  110. package/packages/server/dist/services/harnessCommandService.d.ts.map +1 -0
  111. package/packages/server/dist/services/harnessCommandService.js +853 -0
  112. package/packages/server/dist/services/harnessCommandService.js.map +1 -0
  113. package/packages/server/dist/services/harnessHookService.d.ts +55 -0
  114. package/packages/server/dist/services/harnessHookService.d.ts.map +1 -0
  115. package/packages/server/dist/services/harnessHookService.js +1060 -0
  116. package/packages/server/dist/services/harnessHookService.js.map +1 -0
  117. package/packages/server/dist/services/harnessLintService.d.ts +49 -0
  118. package/packages/server/dist/services/harnessLintService.d.ts.map +1 -0
  119. package/packages/server/dist/services/harnessLintService.js +628 -0
  120. package/packages/server/dist/services/harnessLintService.js.map +1 -0
  121. package/packages/server/dist/services/harnessMcpService.d.ts +77 -0
  122. package/packages/server/dist/services/harnessMcpService.d.ts.map +1 -0
  123. package/packages/server/dist/services/harnessMcpService.js +814 -0
  124. package/packages/server/dist/services/harnessMcpService.js.map +1 -0
  125. package/packages/server/dist/services/harnessPluginService.d.ts +66 -0
  126. package/packages/server/dist/services/harnessPluginService.d.ts.map +1 -0
  127. package/packages/server/dist/services/harnessPluginService.js +559 -0
  128. package/packages/server/dist/services/harnessPluginService.js.map +1 -0
  129. package/packages/server/dist/services/harnessService.d.ts +40 -0
  130. package/packages/server/dist/services/harnessService.d.ts.map +1 -0
  131. package/packages/server/dist/services/harnessService.js +222 -0
  132. package/packages/server/dist/services/harnessService.js.map +1 -0
  133. package/packages/server/dist/services/harnessShareScopeService.d.ts +31 -0
  134. package/packages/server/dist/services/harnessShareScopeService.d.ts.map +1 -0
  135. package/packages/server/dist/services/harnessShareScopeService.js +93 -0
  136. package/packages/server/dist/services/harnessShareScopeService.js.map +1 -0
  137. package/packages/server/dist/services/harnessSkillService.d.ts +70 -0
  138. package/packages/server/dist/services/harnessSkillService.d.ts.map +1 -0
  139. package/packages/server/dist/services/harnessSkillService.js +636 -0
  140. package/packages/server/dist/services/harnessSkillService.js.map +1 -0
  141. package/packages/server/dist/services/issueService.d.ts.map +1 -1
  142. package/packages/server/dist/services/issueService.js +2 -1
  143. package/packages/server/dist/services/issueService.js.map +1 -1
  144. package/packages/server/dist/services/manualSyncService.d.ts +19 -0
  145. package/packages/server/dist/services/manualSyncService.d.ts.map +1 -0
  146. package/packages/server/dist/services/manualSyncService.js +110 -0
  147. package/packages/server/dist/services/manualSyncService.js.map +1 -0
  148. package/packages/server/dist/services/queueService.d.ts.map +1 -1
  149. package/packages/server/dist/services/queueService.js +45 -2
  150. package/packages/server/dist/services/queueService.js.map +1 -1
  151. package/packages/server/dist/services/snippetService.d.ts +54 -0
  152. package/packages/server/dist/services/snippetService.d.ts.map +1 -0
  153. package/packages/server/dist/services/snippetService.js +371 -0
  154. package/packages/server/dist/services/snippetService.js.map +1 -0
  155. package/packages/server/dist/services/utils/applyYamlFrontmatterPatch.d.ts +46 -0
  156. package/packages/server/dist/services/utils/applyYamlFrontmatterPatch.d.ts.map +1 -0
  157. package/packages/server/dist/services/utils/applyYamlFrontmatterPatch.js +125 -0
  158. package/packages/server/dist/services/utils/applyYamlFrontmatterPatch.js.map +1 -0
  159. package/packages/server/dist/snippets/split-commit +9 -0
  160. package/packages/server/dist/utils/applySecretsPolicy.d.ts +53 -0
  161. package/packages/server/dist/utils/applySecretsPolicy.d.ts.map +1 -0
  162. package/packages/server/dist/utils/applySecretsPolicy.js +204 -0
  163. package/packages/server/dist/utils/applySecretsPolicy.js.map +1 -0
  164. package/packages/server/dist/utils/assertNoSecretOnShared.d.ts +40 -0
  165. package/packages/server/dist/utils/assertNoSecretOnShared.d.ts.map +1 -0
  166. package/packages/server/dist/utils/assertNoSecretOnShared.js +47 -0
  167. package/packages/server/dist/utils/assertNoSecretOnShared.js.map +1 -0
  168. package/packages/server/dist/utils/gitignoreFilter.d.ts +23 -0
  169. package/packages/server/dist/utils/gitignoreFilter.d.ts.map +1 -0
  170. package/packages/server/dist/utils/gitignoreFilter.js +42 -0
  171. package/packages/server/dist/utils/gitignoreFilter.js.map +1 -0
  172. package/packages/server/dist/utils/harnessBundleSchema.d.ts +105 -0
  173. package/packages/server/dist/utils/harnessBundleSchema.d.ts.map +1 -0
  174. package/packages/server/dist/utils/harnessBundleSchema.js +79 -0
  175. package/packages/server/dist/utils/harnessBundleSchema.js.map +1 -0
  176. package/packages/server/dist/utils/harnessPaths.d.ts +34 -0
  177. package/packages/server/dist/utils/harnessPaths.d.ts.map +1 -0
  178. package/packages/server/dist/utils/harnessPaths.js +124 -0
  179. package/packages/server/dist/utils/harnessPaths.js.map +1 -0
  180. package/packages/server/dist/utils/secretHeuristic.d.ts +72 -0
  181. package/packages/server/dist/utils/secretHeuristic.d.ts.map +1 -0
  182. package/packages/server/dist/utils/secretHeuristic.js +163 -0
  183. package/packages/server/dist/utils/secretHeuristic.js.map +1 -0
  184. package/packages/server/dist/utils/secretPlaceholderNamer.d.ts +41 -0
  185. package/packages/server/dist/utils/secretPlaceholderNamer.d.ts.map +1 -0
  186. package/packages/server/dist/utils/secretPlaceholderNamer.js +81 -0
  187. package/packages/server/dist/utils/secretPlaceholderNamer.js.map +1 -0
  188. package/packages/server/dist/utils/serverPathResolver.d.ts +29 -0
  189. package/packages/server/dist/utils/serverPathResolver.d.ts.map +1 -0
  190. package/packages/server/dist/utils/serverPathResolver.js +59 -0
  191. package/packages/server/dist/utils/serverPathResolver.js.map +1 -0
  192. package/packages/server/dist/utils/snippetPaths.d.ts +61 -0
  193. package/packages/server/dist/utils/snippetPaths.d.ts.map +1 -0
  194. package/packages/server/dist/utils/snippetPaths.js +123 -0
  195. package/packages/server/dist/utils/snippetPaths.js.map +1 -0
  196. package/packages/server/dist/utils/structuredEditor.d.ts +34 -0
  197. package/packages/server/dist/utils/structuredEditor.d.ts.map +1 -0
  198. package/packages/server/dist/utils/structuredEditor.js +111 -0
  199. package/packages/server/dist/utils/structuredEditor.js.map +1 -0
  200. package/packages/server/package.json +4 -1
  201. package/packages/server/resources/internals/INDEX.md +23 -0
  202. package/packages/server/resources/internals/harness-files.md +63 -0
  203. package/packages/server/resources/internals/image-storage.md +43 -0
  204. package/packages/server/resources/manual/01-getting-started.md +104 -0
  205. package/packages/server/resources/manual/02-chat.md +285 -0
  206. package/packages/server/resources/manual/03-sessions.md +48 -0
  207. package/packages/server/resources/manual/04-slash-commands-favorites.md +152 -0
  208. package/packages/server/resources/manual/05-projects.md +74 -0
  209. package/packages/server/resources/manual/06-file-explorer-editor.md +90 -0
  210. package/packages/server/resources/manual/07-git.md +94 -0
  211. package/packages/server/resources/manual/08-terminal.md +59 -0
  212. package/packages/server/resources/manual/09-queue-runner.md +262 -0
  213. package/packages/server/resources/manual/10-project-board.md +193 -0
  214. package/packages/server/resources/manual/11-bmad-method-integration.md +128 -0
  215. package/packages/server/resources/manual/12-harness-workbench.md +175 -0
  216. package/packages/server/resources/manual/13-settings.md +241 -0
  217. package/packages/server/resources/manual/14-keyboard-shortcuts.md +68 -0
  218. package/packages/server/resources/manual/15-environment-variables.md +28 -0
  219. package/packages/server/resources/manual/16-troubleshooting.md +110 -0
  220. package/packages/server/resources/manual/INDEX.md +60 -0
  221. package/packages/shared/dist/index.d.ts +3 -0
  222. package/packages/shared/dist/index.d.ts.map +1 -1
  223. package/packages/shared/dist/index.js +6 -0
  224. package/packages/shared/dist/index.js.map +1 -1
  225. package/packages/shared/dist/types/command.d.ts +3 -3
  226. package/packages/shared/dist/types/command.d.ts.map +1 -1
  227. package/packages/shared/dist/types/harness.d.ts +1211 -0
  228. package/packages/shared/dist/types/harness.d.ts.map +1 -0
  229. package/packages/shared/dist/types/harness.js +107 -0
  230. package/packages/shared/dist/types/harness.js.map +1 -0
  231. package/packages/shared/dist/types/harnessBundle.d.ts +170 -0
  232. package/packages/shared/dist/types/harnessBundle.d.ts.map +1 -0
  233. package/packages/shared/dist/types/harnessBundle.js +18 -0
  234. package/packages/shared/dist/types/harnessBundle.js.map +1 -0
  235. package/packages/shared/dist/types/preferences.d.ts +2 -0
  236. package/packages/shared/dist/types/preferences.d.ts.map +1 -1
  237. package/packages/shared/dist/types/preferences.js.map +1 -1
  238. package/packages/shared/dist/types/queue.d.ts +9 -0
  239. package/packages/shared/dist/types/queue.d.ts.map +1 -1
  240. package/packages/shared/dist/types/websocket.d.ts +10 -0
  241. package/packages/shared/dist/types/websocket.d.ts.map +1 -1
  242. package/packages/shared/dist/utils/markdownSections.d.ts +50 -0
  243. package/packages/shared/dist/utils/markdownSections.d.ts.map +1 -0
  244. package/packages/shared/dist/utils/markdownSections.js +111 -0
  245. package/packages/shared/dist/utils/markdownSections.js.map +1 -0
  246. package/packages/shared/dist/utils/queueParser.d.ts.map +1 -1
  247. package/packages/shared/dist/utils/queueParser.js +104 -0
  248. package/packages/shared/dist/utils/queueParser.js.map +1 -1
  249. package/scripts/build-manual-shards.mjs +100 -0
  250. package/packages/client/dist/assets/index-6jREnVYd.js +0 -2
  251. package/packages/client/dist/assets/index-BFF0iqyW.css +0 -32
  252. package/packages/client/dist/assets/index-BcI4y-fU.js +0 -1454
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Story 30.3 (Task 2.2): apply the three `secretsPolicy` modes to a payload
3
+ * before it is written into the bundle.
4
+ *
5
+ * Two operating shapes, mirroring `detectSecretsInValue` / `detectSecretsInText`:
6
+ *
7
+ * 1. `applyPolicyToValue` walks a JSON-like value (mcp config, settings.json
8
+ * hooks block). For `excluded` the matched leaf is deleted from its
9
+ * parent; for `placeholder` it is rewritten as `${ENV_REF_NAME}` using
10
+ * `secretPlaceholderNamer`; for `included-explicit` the value is left
11
+ * untouched.
12
+ *
13
+ * 2. `applyPolicyToText` walks line-oriented text (CLAUDE.md, agent body,
14
+ * command body). For `excluded` the offending line is replaced with the
15
+ * sentinel `<< SECRET REMOVED >>` so line numbers stay stable; for
16
+ * `placeholder` every secret substring on that line is rewritten as
17
+ * `${ENV_REF_NAME}`; for `included-explicit` the text is unchanged.
18
+ *
19
+ * Both return per-call counters that the caller aggregates into the
20
+ * `ImportApplySummary` (well, the export equivalent — same idea: surface to
21
+ * the user how many secrets were affected).
22
+ */
23
+ import type { BundleItemDomain, SecretsPolicy } from '@hammoc/shared';
24
+ export declare const SECRET_REMOVED_TEXT_PLACEHOLDER = "<< SECRET REMOVED >>";
25
+ export interface ApplyPolicyValueInput {
26
+ policy: SecretsPolicy;
27
+ domain: BundleItemDomain;
28
+ cardName: string;
29
+ hookEvent?: string;
30
+ /** Root-relative path prefix for matched dot-paths (e.g. `mcpServers.context7`). */
31
+ pathPrefix?: string[];
32
+ value: unknown;
33
+ }
34
+ export interface ApplyPolicyValueResult {
35
+ value: unknown;
36
+ removedCount: number;
37
+ replacedCount: number;
38
+ }
39
+ export interface ApplyPolicyTextInput {
40
+ policy: SecretsPolicy;
41
+ domain: BundleItemDomain;
42
+ cardName: string;
43
+ hookEvent?: string;
44
+ text: string;
45
+ }
46
+ export interface ApplyPolicyTextResult {
47
+ text: string;
48
+ removedCount: number;
49
+ replacedCount: number;
50
+ }
51
+ export declare function applyPolicyToText(input: ApplyPolicyTextInput): ApplyPolicyTextResult;
52
+ export declare function applyPolicyToValue(input: ApplyPolicyValueInput): ApplyPolicyValueResult;
53
+ //# sourceMappingURL=applySecretsPolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applySecretsPolicy.d.ts","sourceRoot":"","sources":["../../src/utils/applySecretsPolicy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AASH,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEtE,eAAO,MAAM,+BAA+B,yBAAyB,CAAC;AAEtE,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAwFD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CAsCpF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,qBAAqB,GAAG,sBAAsB,CA4DvF"}
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Story 30.3 (Task 2.2): apply the three `secretsPolicy` modes to a payload
3
+ * before it is written into the bundle.
4
+ *
5
+ * Two operating shapes, mirroring `detectSecretsInValue` / `detectSecretsInText`:
6
+ *
7
+ * 1. `applyPolicyToValue` walks a JSON-like value (mcp config, settings.json
8
+ * hooks block). For `excluded` the matched leaf is deleted from its
9
+ * parent; for `placeholder` it is rewritten as `${ENV_REF_NAME}` using
10
+ * `secretPlaceholderNamer`; for `included-explicit` the value is left
11
+ * untouched.
12
+ *
13
+ * 2. `applyPolicyToText` walks line-oriented text (CLAUDE.md, agent body,
14
+ * command body). For `excluded` the offending line is replaced with the
15
+ * sentinel `<< SECRET REMOVED >>` so line numbers stay stable; for
16
+ * `placeholder` every secret substring on that line is rewritten as
17
+ * `${ENV_REF_NAME}`; for `included-explicit` the text is unchanged.
18
+ *
19
+ * Both return per-call counters that the caller aggregates into the
20
+ * `ImportApplySummary` (well, the export equivalent — same idea: surface to
21
+ * the user how many secrets were affected).
22
+ */
23
+ import { ENV_REF_RE, SECRET_PATTERNS, shannonEntropy, } from './secretHeuristic.js';
24
+ import { namePlaceholder } from './secretPlaceholderNamer.js';
25
+ export const SECRET_REMOVED_TEXT_PLACEHOLDER = '<< SECRET REMOVED >>';
26
+ const BASE64_NON_ALPHA_RE = /[0-9+/=]/;
27
+ function matchPasses(s, pat) {
28
+ if (pat.minEntropy === undefined)
29
+ return true;
30
+ return shannonEntropy(s) >= pat.minEntropy && BASE64_NON_ALPHA_RE.test(s);
31
+ }
32
+ /** Iterate every secret substring inside `text`. */
33
+ function* iterateSecretMatches(text) {
34
+ for (const pat of SECRET_PATTERNS) {
35
+ const re = pat.re.global ? pat.re : new RegExp(pat.re.source, pat.re.flags + 'g');
36
+ re.lastIndex = 0;
37
+ let m;
38
+ while ((m = re.exec(text)) !== null) {
39
+ const raw = m[0];
40
+ if (matchPasses(raw, pat)) {
41
+ yield { start: m.index, end: m.index + raw.length, raw, pat };
42
+ }
43
+ if (m.index === re.lastIndex)
44
+ re.lastIndex += 1;
45
+ }
46
+ }
47
+ }
48
+ function stripEnvRefs(text) {
49
+ return text.replace(ENV_REF_RE, '');
50
+ }
51
+ function containsSecret(text) {
52
+ const stripped = stripEnvRefs(text);
53
+ for (const _ of iterateSecretMatches(stripped)) {
54
+ return true;
55
+ }
56
+ return false;
57
+ }
58
+ /**
59
+ * Replace every secret substring inside `text` with the ENV-ref produced by
60
+ * the namer. Matches on the env-stripped clone first so existing `${FOO}`
61
+ * indirection isn't double-replaced.
62
+ */
63
+ function replaceSecretsInText(text, makeName) {
64
+ // We need the original text positions but the secret-detection regex must
65
+ // not double-count existing ENV refs. Strategy: collect matches against the
66
+ // env-stripped clone, then translate offsets back to the original by
67
+ // walking through both strings in parallel.
68
+ const stripped = stripEnvRefs(text);
69
+ if (stripped === text) {
70
+ return rebuildText(text, makeName);
71
+ }
72
+ // When there were ENV refs, the safest fallback is to scan the original text
73
+ // directly. Existing `${FOO}` snippets won't match `SECRET_PATTERNS` (none of
74
+ // the regexes accept `{` or `}` in the middle), so direct scanning is fine.
75
+ return rebuildText(text, makeName);
76
+ }
77
+ function rebuildText(text, makeName) {
78
+ const matches = [];
79
+ for (const m of iterateSecretMatches(text)) {
80
+ matches.push({ start: m.start, end: m.end, raw: m.raw });
81
+ }
82
+ if (matches.length === 0)
83
+ return { text, replacedCount: 0 };
84
+ // Sort by start ascending, drop overlaps (keep first).
85
+ matches.sort((a, b) => a.start - b.start);
86
+ const nonOverlapping = [];
87
+ let lastEnd = -1;
88
+ for (const m of matches) {
89
+ if (m.start >= lastEnd) {
90
+ nonOverlapping.push(m);
91
+ lastEnd = m.end;
92
+ }
93
+ }
94
+ let out = '';
95
+ let cursor = 0;
96
+ let replaced = 0;
97
+ for (const m of nonOverlapping) {
98
+ out += text.slice(cursor, m.start);
99
+ out += '${' + makeName(m.raw, replaced) + '}';
100
+ cursor = m.end;
101
+ replaced += 1;
102
+ }
103
+ out += text.slice(cursor);
104
+ return { text: out, replacedCount: replaced };
105
+ }
106
+ export function applyPolicyToText(input) {
107
+ const { policy, domain, cardName, hookEvent, text } = input;
108
+ if (policy === 'included-explicit') {
109
+ return { text, removedCount: 0, replacedCount: 0 };
110
+ }
111
+ if (!text) {
112
+ return { text, removedCount: 0, replacedCount: 0 };
113
+ }
114
+ if (policy === 'excluded') {
115
+ // Replace each offending line with the sentinel so line numbers stay
116
+ // stable for downstream tools that index by line.
117
+ const lines = text.split(/\r?\n/);
118
+ let removed = 0;
119
+ for (let i = 0; i < lines.length; i += 1) {
120
+ if (containsSecret(lines[i])) {
121
+ lines[i] = SECRET_REMOVED_TEXT_PLACEHOLDER;
122
+ removed += 1;
123
+ }
124
+ }
125
+ return { text: lines.join('\n'), removedCount: removed, replacedCount: 0 };
126
+ }
127
+ // placeholder
128
+ const seenCounts = new Map();
129
+ const result = replaceSecretsInText(text, (_raw, idx) => {
130
+ const base = {
131
+ domain,
132
+ fieldPath: `body:${idx}`,
133
+ cardName,
134
+ hookEvent,
135
+ };
136
+ const baseName = namePlaceholder(base);
137
+ const count = seenCounts.get(baseName) ?? 0;
138
+ seenCounts.set(baseName, count + 1);
139
+ return count === 0 ? baseName : `${baseName}_${count + 1}`;
140
+ });
141
+ return { text: result.text, removedCount: 0, replacedCount: result.replacedCount };
142
+ }
143
+ export function applyPolicyToValue(input) {
144
+ const { policy, domain, cardName, hookEvent, value } = input;
145
+ if (policy === 'included-explicit') {
146
+ return { value, removedCount: 0, replacedCount: 0 };
147
+ }
148
+ const pathPrefix = input.pathPrefix ?? [];
149
+ let removedCount = 0;
150
+ let replacedCount = 0;
151
+ const seenCounts = new Map();
152
+ const transform = (v, p) => {
153
+ if (typeof v === 'string') {
154
+ const stripped = stripEnvRefs(v);
155
+ if (!stripped || !containsSecret(stripped)) {
156
+ return v;
157
+ }
158
+ if (policy === 'excluded') {
159
+ removedCount += 1;
160
+ // Return a sentinel that the caller (e.g. the mcp/hook config walker)
161
+ // will interpret as "delete this leaf" — strings, by themselves, can't
162
+ // disappear from their parent. We use the literal undefined sentinel
163
+ // and let the array/object handlers filter.
164
+ return SECRET_REMOVED_SENTINEL;
165
+ }
166
+ // placeholder
167
+ const baseName = namePlaceholder({
168
+ domain,
169
+ cardName,
170
+ hookEvent,
171
+ fieldPath: p.join('.'),
172
+ });
173
+ const count = seenCounts.get(baseName) ?? 0;
174
+ seenCounts.set(baseName, count + 1);
175
+ const name = count === 0 ? baseName : `${baseName}_${count + 1}`;
176
+ replacedCount += 1;
177
+ return '${' + name + '}';
178
+ }
179
+ if (Array.isArray(v)) {
180
+ return v
181
+ .map((item, i) => transform(item, [...p, String(i)]))
182
+ .filter((item) => item !== SECRET_REMOVED_SENTINEL);
183
+ }
184
+ if (v && typeof v === 'object') {
185
+ const out = {};
186
+ for (const [k, child] of Object.entries(v)) {
187
+ const next = transform(child, [...p, k]);
188
+ if (next !== SECRET_REMOVED_SENTINEL)
189
+ out[k] = next;
190
+ }
191
+ return out;
192
+ }
193
+ return v;
194
+ };
195
+ const result = transform(value, pathPrefix);
196
+ // Top-level scalar might be the sentinel — flatten to undefined for callers.
197
+ return {
198
+ value: result === SECRET_REMOVED_SENTINEL ? undefined : result,
199
+ removedCount,
200
+ replacedCount,
201
+ };
202
+ }
203
+ const SECRET_REMOVED_SENTINEL = Symbol('secret-removed');
204
+ //# sourceMappingURL=applySecretsPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applySecretsPolicy.js","sourceRoot":"","sources":["../../src/utils/applySecretsPolicy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Story 30.1 (Task 6.2): server-side guard that escalates a secret detection
3
+ * to a hard `HARNESS_SECRET_ON_SHARED` block when the target file is tracked
4
+ * by git (`shared` verdict from `harnessShareScopeService`).
5
+ *
6
+ * Sub-spike 6.2.0 decision: option (b) — distributed at the four domain
7
+ * services (agent / command / hook / mcp). Rationale:
8
+ * - `harnessService.write` IS a single common call site, so option (a)
9
+ * would also work for the raw write path. But AC4.d carves out
10
+ * domain-specific scopes (settings.json values, hook command/prompt
11
+ * fields, agent frontmatter) that the single point cannot meaningfully
12
+ * filter without re-parsing the file. Distributing the helper keeps each
13
+ * domain's existing per-field detection in place and just adds the
14
+ * "shared → block" escalation on top.
15
+ *
16
+ * The helper performs the cheap path-classification round trip
17
+ * (`harnessShareScopeService.evaluate` is a single `.gitignore` load + one
18
+ * `isIgnored()` call). User-scope writes are no-ops (no `.gitignore`
19
+ * involved).
20
+ */
21
+ import { type HarnessScope } from '@hammoc/shared';
22
+ export interface AssertNoSecretOnSharedInput {
23
+ scope: HarnessScope;
24
+ projectSlug?: string;
25
+ /** Project-relative POSIX path of the file being written (e.g. `.claude/agents/dev.md`). */
26
+ relativePath: string;
27
+ /**
28
+ * Pre-computed detection result from the calling service. The helper does
29
+ * not re-run secret detection because each service knows which fields are
30
+ * in-scope per AC4.d.
31
+ */
32
+ secretDetected: boolean;
33
+ /** Optional secret locations (line numbers / dot-paths) to surface in the error. */
34
+ detectedAt?: {
35
+ lines?: number[];
36
+ paths?: string[];
37
+ };
38
+ }
39
+ export declare function assertNoSecretOnShared(input: AssertNoSecretOnSharedInput): Promise<void>;
40
+ //# sourceMappingURL=assertNoSecretOnShared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertNoSecretOnShared.d.ts","sourceRoot":"","sources":["../../src/utils/assertNoSecretOnShared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGnE,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,YAAY,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,cAAc,EAAE,OAAO,CAAC;IACxB,oFAAoF;IACpF,UAAU,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACrD;AAED,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAAC,IAAI,CAAC,CAsBf"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Story 30.1 (Task 6.2): server-side guard that escalates a secret detection
3
+ * to a hard `HARNESS_SECRET_ON_SHARED` block when the target file is tracked
4
+ * by git (`shared` verdict from `harnessShareScopeService`).
5
+ *
6
+ * Sub-spike 6.2.0 decision: option (b) — distributed at the four domain
7
+ * services (agent / command / hook / mcp). Rationale:
8
+ * - `harnessService.write` IS a single common call site, so option (a)
9
+ * would also work for the raw write path. But AC4.d carves out
10
+ * domain-specific scopes (settings.json values, hook command/prompt
11
+ * fields, agent frontmatter) that the single point cannot meaningfully
12
+ * filter without re-parsing the file. Distributing the helper keeps each
13
+ * domain's existing per-field detection in place and just adds the
14
+ * "shared → block" escalation on top.
15
+ *
16
+ * The helper performs the cheap path-classification round trip
17
+ * (`harnessShareScopeService.evaluate` is a single `.gitignore` load + one
18
+ * `isIgnored()` call). User-scope writes are no-ops (no `.gitignore`
19
+ * involved).
20
+ */
21
+ import { HARNESS_ERRORS } from '@hammoc/shared';
22
+ import { harnessShareScopeService } from '../services/harnessShareScopeService.js';
23
+ export async function assertNoSecretOnShared(input) {
24
+ if (!input.secretDetected)
25
+ return;
26
+ // User scope (`~/.claude`) is not git-tracked — `.gitignore` does not apply.
27
+ if (input.scope !== 'project' || !input.projectSlug)
28
+ return;
29
+ const result = await harnessShareScopeService.evaluate({
30
+ projectSlug: input.projectSlug,
31
+ relativePaths: [input.relativePath],
32
+ });
33
+ const verdict = result.cards[input.relativePath];
34
+ // Only `shared` triggers the hard block. `local` / `fullyIgnored` keep
35
+ // the existing per-service acknowledgement flow.
36
+ if (verdict !== 'shared')
37
+ return;
38
+ const err = new Error('plaintext secret detected on a git-tracked file');
39
+ err.code = HARNESS_ERRORS.HARNESS_SECRET_ON_SHARED.code;
40
+ err.relativePath = input.relativePath;
41
+ if (input.detectedAt?.lines)
42
+ err.lines = input.detectedAt.lines;
43
+ if (input.detectedAt?.paths)
44
+ err.paths = input.detectedAt.paths;
45
+ throw err;
46
+ }
47
+ //# sourceMappingURL=assertNoSecretOnShared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertNoSecretOnShared.js","sourceRoot":"","sources":["../../src/utils/assertNoSecretOnShared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,cAAc,EAAqB,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAC;AAiBnF,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,KAAkC;IAElC,IAAI,CAAC,KAAK,CAAC,cAAc;QAAE,OAAO;IAClC,6EAA6E;IAC7E,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,WAAW;QAAE,OAAO;IAE5D,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC,QAAQ,CAAC;QACrD,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,aAAa,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC;KACpC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAEjD,uEAAuE;IACvE,iDAAiD;IACjD,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO;IAEjC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,iDAAiD,CACN,CAAC;IAClE,GAAG,CAAC,IAAI,GAAG,cAAc,CAAC,wBAAwB,CAAC,IAAI,CAAC;IACxD,GAAG,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;IACtC,IAAI,KAAK,CAAC,UAAU,EAAE,KAAK;QAAE,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;IAChE,IAAI,KAAK,CAAC,UAAU,EAAE,KAAK;QAAE,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;IAChE,MAAM,GAAG,CAAC;AACZ,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Story 28.0.5 (Task 5): thin wrapper around `ignore` (kaelzhang/node-ignore).
3
+ *
4
+ * Originally introduced as preemptive infrastructure under the placeholder
5
+ * label "Epic 30 Story 10" (the pre-BMad-renumbering forward reference);
6
+ * Story 30.1 fills the call-sites (`harnessShareScopeService` + the
7
+ * client-side `ShareBadge` / `ModeBanner`) by consuming `loadGitignore()` +
8
+ * `isIgnored()` to drive the "shared vs. local vs. fully-ignored" badges on
9
+ * the harness workbench tree.
10
+ */
11
+ import { type Ignore } from 'ignore';
12
+ /**
13
+ * Load `<rootPath>/.gitignore` into an `Ignore` matcher. Missing files yield
14
+ * a matcher that never excludes anything (so callers can treat "no
15
+ * .gitignore" as "nothing is ignored" without a separate branch).
16
+ */
17
+ export declare function loadGitignore(rootPath: string): Promise<Ignore>;
18
+ /**
19
+ * Test a relative path against the matcher. Input paths are normalized to
20
+ * POSIX separators as required by `ignore`'s contract.
21
+ */
22
+ export declare function isIgnored(matcher: Ignore, relativePath: string): boolean;
23
+ //# sourceMappingURL=gitignoreFilter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitignoreFilter.d.ts","sourceRoot":"","sources":["../../src/utils/gitignoreFilter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAsB,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEpD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAarE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAGxE"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Story 28.0.5 (Task 5): thin wrapper around `ignore` (kaelzhang/node-ignore).
3
+ *
4
+ * Originally introduced as preemptive infrastructure under the placeholder
5
+ * label "Epic 30 Story 10" (the pre-BMad-renumbering forward reference);
6
+ * Story 30.1 fills the call-sites (`harnessShareScopeService` + the
7
+ * client-side `ShareBadge` / `ModeBanner`) by consuming `loadGitignore()` +
8
+ * `isIgnored()` to drive the "shared vs. local vs. fully-ignored" badges on
9
+ * the harness workbench tree.
10
+ */
11
+ import fs from 'fs/promises';
12
+ import path from 'path';
13
+ import ignoreFactory from 'ignore';
14
+ /**
15
+ * Load `<rootPath>/.gitignore` into an `Ignore` matcher. Missing files yield
16
+ * a matcher that never excludes anything (so callers can treat "no
17
+ * .gitignore" as "nothing is ignored" without a separate branch).
18
+ */
19
+ export async function loadGitignore(rootPath) {
20
+ const matcher = ignoreFactory();
21
+ const gitignorePath = path.join(rootPath, '.gitignore');
22
+ try {
23
+ const content = await fs.readFile(gitignorePath, 'utf-8');
24
+ matcher.add(content);
25
+ }
26
+ catch (error) {
27
+ if (error.code !== 'ENOENT') {
28
+ throw error;
29
+ }
30
+ // No .gitignore — return an empty matcher.
31
+ }
32
+ return matcher;
33
+ }
34
+ /**
35
+ * Test a relative path against the matcher. Input paths are normalized to
36
+ * POSIX separators as required by `ignore`'s contract.
37
+ */
38
+ export function isIgnored(matcher, relativePath) {
39
+ const posix = relativePath.replace(/\\/g, '/');
40
+ return matcher.ignores(posix);
41
+ }
42
+ //# sourceMappingURL=gitignoreFilter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitignoreFilter.js","sourceRoot":"","sources":["../../src/utils/gitignoreFilter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,aAA8B,MAAM,QAAQ,CAAC;AAEpD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB;IAClD,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAChC,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACxD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,KAAK,CAAC;QACd,CAAC;QACD,2CAA2C;IAC7C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,YAAoB;IAC7D,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC/C,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Story 30.3 (Task 4.2): Zod runtime validation of `manifest.json` inside the
3
+ * harness export/import bundle. Lives on the server because zod is a
4
+ * server-only dep — the shared package exposes only the TypeScript surface
5
+ * (`packages/shared/src/types/harnessBundle.ts`).
6
+ *
7
+ * Two boundaries call this schema:
8
+ * - the bundle service when unpacking an import ZIP (AC5.c "malformed
9
+ * manifest" branch)
10
+ * - the controller when accepting an export request body (AC1, AC2, AC5)
11
+ *
12
+ * Both reuse the discriminator/value sets exported from `@hammoc/shared` so
13
+ * the schema and types stay in lockstep.
14
+ */
15
+ import { z } from 'zod';
16
+ /**
17
+ * Strict manifest schema — `bundleVersion` is locked to the literal 1 so
18
+ * future-version bundles fall through to the AC5.a "futureBundle" branch
19
+ * before this schema is even consulted (the import service inspects the raw
20
+ * JSON's version field first, then runs full Zod validation).
21
+ */
22
+ export declare const bundleManifestSchema: z.ZodObject<{
23
+ bundleVersion: z.ZodLiteral<1>;
24
+ hammocVersion: z.ZodString;
25
+ claudeCodeSpecVersion: z.ZodUnion<readonly [z.ZodString, z.ZodNull]>;
26
+ createdAt: z.ZodString;
27
+ sourceProjectSlug: z.ZodString;
28
+ includes: z.ZodArray<z.ZodEnum<{
29
+ agents: "agents";
30
+ hooks: "hooks";
31
+ commands: "commands";
32
+ skills: "skills";
33
+ mcp: "mcp";
34
+ "claude-md": "claude-md";
35
+ bmad: "bmad";
36
+ }>>;
37
+ secretsPolicy: z.ZodEnum<{
38
+ excluded: "excluded";
39
+ placeholder: "placeholder";
40
+ "included-explicit": "included-explicit";
41
+ }>;
42
+ pluginDependencies: z.ZodArray<z.ZodObject<{
43
+ name: z.ZodString;
44
+ marketplace: z.ZodString;
45
+ version: z.ZodOptional<z.ZodString>;
46
+ }, z.core.$strip>>;
47
+ items: z.ZodArray<z.ZodObject<{
48
+ domain: z.ZodEnum<{
49
+ agent: "agent";
50
+ command: "command";
51
+ skill: "skill";
52
+ mcp: "mcp";
53
+ hook: "hook";
54
+ "claude-md": "claude-md";
55
+ bmad: "bmad";
56
+ }>;
57
+ identity: z.ZodString;
58
+ relativePath: z.ZodString;
59
+ sourceShareScope: z.ZodEnum<{
60
+ local: "local";
61
+ shared: "shared";
62
+ fullyIgnored: "fullyIgnored";
63
+ }>;
64
+ }, z.core.$strip>>;
65
+ }, z.core.$strip>;
66
+ export type BundleManifestParsed = z.infer<typeof bundleManifestSchema>;
67
+ /**
68
+ * Loose schema used for "is this even a manifest?" detection before the
69
+ * strict schema runs. Lets the import service distinguish "totally garbage
70
+ * JSON" (no bundleVersion field at all) from "future bundle" (bundleVersion
71
+ * is a number outside our supported range).
72
+ */
73
+ export declare const loosenedManifestSchema: z.ZodObject<{
74
+ bundleVersion: z.ZodOptional<z.ZodNumber>;
75
+ }, z.core.$strip>;
76
+ export declare const exportBundleRequestSchema: z.ZodObject<{
77
+ projectSlug: z.ZodString;
78
+ includes: z.ZodArray<z.ZodEnum<{
79
+ agents: "agents";
80
+ hooks: "hooks";
81
+ commands: "commands";
82
+ skills: "skills";
83
+ mcp: "mcp";
84
+ "claude-md": "claude-md";
85
+ bmad: "bmad";
86
+ }>>;
87
+ secretsPolicy: z.ZodEnum<{
88
+ excluded: "excluded";
89
+ placeholder: "placeholder";
90
+ "included-explicit": "included-explicit";
91
+ }>;
92
+ }, z.core.$strip>;
93
+ export declare const importApplyRequestSchema: z.ZodObject<{
94
+ bundleToken: z.ZodString;
95
+ itemActions: z.ZodRecord<z.ZodString, z.ZodEnum<{
96
+ rename: "rename";
97
+ overwrite: "overwrite";
98
+ skip: "skip";
99
+ appendSection: "appendSection";
100
+ }>>;
101
+ }, z.core.$strip>;
102
+ export declare const pluginDepsQuerySchema: z.ZodObject<{
103
+ projectSlug: z.ZodString;
104
+ }, z.core.$strip>;
105
+ //# sourceMappingURL=harnessBundleSchema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harnessBundleSchema.d.ts","sourceRoot":"","sources":["../../src/utils/harnessBundleSchema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA0CxB;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAU/B,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB;;iBAEjC,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;iBAIpC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;iBAGnC,CAAC;AAEH,eAAO,MAAM,qBAAqB;;iBAEhC,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Story 30.3 (Task 4.2): Zod runtime validation of `manifest.json` inside the
3
+ * harness export/import bundle. Lives on the server because zod is a
4
+ * server-only dep — the shared package exposes only the TypeScript surface
5
+ * (`packages/shared/src/types/harnessBundle.ts`).
6
+ *
7
+ * Two boundaries call this schema:
8
+ * - the bundle service when unpacking an import ZIP (AC5.c "malformed
9
+ * manifest" branch)
10
+ * - the controller when accepting an export request body (AC1, AC2, AC5)
11
+ *
12
+ * Both reuse the discriminator/value sets exported from `@hammoc/shared` so
13
+ * the schema and types stay in lockstep.
14
+ */
15
+ import { z } from 'zod';
16
+ import { BUNDLE_SECTIONS, HARNESS_BUNDLE_VERSION, } from '@hammoc/shared';
17
+ const sectionSchema = z.enum(BUNDLE_SECTIONS);
18
+ const secretsPolicySchema = z.enum(['excluded', 'placeholder', 'included-explicit']);
19
+ const itemDomainSchema = z.enum([
20
+ 'claude-md',
21
+ 'skill',
22
+ 'mcp',
23
+ 'hook',
24
+ 'command',
25
+ 'agent',
26
+ 'bmad',
27
+ ]);
28
+ const sourceShareScopeSchema = z.enum(['shared', 'local', 'fullyIgnored']);
29
+ const itemActionSchema = z.enum(['overwrite', 'skip', 'rename', 'appendSection']);
30
+ const pluginRefSchema = z.object({
31
+ name: z.string().min(1),
32
+ marketplace: z.string().min(1),
33
+ version: z.string().optional(),
34
+ });
35
+ const bundleItemSchema = z.object({
36
+ domain: itemDomainSchema,
37
+ identity: z.string().min(1),
38
+ relativePath: z.string().min(1),
39
+ sourceShareScope: sourceShareScopeSchema,
40
+ });
41
+ /**
42
+ * Strict manifest schema — `bundleVersion` is locked to the literal 1 so
43
+ * future-version bundles fall through to the AC5.a "futureBundle" branch
44
+ * before this schema is even consulted (the import service inspects the raw
45
+ * JSON's version field first, then runs full Zod validation).
46
+ */
47
+ export const bundleManifestSchema = z.object({
48
+ bundleVersion: z.literal(HARNESS_BUNDLE_VERSION),
49
+ hammocVersion: z.string().min(1),
50
+ claudeCodeSpecVersion: z.union([z.string().min(1), z.null()]),
51
+ createdAt: z.string().min(1),
52
+ sourceProjectSlug: z.string().min(1),
53
+ includes: z.array(sectionSchema),
54
+ secretsPolicy: secretsPolicySchema,
55
+ pluginDependencies: z.array(pluginRefSchema),
56
+ items: z.array(bundleItemSchema),
57
+ });
58
+ /**
59
+ * Loose schema used for "is this even a manifest?" detection before the
60
+ * strict schema runs. Lets the import service distinguish "totally garbage
61
+ * JSON" (no bundleVersion field at all) from "future bundle" (bundleVersion
62
+ * is a number outside our supported range).
63
+ */
64
+ export const loosenedManifestSchema = z.object({
65
+ bundleVersion: z.number().int().optional(),
66
+ });
67
+ export const exportBundleRequestSchema = z.object({
68
+ projectSlug: z.string().min(1),
69
+ includes: z.array(sectionSchema).min(1, 'at least one section is required'),
70
+ secretsPolicy: secretsPolicySchema,
71
+ });
72
+ export const importApplyRequestSchema = z.object({
73
+ bundleToken: z.string().min(1),
74
+ itemActions: z.record(z.string(), itemActionSchema),
75
+ });
76
+ export const pluginDepsQuerySchema = z.object({
77
+ projectSlug: z.string().min(1),
78
+ });
79
+ //# sourceMappingURL=harnessBundleSchema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harnessBundleSchema.js","sourceRoot":"","sources":["../../src/utils/harnessBundleSchema.ts"],"names":[],"mappings":"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"}