kastell 2.2.4 → 2.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +18 -18
- package/.claude-plugin/plugin.json +45 -38
- package/CHANGELOG.md +1313 -1266
- package/LICENSE +201 -201
- package/NOTICE +5 -5
- package/README.md +1 -1
- package/README.tr.md +1 -1
- package/bin/kastell +2 -2
- package/bin/kastell-mcp +5 -5
- package/dist/adapters/coolify.js +92 -92
- package/dist/adapters/dokploy.js +99 -99
- package/dist/commands/fix.d.ts +2 -0
- package/dist/commands/fix.d.ts.map +1 -1
- package/dist/commands/fix.js +26 -1
- package/dist/commands/fix.js.map +1 -1
- package/dist/commands/interactive/plugins.d.ts.map +1 -1
- package/dist/commands/interactive/plugins.js +26 -2
- package/dist/commands/interactive/plugins.js.map +1 -1
- package/dist/commands/plugin.d.ts.map +1 -1
- package/dist/commands/plugin.js +6 -2
- package/dist/commands/plugin.js.map +1 -1
- package/dist/core/audit/commands.d.ts +13 -2
- package/dist/core/audit/commands.d.ts.map +1 -1
- package/dist/core/audit/commands.js +39 -2
- package/dist/core/audit/commands.js.map +1 -1
- package/dist/core/audit/explainCheck.d.ts +1 -0
- package/dist/core/audit/explainCheck.d.ts.map +1 -1
- package/dist/core/audit/explainCheck.js +1 -1
- package/dist/core/audit/explainCheck.js.map +1 -1
- package/dist/core/audit/fix-history.d.ts +3 -1
- package/dist/core/audit/fix-history.d.ts.map +1 -1
- package/dist/core/audit/fix-history.js +6 -2
- package/dist/core/audit/fix-history.js.map +1 -1
- package/dist/core/audit/fix.d.ts.map +1 -1
- package/dist/core/audit/fix.js +22 -0
- package/dist/core/audit/fix.js.map +1 -1
- package/dist/core/audit/formatters/badge.js +20 -20
- package/dist/core/audit/index.d.ts.map +1 -1
- package/dist/core/audit/index.js +12 -3
- package/dist/core/audit/index.js.map +1 -1
- package/dist/core/audit/listChecks.d.ts.map +1 -1
- package/dist/core/audit/listChecks.js +24 -0
- package/dist/core/audit/listChecks.js.map +1 -1
- package/dist/core/audit/pluginAudit.d.ts +8 -0
- package/dist/core/audit/pluginAudit.d.ts.map +1 -0
- package/dist/core/audit/pluginAudit.js +134 -0
- package/dist/core/audit/pluginAudit.js.map +1 -0
- package/dist/core/audit/pluginFix.d.ts +19 -0
- package/dist/core/audit/pluginFix.d.ts.map +1 -0
- package/dist/core/audit/pluginFix.js +122 -0
- package/dist/core/audit/pluginFix.js.map +1 -0
- package/dist/core/audit/snapshot.d.ts +4 -4
- package/dist/core/audit/types.d.ts +2 -1
- package/dist/core/audit/types.d.ts.map +1 -1
- package/dist/core/completions.js +631 -631
- package/dist/core/plugin.d.ts +6 -0
- package/dist/core/plugin.d.ts.map +1 -1
- package/dist/core/plugin.js +2 -0
- package/dist/core/plugin.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/pluginTools.d.ts +5 -0
- package/dist/mcp/pluginTools.d.ts.map +1 -0
- package/dist/mcp/pluginTools.js +54 -0
- package/dist/mcp/pluginTools.js.map +1 -0
- package/dist/mcp/prompts/workflows.d.ts +17 -0
- package/dist/mcp/prompts/workflows.d.ts.map +1 -0
- package/dist/mcp/prompts/workflows.js +73 -0
- package/dist/mcp/prompts/workflows.js.map +1 -0
- package/dist/mcp/resources/checks.d.ts +4 -0
- package/dist/mcp/resources/checks.d.ts.map +1 -0
- package/dist/mcp/resources/checks.js +49 -0
- package/dist/mcp/resources/checks.js.map +1 -0
- package/dist/mcp/resources/servers.d.ts +4 -0
- package/dist/mcp/resources/servers.d.ts.map +1 -0
- package/dist/mcp/resources/servers.js +59 -0
- package/dist/mcp/resources/servers.js.map +1 -0
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +68 -35
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/serverAudit.d.ts +1 -1
- package/dist/mcp/tools/serverExplain.d.ts.map +1 -1
- package/dist/mcp/tools/serverExplain.js.map +1 -1
- package/dist/mcp/tools/serverFix.d.ts.map +1 -1
- package/dist/mcp/tools/serverFix.js +7 -1
- package/dist/mcp/tools/serverFix.js.map +1 -1
- package/dist/mcp/tools/serverFleet.d.ts.map +1 -1
- package/dist/mcp/tools/serverFleet.js.map +1 -1
- package/dist/mcp/tools/serverInfo.d.ts +1 -1
- package/dist/mcp/tools/serverInfo.js +1 -1
- package/dist/mcp/tools/serverManage.d.ts +2 -1
- package/dist/mcp/tools/serverManage.d.ts.map +1 -1
- package/dist/mcp/tools/serverManage.js +50 -5
- package/dist/mcp/tools/serverManage.js.map +1 -1
- package/dist/mcp/tools/serverPlugin.d.ts +3 -0
- package/dist/mcp/tools/serverPlugin.d.ts.map +1 -1
- package/dist/mcp/tools/serverPlugin.js +11 -1
- package/dist/mcp/tools/serverPlugin.js.map +1 -1
- package/dist/mcp/tools/serverProvision.d.ts +5 -5
- package/dist/mcp/tools/serverProvision.d.ts.map +1 -1
- package/dist/mcp/tools/serverProvision.js +31 -9
- package/dist/mcp/tools/serverProvision.js.map +1 -1
- package/dist/mcp/tools/serverSecure.d.ts.map +1 -1
- package/dist/mcp/tools/serverSecure.js +30 -1
- package/dist/mcp/tools/serverSecure.js.map +1 -1
- package/dist/mcp/utils.d.ts +25 -0
- package/dist/mcp/utils.d.ts.map +1 -1
- package/dist/mcp/utils.js +36 -0
- package/dist/mcp/utils.js.map +1 -1
- package/dist/mcp-bundle.mjs +102301 -0
- package/dist/plugin/handlerResolver.d.ts +2 -0
- package/dist/plugin/handlerResolver.d.ts.map +1 -0
- package/dist/plugin/handlerResolver.js +16 -0
- package/dist/plugin/handlerResolver.js.map +1 -0
- package/dist/plugin/loader.d.ts.map +1 -1
- package/dist/plugin/loader.js +41 -4
- package/dist/plugin/loader.js.map +1 -1
- package/dist/plugin/registerCommands.d.ts +4 -0
- package/dist/plugin/registerCommands.d.ts.map +1 -0
- package/dist/plugin/registerCommands.js +45 -0
- package/dist/plugin/registerCommands.js.map +1 -0
- package/dist/plugin/registry.d.ts +20 -1
- package/dist/plugin/registry.d.ts.map +1 -1
- package/dist/plugin/registry.js +51 -1
- package/dist/plugin/registry.js.map +1 -1
- package/dist/plugin/sdk/constants.d.ts +2 -0
- package/dist/plugin/sdk/constants.d.ts.map +1 -1
- package/dist/plugin/sdk/constants.js +2 -0
- package/dist/plugin/sdk/constants.js.map +1 -1
- package/dist/plugin/sdk/types.d.ts +74 -1
- package/dist/plugin/sdk/types.d.ts.map +1 -1
- package/dist/plugin/validate.d.ts +2 -1
- package/dist/plugin/validate.d.ts.map +1 -1
- package/dist/plugin/validate.js +106 -1
- package/dist/plugin/validate.js.map +1 -1
- package/dist/utils/cloudInit.js +58 -58
- package/dist/utils/fileLock.d.ts +5 -1
- package/dist/utils/fileLock.d.ts.map +1 -1
- package/dist/utils/fileLock.js +70 -15
- package/dist/utils/fileLock.js.map +1 -1
- package/dist/utils/paths.d.ts +0 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +1 -2
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/secureWrite.d.ts.map +1 -1
- package/dist/utils/secureWrite.js +3 -38
- package/dist/utils/secureWrite.js.map +1 -1
- package/dist/utils/version.d.ts.map +1 -1
- package/dist/utils/version.js +19 -4
- package/dist/utils/version.js.map +1 -1
- package/kastell-plugin/.claude-plugin/plugin.json +20 -20
- package/kastell-plugin/.mcp.json +15 -8
- package/kastell-plugin/README.md +113 -113
- package/kastell-plugin/agents/kastell-auditor.md +77 -77
- package/kastell-plugin/agents/scripts/bucket_mapper.sh +101 -101
- package/kastell-plugin/agents/scripts/trend_report.sh +91 -91
- package/kastell-plugin/hooks/destroy-block.cjs +31 -31
- package/kastell-plugin/hooks/hooks.json +57 -57
- package/kastell-plugin/hooks/pre-commit-audit-guard.cjs +75 -75
- package/kastell-plugin/hooks/session-audit.cjs +86 -86
- package/kastell-plugin/hooks/session-log.cjs +56 -56
- package/kastell-plugin/hooks/stop-quality-check.cjs +72 -72
- package/kastell-plugin/skills/kastell-careful/SKILL.md +64 -64
- package/kastell-plugin/skills/kastell-ops/SKILL.md +139 -139
- package/kastell-plugin/skills/kastell-ops/references/commands.md +45 -45
- package/kastell-plugin/skills/kastell-ops/references/mcp-tools.md +50 -50
- package/kastell-plugin/skills/kastell-ops/references/patterns.md +145 -145
- package/kastell-plugin/skills/kastell-ops/references/pitfalls.md +136 -136
- package/kastell-plugin/skills/kastell-ops/scripts/check_coverage.sh +101 -101
- package/kastell-plugin/skills/kastell-ops/scripts/fleet_report.sh +73 -73
- package/kastell-plugin/skills/kastell-ops/scripts/parse_audit.sh +76 -76
- package/kastell-plugin/skills/kastell-research/SKILL.md +90 -90
- package/kastell-plugin/skills/kastell-scaffold/SKILL.md +104 -104
- package/kastell-plugin/skills/kastell-scaffold/references/template-audit-check.md +150 -150
- package/kastell-plugin/skills/kastell-scaffold/references/template-command.md +80 -80
- package/kastell-plugin/skills/kastell-scaffold/references/template-mcp-tool.md +72 -72
- package/kastell-plugin/skills/kastell-scaffold/references/template-provider.md +67 -67
- package/kastell-plugin/skills/kastell-scaffold/scripts/scaffold.sh +180 -180
- package/kastell-plugin/skills/kastell-scaffold/templates/check-test.ts.tpl +27 -27
- package/kastell-plugin/skills/kastell-scaffold/templates/check.ts.tpl +50 -50
- package/kastell-plugin/skills/kastell-scaffold/templates/command-core.ts.tpl +18 -18
- package/kastell-plugin/skills/kastell-scaffold/templates/command-test.ts.tpl +17 -17
- package/kastell-plugin/skills/kastell-scaffold/templates/command.ts.tpl +25 -25
- package/kastell-plugin/skills/kastell-scaffold/templates/mcp-tool-test.ts.tpl +30 -30
- package/kastell-plugin/skills/kastell-scaffold/templates/mcp-tool.ts.tpl +29 -29
- package/kastell-plugin/skills/kastell-scaffold/templates/provider-test.ts.tpl +34 -34
- package/kastell-plugin/skills/kastell-scaffold/templates/provider.ts.tpl +32 -32
- package/package.json +125 -122
- package/dist/commands/interactive.d.ts +0 -11
- package/dist/commands/interactive.d.ts.map +0 -1
- package/dist/commands/interactive.js +0 -1079
- package/dist/commands/interactive.js.map +0 -1
- package/dist/core/lock.d.ts +0 -66
- package/dist/core/lock.d.ts.map +0 -1
- package/dist/core/lock.js +0 -556
- package/dist/core/lock.js.map +0 -1
package/dist/utils/cloudInit.js
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
1
|
export function getBareCloudInit(serverName) {
|
|
2
2
|
const safeName = serverName.toLowerCase().replace(/[^a-z0-9-]/g, "");
|
|
3
|
-
return `#!/bin/bash
|
|
4
|
-
set +e
|
|
5
|
-
touch /var/log/kastell-install.log
|
|
6
|
-
chmod 600 /var/log/kastell-install.log
|
|
7
|
-
exec > >(tee /var/log/kastell-install.log) 2>&1
|
|
8
|
-
|
|
9
|
-
echo "=================================="
|
|
10
|
-
echo "Kastell Bare Server Setup"
|
|
11
|
-
echo "Server: ${safeName}"
|
|
12
|
-
echo "=================================="
|
|
13
|
-
|
|
14
|
-
# Wait for network connectivity
|
|
15
|
-
echo "Waiting for network connectivity..."
|
|
16
|
-
MAX_ATTEMPTS=30
|
|
17
|
-
ATTEMPTS=0
|
|
18
|
-
while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do
|
|
19
|
-
if curl -s --max-time 5 https://apt.releases.hashicorp.com > /dev/null 2>&1 || curl -s --max-time 5 https://archive.ubuntu.com > /dev/null 2>&1; then
|
|
20
|
-
echo "Network is ready!"
|
|
21
|
-
break
|
|
22
|
-
fi
|
|
23
|
-
ATTEMPTS=$((ATTEMPTS + 1))
|
|
24
|
-
echo "Network not ready (attempt $ATTEMPTS/$MAX_ATTEMPTS)..."
|
|
25
|
-
sleep 2
|
|
26
|
-
done
|
|
27
|
-
|
|
28
|
-
# Update system packages
|
|
29
|
-
echo "Updating system packages..."
|
|
30
|
-
apt-get update -y
|
|
31
|
-
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y
|
|
32
|
-
|
|
33
|
-
# Install hardening packages
|
|
34
|
-
echo "Installing hardening packages (fail2ban, ufw, unattended-upgrades)..."
|
|
35
|
-
DEBIAN_FRONTEND=noninteractive apt-get install -y fail2ban ufw unattended-upgrades
|
|
36
|
-
|
|
37
|
-
# Configure UFW firewall
|
|
38
|
-
echo "Configuring UFW firewall..."
|
|
39
|
-
ufw allow 22/tcp
|
|
40
|
-
ufw allow 80/tcp
|
|
41
|
-
ufw allow 443/tcp
|
|
42
|
-
echo "y" | ufw enable || true
|
|
43
|
-
ufw status
|
|
44
|
-
|
|
45
|
-
# Configure unattended-upgrades for automatic security updates
|
|
46
|
-
echo "Configuring unattended-upgrades..."
|
|
47
|
-
dpkg-reconfigure -f noninteractive unattended-upgrades
|
|
48
|
-
|
|
49
|
-
# Enable and start fail2ban
|
|
50
|
-
echo "Enabling fail2ban..."
|
|
51
|
-
systemctl enable fail2ban || true
|
|
52
|
-
systemctl start fail2ban || true
|
|
53
|
-
|
|
54
|
-
echo "=================================="
|
|
55
|
-
echo "Bare server setup completed!"
|
|
56
|
-
echo "Server: ${safeName}"
|
|
57
|
-
echo "=================================="
|
|
58
|
-
echo ""
|
|
59
|
-
echo "Your server is ready. Connect via SSH:"
|
|
60
|
-
echo " ssh root@YOUR_SERVER_IP"
|
|
3
|
+
return `#!/bin/bash
|
|
4
|
+
set +e
|
|
5
|
+
touch /var/log/kastell-install.log
|
|
6
|
+
chmod 600 /var/log/kastell-install.log
|
|
7
|
+
exec > >(tee /var/log/kastell-install.log) 2>&1
|
|
8
|
+
|
|
9
|
+
echo "=================================="
|
|
10
|
+
echo "Kastell Bare Server Setup"
|
|
11
|
+
echo "Server: ${safeName}"
|
|
12
|
+
echo "=================================="
|
|
13
|
+
|
|
14
|
+
# Wait for network connectivity
|
|
15
|
+
echo "Waiting for network connectivity..."
|
|
16
|
+
MAX_ATTEMPTS=30
|
|
17
|
+
ATTEMPTS=0
|
|
18
|
+
while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do
|
|
19
|
+
if curl -s --max-time 5 https://apt.releases.hashicorp.com > /dev/null 2>&1 || curl -s --max-time 5 https://archive.ubuntu.com > /dev/null 2>&1; then
|
|
20
|
+
echo "Network is ready!"
|
|
21
|
+
break
|
|
22
|
+
fi
|
|
23
|
+
ATTEMPTS=$((ATTEMPTS + 1))
|
|
24
|
+
echo "Network not ready (attempt $ATTEMPTS/$MAX_ATTEMPTS)..."
|
|
25
|
+
sleep 2
|
|
26
|
+
done
|
|
27
|
+
|
|
28
|
+
# Update system packages
|
|
29
|
+
echo "Updating system packages..."
|
|
30
|
+
apt-get update -y
|
|
31
|
+
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y
|
|
32
|
+
|
|
33
|
+
# Install hardening packages
|
|
34
|
+
echo "Installing hardening packages (fail2ban, ufw, unattended-upgrades)..."
|
|
35
|
+
DEBIAN_FRONTEND=noninteractive apt-get install -y fail2ban ufw unattended-upgrades
|
|
36
|
+
|
|
37
|
+
# Configure UFW firewall
|
|
38
|
+
echo "Configuring UFW firewall..."
|
|
39
|
+
ufw allow 22/tcp
|
|
40
|
+
ufw allow 80/tcp
|
|
41
|
+
ufw allow 443/tcp
|
|
42
|
+
echo "y" | ufw enable || true
|
|
43
|
+
ufw status
|
|
44
|
+
|
|
45
|
+
# Configure unattended-upgrades for automatic security updates
|
|
46
|
+
echo "Configuring unattended-upgrades..."
|
|
47
|
+
dpkg-reconfigure -f noninteractive unattended-upgrades
|
|
48
|
+
|
|
49
|
+
# Enable and start fail2ban
|
|
50
|
+
echo "Enabling fail2ban..."
|
|
51
|
+
systemctl enable fail2ban || true
|
|
52
|
+
systemctl start fail2ban || true
|
|
53
|
+
|
|
54
|
+
echo "=================================="
|
|
55
|
+
echo "Bare server setup completed!"
|
|
56
|
+
echo "Server: ${safeName}"
|
|
57
|
+
echo "=================================="
|
|
58
|
+
echo ""
|
|
59
|
+
echo "Your server is ready. Connect via SSH:"
|
|
60
|
+
echo " ssh root@YOUR_SERVER_IP"
|
|
61
61
|
`;
|
|
62
62
|
}
|
|
63
63
|
//# sourceMappingURL=cloudInit.js.map
|
package/dist/utils/fileLock.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
/** Module-local wrapper for testability — DO NOT inline `process.kill`. */
|
|
2
|
+
export declare function probeProcess(pid: number): "alive" | "dead" | "unknown";
|
|
3
|
+
type ProbeFn = (pid: number) => "alive" | "dead" | "unknown";
|
|
4
|
+
export declare function withFileLock<T>(filePath: string, fn: () => Promise<T> | T, probe?: ProbeFn): Promise<T>;
|
|
2
5
|
/** Warn on stderr if a caught error is a permission issue. Returns true if it was a permission error. */
|
|
3
6
|
export declare function warnIfPermissionError(err: unknown, label: string): boolean;
|
|
7
|
+
export {};
|
|
4
8
|
//# sourceMappingURL=fileLock.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileLock.d.ts","sourceRoot":"","sources":["../../src/utils/fileLock.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fileLock.d.ts","sourceRoot":"","sources":["../../src/utils/fileLock.ts"],"names":[],"mappings":"AAQA,2EAA2E;AAC3E,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAStE;AAoBD,KAAK,OAAO,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAsB7D,wBAAsB,YAAY,CAAC,CAAC,EAClC,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EACxB,KAAK,GAAE,OAAsB,GAC5B,OAAO,CAAC,CAAC,CAAC,CA+CZ;AAED,yGAAyG;AACzG,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAO1E"}
|
package/dist/utils/fileLock.js
CHANGED
|
@@ -1,21 +1,78 @@
|
|
|
1
|
-
import { mkdirSync,
|
|
2
|
-
import { dirname } from "path";
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { mkdirSync, rmSync, statSync, writeFileSync, readFileSync } from "fs";
|
|
2
|
+
import { dirname, join } from "path";
|
|
3
|
+
import { hostname } from "os";
|
|
4
|
+
const STALE_THRESHOLD_MS = 30_000;
|
|
5
|
+
// Reclaim even when probeProcess reports "alive" (guards against clock drift, zombies, PID reuse).
|
|
6
|
+
const HARD_CEILING_MS = 60_000;
|
|
7
|
+
/** Module-local wrapper for testability — DO NOT inline `process.kill`. */
|
|
8
|
+
export function probeProcess(pid) {
|
|
9
|
+
try {
|
|
10
|
+
process.kill(pid, 0);
|
|
11
|
+
return "alive";
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
const code = err.code;
|
|
15
|
+
if (code === "ESRCH")
|
|
16
|
+
return "dead";
|
|
17
|
+
return "unknown";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function readPidFile(lockDir) {
|
|
21
|
+
try {
|
|
22
|
+
const raw = readFileSync(join(lockDir, "owner.pid"), "utf-8");
|
|
23
|
+
const parts = raw.split("@");
|
|
24
|
+
if (parts.length !== 3)
|
|
25
|
+
return null;
|
|
26
|
+
const pid = parseInt(parts[0], 10);
|
|
27
|
+
if (isNaN(pid) || pid <= 0)
|
|
28
|
+
return null;
|
|
29
|
+
return { pid, host: parts[1] };
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function shouldReclaimStaleLock(lockDir, probe) {
|
|
36
|
+
let mtimeMs;
|
|
37
|
+
try {
|
|
38
|
+
mtimeMs = statSync(lockDir).mtimeMs;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false; // lock disappeared between checks
|
|
42
|
+
}
|
|
43
|
+
const age = Date.now() - mtimeMs;
|
|
44
|
+
const parsed = readPidFile(lockDir);
|
|
45
|
+
if (parsed && parsed.host === hostname()) {
|
|
46
|
+
const liveness = probe(parsed.pid);
|
|
47
|
+
if (liveness === "dead")
|
|
48
|
+
return true;
|
|
49
|
+
if (liveness === "alive")
|
|
50
|
+
return age > HARD_CEILING_MS;
|
|
51
|
+
// "unknown" → mtime fallback (aggressive: STALE_THRESHOLD_MS)
|
|
52
|
+
}
|
|
53
|
+
// farklı hostname, parse fail, PID file yok, veya "unknown" → mtime fallback
|
|
54
|
+
return age > STALE_THRESHOLD_MS;
|
|
55
|
+
}
|
|
56
|
+
export async function withFileLock(filePath, fn, probe = probeProcess) {
|
|
5
57
|
const lockDir = filePath + ".lock";
|
|
6
58
|
const maxRetries = 10;
|
|
7
59
|
const retryDelay = 200;
|
|
8
|
-
// Ensure parent directory exists (CI runners may not have ~/.kastell/)
|
|
9
60
|
mkdirSync(dirname(lockDir), { recursive: true });
|
|
10
61
|
for (let i = 0; i < maxRetries; i++) {
|
|
11
62
|
try {
|
|
12
63
|
mkdirSync(lockDir);
|
|
13
64
|
try {
|
|
65
|
+
try {
|
|
66
|
+
writeFileSync(join(lockDir, "owner.pid"), `${process.pid}@${hostname()}@${Date.now()}`, { encoding: "utf-8" });
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
/* best effort — if PID write fails, mtime fallback still protects */
|
|
70
|
+
}
|
|
14
71
|
return await fn();
|
|
15
72
|
}
|
|
16
73
|
finally {
|
|
17
74
|
try {
|
|
18
|
-
|
|
75
|
+
rmSync(lockDir, { recursive: true, force: true });
|
|
19
76
|
}
|
|
20
77
|
catch {
|
|
21
78
|
/* best effort */
|
|
@@ -24,16 +81,14 @@ export async function withFileLock(filePath, fn) {
|
|
|
24
81
|
}
|
|
25
82
|
catch (err) {
|
|
26
83
|
if (err.code === "EEXIST") {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (Date.now() - stat.mtimeMs > STALE_THRESHOLD_MS) {
|
|
31
|
-
rmdirSync(lockDir);
|
|
32
|
-
continue;
|
|
84
|
+
if (shouldReclaimStaleLock(lockDir, probe)) {
|
|
85
|
+
try {
|
|
86
|
+
rmSync(lockDir, { recursive: true, force: true });
|
|
33
87
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
88
|
+
catch {
|
|
89
|
+
/* best effort, retry */
|
|
90
|
+
}
|
|
91
|
+
continue;
|
|
37
92
|
}
|
|
38
93
|
await new Promise((r) => setTimeout(r, retryDelay));
|
|
39
94
|
continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileLock.js","sourceRoot":"","sources":["../../src/utils/fileLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"fileLock.js","sourceRoot":"","sources":["../../src/utils/fileLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAE9B,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAClC,mGAAmG;AACnG,MAAM,eAAe,GAAG,MAAM,CAAC;AAE/B,2EAA2E;AAC3E,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,IAAI,IAAI,KAAK,OAAO;YAAE,OAAO,MAAM,CAAC;QACpC,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAOD,SAAS,WAAW,CAAC,OAAe;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;QAC9D,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACpC,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACnC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACxC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAID,SAAS,sBAAsB,CAAC,OAAe,EAAE,KAAc;IAC7D,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC,CAAC,kCAAkC;IAClD,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC;IACjC,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAEpC,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,EAAE,CAAC;QACzC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,QAAQ,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;QACrC,IAAI,QAAQ,KAAK,OAAO;YAAE,OAAO,GAAG,GAAG,eAAe,CAAC;QACvD,8DAA8D;IAChE,CAAC;IACD,6EAA6E;IAC7E,OAAO,GAAG,GAAG,kBAAkB,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAgB,EAChB,EAAwB,EACxB,QAAiB,YAAY;IAE7B,MAAM,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACnC,MAAM,UAAU,GAAG,EAAE,CAAC;IACtB,MAAM,UAAU,GAAG,GAAG,CAAC;IAEvB,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,SAAS,CAAC,OAAO,CAAC,CAAC;YACnB,IAAI,CAAC;gBACH,IAAI,CAAC;oBACH,aAAa,CACX,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,EAC1B,GAAG,OAAO,CAAC,GAAG,IAAI,QAAQ,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,EAC5C,EAAE,QAAQ,EAAE,OAAO,EAAE,CACtB,CAAC;gBACJ,CAAC;gBAAC,MAAM,CAAC;oBACP,qEAAqE;gBACvE,CAAC;gBACD,OAAO,MAAM,EAAE,EAAE,CAAC;YACpB,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC;oBACH,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBACpD,CAAC;gBAAC,MAAM,CAAC;oBACP,iBAAiB;gBACnB,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrD,IAAI,sBAAsB,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC;oBAC3C,IAAI,CAAC;wBACH,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;oBACpD,CAAC;oBAAC,MAAM,CAAC;wBACP,wBAAwB;oBAC1B,CAAC;oBACD,SAAS;gBACX,CAAC;gBACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;gBACpD,SAAS;YACX,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CACb,6BAA6B,QAAQ,UAAU,UAAU,UAAU,CACpE,CAAC;AACJ,CAAC;AAED,yGAAyG;AACzG,MAAM,UAAU,qBAAqB,CAAC,GAAY,EAAE,KAAa;IAC/D,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;IACjD,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QAC1C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC;QAClE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/utils/paths.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAGA,
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,QAAyD,CAAC;AAElF,4CAA4C;AAC5C,eAAO,MAAM,WAAW,QAA+B,CAAC;AAExD,kDAAkD;AAClD,eAAO,MAAM,YAAY,QAAoC,CAAC;AAE9D,oDAAoD;AACpD,eAAO,MAAM,WAAW,QAA+B,CAAC;AAExD,2DAA2D;AAC3D,eAAO,MAAM,oBAAoB,QAAoC,CAAC"}
|
package/dist/utils/paths.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { homedir } from "os";
|
|
2
2
|
import { join } from "path";
|
|
3
|
-
|
|
4
|
-
export const KASTELL_DIR = join(homedir(), ".kastell");
|
|
3
|
+
export const KASTELL_DIR = process.env.KASTELL_DIR || join(homedir(), ".kastell");
|
|
5
4
|
/** Backups directory: ~/.kastell/backups */
|
|
6
5
|
export const BACKUPS_DIR = join(KASTELL_DIR, "backups");
|
|
7
6
|
/** Security audit log: ~/.kastell/security.log */
|
package/dist/utils/paths.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AAElF,4CAA4C;AAC5C,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AAExD,kDAAkD;AAClD,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;AAE9D,oDAAoD;AACpD,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AAExD,2DAA2D;AAC3D,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secureWrite.d.ts","sourceRoot":"","sources":["../../src/utils/secureWrite.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"secureWrite.d.ts","sourceRoot":"","sources":["../../src/utils/secureWrite.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAOD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAMrD;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,gBAAgB,GACzB,IAAI,CAGN;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAChC,IAAI,CAGN"}
|
|
@@ -1,47 +1,12 @@
|
|
|
1
|
-
import { spawnSync } from "child_process";
|
|
2
1
|
import { writeFileSync, mkdirSync, chmodSync } from "fs";
|
|
3
|
-
import { userInfo } from "os";
|
|
4
|
-
import { SecurityLogger } from "./securityLogger.js";
|
|
5
|
-
import { extractReason } from "./errors.js";
|
|
6
|
-
let cachedUsername;
|
|
7
|
-
function getUsername() {
|
|
8
|
-
if (!cachedUsername)
|
|
9
|
-
cachedUsername = userInfo().username;
|
|
10
|
-
return cachedUsername;
|
|
11
|
-
}
|
|
12
2
|
const securedDirs = new Set();
|
|
13
3
|
export function clearCache() {
|
|
14
4
|
securedDirs.clear();
|
|
15
|
-
cachedUsername = undefined;
|
|
16
5
|
}
|
|
17
6
|
function applyPermissions(targetPath, mode) {
|
|
18
|
-
if (process.platform === "win32")
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"/inheritance:r",
|
|
22
|
-
"/grant:r",
|
|
23
|
-
`${getUsername()}:F`,
|
|
24
|
-
]);
|
|
25
|
-
if (result.status !== 0) {
|
|
26
|
-
SecurityLogger.warn("ACL operation failed", {
|
|
27
|
-
path: targetPath,
|
|
28
|
-
platform: process.platform,
|
|
29
|
-
error: result.stderr?.toString() ?? "unknown",
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
try {
|
|
35
|
-
chmodSync(targetPath, mode);
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
SecurityLogger.warn("chmod operation failed", {
|
|
39
|
-
path: targetPath,
|
|
40
|
-
platform: process.platform,
|
|
41
|
-
error: extractReason(error),
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
}
|
|
7
|
+
if (process.platform === "win32")
|
|
8
|
+
return; // ACL hardening → v2.4 backlog
|
|
9
|
+
chmodSync(targetPath, mode);
|
|
45
10
|
}
|
|
46
11
|
export function ensureSecureDir(dirPath) {
|
|
47
12
|
if (securedDirs.has(dirPath)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secureWrite.js","sourceRoot":"","sources":["../../src/utils/secureWrite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"secureWrite.js","sourceRoot":"","sources":["../../src/utils/secureWrite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAOzD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;AAEtC,MAAM,UAAU,UAAU;IACxB,WAAW,CAAC,KAAK,EAAE,CAAC;AACtB,CAAC;AAED,SAAS,gBAAgB,CAAC,UAAkB,EAAE,IAAmB;IAC/D,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,CAAC,+BAA+B;IACzE,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,IAAI,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,OAAO;IACT,CAAC;IACD,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACjC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,IAAY,EACZ,OAA0B;IAE1B,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACvC,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,OAAe,EACf,OAAiC;IAEjC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,IAAI,EAAE,CAAC,CAAC;IAC9D,eAAe,CAAC,OAAO,CAAC,CAAC;AAC3B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/utils/version.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/utils/version.ts"],"names":[],"mappings":"AAkBA,wBAAgB,iBAAiB,IAAI,MAAM,CAW1C;AAED,eAAO,MAAM,eAAe,QAAsB,CAAC;AAEnD,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
package/dist/utils/version.js
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
|
-
import { readFileSync } from "fs";
|
|
2
|
-
import { join } from "path";
|
|
1
|
+
import { readFileSync, existsSync } from "fs";
|
|
2
|
+
import { join, dirname } from "path";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
4
|
let cachedVersion = null;
|
|
5
|
+
function findPackageJson() {
|
|
6
|
+
let dir = fileURLToPath(new URL(".", import.meta.url));
|
|
7
|
+
for (let i = 0; i < 5; i++) {
|
|
8
|
+
const candidate = join(dir, "package.json");
|
|
9
|
+
if (existsSync(candidate))
|
|
10
|
+
return candidate;
|
|
11
|
+
const parent = dirname(dir);
|
|
12
|
+
if (parent === dir)
|
|
13
|
+
break;
|
|
14
|
+
dir = parent;
|
|
15
|
+
}
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
5
18
|
export function getKastellVersion() {
|
|
6
19
|
if (cachedVersion !== null)
|
|
7
20
|
return cachedVersion;
|
|
8
21
|
try {
|
|
9
|
-
const
|
|
10
|
-
|
|
22
|
+
const pkgPath = findPackageJson();
|
|
23
|
+
if (!pkgPath)
|
|
24
|
+
return "0.0.0";
|
|
25
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
11
26
|
cachedVersion = pkg.version;
|
|
12
27
|
return cachedVersion;
|
|
13
28
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/utils/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/utils/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,IAAI,aAAa,GAAkB,IAAI,CAAC;AAExC,SAAS,eAAe;IACtB,IAAI,GAAG,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC5C,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;QAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,MAAM;QAC1B,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,IAAI,aAAa,KAAK,IAAI;QAAE,OAAO,aAAa,CAAC;IACjD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;QAClC,IAAI,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAwB,CAAC;QAC9E,aAAa,GAAG,GAAG,CAAC,OAAO,CAAC;QAC5B,OAAO,aAAa,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,EAAE,CAAC;AAEnD,MAAM,UAAU,iBAAiB;IAC/B,aAAa,GAAG,IAAI,CAAC;AACvB,CAAC"}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "kastell",
|
|
3
|
-
"version": "2.2.
|
|
4
|
-
"description": "Autonomous server security and infrastructure management. Provides
|
|
5
|
-
"author": {
|
|
6
|
-
"name": "kastelldev"
|
|
7
|
-
},
|
|
8
|
-
"homepage": "https://kastell.dev",
|
|
9
|
-
"repository": "https://github.com/kastelldev/kastell",
|
|
10
|
-
"keywords": [
|
|
11
|
-
"server",
|
|
12
|
-
"security",
|
|
13
|
-
"infrastructure",
|
|
14
|
-
"mcp",
|
|
15
|
-
"audit",
|
|
16
|
-
"hardening",
|
|
17
|
-
"vps",
|
|
18
|
-
"cloud"
|
|
19
|
-
]
|
|
20
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "kastell",
|
|
3
|
+
"version": "2.2.5",
|
|
4
|
+
"description": "Autonomous server security and infrastructure management. Provides 17 MCP tools for cloud server provisioning, security auditing (457 checks), hardening, backup, and fleet management across Hetzner, DigitalOcean, Vultr, and Linode.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "kastelldev"
|
|
7
|
+
},
|
|
8
|
+
"homepage": "https://kastell.dev",
|
|
9
|
+
"repository": "https://github.com/kastelldev/kastell",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"server",
|
|
12
|
+
"security",
|
|
13
|
+
"infrastructure",
|
|
14
|
+
"mcp",
|
|
15
|
+
"audit",
|
|
16
|
+
"hardening",
|
|
17
|
+
"vps",
|
|
18
|
+
"cloud"
|
|
19
|
+
]
|
|
20
|
+
}
|
package/kastell-plugin/.mcp.json
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
{
|
|
2
|
-
"mcpServers": {
|
|
3
|
-
"kastell": {
|
|
4
|
-
"command": "node",
|
|
5
|
-
"args": ["${CLAUDE_PLUGIN_ROOT}/../../
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"kastell": {
|
|
4
|
+
"command": "node",
|
|
5
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/../../dist/mcp-bundle.mjs"],
|
|
6
|
+
"env": {
|
|
7
|
+
"HETZNER_TOKEN": "${HETZNER_TOKEN}",
|
|
8
|
+
"DIGITALOCEAN_TOKEN": "${DIGITALOCEAN_TOKEN}",
|
|
9
|
+
"VULTR_TOKEN": "${VULTR_TOKEN}",
|
|
10
|
+
"LINODE_TOKEN": "${LINODE_TOKEN}",
|
|
11
|
+
"KASTELL_SAFE_MODE": "true"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|