@hasna/machines 0.0.35 → 0.0.36
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/README.md +16 -0
- package/dist/cli/index.js +48 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/index.js +48 -1
- package/dist/mcp/index.js +48 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,10 +59,21 @@ machines self-test
|
|
|
59
59
|
`machines setup` is a dry-run plan by default. The generated playbook favors
|
|
60
60
|
idempotent operations (`mkdir -p`, command-existence guards, package-manager
|
|
61
61
|
installs) and only executes when both `--apply` and `--yes` are provided.
|
|
62
|
+
The default plan also adds update-check/download settings without enabling
|
|
63
|
+
automatic OS installation: Linux uses apt periodic download-only settings, and
|
|
64
|
+
macOS uses `softwareupdate`/`defaults` with `AutomaticallyInstallMacOSUpdates`
|
|
65
|
+
left disabled.
|
|
62
66
|
`doctor --json` includes public-safe source/ref diagnostics plus optional
|
|
63
67
|
adapter hook results for secrets, configs, monitors, repos, MCPs, and shield
|
|
64
68
|
checks. When no adapter is configured, those checks report a skipped fallback
|
|
65
69
|
instead of importing private dependencies.
|
|
70
|
+
It also reports noninteractive sudo readiness, SSH certificate support, and
|
|
71
|
+
GitHub App secret-reference readiness without printing credentials or private
|
|
72
|
+
keys.
|
|
73
|
+
|
|
74
|
+
Apple device management belongs in the private deployment layer. The public
|
|
75
|
+
setup plan can report enrollment status with `profiles status -type enrollment`,
|
|
76
|
+
but it does not enroll devices, install profiles, or publish team identifiers.
|
|
66
77
|
|
|
67
78
|
## Topology SDK
|
|
68
79
|
|
|
@@ -168,6 +179,11 @@ machines defaults to
|
|
|
168
179
|
`machines/screen-sharing/screen-<machine>-vnc-password`, or the namespace set in
|
|
169
180
|
`HASNA_MACHINES_SCREEN_SECRET_NAMESPACE`. The user comes from the manifest
|
|
170
181
|
(`metadata.user`) when present, or `--user`.
|
|
182
|
+
|
|
183
|
+
For GitHub automation, prefer GitHub App installation tokens over personal user
|
|
184
|
+
tokens. Public manifests and docs should store only opaque secret references
|
|
185
|
+
for the app id/private key material; private adapters or `open-secrets` should
|
|
186
|
+
resolve those references at runtime.
|
|
171
187
|
`screen-credentials` verifies the resolved user and secret key for a machine or
|
|
172
188
|
the full fleet without printing secret values.
|
|
173
189
|
|
package/dist/cli/index.js
CHANGED
|
@@ -8386,6 +8386,13 @@ function buildBaseSteps(machine) {
|
|
|
8386
8386
|
manager: "apt",
|
|
8387
8387
|
privileged: true
|
|
8388
8388
|
});
|
|
8389
|
+
steps.push({
|
|
8390
|
+
id: "linux-update-downloads",
|
|
8391
|
+
title: "Enable Linux package list refresh and download-only upgrades",
|
|
8392
|
+
command: `printf '%s\\n' 'APT::Periodic::Update-Package-Lists "1";' 'APT::Periodic::Download-Upgradeable-Packages "1";' 'APT::Periodic::Unattended-Upgrade "0";' | sudo tee /etc/apt/apt.conf.d/20auto-upgrades >/dev/null`,
|
|
8393
|
+
manager: "apt",
|
|
8394
|
+
privileged: true
|
|
8395
|
+
});
|
|
8389
8396
|
} else if (machine.platform === "macos") {
|
|
8390
8397
|
steps.push({
|
|
8391
8398
|
id: "brew-base",
|
|
@@ -8399,7 +8406,26 @@ function buildBaseSteps(machine) {
|
|
|
8399
8406
|
command: "brew install git coreutils",
|
|
8400
8407
|
manager: "brew"
|
|
8401
8408
|
});
|
|
8409
|
+
steps.push({
|
|
8410
|
+
id: "macos-update-downloads",
|
|
8411
|
+
title: "Enable macOS update checks and downloads without automatic install",
|
|
8412
|
+
command: "sudo softwareupdate --schedule on && sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled -bool true && sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload -int 1 && sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticallyInstallMacOSUpdates -int 0",
|
|
8413
|
+
manager: "custom",
|
|
8414
|
+
privileged: true
|
|
8415
|
+
});
|
|
8416
|
+
steps.push({
|
|
8417
|
+
id: "macos-management-readiness",
|
|
8418
|
+
title: "Report Apple management readiness without enrolling devices",
|
|
8419
|
+
command: "profiles status -type enrollment 2>/dev/null || true",
|
|
8420
|
+
manager: "custom"
|
|
8421
|
+
});
|
|
8402
8422
|
}
|
|
8423
|
+
steps.push({
|
|
8424
|
+
id: "github-app-auth-readiness",
|
|
8425
|
+
title: "Check GitHub CLI/App auth readiness without printing credentials",
|
|
8426
|
+
command: "command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1 || true",
|
|
8427
|
+
manager: "custom"
|
|
8428
|
+
});
|
|
8403
8429
|
return steps;
|
|
8404
8430
|
}
|
|
8405
8431
|
function buildPackageSteps(machine) {
|
|
@@ -10192,7 +10218,12 @@ function buildDoctorCommand() {
|
|
|
10192
10218
|
`printf 'ssh=%s\\n' "$(command -v ssh >/dev/null 2>&1 && printf ok || printf missing)"`,
|
|
10193
10219
|
`printf 'machines=%s\\n' "$(command -v machines 2>/dev/null || printf missing)"`,
|
|
10194
10220
|
`printf 'machines_agent=%s\\n' "$(command -v machines-agent 2>/dev/null || printf missing)"`,
|
|
10195
|
-
`printf 'machines_mcp=%s\\n' "$(command -v machines-mcp 2>/dev/null || printf missing)"
|
|
10221
|
+
`printf 'machines_mcp=%s\\n' "$(command -v machines-mcp 2>/dev/null || printf missing)"`,
|
|
10222
|
+
`printf 'sudo_noninteractive=%s\\n' "$(sudo -n true >/dev/null 2>&1 && printf ok || printf unavailable)"`,
|
|
10223
|
+
`printf 'ssh_cert_support=%s\\n' "$(ssh -Q key-cert 2>/dev/null | grep -q 'ssh-ed25519-cert-v01@openssh.com' && printf ok || printf unavailable)"`,
|
|
10224
|
+
`printf 'gh_cli=%s\\n' "$(command -v gh 2>/dev/null || printf missing)"`,
|
|
10225
|
+
`printf 'gh_auth=%s\\n' "$(gh auth status >/dev/null 2>&1 && printf ok || printf unavailable)"`,
|
|
10226
|
+
"printf 'github_app_ref=%s\\n' \"$(test -n \\\"${HASNA_GITHUB_APP_ID:-}\\\" -a -n \\\"${HASNA_GITHUB_APP_PRIVATE_KEY_REF:-}\\\" && printf configured || printf missing)\""
|
|
10196
10227
|
].join("; ");
|
|
10197
10228
|
}
|
|
10198
10229
|
function fallbackAdapterCheck(domain) {
|
|
@@ -10293,6 +10324,22 @@ function runDoctor(machineId = getLocalMachineId(), options = {}) {
|
|
|
10293
10324
|
makeCheck2("machines-agent-cli", details["machines_agent"] && details["machines_agent"] !== "missing" ? "ok" : "warn", "machines-agent availability", details["machines_agent"] || "missing"),
|
|
10294
10325
|
makeCheck2("machines-mcp-cli", details["machines_mcp"] && details["machines_mcp"] !== "missing" ? "ok" : "warn", "machines-mcp availability", details["machines_mcp"] || "missing"),
|
|
10295
10326
|
makeCheck2("ssh", details["ssh"] === "ok" ? "ok" : "warn", "SSH availability", details["ssh"] || "missing"),
|
|
10327
|
+
makeCheck2("sudo-noninteractive", details["sudo_noninteractive"] === "ok" ? "ok" : "warn", "Noninteractive sudo availability", details["sudo_noninteractive"] === "ok" ? "sudo -n is available" : "sudo -n unavailable; setup may require user-provided approval or password handling.", {
|
|
10328
|
+
data: { available: details["sudo_noninteractive"] === "ok" },
|
|
10329
|
+
remediation: details["sudo_noninteractive"] === "ok" ? undefined : ["Configure explicit sudo policy or run setup commands manually; do not store sudo passwords in public manifests."]
|
|
10330
|
+
}),
|
|
10331
|
+
makeCheck2("ssh-cert-support", details["ssh_cert_support"] === "ok" ? "ok" : "warn", "SSH certificate support", details["ssh_cert_support"] === "ok" ? "OpenSSH reports ed25519 certificate support" : "OpenSSH certificate support not detected.", {
|
|
10332
|
+
data: { supported: details["ssh_cert_support"] === "ok" },
|
|
10333
|
+
remediation: details["ssh_cert_support"] === "ok" ? undefined : ["Install or update OpenSSH before adopting SSH certificate auth for this machine."]
|
|
10334
|
+
}),
|
|
10335
|
+
makeCheck2("github-app-auth", details["github_app_ref"] === "configured" ? "ok" : "warn", "GitHub App auth references", details["github_app_ref"] === "configured" ? "GitHub App id and private-key reference are configured" : "GitHub App id/private-key reference missing; use secret references, not user tokens or raw private keys.", {
|
|
10336
|
+
data: {
|
|
10337
|
+
gh_cli: details["gh_cli"] && details["gh_cli"] !== "missing",
|
|
10338
|
+
gh_auth: details["gh_auth"] === "ok",
|
|
10339
|
+
app_ref_configured: details["github_app_ref"] === "configured"
|
|
10340
|
+
},
|
|
10341
|
+
remediation: details["github_app_ref"] === "configured" ? undefined : ["Set HASNA_GITHUB_APP_ID plus HASNA_GITHUB_APP_PRIVATE_KEY_REF or provide an equivalent open-secrets adapter."]
|
|
10342
|
+
}),
|
|
10296
10343
|
...optionalAdapterChecks
|
|
10297
10344
|
];
|
|
10298
10345
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AACA,OAAO,EAA0B,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAGrF,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE9F,eAAO,MAAM,+BAA+B,uEAAwE,CAAC;AAErH,MAAM,MAAM,2BAA2B,GAAG,OAAO,+BAA+B,CAAC,MAAM,CAAC,CAAC;AAEzF,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,aAAa,CAAC;IACxB,cAAc,EAAE,gBAAgB,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,GAAG,EAAE,IAAI,CAAC;CACX;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,oBAAoB,KAAK,WAAW,GAAG,WAAW,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;AAElH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,2BAA2B,EAAE,iBAAiB,CAAC,CAAC,CAAC;CAC1E;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,eAAe,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC/C,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAC3B,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AACA,OAAO,EAA0B,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAGrF,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE9F,eAAO,MAAM,+BAA+B,uEAAwE,CAAC;AAErH,MAAM,MAAM,2BAA2B,GAAG,OAAO,+BAA+B,CAAC,MAAM,CAAC,CAAC;AAEzF,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,aAAa,CAAC;IACxB,cAAc,EAAE,gBAAgB,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,GAAG,EAAE,IAAI,CAAC;CACX;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,oBAAoB,KAAK,WAAW,GAAG,WAAW,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;AAElH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,2BAA2B,EAAE,iBAAiB,CAAC,CAAC,CAAC;CAC1E;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,eAAe,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC/C,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAC3B,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAuHD,wBAAgB,SAAS,CAAC,SAAS,SAAsB,EAAE,OAAO,GAAE,aAAkB,GAAG,YAAY,CAwLpG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoD,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC3G,OAAO,KAAK,EAAmB,WAAW,EAAa,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoD,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC3G,OAAO,KAAK,EAAmB,WAAW,EAAa,MAAM,aAAa,CAAC;AAiG3E,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,CAyB9D;AAED,wBAAgB,QAAQ,CACtB,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,EAChD,MAAM,GAAE,oBAAwC,GAC/C,WAAW,CAmCb"}
|
package/dist/index.js
CHANGED
|
@@ -13079,7 +13079,12 @@ function buildDoctorCommand() {
|
|
|
13079
13079
|
`printf 'ssh=%s\\n' "$(command -v ssh >/dev/null 2>&1 && printf ok || printf missing)"`,
|
|
13080
13080
|
`printf 'machines=%s\\n' "$(command -v machines 2>/dev/null || printf missing)"`,
|
|
13081
13081
|
`printf 'machines_agent=%s\\n' "$(command -v machines-agent 2>/dev/null || printf missing)"`,
|
|
13082
|
-
`printf 'machines_mcp=%s\\n' "$(command -v machines-mcp 2>/dev/null || printf missing)"
|
|
13082
|
+
`printf 'machines_mcp=%s\\n' "$(command -v machines-mcp 2>/dev/null || printf missing)"`,
|
|
13083
|
+
`printf 'sudo_noninteractive=%s\\n' "$(sudo -n true >/dev/null 2>&1 && printf ok || printf unavailable)"`,
|
|
13084
|
+
`printf 'ssh_cert_support=%s\\n' "$(ssh -Q key-cert 2>/dev/null | grep -q 'ssh-ed25519-cert-v01@openssh.com' && printf ok || printf unavailable)"`,
|
|
13085
|
+
`printf 'gh_cli=%s\\n' "$(command -v gh 2>/dev/null || printf missing)"`,
|
|
13086
|
+
`printf 'gh_auth=%s\\n' "$(gh auth status >/dev/null 2>&1 && printf ok || printf unavailable)"`,
|
|
13087
|
+
"printf 'github_app_ref=%s\\n' \"$(test -n \\\"${HASNA_GITHUB_APP_ID:-}\\\" -a -n \\\"${HASNA_GITHUB_APP_PRIVATE_KEY_REF:-}\\\" && printf configured || printf missing)\""
|
|
13083
13088
|
].join("; ");
|
|
13084
13089
|
}
|
|
13085
13090
|
function fallbackAdapterCheck(domain) {
|
|
@@ -13180,6 +13185,22 @@ function runDoctor(machineId = getLocalMachineId(), options = {}) {
|
|
|
13180
13185
|
makeCheck2("machines-agent-cli", details["machines_agent"] && details["machines_agent"] !== "missing" ? "ok" : "warn", "machines-agent availability", details["machines_agent"] || "missing"),
|
|
13181
13186
|
makeCheck2("machines-mcp-cli", details["machines_mcp"] && details["machines_mcp"] !== "missing" ? "ok" : "warn", "machines-mcp availability", details["machines_mcp"] || "missing"),
|
|
13182
13187
|
makeCheck2("ssh", details["ssh"] === "ok" ? "ok" : "warn", "SSH availability", details["ssh"] || "missing"),
|
|
13188
|
+
makeCheck2("sudo-noninteractive", details["sudo_noninteractive"] === "ok" ? "ok" : "warn", "Noninteractive sudo availability", details["sudo_noninteractive"] === "ok" ? "sudo -n is available" : "sudo -n unavailable; setup may require user-provided approval or password handling.", {
|
|
13189
|
+
data: { available: details["sudo_noninteractive"] === "ok" },
|
|
13190
|
+
remediation: details["sudo_noninteractive"] === "ok" ? undefined : ["Configure explicit sudo policy or run setup commands manually; do not store sudo passwords in public manifests."]
|
|
13191
|
+
}),
|
|
13192
|
+
makeCheck2("ssh-cert-support", details["ssh_cert_support"] === "ok" ? "ok" : "warn", "SSH certificate support", details["ssh_cert_support"] === "ok" ? "OpenSSH reports ed25519 certificate support" : "OpenSSH certificate support not detected.", {
|
|
13193
|
+
data: { supported: details["ssh_cert_support"] === "ok" },
|
|
13194
|
+
remediation: details["ssh_cert_support"] === "ok" ? undefined : ["Install or update OpenSSH before adopting SSH certificate auth for this machine."]
|
|
13195
|
+
}),
|
|
13196
|
+
makeCheck2("github-app-auth", details["github_app_ref"] === "configured" ? "ok" : "warn", "GitHub App auth references", details["github_app_ref"] === "configured" ? "GitHub App id and private-key reference are configured" : "GitHub App id/private-key reference missing; use secret references, not user tokens or raw private keys.", {
|
|
13197
|
+
data: {
|
|
13198
|
+
gh_cli: details["gh_cli"] && details["gh_cli"] !== "missing",
|
|
13199
|
+
gh_auth: details["gh_auth"] === "ok",
|
|
13200
|
+
app_ref_configured: details["github_app_ref"] === "configured"
|
|
13201
|
+
},
|
|
13202
|
+
remediation: details["github_app_ref"] === "configured" ? undefined : ["Set HASNA_GITHUB_APP_ID plus HASNA_GITHUB_APP_PRIVATE_KEY_REF or provide an equivalent open-secrets adapter."]
|
|
13203
|
+
}),
|
|
13183
13204
|
...optionalAdapterChecks
|
|
13184
13205
|
];
|
|
13185
13206
|
return {
|
|
@@ -14233,6 +14254,13 @@ function buildBaseSteps(machine) {
|
|
|
14233
14254
|
manager: "apt",
|
|
14234
14255
|
privileged: true
|
|
14235
14256
|
});
|
|
14257
|
+
steps.push({
|
|
14258
|
+
id: "linux-update-downloads",
|
|
14259
|
+
title: "Enable Linux package list refresh and download-only upgrades",
|
|
14260
|
+
command: `printf '%s\\n' 'APT::Periodic::Update-Package-Lists "1";' 'APT::Periodic::Download-Upgradeable-Packages "1";' 'APT::Periodic::Unattended-Upgrade "0";' | sudo tee /etc/apt/apt.conf.d/20auto-upgrades >/dev/null`,
|
|
14261
|
+
manager: "apt",
|
|
14262
|
+
privileged: true
|
|
14263
|
+
});
|
|
14236
14264
|
} else if (machine.platform === "macos") {
|
|
14237
14265
|
steps.push({
|
|
14238
14266
|
id: "brew-base",
|
|
@@ -14246,7 +14274,26 @@ function buildBaseSteps(machine) {
|
|
|
14246
14274
|
command: "brew install git coreutils",
|
|
14247
14275
|
manager: "brew"
|
|
14248
14276
|
});
|
|
14277
|
+
steps.push({
|
|
14278
|
+
id: "macos-update-downloads",
|
|
14279
|
+
title: "Enable macOS update checks and downloads without automatic install",
|
|
14280
|
+
command: "sudo softwareupdate --schedule on && sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled -bool true && sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload -int 1 && sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticallyInstallMacOSUpdates -int 0",
|
|
14281
|
+
manager: "custom",
|
|
14282
|
+
privileged: true
|
|
14283
|
+
});
|
|
14284
|
+
steps.push({
|
|
14285
|
+
id: "macos-management-readiness",
|
|
14286
|
+
title: "Report Apple management readiness without enrolling devices",
|
|
14287
|
+
command: "profiles status -type enrollment 2>/dev/null || true",
|
|
14288
|
+
manager: "custom"
|
|
14289
|
+
});
|
|
14249
14290
|
}
|
|
14291
|
+
steps.push({
|
|
14292
|
+
id: "github-app-auth-readiness",
|
|
14293
|
+
title: "Check GitHub CLI/App auth readiness without printing credentials",
|
|
14294
|
+
command: "command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1 || true",
|
|
14295
|
+
manager: "custom"
|
|
14296
|
+
});
|
|
14250
14297
|
return steps;
|
|
14251
14298
|
}
|
|
14252
14299
|
function buildPackageSteps(machine) {
|
package/dist/mcp/index.js
CHANGED
|
@@ -5825,7 +5825,12 @@ function buildDoctorCommand() {
|
|
|
5825
5825
|
`printf 'ssh=%s\\n' "$(command -v ssh >/dev/null 2>&1 && printf ok || printf missing)"`,
|
|
5826
5826
|
`printf 'machines=%s\\n' "$(command -v machines 2>/dev/null || printf missing)"`,
|
|
5827
5827
|
`printf 'machines_agent=%s\\n' "$(command -v machines-agent 2>/dev/null || printf missing)"`,
|
|
5828
|
-
`printf 'machines_mcp=%s\\n' "$(command -v machines-mcp 2>/dev/null || printf missing)"
|
|
5828
|
+
`printf 'machines_mcp=%s\\n' "$(command -v machines-mcp 2>/dev/null || printf missing)"`,
|
|
5829
|
+
`printf 'sudo_noninteractive=%s\\n' "$(sudo -n true >/dev/null 2>&1 && printf ok || printf unavailable)"`,
|
|
5830
|
+
`printf 'ssh_cert_support=%s\\n' "$(ssh -Q key-cert 2>/dev/null | grep -q 'ssh-ed25519-cert-v01@openssh.com' && printf ok || printf unavailable)"`,
|
|
5831
|
+
`printf 'gh_cli=%s\\n' "$(command -v gh 2>/dev/null || printf missing)"`,
|
|
5832
|
+
`printf 'gh_auth=%s\\n' "$(gh auth status >/dev/null 2>&1 && printf ok || printf unavailable)"`,
|
|
5833
|
+
"printf 'github_app_ref=%s\\n' \"$(test -n \\\"${HASNA_GITHUB_APP_ID:-}\\\" -a -n \\\"${HASNA_GITHUB_APP_PRIVATE_KEY_REF:-}\\\" && printf configured || printf missing)\""
|
|
5829
5834
|
].join("; ");
|
|
5830
5835
|
}
|
|
5831
5836
|
function fallbackAdapterCheck(domain) {
|
|
@@ -5926,6 +5931,22 @@ function runDoctor(machineId = getLocalMachineId(), options = {}) {
|
|
|
5926
5931
|
makeCheck("machines-agent-cli", details["machines_agent"] && details["machines_agent"] !== "missing" ? "ok" : "warn", "machines-agent availability", details["machines_agent"] || "missing"),
|
|
5927
5932
|
makeCheck("machines-mcp-cli", details["machines_mcp"] && details["machines_mcp"] !== "missing" ? "ok" : "warn", "machines-mcp availability", details["machines_mcp"] || "missing"),
|
|
5928
5933
|
makeCheck("ssh", details["ssh"] === "ok" ? "ok" : "warn", "SSH availability", details["ssh"] || "missing"),
|
|
5934
|
+
makeCheck("sudo-noninteractive", details["sudo_noninteractive"] === "ok" ? "ok" : "warn", "Noninteractive sudo availability", details["sudo_noninteractive"] === "ok" ? "sudo -n is available" : "sudo -n unavailable; setup may require user-provided approval or password handling.", {
|
|
5935
|
+
data: { available: details["sudo_noninteractive"] === "ok" },
|
|
5936
|
+
remediation: details["sudo_noninteractive"] === "ok" ? undefined : ["Configure explicit sudo policy or run setup commands manually; do not store sudo passwords in public manifests."]
|
|
5937
|
+
}),
|
|
5938
|
+
makeCheck("ssh-cert-support", details["ssh_cert_support"] === "ok" ? "ok" : "warn", "SSH certificate support", details["ssh_cert_support"] === "ok" ? "OpenSSH reports ed25519 certificate support" : "OpenSSH certificate support not detected.", {
|
|
5939
|
+
data: { supported: details["ssh_cert_support"] === "ok" },
|
|
5940
|
+
remediation: details["ssh_cert_support"] === "ok" ? undefined : ["Install or update OpenSSH before adopting SSH certificate auth for this machine."]
|
|
5941
|
+
}),
|
|
5942
|
+
makeCheck("github-app-auth", details["github_app_ref"] === "configured" ? "ok" : "warn", "GitHub App auth references", details["github_app_ref"] === "configured" ? "GitHub App id and private-key reference are configured" : "GitHub App id/private-key reference missing; use secret references, not user tokens or raw private keys.", {
|
|
5943
|
+
data: {
|
|
5944
|
+
gh_cli: details["gh_cli"] && details["gh_cli"] !== "missing",
|
|
5945
|
+
gh_auth: details["gh_auth"] === "ok",
|
|
5946
|
+
app_ref_configured: details["github_app_ref"] === "configured"
|
|
5947
|
+
},
|
|
5948
|
+
remediation: details["github_app_ref"] === "configured" ? undefined : ["Set HASNA_GITHUB_APP_ID plus HASNA_GITHUB_APP_PRIVATE_KEY_REF or provide an equivalent open-secrets adapter."]
|
|
5949
|
+
}),
|
|
5929
5950
|
...optionalAdapterChecks
|
|
5930
5951
|
];
|
|
5931
5952
|
return {
|
|
@@ -6720,6 +6741,13 @@ function buildBaseSteps(machine) {
|
|
|
6720
6741
|
manager: "apt",
|
|
6721
6742
|
privileged: true
|
|
6722
6743
|
});
|
|
6744
|
+
steps.push({
|
|
6745
|
+
id: "linux-update-downloads",
|
|
6746
|
+
title: "Enable Linux package list refresh and download-only upgrades",
|
|
6747
|
+
command: `printf '%s\\n' 'APT::Periodic::Update-Package-Lists "1";' 'APT::Periodic::Download-Upgradeable-Packages "1";' 'APT::Periodic::Unattended-Upgrade "0";' | sudo tee /etc/apt/apt.conf.d/20auto-upgrades >/dev/null`,
|
|
6748
|
+
manager: "apt",
|
|
6749
|
+
privileged: true
|
|
6750
|
+
});
|
|
6723
6751
|
} else if (machine.platform === "macos") {
|
|
6724
6752
|
steps.push({
|
|
6725
6753
|
id: "brew-base",
|
|
@@ -6733,7 +6761,26 @@ function buildBaseSteps(machine) {
|
|
|
6733
6761
|
command: "brew install git coreutils",
|
|
6734
6762
|
manager: "brew"
|
|
6735
6763
|
});
|
|
6764
|
+
steps.push({
|
|
6765
|
+
id: "macos-update-downloads",
|
|
6766
|
+
title: "Enable macOS update checks and downloads without automatic install",
|
|
6767
|
+
command: "sudo softwareupdate --schedule on && sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled -bool true && sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload -int 1 && sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticallyInstallMacOSUpdates -int 0",
|
|
6768
|
+
manager: "custom",
|
|
6769
|
+
privileged: true
|
|
6770
|
+
});
|
|
6771
|
+
steps.push({
|
|
6772
|
+
id: "macos-management-readiness",
|
|
6773
|
+
title: "Report Apple management readiness without enrolling devices",
|
|
6774
|
+
command: "profiles status -type enrollment 2>/dev/null || true",
|
|
6775
|
+
manager: "custom"
|
|
6776
|
+
});
|
|
6736
6777
|
}
|
|
6778
|
+
steps.push({
|
|
6779
|
+
id: "github-app-auth-readiness",
|
|
6780
|
+
title: "Check GitHub CLI/App auth readiness without printing credentials",
|
|
6781
|
+
command: "command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1 || true",
|
|
6782
|
+
manager: "custom"
|
|
6783
|
+
});
|
|
6737
6784
|
return steps;
|
|
6738
6785
|
}
|
|
6739
6786
|
function buildPackageSteps(machine) {
|