kastell 2.2.4 → 2.2.6

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