diff --git a/src/cli-schema.mjs b/src/cli-schema.mjs index 52cff6c3..b284075a 100644 --- a/src/cli-schema.mjs +++ b/src/cli-schema.mjs @@ -1148,7 +1148,8 @@ export const DNS_VERBS = [ name: "ca", description: "trust the registry's root here, so every Moshpit name is trusted at once", synopsis: [ - ["moshcode dns ca", "fetch the registry's root, check it, install it (NSS without root, the system store with sudo)"], + ["moshcode dns ca", "fetch the registry's root, check it, install it everywhere (asks for sudo for the system store)"], + ["moshcode dns ca --user-only", "the browser store only; no prompt"], ["moshcode dns ca --remove", "take it back out of every store"], ], }, diff --git a/src/dns.mjs b/src/dns.mjs index 1a87524a..1fec6493 100644 --- a/src/dns.mjs +++ b/src/dns.mjs @@ -2625,6 +2625,23 @@ export async function dnsCommand(args = [], out = console.log, deps = {}) { // bridge, DoH in the browser, TronBrowser's own resolver) but its clients // still refuse the certificates. `--remove` takes it back out. if (sub === "ca") { + // Half of this needs root (the system store) and half must not run as + // root's own user (the operator's NSS database), which is exactly the + // shape `dns enable` already handles: escalate this one command, and let + // operatorHome() find the person behind sudo. `sudo moshcode dns ca` from + // a shell is what bonita hit: moshcode lives in the operator's PATH, not + // root's, so "command not found". Escalating from inside carries the path. + // --user-only keeps it to the browser store, no prompt, for a machine + // where sudo is not on offer. + if (uid !== 0 && !rest.includes("--user-only")) { + const escalated = escalate({ + args: ["dns", "ca", ...rest], + what: "dns ca", + out, + }); + if (escalated.ran) return escalated.code; + out("(no sudo here — installing into the browser store only; the system store needs root)"); + } if (rest.includes("--remove")) { const r = await removeRegistryTrust(out, deps); return r.ok ? 0 : 1; diff --git a/src/trust.mjs b/src/trust.mjs index 685b54c9..00ce5bd2 100644 --- a/src/trust.mjs +++ b/src/trust.mjs @@ -1167,7 +1167,7 @@ export async function applyRegistryTrust(out, deps = {}) { } for (const step of plan.skipped) { out(` -- ${step.label} — ${step.why}`); - if (step.needsRoot) out(" re-run with root to cover it: sudo moshcode dns ca"); + if (step.needsRoot) out(" run `moshcode dns ca` from a terminal to cover it — it asks for sudo itself"); } return { ok: true, installed, skipped: plan.skipped.length, file }; } @@ -1225,7 +1225,7 @@ export async function removeRegistryTrust(out, deps = {}) { if (haveFile) await runner("rm", ["-f", file]); for (const step of plan.skipped) { out(` -- ${step.label} — ${step.why}`); - if (step.needsRoot && uid !== 0) out(" re-run with root to cover it: sudo moshcode dns ca --remove"); + if (step.needsRoot && uid !== 0) out(" run `moshcode dns ca --remove` from a terminal to cover it — it asks for sudo itself"); } return { ok: true, removed, skipped: plan.skipped.length }; }