@wrongstack/core 0.313.0 → 0.316.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. package/dist/chronicle/index.js +84 -6391
  2. package/dist/chronicle/legacy-journal-import.d.ts +0 -6
  3. package/dist/chronicle/metrics-ingest.d.ts +14 -0
  4. package/dist/chronicle/metrics-schema.d.ts +10 -1
  5. package/dist/chronicle/metrics-store.d.ts +20 -2
  6. package/dist/chronicle/project-server.js +98 -4874
  7. package/dist/chronicle/sink.d.ts +13 -0
  8. package/dist/chronicle/sqlite-journal.d.ts +20 -2
  9. package/dist/chunk-25LSLC3G.js +334 -0
  10. package/dist/chunk-27QIURLN.js +1073 -0
  11. package/dist/chunk-2FK4WTFF.js +207 -0
  12. package/dist/chunk-2YU4WVBW.js +134 -0
  13. package/dist/chunk-3AGWVSS7.js +4608 -0
  14. package/dist/chunk-3BDV7RL3.js +211 -0
  15. package/dist/chunk-3ECENVHL.js +325 -0
  16. package/dist/chunk-3XPVB7BA.js +135 -0
  17. package/dist/chunk-45WI72ZB.js +16884 -0
  18. package/dist/chunk-4BMVPOHO.js +3748 -0
  19. package/dist/chunk-4I7HGVVA.js +363 -0
  20. package/dist/chunk-4LCZVJVF.js +317 -0
  21. package/dist/chunk-4SJNS7OB.js +217 -0
  22. package/dist/chunk-4VWO3ZXL.js +342 -0
  23. package/dist/chunk-57GEWK5X.js +26 -0
  24. package/dist/chunk-5BMIE7QG.js +46 -0
  25. package/dist/chunk-5S437PRC.js +50 -0
  26. package/dist/chunk-5XDUGTKN.js +511 -0
  27. package/dist/chunk-5YPSXQXM.js +1443 -0
  28. package/dist/chunk-6FHWXLPT.js +10 -0
  29. package/dist/chunk-6H5GEOET.js +2406 -0
  30. package/dist/chunk-6NWEVFEL.js +151 -0
  31. package/dist/chunk-AYW5YINX.js +58 -0
  32. package/dist/chunk-B4AMLZPB.js +9 -0
  33. package/dist/chunk-B7F4WVP4.js +65 -0
  34. package/dist/chunk-BJHVULHO.js +55 -0
  35. package/dist/chunk-BPBKKBUK.js +2085 -0
  36. package/dist/chunk-BYD345OX.js +589 -0
  37. package/dist/chunk-C27KDLOX.js +279 -0
  38. package/dist/chunk-CU546ESW.js +597 -0
  39. package/dist/chunk-DLHHXUAM.js +172 -0
  40. package/dist/chunk-DOTHQSJ2.js +429 -0
  41. package/dist/chunk-DYLPMV4Q.js +711 -0
  42. package/dist/chunk-EODDVJBM.js +82 -0
  43. package/dist/chunk-F3JWNST7.js +361 -0
  44. package/dist/chunk-FC2ZGRF3.js +140 -0
  45. package/dist/chunk-FCBTO76Z.js +5786 -0
  46. package/dist/chunk-FHZVFYSL.js +396 -0
  47. package/dist/chunk-FNXVT7HF.js +52 -0
  48. package/dist/chunk-FWNLEZYG.js +259 -0
  49. package/dist/chunk-FXQLIX3K.js +211 -0
  50. package/dist/chunk-G5S3S5ZN.js +38 -0
  51. package/dist/chunk-GDQ7CZRQ.js +116 -0
  52. package/dist/chunk-GJJGJB2R.js +1374 -0
  53. package/dist/chunk-GTCU6DZ3.js +1 -0
  54. package/dist/chunk-HA4ZYA6T.js +178 -0
  55. package/dist/chunk-HI3JGZR2.js +188 -0
  56. package/dist/chunk-HMLIGAU7.js +395 -0
  57. package/dist/chunk-HXKZ7OBQ.js +303 -0
  58. package/dist/chunk-I7DALG7J.js +292 -0
  59. package/dist/chunk-IRUTEHCE.js +960 -0
  60. package/dist/chunk-IYFBFX34.js +86 -0
  61. package/dist/chunk-J2WRWR37.js +1104 -0
  62. package/dist/chunk-JFPJ6LLQ.js +129 -0
  63. package/dist/chunk-JMULFFLN.js +9 -0
  64. package/dist/chunk-JO4MGB6Z.js +1264 -0
  65. package/dist/chunk-JVKB2TBL.js +48 -0
  66. package/dist/chunk-JX7VBZDK.js +31 -0
  67. package/dist/chunk-K6BXGITA.js +931 -0
  68. package/dist/chunk-KDQJCT2J.js +45 -0
  69. package/dist/chunk-KJ2ZTQSL.js +47 -0
  70. package/dist/chunk-KZMSZV32.js +187 -0
  71. package/dist/chunk-LA7CLDRW.js +129 -0
  72. package/dist/chunk-LHOA5DWA.js +28 -0
  73. package/dist/chunk-LSMMOS2Z.js +119 -0
  74. package/dist/chunk-LX5QWLBL.js +27 -0
  75. package/dist/chunk-LXWCMQNJ.js +789 -0
  76. package/dist/chunk-M27LIEKV.js +2829 -0
  77. package/dist/chunk-MJPHJRAL.js +663 -0
  78. package/dist/chunk-MTL4O5YR.js +228 -0
  79. package/dist/chunk-NDBIPFNY.js +102 -0
  80. package/dist/chunk-NEMIWEXC.js +1199 -0
  81. package/dist/chunk-NHJ75HXY.js +1 -0
  82. package/dist/chunk-NIOAGFPB.js +1510 -0
  83. package/dist/chunk-NS52ISWS.js +355 -0
  84. package/dist/chunk-NSOFPKGT.js +5352 -0
  85. package/dist/chunk-NVIZG63R.js +757 -0
  86. package/dist/chunk-O37BQ65S.js +21 -0
  87. package/dist/chunk-OOYZPOXM.js +308 -0
  88. package/dist/chunk-OSGLYW5J.js +28 -0
  89. package/dist/chunk-PFCMSSUF.js +1640 -0
  90. package/dist/chunk-PFZO3C6H.js +14 -0
  91. package/dist/chunk-PGRVXIMY.js +158 -0
  92. package/dist/chunk-PHH7LD45.js +113 -0
  93. package/dist/chunk-PISBFBJN.js +109 -0
  94. package/dist/chunk-POOOIWE5.js +9 -0
  95. package/dist/chunk-PQNS3U7Z.js +1240 -0
  96. package/dist/chunk-QSTSJOCK.js +402 -0
  97. package/dist/chunk-RFQMOKWK.js +282 -0
  98. package/dist/chunk-RJIZEJ42.js +30 -0
  99. package/dist/chunk-RTOTNK3P.js +484 -0
  100. package/dist/chunk-RXKSDUAU.js +1172 -0
  101. package/dist/chunk-S45JPKQN.js +3317 -0
  102. package/dist/chunk-SAFHACFA.js +152 -0
  103. package/dist/chunk-SQJVFEBV.js +41 -0
  104. package/dist/chunk-SVT4RNTR.js +49 -0
  105. package/dist/chunk-SWUFN7XM.js +43 -0
  106. package/dist/chunk-SXMVYC5H.js +174 -0
  107. package/dist/chunk-SZ6AYUIZ.js +23 -0
  108. package/dist/chunk-TBRL2RCC.js +9 -0
  109. package/dist/chunk-TCCHINEF.js +655 -0
  110. package/dist/chunk-THEGTRAG.js +316 -0
  111. package/dist/chunk-TR4LQE7L.js +2256 -0
  112. package/dist/chunk-TRT2HRWZ.js +18 -0
  113. package/dist/chunk-TWJMGXCI.js +900 -0
  114. package/dist/chunk-U45AXT5D.js +1023 -0
  115. package/dist/chunk-U4FWBSO3.js +509 -0
  116. package/dist/chunk-UBGDX6FI.js +147 -0
  117. package/dist/chunk-UJILKYES.js +75 -0
  118. package/dist/chunk-ULMAQV3T.js +234 -0
  119. package/dist/chunk-VVBP6KGT.js +9 -0
  120. package/dist/chunk-W5VITDM2.js +168 -0
  121. package/dist/chunk-WAHQVNWT.js +194 -0
  122. package/dist/chunk-WBPVKEEE.js +227 -0
  123. package/dist/chunk-WGGYRBXH.js +5434 -0
  124. package/dist/chunk-WLYKU45P.js +5770 -0
  125. package/dist/chunk-WP7BVANJ.js +53 -0
  126. package/dist/chunk-WQQON3SV.js +473 -0
  127. package/dist/chunk-WQTOVMGV.js +119 -0
  128. package/dist/chunk-XBDP4QPW.js +7 -0
  129. package/dist/chunk-XEBHSJLT.js +103 -0
  130. package/dist/chunk-XF4VUMKW.js +231 -0
  131. package/dist/chunk-XQ2ECNK3.js +1 -0
  132. package/dist/chunk-Y5YXDM7D.js +74 -0
  133. package/dist/chunk-YOPAUVU4.js +2588 -0
  134. package/dist/chunk-YPT4A46F.js +362 -0
  135. package/dist/chunk-YWXT3JNM.js +425 -0
  136. package/dist/chunk-YY6APYUM.js +49 -0
  137. package/dist/chunk-Z2IJUO45.js +691 -0
  138. package/dist/chunk-ZHZ2Y2DH.js +1643 -0
  139. package/dist/chunk-ZT7JNIGX.js +152 -0
  140. package/dist/coordination/agent-monitor.d.ts +9 -1
  141. package/dist/coordination/agent-subagent-runner.d.ts +1 -1
  142. package/dist/coordination/agents/agent-prompts.d.ts +8 -0
  143. package/dist/coordination/agents/index.d.ts +33 -1
  144. package/dist/coordination/agents/index.js +184 -6269
  145. package/dist/coordination/agents/phase3-wave1-platform.d.ts +1 -3
  146. package/dist/coordination/agents/phase3-wave2-meta.d.ts +1 -3
  147. package/dist/coordination/agents/phase8-wave3-products.d.ts +1 -3
  148. package/dist/coordination/agents/phase9-wave4-platform-meta.d.ts +1 -3
  149. package/dist/coordination/agents/project-agent-identity.d.ts +11 -11
  150. package/dist/coordination/agents/types.d.ts +13 -2
  151. package/dist/coordination/brain-monitor.d.ts +30 -7
  152. package/dist/coordination/collab-debug.d.ts +1 -1
  153. package/dist/coordination/collab-pause.d.ts +1 -1
  154. package/dist/coordination/delegate-tool.d.ts +7 -5
  155. package/dist/coordination/director-kanban-queue-helpers.d.ts +1 -0
  156. package/dist/coordination/director-options.d.ts +7 -0
  157. package/dist/coordination/director-spawn-model.d.ts +17 -0
  158. package/dist/coordination/director-tools.d.ts +2 -2
  159. package/dist/coordination/director.d.ts +12 -0
  160. package/dist/coordination/dispatcher.d.ts +8 -0
  161. package/dist/coordination/fleet-bus.d.ts +35 -4
  162. package/dist/coordination/fleet-supervisor.d.ts +10 -2
  163. package/dist/coordination/fleet.d.ts +16 -7
  164. package/dist/coordination/index.d.ts +4 -0
  165. package/dist/coordination/index.js +402 -34324
  166. package/dist/coordination/kanban-dispatch-port.d.ts +2 -2
  167. package/dist/coordination/mailbox-http-router.d.ts +4 -3
  168. package/dist/coordination/mailbox-http-validation.d.ts +1 -1
  169. package/dist/coordination/mailbox-project-server.js +48 -3276
  170. package/dist/coordination/mailbox-types.d.ts +24 -6
  171. package/dist/coordination/model-tier-leader.d.ts +122 -0
  172. package/dist/coordination/model-tier.d.ts +122 -0
  173. package/dist/coordination/multi-agent-coordinator.d.ts +24 -0
  174. package/dist/coordination/origin-session.d.ts +16 -0
  175. package/dist/coordination/provider-status-tracker.d.ts +41 -5
  176. package/dist/coordination/session-note-hub.d.ts +44 -0
  177. package/dist/coordination/session-note-tool.d.ts +10 -0
  178. package/dist/core/agent.d.ts +15 -2
  179. package/dist/core/context.d.ts +22 -3
  180. package/dist/core/index.d.ts +2 -0
  181. package/dist/core/index.js +239 -12360
  182. package/dist/core/model-ref.js +5 -23
  183. package/dist/core/provider-runner.d.ts +36 -1
  184. package/dist/core/request-conversation-binding.d.ts +37 -0
  185. package/dist/core/session-notes.d.ts +25 -0
  186. package/dist/core/system-prompt-builder.d.ts +11 -2
  187. package/dist/core/system-prompt-variants.d.ts +78 -0
  188. package/dist/design/index.js +50 -1087
  189. package/dist/execution/auto-compaction-middleware.d.ts +11 -0
  190. package/dist/execution/autonomy-brain.d.ts +2 -1
  191. package/dist/execution/autonomy-prompt-contributor.d.ts +7 -2
  192. package/dist/execution/compaction-core.d.ts +4 -4
  193. package/dist/execution/eternal-autonomy.d.ts +1 -1
  194. package/dist/execution/index.d.ts +1 -1
  195. package/dist/execution/index.js +1615 -21895
  196. package/dist/execution/model-runtime.d.ts +0 -7
  197. package/dist/execution/parallel-eternal-engine.d.ts +7 -7
  198. package/dist/execution/prompt-enhancer.js +16 -535
  199. package/dist/execution/retry-policy.d.ts +31 -1
  200. package/dist/extension/index.js +7 -311
  201. package/dist/goal/index.js +33 -3435
  202. package/dist/hooks/index.js +14 -1138
  203. package/dist/hq/index.js +114 -5139
  204. package/dist/hq/persistence/event-log.d.ts +0 -1
  205. package/dist/hq/persistence.d.ts +4 -4
  206. package/dist/hq/protocol.js +21 -668
  207. package/dist/hq/publisher.d.ts +2 -0
  208. package/dist/index.d.ts +14 -11
  209. package/dist/index.js +1502 -92655
  210. package/dist/infrastructure/index.d.ts +4 -4
  211. package/dist/infrastructure/index.js +504 -5230
  212. package/dist/infrastructure/token-counter.d.ts +9 -0
  213. package/dist/kernel/events/agent-events.d.ts +77 -3
  214. package/dist/kernel/events/brain-events.d.ts +12 -0
  215. package/dist/kernel/events/provider-events.d.ts +22 -1
  216. package/dist/kernel/events/session-events.d.ts +14 -0
  217. package/dist/kernel/events/tool-events.d.ts +13 -0
  218. package/dist/kernel/index.js +14 -992
  219. package/dist/mailbox-attach.d.ts +1 -1
  220. package/dist/models/index.js +41 -1117
  221. package/dist/notifications/index.js +3 -108
  222. package/dist/observability/event-bridge.d.ts +25 -5
  223. package/dist/observability/index.d.ts +9 -8
  224. package/dist/observability/index.js +477 -631
  225. package/dist/observability/tool-usage-source.d.ts +65 -0
  226. package/dist/plugin/index.d.ts +5 -0
  227. package/dist/plugin/index.js +600 -14835
  228. package/dist/plugins/auto-review-plugin.d.ts +3 -2
  229. package/dist/plugins/review-finding-commands.d.ts +0 -8
  230. package/dist/plugins/review-finding-store.js +22 -0
  231. package/dist/plugins/review-finding-types.js +19 -0
  232. package/dist/plugins/review-report-integration.js +21 -0
  233. package/dist/plugins/review-report-store.js +20 -0
  234. package/dist/plugins/review-report-types.js +13 -0
  235. package/dist/prompts/index.js +14 -948
  236. package/dist/registry/index.js +9 -822
  237. package/dist/registry/tool-registry.d.ts +59 -9
  238. package/dist/registry-7N4O3E7W.js +14 -0
  239. package/dist/replay/index.js +6 -84
  240. package/dist/security/capabilities.d.ts +6 -0
  241. package/dist/security/file-permissions.d.ts +1 -1
  242. package/dist/security/index.js +161 -2235
  243. package/dist/security/permission-policy.d.ts +12 -1
  244. package/dist/security/secret-scrubber.d.ts +15 -0
  245. package/dist/session-catalog/index.d.ts +1 -0
  246. package/dist/session-catalog/index.js +41 -2103
  247. package/dist/session-catalog/project-server.js +59 -1435
  248. package/dist/session-catalog/protocol.d.ts +32 -1
  249. package/dist/session-catalog/registry.d.ts +17 -1
  250. package/dist/session-catalog/session-agents.d.ts +56 -0
  251. package/dist/session-catalog/store-rebuild.d.ts +14 -0
  252. package/dist/session-catalog/store-schema.d.ts +26 -0
  253. package/dist/session-catalog/store.d.ts +27 -1
  254. package/dist/session-note-attach.d.ts +9 -0
  255. package/dist/skills/index.js +35 -1578
  256. package/dist/statusline/index.d.ts +43 -0
  257. package/dist/statusline/index.js +102 -0
  258. package/dist/storage/board-store-port.d.ts +2 -2
  259. package/dist/storage/config-loader/in-project-policy.d.ts +29 -0
  260. package/dist/storage/config-loader.d.ts +3 -2
  261. package/dist/storage/file-session-writer.d.ts +4 -2
  262. package/dist/storage/goal-coordination.d.ts +6 -1
  263. package/dist/storage/goal-kanban.d.ts +4 -1
  264. package/dist/storage/index.d.ts +12 -4
  265. package/dist/storage/index.js +198 -15601
  266. package/dist/storage/input-history-store.d.ts +2 -4
  267. package/dist/storage/memory-curator.d.ts +133 -0
  268. package/dist/storage/session-agent-attribution.d.ts +39 -0
  269. package/dist/storage/session-doctor.d.ts +109 -0
  270. package/dist/storage/session-event-bridge.d.ts +5 -7
  271. package/dist/storage/session-outcome.d.ts +42 -0
  272. package/dist/storage/session-recovery.d.ts +55 -0
  273. package/dist/storage/session-store/load-session-data.d.ts +11 -0
  274. package/dist/storage/session-store/prune-helpers.d.ts +1 -1
  275. package/dist/storage/session-store/resume-session.d.ts +0 -2
  276. package/dist/storage/session-store/types.d.ts +8 -0
  277. package/dist/storage/session-store.d.ts +3 -3
  278. package/dist/storage/session-summary-tracker.d.ts +8 -1
  279. package/dist/storage/session-write-buffer.d.ts +18 -0
  280. package/dist/storage/session-writer-truncate.d.ts +2 -0
  281. package/dist/tasking/index.js +10 -676
  282. package/dist/tools/fallback-manage-tools.d.ts +6 -4
  283. package/dist/tools/index.js +52 -9590
  284. package/dist/tools/model-tier-set-tool.d.ts +66 -0
  285. package/dist/types/agent-bridge.d.ts +2 -1
  286. package/dist/types/config/autonomy.d.ts +5 -0
  287. package/dist/types/config/mcp-features.d.ts +7 -0
  288. package/dist/types/config/model-tiers.d.ts +148 -0
  289. package/dist/types/config/root.d.ts +9 -0
  290. package/dist/types/config/tools.d.ts +73 -0
  291. package/dist/types/config/ui.d.ts +1 -1
  292. package/dist/types/config.d.ts +1 -0
  293. package/dist/types/context.d.ts +2 -0
  294. package/dist/types/default-config.d.ts +6 -0
  295. package/dist/types/errors.d.ts +20 -1
  296. package/dist/types/index.d.ts +11 -9
  297. package/dist/types/index.js +131 -1342
  298. package/dist/types/multi-agent.d.ts +43 -0
  299. package/dist/types/plugin.d.ts +1 -1
  300. package/dist/types/provider-runner.d.ts +8 -0
  301. package/dist/types/provider.d.ts +15 -0
  302. package/dist/types/runtime-capability-manifest.d.ts +1 -1
  303. package/dist/types/secret-scrubber.d.ts +15 -0
  304. package/dist/types/session-markers.d.ts +37 -10
  305. package/dist/types/session-markers.js +8 -144
  306. package/dist/types/session-timeline.d.ts +197 -0
  307. package/dist/types/session-timeline.js +12 -0
  308. package/dist/types/session.d.ts +172 -11
  309. package/dist/types/system-prompt.d.ts +27 -0
  310. package/dist/utils/config-backup.d.ts +9 -1
  311. package/dist/utils/error.js +3 -4
  312. package/dist/utils/expect-defined.js +3 -9
  313. package/dist/utils/heap-watchdog.js +6 -706
  314. package/dist/utils/index.js +271 -5685
  315. package/dist/utils/message-invariants.d.ts +4 -1
  316. package/dist/utils/regex-guard.d.ts +1 -1
  317. package/dist/utils/sage-output-block.js +5 -42
  318. package/dist/utils/socket-path.d.ts +1 -1
  319. package/dist/utils/token-estimate.d.ts +6 -2
  320. package/dist/utils/wstack-paths.d.ts +2 -0
  321. package/dist/wiring/proxy-rewrite.d.ts +46 -0
  322. package/dist/wiring/proxy-rewrite.js +24 -121
  323. package/dist/worktree/index.js +6 -887
  324. package/instructions/agents/explore-companion.md +45 -18
  325. package/instructions/agents/memory-curator.md +34 -22
  326. package/instructions/coordination/director-preamble.md +12 -7
  327. package/instructions/coordination/subagent-baseline.md +26 -5
  328. package/instructions/leader-after-task.md +4 -1
  329. package/instructions/llm/chimera-review.md +30 -9
  330. package/instructions/llm/memory-curator.md +31 -0
  331. package/instructions/sections/tool/delegation-compact.md +2 -0
  332. package/instructions/sections/tool/delegation-full.md +5 -1
  333. package/instructions/sections/tool/mailbox-compact.md +5 -1
  334. package/instructions/sections/tool/mailbox-full.md +3 -0
  335. package/instructions/sections/tool/session-note-compact.md +3 -0
  336. package/instructions/sections/tool/session-note-full.md +15 -0
  337. package/instructions/system-lite.md +9 -4
  338. package/instructions/system-pro.md +66 -143
  339. package/instructions/system.md +73 -175
  340. package/package.json +32 -4
  341. package/dist/coordination/agents.d.ts +0 -8
  342. package/dist/coordination/transport.d.ts +0 -2
  343. package/dist/storage/session-writer/session-writer-summary-tracker.d.ts +0 -28
@@ -0,0 +1,597 @@
1
+ import {
2
+ encryptConfigSecrets,
3
+ isSecretField
4
+ } from "./chunk-YY6APYUM.js";
5
+ import {
6
+ deepMerge
7
+ } from "./chunk-B7F4WVP4.js";
8
+ import {
9
+ restrictFilePermissions
10
+ } from "./chunk-6FHWXLPT.js";
11
+ import {
12
+ atomicWrite
13
+ } from "./chunk-OSGLYW5J.js";
14
+ import {
15
+ ConfigError,
16
+ ERROR_CODES
17
+ } from "./chunk-25LSLC3G.js";
18
+
19
+ // src/types/secret-vault.ts
20
+ var ENCRYPTED_PREFIX_PATTERN = /^enc:v(\d+):/;
21
+ function encryptedPrefixForVersion(version) {
22
+ return `enc:v${version}:`;
23
+ }
24
+ function parseEncryptedVersion(value) {
25
+ const match = value.match(ENCRYPTED_PREFIX_PATTERN);
26
+ return match ? Number.parseInt(match[1], 10) : void 0;
27
+ }
28
+ var noOpVault = {
29
+ encrypt: (v) => v,
30
+ decrypt: (v) => v,
31
+ isEncrypted: () => false,
32
+ keyVersion: 1
33
+ };
34
+
35
+ // src/security/secret-vault.ts
36
+ import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from "node:crypto";
37
+ import * as fs from "node:fs";
38
+ import * as fsp from "node:fs/promises";
39
+ import * as path from "node:path";
40
+ var KEY_BYTES = 32;
41
+ var IV_BYTES = 12;
42
+ var TAG_BYTES = 16;
43
+ var ALGO = "aes-256-gcm";
44
+ var KEY_FILE_MODE = 384;
45
+ var KEY_FILE_MAGIC = Buffer.from("WSKV", "ascii");
46
+ var VERSIONED_KEY_FILE_SIZE = KEY_FILE_MAGIC.length + 1 + KEY_BYTES;
47
+ var KEK_MAGIC = Buffer.from("WSKW", "ascii");
48
+ var KEK_SALT_BYTES = 16;
49
+ var WRAPPED_KEY_FILE_SIZE = KEK_MAGIC.length + 1 + KEK_SALT_BYTES + IV_BYTES + TAG_BYTES + KEY_BYTES;
50
+ var SCRYPT_N = 1 << 15;
51
+ var SCRYPT_R = 8;
52
+ var SCRYPT_P = 1;
53
+ var SCRYPT_MAXMEM = 64 * 1024 * 1024;
54
+ function getVaultPassphrase() {
55
+ const v = process.env["WRONGSTACK_VAULT_PASSPHRASE"];
56
+ return v && v.length > 0 ? v : void 0;
57
+ }
58
+ function isWrappedKeyFile(buf) {
59
+ return buf.length === WRAPPED_KEY_FILE_SIZE && buf.subarray(0, KEK_MAGIC.length).equals(KEK_MAGIC);
60
+ }
61
+ function deriveKEK(passphrase, salt) {
62
+ return scryptSync(passphrase, salt, KEY_BYTES, {
63
+ N: SCRYPT_N,
64
+ r: SCRYPT_R,
65
+ p: SCRYPT_P,
66
+ maxmem: SCRYPT_MAXMEM
67
+ });
68
+ }
69
+ function wrapDataKey(dataKey, keyVersion, passphrase) {
70
+ const salt = randomBytes(KEK_SALT_BYTES);
71
+ const iv = randomBytes(IV_BYTES);
72
+ const kek = deriveKEK(passphrase, salt);
73
+ const cipher = createCipheriv(ALGO, kek, iv);
74
+ const ct = Buffer.concat([cipher.update(dataKey), cipher.final()]);
75
+ const tag = cipher.getAuthTag();
76
+ const out = Buffer.alloc(WRAPPED_KEY_FILE_SIZE);
77
+ let off = 0;
78
+ KEK_MAGIC.copy(out, off);
79
+ off += KEK_MAGIC.length;
80
+ out[off] = keyVersion & 255;
81
+ off += 1;
82
+ salt.copy(out, off);
83
+ off += KEK_SALT_BYTES;
84
+ iv.copy(out, off);
85
+ off += IV_BYTES;
86
+ tag.copy(out, off);
87
+ off += TAG_BYTES;
88
+ ct.copy(out, off);
89
+ return out;
90
+ }
91
+ function unwrapDataKey(buf, keyFile) {
92
+ const passphrase = getVaultPassphrase();
93
+ if (!passphrase) {
94
+ throw new ConfigError({
95
+ message: `SecretVault: key file ${keyFile} is passphrase-protected \u2014 set the WRONGSTACK_VAULT_PASSPHRASE environment variable to unlock it.`,
96
+ code: ERROR_CODES.CONFIG_INVALID,
97
+ context: { keyFile }
98
+ });
99
+ }
100
+ let off = KEK_MAGIC.length;
101
+ const version = buf[off];
102
+ off += 1;
103
+ const salt = buf.subarray(off, off + KEK_SALT_BYTES);
104
+ off += KEK_SALT_BYTES;
105
+ const iv = buf.subarray(off, off + IV_BYTES);
106
+ off += IV_BYTES;
107
+ const tag = buf.subarray(off, off + TAG_BYTES);
108
+ off += TAG_BYTES;
109
+ const ct = buf.subarray(off, off + KEY_BYTES);
110
+ const kek = deriveKEK(passphrase, salt);
111
+ const decipher = createDecipheriv(ALGO, kek, iv);
112
+ decipher.setAuthTag(tag);
113
+ try {
114
+ const key = Buffer.concat([decipher.update(ct), decipher.final()]);
115
+ return { key: Buffer.from(key), version };
116
+ } catch {
117
+ throw new ConfigError({
118
+ message: `SecretVault: failed to unlock key file ${keyFile} \u2014 wrong WRONGSTACK_VAULT_PASSPHRASE (key unwrap authentication failed).`,
119
+ code: ERROR_CODES.CONFIG_INVALID,
120
+ context: { keyFile }
121
+ });
122
+ }
123
+ }
124
+ function keyFileNeedsHardening(keyFile, opts) {
125
+ if (process.platform === "win32") return false;
126
+ const warn = opts?.warn ?? ((msg) => console.warn(msg));
127
+ try {
128
+ const stat = fs.statSync(keyFile);
129
+ const actualMode = stat.mode & 511;
130
+ if (actualMode !== KEY_FILE_MODE) {
131
+ warn(
132
+ `Key file ${keyFile} has mode ${actualMode.toString(8)} \u2014 expected ${KEY_FILE_MODE.toString(8)}. Hardening\u2026`
133
+ );
134
+ return true;
135
+ }
136
+ } catch {
137
+ }
138
+ return false;
139
+ }
140
+ function mkdirSecretDirSync(dir) {
141
+ fs.mkdirSync(dir, { recursive: true, mode: 448 });
142
+ if (process.platform === "win32") return;
143
+ try {
144
+ fs.chmodSync(dir, 448);
145
+ } catch {
146
+ }
147
+ }
148
+ function writeKeyFileAtomicSync(keyFile, content) {
149
+ const tmp = `${keyFile}.${randomBytes(4).toString("hex")}.tmp`;
150
+ const fd = fs.openSync(tmp, "w", 384);
151
+ try {
152
+ fs.writeFileSync(fd, content);
153
+ try {
154
+ fs.fsyncSync(fd);
155
+ } catch {
156
+ }
157
+ } finally {
158
+ fs.closeSync(fd);
159
+ }
160
+ try {
161
+ fs.renameSync(tmp, keyFile);
162
+ } catch (err) {
163
+ try {
164
+ fs.unlinkSync(tmp);
165
+ } catch {
166
+ }
167
+ throw err;
168
+ }
169
+ }
170
+ var DefaultSecretVault = class {
171
+ keyFile;
172
+ logger;
173
+ key;
174
+ _keyVersion = 1;
175
+ /**
176
+ * Pending key-file hardening promises (Windows ACL restrictions via icacls).
177
+ * Tracked so async callers can `flushHardening()` before returning, ensuring
178
+ * a short-lived CLI process does not exit before the hardening resolves.
179
+ * Sync-only callers (encrypt/decrypt lazy-load) leave these pending —
180
+ * hardening remains best-effort in that case.
181
+ */
182
+ pendingHardening = [];
183
+ constructor(opts) {
184
+ this.keyFile = opts.keyFile;
185
+ this.logger = opts.logger;
186
+ }
187
+ /**
188
+ * Emit a structured warning. Uses the configured Logger when available;
189
+ * falls back to console.warn(JSON) so warnings are never silently dropped
190
+ * during early boot.
191
+ */
192
+ logWarn(msg, ctx) {
193
+ if (this.logger) {
194
+ this.logger.warn(msg, ctx);
195
+ } else {
196
+ console.warn(JSON.stringify({ ...ctx, message: msg, timestamp: (/* @__PURE__ */ new Date()).toISOString() }));
197
+ }
198
+ }
199
+ /**
200
+ * Schedule best-effort key-file hardening and track the promise so async
201
+ * callers can await it via `flushHardening()` before returning. Rejections
202
+ * are swallowed here (the helper already warns on failure) so a rejection
203
+ * can never become an unhandled one.
204
+ */
205
+ scheduleKeyHardening() {
206
+ const p = restrictFilePermissions(this.keyFile, {
207
+ label: "secret-vault-key",
208
+ warn: (msg) => this.logWarn(msg)
209
+ }).catch(() => void 0);
210
+ this.pendingHardening.push(p);
211
+ }
212
+ /** Detect and schedule repair of a pre-existing POSIX key with loose mode bits. */
213
+ checkKeyFilePermissions() {
214
+ if (keyFileNeedsHardening(this.keyFile, {
215
+ warn: (msg) => this.logWarn(msg)
216
+ })) {
217
+ this.scheduleKeyHardening();
218
+ }
219
+ }
220
+ /** Flush all pending key-file hardening promises. */
221
+ flushHardening() {
222
+ if (this.pendingHardening.length === 0) return Promise.resolve();
223
+ const all = Promise.all(this.pendingHardening).then(() => void 0);
224
+ this.pendingHardening = [];
225
+ return all;
226
+ }
227
+ /** Current key version. Starts at 1; incremented by rotateKey(). */
228
+ get keyVersion() {
229
+ if (!this.key) this.loadOrCreateKey();
230
+ return this._keyVersion;
231
+ }
232
+ isEncrypted(value) {
233
+ return typeof value === "string" && ENCRYPTED_PREFIX_PATTERN.test(value);
234
+ }
235
+ encrypt(plaintext) {
236
+ if (this.isEncrypted(plaintext)) return plaintext;
237
+ const key = this.loadOrCreateKey();
238
+ const iv = randomBytes(IV_BYTES);
239
+ const cipher = createCipheriv(ALGO, key, iv);
240
+ const ct = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
241
+ const tag = cipher.getAuthTag();
242
+ const prefix = encryptedPrefixForVersion(this._keyVersion);
243
+ return `${prefix}${iv.toString("base64")}:${tag.toString("base64")}:${ct.toString("base64")}`;
244
+ }
245
+ decrypt(value) {
246
+ if (!this.isEncrypted(value)) return value;
247
+ const prefixMatch = value.match(ENCRYPTED_PREFIX_PATTERN);
248
+ if (!prefixMatch) {
249
+ throw new ConfigError({
250
+ message: "SecretVault: malformed encrypted value",
251
+ code: ERROR_CODES.CONFIG_PARSE_FAILED,
252
+ context: { field: "encrypted_value" }
253
+ });
254
+ }
255
+ const rest = value.slice(prefixMatch[0].length);
256
+ const parts = rest.split(":");
257
+ if (parts.length !== 3) {
258
+ throw new ConfigError({
259
+ message: "SecretVault: malformed encrypted value",
260
+ code: ERROR_CODES.CONFIG_PARSE_FAILED,
261
+ context: { field: "encrypted_value" }
262
+ });
263
+ }
264
+ const [ivB64, tagB64, ctB64] = parts;
265
+ const iv = Buffer.from(ivB64, "base64");
266
+ const tag = Buffer.from(tagB64, "base64");
267
+ const ct = Buffer.from(ctB64, "base64");
268
+ if (iv.length !== IV_BYTES)
269
+ throw new ConfigError({
270
+ message: "SecretVault: bad IV length",
271
+ code: ERROR_CODES.CONFIG_PARSE_FAILED,
272
+ context: { expected: IV_BYTES, actual: iv.length }
273
+ });
274
+ if (tag.length !== TAG_BYTES)
275
+ throw new ConfigError({
276
+ message: "SecretVault: bad tag length",
277
+ code: ERROR_CODES.CONFIG_PARSE_FAILED,
278
+ context: { expected: TAG_BYTES, actual: tag.length }
279
+ });
280
+ const key = this.loadOrCreateKey();
281
+ const decipher = createDecipheriv(ALGO, key, iv);
282
+ decipher.setAuthTag(tag);
283
+ const pt = Buffer.concat([decipher.update(ct), decipher.final()]);
284
+ return pt.toString("utf8");
285
+ }
286
+ /**
287
+ * Generate a new encryption key, write it to disk, and increment the key version.
288
+ * After rotation, encrypt() emits the new version prefix (e.g. enc:v2:).
289
+ * The caller must re-encrypt existing config values (see rotateConfigKeys()).
290
+ */
291
+ rotateKey() {
292
+ const oldVersion = this._keyVersion;
293
+ const newKey = randomBytes(KEY_BYTES);
294
+ const newVersion = oldVersion + 1;
295
+ mkdirSecretDirSync(path.dirname(this.keyFile));
296
+ const passphrase = getVaultPassphrase();
297
+ if (passphrase) {
298
+ writeKeyFileAtomicSync(this.keyFile, wrapDataKey(newKey, newVersion, passphrase));
299
+ } else {
300
+ const keyFileBuf = Buffer.alloc(VERSIONED_KEY_FILE_SIZE);
301
+ KEY_FILE_MAGIC.copy(keyFileBuf, 0);
302
+ keyFileBuf[KEY_FILE_MAGIC.length] = newVersion;
303
+ newKey.copy(keyFileBuf, KEY_FILE_MAGIC.length + 1);
304
+ writeKeyFileAtomicSync(this.keyFile, keyFileBuf);
305
+ }
306
+ this.scheduleKeyHardening();
307
+ this.checkKeyFilePermissions();
308
+ this.key = newKey;
309
+ this._keyVersion = newVersion;
310
+ return { oldVersion, newVersion };
311
+ }
312
+ /**
313
+ * If WRONGSTACK_VAULT_PASSPHRASE is set but the key on disk is still stored
314
+ * unwrapped (legacy v1 / versioned v2), re-write it in passphrase-wrapped (v3)
315
+ * form. The data key is preserved, so all existing ciphertext keeps
316
+ * decrypting. Best-effort: a write failure leaves the working unwrapped file
317
+ * in place and is not fatal to load.
318
+ */
319
+ migrateToWrappedIfPassphrase() {
320
+ const passphrase = getVaultPassphrase();
321
+ if (!passphrase || !this.key) return;
322
+ try {
323
+ writeKeyFileAtomicSync(this.keyFile, wrapDataKey(this.key, this._keyVersion, passphrase));
324
+ this.scheduleKeyHardening();
325
+ this.checkKeyFilePermissions();
326
+ } catch {
327
+ }
328
+ }
329
+ loadOrCreateKey() {
330
+ if (this.key) return this.key;
331
+ try {
332
+ const buf = fs.readFileSync(this.keyFile);
333
+ if (isWrappedKeyFile(buf)) {
334
+ const { key: key2, version } = unwrapDataKey(buf, this.keyFile);
335
+ this.key = key2;
336
+ this._keyVersion = version;
337
+ this.checkKeyFilePermissions();
338
+ return this.key;
339
+ }
340
+ if (buf.length === KEY_BYTES) {
341
+ this.key = buf;
342
+ this._keyVersion = 1;
343
+ this.checkKeyFilePermissions();
344
+ this.migrateToWrappedIfPassphrase();
345
+ return this.key;
346
+ }
347
+ if (buf.length === VERSIONED_KEY_FILE_SIZE) {
348
+ const magic = buf.subarray(0, KEY_FILE_MAGIC.length);
349
+ if (!magic.equals(KEY_FILE_MAGIC)) {
350
+ throw new ConfigError({
351
+ message: `SecretVault: key file ${this.keyFile} has invalid magic header`,
352
+ code: ERROR_CODES.CONFIG_INVALID,
353
+ context: { keyFile: this.keyFile }
354
+ });
355
+ }
356
+ const version = buf[KEY_FILE_MAGIC.length];
357
+ const key2 = buf.subarray(KEY_FILE_MAGIC.length + 1);
358
+ if (key2.length !== KEY_BYTES) {
359
+ throw new ConfigError({
360
+ message: `SecretVault: key file ${this.keyFile} has wrong key size (${key2.length} bytes, expected ${KEY_BYTES})`,
361
+ code: ERROR_CODES.CONFIG_INVALID,
362
+ context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: key2.length }
363
+ });
364
+ }
365
+ this.key = Buffer.from(key2);
366
+ this._keyVersion = version;
367
+ this.checkKeyFilePermissions();
368
+ this.migrateToWrappedIfPassphrase();
369
+ return this.key;
370
+ }
371
+ throw new ConfigError({
372
+ message: `SecretVault: key file ${this.keyFile} is ${buf.length} bytes (expected ${KEY_BYTES} for v1 or ${VERSIONED_KEY_FILE_SIZE} for v2+). Remove it manually to generate a new key.`,
373
+ code: ERROR_CODES.CONFIG_INVALID,
374
+ context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: buf.length }
375
+ });
376
+ } catch (err) {
377
+ if (err.code !== "ENOENT") throw err;
378
+ }
379
+ mkdirSecretDirSync(path.dirname(this.keyFile));
380
+ const key = randomBytes(KEY_BYTES);
381
+ const passphrase = getVaultPassphrase();
382
+ const initialBytes = passphrase ? wrapDataKey(key, 1, passphrase) : key;
383
+ try {
384
+ fs.writeFileSync(this.keyFile, initialBytes, { mode: 384, flag: "wx" });
385
+ this.scheduleKeyHardening();
386
+ } catch (err) {
387
+ if (err.code !== "EEXIST") throw err;
388
+ this.scheduleKeyHardening();
389
+ const buf = fs.readFileSync(this.keyFile);
390
+ if (isWrappedKeyFile(buf)) {
391
+ const { key: winnerKey, version } = unwrapDataKey(buf, this.keyFile);
392
+ this.key = winnerKey;
393
+ this._keyVersion = version;
394
+ this.checkKeyFilePermissions();
395
+ return this.key;
396
+ }
397
+ if (buf.length === KEY_BYTES) {
398
+ this.key = buf;
399
+ this._keyVersion = 1;
400
+ this.checkKeyFilePermissions();
401
+ return this.key;
402
+ }
403
+ if (buf.length === VERSIONED_KEY_FILE_SIZE) {
404
+ const magic = buf.subarray(0, KEY_FILE_MAGIC.length);
405
+ if (!magic.equals(KEY_FILE_MAGIC)) {
406
+ throw new ConfigError({
407
+ message: `SecretVault: key file ${this.keyFile} has invalid magic header`,
408
+ code: ERROR_CODES.CONFIG_INVALID,
409
+ context: { keyFile: this.keyFile }
410
+ });
411
+ }
412
+ const version = buf[KEY_FILE_MAGIC.length];
413
+ const winnerKey = buf.subarray(KEY_FILE_MAGIC.length + 1);
414
+ this.key = Buffer.from(winnerKey);
415
+ this._keyVersion = version;
416
+ this.checkKeyFilePermissions();
417
+ return this.key;
418
+ }
419
+ throw new ConfigError({
420
+ message: `SecretVault: key file ${this.keyFile} is ${buf.length} bytes (expected ${KEY_BYTES} for v1 or ${VERSIONED_KEY_FILE_SIZE} for v2+). Remove it manually to generate a new key.`,
421
+ code: ERROR_CODES.CONFIG_INVALID,
422
+ context: { keyFile: this.keyFile, expectedBytes: KEY_BYTES, actualBytes: buf.length }
423
+ });
424
+ }
425
+ this.key = key;
426
+ this._keyVersion = 1;
427
+ return key;
428
+ }
429
+ };
430
+ async function rewriteConfigEncrypted(configPath, vault, patch) {
431
+ let current = {};
432
+ try {
433
+ const raw = await fsp.readFile(configPath, "utf8");
434
+ current = JSON.parse(raw);
435
+ } catch {
436
+ }
437
+ const merged = deepMerge(current, patch ?? {});
438
+ const encrypted = encryptConfigSecrets(merged, vault);
439
+ await fsp.mkdir(path.dirname(configPath), { recursive: true });
440
+ await atomicWrite(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
441
+ await restrictFilePermissions2(configPath);
442
+ await vault.flushHardening?.();
443
+ }
444
+ async function migratePlaintextSecrets(configPath, vault, logger) {
445
+ let raw;
446
+ try {
447
+ raw = await fsp.readFile(configPath, "utf8");
448
+ } catch {
449
+ return { migrated: 0, file: configPath };
450
+ }
451
+ let parsed;
452
+ try {
453
+ parsed = JSON.parse(raw);
454
+ } catch {
455
+ return { migrated: 0, file: configPath };
456
+ }
457
+ const counter = { n: 0 };
458
+ const migrated = walkCount(parsed, vault, counter);
459
+ if (counter.n === 0) return { migrated: 0, file: configPath };
460
+ await atomicWrite(configPath, JSON.stringify(migrated, null, 2), { mode: 384 });
461
+ await restrictFilePermissions2(
462
+ configPath,
463
+ logger ? { warn: (msg) => logger.warn(msg) } : void 0
464
+ );
465
+ await vault.flushHardening?.();
466
+ return { migrated: counter.n, file: configPath };
467
+ }
468
+ async function rotateConfigKeys(configPath, vault, logger) {
469
+ const log = logger?.info ?? (() => {
470
+ });
471
+ const warn = logger?.warn ?? ((msg) => console.warn(msg));
472
+ let raw;
473
+ try {
474
+ raw = await fsp.readFile(configPath, "utf8");
475
+ } catch {
476
+ const { oldVersion: oldVersion2, newVersion: newVersion2 } = vault.rotateKey();
477
+ log(
478
+ `[secret-vault] Key rotated (v${oldVersion2} \u2192 v${newVersion2}) \u2014 no config file to re-encrypt`
479
+ );
480
+ await vault.flushHardening?.();
481
+ return { rotated: 0, oldVersion: oldVersion2, newVersion: newVersion2, file: configPath };
482
+ }
483
+ let parsed;
484
+ try {
485
+ parsed = JSON.parse(raw);
486
+ } catch {
487
+ warn(`[secret-vault] Config file ${configPath} is not valid JSON \u2014 skipping rotation`);
488
+ return {
489
+ rotated: 0,
490
+ oldVersion: vault.keyVersion,
491
+ newVersion: vault.keyVersion,
492
+ file: configPath
493
+ };
494
+ }
495
+ const counter = { n: 0, failed: [] };
496
+ const decrypted = walkDecryptCount(parsed, vault, counter);
497
+ if (counter.failed.length > 0) {
498
+ throw new Error(
499
+ `[secret-vault] Aborting key rotation: ${counter.failed.length} field(s) could not be decrypted with the current key and would be permanently lost on rotation: ${counter.failed.join(", ")}. Restore or remove these fields before rotating.`
500
+ );
501
+ }
502
+ if (counter.n === 0) {
503
+ const { oldVersion: oldVersion2, newVersion: newVersion2 } = vault.rotateKey();
504
+ log(
505
+ `[secret-vault] Key rotated (v${oldVersion2} \u2192 v${newVersion2}) \u2014 no encrypted fields to re-encrypt`
506
+ );
507
+ await vault.flushHardening?.();
508
+ return { rotated: 0, oldVersion: oldVersion2, newVersion: newVersion2, file: configPath };
509
+ }
510
+ const { oldVersion, newVersion } = vault.rotateKey();
511
+ const reencrypted = walkReencrypt(decrypted, vault);
512
+ await atomicWrite(configPath, JSON.stringify(reencrypted, null, 2), { mode: 384 });
513
+ await restrictFilePermissions2(configPath, { warn });
514
+ log(
515
+ `[secret-vault] Key rotated (v${oldVersion} \u2192 v${newVersion}) \u2014 re-encrypted ${counter.n} field(s)`
516
+ );
517
+ await vault.flushHardening?.();
518
+ return { rotated: counter.n, oldVersion, newVersion, file: configPath };
519
+ }
520
+ function walkDecryptCount(node, vault, counter, pathPrefix = "") {
521
+ if (node === null || node === void 0) return node;
522
+ if (typeof node !== "object") return node;
523
+ if (Array.isArray(node)) {
524
+ return node.map(
525
+ (item, i) => walkDecryptCount(item, vault, counter, `${pathPrefix}[${i}]`)
526
+ );
527
+ }
528
+ const out = /* @__PURE__ */ Object.create(null);
529
+ for (const [k, v] of Object.entries(node)) {
530
+ const keyPath = pathPrefix ? `${pathPrefix}.${k}` : k;
531
+ if (typeof v === "string" && vault.isEncrypted(v)) {
532
+ try {
533
+ out[k] = vault.decrypt(v);
534
+ counter.n++;
535
+ } catch {
536
+ counter.failed.push(keyPath);
537
+ out[k] = v;
538
+ }
539
+ } else if (typeof v === "object" && v !== null) {
540
+ out[k] = walkDecryptCount(v, vault, counter, keyPath);
541
+ } else {
542
+ out[k] = v;
543
+ }
544
+ }
545
+ return out;
546
+ }
547
+ function walkReencrypt(node, vault) {
548
+ if (node === null || node === void 0) return node;
549
+ if (typeof node !== "object") return node;
550
+ if (Array.isArray(node)) {
551
+ return node.map((item) => walkReencrypt(item, vault));
552
+ }
553
+ const out = /* @__PURE__ */ Object.create(null);
554
+ for (const [k, v] of Object.entries(node)) {
555
+ if (typeof v === "string" && isSecretField(k) && v.length > 0 && !vault.isEncrypted(v)) {
556
+ out[k] = vault.encrypt(v);
557
+ } else if (typeof v === "object" && v !== null) {
558
+ out[k] = walkReencrypt(v, vault);
559
+ } else {
560
+ out[k] = v;
561
+ }
562
+ }
563
+ return out;
564
+ }
565
+ async function restrictFilePermissions2(filePath, opts) {
566
+ await restrictFilePermissions(filePath, { label: "secret-vault", warn: opts?.warn });
567
+ }
568
+ function walkCount(node, vault, counter) {
569
+ if (node === null || node === void 0) return node;
570
+ if (typeof node !== "object") return node;
571
+ if (Array.isArray(node)) {
572
+ return node.map((item) => walkCount(item, vault, counter));
573
+ }
574
+ const out = /* @__PURE__ */ Object.create(null);
575
+ for (const [k, v] of Object.entries(node)) {
576
+ if (typeof v === "string" && isSecretField(k) && !vault.isEncrypted(v) && v.length > 0) {
577
+ out[k] = vault.encrypt(v);
578
+ counter.n++;
579
+ } else if (typeof v === "object" && v !== null) {
580
+ out[k] = walkCount(v, vault, counter);
581
+ } else {
582
+ out[k] = v;
583
+ }
584
+ }
585
+ return out;
586
+ }
587
+
588
+ export {
589
+ encryptedPrefixForVersion,
590
+ parseEncryptedVersion,
591
+ noOpVault,
592
+ DefaultSecretVault,
593
+ rewriteConfigEncrypted,
594
+ migratePlaintextSecrets,
595
+ rotateConfigKeys
596
+ };
597
+ //# sourceMappingURL=chunk-CU546ESW.js.map