kastell 2.2.3 → 2.2.5

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