kastell 2.1.0 → 2.2.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 (501) hide show
  1. package/.claude-plugin/marketplace.json +18 -0
  2. package/.claude-plugin/plugin.json +39 -0
  3. package/CHANGELOG.md +1266 -1216
  4. package/LICENSE +201 -201
  5. package/NOTICE +5 -5
  6. package/README.md +1 -1
  7. package/README.tr.md +1 -1
  8. package/bin/kastell +2 -2
  9. package/bin/kastell-mcp +5 -5
  10. package/dist/adapters/coolify.js +92 -92
  11. package/dist/adapters/dokploy.js +99 -99
  12. package/dist/adapters/shared.d.ts.map +1 -1
  13. package/dist/adapters/shared.js +4 -2
  14. package/dist/adapters/shared.js.map +1 -1
  15. package/dist/commands/add.d.ts.map +1 -1
  16. package/dist/commands/add.js +6 -9
  17. package/dist/commands/add.js.map +1 -1
  18. package/dist/commands/auth.d.ts.map +1 -1
  19. package/dist/commands/auth.js +12 -12
  20. package/dist/commands/auth.js.map +1 -1
  21. package/dist/commands/doctor.d.ts +1 -0
  22. package/dist/commands/doctor.d.ts.map +1 -1
  23. package/dist/commands/doctor.js +23 -8
  24. package/dist/commands/doctor.js.map +1 -1
  25. package/dist/commands/evidence.d.ts.map +1 -1
  26. package/dist/commands/evidence.js +8 -9
  27. package/dist/commands/evidence.js.map +1 -1
  28. package/dist/commands/fix.d.ts +1 -0
  29. package/dist/commands/fix.d.ts.map +1 -1
  30. package/dist/commands/fix.js +24 -5
  31. package/dist/commands/fix.js.map +1 -1
  32. package/dist/commands/init.d.ts.map +1 -1
  33. package/dist/commands/init.js +4 -7
  34. package/dist/commands/init.js.map +1 -1
  35. package/dist/commands/interactive/backup-maintenance.d.ts +8 -0
  36. package/dist/commands/interactive/backup-maintenance.d.ts.map +1 -0
  37. package/dist/commands/interactive/backup-maintenance.js +120 -0
  38. package/dist/commands/interactive/backup-maintenance.js.map +1 -0
  39. package/dist/commands/interactive/index.d.ts +4 -0
  40. package/dist/commands/interactive/index.d.ts.map +1 -0
  41. package/dist/commands/interactive/index.js +94 -0
  42. package/dist/commands/interactive/index.js.map +1 -0
  43. package/dist/commands/interactive/menu.d.ts +23 -0
  44. package/dist/commands/interactive/menu.d.ts.map +1 -0
  45. package/dist/commands/interactive/menu.js +121 -0
  46. package/dist/commands/interactive/menu.js.map +1 -0
  47. package/dist/commands/interactive/monitoring.d.ts +5 -0
  48. package/dist/commands/interactive/monitoring.d.ts.map +1 -0
  49. package/dist/commands/interactive/monitoring.js +96 -0
  50. package/dist/commands/interactive/monitoring.js.map +1 -0
  51. package/dist/commands/interactive/plugins.d.ts +2 -0
  52. package/dist/commands/interactive/plugins.d.ts.map +1 -0
  53. package/dist/commands/interactive/plugins.js +30 -0
  54. package/dist/commands/interactive/plugins.js.map +1 -0
  55. package/dist/commands/interactive/security.d.ts +9 -0
  56. package/dist/commands/interactive/security.d.ts.map +1 -0
  57. package/dist/commands/interactive/security.js +535 -0
  58. package/dist/commands/interactive/security.js.map +1 -0
  59. package/dist/commands/interactive/server-management.d.ts +5 -0
  60. package/dist/commands/interactive/server-management.d.ts.map +1 -0
  61. package/dist/commands/interactive/server-management.js +79 -0
  62. package/dist/commands/interactive/server-management.js.map +1 -0
  63. package/dist/commands/interactive/shared.d.ts +12 -0
  64. package/dist/commands/interactive/shared.d.ts.map +1 -0
  65. package/dist/commands/interactive/shared.js +30 -0
  66. package/dist/commands/interactive/shared.js.map +1 -0
  67. package/dist/commands/interactive.d.ts.map +1 -1
  68. package/dist/commands/interactive.js +29 -0
  69. package/dist/commands/interactive.js.map +1 -1
  70. package/dist/commands/lock.js +1 -1
  71. package/dist/commands/lock.js.map +1 -1
  72. package/dist/commands/plugin.d.ts +8 -0
  73. package/dist/commands/plugin.d.ts.map +1 -0
  74. package/dist/commands/plugin.js +87 -0
  75. package/dist/commands/plugin.js.map +1 -0
  76. package/dist/commands/regression.d.ts.map +1 -1
  77. package/dist/commands/regression.js +1 -2
  78. package/dist/commands/regression.js.map +1 -1
  79. package/dist/commands/restart.d.ts.map +1 -1
  80. package/dist/commands/restart.js +3 -2
  81. package/dist/commands/restart.js.map +1 -1
  82. package/dist/commands/schedule.js +2 -2
  83. package/dist/commands/schedule.js.map +1 -1
  84. package/dist/core/audit/checkIds.d.ts +516 -0
  85. package/dist/core/audit/checkIds.d.ts.map +1 -0
  86. package/dist/core/audit/checkIds.js +515 -0
  87. package/dist/core/audit/checkIds.js.map +1 -0
  88. package/dist/core/audit/checks/accounts.d.ts.map +1 -1
  89. package/dist/core/audit/checks/accounts.js +23 -22
  90. package/dist/core/audit/checks/accounts.js.map +1 -1
  91. package/dist/core/audit/checks/auth.d.ts.map +1 -1
  92. package/dist/core/audit/checks/auth.js +23 -22
  93. package/dist/core/audit/checks/auth.js.map +1 -1
  94. package/dist/core/audit/checks/backup.d.ts.map +1 -1
  95. package/dist/core/audit/checks/backup.js +9 -8
  96. package/dist/core/audit/checks/backup.js.map +1 -1
  97. package/dist/core/audit/checks/banners.d.ts.map +1 -1
  98. package/dist/core/audit/checks/banners.js +7 -6
  99. package/dist/core/audit/checks/banners.js.map +1 -1
  100. package/dist/core/audit/checks/boot.d.ts.map +1 -1
  101. package/dist/core/audit/checks/boot.js +12 -11
  102. package/dist/core/audit/checks/boot.js.map +1 -1
  103. package/dist/core/audit/checks/cloudmeta.d.ts.map +1 -1
  104. package/dist/core/audit/checks/cloudmeta.js +7 -6
  105. package/dist/core/audit/checks/cloudmeta.js.map +1 -1
  106. package/dist/core/audit/checks/crypto.d.ts +0 -5
  107. package/dist/core/audit/checks/crypto.d.ts.map +1 -1
  108. package/dist/core/audit/checks/crypto.js +20 -19
  109. package/dist/core/audit/checks/crypto.js.map +1 -1
  110. package/dist/core/audit/checks/ddos.d.ts.map +1 -1
  111. package/dist/core/audit/checks/ddos.js +9 -8
  112. package/dist/core/audit/checks/ddos.js.map +1 -1
  113. package/dist/core/audit/checks/dns.d.ts.map +1 -1
  114. package/dist/core/audit/checks/dns.js +9 -8
  115. package/dist/core/audit/checks/dns.js.map +1 -1
  116. package/dist/core/audit/checks/docker.d.ts.map +1 -1
  117. package/dist/core/audit/checks/docker.js +65 -64
  118. package/dist/core/audit/checks/docker.js.map +1 -1
  119. package/dist/core/audit/checks/fileintegrity.d.ts.map +1 -1
  120. package/dist/core/audit/checks/fileintegrity.js +11 -10
  121. package/dist/core/audit/checks/fileintegrity.js.map +1 -1
  122. package/dist/core/audit/checks/filesystem.d.ts.map +1 -1
  123. package/dist/core/audit/checks/filesystem.js +21 -20
  124. package/dist/core/audit/checks/filesystem.js.map +1 -1
  125. package/dist/core/audit/checks/firewall.d.ts.map +1 -1
  126. package/dist/core/audit/checks/firewall.js +18 -17
  127. package/dist/core/audit/checks/firewall.js.map +1 -1
  128. package/dist/core/audit/checks/httpHeaders.d.ts.map +1 -1
  129. package/dist/core/audit/checks/httpHeaders.js +7 -6
  130. package/dist/core/audit/checks/httpHeaders.js.map +1 -1
  131. package/dist/core/audit/checks/incidentready.d.ts.map +1 -1
  132. package/dist/core/audit/checks/incidentready.js +13 -12
  133. package/dist/core/audit/checks/incidentready.js.map +1 -1
  134. package/dist/core/audit/checks/kernel.d.ts.map +1 -1
  135. package/dist/core/audit/checks/kernel.js +32 -31
  136. package/dist/core/audit/checks/kernel.js.map +1 -1
  137. package/dist/core/audit/checks/logging.d.ts.map +1 -1
  138. package/dist/core/audit/checks/logging.js +21 -20
  139. package/dist/core/audit/checks/logging.js.map +1 -1
  140. package/dist/core/audit/checks/mac.d.ts.map +1 -1
  141. package/dist/core/audit/checks/mac.js +11 -10
  142. package/dist/core/audit/checks/mac.js.map +1 -1
  143. package/dist/core/audit/checks/malware.d.ts.map +1 -1
  144. package/dist/core/audit/checks/malware.js +12 -11
  145. package/dist/core/audit/checks/malware.js.map +1 -1
  146. package/dist/core/audit/checks/memory.d.ts.map +1 -1
  147. package/dist/core/audit/checks/memory.js +12 -11
  148. package/dist/core/audit/checks/memory.js.map +1 -1
  149. package/dist/core/audit/checks/network.d.ts.map +1 -1
  150. package/dist/core/audit/checks/network.js +22 -21
  151. package/dist/core/audit/checks/network.js.map +1 -1
  152. package/dist/core/audit/checks/nginx.d.ts.map +1 -1
  153. package/dist/core/audit/checks/nginx.js +17 -16
  154. package/dist/core/audit/checks/nginx.js.map +1 -1
  155. package/dist/core/audit/checks/resourcelimits.d.ts.map +1 -1
  156. package/dist/core/audit/checks/resourcelimits.js +9 -8
  157. package/dist/core/audit/checks/resourcelimits.js.map +1 -1
  158. package/dist/core/audit/checks/scheduling.d.ts.map +1 -1
  159. package/dist/core/audit/checks/scheduling.js +13 -12
  160. package/dist/core/audit/checks/scheduling.js.map +1 -1
  161. package/dist/core/audit/checks/secrets.d.ts.map +1 -1
  162. package/dist/core/audit/checks/secrets.js +16 -15
  163. package/dist/core/audit/checks/secrets.js.map +1 -1
  164. package/dist/core/audit/checks/services.d.ts.map +1 -1
  165. package/dist/core/audit/checks/services.js +26 -25
  166. package/dist/core/audit/checks/services.js.map +1 -1
  167. package/dist/core/audit/checks/ssh.d.ts.map +1 -1
  168. package/dist/core/audit/checks/ssh.js +23 -22
  169. package/dist/core/audit/checks/ssh.js.map +1 -1
  170. package/dist/core/audit/checks/supplychain.d.ts.map +1 -1
  171. package/dist/core/audit/checks/supplychain.js +13 -12
  172. package/dist/core/audit/checks/supplychain.js.map +1 -1
  173. package/dist/core/audit/checks/time.d.ts.map +1 -1
  174. package/dist/core/audit/checks/time.js +10 -9
  175. package/dist/core/audit/checks/time.js.map +1 -1
  176. package/dist/core/audit/checks/tls.d.ts.map +1 -1
  177. package/dist/core/audit/checks/tls.js +9 -8
  178. package/dist/core/audit/checks/tls.js.map +1 -1
  179. package/dist/core/audit/checks/updates.d.ts.map +1 -1
  180. package/dist/core/audit/checks/updates.js +12 -11
  181. package/dist/core/audit/checks/updates.js.map +1 -1
  182. package/dist/core/audit/compliance/categories/index.d.ts +3 -0
  183. package/dist/core/audit/compliance/categories/index.d.ts.map +1 -0
  184. package/dist/core/audit/compliance/categories/index.js +737 -0
  185. package/dist/core/audit/compliance/categories/index.js.map +1 -0
  186. package/dist/core/audit/compliance/helpers.d.ts +17 -0
  187. package/dist/core/audit/compliance/helpers.d.ts.map +1 -0
  188. package/dist/core/audit/compliance/helpers.js +40 -0
  189. package/dist/core/audit/compliance/helpers.js.map +1 -0
  190. package/dist/core/audit/compliance/mapper.d.ts +4 -16
  191. package/dist/core/audit/compliance/mapper.d.ts.map +1 -1
  192. package/dist/core/audit/compliance/mapper.js +3 -776
  193. package/dist/core/audit/compliance/mapper.js.map +1 -1
  194. package/dist/core/audit/fix-history.d.ts +16 -7
  195. package/dist/core/audit/fix-history.d.ts.map +1 -1
  196. package/dist/core/audit/fix-history.js +25 -2
  197. package/dist/core/audit/fix-history.js.map +1 -1
  198. package/dist/core/audit/fix.d.ts +17 -2
  199. package/dist/core/audit/fix.d.ts.map +1 -1
  200. package/dist/core/audit/fix.js +115 -42
  201. package/dist/core/audit/fix.js.map +1 -1
  202. package/dist/core/audit/formatters/badge.js +20 -20
  203. package/dist/core/audit/index.d.ts.map +1 -1
  204. package/dist/core/audit/index.js +3 -2
  205. package/dist/core/audit/index.js.map +1 -1
  206. package/dist/core/audit/snapshot.d.ts.map +1 -1
  207. package/dist/core/audit/snapshot.js +6 -2
  208. package/dist/core/audit/snapshot.js.map +1 -1
  209. package/dist/core/audit/types.d.ts +11 -1
  210. package/dist/core/audit/types.d.ts.map +1 -1
  211. package/dist/core/audit/watch.d.ts.map +1 -1
  212. package/dist/core/audit/watch.js +3 -2
  213. package/dist/core/audit/watch.js.map +1 -1
  214. package/dist/core/backup.d.ts.map +1 -1
  215. package/dist/core/backup.js +10 -5
  216. package/dist/core/backup.js.map +1 -1
  217. package/dist/core/bot/handlers.d.ts.map +1 -1
  218. package/dist/core/bot/handlers.js +2 -17
  219. package/dist/core/bot/handlers.js.map +1 -1
  220. package/dist/core/completions.d.ts.map +1 -1
  221. package/dist/core/completions.js +632 -610
  222. package/dist/core/completions.js.map +1 -1
  223. package/dist/core/deploy.d.ts.map +1 -1
  224. package/dist/core/deploy.js +7 -4
  225. package/dist/core/deploy.js.map +1 -1
  226. package/dist/core/doctor-fix.d.ts +1 -1
  227. package/dist/core/doctor-fix.d.ts.map +1 -1
  228. package/dist/core/doctor-fix.js +17 -2
  229. package/dist/core/doctor-fix.js.map +1 -1
  230. package/dist/core/doctor.d.ts.map +1 -1
  231. package/dist/core/doctor.js +2 -1
  232. package/dist/core/doctor.js.map +1 -1
  233. package/dist/core/firewall.d.ts +0 -1
  234. package/dist/core/firewall.d.ts.map +1 -1
  235. package/dist/core/firewall.js +2 -13
  236. package/dist/core/firewall.js.map +1 -1
  237. package/dist/core/lock/auth.d.ts +7 -0
  238. package/dist/core/lock/auth.d.ts.map +1 -0
  239. package/dist/core/lock/auth.js +59 -0
  240. package/dist/core/lock/auth.js.map +1 -0
  241. package/dist/core/lock/docker.d.ts +4 -0
  242. package/dist/core/lock/docker.d.ts.map +1 -0
  243. package/dist/core/lock/docker.js +28 -0
  244. package/dist/core/lock/docker.js.map +1 -0
  245. package/dist/core/lock/index.d.ts +11 -0
  246. package/dist/core/lock/index.d.ts.map +1 -0
  247. package/dist/core/lock/index.js +247 -0
  248. package/dist/core/lock/index.js.map +1 -0
  249. package/dist/core/lock/monitoring.d.ts +4 -0
  250. package/dist/core/lock/monitoring.d.ts.map +1 -0
  251. package/dist/core/lock/monitoring.js +55 -0
  252. package/dist/core/lock/monitoring.js.map +1 -0
  253. package/dist/core/lock/network.d.ts +6 -0
  254. package/dist/core/lock/network.d.ts.map +1 -0
  255. package/dist/core/lock/network.js +59 -0
  256. package/dist/core/lock/network.js.map +1 -0
  257. package/dist/core/lock/ssh.d.ts +5 -0
  258. package/dist/core/lock/ssh.d.ts.map +1 -0
  259. package/dist/core/lock/ssh.js +49 -0
  260. package/dist/core/lock/ssh.js.map +1 -0
  261. package/dist/core/lock/system.d.ts +9 -0
  262. package/dist/core/lock/system.d.ts.map +1 -0
  263. package/dist/core/lock/system.js +80 -0
  264. package/dist/core/lock/system.js.map +1 -0
  265. package/dist/core/lock/types.d.ts +41 -0
  266. package/dist/core/lock/types.d.ts.map +1 -0
  267. package/dist/core/lock/types.js +2 -0
  268. package/dist/core/lock/types.js.map +1 -0
  269. package/dist/core/maintain.d.ts.map +1 -1
  270. package/dist/core/maintain.js +3 -1
  271. package/dist/core/maintain.js.map +1 -1
  272. package/dist/core/manage.d.ts.map +1 -1
  273. package/dist/core/manage.js +7 -4
  274. package/dist/core/manage.js.map +1 -1
  275. package/dist/core/notify.d.ts.map +1 -1
  276. package/dist/core/notify.js +2 -1
  277. package/dist/core/notify.js.map +1 -1
  278. package/dist/core/notifyStore.d.ts.map +1 -1
  279. package/dist/core/notifyStore.js +3 -1
  280. package/dist/core/notifyStore.js.map +1 -1
  281. package/dist/core/plugin.d.ts +23 -0
  282. package/dist/core/plugin.d.ts.map +1 -0
  283. package/dist/core/plugin.js +107 -0
  284. package/dist/core/plugin.js.map +1 -0
  285. package/dist/core/provision.d.ts.map +1 -1
  286. package/dist/core/provision.js +9 -4
  287. package/dist/core/provision.js.map +1 -1
  288. package/dist/core/scheduleManager.d.ts +2 -1
  289. package/dist/core/scheduleManager.d.ts.map +1 -1
  290. package/dist/core/scheduleManager.js +13 -7
  291. package/dist/core/scheduleManager.js.map +1 -1
  292. package/dist/index.js +34 -2
  293. package/dist/index.js.map +1 -1
  294. package/dist/mcp/index.js +5 -9
  295. package/dist/mcp/index.js.map +1 -1
  296. package/dist/mcp/schemas/audit.d.ts +34 -0
  297. package/dist/mcp/schemas/audit.d.ts.map +1 -0
  298. package/dist/mcp/schemas/audit.js +23 -0
  299. package/dist/mcp/schemas/audit.js.map +1 -0
  300. package/dist/mcp/schemas/common.d.ts +16 -0
  301. package/dist/mcp/schemas/common.d.ts.map +1 -0
  302. package/dist/mcp/schemas/common.js +14 -0
  303. package/dist/mcp/schemas/common.js.map +1 -0
  304. package/dist/mcp/schemas/health.d.ts +14 -0
  305. package/dist/mcp/schemas/health.d.ts.map +1 -0
  306. package/dist/mcp/schemas/health.js +13 -0
  307. package/dist/mcp/schemas/health.js.map +1 -0
  308. package/dist/mcp/schemas/index.d.ts +5 -0
  309. package/dist/mcp/schemas/index.d.ts.map +1 -0
  310. package/dist/mcp/schemas/index.js +5 -0
  311. package/dist/mcp/schemas/index.js.map +1 -0
  312. package/dist/mcp/schemas/server.d.ts +18 -0
  313. package/dist/mcp/schemas/server.d.ts.map +1 -0
  314. package/dist/mcp/schemas/server.js +16 -0
  315. package/dist/mcp/schemas/server.js.map +1 -0
  316. package/dist/mcp/server.d.ts.map +1 -1
  317. package/dist/mcp/server.js +71 -40
  318. package/dist/mcp/server.js.map +1 -1
  319. package/dist/mcp/tools/serverAudit.d.ts +63 -1
  320. package/dist/mcp/tools/serverAudit.d.ts.map +1 -1
  321. package/dist/mcp/tools/serverAudit.js +63 -6
  322. package/dist/mcp/tools/serverAudit.js.map +1 -1
  323. package/dist/mcp/tools/serverBackup.d.ts +100 -2
  324. package/dist/mcp/tools/serverBackup.d.ts.map +1 -1
  325. package/dist/mcp/tools/serverBackup.handlers.d.ts.map +1 -1
  326. package/dist/mcp/tools/serverBackup.handlers.js +9 -0
  327. package/dist/mcp/tools/serverBackup.handlers.js.map +1 -1
  328. package/dist/mcp/tools/serverBackup.js +74 -0
  329. package/dist/mcp/tools/serverBackup.js.map +1 -1
  330. package/dist/mcp/tools/serverCompare.d.ts +33 -0
  331. package/dist/mcp/tools/serverCompare.d.ts.map +1 -1
  332. package/dist/mcp/tools/serverCompare.js +45 -2
  333. package/dist/mcp/tools/serverCompare.js.map +1 -1
  334. package/dist/mcp/tools/serverDoctor.d.ts +14 -0
  335. package/dist/mcp/tools/serverDoctor.d.ts.map +1 -1
  336. package/dist/mcp/tools/serverDoctor.js +16 -1
  337. package/dist/mcp/tools/serverDoctor.js.map +1 -1
  338. package/dist/mcp/tools/serverEvidence.d.ts +13 -0
  339. package/dist/mcp/tools/serverEvidence.d.ts.map +1 -1
  340. package/dist/mcp/tools/serverEvidence.js +17 -2
  341. package/dist/mcp/tools/serverEvidence.js.map +1 -1
  342. package/dist/mcp/tools/serverExplain.d.ts +17 -0
  343. package/dist/mcp/tools/serverExplain.d.ts.map +1 -1
  344. package/dist/mcp/tools/serverExplain.js +33 -1
  345. package/dist/mcp/tools/serverExplain.js.map +1 -1
  346. package/dist/mcp/tools/serverFix.d.ts +78 -0
  347. package/dist/mcp/tools/serverFix.d.ts.map +1 -1
  348. package/dist/mcp/tools/serverFix.js +87 -0
  349. package/dist/mcp/tools/serverFix.js.map +1 -1
  350. package/dist/mcp/tools/serverFleet.d.ts +24 -1
  351. package/dist/mcp/tools/serverFleet.d.ts.map +1 -1
  352. package/dist/mcp/tools/serverFleet.js +24 -1
  353. package/dist/mcp/tools/serverFleet.js.map +1 -1
  354. package/dist/mcp/tools/serverGuard.d.ts +12 -0
  355. package/dist/mcp/tools/serverGuard.d.ts.map +1 -1
  356. package/dist/mcp/tools/serverGuard.js +16 -0
  357. package/dist/mcp/tools/serverGuard.js.map +1 -1
  358. package/dist/mcp/tools/serverInfo.d.ts +77 -1
  359. package/dist/mcp/tools/serverInfo.d.ts.map +1 -1
  360. package/dist/mcp/tools/serverInfo.js +77 -4
  361. package/dist/mcp/tools/serverInfo.js.map +1 -1
  362. package/dist/mcp/tools/serverLock.d.ts +10 -0
  363. package/dist/mcp/tools/serverLock.d.ts.map +1 -1
  364. package/dist/mcp/tools/serverLock.js +15 -3
  365. package/dist/mcp/tools/serverLock.js.map +1 -1
  366. package/dist/mcp/tools/serverLogs.d.ts +43 -0
  367. package/dist/mcp/tools/serverLogs.d.ts.map +1 -1
  368. package/dist/mcp/tools/serverLogs.js +28 -0
  369. package/dist/mcp/tools/serverLogs.js.map +1 -1
  370. package/dist/mcp/tools/serverMaintain.d.ts +47 -0
  371. package/dist/mcp/tools/serverMaintain.d.ts.map +1 -1
  372. package/dist/mcp/tools/serverMaintain.js +75 -41
  373. package/dist/mcp/tools/serverMaintain.js.map +1 -1
  374. package/dist/mcp/tools/serverManage.d.ts +50 -0
  375. package/dist/mcp/tools/serverManage.d.ts.map +1 -1
  376. package/dist/mcp/tools/serverManage.js +49 -0
  377. package/dist/mcp/tools/serverManage.js.map +1 -1
  378. package/dist/mcp/tools/serverPlugin.d.ts +30 -0
  379. package/dist/mcp/tools/serverPlugin.d.ts.map +1 -0
  380. package/dist/mcp/tools/serverPlugin.js +47 -0
  381. package/dist/mcp/tools/serverPlugin.js.map +1 -0
  382. package/dist/mcp/tools/serverProvision.d.ts +22 -0
  383. package/dist/mcp/tools/serverProvision.d.ts.map +1 -1
  384. package/dist/mcp/tools/serverProvision.js +22 -2
  385. package/dist/mcp/tools/serverProvision.js.map +1 -1
  386. package/dist/mcp/tools/serverSecure.d.ts +120 -0
  387. package/dist/mcp/tools/serverSecure.d.ts.map +1 -1
  388. package/dist/mcp/tools/serverSecure.handlers.d.ts.map +1 -1
  389. package/dist/mcp/tools/serverSecure.handlers.js +39 -98
  390. package/dist/mcp/tools/serverSecure.handlers.js.map +1 -1
  391. package/dist/mcp/tools/serverSecure.js +101 -0
  392. package/dist/mcp/tools/serverSecure.js.map +1 -1
  393. package/dist/mcp/utils.d.ts +1 -0
  394. package/dist/mcp/utils.d.ts.map +1 -1
  395. package/dist/mcp/utils.js +5 -1
  396. package/dist/mcp/utils.js.map +1 -1
  397. package/dist/plugin/loader.d.ts +10 -0
  398. package/dist/plugin/loader.d.ts.map +1 -0
  399. package/dist/plugin/loader.js +88 -0
  400. package/dist/plugin/loader.js.map +1 -0
  401. package/dist/plugin/registry.d.ts +16 -0
  402. package/dist/plugin/registry.d.ts.map +1 -0
  403. package/dist/plugin/registry.js +101 -0
  404. package/dist/plugin/registry.js.map +1 -0
  405. package/dist/plugin/sdk/constants.d.ts +3 -0
  406. package/dist/plugin/sdk/constants.d.ts.map +1 -0
  407. package/dist/plugin/sdk/constants.js +3 -0
  408. package/dist/plugin/sdk/constants.js.map +1 -0
  409. package/dist/plugin/sdk/types.d.ts +29 -0
  410. package/dist/plugin/sdk/types.d.ts.map +1 -0
  411. package/dist/plugin/sdk/types.js +2 -0
  412. package/dist/plugin/sdk/types.js.map +1 -0
  413. package/dist/plugin/validate.d.ts +3 -0
  414. package/dist/plugin/validate.d.ts.map +1 -0
  415. package/dist/plugin/validate.js +31 -0
  416. package/dist/plugin/validate.js.map +1 -0
  417. package/dist/providers/base.d.ts.map +1 -1
  418. package/dist/providers/base.js +2 -1
  419. package/dist/providers/base.js.map +1 -1
  420. package/dist/providers/linode.d.ts +1 -0
  421. package/dist/providers/linode.d.ts.map +1 -1
  422. package/dist/providers/linode.js +4 -0
  423. package/dist/providers/linode.js.map +1 -1
  424. package/dist/utils/cloudInit.js +58 -58
  425. package/dist/utils/config.d.ts +3 -0
  426. package/dist/utils/config.d.ts.map +1 -1
  427. package/dist/utils/config.js +11 -6
  428. package/dist/utils/config.js.map +1 -1
  429. package/dist/utils/encryption.d.ts.map +1 -1
  430. package/dist/utils/encryption.js +4 -1
  431. package/dist/utils/encryption.js.map +1 -1
  432. package/dist/utils/errorMapper.d.ts.map +1 -1
  433. package/dist/utils/errorMapper.js +2 -1
  434. package/dist/utils/errorMapper.js.map +1 -1
  435. package/dist/utils/errors.d.ts +1 -0
  436. package/dist/utils/errors.d.ts.map +1 -1
  437. package/dist/utils/errors.js +3 -0
  438. package/dist/utils/errors.js.map +1 -1
  439. package/dist/utils/migration.d.ts.map +1 -1
  440. package/dist/utils/migration.js +25 -14
  441. package/dist/utils/migration.js.map +1 -1
  442. package/dist/utils/paths.d.ts +4 -0
  443. package/dist/utils/paths.d.ts.map +1 -1
  444. package/dist/utils/paths.js +4 -0
  445. package/dist/utils/paths.js.map +1 -1
  446. package/dist/utils/safeMode.d.ts.map +1 -1
  447. package/dist/utils/safeMode.js +3 -2
  448. package/dist/utils/safeMode.js.map +1 -1
  449. package/dist/utils/secureWrite.d.ts.map +1 -1
  450. package/dist/utils/secureWrite.js +2 -1
  451. package/dist/utils/secureWrite.js.map +1 -1
  452. package/dist/utils/securityLogger.d.ts.map +1 -1
  453. package/dist/utils/securityLogger.js +7 -3
  454. package/dist/utils/securityLogger.js.map +1 -1
  455. package/dist/utils/version.d.ts +4 -0
  456. package/dist/utils/version.d.ts.map +1 -0
  457. package/dist/utils/version.js +22 -0
  458. package/dist/utils/version.js.map +1 -0
  459. package/dist/utils/yamlConfig.d.ts.map +1 -1
  460. package/dist/utils/yamlConfig.js +3 -2
  461. package/dist/utils/yamlConfig.js.map +1 -1
  462. package/kastell-plugin/.claude-plugin/plugin.json +20 -0
  463. package/kastell-plugin/.mcp.json +8 -0
  464. package/kastell-plugin/README.md +113 -0
  465. package/kastell-plugin/agents/.gitkeep +0 -0
  466. package/kastell-plugin/agents/kastell-auditor.md +77 -0
  467. package/kastell-plugin/agents/scripts/bucket_mapper.sh +101 -0
  468. package/kastell-plugin/agents/scripts/trend_report.sh +91 -0
  469. package/kastell-plugin/hooks/destroy-block.cjs +31 -0
  470. package/kastell-plugin/hooks/hooks.json +57 -0
  471. package/kastell-plugin/hooks/pre-commit-audit-guard.cjs +75 -0
  472. package/kastell-plugin/hooks/session-audit.cjs +86 -0
  473. package/kastell-plugin/hooks/session-log.cjs +56 -0
  474. package/kastell-plugin/hooks/stop-quality-check.cjs +72 -0
  475. package/kastell-plugin/skills/.gitkeep +0 -0
  476. package/kastell-plugin/skills/kastell-careful/SKILL.md +64 -0
  477. package/kastell-plugin/skills/kastell-ops/SKILL.md +139 -0
  478. package/kastell-plugin/skills/kastell-ops/references/commands.md +45 -0
  479. package/kastell-plugin/skills/kastell-ops/references/mcp-tools.md +50 -0
  480. package/kastell-plugin/skills/kastell-ops/references/patterns.md +145 -0
  481. package/kastell-plugin/skills/kastell-ops/references/pitfalls.md +136 -0
  482. package/kastell-plugin/skills/kastell-ops/scripts/check_coverage.sh +101 -0
  483. package/kastell-plugin/skills/kastell-ops/scripts/fleet_report.sh +73 -0
  484. package/kastell-plugin/skills/kastell-ops/scripts/parse_audit.sh +76 -0
  485. package/kastell-plugin/skills/kastell-research/SKILL.md +90 -0
  486. package/kastell-plugin/skills/kastell-scaffold/SKILL.md +104 -0
  487. package/kastell-plugin/skills/kastell-scaffold/references/template-audit-check.md +150 -0
  488. package/kastell-plugin/skills/kastell-scaffold/references/template-command.md +80 -0
  489. package/kastell-plugin/skills/kastell-scaffold/references/template-mcp-tool.md +72 -0
  490. package/kastell-plugin/skills/kastell-scaffold/references/template-provider.md +67 -0
  491. package/kastell-plugin/skills/kastell-scaffold/scripts/scaffold.sh +180 -0
  492. package/kastell-plugin/skills/kastell-scaffold/templates/check-test.ts.tpl +27 -0
  493. package/kastell-plugin/skills/kastell-scaffold/templates/check.ts.tpl +50 -0
  494. package/kastell-plugin/skills/kastell-scaffold/templates/command-core.ts.tpl +18 -0
  495. package/kastell-plugin/skills/kastell-scaffold/templates/command-test.ts.tpl +17 -0
  496. package/kastell-plugin/skills/kastell-scaffold/templates/command.ts.tpl +25 -0
  497. package/kastell-plugin/skills/kastell-scaffold/templates/mcp-tool-test.ts.tpl +30 -0
  498. package/kastell-plugin/skills/kastell-scaffold/templates/mcp-tool.ts.tpl +29 -0
  499. package/kastell-plugin/skills/kastell-scaffold/templates/provider-test.ts.tpl +34 -0
  500. package/kastell-plugin/skills/kastell-scaffold/templates/provider.ts.tpl +32 -0
  501. package/package.json +122 -113
package/CHANGELOG.md CHANGED
@@ -1,1216 +1,1266 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- ## [2.1.0] - 2026-04-28
6
-
7
- ### Added
8
- - **`kastell init` 3-way wizard** — interactive setup with three paths: provision a new server, register an existing server, or configure defaults (compliance framework, notification channels)
9
- - **`kastell explain <check-id>`** — deep-dive into any audit check: why it matters, fix command, fix tier (SAFE/GUARDED/FORBIDDEN), CIS/PCI-DSS/HIPAA compliance references. Supports `--format terminal|json|md`
10
- - **`audit --ci` flag** CI mode with JSON output, no spinner, requires `--threshold` for exit code gating
11
- - **`fleet --categories`** shows weakest audit category per server in fleet dashboard
12
- - **`audit --compare` enhancements** `--fresh` flag for live audit (skip snapshots), `--detail` for check-level diff instead of category summary
13
- - **`server_compare` MCP tool** side-by-side server comparison with snapshot fallback and detail mode (16th MCP tool)
14
- - **Doctor score** `computeDoctorScore` with severity-weighted findings, wired into CLI and MCP
15
- - **Regression gating** — pre-fix regression check with `--force` bypass, conditional baseline save, `kastell regression status/reset` commands
16
- - **Substring fuzzy match** — `kastell explain ssh-password` resolves to `SSH-PASSWORD-AUTH` (single match returns result, multiple returns suggestions)
17
- - **`defaults.json` support** — `loadDefaults`/`saveDefaults` with Zod validation for threshold/framework fallback
18
-
19
- ### Changed
20
- - **Regression wiring** — `saveBaseline`/`checkRegression` integrated into all 4 callers (CLI audit, CLI fix, MCP serverAudit, MCP serverFix)
21
- - **`confirmOrCancel` helper** — extracted to `prompts.ts` with DI pattern, replacing inline confirm logic in fix and regression flows
22
- - **`hasRegression()` helper** — single source of truth for regression detection, replaces 3 inline copies
23
- - **`resolveAuditPair` extraction** — DRY compare logic with exit code bug fix
24
- - **`formatRegressionSummary`**typed DRY helper for consistent regression display across CLI and MCP
25
- - **`runPostFixReAudit`**returns full AuditResult for accurate post-fix baseline
26
- - **`scoreRegressed` removed from interface** — derived inline via `hasRegression()`, 8 test fixtures updated
27
- - **Discriminated union for `AddServerResult`** type-safe success/failure branching in init wizard
28
- - **`providerConfig.ts` rename** — `utils/defaults.ts` renamed for clarity
29
- - **`formatSuggestions` DRY helper** — shared between explain command and MCP tool
30
- - **Index-based `listSnapshots`**O(1) read instead of O(N) file parse
31
- - **Firewall port deduplication** uses `adapter.platformPorts` as single source
32
-
33
- ### Security
34
- - **Dependency updates** — actions/checkout v6, actions/setup-node v6, actions/upload-artifact v7
35
-
36
- ### Tests
37
- - 255 suites, 10265 tests, 12 snapshots (up from 240 suites, 10127 tests in v2.0.0)
38
- - Coverage threshold: 90% global, 95% audit, 90% provider, 90% MCP
39
-
40
- ## [2.0.0] - 2026-04-20
41
-
42
- ### Added
43
- - **`classifyError` helper** — unified instanceof-based error branching for KastellError hierarchy (TransientError, ValidationError, BusinessError, PermissionError)
44
- - **`logSafeModeBlock`** structured security logging wired into all 9 `isSafeMode()` guard sites in commands/ and MCP tools
45
- - **`secureWriteFileSync` / `secureMkdirSync` / `ensureSecureDir`** platform-aware secure file operations with POSIX permission enforcement
46
- - **`configRepair` core + CLI** — `kastell config repair` diagnoses and repairs corrupted config files
47
- - **MCP audit enhancements** — snapshot save/compare, category/severity filter, threshold gate, profile filter for `server_audit`
48
- - **`--checks` flag** — `kastell fix --checks KERN-SYNCOOKIES,...` for specific check IDs
49
- - **Property-based tests** — fast-check arbitraries for MCP and config Zod schemas
50
- - **Fuzz tests** — kernel, firewall, and filesystem parser fuzzing with fast-check
51
- - **E2E nightly workflow** CI provision→lock→audit→destroy end-to-end pipeline
52
- - **Schema exports** property-based snapshot tests for Zod schema stability
53
-
54
- ### Changed
55
- - **Structured error migration (P107+P113)** — all 9 commands/ catch blocks use `instanceof` branching instead of string matching; mappers (mapProviderError, mapSshError, mapFileSystemError) preserved for backward compat
56
- - **Security logging (P107)** — SecurityLogger module with JSON audit trail, throw-point migration
57
- - **Audit DRY (P106)** — shared sysctl utility, typed audit categories, v1.12 review backlog closed
58
- - **CONFIG_DIR→KASTELL_DIR (P105)** — unified path constant, inline paths eliminated
59
- - **Code quality**template literals, cleaner conditionals, import cleanup across codebase
60
- - **MCP parity** — CLI/MCP feature gap closed (parity matrix verification tests added)
61
-
62
- ### Security
63
- - **secureWrite migration (SEC-06)** — all credential files use `secureWriteFileSync` with 0o600 permissions
64
- - **TOCTOU fix** — removed `existsSync` guard before `secureMkdirSync` in auth.ts
65
- - **Path traversal guard** — server-side validation in `rollbackFix` for E2E JSON parse errors
66
- - **ESLint security plugins (P108)** — Zod schemas for all 4 providers, shellEscape utility, retry resilience (502/503/ETIMEDOUT)
67
- - **CI hardening** — explicit permissions blocks in all workflows, SHA-pinned checkout actions
68
- - **Dependency updates** — axios 1.15.0 (CVE-2025-62718), follow-redirects 1.16.0, hono 4.12.14, actions/cache 5.0.5
69
-
70
- ### Tests
71
- - 240 suites, 10127 tests, 12 snapshots (up from ~9500 in v1.17.1)
72
- - Coverage threshold: 90% global, 95% audit, 90% provider, 90% MCP
73
-
74
- ## [1.17.1] - 2026-04-01
75
-
76
- ### Security
77
- - **28 defence-in-depth fixes** from 5-skill security audit (security-audit, supply-chain, insecure-defaults, sharp-edges, code-review)
78
- - **`sshExec` type narrowing** — accepts `SshCommand` only (removed `| string`), 33 callers wrapped with `raw()` for explicit shell trust
79
- - **`SAFE_MODE` typo-safe** — accepts `"yes"`, `"1"`, `"on"` as truthy; warns on unrecognized values; `remove` action now gated
80
- - **`sanitizedEnv()` expanded blocklist** 10 secret patterns (up from 4): TOKEN, SECRET, PASSWORD, CREDENTIAL, API_KEY, APIKEY, AUTH_KEY, AUTHKEY, PRIVATE_KEY, ACCESS_KEY
81
- - **Rollback SHA256 integrity** — `restore-commands.sh` checksum written during backup, verified before execution
82
- - **MCP error sanitization** — all 12 tool handlers route errors through `sanitizeStderr` to prevent IP/path leakage
83
- - **Path traversal guard** — `relPath` in rollback validated with allowlist regex (`/^[a-zA-Z0-9_./-]+$/`)
84
- - **`backupPath` Zod regex** — format constraint prevents tampered `fix-history.json` from injecting shell commands
85
- - **`SHELL_METACHAR`** — added `&` to block `&&` on fallback path
86
- - **`sedReplace` path quoting** — POSIX single-quote escape for file paths
87
- - **`DEBIAN_FRONTEND` scope** applied to both `apt-get update` and `apt-get upgrade`
88
-
89
- ### Changed
90
- - **`scheduleManager` `execSync` → `spawnSync`** — temp file approach, no shell interpolation, `updateCrontab()` DRY helper
91
- - **`encryption.ts` `execSync` → `spawnSync`** — array args for machine ID retrieval
92
- - **Production deps pinned** — all 11 dependencies use exact versions (no caret ranges)
93
- - **`isSafeMode()` extracted** to `src/utils/safeMode.ts` (re-exported from `manage.ts`)
94
- - **Platform fallback** detection failure defaults to `"bare"` (was `"coolify"`)
95
- - **`cmd("")` throws**empty string arguments rejected
96
- - **`timeoutMs=0` guard** — falls back to default instead of instant kill
97
- - **ControlMaster socket dir** — created with `mode: 0o700`
98
- - **`debugLog` redaction** — sensitive keywords and objects redacted
99
- - **`getServers()` hardened** — JSON.parse catch, provider validation against `SUPPORTED_PROVIDERS`
100
- - **`warnIfPermissionError`**shared helper for EACCES/EPERM distinction
101
-
102
- ## [1.17.0] - 2026-04-01
103
-
104
- ### Added
105
- - **Bulk rollback** — `kastell fix --rollback-all` and `--rollback-to <fix-id>` for batch fix reversal
106
- - **Doctor auto-fix** — `kastell doctor --auto-fix` diagnose-then-fix pipeline with `--dry-run` and `--force` options
107
- - **Fix scheduling** — `kastell schedule fix|audit` installs local cron for automated fix/audit runs with `list` and `remove` management
108
- - **Fix engine DRY refactor** — shared bulk rollback helpers, sed-replace and aptUpgrade programmatic handlers
109
- - **Custom fix profiles** — user-defined profiles loaded from `~/.kastell/profiles/` alongside built-in web-server/database/mail-server
110
- - **SSH ControlMaster** — connection multiplexing for fix engine prevents sshd MaxStartups exhaustion during bulk operations
111
- - **Interactive menu full CLI parity** — schedule category, audit extras (snapshot/trend/watch/host/threshold/report/compare), fix extras (category/diff/report/rollback-to), doctor/lock/evidence/maintain/backup/status/snapshot/fleet options, shared validators
112
- - **WAF bot detection checks** — NGX-WAF-BOT-DETECT and NGX-WAF-CHALLENGE-MODE audit checks for nginx bot mitigation
113
- - **`--no-interactive` flag** — `kastell fix --no-interactive` for scheduled/automated runs without confirmation prompts
114
-
115
- ### Fixed
116
- - **SSH lockout prevention** — NET-HOSTS-DENY moved to GUARDED tier, prevents TCP wrapper lockout via `/etc/hosts.deny`
117
- - **Sysctl SSH breakage** — all sysctl fixes promoted to GUARDED tier, network sysctl SSH probe with automatic rollback (D-20)
118
- - **Session-terminating commands** — reboot/shutdown/poweroff/halt promoted to GUARDED tier (D-22)
119
- - **SSH ControlMaster Windows** — Unix-style `/tmp` socket path, stale socket cleanup, fork detection fix
120
- - **MCP SAFE_MODE guards** — `serverLock`, `serverGuard`, `serverSecure` now enforce `isSafeMode()` for destructive operations
121
- - **Fix backup directory** rollback remote backup path resolution bug fixed (BUG-01)
122
- - **fileWrite + systemctl handlers** shell metachar bypass prevention for programmatic fix handlers
123
-
124
- ### Changed
125
- - **TOCTOU elimination** — replaced `existsSync` checks with direct operation + ENOENT handling across fix engine and core modules
126
- - **KASTELL_DIR consolidation** — unified `CONFIG_DIR` imports to `KASTELL_DIR` from `paths.ts`, eliminated deprecated re-exports
127
- - **severityChalk utility** centralized severity-to-chalk color mapping, replaces inline switch statements
128
- - **9,871 tests** across 219 suites (up from 9,611 / 215 in v1.16)
129
-
130
- ### Security
131
- - **Tier promotion system** — dangerous fixes (sysctl, hosts.deny, reboot) automatically promoted from SAFE to GUARDED, requiring explicit `--guarded` flag
132
- - **MCP fail-closed SAFE_MODE** — MCP server defaults to safe mode, blocking destructive operations unless explicitly disabled
133
-
134
- ## [1.16.0] - 2026-03-29
135
-
136
- ### Added
137
- - **AES-256-GCM token encryption** — tokens.json and notify-secrets.json encrypted at rest when OS keychain is unavailable. Per-installation random salt, cross-platform machine key derivation (Linux/macOS/Windows), transparent plaintext auto-migration
138
- - **Fix rollback & history** — `kastell fix --rollback <id>` restores from backup, `kastell fix --history` shows fix log
139
- - **Fix prioritization** — `kastell fix --top N` applies highest-impact fixes, `kastell fix --target 80` fixes until score reaches target
140
- - **Programmatic fix handlers**4 dedicated handlers (sysctl, file-append, package-install, chmod/chown) replace shell redirect/pipe for SAFE tier fixes
141
- - **Fix profiles** `kastell fix --profile web-server|database|mail-server` applies server-type-specific fix sets
142
- - **Fix diff preview** — `kastell fix --diff` shows per-fix before/after changes
143
- - **Fix report** `kastell fix --report` generates markdown fix report with score change and compliance info
144
- - **WAF audit deep checks** — 5 new WAF pipeline checks (IP ACL, rate limiting, input sanitization, bot detection headers, data masking) expanding nginx category to 14 checks
145
- - **Dependabot config** — `.github/dependabot.yml` for automated GitHub Actions SHA updates
146
- - 10 project-specific security audit custom checks (SSH injection, SAFE_MODE bypass, token leak, MCP validation, subprocess env, SSH host key, API sanitization, error disclosure, npm lifecycle)
147
-
148
- ### Fixed
149
- - **getServers() fail-closed** — corrupt servers.json now throws instead of silently returning empty array
150
- - **fileAppend handler shell injection** single-quote escape via shellEscape() on forward path (rollback already escaped)
151
- - **Encryption key hardening** — per-installation random salt replaces hardcoded "kastell-v1", persistent random UUID fallback replaces low-entropy hostname
152
-
153
- ### Security
154
- - All 13 GitHub Actions references SHA-pinned across 5 workflow files (zero floating tags)
155
- - SECFIX-01 through SECFIX-09 addressed: token encryption, supply chain hardening, fail-closed config, 5 already-closed findings verified
156
- - Security audit: 29 findings (down from 39), 0 critical, 1 high (deferred to v2.0 by design)
157
- - `/review` skill added to release security gate
158
-
159
- ### Changed
160
- - Test count: 5,522 9,611 (4,089 new tests including 3,623 mutation killers)
161
- - Test suites: 207 215
162
- - Test helpers: 4 5 factory files (encryption-factories.ts added)
163
- - Mutation score: 44.65% 59.06% nominal / 78.6% effective (Dalga 1-3 complete)
164
-
165
- ## [1.15.1] - 2026-03-28
166
-
167
- ### Added
168
- - **`kastell changelog` command** — Parse and display CHANGELOG.md in terminal (`kastell changelog`, `kastell changelog v1.14.0`, `kastell changelog --all`)
169
- - **"Why Kastell?" manifesto** in README (EN + TR) problem statement, approach, AI-native positioning
170
- - **Kastell vs Alternatives comparison table** in README (EN + TR) Kastell vs Lynis vs OpenSCAP across 12 dimensions
171
- - **Zero Telemetry badge** in README (EN + TR) trust signal, no data collection
172
- - **CI profile stats dispatch** — `.github` org profile auto-updates on every main push (test/check/category/MCP counts)
173
- - Interactive menu: "View changelog" entry in Configuration section
174
- - CHANGELOG.md included in npm package files
175
-
176
- ### Fixed
177
- - **sshExec SSH banner handling** — servers with login banners caused non-zero exit codes on Windows, breaking health checks, audit scores (42→11 false drop), and doctor cache writes. Now checks stdout content when stderr is banner-only
178
- - **3 incorrect fix commands** `grub2-mkpasswd-pbkdf2` `grub-mkpasswd-pbkdf2` (Ubuntu), `dc3dd` `sleuthkit` (available in repos), `vector` → `rsyslog` (no 3rd party repo needed)
179
- - **Backup fix command** — `kastell backup create` (local CLI, not available on server) → server-side `tar` command
180
- - **audit-watch test timeout** — Windows CI fake timer slowness (jest.setTimeout 15s + extra microtick flushes)
181
- - **CI dispatch format** — JSON body for repository_dispatch (was form-encoded)
182
-
183
- ### Security
184
- - 10 security audit remediation items applied: SHELL_METACHAR validation, bot middleware fail-closed, clearKnownHostKey IP validation, sendTelegram token validation, unhandled rejection handler, npm publish --provenance, staging token scope, debugLog→KASTELL_DEBUG
185
- - Security audit report: `security-audit-report.md` (39 findings, 0 critical)
186
-
187
- ### Changed
188
- - Test count: 5,506 5,522 (16 new tests: 4 SSH banner + 12 changelog)
189
- - Test suites: 206 207
190
-
191
- ## [1.15.0] - 2026-03-27
192
-
193
- ### Added
194
- - **Edge & WAF Audit (P88):** 9 Nginx config checks + WAF detection, 30th audit category, CIS/PCI-DSS compliance mapping
195
- - **TCP Stack DDoS Hardening (P89):** 8 sysctl DDoS parameter checks, 31st audit category, Docker platform guard
196
- - **kastell fix --safe (P90):** SAFE/GUARDED/FORBIDDEN tier classification for 442+ checks, mandatory backup, dry-run, fix→verify pipeline
197
- - **MCP server_fix (P91):** 14th MCP tool with dryRun:true default, SAFE_MODE guard, TypeScript FORBIDDEN rejection
198
- - **Telegram Bot Notifications (P92):** Guard audit score monitoring, two-tier alerts (warning 5-9pt, critical 10+pt), 24h staleness guard, allowedChatIds CRUD
199
- - **Telegram Bot Commands (P93):** grammy polling bot with /status, /audit, /health, /doctor, /help commands, allowedChatIds middleware, offset persistence
200
- - `kastell bot start` command for foreground Telegram bot
201
- - Interactive menu: "Start Telegram bot" entry in Notifications & Bot section
202
-
203
- ### Changed
204
- - Audit categories: 29 31 (WAF & Reverse Proxy, DDoS Hardening)
205
- - Audit checks: 413 442
206
- - Test count: 5468 5499 (31 new bot module tests)
207
- - Interactive menu audit description updated to 31 categories
208
-
209
- ### Fixed
210
- - npm audit vulnerabilities fixed (brace-expansion, handlebars, picomatch)
211
-
212
- ### Security
213
- - Bot allowedChatIds middleware silently blocks unauthorized users (no response leaked)
214
- - Offset persistence prevents stale command replay on bot restart
215
- - server_fix FORBIDDEN rejection blocks SSH/Firewall/Docker category fixes via MCP
216
- - Fix tier classification: SSH/Firewall changes always FORBIDDEN (never auto-fixed)
217
-
218
- ## [1.14.0] - 2026-03-24
219
-
220
- ### Added
221
- - **Snapshot Restore** `kastell snapshot restore` CLI + MCP `snapshot-restore` action with SAFE_MODE guard, double confirmation, and 4-provider support (Hetzner, DigitalOcean, Vultr, Linode)
222
- - **Cloud ID Lookup** — `findServerByIp()` across all 4 providers; `kastell add` now displays Cloud ID automatically
223
- - **TLS Hardening Audit** 8 checks (min version, weak ciphers, HSTS with max-age validation, OCSP stapling, cert expiry, DH params, compression, cert chain) with PCI-DSS/CIS/HIPAA compliance mappings
224
- - **HTTP Security Headers Audit** 6 checks (X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, CORS wildcard, CSP) with PCI-DSS v4.0 mappings
225
- - **Lock Score Boost** — 4 new lock steps (SSH fine-tuning with 15 directives, login.defs hardening, pam_faillock, sudo logging/requiretty) + 2 extended steps (banners +/etc/motd, cronAccess +at.allow); 24-step orchestrator
226
- - **Interactive menu** — Added snapshot restore, audit --explain/--diff/--fix, doctor --fix options
227
- - **Stryker Mutation Testing** — Baseline 40.74% across 19,726 mutants
228
-
229
- ### Fixed
230
- - **Lock-audit alignment** — 5 misalignments fixed (AIDE cron path, auditd restart, logrotate install+timer, cronAccess step, Docker mkdir)
231
- - **snapshotId MCP validation** — Added regex validation for defense-in-depth
232
- - **CERT_NOT_FOUND sentinel** — Properly emits when certificate file is missing instead of false CERT_EXPIRING_SOON
233
- - **HTTPS-only audit gap** — HTTP header audit now tries HTTPS before HTTP for HTTPS-only servers
234
- - **CLI snapshotCreate SAFE_MODE** Added guard for consistency with MCP handler
235
- - **Vultr/Linode snapshotId validation** — Added `assertValidServerId` for defense-in-depth
236
- - **Hetzner findServerByIp pagination** — Changed `per_page` from 50 to 100 for consistency
237
- - **Faillock idempotency** — Each directive independently checked/updated instead of batch
238
- - **fileLock ENOENT** Ensure parent directory exists before creating lock file
239
-
240
- ### Changed
241
- - **Test suite** — 4178→5087 tests (909 new), 197 suites, 11 snapshots; branch coverage: global 93.25%, audit 95.96%, providers 91.22%, MCP 90.25%
242
- - **Audit categories** — 27→29 (TLS Hardening + HTTP Security Headers); 421+ total checks
243
- - **CI hardening** — Codecov integration, 4 typed test factory helpers, zero `as any` casts (231→0)
244
- - **CI release gate** `release.yml` now depends on CI success via `workflow_run` (prevents releasing when CI fails)
245
- - **CI tag support** CI workflow now runs on tag pushes for release/publish chain
246
- - **TLS weak cipher detection** Added SEED and IDEA to pattern
247
- - **HSTS validation** Now checks max-age >= 31536000
248
- - **Compliance mappings** Added HIPAA for TLS, updated PCI-DSS HDR-005 to v4.0 (6.2.4)
249
- - **Skill consolidation** 5 global security skills delegated to single `kastell-security-check.md`
250
-
251
- ### Removed
252
- - **Stryker from CI** — Mutation testing removed from GitHub Actions (exceeds 6h limit); moved to dedicated infrastructure with scheduled nightly incremental runs
253
-
254
- ### Security
255
- - **Comprehensive v1.14 review** 5-agent parallel audit (OWASP, token/secret, audit system, code quality, test coverage); 13 findings resolved (3 MEDIUM + 10 LOW)
256
- - **Release workflow injection fix** Prevented shell injection via `head_branch` interpolation; added strict semver validation before checkout
257
- - **Zero token leakage** 5-layer sanitization verified across all new code paths
258
-
259
- ## [1.13.0] - 2026-03-19
260
-
261
- ### Added
262
- - **Claude Code Plugin** — `kastell-plugin/` marketplace-ready package with `plugin.json` manifest, `.mcp.json`, and `hooks.json`
263
- - **4 Skills** `kastell-ops` (background server management), `kastell-research` (Explore agent + architecture map), `kastell-careful` (skill-scoped LLM prompt hook), `kastell-scaffold` (4 fork-friendly templates)
264
- - **2 Agents** `kastell-auditor` (security review) and `kastell-fixer` (bug diagnosis) project-scope agents
265
- - **5 Hooks** `session-log`, `stop-quality-check`, `session-audit`, `pre-commit-audit-guard`, `destroy-block` with ESM-compatible `.cjs` scripts
266
- - **MCP Discoverability** `server.instructions`, MCP Logging, `llms.txt`, `SUBMISSIONS.md`, 4 platform setup guides, `mcp-server` keyword
267
- - **Dynamic Content Injection** — `!command` syntax in 4 skill files for live codebase context
268
-
269
- ### Fixed
270
- - **CLI↔MCP parity** — 3 bugs fixed: logs default service (Dokploy), health host-key-mismatch detection, maintain update validation
271
- - **DO Coolify SSH key loss** Re-inject SSH public key after platform installer in cloud-init
272
- - **Docker crash after lock** — SSH host key resolution in MCP health checks
273
- - **Plugin hook ESM compatibility** — Renamed `.js` `.cjs` for ESM project compatibility
274
-
275
- ### Changed
276
- - **Commands→Core extraction** — `backup`, `status`, `update` business logic moved from commands/ to core/ (thin command pattern)
277
- - **Adapter bypass elimination** — 9 commands now use adapter properties (`port`, `defaultLogService`, `platformPorts`) instead of hardcoded values
278
- - **Shared `createMockAdapter()`** — Test mock factory in `tests/helpers/mockAdapter.ts`; deduplicated across all test files
279
- - **Test coverage** — 4156→4178 tests (adapter contract, core extraction, hook tests)
280
-
281
- ## [1.12.0] - 2026-03-18
282
-
283
- ### Added
284
- - **`audit --explain`**Inline "Why:" + fix explanation for each failing check in CLI and MCP (`--explain` flag, 95%+ coverage)
285
- - **Lock: auditd CIS L2 rules** — Deep audit rules (time-change, network-change, kernel-module) in `50-kastell-deep.rules` with immutability ordering
286
- - **Lock: sysctl deep tuning** — 21 kernel hardening settings (dmesg_restrict, kptr_restrict, bpf_jit_harden, rp_filter, ASLR, core dumps)
287
- - **Lock: pwquality** — CIS L1 password policy (minlen=14, complexity classes, maxrepeat=3), non-fatal with graceful skip
288
- - **Lock: SSH cipher blacklist** — Weak ciphers/MACs/KEX removed via minus-prefix with `sshd -t` validation and automatic rollback
289
- - **Lock: Docker runtime hardening** — daemon.json merge (no-new-privileges, live-restore, log rotation, icc:false) with platform-aware guards and reload-not-restart
290
- - **Lock 19-step hardening** — Expanded from 16 to 19 steps (pwquality + SSH cipher + Docker hardening)
291
- - **Audit 413 checks** — 4 new checks (KRN-BPF-JIT-HARDEN, LOG-AUDIT-TIME-RULES, LOG-AUDIT-NETWORK-RULES, LOG-AUDIT-MODULE-RULES)
292
-
293
- ### Fixed
294
- - **jq injection prevention** — Docker hardening uses stdin pipe instead of shell interpolation
295
- - **SSH sed tab pattern** — Cipher/MAC/KEX sed patterns now match both space and tab separators
296
- - **Interactive menu** — Lock description updated from 16-step to 19-step
297
-
298
- ### Changed
299
- - **WEAK_CIPHERS/MACS/KEX constants** — Single source in constants.ts, shared by lock and audit
300
- - **Test coverage** — 4152→4156 tests (SSH cipher builder tests added)
301
-
302
- ## [1.11.0] - 2026-03-18
303
-
304
- ### Added
305
- - **MCP tool descriptions** — Updated all 13 MCP tools with 27-category routing hints and accurate check counts
306
- - **Audit display filter** — `audit --filter` for display-only category/severity filtering without re-running SSH
307
- - **Audit fix score delta** — Post-fix score re-audit shows before/after comparison
308
- - **Lock 16-step expansion** — `server lock` expanded from 5 to 16 hardening steps with grouped CLI output and dry-run preview
309
- - **Lock step helpers** — `runLockStep` + 11 command builders for modular hardening (auditd, sysctl, pwquality, AIDE, etc.)
310
- - **SSH host key remediation** — Proactive `removeStaleHostKey` before SSH polling + error output with remediation hints
311
-
312
- ### Fixed
313
- - **Interactive menu audit filters** — Audit sub-menu now correctly passes filter and fix options
314
- - **FW-05 passed field** — Fixed incorrect variable in firewall IPv6 check (`passed: isActive` `passed: ipv6Enabled`)
315
- - **MCP check count** — Corrected inflated 488+ count back to accurate 409
316
- - **Audit filter+fix hardening** — Shell metacharacter guard, severity validation, structured error logging
317
- - **CLOUDMETA_CATALOG_INPUT format** — Fixed cloud metadata catalog input format
318
- - **SSH retry error handling** — Added `.catch()` to SSH retry preventing unhandled rejections
319
-
320
- ### Changed
321
- - **`getErrorMessage` reuse** — Consolidated error message extraction across modules
322
- - **`extractSentinelValue` scoping** — Documented as intentionally local to firewall.ts
323
-
324
- ## [1.10.1] - 2026-03-17
325
-
326
- ### Added
327
- - **sshStream stdin support** — SSH batch commands piped via stdin for reliable cross-platform execution
328
- - **Audit batch error reporting** Structured error details when audit SSH batches fail
329
-
330
- ### Fixed
331
- - **Windows SSH argument escaping** — Batch commands now use stdin pipe instead of spawn arguments, fixing truncation on Windows
332
- - **Audit sentinel wrappers** — Added sentinel markers for 4 categories (accounts, services, boot, scheduling — 24 checks) fixing parser mismatches
333
- - **Cloud-init SSH lockout** — Fixed DigitalOcean + Coolify SSH lockout caused by ssh.socket/needrestart/UFW ordering
334
- - **Interactive menu back navigation** Back option now works correctly in nested sub-menus
335
- - **DEBIAN_FRONTEND=noninteractive** — Added to Coolify and Dokploy cloud-init scripts preventing apt prompts
336
- - **Provision reliability** — Orphan cleanup, Vultr boot timeout (135s), SSH hardening safety guards
337
- - **Snapshot Zod schema** — Added 6 P52 optional fields (vpsIrrelevant, connectionError, vpsType, vpsAdjustedCount, skippedCategories, warnings) preventing silent strip on load
338
-
339
- ## [1.10.0] - 2026-03-16
340
-
341
- ### Added
342
- - **Audit Pro: 27 categories, 406+ checks** — Expanded from 9 categories / 46 checks to 27 categories / 406+ checks with Lynis-parity coverage
343
- - **New audit categories** — Accounts, Services, Boot, Scheduling, Time, Banners, Crypto, File Integrity, Malware, MAC, Memory, Secrets, Cloud Metadata, Supply Chain, Backup Hygiene, Resource Limits, Incident Readiness, DNS Security
344
- - **Compliance mapping** — CIS Ubuntu L1/L2 (290 mappings), PCI-DSS v4.0 (89 refs), HIPAA §164.312 (41 refs)
345
- - **`audit --list-checks`** Static catalog of all 406+ checks with severity, description, and compliance refs
346
- - **`audit --profile`**Filter audit by compliance profile (cis-level1, cis-level2, pci-dss, hipaa)
347
- - **`audit --compliance`** — Framework-grouped compliance report (cis, pci-dss, hipaa)
348
- - **VPS detection** — Auto-detect virtualization type (kvm, vmware, xen, etc.) with VPS-irrelevant check skipping
349
- - **Interactive menu v1.10 options** — Audit sub-menu now includes list-checks, profile filter, compliance report; notify sub-menu includes list/remove
350
-
351
- ### Changed
352
- - **Weighted category scoring** — Categories now have configurable weights (Secrets, Supply Chain weight=3)
353
- - **Snapshot schema v2** — Added `auditVersion` field, automatic v1→v2 migration, Zod strict validation
354
- - **Version-aware trend detection** — Methodology-change banner when comparing different audit versions
355
- - **Semantic check IDs** — All checks renamed from numeric to `CATEGORY-DESCRIPTION` format (e.g., `SSH-PASSWORD-AUTH`)
356
- - **Named separators + 3-tier batches** — SSH command grouping optimized for audit performance
357
- - **Terminal formatter** — Category grouping (fail expanded / pass collapsed), stats header, VPS banner
358
- - **QuickWins** — Max 7, compliance boost factor 1.5x for compliance-mapped checks
359
- - **Provider boot timeout** — Provider-specific polling: Hetzner 30s, DigitalOcean 60s, Vultr 135s, Linode 120s
360
- - Test count: 3,333 3,992 (+659 new tests across 178 suites)
361
-
362
- ### Fixed
363
- - **Pre-release audit cleanup** — Deduplicated formatter helpers, strengthened secrets regex, fixed compliance mapper edge cases, added NaN guards
364
- - **Boot timeout** — Vultr/Linode provision no longer times out due to fixed 30s polling
365
-
366
- ## [1.9.1] - 2026-03-15
367
-
368
- ### Security
369
- - **Socket.dev alert fixes** — Resolved 3 supply-chain alerts on npm:
370
- - `curl|bash` update commands moved from `constants.ts` into adapter files (eliminates obfuscated code alert)
371
- - `child_process` import removed from `deploy.ts` uses `removeStaleHostKey()` utility instead
372
- - `globalThis["fetch"]` false positive documented in SOCKET_JUSTIFICATION.md
373
-
374
- ## [1.9.0] - 2026-03-15
375
-
376
- ### Fixed
377
- - **doctor --fix apt hang** — `DEBIAN_FRONTEND=noninteractive` prefix added to apt fix commands over SSH, preventing interactive prompts on headless servers
378
- - **restore --force bypass** — `--force` flag now auto-selects the latest backup without prompting when `--backup` is not specified
379
- - **README codecov badge** — Replaced broken codecov.io badge URL with shields.io integration for reliable rendering with logo
380
-
381
- ### Security
382
- - **Notify token keychain migration** — Notification tokens (Telegram/Discord/Slack) moved from plain-text config to OS keychain storage with secure file-backed fallback for headless environments
383
- - **SSH command builder** — New `SshCommand` branded type with `cmd()`/`raw()` builders and POSIX `shellEscape()` — eliminates string concatenation injection risk across 11 core modules
384
-
385
- ### Changed
386
- - **MCP SDK isolation** — Dynamic `import()` boundary ensures non-MCP commands (`status`, `fleet`, `audit`, etc.) never load MCP SDK's 179 transitive dependencies
387
- - **execSync spawnSync migration** — Shell invocation eliminated from `ssh.ts` and `doctor.ts`, closing Socket.dev shell alert
388
- - **MCP handler decomposition** — `serverSecure` (10 handlers) and `serverBackup` (6 handlers) extracted to colocated handler modules with 63 new unit tests
389
- - **Quality audit fixes** — 16 code quality findings resolved: layer violations, duplication, naming consistency, constant extraction
390
- - Test count: 3,175 → 3,333 (+158 new tests)
391
-
392
- ## [1.8.1] - 2026-03-15
393
-
394
- ### Added
395
- - **Interactive menu complete** All missing commands added to interactive menu: fleet, audit, lock, evidence, guard, doctor, backup-list, notify, completions with sub-prompts and emoji categories
396
- - **`--force` flag**Added to 7 CLI commands (backup, secure, lock, domain, update, maintain, evidence) for non-interactive/CI usage
397
- - **`backup list` CLI command** List all local backups (previously MCP-only)
398
- - **Dokploy domain support** — CLI domain commands (add, remove, list, info) now work with Dokploy servers
399
- - **`platformDefaults()` helper** — Eliminates repeated platform ternaries in domain/restart commands
400
- - **Domain completions** — Added `list` and `info` to domain subcommands in bash/zsh/fish
401
-
402
- ### Fixed
403
- - **Dokploy backup/restore** — Fixed `-U postgres` `-U dokploy` (role "postgres" does not exist)
404
- - **Restart message** — Now shows correct platform name and port (Dokploy:3000 vs Coolify:8000)
405
- - **MCP mode detection** — `resolvePlatform()` used in MCP serverInfo (mode now correctly shows "dokploy")
406
- - **MCP serverManage** — Added "dokploy" to mode enum
407
-
408
- ### Changed
409
- - Interactive doctor prompt: `--check-tokens` `--fresh`
410
- - Interactive backup prompt: confirm dialog sub-menu (create/all)
411
- - MCP version metadata added to all tool responses
412
-
413
- ## [1.8.0] - 2026-03-15
414
-
415
- ### Added
416
- - **Fleet Visibility** (`kastell fleet`) — Parallel health check across all servers with status table (online/degraded/offline), audit scores, response times. `--json` for structured output
417
- - **Notification Module** (`kastell notify`) — Multi-channel alert dispatch: webhook, Slack, Discord, email (SMTP). `kastell notify add-channel` + `kastell notify test`
418
- - **Guard Notification Integration** — Guard breach alerts automatically dispatched via configured notification channels with severity categorization
419
- - **Doctor --fix** (`kastell doctor --fix`) Interactive auto-remediation for doctor findings. Per-finding confirm gate, `--force` to skip prompts, `--dry-run` to preview. Whitelisted fix commands only
420
- - **MCP server_fleet tool** Fleet visibility exposed via MCP (list all servers with health/audit status)
421
- - **Shell completions updated** fleet, notify, audit, evidence commands and all v1.8 flags added to bash/zsh/fish generators
422
-
423
- ### Security
424
- - **OWASP review** — 8 security fixes: evidence path traversal (H-01), evidence lines sanitize (H-02), webhook SSRF protection (M-01), guard stale comment fix (M-03), doctor fix whitelist (M-04), metrics file permission (L-03), audit history file permission (L-04), backup restore safe mode guard (I-01)
425
- - 8 code quality improvements: notify DRY (sendHttp), Promise.all optimization, channel validation, guard version tracking, firewall platform messages, secure score DRY, default audit constants, IP validation consolidation
426
-
427
- ### Changed
428
- - **Architecture**: Layer violation fix — `firewallSetup` and `secureSetup` moved from `commands/` to `core/`
429
- - **Architecture**: Adapter deduplication`sharedCreateBackup` and `sharedRestoreBackup` extracted to `src/adapters/shared.ts`
430
- - **Architecture**: PostSetup decomposed into `barePostSetup` + `platformPostSetup`
431
- - Platform name capitalized in restore backup step labels (e.g., "coolify" → "Coolify")
432
- - Removed `.planning/` from git tracking (was leaking internal planning files)
433
- - Test count: 3,038 3,175 (+137 new tests)
434
- - MCP tools: 12 → 13 (server_fleet added)
435
-
436
- ## [1.7.0] - 2026-03-14
437
-
438
- ### Added
439
- - **Server Lock** (`kastell lock`) One-command production hardening: SSH key-only auth, fail2ban, UFW firewall, sysctl hardening, unattended-upgrades. Shows audit score before/after. `--dry-run` preview, `--force` for already-hardened servers
440
- - **Backup Schedule** (`kastell backup --schedule`) Cron-based automatic backups via SSH crontab. Supports `--schedule hourly|daily|weekly|custom` with custom cron expressions
441
- - **Guard Daemon** (`kastell guard start|stop|status`) — Autonomous security monitoring via remote cron. Checks disk/RAM/CPU/audit every 5 minutes with threshold breach detection
442
- - **Risk Trend** (`kastell audit --trend`) — Audit score trend analysis over time. `--days N` to control window. Terminal and JSON output formats
443
- - **Doctor (Server Mode)** (`kastell doctor <server>`) — Per-server proactive health analysis: disk trending, high swap, stale packages, fail2ban bans, audit regression, old backups, reclaimable Docker space. `--fresh` for live SSH data, `--json` for structured output
444
- - **3 new MCP tools**: `server_guard` (start/stop/status), `server_doctor` (summary/json), `server_lock` (dry-run/production/force)
445
- - **Shell completions**: guard, lock, doctor flags added for bash/zsh/fish
446
-
447
- ### Security
448
- - **OWASP review**: 10 security and quality fixes sanitized error paths, hardened input validation, tightened type guards
449
- - **Dependency fix**: flatted 3.3.3 3.4.1 (unbounded recursion DoS)
450
-
451
- ### Fixed
452
- - CLI `list`/`status` now shows actual platform label (dokploy/coolify/bare) instead of generic "mode"
453
- - `--force` flag added to secure/update CLI commands
454
- - MCP evidence `force` parameter passthrough
455
-
456
- ### Changed
457
- - Test count: 2,467 → 3,038 (+571 new tests)
458
- - MCP tools: 9 → 12 (server_guard, server_doctor, server_lock added)
459
-
460
- ## [1.6.0] - 2026-03-11
461
-
462
- ### Added
463
- - **Audit Snapshots** (`kastell audit --snapshot`) — Persist audit results as timestamped JSON snapshots. `--snapshots` to list saved snapshots
464
- - **Audit Diff** (`kastell audit --diff <id>`, `--compare <id1> <id2>`) — Compare audit results between snapshots. Shows category-level score changes and new/fixed findings
465
- - **Evidence Collection** (`kastell evidence <server>`) — Forensic evidence package: firewall rules, auth.log, listening ports, system logs, Docker info. SHA256 checksums per file. Written to `~/.kastell/evidence/{server}/{date}/`
466
- - **MCP server_evidence tool** — Evidence collection exposed via MCP
467
- - **Adapter contract conformance tests**Verify PlatformAdapter interface compliance
468
- - **Infrastructure utilities**: `withRetry` (exponential backoff for provider API calls), `withFileLock` (file-based mutex for config writes)
469
- - **Provider retry integration** — All provider GET methods wrapped with `withRetry`
470
- - **Config lock integration** — All config writes protected with `withFileLock`
471
- - **Mode migration** — Automatic `ServerMode` field addition to legacy server records
472
-
473
- ### Security
474
- - Consolidated IP validation, removed dead code, hardened security paths
475
- - Auth keyring: replaced top-level await with lazy require (fixes non-interactive environments)
476
-
477
- ### Fixed
478
- - Evidence dynamic section-to-filename mapping prevents index mismatch bug
479
- - Linode test mocks updated to use Error instances for `withProviderErrorHandling`
480
-
481
- ### Changed
482
- - Deduplicated provider error handling into `withProviderErrorHandling` + `extractApiMessage`
483
- - Test count: 2,2662,467 (+201 new tests)
484
- - MCP tools: 89 (server_evidence added)
485
-
486
- ## [1.5.2] - 2026-03-09
487
-
488
- ### Fixed
489
- - **Phase 2 code review**: 30 bug fixes across critical, high, medium, and low severity (3C+8H+14M+5L) provider validation, error handling, type safety improvements
490
- - **Phase 1 remaining fixes**: 15 files provider validation hardening, audit check corrections, backup safety guards
491
-
492
- ### Changed
493
- - **CI**: Automatic GitHub Release workflow on tag push
494
- - **Docs (TR)**: Security audit section, MCP server_audit, CI pipeline example added to Turkish README
495
-
496
- ## [1.5.1] - 2026-03-08
497
-
498
- ### Fixed
499
- - **Dokploy update command**: Install script now called with `update` argument — previously ran fresh-install mode which failed on port 80/443 conflict with running Dokploy instance
500
- - 5 Dokploy integration bugs found during real-server testing (health check port, firewall ports, backup paths, restore commands, version detection)
501
-
502
- ## [1.5.0] - 2026-03-08
503
-
504
- ### Added
505
- - **Security audit system**: `kastell audit` command with 9 check categories (SSH, auth, firewall, Docker, kernel, filesystem, network, logging, updates), scoring 0-100, terminal/JSON/summary/badge formatters
506
- - **Audit history**: `kastell audit --history` tracks score trends over time with comparison
507
- - **Audit watch mode**: `kastell audit --watch` monitors security score changes on interval
508
- - **Audit quick wins**: `kastell audit --quick-wins` suggests highest-impact fixes
509
- - **Audit auto-fix**: `kastell audit --fix` applies safe remediations automatically
510
- - **MCP server_audit tool**: Full audit capabilities exposed via MCP (summary/json/score formats)
511
- - **Token buffer**: In-memory token protection with controlled exposure window
512
- - **Platform auto-detection**: SSH-based `detectPlatform()` checks filesystem markers for Dokploy/Coolify/bare
513
-
514
- ### Changed
515
- - Test count: 2,266 2,467 (+201 new tests)
516
- - Test suites: 86 112 (+26 new suites)
517
- - MCP tools: 7 8 (server_audit added)
518
-
519
- ## [1.4.0] - 2026-03-08
520
-
521
- ### Added
522
- - **CLI header**: Gradient ASCII banner with cyan-to-blue color scheme, version info bar, and quick-start command examples on interactive mode launch
523
- - **Shell completions**: `kastell completions bash|zsh|fish` generates shell completion scripts for tab-completion
524
- - **Config validation**: `kastell config validate` checks `servers.yaml` for structural and type errors using Zod strict schemas
525
- - **Version check**: `kastell --version` now notifies if a newer version is available on npm
526
- - **Dry-run support**: Added `--dry-run` flag to `destroy`, `remove`, `backup`, `snapshot`, and `secure` commands
527
- - **Dokploy lifecycle**: Full Dokploy adapter with update, maintain, logs, health, backup, and restore support
528
- - **Platform adapters**: `src/adapters/` architecture Coolify and Dokploy adapters implement `PlatformAdapter` interface
529
-
530
- ### Changed
531
- - Interactive menu no longer uses figlet — replaced with custom gradient ASCII art header
532
- - `PROVIDER_REGISTRY` centralized in `src/constants.ts` as single source of truth
533
- - Test count: 2,099 → 2,266 (+167 new tests)
534
- - Test suites: 7886 (+8 new suites)
535
-
536
- ## [1.3.1] - 2026-03-05
537
-
538
- ### Changed
539
- - **Metadata update**: Package description, keywords, and homepage updated for Kastell branding
540
- - **Repository references**: All internal references updated from `omrfc/kastell` to `kastelldev/kastell`
541
-
542
- ## [1.3.0] - 2026-03-05
543
-
544
- ### Breaking Changes
545
- - **Package renamed**: `quicklify` is now `kastell` on npm. Install with `npm install -g kastell`
546
- - **Binary renamed**: `quicklify` CLI is now `kastell`, `quicklify-mcp` is now `kastell-mcp`
547
- - **License changed**: MIT -> Apache License 2.0 (patent protection added)
548
-
549
- ### Added
550
- - **Config migration**: Automatic migration from `~/.quicklify` to `~/.kastell` on first run (copies entire directory, `.migrated` flag prevents re-migration)
551
- - **NOTICE file**: Apache 2.0 attribution notice added
552
-
553
- ### Changed
554
- - **Package identity**: name `kastell`, version `1.3.0`, homepage `https://kastell.dev`
555
- - **Environment variable**: `KASTELL_SAFE_MODE` is now the primary env var for MCP safe mode. `QUICKLIFY_SAFE_MODE` still works with a one-time deprecation warning (backward compat until v2.0)
556
- - **Internal types**: `QuicklifyYamlConfig` -> `KastellYamlConfig`, `QuicklifyConfig` -> `KastellConfig`, `QuicklifyResult` -> `KastellResult`
557
- - **Config directory**: `~/.quicklify/` -> `~/.kastell/` (automatic migration on first run)
558
- - **SSH key prefix**: `quicklify-` -> `kastell-` for auto-generated SSH keys
559
- - **Snapshot prefix**: `quicklify-` -> `kastell-` for new snapshots (existing `quicklify-*` snapshots still recognized via dual-prefix filter)
560
- - **Export filename**: Default export changed from `quicklify-export.json` to `kastell-export.json`
561
- - **Update check**: Now queries `registry.npmjs.org/kastell/latest`
562
- - **All documentation**: README.md, README.tr.md, SECURITY.md, CONTRIBUTING.md, llms.txt updated to Kastell branding
563
- - **Example config**: `quicklify.yml` renamed to `kastell.yml`
564
- - **MCP config**: Server name changed from `quicklify` to `kastell`
565
-
566
- ### Deprecated
567
- - `quicklify` npm package (will show deprecation notice pointing to `kastell`)
568
- - `QUICKLIFY_SAFE_MODE` env var (use `KASTELL_SAFE_MODE` instead, removed in v2.0)
569
-
570
- ## [1.2.1] - 2026-03-02
571
-
572
- ### Security
573
- - **CRITICAL FIX**: `stripSensitiveData()` now sanitizes `error.response.data` and `error.response.headers` prevents API tokens, rootPass, and other sensitive data from leaking via error cause chains
574
- - Whitelist-based `sanitizeResponseData()` preserves only known error message fields (Hetzner `error.message`, DigitalOcean `message`, Vultr `error`, Linode `errors[].reason`)
575
- - Response headers cleared to prevent `set-cookie` and tracking header exposure
576
- - Linode `root_pass` reflection in error responses now stripped
577
-
578
- ### Changed
579
- - **Refactoring**: Extracted `init.ts` command logic into `src/core/deploy.ts` (619 → 243 lines)
580
- - **Refactoring**: `PROVIDER_REGISTRY` centralized in `src/constants.ts` — single source of truth for provider metadata
581
- - **Refactoring**: `stripSensitiveData()` consolidated from 4 provider files into `src/providers/base.ts`
582
- - **Security**: SCP path hardening via `assertSafePath()` with shell metacharacter rejection
583
- - **Security**: Token sanitization via `sanitizedEnv()` applied to all remaining child process calls
584
- - Test count: 2,0472,099 (+52 new tests)
585
- - Test suites: 76 → 78 (+2 new suites)
586
-
587
- ## [1.2.0] - 2026-03-01
588
-
589
- ### Added
590
- - **Bare Mode** Generic VPS support without Coolify (`--mode bare` on init/add)
591
- - `ServerRecord.mode` field: `"coolify"` (default) or `"bare"`
592
- - `requireCoolifyMode()` guard blocks Coolify-only operations on bare servers
593
- - `getBareCloudInit()` — hardening-only cloud-init script (UFW + system updates)
594
- - Bare mode support across all 23 CLI commands and 7 MCP tools
595
- - 2GB RAM minimum removed for bare mode provisioning
596
- - Backward compatibility: legacy records without `mode` field default to `"coolify"`
597
- - **Interactive Menu** Run `quicklify` without arguments for a categorized menu
598
- - 6 categories: Server Management, Security, Monitoring & Logs, Backup & Snapshots, Maintenance, Configuration
599
- - Sub-option prompts for each action (mode, template, log source, port, etc.)
600
- - `← Back` navigation to return to main menu at any point
601
- - 49 new tests (`interactive.test.ts`)
602
- - **MCP `sizes` action** — `server_info` tool now supports listing available server types with prices per provider/region
603
- - **MCP shared utilities** — `src/mcp/utils.ts` with `resolveServerForMcp`, `mcpSuccess`, `mcpError`
604
- - **SSH host key auto-fix** `removeStaleHostKey()` helper auto-removes stale known_hosts entries
605
- - Health command detects host key mismatch and suggests fix
606
- - SSH retry mechanism after stale key removal
607
- - **UX improvements** (6 enhancements):
608
- - Better dpkg lock messaging during provisioning
609
- - Token source display (env var vs prompt)
610
- - Firewall status shows current rules inline
611
- - Domain info shows current FQDN
612
- - Orphan backup cleanup
613
- - Backup/restore shows provider + IP context
614
-
615
- ### Security
616
- - **OWASP hardening**: `assertSafePath()` for SCP paths (shell metacharacter check including `<>`)
617
- - **Port validation**: MCP port range restricted to 1-65535
618
- - **Token isolation**: `sanitizedEnv()` applied to all `spawn`/`exec`/`spawnSync` calls including `openBrowser`, `sshKey`, and `removeStaleHostKey`
619
- - **SECURITY.md**: Added OWASP Top 10 compliance table with detailed mitigation descriptions
620
-
621
- ### Fixed
622
- - Init `--full-setup` crash on bare mode servers
623
- - Domain `--name` flag ignored on bare mode
624
- - Cloud-init completion wait missing
625
- - Bare mode showing incorrect port information
626
- - Health command missing query argument
627
- - Restart bare mode "command not found" message
628
- - MCP SSH path incorrect during provision
629
-
630
- ### Changed
631
- - Test count: 1,758 2,047 (+289 new tests)
632
- - Test suites: 64 76 (+12 new suites)
633
- - Banner slogan updated to "Self-hosting, fully managed"
634
- - README interactive menu documentation with example output
635
- - LICENSE name correction: "omrfc""Ömer Faruk CAN"
636
- - `.gitignore`: added `servers.json`
637
-
638
- ## [1.1.0] - 2026-02-27
639
-
640
- ### Added
641
- - **MCP Server** Built-in Model Context Protocol server for AI-powered server management with 7 tools:
642
- - `server_info` `list`, `status`, `health` (readOnly)
643
- - `server_logs` — `logs`, `monitor` (readOnly)
644
- - `server_manage` `add`, `remove`, `destroy` (destructive, SAFE_MODE on destroy)
645
- - `server_maintain` `update`, `restart`, `maintain`
646
- - `server_secure` `secure-setup`, `secure-audit`, `firewall-setup`, `firewall-add`, `firewall-remove`, `firewall-status`, `domain-set`, `domain-remove`, `domain-check`, `domain-info`
647
- - `server_backup``backup-create`, `backup-list`, `backup-restore`, `snapshot-create`, `snapshot-list`, `snapshot-delete` (SAFE_MODE on restore/delete)
648
- - `server_provision` `create` (destructive, SAFE_MODE creates billable cloud resources)
649
- - Structured JSON responses with `suggested_actions` for AI context optimization
650
- - Tool annotations: `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`
651
- - Rate limiting guidance in tool descriptions
652
- - SAFE_MODE guards on destructive operations (provision, destroy, restore, snapshot-delete)
653
- - **`src/core/` module** — Pure business logic extracted from CLI commands (no CLI dependencies)
654
- - `status.ts` — `checkCoolifyHealth`, `getCloudServerStatus`, `checkServerStatus`, `checkAllServersStatus`
655
- - `tokens.ts` `getProviderToken`, `collectProviderTokensFromEnv` (non-interactive token resolution)
656
- - `secure.ts` — SSH hardening + audit (pure functions + async wrappers)
657
- - `firewall.ts` UFW management (pure functions + async wrappers)
658
- - `domain.ts` FQDN/DNS management (pure functions + async wrappers)
659
- - `backup.ts` Backup/restore (20 pure functions + SCP helpers)
660
- - `snapshot.ts` Snapshot create/list/delete + cost estimate
661
- - `provision.ts` Server provisioning (13-step flow: validate → token → SSH → cloudInit → create → boot → IP → save)
662
- - **`src/mcp/` module** — MCP server implementation
663
- - `src/mcp/server.ts` MCP server setup with 7 tool registrations
664
- - `src/mcp/tools/` — 7 tool handlers (serverInfo, serverLogs, serverManage, serverMaintain, serverSecure, serverBackup, serverProvision)
665
- - `src/mcp/index.ts` — stdio transport entry point
666
- - `bin/quicklify-mcp` MCP server binary entry point
667
- - SSRF defense: `assertValidIp()` added to `checkCoolifyHealth` (IP format validation before HTTP request)
668
- - Stack trace sanitization in MCP error responses via `getErrorMessage()`
669
-
670
- ### Security
671
- - **Path traversal protection**: `backupId` validated with Zod regex (`/^[\w-]+$/`) + `path.resolve()` guard in restore
672
- - **SAFE_MODE enforcement**: Added `isSafeMode()` guards on `restart`, `maintain`, and `snapshot-create` MCP actions
673
- - **IP validation hardened**: `assertValidIp()` now validates octet range (0-255), IP removed from error messages
674
- - **stderr sanitization**: New `sanitizeStderr()` function redacts IPs, home paths, tokens, secrets (200 char limit) — applied to all backup/restore/logs error output
675
- - **Port validation**: MCP `server_secure` port restricted to `z.number().min(1).max(65535)`
676
- - **Provider enum validation**: MCP `server_manage` provider changed from `z.string()` to `z.enum()` (prevents invalid provider injection)
677
- - **Manifest hardening**: `serverIp` field removed from `BackupManifest` type, manifest files written with `mode: 0o600`
678
- - **SCP IP validation**: `assertValidIp()` added to `scpDownload()` and `scpUpload()` before spawning child process
679
- - **Log redaction**: `manage.ts` stderr no longer exposes server IP address
680
- - **SSH key auto-generation**: `provision` now auto-generates SSH key when none exists (instead of skipping)
681
- - `.mcp.json` added to `.gitignore` (contains local absolute paths)
682
-
683
- ### Changed
684
- - `src/commands/status.ts` refactored to use `src/core/status.ts` (DRY: eliminated duplicate Coolify health check)
685
- - Test count: 13691758 (+389 new tests across 9 new test suites)
686
- - Test suites: 55 → 64
687
-
688
- ### Dependencies
689
- - Added `@modelcontextprotocol/sdk` ^1.27.1 (MCP server SDK)
690
- - Added `zod` ^4.3.6 (MCP input schema validation)
691
-
692
- ## [1.0.5] - 2026-02-26
693
-
694
- ### Added
695
- - `mapSshError` — 10 SSH error patterns mapped to actionable hints (connection refused, permission denied, host key, timeout, reset, hostname, command not found, disk full, broken pipe)
696
- - `mapFileSystemError` — 4 filesystem error codes mapped to hints (ENOENT, EACCES, EPERM, ENOSPC)
697
- - `getErrorMessage` — DRY helper replacing `error instanceof Error ? error.message : String(error)` across 15 command files
698
-
699
- ### Changed
700
- - All 53 catch blocks now use appropriate error mappers: Provider API → `mapProviderError`, SSH → `mapSshError`, Filesystem → `mapFileSystemError`
701
- - `mapProviderError` spread to 5 additional files (restart, maintain, status, update, snapshot)
702
- - 3 silent catches in backup.ts now log error messages and provide SSH hints
703
- - Test count: 1334 1369 (+35 new error hint integration tests)
704
-
705
- ## [1.0.4] - 2026-02-25
706
-
707
- ### Security
708
- - Restore rollback: automatically restart Coolify if restore steps 3-5 fail after Coolify was stopped
709
- - Fail2ban warning: show "partially complete" instead of misleading "complete" when fail2ban fails
710
- - SSH key warnings: stronger guidance to run `quicklify secure setup` when key generation/upload fails
711
-
712
- ## [1.0.3] - 2026-02-25
713
-
714
- ### Added
715
- - `doctor --check-tokens` — Validate provider API tokens from environment variables against live APIs (Hetzner, DigitalOcean, Vultr, Linode)
716
- - Update notification Check npm registry for newer versions (24h cache, non-blocking)
717
- - Auto-open browser Automatically open Coolify dashboard after successful `init` deployment (platform-aware, `--no-open` to disable)
718
- - Error mapper Actionable error messages with provider-specific URLs for billing, token management, and troubleshooting
719
-
720
- ### Changed
721
- - Init onboarding Improved post-deployment "What's Next?" guide with numbered steps and copy-paste commands
722
- - README slogan updated to "Self-hosting made simple" (platform-agnostic)
723
- - CONTRIBUTING.md completely rewritten to reflect current project state (22 commands, 5 providers, 13 utils)
724
-
725
- ### Documentation
726
- - `llms.txt` AI-friendly project documentation with architecture, commands, and workflows
727
-
728
- ## [1.0.2] - 2026-02-24
729
-
730
- ### Security
731
- - Sanitize error cause chains to prevent API token leakage in all provider errors
732
- - Mask process title when `--token` flag is used
733
- - Replace `execSync` with `spawnSync` for ssh-keygen (prevent shell injection)
734
- - Add shell-safe assertions to domain FQDN and DNS check commands
735
- - Case-insensitive + nested security key detection in YAML config
736
- - Strip unknown fields from imported server data
737
- - Add IP address format validation to all SSH functions
738
- - Filter sensitive environment variables from child processes
739
- - Add `StrictHostKeyChecking` to interactive SSH connections
740
- - Set file permissions (`0o600`) on export files
741
- - Set directory permissions (`0o700`) on backup directories
742
- - Add Vultr and Linode to default provider validation
743
- - Clear `error.config.data` on Linode API failures (rootPass protection)
744
-
745
- ## [1.0.1] - 2026-02-24
746
-
747
- ### Added
748
- - `quicklify snapshot create/list/delete` — VPS snapshot management with cost estimates
749
- - Maintain integration: automatic snapshot offer before maintenance (with cost estimate)
750
- - `sshKey.test.ts` dedicated tests for SSH key utilities (13 tests)
751
- - Provider snapshot support for Hetzner, DigitalOcean, Vultr, and Linode
752
-
753
- ### Fixed
754
- - **domain.ts**: SQL escape for FQDN values (defense-in-depth against SQL injection)
755
- - **restore.ts**: Path traversal protection with `basename()` for `--backup` flag
756
- - **yamlConfig.ts**: Expanded security key detection (6 → 21 patterns including password, credential, jwt, bearer, etc.)
757
-
758
- ## [1.0.0] - 2026-02-23
759
-
760
- ### Added
761
- - **Vultr provider** (`src/providers/vultr.ts`) - Full Vultr API v2 integration
762
- - Base64-encoded user_data for cloud-init
763
- - SSH key upload with HTTP 409 conflict handling
764
- - OS: Ubuntu 24.04 (os_id: 2284)
765
- - Power status normalization (running/stopped)
766
- - **Linode (Akamai) provider** (`src/providers/linode.ts`) - Full Linode API v4 integration
767
- - Auto-generated root_pass via `crypto.randomBytes()`
768
- - SSH key upload via `/profile/sshkeys`
769
- - Metadata user_data for cloud-init (base64)
770
- - Disk size conversion (MB → GB)
771
- - **`quicklify add`** command - Register existing Coolify servers to Quicklify management
772
- - Interactive flow: provider token IP → verify Coolify → save
773
- - Non-interactive: `--provider`, `--ip`, `--name`, `--skip-verify` flags
774
- - Coolify verification via SSH (health check or `docker ps`)
775
- - Duplicate detection by IP address
776
- - **`quicklify maintain [query]`** command - Full maintenance cycle
777
- - 6-step flow: snapshot warning → status check → Coolify update → health check → reboot → final check
778
- - `--skip-reboot` to skip the reboot step
779
- - `--all` to maintain all servers sequentially
780
- - `--dry-run` to preview maintenance steps
781
- - **`quicklify remove [query]`** command - Remove a server from local config without destroying the cloud server
782
- - Accepts server name or IP address
783
- - Confirmation prompt before removal
784
- - **`--all` flag** on `status`, `update`, `backup` commands
785
- - `status --all`: parallel status check with table output (Promise.all)
786
- - `update --all`: sequential update with single confirmation prompt
787
- - `backup --all`: sequential backup across all servers
788
- - **`status --autostart`** flag - Restarts Coolify via SSH if server is running but Coolify is down
789
- - Uses `docker compose restart coolify` command
790
- - Waits 5 seconds and verifies Coolify came back up
791
- - **`collectProviderTokens()`** utility - Deduplicates token prompts per unique provider across servers
792
- - `VULTR_TOKEN` and `LINODE_TOKEN` environment variable support
793
- - Vultr and Linode defaults in all 3 templates (starter, production, dev)
794
- - `"vultr"` and `"linode"` in YAML config validation
795
- - 195 new tests across 6 new test files + enhanced existing test files
796
-
797
- ### Changed
798
- - Provider selection now shows 4 choices: Hetzner Cloud, DigitalOcean, Vultr, Linode (Akamai)
799
- - Provider factory supports `"vultr"` and `"linode"` cases
800
- - Total commands: 19 23 (add, maintain, remove + maintain --all)
801
- - Test count: 742 937
802
- - Test suites: 40 → 44
803
- - Coverage: 98%+ statements, 91%+ branches, 98%+ functions
804
- - Zero new npm dependencies added
805
-
806
- ## [0.9.0] - 2026-02-21
807
-
808
- ### Added
809
- - **`--config <path>`** flag on `quicklify init` - Load deployment parameters from a YAML config file
810
- - Supports all init options: provider, region, size, name, fullSetup, template, domain
811
- - Validates config with detailed warnings for invalid values
812
- - Security: detects and warns about token fields in config files
813
- - Handles missing files and invalid YAML syntax gracefully
814
- - **`--template <name>`** flag on `quicklify init` - Use predefined server templates
815
- - `starter` - Minimal setup (cheapest option, no hardening)
816
- - `production` - Production-ready (larger server, auto firewall + SSH hardening)
817
- - `dev` - Development/testing (cheap, no hardening)
818
- - Per-provider defaults: Hetzner and DigitalOcean have optimized region/size pairs
819
- - **Config merge system** with priority: CLI flags > YAML config > template defaults > interactive prompts
820
- - `QuicklifyYamlConfig`, `TemplateName`, `TemplateDefinition` TypeScript interfaces
821
- - `src/utils/templates.ts` - Template definitions with per-provider defaults
822
- - `src/utils/yamlConfig.ts` - YAML config loader with validation and security checks
823
- - `src/utils/configMerge.ts` - Multi-source config merge logic
824
- - 106 new tests across 4 new test files (templates, yamlConfig, configMerge, init-config E2E)
825
-
826
- ### Changed
827
- - `InitOptions` interface extended with `config` and `template` fields
828
- - `initCommand()` now processes YAML config and template before main flow
829
- - Total commands: 19 (unchanged)
830
- - Test count: 636 742
831
- - Test suites: 36 40
832
- - Coverage: 98%+ statements, 91%+ branches, 98%+ functions
833
-
834
- ### Dependencies
835
- - Added `js-yaml` (runtime) + `@types/js-yaml` (dev) - YAML parsing
836
-
837
- ## [0.8.0] - 2026-02-21
838
-
839
- ### Added
840
- - **`quicklify backup [query]`** command - Backup Coolify database and config files
841
- - `pg_dump` + gzip for PostgreSQL database backup
842
- - Config tarball (`.env`, `docker-compose.yml`, `docker-compose.prod.yml`)
843
- - SCP download to `~/.quicklify/backups/{server-name}/{timestamp}/`
844
- - `manifest.json` with server info, Coolify version, file list
845
- - `--dry-run` flag to preview backup steps
846
- - **`quicklify restore [query]`** command - Restore Coolify from a backup
847
- - Interactive backup selection from available backups
848
- - `--backup <timestamp>` flag to skip selection prompt
849
- - Double confirmation safety (confirm + type server name)
850
- - Full restore flow: uploadstop Coolify start DB restore DB → restore config → start Coolify
851
- - `--dry-run` flag to preview restore steps
852
- - **`quicklify export [path]`** command - Export server list to JSON file
853
- - Default path: `./quicklify-export.json`
854
- - Custom path: `quicklify export /path/to/file.json`
855
- - **`quicklify import <path>`** command - Import servers from JSON file
856
- - Format validation with field-level checking
857
- - Duplicate detection by server ID (skips existing)
858
- - **`--full-setup` flag** on `quicklify init` - Auto-configure firewall + SSH hardening after deploy
859
- - Runs `firewallSetup()` + `secureSetup(force=true)` after Coolify health check
860
- - Skips interactive confirmations in automated mode
861
- - `BackupManifest` TypeScript interface
862
- - `BACKUPS_DIR` config constant (`~/.quicklify/backups/`)
863
- - `validateServerRecords()` pure function for import validation
864
- - `scpDownload()` and `scpUpload()` SCP helpers using `spawn`
865
- - `loadManifest()` and `listBackups()` backup utility functions
866
- - Pure command builder functions for all backup/restore SSH operations
867
- - 137 new tests across 4 new test files + 6 enhanced test files
868
- - Provider test coverage: uploadSshKey, rebootServer, createServer with sshKeyIds
869
- - Doctor, monitor, restart, status, healthCheck, ssh edge case coverage
870
-
871
- ### Changed
872
- - `firewallSetup()` now exported from `firewall.ts` (was private)
873
- - `secureSetup()` now exported from `secure.ts` with `force` parameter to skip prompts
874
- - Total commands: 15 19 (backup, restore, export, import)
875
- - Test count: 499 → 636
876
- - Test suites: 32 → 36
877
- - Coverage: 98%+ statements, 90%+ branches, 98%+ functions
878
- - Zero new npm dependencies added
879
-
880
- ## [0.7.2] - 2026-02-21
881
-
882
- ### Added
883
- - **Auto SSH key upload** during `quicklify init` — detects local SSH key (`~/.ssh/id_ed25519.pub`, `id_rsa.pub`, `id_ecdsa.pub`) and uploads to provider (DigitalOcean/Hetzner) automatically. Eliminates password requirement on first SSH login
884
- - **Auto SSH key generation** — if no SSH key exists, generates ed25519 key pair automatically
885
- - **Local config cleanup on destroy failure** — when `quicklify destroy` fails (server already deleted), prompts to remove from local config
886
-
887
- ### Fixed
888
- - **Fail2ban heredoc bug** — heredoc delimiter was not recognized when joined with `&&` chain, causing invalid config file and fail2ban crash. Replaced with `printf`
889
- - **Fail2ban systemd backend** — added `python3-systemd` package (required for `backend = systemd` on Ubuntu)
890
-
891
- ## [0.7.1] - 2026-02-20
892
-
893
- ### Fixed
894
- - **Domain command rewritten for Coolify v4** - Uses PostgreSQL `instance_settings` table instead of `.env` APP_URL
895
- - Domain add now uses `docker compose -f docker-compose.yml -f docker-compose.prod.yml restart` (fixes compose error)
896
- - Coolify existence check uses `docker ps` container check instead of `.env` file check
897
- - DNS check fallback to `getent ahosts` (works on servers without `dig`/`dnsutils`)
898
- - SSH restart compatibility: fallback `systemctl restart ssh` for Ubuntu/Debian (was `sshd` only)
899
-
900
- ## [0.7.0] - 2026-02-20
901
-
902
- ### Added
903
- - **`quicklify firewall [subcommand]`** command - Manage server firewall (UFW)
904
- - `setup` - Install UFW + configure Coolify ports (80, 443, 8000, 6001, 6002) + SSH (22)
905
- - `add` - Open a port (`--port`, `--protocol tcp|udp`)
906
- - `remove` - Close a port (port 22 protected, Coolify ports warn before removal)
907
- - `list` - Show current firewall rules
908
- - `status` - Check UFW active/inactive state
909
- - **`quicklify domain [subcommand]`** command - Manage server domain and SSL
910
- - `add` - Bind domain to Coolify (`--domain`, `--no-ssl` to disable HTTPS)
911
- - `remove` - Remove domain, revert to IP:8000
912
- - `check` - Verify DNS A record matches server IP
913
- - `list` - Show current APP_URL configuration
914
- - **`quicklify secure [subcommand]`** command - SSH hardening and fail2ban
915
- - `setup` - Disable password auth, set root login to key-only, install fail2ban (requires SSH key check + double confirmation)
916
- - `status` - Show current SSH security settings
917
- - `audit` - Detailed security report with score (0-4)
918
- - `--dry-run` flag on all three commands - Preview commands without executing
919
- - Protected port system: port 22 cannot be removed via `firewall remove`
920
- - Coolify port warnings: removing ports 80/443/8000/6001/6002 requires confirmation
921
- - SSH key safety check: `secure setup` refuses to run if no authorized_keys found
922
- - Pure functions for all commands (unit-testable): `isValidPort`, `isProtectedPort`, `buildUfwRuleCommand`, `parseUfwStatus`, `isValidDomain`, `sanitizeDomain`, `buildSetFqdnCommand`, `parseDnsResult`, `parseFqdn`, `parseSshdConfig`, `parseAuditResult`, `buildHardeningCommand`, `buildFail2banCommand`
923
- - `FirewallRule`, `FirewallStatus`, `SshdSetting`, `SecureAuditResult` TypeScript interfaces
924
- - 140 new tests across 3 test files (firewall, domain, secure)
925
-
926
- ### Changed
927
- - Total commands: 12 15
928
- - Test count: 354 494
929
- - Test suites: 29 → 32
930
- - Coverage maintained: 97%+ statements, 85%+ branches, 96%+ functions
931
- - Zero new npm dependencies added
932
-
933
- ## [0.6.0] - 2026-02-20
934
-
935
- ### Added
936
- - **`quicklify logs [query]`** command - View Coolify, Docker, or system logs via SSH
937
- - `--lines N` (default 50), `--follow` (real-time streaming), `--service coolify|docker|system`
938
- - **`quicklify monitor [query]`** command - Show CPU, RAM, Disk usage via SSH
939
- - `--containers` flag to display Docker container list
940
- - **`quicklify health`** command - Bulk health check of all registered servers
941
- - Parallel HTTP checks with response time measurement and table output
942
- - **`quicklify doctor`** command - Local environment diagnostics
943
- - Checks Node.js version, npm, SSH client, config directory, registered servers
944
- - `--check-tokens` flag for future provider token validation
945
- - `sshStream()` SSH helper - Spawns SSH with `stdio: "inherit"` for real-time log streaming
946
- - `parseMetrics()` pure function for parsing `top`/`free`/`df` output
947
- - `buildLogCommand()` pure function for service-to-command mapping
948
- - `checkServerHealth()` function for individual server HTTP health checks
949
- - 43 new tests across 5 test files (doctor, health-command, logs, monitor, ssh-utils)
950
-
951
- ### Changed
952
- - Test count: 311 → 354
953
- - Test suites: 25 29
954
- - Coverage maintained: 97%+ statements, 87%+ branches, 96%+ functions
955
- - Zero new npm dependencies added
956
-
957
- ## [0.5.0] - 2026-02-20
958
-
959
- ### Added
960
- - **`quicklify config`** command - Manage default configuration (`set`, `get`, `list`, `reset`)
961
- - **`quicklify ssh [query]`** command - SSH into a registered server (interactive or `--command` mode)
962
- - **`quicklify update [query]`** command - Update Coolify on a registered server via SSH
963
- - **`quicklify restart [query]`** command - Restart a server via provider API (Hetzner + DigitalOcean)
964
- - `rebootServer()` method on `CloudProvider` interface (Hetzner + DigitalOcean implementations)
965
- - Shared `resolveServer()` and `promptApiToken()` utilities (`src/utils/serverSelect.ts`)
966
- - Default config management via `~/.quicklify/config.json` (`src/utils/defaults.ts`)
967
- - SSH helper utilities: `checkSshAvailable()`, `sshConnect()`, `sshExec()` (`src/utils/ssh.ts`)
968
- - `QuicklifyConfig` TypeScript interface
969
- - 65 new tests across 7 new test files
970
- - SSH availability detection for Windows/Linux/macOS
971
-
972
- ### Changed
973
- - Extracted duplicate `selectServer()` into shared utility (DRY refactor)
974
- - Refactored `status` and `destroy` commands to use shared `resolveServer` + `promptApiToken`
975
- - Test count: 246 → 311
976
- - Coverage maintained: 97%+ statements, 88%+ branches
977
-
978
- ## [0.4.1] - 2026-02-20
979
-
980
- ### Security
981
- - **Environment variable token support** - Use `HETZNER_TOKEN` / `DIGITALOCEAN_TOKEN` env vars instead of `--token` flag to avoid shell history and `ps aux` exposure
982
- - Config directory (`~/.quicklify/`) created with `0o700` permissions (owner only)
983
- - Cloud-init install log restricted to `chmod 600` (root read/write only)
984
- - Server name validation strengthened: 3-63 chars, must start with letter, end with letter/number
985
- - SSL/HTTPS setup warnings added to `init` and `status` command output
986
- - Updated `SECURITY.md` with current security measures and DigitalOcean API v2
987
-
988
- ### Changed
989
- - ESLint upgraded from v9 to v10 (new `preserve-caught-error` rule compliance)
990
- - Updated dependencies: axios 1.13, chalk 5.6, commander 14, ora 9, tsx 4.21, typescript 5.9
991
- - Minimum Node.js version: 20 (ESLint 10 + ora 9 + commander 14 requirement)
992
- - CI matrix: 3 OS x 2 Node versions (dropped Node 18)
993
- - Non-interactive mode now detected by `--provider` flag alone (token can come from env var)
994
- - `--token` option description updated to mention env var alternatives
995
-
996
- ## [0.4.0] - 2026-02-20
997
-
998
- ### Added
999
- - **`quicklify list`** command - List all registered servers (no token required)
1000
- - **`quicklify status [query]`** command - Check server and Coolify status by IP or name
1001
- - **`quicklify destroy [query]`** command - Destroy a server with double confirmation safety
1002
- - **Non-interactive mode** for `quicklify init` with `--provider`, `--token`, `--region`, `--size`, `--name` flags
1003
- - **Coolify health check polling** - Replaces blind wait with intelligent `http://IP:8000` polling
1004
- - **Server record persistence** - Successful deploys saved to `~/.quicklify/servers.json`
1005
- - `ServerRecord` and `InitOptions` TypeScript interfaces
1006
- - `src/utils/config.ts` - Config module for server record CRUD (`getServers`, `saveServer`, `removeServer`, `findServer`)
1007
- - `src/utils/providerFactory.ts` - Provider factory extracted from init.ts for better testability
1008
- - `src/utils/healthCheck.ts` - `waitForCoolify()` with configurable polling (min wait + 5s interval + max attempts)
1009
- - `destroyServer()` method on `CloudProvider` interface (Hetzner + DigitalOcean implementations)
1010
- - 86 new tests: config, list, status, destroy, healthCheck, providerFactory, edge cases, E2E flows
1011
- - Edge case test coverage: config corruption, health check retries, non-interactive validation
1012
-
1013
- ### Changed
1014
- - `initCommand` now accepts `InitOptions` parameter for non-interactive mode
1015
- - Init flow uses `waitForCoolify()` instead of fixed `setTimeout` (faster with early exit on success)
1016
- - Init flow saves server record to local config after successful deploy
1017
- - Success message now includes `quicklify status` and `quicklify list` hints
1018
- - Provider creation extracted to `providerFactory.ts` (no behavior change)
1019
- - Test count: 145 233
1020
- - Coverage maintained: 97%+ statements, 89%+ branches, 96%+ functions
1021
-
1022
- ### Fixed
1023
- - Non-interactive mode properly exits with code 1 on invalid provider or token
1024
- - Health check accepts any HTTP response (200, 302, 401, 500) as "Coolify is running"
1025
- - `destroy` now removes local config record when server already deleted from provider ("not found")
1026
-
1027
- ## [0.3.1] - 2026-02-19
1028
-
1029
- ### Fixed
1030
- - Hetzner pricing now shows net prices (excl. VAT) matching website display
1031
- - Hetzner server types filtered by `/datacenters` API for real availability
1032
- - Replaced deprecated Hetzner server types (cpx→cx23/cx33, per Jan 2026 deprecation)
1033
- - "Server name already used" error now prompts for a new name instead of crashing
1034
- - Location disabled retry now re-prompts for both region and server type
1035
- - Back navigation in error retry flows (server type region)
1036
- - Updated static fallback prices to match current Hetzner net pricing
1037
-
1038
- ### Changed
1039
- - `getLocationConfig` now accepts `exclude` parameter to filter disabled locations
1040
-
1041
- ## [0.3.0] - 2026-02-19
1042
-
1043
- ### Added
1044
- - DigitalOcean provider implementation (full API integration)
1045
- - Provider selection UI prompt (Hetzner Cloud / DigitalOcean)
1046
- - `getProviderConfig()` prompt function
1047
- - DigitalOcean-specific interfaces (`DORegion`, `DOSize`, `DOErrorResponse`)
1048
- - Step-based back navigation with `← Back` option in all prompts
1049
- - `getServerDetails()` + IP refresh for DigitalOcean delayed IP assignment
1050
- - Minimum 2GB RAM + 2 vCPU filter for Coolify requirements
1051
- - Network connectivity wait loop in cloud-init (DigitalOcean cloud-init timing fix)
1052
- - Installation logging to `/var/log/quicklify-install.log` for troubleshooting
1053
- - Troubleshooting info in deployment success message
1054
- - Location retry on "server location disabled" error (offers region change)
1055
- - 50+ new tests (DigitalOcean integration, provider selection, E2E flows)
1056
-
1057
- ### Changed
1058
- - `init` command now prompts for provider selection instead of defaulting to Hetzner
1059
- - DigitalOcean image changed from Ubuntu 24.04 to 22.04 (stable cloud-init support)
1060
- - Hetzner server type filtering now uses `/datacenters` API for real availability
1061
- - Replaced deprecated Hetzner server types (cpx→cx23/cx33, per Jan 2026 deprecation)
1062
- - Provider-specific deployment timing (Hetzner ~5 min, DigitalOcean ~7 min)
1063
- - Cloud-init script now uses `set +e` for resilient execution
1064
- - UFW firewall support for DigitalOcean (alongside iptables for Hetzner)
1065
- - Updated `typescript-eslint` from 8.55 to 8.56
1066
- - Test count: 95 143+
1067
-
1068
- ### Fixed
1069
- - Hetzner deprecated server types (cpx11, cx22 etc.) shown but failing on creation
1070
- - DigitalOcean cloud-init failing due to network not ready at script execution time
1071
- - Hetzner pricing now shows net prices (excl. VAT) matching website display
1072
- - Coverage gaps in Hetzner provider (price null fallback, error.data.error undefined)
1073
-
1074
- ## [0.2.8] - 2026-02-16
1075
-
1076
- ### Added
1077
- - ESLint 9 + typescript-eslint 8 + Prettier setup with npm scripts
1078
- - `.prettierrc` and `eslint.config.js` configuration files
1079
- - `CHANGELOG.md` with full version history
1080
- - `CONTRIBUTING.md` with development guide and PR process
1081
- - Proper TypeScript interfaces for Hetzner API responses (`HetznerLocation`, `HetznerServerType`, `HetznerPrice`, `HetznerErrorResponse`)
1082
- - `isAxiosError` mock in test helpers
1083
-
1084
- ### Changed
1085
- - Replaced all `catch (error: any)` with `catch (error: unknown)` + proper type guards
1086
- - Replaced `any` type annotations with proper interfaces in Hetzner provider
1087
- - Applied Prettier formatting across all source files
1088
-
1089
- ## [0.2.7] - 2026-02-16
1090
-
1091
- ### Changed
1092
- - Updated README with accurate feature descriptions and missing version history
1093
- - Fixed inaccurate SECURITY.md claims (token handling, SDK references)
1094
- - Added npm keywords for better discoverability (vps, cloud, automation, self-hosted, paas, devops, server)
1095
-
1096
- ### Security
1097
- - Added server name sanitization in cloud-init script (defense-in-depth)
1098
-
1099
- ## [0.2.6] - 2026-02-16
1100
-
1101
- ### Changed
1102
- - CI: Upgraded Codecov action to v5
1103
-
1104
- ## [0.2.5] - 2026-02-16
1105
-
1106
- ### Added
1107
- - CI: Codecov integration for automatic coverage badge
1108
-
1109
- ## [0.2.4] - 2026-02-15
1110
-
1111
- ### Changed
1112
- - Refactor: Removed recommended label from server type selection
1113
- - Excluded failed server types from retry list
1114
-
1115
- ## [0.2.3] - 2026-02-15
1116
-
1117
- ### Fixed
1118
- - Unsupported server type error now triggers retry
1119
- - Dynamic deployment summary based on actual server config
1120
- - Dynamic recommended server type selection
1121
-
1122
- ## [0.2.2] - 2026-02-15
1123
-
1124
- ### Added
1125
- - Deprecated server type filtering
1126
- - Retry mechanism for unavailable server types
1127
-
1128
- ## [0.2.1] - 2026-02-14
1129
-
1130
- ### Fixed
1131
- - URL protocol changed from https to http for initial Coolify setup
1132
-
1133
- ## [0.2.0] - 2026-02-14
1134
-
1135
- ### Added
1136
- - Dynamic server type filtering based on selected location
1137
- - Auto firewall configuration (ports 8000, 22, 80, 443)
1138
-
1139
- ### Changed
1140
- - Improved price formatting
1141
-
1142
- ### Removed
1143
- - Debug logs
1144
-
1145
- ## [0.1.11] - 2026-02-14
1146
-
1147
- ### Changed
1148
- - Removed tracked Claude Code local settings
1149
-
1150
- ### Added
1151
- - Firewall rules to cloud-init
1152
- - Security notes to README
1153
-
1154
- ## [0.1.10] - 2026-02-14
1155
-
1156
- ### Fixed
1157
- - Updated deploy time estimate from 60 seconds to 4 minutes
1158
-
1159
- ## [0.1.9] - 2026-02-14
1160
-
1161
- ### Fixed
1162
- - Read version from package.json dynamically
1163
-
1164
- ## [0.1.8] - 2026-02-14
1165
-
1166
- ### Fixed
1167
- - Added build step to publish workflow
1168
-
1169
- ## [0.1.7] - 2026-02-14
1170
-
1171
- ### Fixed
1172
- - Added .npmignore to include dist/ in npm package
1173
-
1174
- ## [0.1.6] - 2026-02-14
1175
-
1176
- ### Fixed
1177
- - Added bin wrapper for Windows npx compatibility
1178
-
1179
- ## [0.1.5] - 2026-02-14
1180
-
1181
- ### Fixed
1182
- - Added files field to include dist/ in npm package
1183
-
1184
- ## [0.1.4] - 2026-02-14
1185
-
1186
- ### Added
1187
- - SECURITY.md with security policy
1188
- - Socket.dev security badge
1189
- - Package.json metadata (repository, bugs, homepage, author)
1190
-
1191
- ## [0.1.3] - 2026-02-14
1192
-
1193
- ### Added
1194
- - Auto npm publish workflow via GitHub Actions
1195
- - GitHub stars badge to README
1196
-
1197
- ## [0.1.2] - 2026-02-14
1198
-
1199
- ### Changed
1200
- - Updated deploy time references from 60s to 4 minutes
1201
-
1202
- ## [0.1.1] - 2026-02-14
1203
-
1204
- ### Fixed
1205
- - Corrected bin field in package.json
1206
- - Added status badges to README
1207
-
1208
- ## [0.1.0] - 2026-02-14
1209
-
1210
- ### Added
1211
- - Initial release
1212
- - Hetzner Cloud integration
1213
- - Interactive CLI with Commander.js + Inquirer.js
1214
- - Automated Coolify installation via cloud-init
1215
- - ARM64 support
1216
- - Full test suite (unit, integration, e2e)
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [2.2.0] - 2026-05-03
6
+
7
+ ### Added
8
+ - **Plugin Ecosystem** — third-party audit check plugins via `kastell-plugin-*` npm packages
9
+ - `kastell plugin install/remove/list/validate` CLI commands
10
+ - `server_plugin` MCP tool (list + validate actions)
11
+ - Plugin SDK types (`PluginManifest`, `PluginCheck`, `PluginSeverity`, `PluginFixTier`)
12
+ - Manifest validation with Zod + semver compatibility check
13
+ - Plugin loader with collision detection, cache, and startup integration
14
+ - Bash/Zsh/Fish completions for plugin commands
15
+ - Example plugins: `kastell-plugin-wordpress` (3 checks), `kastell-plugin-auditor` (2 checks)
16
+ - **`--include-forbidden` flag** — run FORBIDDEN tier fixes with per-fix confirmation prompt
17
+ - **`--auto-fix --schedule` pipeline** — combines doctor diagnosis + fix application on a cron schedule (DOC-04)
18
+ - **Fix session logging** — per-command execution log with stdout/stderr and duration in `FixHistoryEntry` (AH-03)
19
+ - **Doctor fix history merge** — doctor fix results persisted to `fix-history.json` audit trail (DOC-02)
20
+ - **FORBIDDEN rawCommand handler** — shows dangerous commands to user with confirmation before execution (DOC-03)
21
+
22
+ ### Changed
23
+ - **CHECK_IDS constants** — all 481 audit check IDs migrated from string literals to typed const object (`CHECK_IDS.SSH.PASSWORD_AUTH` etc.), zero string literals remain in src/ or tests/
24
+ - **`extractReason` shared helper** replaces 18 inline `instanceof Error ? .message : String()` patterns across codebase
25
+ - **`createMockProcess` shared helper** unified test mock for spawn processes with stderr support, replaces 3 inline duplicates
26
+ - **`executeSingleFix` extraction** — shared fix execution logic between safe and forbidden paths with backup support
27
+ - **`compliance/mapper.ts` split** — category-based sub-modules (`categories/index.ts` barrel) for maintainability (DEF-06)
28
+ - **`buildFirewallSetupCommand` merge** — bare firewall command merged into single function (DEF-07)
29
+ - **Plugin list dynamic columns** — table sizing adapts to terminal width
30
+ - **Plugin install UX** name validation before confirmation prompt (not after)
31
+ - **`PLUGIN_NAME_PATTERN`** single source of truth in `sdk/constants.ts`
32
+ - **`mapRegistryPlugins` helper** — replaces inline registry iteration in list/validate/loader
33
+
34
+ ### Fixed
35
+ - **Backup idempotent** — first-writer-wins prevents SAFE/FORBIDDEN backup overwrite on repeated fix runs
36
+ - **Plugin remove ghost check** — `deletePlugin` + cache update instead of full reload prevents stale entries
37
+ - **Plugin install shell injection** VERSION_PATTERN + name validation closes injection vector
38
+ - **Windows npm spawn** Node 24 `shell:true` DEP0190 fix via joined command string
39
+ - **Commander.js `--version` collision** — renamed to `--ver` flag for plugin version display
40
+ - **Notify completions restore** — bash completions case label fix (append, not replace)
41
+ - **Doctor `--schedule` validation** — requires `--auto-fix` flag, rejects invalid combinations
42
+
43
+ ### Security
44
+ - **Plugin loader path traversal guard** resolve+startsWith prevents directory escape (SEC-08)
45
+ - **Snapshot path traversal guard**loadSnapshot validates path stays within snapshots dir (SEC-09)
46
+ - **`server_lock` MCP destructiveHint** — marked as destructive for client-side gating (SEC-10)
47
+ - **SHELL_METACHAR duplicate fix** — removed duplicate `&` from regex (SEC-11)
48
+ - **CI expression injection fix** — `inputs.server_size` and `inputs.concurrency` moved to `env:` (SEC-07)
49
+
50
+ ### Stats
51
+ - 10401 tests (267 suites, 14 snapshots), coverage 96.33%
52
+ - 100 files changed across 6 phases (P124-P129)
53
+ - 35+ commits (30 Minimax + 5 Opus fix/simplify)
54
+
55
+ ## [2.1.0] - 2026-04-28
56
+
57
+ ### Added
58
+ - **`kastell init` 3-way wizard** — interactive setup with three paths: provision a new server, register an existing server, or configure defaults (compliance framework, notification channels)
59
+ - **`kastell explain <check-id>`** deep-dive into any audit check: why it matters, fix command, fix tier (SAFE/GUARDED/FORBIDDEN), CIS/PCI-DSS/HIPAA compliance references. Supports `--format terminal|json|md`
60
+ - **`audit --ci` flag** — CI mode with JSON output, no spinner, requires `--threshold` for exit code gating
61
+ - **`fleet --categories`** — shows weakest audit category per server in fleet dashboard
62
+ - **`audit --compare` enhancements** — `--fresh` flag for live audit (skip snapshots), `--detail` for check-level diff instead of category summary
63
+ - **`server_compare` MCP tool** — side-by-side server comparison with snapshot fallback and detail mode (16th MCP tool)
64
+ - **Doctor score** — `computeDoctorScore` with severity-weighted findings, wired into CLI and MCP
65
+ - **Regression gating** — pre-fix regression check with `--force` bypass, conditional baseline save, `kastell regression status/reset` commands
66
+ - **Substring fuzzy match** — `kastell explain ssh-password` resolves to `SSH-PASSWORD-AUTH` (single match returns result, multiple returns suggestions)
67
+ - **`defaults.json` support** — `loadDefaults`/`saveDefaults` with Zod validation for threshold/framework fallback
68
+
69
+ ### Changed
70
+ - **Regression wiring** — `saveBaseline`/`checkRegression` integrated into all 4 callers (CLI audit, CLI fix, MCP serverAudit, MCP serverFix)
71
+ - **`confirmOrCancel` helper** extracted to `prompts.ts` with DI pattern, replacing inline confirm logic in fix and regression flows
72
+ - **`hasRegression()` helper** single source of truth for regression detection, replaces 3 inline copies
73
+ - **`resolveAuditPair` extraction** — DRY compare logic with exit code bug fix
74
+ - **`formatRegressionSummary`** typed DRY helper for consistent regression display across CLI and MCP
75
+ - **`runPostFixReAudit`** — returns full AuditResult for accurate post-fix baseline
76
+ - **`scoreRegressed` removed from interface** — derived inline via `hasRegression()`, 8 test fixtures updated
77
+ - **Discriminated union for `AddServerResult`** — type-safe success/failure branching in init wizard
78
+ - **`providerConfig.ts` rename** — `utils/defaults.ts` renamed for clarity
79
+ - **`formatSuggestions` DRY helper** — shared between explain command and MCP tool
80
+ - **Index-based `listSnapshots`**O(1) read instead of O(N) file parse
81
+ - **Firewall port deduplication** — uses `adapter.platformPorts` as single source
82
+
83
+ ### Security
84
+ - **Dependency updates** — actions/checkout v6, actions/setup-node v6, actions/upload-artifact v7
85
+
86
+ ### Tests
87
+ - 255 suites, 10265 tests, 12 snapshots (up from 240 suites, 10127 tests in v2.0.0)
88
+ - Coverage threshold: 90% global, 95% audit, 90% provider, 90% MCP
89
+
90
+ ## [2.0.0] - 2026-04-20
91
+
92
+ ### Added
93
+ - **`classifyError` helper** unified instanceof-based error branching for KastellError hierarchy (TransientError, ValidationError, BusinessError, PermissionError)
94
+ - **`logSafeModeBlock`**structured security logging wired into all 9 `isSafeMode()` guard sites in commands/ and MCP tools
95
+ - **`secureWriteFileSync` / `secureMkdirSync` / `ensureSecureDir`** platform-aware secure file operations with POSIX permission enforcement
96
+ - **`configRepair` core + CLI** — `kastell config repair` diagnoses and repairs corrupted config files
97
+ - **MCP audit enhancements** — snapshot save/compare, category/severity filter, threshold gate, profile filter for `server_audit`
98
+ - **`--checks` flag** — `kastell fix --checks KERN-SYNCOOKIES,...` for specific check IDs
99
+ - **Property-based tests** — fast-check arbitraries for MCP and config Zod schemas
100
+ - **Fuzz tests** kernel, firewall, and filesystem parser fuzzing with fast-check
101
+ - **E2E nightly workflow** — CI provision→lock→audit→destroy end-to-end pipeline
102
+ - **Schema exports** — property-based snapshot tests for Zod schema stability
103
+
104
+ ### Changed
105
+ - **Structured error migration (P107+P113)** — all 9 commands/ catch blocks use `instanceof` branching instead of string matching; mappers (mapProviderError, mapSshError, mapFileSystemError) preserved for backward compat
106
+ - **Security logging (P107)** — SecurityLogger module with JSON audit trail, throw-point migration
107
+ - **Audit DRY (P106)** — shared sysctl utility, typed audit categories, v1.12 review backlog closed
108
+ - **CONFIG_DIR→KASTELL_DIR (P105)** — unified path constant, inline paths eliminated
109
+ - **Code quality** — template literals, cleaner conditionals, import cleanup across codebase
110
+ - **MCP parity** — CLI/MCP feature gap closed (parity matrix verification tests added)
111
+
112
+ ### Security
113
+ - **secureWrite migration (SEC-06)** — all credential files use `secureWriteFileSync` with 0o600 permissions
114
+ - **TOCTOU fix** — removed `existsSync` guard before `secureMkdirSync` in auth.ts
115
+ - **Path traversal guard** — server-side validation in `rollbackFix` for E2E JSON parse errors
116
+ - **ESLint security plugins (P108)** — Zod schemas for all 4 providers, shellEscape utility, retry resilience (502/503/ETIMEDOUT)
117
+ - **CI hardening** — explicit permissions blocks in all workflows, SHA-pinned checkout actions
118
+ - **Dependency updates** — axios 1.15.0 (CVE-2025-62718), follow-redirects 1.16.0, hono 4.12.14, actions/cache 5.0.5
119
+
120
+ ### Tests
121
+ - 240 suites, 10127 tests, 12 snapshots (up from ~9500 in v1.17.1)
122
+ - Coverage threshold: 90% global, 95% audit, 90% provider, 90% MCP
123
+
124
+ ## [1.17.1] - 2026-04-01
125
+
126
+ ### Security
127
+ - **28 defence-in-depth fixes** from 5-skill security audit (security-audit, supply-chain, insecure-defaults, sharp-edges, code-review)
128
+ - **`sshExec` type narrowing** accepts `SshCommand` only (removed `| string`), 33 callers wrapped with `raw()` for explicit shell trust
129
+ - **`SAFE_MODE` typo-safe** — accepts `"yes"`, `"1"`, `"on"` as truthy; warns on unrecognized values; `remove` action now gated
130
+ - **`sanitizedEnv()` expanded blocklist** — 10 secret patterns (up from 4): TOKEN, SECRET, PASSWORD, CREDENTIAL, API_KEY, APIKEY, AUTH_KEY, AUTHKEY, PRIVATE_KEY, ACCESS_KEY
131
+ - **Rollback SHA256 integrity** — `restore-commands.sh` checksum written during backup, verified before execution
132
+ - **MCP error sanitization** — all 12 tool handlers route errors through `sanitizeStderr` to prevent IP/path leakage
133
+ - **Path traversal guard** — `relPath` in rollback validated with allowlist regex (`/^[a-zA-Z0-9_./-]+$/`)
134
+ - **`backupPath` Zod regex** — format constraint prevents tampered `fix-history.json` from injecting shell commands
135
+ - **`SHELL_METACHAR`** — added `&` to block `&&` on fallback path
136
+ - **`sedReplace` path quoting** — POSIX single-quote escape for file paths
137
+ - **`DEBIAN_FRONTEND` scope** — applied to both `apt-get update` and `apt-get upgrade`
138
+
139
+ ### Changed
140
+ - **`scheduleManager` `execSync` `spawnSync`** temp file approach, no shell interpolation, `updateCrontab()` DRY helper
141
+ - **`encryption.ts` `execSync` `spawnSync`** array args for machine ID retrieval
142
+ - **Production deps pinned** — all 11 dependencies use exact versions (no caret ranges)
143
+ - **`isSafeMode()` extracted** to `src/utils/safeMode.ts` (re-exported from `manage.ts`)
144
+ - **Platform fallback** — detection failure defaults to `"bare"` (was `"coolify"`)
145
+ - **`cmd("")` throws** — empty string arguments rejected
146
+ - **`timeoutMs=0` guard** falls back to default instead of instant kill
147
+ - **ControlMaster socket dir** — created with `mode: 0o700`
148
+ - **`debugLog` redaction** — sensitive keywords and objects redacted
149
+ - **`getServers()` hardened** — JSON.parse catch, provider validation against `SUPPORTED_PROVIDERS`
150
+ - **`warnIfPermissionError`**shared helper for EACCES/EPERM distinction
151
+
152
+ ## [1.17.0] - 2026-04-01
153
+
154
+ ### Added
155
+ - **Bulk rollback** `kastell fix --rollback-all` and `--rollback-to <fix-id>` for batch fix reversal
156
+ - **Doctor auto-fix** `kastell doctor --auto-fix` diagnose-then-fix pipeline with `--dry-run` and `--force` options
157
+ - **Fix scheduling** — `kastell schedule fix|audit` installs local cron for automated fix/audit runs with `list` and `remove` management
158
+ - **Fix engine DRY refactor** — shared bulk rollback helpers, sed-replace and aptUpgrade programmatic handlers
159
+ - **Custom fix profiles** — user-defined profiles loaded from `~/.kastell/profiles/` alongside built-in web-server/database/mail-server
160
+ - **SSH ControlMaster** connection multiplexing for fix engine prevents sshd MaxStartups exhaustion during bulk operations
161
+ - **Interactive menu full CLI parity** — schedule category, audit extras (snapshot/trend/watch/host/threshold/report/compare), fix extras (category/diff/report/rollback-to), doctor/lock/evidence/maintain/backup/status/snapshot/fleet options, shared validators
162
+ - **WAF bot detection checks** NGX-WAF-BOT-DETECT and NGX-WAF-CHALLENGE-MODE audit checks for nginx bot mitigation
163
+ - **`--no-interactive` flag** `kastell fix --no-interactive` for scheduled/automated runs without confirmation prompts
164
+
165
+ ### Fixed
166
+ - **SSH lockout prevention** — NET-HOSTS-DENY moved to GUARDED tier, prevents TCP wrapper lockout via `/etc/hosts.deny`
167
+ - **Sysctl SSH breakage** — all sysctl fixes promoted to GUARDED tier, network sysctl SSH probe with automatic rollback (D-20)
168
+ - **Session-terminating commands** — reboot/shutdown/poweroff/halt promoted to GUARDED tier (D-22)
169
+ - **SSH ControlMaster Windows** Unix-style `/tmp` socket path, stale socket cleanup, fork detection fix
170
+ - **MCP SAFE_MODE guards** `serverLock`, `serverGuard`, `serverSecure` now enforce `isSafeMode()` for destructive operations
171
+ - **Fix backup directory** rollback remote backup path resolution bug fixed (BUG-01)
172
+ - **fileWrite + systemctl handlers** — shell metachar bypass prevention for programmatic fix handlers
173
+
174
+ ### Changed
175
+ - **TOCTOU elimination** — replaced `existsSync` checks with direct operation + ENOENT handling across fix engine and core modules
176
+ - **KASTELL_DIR consolidation** — unified `CONFIG_DIR` imports to `KASTELL_DIR` from `paths.ts`, eliminated deprecated re-exports
177
+ - **severityChalk utility** — centralized severity-to-chalk color mapping, replaces inline switch statements
178
+ - **9,871 tests** across 219 suites (up from 9,611 / 215 in v1.16)
179
+
180
+ ### Security
181
+ - **Tier promotion system** — dangerous fixes (sysctl, hosts.deny, reboot) automatically promoted from SAFE to GUARDED, requiring explicit `--guarded` flag
182
+ - **MCP fail-closed SAFE_MODE** — MCP server defaults to safe mode, blocking destructive operations unless explicitly disabled
183
+
184
+ ## [1.16.0] - 2026-03-29
185
+
186
+ ### Added
187
+ - **AES-256-GCM token encryption** — tokens.json and notify-secrets.json encrypted at rest when OS keychain is unavailable. Per-installation random salt, cross-platform machine key derivation (Linux/macOS/Windows), transparent plaintext auto-migration
188
+ - **Fix rollback & history** `kastell fix --rollback <id>` restores from backup, `kastell fix --history` shows fix log
189
+ - **Fix prioritization** `kastell fix --top N` applies highest-impact fixes, `kastell fix --target 80` fixes until score reaches target
190
+ - **Programmatic fix handlers** — 4 dedicated handlers (sysctl, file-append, package-install, chmod/chown) replace shell redirect/pipe for SAFE tier fixes
191
+ - **Fix profiles** — `kastell fix --profile web-server|database|mail-server` applies server-type-specific fix sets
192
+ - **Fix diff preview** — `kastell fix --diff` shows per-fix before/after changes
193
+ - **Fix report** — `kastell fix --report` generates markdown fix report with score change and compliance info
194
+ - **WAF audit deep checks** — 5 new WAF pipeline checks (IP ACL, rate limiting, input sanitization, bot detection headers, data masking) expanding nginx category to 14 checks
195
+ - **Dependabot config** `.github/dependabot.yml` for automated GitHub Actions SHA updates
196
+ - 10 project-specific security audit custom checks (SSH injection, SAFE_MODE bypass, token leak, MCP validation, subprocess env, SSH host key, API sanitization, error disclosure, npm lifecycle)
197
+
198
+ ### Fixed
199
+ - **getServers() fail-closed** corrupt servers.json now throws instead of silently returning empty array
200
+ - **fileAppend handler shell injection** single-quote escape via shellEscape() on forward path (rollback already escaped)
201
+ - **Encryption key hardening** per-installation random salt replaces hardcoded "kastell-v1", persistent random UUID fallback replaces low-entropy hostname
202
+
203
+ ### Security
204
+ - All 13 GitHub Actions references SHA-pinned across 5 workflow files (zero floating tags)
205
+ - SECFIX-01 through SECFIX-09 addressed: token encryption, supply chain hardening, fail-closed config, 5 already-closed findings verified
206
+ - Security audit: 29 findings (down from 39), 0 critical, 1 high (deferred to v2.0 by design)
207
+ - `/review` skill added to release security gate
208
+
209
+ ### Changed
210
+ - Test count: 5,522 9,611 (4,089 new tests including 3,623 mutation killers)
211
+ - Test suites: 207 → 215
212
+ - Test helpers: 4 → 5 factory files (encryption-factories.ts added)
213
+ - Mutation score: 44.65% 59.06% nominal / 78.6% effective (Dalga 1-3 complete)
214
+
215
+ ## [1.15.1] - 2026-03-28
216
+
217
+ ### Added
218
+ - **`kastell changelog` command** — Parse and display CHANGELOG.md in terminal (`kastell changelog`, `kastell changelog v1.14.0`, `kastell changelog --all`)
219
+ - **"Why Kastell?" manifesto** in README (EN + TR) — problem statement, approach, AI-native positioning
220
+ - **Kastell vs Alternatives comparison table** in README (EN + TR) — Kastell vs Lynis vs OpenSCAP across 12 dimensions
221
+ - **Zero Telemetry badge** in README (EN + TR) trust signal, no data collection
222
+ - **CI profile stats dispatch** — `.github` org profile auto-updates on every main push (test/check/category/MCP counts)
223
+ - Interactive menu: "View changelog" entry in Configuration section
224
+ - CHANGELOG.md included in npm package files
225
+
226
+ ### Fixed
227
+ - **sshExec SSH banner handling** — servers with login banners caused non-zero exit codes on Windows, breaking health checks, audit scores (42→11 false drop), and doctor cache writes. Now checks stdout content when stderr is banner-only
228
+ - **3 incorrect fix commands** — `grub2-mkpasswd-pbkdf2` → `grub-mkpasswd-pbkdf2` (Ubuntu), `dc3dd` → `sleuthkit` (available in repos), `vector` → `rsyslog` (no 3rd party repo needed)
229
+ - **Backup fix command** — `kastell backup create` (local CLI, not available on server) → server-side `tar` command
230
+ - **audit-watch test timeout** — Windows CI fake timer slowness (jest.setTimeout 15s + extra microtick flushes)
231
+ - **CI dispatch format** — JSON body for repository_dispatch (was form-encoded)
232
+
233
+ ### Security
234
+ - 10 security audit remediation items applied: SHELL_METACHAR validation, bot middleware fail-closed, clearKnownHostKey IP validation, sendTelegram token validation, unhandled rejection handler, npm publish --provenance, staging token scope, debugLog→KASTELL_DEBUG
235
+ - Security audit report: `security-audit-report.md` (39 findings, 0 critical)
236
+
237
+ ### Changed
238
+ - Test count: 5,506 5,522 (16 new tests: 4 SSH banner + 12 changelog)
239
+ - Test suites: 206 → 207
240
+
241
+ ## [1.15.0] - 2026-03-27
242
+
243
+ ### Added
244
+ - **Edge & WAF Audit (P88):** 9 Nginx config checks + WAF detection, 30th audit category, CIS/PCI-DSS compliance mapping
245
+ - **TCP Stack DDoS Hardening (P89):** 8 sysctl DDoS parameter checks, 31st audit category, Docker platform guard
246
+ - **kastell fix --safe (P90):** SAFE/GUARDED/FORBIDDEN tier classification for 442+ checks, mandatory backup, dry-run, fix→verify pipeline
247
+ - **MCP server_fix (P91):** 14th MCP tool with dryRun:true default, SAFE_MODE guard, TypeScript FORBIDDEN rejection
248
+ - **Telegram Bot Notifications (P92):** Guard audit score monitoring, two-tier alerts (warning 5-9pt, critical 10+pt), 24h staleness guard, allowedChatIds CRUD
249
+ - **Telegram Bot Commands (P93):** grammy polling bot with /status, /audit, /health, /doctor, /help commands, allowedChatIds middleware, offset persistence
250
+ - `kastell bot start` command for foreground Telegram bot
251
+ - Interactive menu: "Start Telegram bot" entry in Notifications & Bot section
252
+
253
+ ### Changed
254
+ - Audit categories: 29 → 31 (WAF & Reverse Proxy, DDoS Hardening)
255
+ - Audit checks: 413 442
256
+ - Test count: 5468 5499 (31 new bot module tests)
257
+ - Interactive menu audit description updated to 31 categories
258
+
259
+ ### Fixed
260
+ - npm audit vulnerabilities fixed (brace-expansion, handlebars, picomatch)
261
+
262
+ ### Security
263
+ - Bot allowedChatIds middleware silently blocks unauthorized users (no response leaked)
264
+ - Offset persistence prevents stale command replay on bot restart
265
+ - server_fix FORBIDDEN rejection blocks SSH/Firewall/Docker category fixes via MCP
266
+ - Fix tier classification: SSH/Firewall changes always FORBIDDEN (never auto-fixed)
267
+
268
+ ## [1.14.0] - 2026-03-24
269
+
270
+ ### Added
271
+ - **Snapshot Restore** `kastell snapshot restore` CLI + MCP `snapshot-restore` action with SAFE_MODE guard, double confirmation, and 4-provider support (Hetzner, DigitalOcean, Vultr, Linode)
272
+ - **Cloud ID Lookup** — `findServerByIp()` across all 4 providers; `kastell add` now displays Cloud ID automatically
273
+ - **TLS Hardening Audit** — 8 checks (min version, weak ciphers, HSTS with max-age validation, OCSP stapling, cert expiry, DH params, compression, cert chain) with PCI-DSS/CIS/HIPAA compliance mappings
274
+ - **HTTP Security Headers Audit** — 6 checks (X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, CORS wildcard, CSP) with PCI-DSS v4.0 mappings
275
+ - **Lock Score Boost** — 4 new lock steps (SSH fine-tuning with 15 directives, login.defs hardening, pam_faillock, sudo logging/requiretty) + 2 extended steps (banners +/etc/motd, cronAccess +at.allow); 24-step orchestrator
276
+ - **Interactive menu** — Added snapshot restore, audit --explain/--diff/--fix, doctor --fix options
277
+ - **Stryker Mutation Testing** — Baseline 40.74% across 19,726 mutants
278
+
279
+ ### Fixed
280
+ - **Lock-audit alignment** — 5 misalignments fixed (AIDE cron path, auditd restart, logrotate install+timer, cronAccess step, Docker mkdir)
281
+ - **snapshotId MCP validation** — Added regex validation for defense-in-depth
282
+ - **CERT_NOT_FOUND sentinel** — Properly emits when certificate file is missing instead of false CERT_EXPIRING_SOON
283
+ - **HTTPS-only audit gap** — HTTP header audit now tries HTTPS before HTTP for HTTPS-only servers
284
+ - **CLI snapshotCreate SAFE_MODE** Added guard for consistency with MCP handler
285
+ - **Vultr/Linode snapshotId validation** — Added `assertValidServerId` for defense-in-depth
286
+ - **Hetzner findServerByIp pagination** — Changed `per_page` from 50 to 100 for consistency
287
+ - **Faillock idempotency** — Each directive independently checked/updated instead of batch
288
+ - **fileLock ENOENT** — Ensure parent directory exists before creating lock file
289
+
290
+ ### Changed
291
+ - **Test suite** — 4178→5087 tests (909 new), 197 suites, 11 snapshots; branch coverage: global 93.25%, audit 95.96%, providers 91.22%, MCP 90.25%
292
+ - **Audit categories** — 27→29 (TLS Hardening + HTTP Security Headers); 421+ total checks
293
+ - **CI hardening** — Codecov integration, 4 typed test factory helpers, zero `as any` casts (231→0)
294
+ - **CI release gate** — `release.yml` now depends on CI success via `workflow_run` (prevents releasing when CI fails)
295
+ - **CI tag support** — CI workflow now runs on tag pushes for release/publish chain
296
+ - **TLS weak cipher detection** — Added SEED and IDEA to pattern
297
+ - **HSTS validation** — Now checks max-age >= 31536000
298
+ - **Compliance mappings** — Added HIPAA for TLS, updated PCI-DSS HDR-005 to v4.0 (6.2.4)
299
+ - **Skill consolidation** — 5 global security skills delegated to single `kastell-security-check.md`
300
+
301
+ ### Removed
302
+ - **Stryker from CI** — Mutation testing removed from GitHub Actions (exceeds 6h limit); moved to dedicated infrastructure with scheduled nightly incremental runs
303
+
304
+ ### Security
305
+ - **Comprehensive v1.14 review** — 5-agent parallel audit (OWASP, token/secret, audit system, code quality, test coverage); 13 findings resolved (3 MEDIUM + 10 LOW)
306
+ - **Release workflow injection fix** — Prevented shell injection via `head_branch` interpolation; added strict semver validation before checkout
307
+ - **Zero token leakage** — 5-layer sanitization verified across all new code paths
308
+
309
+ ## [1.13.0] - 2026-03-19
310
+
311
+ ### Added
312
+ - **Claude Code Plugin** — `kastell-plugin/` marketplace-ready package with `plugin.json` manifest, `.mcp.json`, and `hooks.json`
313
+ - **4 Skills** — `kastell-ops` (background server management), `kastell-research` (Explore agent + architecture map), `kastell-careful` (skill-scoped LLM prompt hook), `kastell-scaffold` (4 fork-friendly templates)
314
+ - **2 Agents** — `kastell-auditor` (security review) and `kastell-fixer` (bug diagnosis) project-scope agents
315
+ - **5 Hooks** — `session-log`, `stop-quality-check`, `session-audit`, `pre-commit-audit-guard`, `destroy-block` with ESM-compatible `.cjs` scripts
316
+ - **MCP Discoverability** — `server.instructions`, MCP Logging, `llms.txt`, `SUBMISSIONS.md`, 4 platform setup guides, `mcp-server` keyword
317
+ - **Dynamic Content Injection** — `!command` syntax in 4 skill files for live codebase context
318
+
319
+ ### Fixed
320
+ - **CLI↔MCP parity** — 3 bugs fixed: logs default service (Dokploy), health host-key-mismatch detection, maintain update validation
321
+ - **DO Coolify SSH key loss** — Re-inject SSH public key after platform installer in cloud-init
322
+ - **Docker crash after lock** — SSH host key resolution in MCP health checks
323
+ - **Plugin hook ESM compatibility** — Renamed `.js` → `.cjs` for ESM project compatibility
324
+
325
+ ### Changed
326
+ - **Commands→Core extraction** — `backup`, `status`, `update` business logic moved from commands/ to core/ (thin command pattern)
327
+ - **Adapter bypass elimination** — 9 commands now use adapter properties (`port`, `defaultLogService`, `platformPorts`) instead of hardcoded values
328
+ - **Shared `createMockAdapter()`** Test mock factory in `tests/helpers/mockAdapter.ts`; deduplicated across all test files
329
+ - **Test coverage** — 4156→4178 tests (adapter contract, core extraction, hook tests)
330
+
331
+ ## [1.12.0] - 2026-03-18
332
+
333
+ ### Added
334
+ - **`audit --explain`** Inline "Why:" + fix explanation for each failing check in CLI and MCP (`--explain` flag, 95%+ coverage)
335
+ - **Lock: auditd CIS L2 rules** — Deep audit rules (time-change, network-change, kernel-module) in `50-kastell-deep.rules` with immutability ordering
336
+ - **Lock: sysctl deep tuning** — 21 kernel hardening settings (dmesg_restrict, kptr_restrict, bpf_jit_harden, rp_filter, ASLR, core dumps)
337
+ - **Lock: pwquality** — CIS L1 password policy (minlen=14, complexity classes, maxrepeat=3), non-fatal with graceful skip
338
+ - **Lock: SSH cipher blacklist** — Weak ciphers/MACs/KEX removed via minus-prefix with `sshd -t` validation and automatic rollback
339
+ - **Lock: Docker runtime hardening** — daemon.json merge (no-new-privileges, live-restore, log rotation, icc:false) with platform-aware guards and reload-not-restart
340
+ - **Lock 19-step hardening** — Expanded from 16 to 19 steps (pwquality + SSH cipher + Docker hardening)
341
+ - **Audit 413 checks** — 4 new checks (KRN-BPF-JIT-HARDEN, LOG-AUDIT-TIME-RULES, LOG-AUDIT-NETWORK-RULES, LOG-AUDIT-MODULE-RULES)
342
+
343
+ ### Fixed
344
+ - **jq injection prevention** — Docker hardening uses stdin pipe instead of shell interpolation
345
+ - **SSH sed tab pattern** Cipher/MAC/KEX sed patterns now match both space and tab separators
346
+ - **Interactive menu**Lock description updated from 16-step to 19-step
347
+
348
+ ### Changed
349
+ - **WEAK_CIPHERS/MACS/KEX constants** — Single source in constants.ts, shared by lock and audit
350
+ - **Test coverage** — 4152→4156 tests (SSH cipher builder tests added)
351
+
352
+ ## [1.11.0] - 2026-03-18
353
+
354
+ ### Added
355
+ - **MCP tool descriptions** — Updated all 13 MCP tools with 27-category routing hints and accurate check counts
356
+ - **Audit display filter** — `audit --filter` for display-only category/severity filtering without re-running SSH
357
+ - **Audit fix score delta** — Post-fix score re-audit shows before/after comparison
358
+ - **Lock 16-step expansion** — `server lock` expanded from 5 to 16 hardening steps with grouped CLI output and dry-run preview
359
+ - **Lock step helpers** — `runLockStep` + 11 command builders for modular hardening (auditd, sysctl, pwquality, AIDE, etc.)
360
+ - **SSH host key remediation** Proactive `removeStaleHostKey` before SSH polling + error output with remediation hints
361
+
362
+ ### Fixed
363
+ - **Interactive menu audit filters** — Audit sub-menu now correctly passes filter and fix options
364
+ - **FW-05 passed field** — Fixed incorrect variable in firewall IPv6 check (`passed: isActive` `passed: ipv6Enabled`)
365
+ - **MCP check count** — Corrected inflated 488+ count back to accurate 409
366
+ - **Audit filter+fix hardening** — Shell metacharacter guard, severity validation, structured error logging
367
+ - **CLOUDMETA_CATALOG_INPUT format** — Fixed cloud metadata catalog input format
368
+ - **SSH retry error handling** — Added `.catch()` to SSH retry preventing unhandled rejections
369
+
370
+ ### Changed
371
+ - **`getErrorMessage` reuse** Consolidated error message extraction across modules
372
+ - **`extractSentinelValue` scoping** Documented as intentionally local to firewall.ts
373
+
374
+ ## [1.10.1] - 2026-03-17
375
+
376
+ ### Added
377
+ - **sshStream stdin support** — SSH batch commands piped via stdin for reliable cross-platform execution
378
+ - **Audit batch error reporting** — Structured error details when audit SSH batches fail
379
+
380
+ ### Fixed
381
+ - **Windows SSH argument escaping** — Batch commands now use stdin pipe instead of spawn arguments, fixing truncation on Windows
382
+ - **Audit sentinel wrappers** — Added sentinel markers for 4 categories (accounts, services, boot, scheduling 24 checks) fixing parser mismatches
383
+ - **Cloud-init SSH lockout** — Fixed DigitalOcean + Coolify SSH lockout caused by ssh.socket/needrestart/UFW ordering
384
+ - **Interactive menu back navigation** — Back option now works correctly in nested sub-menus
385
+ - **DEBIAN_FRONTEND=noninteractive** — Added to Coolify and Dokploy cloud-init scripts preventing apt prompts
386
+ - **Provision reliability** — Orphan cleanup, Vultr boot timeout (135s), SSH hardening safety guards
387
+ - **Snapshot Zod schema** — Added 6 P52 optional fields (vpsIrrelevant, connectionError, vpsType, vpsAdjustedCount, skippedCategories, warnings) preventing silent strip on load
388
+
389
+ ## [1.10.0] - 2026-03-16
390
+
391
+ ### Added
392
+ - **Audit Pro: 27 categories, 406+ checks** — Expanded from 9 categories / 46 checks to 27 categories / 406+ checks with Lynis-parity coverage
393
+ - **New audit categories** — Accounts, Services, Boot, Scheduling, Time, Banners, Crypto, File Integrity, Malware, MAC, Memory, Secrets, Cloud Metadata, Supply Chain, Backup Hygiene, Resource Limits, Incident Readiness, DNS Security
394
+ - **Compliance mapping** — CIS Ubuntu L1/L2 (290 mappings), PCI-DSS v4.0 (89 refs), HIPAA §164.312 (41 refs)
395
+ - **`audit --list-checks`**Static catalog of all 406+ checks with severity, description, and compliance refs
396
+ - **`audit --profile`**Filter audit by compliance profile (cis-level1, cis-level2, pci-dss, hipaa)
397
+ - **`audit --compliance`**Framework-grouped compliance report (cis, pci-dss, hipaa)
398
+ - **VPS detection** — Auto-detect virtualization type (kvm, vmware, xen, etc.) with VPS-irrelevant check skipping
399
+ - **Interactive menu v1.10 options** — Audit sub-menu now includes list-checks, profile filter, compliance report; notify sub-menu includes list/remove
400
+
401
+ ### Changed
402
+ - **Weighted category scoring** — Categories now have configurable weights (Secrets, Supply Chain weight=3)
403
+ - **Snapshot schema v2** — Added `auditVersion` field, automatic v1→v2 migration, Zod strict validation
404
+ - **Version-aware trend detection** — Methodology-change banner when comparing different audit versions
405
+ - **Semantic check IDs** — All checks renamed from numeric to `CATEGORY-DESCRIPTION` format (e.g., `SSH-PASSWORD-AUTH`)
406
+ - **Named separators + 3-tier batches** — SSH command grouping optimized for audit performance
407
+ - **Terminal formatter** — Category grouping (fail expanded / pass collapsed), stats header, VPS banner
408
+ - **QuickWins** — Max 7, compliance boost factor 1.5x for compliance-mapped checks
409
+ - **Provider boot timeout** — Provider-specific polling: Hetzner 30s, DigitalOcean 60s, Vultr 135s, Linode 120s
410
+ - Test count: 3,3333,992 (+659 new tests across 178 suites)
411
+
412
+ ### Fixed
413
+ - **Pre-release audit cleanup** — Deduplicated formatter helpers, strengthened secrets regex, fixed compliance mapper edge cases, added NaN guards
414
+ - **Boot timeout** — Vultr/Linode provision no longer times out due to fixed 30s polling
415
+
416
+ ## [1.9.1] - 2026-03-15
417
+
418
+ ### Security
419
+ - **Socket.dev alert fixes** — Resolved 3 supply-chain alerts on npm:
420
+ - `curl|bash` update commands moved from `constants.ts` into adapter files (eliminates obfuscated code alert)
421
+ - `child_process` import removed from `deploy.ts` uses `removeStaleHostKey()` utility instead
422
+ - `globalThis["fetch"]` false positive documented in SOCKET_JUSTIFICATION.md
423
+
424
+ ## [1.9.0] - 2026-03-15
425
+
426
+ ### Fixed
427
+ - **doctor --fix apt hang** — `DEBIAN_FRONTEND=noninteractive` prefix added to apt fix commands over SSH, preventing interactive prompts on headless servers
428
+ - **restore --force bypass**`--force` flag now auto-selects the latest backup without prompting when `--backup` is not specified
429
+ - **README codecov badge**Replaced broken codecov.io badge URL with shields.io integration for reliable rendering with logo
430
+
431
+ ### Security
432
+ - **Notify token keychain migration** Notification tokens (Telegram/Discord/Slack) moved from plain-text config to OS keychain storage with secure file-backed fallback for headless environments
433
+ - **SSH command builder** New `SshCommand` branded type with `cmd()`/`raw()` builders and POSIX `shellEscape()` — eliminates string concatenation injection risk across 11 core modules
434
+
435
+ ### Changed
436
+ - **MCP SDK isolation** — Dynamic `import()` boundary ensures non-MCP commands (`status`, `fleet`, `audit`, etc.) never load MCP SDK's 179 transitive dependencies
437
+ - **execSync → spawnSync migration** — Shell invocation eliminated from `ssh.ts` and `doctor.ts`, closing Socket.dev shell alert
438
+ - **MCP handler decomposition** — `serverSecure` (10 handlers) and `serverBackup` (6 handlers) extracted to colocated handler modules with 63 new unit tests
439
+ - **Quality audit fixes** 16 code quality findings resolved: layer violations, duplication, naming consistency, constant extraction
440
+ - Test count: 3,175 3,333 (+158 new tests)
441
+
442
+ ## [1.8.1] - 2026-03-15
443
+
444
+ ### Added
445
+ - **Interactive menu complete** — All missing commands added to interactive menu: fleet, audit, lock, evidence, guard, doctor, backup-list, notify, completions with sub-prompts and emoji categories
446
+ - **`--force` flag** — Added to 7 CLI commands (backup, secure, lock, domain, update, maintain, evidence) for non-interactive/CI usage
447
+ - **`backup list` CLI command** — List all local backups (previously MCP-only)
448
+ - **Dokploy domain support** CLI domain commands (add, remove, list, info) now work with Dokploy servers
449
+ - **`platformDefaults()` helper** Eliminates repeated platform ternaries in domain/restart commands
450
+ - **Domain completions** — Added `list` and `info` to domain subcommands in bash/zsh/fish
451
+
452
+ ### Fixed
453
+ - **Dokploy backup/restore** — Fixed `-U postgres` `-U dokploy` (role "postgres" does not exist)
454
+ - **Restart message** Now shows correct platform name and port (Dokploy:3000 vs Coolify:8000)
455
+ - **MCP mode detection** — `resolvePlatform()` used in MCP serverInfo (mode now correctly shows "dokploy")
456
+ - **MCP serverManage** — Added "dokploy" to mode enum
457
+
458
+ ### Changed
459
+ - Interactive doctor prompt: `--check-tokens` → `--fresh`
460
+ - Interactive backup prompt: confirm dialog → sub-menu (create/all)
461
+ - MCP version metadata added to all tool responses
462
+
463
+ ## [1.8.0] - 2026-03-15
464
+
465
+ ### Added
466
+ - **Fleet Visibility** (`kastell fleet`) Parallel health check across all servers with status table (online/degraded/offline), audit scores, response times. `--json` for structured output
467
+ - **Notification Module** (`kastell notify`)Multi-channel alert dispatch: webhook, Slack, Discord, email (SMTP). `kastell notify add-channel` + `kastell notify test`
468
+ - **Guard Notification Integration** Guard breach alerts automatically dispatched via configured notification channels with severity categorization
469
+ - **Doctor --fix** (`kastell doctor --fix`) Interactive auto-remediation for doctor findings. Per-finding confirm gate, `--force` to skip prompts, `--dry-run` to preview. Whitelisted fix commands only
470
+ - **MCP server_fleet tool** — Fleet visibility exposed via MCP (list all servers with health/audit status)
471
+ - **Shell completions updated** — fleet, notify, audit, evidence commands and all v1.8 flags added to bash/zsh/fish generators
472
+
473
+ ### Security
474
+ - **OWASP review** — 8 security fixes: evidence path traversal (H-01), evidence lines sanitize (H-02), webhook SSRF protection (M-01), guard stale comment fix (M-03), doctor fix whitelist (M-04), metrics file permission (L-03), audit history file permission (L-04), backup restore safe mode guard (I-01)
475
+ - 8 code quality improvements: notify DRY (sendHttp), Promise.all optimization, channel validation, guard version tracking, firewall platform messages, secure score DRY, default audit constants, IP validation consolidation
476
+
477
+ ### Changed
478
+ - **Architecture**: Layer violation fix `firewallSetup` and `secureSetup` moved from `commands/` to `core/`
479
+ - **Architecture**: Adapter deduplication `sharedCreateBackup` and `sharedRestoreBackup` extracted to `src/adapters/shared.ts`
480
+ - **Architecture**: PostSetup decomposed into `barePostSetup` + `platformPostSetup`
481
+ - Platform name capitalized in restore backup step labels (e.g., "coolify" → "Coolify")
482
+ - Removed `.planning/` from git tracking (was leaking internal planning files)
483
+ - Test count: 3,0383,175 (+137 new tests)
484
+ - MCP tools: 1213 (server_fleet added)
485
+
486
+ ## [1.7.0] - 2026-03-14
487
+
488
+ ### Added
489
+ - **Server Lock** (`kastell lock`) One-command production hardening: SSH key-only auth, fail2ban, UFW firewall, sysctl hardening, unattended-upgrades. Shows audit score before/after. `--dry-run` preview, `--force` for already-hardened servers
490
+ - **Backup Schedule** (`kastell backup --schedule`)Cron-based automatic backups via SSH crontab. Supports `--schedule hourly|daily|weekly|custom` with custom cron expressions
491
+ - **Guard Daemon** (`kastell guard start|stop|status`) — Autonomous security monitoring via remote cron. Checks disk/RAM/CPU/audit every 5 minutes with threshold breach detection
492
+ - **Risk Trend** (`kastell audit --trend`) — Audit score trend analysis over time. `--days N` to control window. Terminal and JSON output formats
493
+ - **Doctor (Server Mode)** (`kastell doctor <server>`) Per-server proactive health analysis: disk trending, high swap, stale packages, fail2ban bans, audit regression, old backups, reclaimable Docker space. `--fresh` for live SSH data, `--json` for structured output
494
+ - **3 new MCP tools**: `server_guard` (start/stop/status), `server_doctor` (summary/json), `server_lock` (dry-run/production/force)
495
+ - **Shell completions**: guard, lock, doctor flags added for bash/zsh/fish
496
+
497
+ ### Security
498
+ - **OWASP review**: 10 security and quality fixes — sanitized error paths, hardened input validation, tightened type guards
499
+ - **Dependency fix**: flatted 3.3.3 3.4.1 (unbounded recursion DoS)
500
+
501
+ ### Fixed
502
+ - CLI `list`/`status` now shows actual platform label (dokploy/coolify/bare) instead of generic "mode"
503
+ - `--force` flag added to secure/update CLI commands
504
+ - MCP evidence `force` parameter passthrough
505
+
506
+ ### Changed
507
+ - Test count: 2,467 3,038 (+571 new tests)
508
+ - MCP tools: 9 12 (server_guard, server_doctor, server_lock added)
509
+
510
+ ## [1.6.0] - 2026-03-11
511
+
512
+ ### Added
513
+ - **Audit Snapshots** (`kastell audit --snapshot`) — Persist audit results as timestamped JSON snapshots. `--snapshots` to list saved snapshots
514
+ - **Audit Diff** (`kastell audit --diff <id>`, `--compare <id1> <id2>`) — Compare audit results between snapshots. Shows category-level score changes and new/fixed findings
515
+ - **Evidence Collection** (`kastell evidence <server>`) — Forensic evidence package: firewall rules, auth.log, listening ports, system logs, Docker info. SHA256 checksums per file. Written to `~/.kastell/evidence/{server}/{date}/`
516
+ - **MCP server_evidence tool** Evidence collection exposed via MCP
517
+ - **Adapter contract conformance tests** Verify PlatformAdapter interface compliance
518
+ - **Infrastructure utilities**: `withRetry` (exponential backoff for provider API calls), `withFileLock` (file-based mutex for config writes)
519
+ - **Provider retry integration** — All provider GET methods wrapped with `withRetry`
520
+ - **Config lock integration** — All config writes protected with `withFileLock`
521
+ - **Mode migration** — Automatic `ServerMode` field addition to legacy server records
522
+
523
+ ### Security
524
+ - Consolidated IP validation, removed dead code, hardened security paths
525
+ - Auth keyring: replaced top-level await with lazy require (fixes non-interactive environments)
526
+
527
+ ### Fixed
528
+ - Evidence dynamic section-to-filename mapping prevents index mismatch bug
529
+ - Linode test mocks updated to use Error instances for `withProviderErrorHandling`
530
+
531
+ ### Changed
532
+ - Deduplicated provider error handling into `withProviderErrorHandling` + `extractApiMessage`
533
+ - Test count: 2,266 → 2,467 (+201 new tests)
534
+ - MCP tools: 89 (server_evidence added)
535
+
536
+ ## [1.5.2] - 2026-03-09
537
+
538
+ ### Fixed
539
+ - **Phase 2 code review**: 30 bug fixes across critical, high, medium, and low severity (3C+8H+14M+5L) provider validation, error handling, type safety improvements
540
+ - **Phase 1 remaining fixes**: 15 files provider validation hardening, audit check corrections, backup safety guards
541
+
542
+ ### Changed
543
+ - **CI**: Automatic GitHub Release workflow on tag push
544
+ - **Docs (TR)**: Security audit section, MCP server_audit, CI pipeline example added to Turkish README
545
+
546
+ ## [1.5.1] - 2026-03-08
547
+
548
+ ### Fixed
549
+ - **Dokploy update command**: Install script now called with `update` argument — previously ran fresh-install mode which failed on port 80/443 conflict with running Dokploy instance
550
+ - 5 Dokploy integration bugs found during real-server testing (health check port, firewall ports, backup paths, restore commands, version detection)
551
+
552
+ ## [1.5.0] - 2026-03-08
553
+
554
+ ### Added
555
+ - **Security audit system**: `kastell audit` command with 9 check categories (SSH, auth, firewall, Docker, kernel, filesystem, network, logging, updates), scoring 0-100, terminal/JSON/summary/badge formatters
556
+ - **Audit history**: `kastell audit --history` tracks score trends over time with comparison
557
+ - **Audit watch mode**: `kastell audit --watch` monitors security score changes on interval
558
+ - **Audit quick wins**: `kastell audit --quick-wins` suggests highest-impact fixes
559
+ - **Audit auto-fix**: `kastell audit --fix` applies safe remediations automatically
560
+ - **MCP server_audit tool**: Full audit capabilities exposed via MCP (summary/json/score formats)
561
+ - **Token buffer**: In-memory token protection with controlled exposure window
562
+ - **Platform auto-detection**: SSH-based `detectPlatform()` checks filesystem markers for Dokploy/Coolify/bare
563
+
564
+ ### Changed
565
+ - Test count: 2,266 → 2,467 (+201 new tests)
566
+ - Test suites: 86 → 112 (+26 new suites)
567
+ - MCP tools: 7 8 (server_audit added)
568
+
569
+ ## [1.4.0] - 2026-03-08
570
+
571
+ ### Added
572
+ - **CLI header**: Gradient ASCII banner with cyan-to-blue color scheme, version info bar, and quick-start command examples on interactive mode launch
573
+ - **Shell completions**: `kastell completions bash|zsh|fish` generates shell completion scripts for tab-completion
574
+ - **Config validation**: `kastell config validate` checks `servers.yaml` for structural and type errors using Zod strict schemas
575
+ - **Version check**: `kastell --version` now notifies if a newer version is available on npm
576
+ - **Dry-run support**: Added `--dry-run` flag to `destroy`, `remove`, `backup`, `snapshot`, and `secure` commands
577
+ - **Dokploy lifecycle**: Full Dokploy adapter with update, maintain, logs, health, backup, and restore support
578
+ - **Platform adapters**: `src/adapters/` architecture — Coolify and Dokploy adapters implement `PlatformAdapter` interface
579
+
580
+ ### Changed
581
+ - Interactive menu no longer uses figlet replaced with custom gradient ASCII art header
582
+ - `PROVIDER_REGISTRY` centralized in `src/constants.ts` as single source of truth
583
+ - Test count: 2,099 2,266 (+167 new tests)
584
+ - Test suites: 7886 (+8 new suites)
585
+
586
+ ## [1.3.1] - 2026-03-05
587
+
588
+ ### Changed
589
+ - **Metadata update**: Package description, keywords, and homepage updated for Kastell branding
590
+ - **Repository references**: All internal references updated from `omrfc/kastell` to `kastelldev/kastell`
591
+
592
+ ## [1.3.0] - 2026-03-05
593
+
594
+ ### Breaking Changes
595
+ - **Package renamed**: `quicklify` is now `kastell` on npm. Install with `npm install -g kastell`
596
+ - **Binary renamed**: `quicklify` CLI is now `kastell`, `quicklify-mcp` is now `kastell-mcp`
597
+ - **License changed**: MIT -> Apache License 2.0 (patent protection added)
598
+
599
+ ### Added
600
+ - **Config migration**: Automatic migration from `~/.quicklify` to `~/.kastell` on first run (copies entire directory, `.migrated` flag prevents re-migration)
601
+ - **NOTICE file**: Apache 2.0 attribution notice added
602
+
603
+ ### Changed
604
+ - **Package identity**: name `kastell`, version `1.3.0`, homepage `https://kastell.dev`
605
+ - **Environment variable**: `KASTELL_SAFE_MODE` is now the primary env var for MCP safe mode. `QUICKLIFY_SAFE_MODE` still works with a one-time deprecation warning (backward compat until v2.0)
606
+ - **Internal types**: `QuicklifyYamlConfig` -> `KastellYamlConfig`, `QuicklifyConfig` -> `KastellConfig`, `QuicklifyResult` -> `KastellResult`
607
+ - **Config directory**: `~/.quicklify/` -> `~/.kastell/` (automatic migration on first run)
608
+ - **SSH key prefix**: `quicklify-` -> `kastell-` for auto-generated SSH keys
609
+ - **Snapshot prefix**: `quicklify-` -> `kastell-` for new snapshots (existing `quicklify-*` snapshots still recognized via dual-prefix filter)
610
+ - **Export filename**: Default export changed from `quicklify-export.json` to `kastell-export.json`
611
+ - **Update check**: Now queries `registry.npmjs.org/kastell/latest`
612
+ - **All documentation**: README.md, README.tr.md, SECURITY.md, CONTRIBUTING.md, llms.txt updated to Kastell branding
613
+ - **Example config**: `quicklify.yml` renamed to `kastell.yml`
614
+ - **MCP config**: Server name changed from `quicklify` to `kastell`
615
+
616
+ ### Deprecated
617
+ - `quicklify` npm package (will show deprecation notice pointing to `kastell`)
618
+ - `QUICKLIFY_SAFE_MODE` env var (use `KASTELL_SAFE_MODE` instead, removed in v2.0)
619
+
620
+ ## [1.2.1] - 2026-03-02
621
+
622
+ ### Security
623
+ - **CRITICAL FIX**: `stripSensitiveData()` now sanitizes `error.response.data` and `error.response.headers` — prevents API tokens, rootPass, and other sensitive data from leaking via error cause chains
624
+ - Whitelist-based `sanitizeResponseData()` preserves only known error message fields (Hetzner `error.message`, DigitalOcean `message`, Vultr `error`, Linode `errors[].reason`)
625
+ - Response headers cleared to prevent `set-cookie` and tracking header exposure
626
+ - Linode `root_pass` reflection in error responses now stripped
627
+
628
+ ### Changed
629
+ - **Refactoring**: Extracted `init.ts` command logic into `src/core/deploy.ts` (619 → 243 lines)
630
+ - **Refactoring**: `PROVIDER_REGISTRY` centralized in `src/constants.ts` — single source of truth for provider metadata
631
+ - **Refactoring**: `stripSensitiveData()` consolidated from 4 provider files into `src/providers/base.ts`
632
+ - **Security**: SCP path hardening via `assertSafePath()` with shell metacharacter rejection
633
+ - **Security**: Token sanitization via `sanitizedEnv()` applied to all remaining child process calls
634
+ - Test count: 2,047 2,099 (+52 new tests)
635
+ - Test suites: 7678 (+2 new suites)
636
+
637
+ ## [1.2.0] - 2026-03-01
638
+
639
+ ### Added
640
+ - **Bare Mode** — Generic VPS support without Coolify (`--mode bare` on init/add)
641
+ - `ServerRecord.mode` field: `"coolify"` (default) or `"bare"`
642
+ - `requireCoolifyMode()` guard blocks Coolify-only operations on bare servers
643
+ - `getBareCloudInit()` — hardening-only cloud-init script (UFW + system updates)
644
+ - Bare mode support across all 23 CLI commands and 7 MCP tools
645
+ - 2GB RAM minimum removed for bare mode provisioning
646
+ - Backward compatibility: legacy records without `mode` field default to `"coolify"`
647
+ - **Interactive Menu** Run `quicklify` without arguments for a categorized menu
648
+ - 6 categories: Server Management, Security, Monitoring & Logs, Backup & Snapshots, Maintenance, Configuration
649
+ - Sub-option prompts for each action (mode, template, log source, port, etc.)
650
+ - `← Back` navigation to return to main menu at any point
651
+ - 49 new tests (`interactive.test.ts`)
652
+ - **MCP `sizes` action** `server_info` tool now supports listing available server types with prices per provider/region
653
+ - **MCP shared utilities** — `src/mcp/utils.ts` with `resolveServerForMcp`, `mcpSuccess`, `mcpError`
654
+ - **SSH host key auto-fix** — `removeStaleHostKey()` helper auto-removes stale known_hosts entries
655
+ - Health command detects host key mismatch and suggests fix
656
+ - SSH retry mechanism after stale key removal
657
+ - **UX improvements** (6 enhancements):
658
+ - Better dpkg lock messaging during provisioning
659
+ - Token source display (env var vs prompt)
660
+ - Firewall status shows current rules inline
661
+ - Domain info shows current FQDN
662
+ - Orphan backup cleanup
663
+ - Backup/restore shows provider + IP context
664
+
665
+ ### Security
666
+ - **OWASP hardening**: `assertSafePath()` for SCP paths (shell metacharacter check including `<>`)
667
+ - **Port validation**: MCP port range restricted to 1-65535
668
+ - **Token isolation**: `sanitizedEnv()` applied to all `spawn`/`exec`/`spawnSync` calls including `openBrowser`, `sshKey`, and `removeStaleHostKey`
669
+ - **SECURITY.md**: Added OWASP Top 10 compliance table with detailed mitigation descriptions
670
+
671
+ ### Fixed
672
+ - Init `--full-setup` crash on bare mode servers
673
+ - Domain `--name` flag ignored on bare mode
674
+ - Cloud-init completion wait missing
675
+ - Bare mode showing incorrect port information
676
+ - Health command missing query argument
677
+ - Restart bare mode "command not found" message
678
+ - MCP SSH path incorrect during provision
679
+
680
+ ### Changed
681
+ - Test count: 1,758 2,047 (+289 new tests)
682
+ - Test suites: 64 → 76 (+12 new suites)
683
+ - Banner slogan updated to "Self-hosting, fully managed"
684
+ - README interactive menu documentation with example output
685
+ - LICENSE name correction: "omrfc""Ömer Faruk CAN"
686
+ - `.gitignore`: added `servers.json`
687
+
688
+ ## [1.1.0] - 2026-02-27
689
+
690
+ ### Added
691
+ - **MCP Server** — Built-in Model Context Protocol server for AI-powered server management with 7 tools:
692
+ - `server_info` `list`, `status`, `health` (readOnly)
693
+ - `server_logs` — `logs`, `monitor` (readOnly)
694
+ - `server_manage` — `add`, `remove`, `destroy` (destructive, SAFE_MODE on destroy)
695
+ - `server_maintain` — `update`, `restart`, `maintain`
696
+ - `server_secure` — `secure-setup`, `secure-audit`, `firewall-setup`, `firewall-add`, `firewall-remove`, `firewall-status`, `domain-set`, `domain-remove`, `domain-check`, `domain-info`
697
+ - `server_backup` — `backup-create`, `backup-list`, `backup-restore`, `snapshot-create`, `snapshot-list`, `snapshot-delete` (SAFE_MODE on restore/delete)
698
+ - `server_provision` — `create` (destructive, SAFE_MODE — creates billable cloud resources)
699
+ - Structured JSON responses with `suggested_actions` for AI context optimization
700
+ - Tool annotations: `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`
701
+ - Rate limiting guidance in tool descriptions
702
+ - SAFE_MODE guards on destructive operations (provision, destroy, restore, snapshot-delete)
703
+ - **`src/core/` module** Pure business logic extracted from CLI commands (no CLI dependencies)
704
+ - `status.ts` — `checkCoolifyHealth`, `getCloudServerStatus`, `checkServerStatus`, `checkAllServersStatus`
705
+ - `tokens.ts` — `getProviderToken`, `collectProviderTokensFromEnv` (non-interactive token resolution)
706
+ - `secure.ts` — SSH hardening + audit (pure functions + async wrappers)
707
+ - `firewall.ts` — UFW management (pure functions + async wrappers)
708
+ - `domain.ts` FQDN/DNS management (pure functions + async wrappers)
709
+ - `backup.ts` Backup/restore (20 pure functions + SCP helpers)
710
+ - `snapshot.ts` Snapshot create/list/delete + cost estimate
711
+ - `provision.ts` — Server provisioning (13-step flow: validate → token → SSH → cloudInit → create → boot → IP → save)
712
+ - **`src/mcp/` module** — MCP server implementation
713
+ - `src/mcp/server.ts` — MCP server setup with 7 tool registrations
714
+ - `src/mcp/tools/` — 7 tool handlers (serverInfo, serverLogs, serverManage, serverMaintain, serverSecure, serverBackup, serverProvision)
715
+ - `src/mcp/index.ts` — stdio transport entry point
716
+ - `bin/quicklify-mcp`MCP server binary entry point
717
+ - SSRF defense: `assertValidIp()` added to `checkCoolifyHealth` (IP format validation before HTTP request)
718
+ - Stack trace sanitization in MCP error responses via `getErrorMessage()`
719
+
720
+ ### Security
721
+ - **Path traversal protection**: `backupId` validated with Zod regex (`/^[\w-]+$/`) + `path.resolve()` guard in restore
722
+ - **SAFE_MODE enforcement**: Added `isSafeMode()` guards on `restart`, `maintain`, and `snapshot-create` MCP actions
723
+ - **IP validation hardened**: `assertValidIp()` now validates octet range (0-255), IP removed from error messages
724
+ - **stderr sanitization**: New `sanitizeStderr()` function redacts IPs, home paths, tokens, secrets (200 char limit) — applied to all backup/restore/logs error output
725
+ - **Port validation**: MCP `server_secure` port restricted to `z.number().min(1).max(65535)`
726
+ - **Provider enum validation**: MCP `server_manage` provider changed from `z.string()` to `z.enum()` (prevents invalid provider injection)
727
+ - **Manifest hardening**: `serverIp` field removed from `BackupManifest` type, manifest files written with `mode: 0o600`
728
+ - **SCP IP validation**: `assertValidIp()` added to `scpDownload()` and `scpUpload()` before spawning child process
729
+ - **Log redaction**: `manage.ts` stderr no longer exposes server IP address
730
+ - **SSH key auto-generation**: `provision` now auto-generates SSH key when none exists (instead of skipping)
731
+ - `.mcp.json` added to `.gitignore` (contains local absolute paths)
732
+
733
+ ### Changed
734
+ - `src/commands/status.ts` refactored to use `src/core/status.ts` (DRY: eliminated duplicate Coolify health check)
735
+ - Test count: 1369 → 1758 (+389 new tests across 9 new test suites)
736
+ - Test suites: 55 64
737
+
738
+ ### Dependencies
739
+ - Added `@modelcontextprotocol/sdk` ^1.27.1 (MCP server SDK)
740
+ - Added `zod` ^4.3.6 (MCP input schema validation)
741
+
742
+ ## [1.0.5] - 2026-02-26
743
+
744
+ ### Added
745
+ - `mapSshError` 10 SSH error patterns mapped to actionable hints (connection refused, permission denied, host key, timeout, reset, hostname, command not found, disk full, broken pipe)
746
+ - `mapFileSystemError` — 4 filesystem error codes mapped to hints (ENOENT, EACCES, EPERM, ENOSPC)
747
+ - `getErrorMessage` — DRY helper replacing `error instanceof Error ? error.message : String(error)` across 15 command files
748
+
749
+ ### Changed
750
+ - All 53 catch blocks now use appropriate error mappers: Provider API → `mapProviderError`, SSH `mapSshError`, Filesystem → `mapFileSystemError`
751
+ - `mapProviderError` spread to 5 additional files (restart, maintain, status, update, snapshot)
752
+ - 3 silent catches in backup.ts now log error messages and provide SSH hints
753
+ - Test count: 1334 → 1369 (+35 new error hint integration tests)
754
+
755
+ ## [1.0.4] - 2026-02-25
756
+
757
+ ### Security
758
+ - Restore rollback: automatically restart Coolify if restore steps 3-5 fail after Coolify was stopped
759
+ - Fail2ban warning: show "partially complete" instead of misleading "complete" when fail2ban fails
760
+ - SSH key warnings: stronger guidance to run `quicklify secure setup` when key generation/upload fails
761
+
762
+ ## [1.0.3] - 2026-02-25
763
+
764
+ ### Added
765
+ - `doctor --check-tokens` Validate provider API tokens from environment variables against live APIs (Hetzner, DigitalOcean, Vultr, Linode)
766
+ - Update notification Check npm registry for newer versions (24h cache, non-blocking)
767
+ - Auto-open browser Automatically open Coolify dashboard after successful `init` deployment (platform-aware, `--no-open` to disable)
768
+ - Error mapper Actionable error messages with provider-specific URLs for billing, token management, and troubleshooting
769
+
770
+ ### Changed
771
+ - Init onboarding Improved post-deployment "What's Next?" guide with numbered steps and copy-paste commands
772
+ - README slogan updated to "Self-hosting made simple" (platform-agnostic)
773
+ - CONTRIBUTING.md completely rewritten to reflect current project state (22 commands, 5 providers, 13 utils)
774
+
775
+ ### Documentation
776
+ - `llms.txt` AI-friendly project documentation with architecture, commands, and workflows
777
+
778
+ ## [1.0.2] - 2026-02-24
779
+
780
+ ### Security
781
+ - Sanitize error cause chains to prevent API token leakage in all provider errors
782
+ - Mask process title when `--token` flag is used
783
+ - Replace `execSync` with `spawnSync` for ssh-keygen (prevent shell injection)
784
+ - Add shell-safe assertions to domain FQDN and DNS check commands
785
+ - Case-insensitive + nested security key detection in YAML config
786
+ - Strip unknown fields from imported server data
787
+ - Add IP address format validation to all SSH functions
788
+ - Filter sensitive environment variables from child processes
789
+ - Add `StrictHostKeyChecking` to interactive SSH connections
790
+ - Set file permissions (`0o600`) on export files
791
+ - Set directory permissions (`0o700`) on backup directories
792
+ - Add Vultr and Linode to default provider validation
793
+ - Clear `error.config.data` on Linode API failures (rootPass protection)
794
+
795
+ ## [1.0.1] - 2026-02-24
796
+
797
+ ### Added
798
+ - `quicklify snapshot create/list/delete` VPS snapshot management with cost estimates
799
+ - Maintain integration: automatic snapshot offer before maintenance (with cost estimate)
800
+ - `sshKey.test.ts` dedicated tests for SSH key utilities (13 tests)
801
+ - Provider snapshot support for Hetzner, DigitalOcean, Vultr, and Linode
802
+
803
+ ### Fixed
804
+ - **domain.ts**: SQL escape for FQDN values (defense-in-depth against SQL injection)
805
+ - **restore.ts**: Path traversal protection with `basename()` for `--backup` flag
806
+ - **yamlConfig.ts**: Expanded security key detection (6 → 21 patterns including password, credential, jwt, bearer, etc.)
807
+
808
+ ## [1.0.0] - 2026-02-23
809
+
810
+ ### Added
811
+ - **Vultr provider** (`src/providers/vultr.ts`) - Full Vultr API v2 integration
812
+ - Base64-encoded user_data for cloud-init
813
+ - SSH key upload with HTTP 409 conflict handling
814
+ - OS: Ubuntu 24.04 (os_id: 2284)
815
+ - Power status normalization (running/stopped)
816
+ - **Linode (Akamai) provider** (`src/providers/linode.ts`) - Full Linode API v4 integration
817
+ - Auto-generated root_pass via `crypto.randomBytes()`
818
+ - SSH key upload via `/profile/sshkeys`
819
+ - Metadata user_data for cloud-init (base64)
820
+ - Disk size conversion (MB → GB)
821
+ - **`quicklify add`** command - Register existing Coolify servers to Quicklify management
822
+ - Interactive flow: provider token IP verify Coolify → save
823
+ - Non-interactive: `--provider`, `--ip`, `--name`, `--skip-verify` flags
824
+ - Coolify verification via SSH (health check or `docker ps`)
825
+ - Duplicate detection by IP address
826
+ - **`quicklify maintain [query]`** command - Full maintenance cycle
827
+ - 6-step flow: snapshot warning status check → Coolify update → health check → reboot → final check
828
+ - `--skip-reboot` to skip the reboot step
829
+ - `--all` to maintain all servers sequentially
830
+ - `--dry-run` to preview maintenance steps
831
+ - **`quicklify remove [query]`** command - Remove a server from local config without destroying the cloud server
832
+ - Accepts server name or IP address
833
+ - Confirmation prompt before removal
834
+ - **`--all` flag** on `status`, `update`, `backup` commands
835
+ - `status --all`: parallel status check with table output (Promise.all)
836
+ - `update --all`: sequential update with single confirmation prompt
837
+ - `backup --all`: sequential backup across all servers
838
+ - **`status --autostart`** flag - Restarts Coolify via SSH if server is running but Coolify is down
839
+ - Uses `docker compose restart coolify` command
840
+ - Waits 5 seconds and verifies Coolify came back up
841
+ - **`collectProviderTokens()`** utility - Deduplicates token prompts per unique provider across servers
842
+ - `VULTR_TOKEN` and `LINODE_TOKEN` environment variable support
843
+ - Vultr and Linode defaults in all 3 templates (starter, production, dev)
844
+ - `"vultr"` and `"linode"` in YAML config validation
845
+ - 195 new tests across 6 new test files + enhanced existing test files
846
+
847
+ ### Changed
848
+ - Provider selection now shows 4 choices: Hetzner Cloud, DigitalOcean, Vultr, Linode (Akamai)
849
+ - Provider factory supports `"vultr"` and `"linode"` cases
850
+ - Total commands: 1923 (add, maintain, remove + maintain --all)
851
+ - Test count: 742 937
852
+ - Test suites: 40 44
853
+ - Coverage: 98%+ statements, 91%+ branches, 98%+ functions
854
+ - Zero new npm dependencies added
855
+
856
+ ## [0.9.0] - 2026-02-21
857
+
858
+ ### Added
859
+ - **`--config <path>`** flag on `quicklify init` - Load deployment parameters from a YAML config file
860
+ - Supports all init options: provider, region, size, name, fullSetup, template, domain
861
+ - Validates config with detailed warnings for invalid values
862
+ - Security: detects and warns about token fields in config files
863
+ - Handles missing files and invalid YAML syntax gracefully
864
+ - **`--template <name>`** flag on `quicklify init` - Use predefined server templates
865
+ - `starter` - Minimal setup (cheapest option, no hardening)
866
+ - `production` - Production-ready (larger server, auto firewall + SSH hardening)
867
+ - `dev` - Development/testing (cheap, no hardening)
868
+ - Per-provider defaults: Hetzner and DigitalOcean have optimized region/size pairs
869
+ - **Config merge system** with priority: CLI flags > YAML config > template defaults > interactive prompts
870
+ - `QuicklifyYamlConfig`, `TemplateName`, `TemplateDefinition` TypeScript interfaces
871
+ - `src/utils/templates.ts` - Template definitions with per-provider defaults
872
+ - `src/utils/yamlConfig.ts` - YAML config loader with validation and security checks
873
+ - `src/utils/configMerge.ts` - Multi-source config merge logic
874
+ - 106 new tests across 4 new test files (templates, yamlConfig, configMerge, init-config E2E)
875
+
876
+ ### Changed
877
+ - `InitOptions` interface extended with `config` and `template` fields
878
+ - `initCommand()` now processes YAML config and template before main flow
879
+ - Total commands: 19 (unchanged)
880
+ - Test count: 636 → 742
881
+ - Test suites: 36 → 40
882
+ - Coverage: 98%+ statements, 91%+ branches, 98%+ functions
883
+
884
+ ### Dependencies
885
+ - Added `js-yaml` (runtime) + `@types/js-yaml` (dev) - YAML parsing
886
+
887
+ ## [0.8.0] - 2026-02-21
888
+
889
+ ### Added
890
+ - **`quicklify backup [query]`** command - Backup Coolify database and config files
891
+ - `pg_dump` + gzip for PostgreSQL database backup
892
+ - Config tarball (`.env`, `docker-compose.yml`, `docker-compose.prod.yml`)
893
+ - SCP download to `~/.quicklify/backups/{server-name}/{timestamp}/`
894
+ - `manifest.json` with server info, Coolify version, file list
895
+ - `--dry-run` flag to preview backup steps
896
+ - **`quicklify restore [query]`** command - Restore Coolify from a backup
897
+ - Interactive backup selection from available backups
898
+ - `--backup <timestamp>` flag to skip selection prompt
899
+ - Double confirmation safety (confirm + type server name)
900
+ - Full restore flow: upload → stop Coolify → start DB → restore DB → restore config → start Coolify
901
+ - `--dry-run` flag to preview restore steps
902
+ - **`quicklify export [path]`** command - Export server list to JSON file
903
+ - Default path: `./quicklify-export.json`
904
+ - Custom path: `quicklify export /path/to/file.json`
905
+ - **`quicklify import <path>`** command - Import servers from JSON file
906
+ - Format validation with field-level checking
907
+ - Duplicate detection by server ID (skips existing)
908
+ - **`--full-setup` flag** on `quicklify init` - Auto-configure firewall + SSH hardening after deploy
909
+ - Runs `firewallSetup()` + `secureSetup(force=true)` after Coolify health check
910
+ - Skips interactive confirmations in automated mode
911
+ - `BackupManifest` TypeScript interface
912
+ - `BACKUPS_DIR` config constant (`~/.quicklify/backups/`)
913
+ - `validateServerRecords()` pure function for import validation
914
+ - `scpDownload()` and `scpUpload()` SCP helpers using `spawn`
915
+ - `loadManifest()` and `listBackups()` backup utility functions
916
+ - Pure command builder functions for all backup/restore SSH operations
917
+ - 137 new tests across 4 new test files + 6 enhanced test files
918
+ - Provider test coverage: uploadSshKey, rebootServer, createServer with sshKeyIds
919
+ - Doctor, monitor, restart, status, healthCheck, ssh edge case coverage
920
+
921
+ ### Changed
922
+ - `firewallSetup()` now exported from `firewall.ts` (was private)
923
+ - `secureSetup()` now exported from `secure.ts` with `force` parameter to skip prompts
924
+ - Total commands: 15 19 (backup, restore, export, import)
925
+ - Test count: 499 → 636
926
+ - Test suites: 32 → 36
927
+ - Coverage: 98%+ statements, 90%+ branches, 98%+ functions
928
+ - Zero new npm dependencies added
929
+
930
+ ## [0.7.2] - 2026-02-21
931
+
932
+ ### Added
933
+ - **Auto SSH key upload** during `quicklify init` — detects local SSH key (`~/.ssh/id_ed25519.pub`, `id_rsa.pub`, `id_ecdsa.pub`) and uploads to provider (DigitalOcean/Hetzner) automatically. Eliminates password requirement on first SSH login
934
+ - **Auto SSH key generation** — if no SSH key exists, generates ed25519 key pair automatically
935
+ - **Local config cleanup on destroy failure** — when `quicklify destroy` fails (server already deleted), prompts to remove from local config
936
+
937
+ ### Fixed
938
+ - **Fail2ban heredoc bug** heredoc delimiter was not recognized when joined with `&&` chain, causing invalid config file and fail2ban crash. Replaced with `printf`
939
+ - **Fail2ban systemd backend** — added `python3-systemd` package (required for `backend = systemd` on Ubuntu)
940
+
941
+ ## [0.7.1] - 2026-02-20
942
+
943
+ ### Fixed
944
+ - **Domain command rewritten for Coolify v4** - Uses PostgreSQL `instance_settings` table instead of `.env` APP_URL
945
+ - Domain add now uses `docker compose -f docker-compose.yml -f docker-compose.prod.yml restart` (fixes compose error)
946
+ - Coolify existence check uses `docker ps` container check instead of `.env` file check
947
+ - DNS check fallback to `getent ahosts` (works on servers without `dig`/`dnsutils`)
948
+ - SSH restart compatibility: fallback `systemctl restart ssh` for Ubuntu/Debian (was `sshd` only)
949
+
950
+ ## [0.7.0] - 2026-02-20
951
+
952
+ ### Added
953
+ - **`quicklify firewall [subcommand]`** command - Manage server firewall (UFW)
954
+ - `setup` - Install UFW + configure Coolify ports (80, 443, 8000, 6001, 6002) + SSH (22)
955
+ - `add` - Open a port (`--port`, `--protocol tcp|udp`)
956
+ - `remove` - Close a port (port 22 protected, Coolify ports warn before removal)
957
+ - `list` - Show current firewall rules
958
+ - `status` - Check UFW active/inactive state
959
+ - **`quicklify domain [subcommand]`** command - Manage server domain and SSL
960
+ - `add` - Bind domain to Coolify (`--domain`, `--no-ssl` to disable HTTPS)
961
+ - `remove` - Remove domain, revert to IP:8000
962
+ - `check` - Verify DNS A record matches server IP
963
+ - `list` - Show current APP_URL configuration
964
+ - **`quicklify secure [subcommand]`** command - SSH hardening and fail2ban
965
+ - `setup` - Disable password auth, set root login to key-only, install fail2ban (requires SSH key check + double confirmation)
966
+ - `status` - Show current SSH security settings
967
+ - `audit` - Detailed security report with score (0-4)
968
+ - `--dry-run` flag on all three commands - Preview commands without executing
969
+ - Protected port system: port 22 cannot be removed via `firewall remove`
970
+ - Coolify port warnings: removing ports 80/443/8000/6001/6002 requires confirmation
971
+ - SSH key safety check: `secure setup` refuses to run if no authorized_keys found
972
+ - Pure functions for all commands (unit-testable): `isValidPort`, `isProtectedPort`, `buildUfwRuleCommand`, `parseUfwStatus`, `isValidDomain`, `sanitizeDomain`, `buildSetFqdnCommand`, `parseDnsResult`, `parseFqdn`, `parseSshdConfig`, `parseAuditResult`, `buildHardeningCommand`, `buildFail2banCommand`
973
+ - `FirewallRule`, `FirewallStatus`, `SshdSetting`, `SecureAuditResult` TypeScript interfaces
974
+ - 140 new tests across 3 test files (firewall, domain, secure)
975
+
976
+ ### Changed
977
+ - Total commands: 12 → 15
978
+ - Test count: 354 → 494
979
+ - Test suites: 29 → 32
980
+ - Coverage maintained: 97%+ statements, 85%+ branches, 96%+ functions
981
+ - Zero new npm dependencies added
982
+
983
+ ## [0.6.0] - 2026-02-20
984
+
985
+ ### Added
986
+ - **`quicklify logs [query]`** command - View Coolify, Docker, or system logs via SSH
987
+ - `--lines N` (default 50), `--follow` (real-time streaming), `--service coolify|docker|system`
988
+ - **`quicklify monitor [query]`** command - Show CPU, RAM, Disk usage via SSH
989
+ - `--containers` flag to display Docker container list
990
+ - **`quicklify health`** command - Bulk health check of all registered servers
991
+ - Parallel HTTP checks with response time measurement and table output
992
+ - **`quicklify doctor`** command - Local environment diagnostics
993
+ - Checks Node.js version, npm, SSH client, config directory, registered servers
994
+ - `--check-tokens` flag for future provider token validation
995
+ - `sshStream()` SSH helper - Spawns SSH with `stdio: "inherit"` for real-time log streaming
996
+ - `parseMetrics()` pure function for parsing `top`/`free`/`df` output
997
+ - `buildLogCommand()` pure function for service-to-command mapping
998
+ - `checkServerHealth()` function for individual server HTTP health checks
999
+ - 43 new tests across 5 test files (doctor, health-command, logs, monitor, ssh-utils)
1000
+
1001
+ ### Changed
1002
+ - Test count: 311 354
1003
+ - Test suites: 25 29
1004
+ - Coverage maintained: 97%+ statements, 87%+ branches, 96%+ functions
1005
+ - Zero new npm dependencies added
1006
+
1007
+ ## [0.5.0] - 2026-02-20
1008
+
1009
+ ### Added
1010
+ - **`quicklify config`** command - Manage default configuration (`set`, `get`, `list`, `reset`)
1011
+ - **`quicklify ssh [query]`** command - SSH into a registered server (interactive or `--command` mode)
1012
+ - **`quicklify update [query]`** command - Update Coolify on a registered server via SSH
1013
+ - **`quicklify restart [query]`** command - Restart a server via provider API (Hetzner + DigitalOcean)
1014
+ - `rebootServer()` method on `CloudProvider` interface (Hetzner + DigitalOcean implementations)
1015
+ - Shared `resolveServer()` and `promptApiToken()` utilities (`src/utils/serverSelect.ts`)
1016
+ - Default config management via `~/.quicklify/config.json` (`src/utils/defaults.ts`)
1017
+ - SSH helper utilities: `checkSshAvailable()`, `sshConnect()`, `sshExec()` (`src/utils/ssh.ts`)
1018
+ - `QuicklifyConfig` TypeScript interface
1019
+ - 65 new tests across 7 new test files
1020
+ - SSH availability detection for Windows/Linux/macOS
1021
+
1022
+ ### Changed
1023
+ - Extracted duplicate `selectServer()` into shared utility (DRY refactor)
1024
+ - Refactored `status` and `destroy` commands to use shared `resolveServer` + `promptApiToken`
1025
+ - Test count: 246 311
1026
+ - Coverage maintained: 97%+ statements, 88%+ branches
1027
+
1028
+ ## [0.4.1] - 2026-02-20
1029
+
1030
+ ### Security
1031
+ - **Environment variable token support** - Use `HETZNER_TOKEN` / `DIGITALOCEAN_TOKEN` env vars instead of `--token` flag to avoid shell history and `ps aux` exposure
1032
+ - Config directory (`~/.quicklify/`) created with `0o700` permissions (owner only)
1033
+ - Cloud-init install log restricted to `chmod 600` (root read/write only)
1034
+ - Server name validation strengthened: 3-63 chars, must start with letter, end with letter/number
1035
+ - SSL/HTTPS setup warnings added to `init` and `status` command output
1036
+ - Updated `SECURITY.md` with current security measures and DigitalOcean API v2
1037
+
1038
+ ### Changed
1039
+ - ESLint upgraded from v9 to v10 (new `preserve-caught-error` rule compliance)
1040
+ - Updated dependencies: axios 1.13, chalk 5.6, commander 14, ora 9, tsx 4.21, typescript 5.9
1041
+ - Minimum Node.js version: 20 (ESLint 10 + ora 9 + commander 14 requirement)
1042
+ - CI matrix: 3 OS x 2 Node versions (dropped Node 18)
1043
+ - Non-interactive mode now detected by `--provider` flag alone (token can come from env var)
1044
+ - `--token` option description updated to mention env var alternatives
1045
+
1046
+ ## [0.4.0] - 2026-02-20
1047
+
1048
+ ### Added
1049
+ - **`quicklify list`** command - List all registered servers (no token required)
1050
+ - **`quicklify status [query]`** command - Check server and Coolify status by IP or name
1051
+ - **`quicklify destroy [query]`** command - Destroy a server with double confirmation safety
1052
+ - **Non-interactive mode** for `quicklify init` with `--provider`, `--token`, `--region`, `--size`, `--name` flags
1053
+ - **Coolify health check polling** - Replaces blind wait with intelligent `http://IP:8000` polling
1054
+ - **Server record persistence** - Successful deploys saved to `~/.quicklify/servers.json`
1055
+ - `ServerRecord` and `InitOptions` TypeScript interfaces
1056
+ - `src/utils/config.ts` - Config module for server record CRUD (`getServers`, `saveServer`, `removeServer`, `findServer`)
1057
+ - `src/utils/providerFactory.ts` - Provider factory extracted from init.ts for better testability
1058
+ - `src/utils/healthCheck.ts` - `waitForCoolify()` with configurable polling (min wait + 5s interval + max attempts)
1059
+ - `destroyServer()` method on `CloudProvider` interface (Hetzner + DigitalOcean implementations)
1060
+ - 86 new tests: config, list, status, destroy, healthCheck, providerFactory, edge cases, E2E flows
1061
+ - Edge case test coverage: config corruption, health check retries, non-interactive validation
1062
+
1063
+ ### Changed
1064
+ - `initCommand` now accepts `InitOptions` parameter for non-interactive mode
1065
+ - Init flow uses `waitForCoolify()` instead of fixed `setTimeout` (faster with early exit on success)
1066
+ - Init flow saves server record to local config after successful deploy
1067
+ - Success message now includes `quicklify status` and `quicklify list` hints
1068
+ - Provider creation extracted to `providerFactory.ts` (no behavior change)
1069
+ - Test count: 145 233
1070
+ - Coverage maintained: 97%+ statements, 89%+ branches, 96%+ functions
1071
+
1072
+ ### Fixed
1073
+ - Non-interactive mode properly exits with code 1 on invalid provider or token
1074
+ - Health check accepts any HTTP response (200, 302, 401, 500) as "Coolify is running"
1075
+ - `destroy` now removes local config record when server already deleted from provider ("not found")
1076
+
1077
+ ## [0.3.1] - 2026-02-19
1078
+
1079
+ ### Fixed
1080
+ - Hetzner pricing now shows net prices (excl. VAT) matching website display
1081
+ - Hetzner server types filtered by `/datacenters` API for real availability
1082
+ - Replaced deprecated Hetzner server types (cpx→cx23/cx33, per Jan 2026 deprecation)
1083
+ - "Server name already used" error now prompts for a new name instead of crashing
1084
+ - Location disabled retry now re-prompts for both region and server type
1085
+ - Back navigation in error retry flows (server type region)
1086
+ - Updated static fallback prices to match current Hetzner net pricing
1087
+
1088
+ ### Changed
1089
+ - `getLocationConfig` now accepts `exclude` parameter to filter disabled locations
1090
+
1091
+ ## [0.3.0] - 2026-02-19
1092
+
1093
+ ### Added
1094
+ - DigitalOcean provider implementation (full API integration)
1095
+ - Provider selection UI prompt (Hetzner Cloud / DigitalOcean)
1096
+ - `getProviderConfig()` prompt function
1097
+ - DigitalOcean-specific interfaces (`DORegion`, `DOSize`, `DOErrorResponse`)
1098
+ - Step-based back navigation with `← Back` option in all prompts
1099
+ - `getServerDetails()` + IP refresh for DigitalOcean delayed IP assignment
1100
+ - Minimum 2GB RAM + 2 vCPU filter for Coolify requirements
1101
+ - Network connectivity wait loop in cloud-init (DigitalOcean cloud-init timing fix)
1102
+ - Installation logging to `/var/log/quicklify-install.log` for troubleshooting
1103
+ - Troubleshooting info in deployment success message
1104
+ - Location retry on "server location disabled" error (offers region change)
1105
+ - 50+ new tests (DigitalOcean integration, provider selection, E2E flows)
1106
+
1107
+ ### Changed
1108
+ - `init` command now prompts for provider selection instead of defaulting to Hetzner
1109
+ - DigitalOcean image changed from Ubuntu 24.04 to 22.04 (stable cloud-init support)
1110
+ - Hetzner server type filtering now uses `/datacenters` API for real availability
1111
+ - Replaced deprecated Hetzner server types (cpx→cx23/cx33, per Jan 2026 deprecation)
1112
+ - Provider-specific deployment timing (Hetzner ~5 min, DigitalOcean ~7 min)
1113
+ - Cloud-init script now uses `set +e` for resilient execution
1114
+ - UFW firewall support for DigitalOcean (alongside iptables for Hetzner)
1115
+ - Updated `typescript-eslint` from 8.55 to 8.56
1116
+ - Test count: 95 → 143+
1117
+
1118
+ ### Fixed
1119
+ - Hetzner deprecated server types (cpx11, cx22 etc.) shown but failing on creation
1120
+ - DigitalOcean cloud-init failing due to network not ready at script execution time
1121
+ - Hetzner pricing now shows net prices (excl. VAT) matching website display
1122
+ - Coverage gaps in Hetzner provider (price null fallback, error.data.error undefined)
1123
+
1124
+ ## [0.2.8] - 2026-02-16
1125
+
1126
+ ### Added
1127
+ - ESLint 9 + typescript-eslint 8 + Prettier setup with npm scripts
1128
+ - `.prettierrc` and `eslint.config.js` configuration files
1129
+ - `CHANGELOG.md` with full version history
1130
+ - `CONTRIBUTING.md` with development guide and PR process
1131
+ - Proper TypeScript interfaces for Hetzner API responses (`HetznerLocation`, `HetznerServerType`, `HetznerPrice`, `HetznerErrorResponse`)
1132
+ - `isAxiosError` mock in test helpers
1133
+
1134
+ ### Changed
1135
+ - Replaced all `catch (error: any)` with `catch (error: unknown)` + proper type guards
1136
+ - Replaced `any` type annotations with proper interfaces in Hetzner provider
1137
+ - Applied Prettier formatting across all source files
1138
+
1139
+ ## [0.2.7] - 2026-02-16
1140
+
1141
+ ### Changed
1142
+ - Updated README with accurate feature descriptions and missing version history
1143
+ - Fixed inaccurate SECURITY.md claims (token handling, SDK references)
1144
+ - Added npm keywords for better discoverability (vps, cloud, automation, self-hosted, paas, devops, server)
1145
+
1146
+ ### Security
1147
+ - Added server name sanitization in cloud-init script (defense-in-depth)
1148
+
1149
+ ## [0.2.6] - 2026-02-16
1150
+
1151
+ ### Changed
1152
+ - CI: Upgraded Codecov action to v5
1153
+
1154
+ ## [0.2.5] - 2026-02-16
1155
+
1156
+ ### Added
1157
+ - CI: Codecov integration for automatic coverage badge
1158
+
1159
+ ## [0.2.4] - 2026-02-15
1160
+
1161
+ ### Changed
1162
+ - Refactor: Removed recommended label from server type selection
1163
+ - Excluded failed server types from retry list
1164
+
1165
+ ## [0.2.3] - 2026-02-15
1166
+
1167
+ ### Fixed
1168
+ - Unsupported server type error now triggers retry
1169
+ - Dynamic deployment summary based on actual server config
1170
+ - Dynamic recommended server type selection
1171
+
1172
+ ## [0.2.2] - 2026-02-15
1173
+
1174
+ ### Added
1175
+ - Deprecated server type filtering
1176
+ - Retry mechanism for unavailable server types
1177
+
1178
+ ## [0.2.1] - 2026-02-14
1179
+
1180
+ ### Fixed
1181
+ - URL protocol changed from https to http for initial Coolify setup
1182
+
1183
+ ## [0.2.0] - 2026-02-14
1184
+
1185
+ ### Added
1186
+ - Dynamic server type filtering based on selected location
1187
+ - Auto firewall configuration (ports 8000, 22, 80, 443)
1188
+
1189
+ ### Changed
1190
+ - Improved price formatting
1191
+
1192
+ ### Removed
1193
+ - Debug logs
1194
+
1195
+ ## [0.1.11] - 2026-02-14
1196
+
1197
+ ### Changed
1198
+ - Removed tracked Claude Code local settings
1199
+
1200
+ ### Added
1201
+ - Firewall rules to cloud-init
1202
+ - Security notes to README
1203
+
1204
+ ## [0.1.10] - 2026-02-14
1205
+
1206
+ ### Fixed
1207
+ - Updated deploy time estimate from 60 seconds to 4 minutes
1208
+
1209
+ ## [0.1.9] - 2026-02-14
1210
+
1211
+ ### Fixed
1212
+ - Read version from package.json dynamically
1213
+
1214
+ ## [0.1.8] - 2026-02-14
1215
+
1216
+ ### Fixed
1217
+ - Added build step to publish workflow
1218
+
1219
+ ## [0.1.7] - 2026-02-14
1220
+
1221
+ ### Fixed
1222
+ - Added .npmignore to include dist/ in npm package
1223
+
1224
+ ## [0.1.6] - 2026-02-14
1225
+
1226
+ ### Fixed
1227
+ - Added bin wrapper for Windows npx compatibility
1228
+
1229
+ ## [0.1.5] - 2026-02-14
1230
+
1231
+ ### Fixed
1232
+ - Added files field to include dist/ in npm package
1233
+
1234
+ ## [0.1.4] - 2026-02-14
1235
+
1236
+ ### Added
1237
+ - SECURITY.md with security policy
1238
+ - Socket.dev security badge
1239
+ - Package.json metadata (repository, bugs, homepage, author)
1240
+
1241
+ ## [0.1.3] - 2026-02-14
1242
+
1243
+ ### Added
1244
+ - Auto npm publish workflow via GitHub Actions
1245
+ - GitHub stars badge to README
1246
+
1247
+ ## [0.1.2] - 2026-02-14
1248
+
1249
+ ### Changed
1250
+ - Updated deploy time references from 60s to 4 minutes
1251
+
1252
+ ## [0.1.1] - 2026-02-14
1253
+
1254
+ ### Fixed
1255
+ - Corrected bin field in package.json
1256
+ - Added status badges to README
1257
+
1258
+ ## [0.1.0] - 2026-02-14
1259
+
1260
+ ### Added
1261
+ - Initial release
1262
+ - Hetzner Cloud integration
1263
+ - Interactive CLI with Commander.js + Inquirer.js
1264
+ - Automated Coolify installation via cloud-init
1265
+ - ARM64 support
1266
+ - Full test suite (unit, integration, e2e)