@openape/apes 0.22.0 → 0.22.1
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/dist/cli.js
CHANGED
|
@@ -1748,7 +1748,7 @@ import { defineCommand as defineCommand24 } from "citty";
|
|
|
1748
1748
|
// src/commands/agents/destroy.ts
|
|
1749
1749
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
1750
1750
|
import { mkdtempSync, rmSync, writeFileSync } from "fs";
|
|
1751
|
-
import { tmpdir } from "os";
|
|
1751
|
+
import { tmpdir, userInfo } from "os";
|
|
1752
1752
|
import { join as join2 } from "path";
|
|
1753
1753
|
import { defineCommand as defineCommand20 } from "citty";
|
|
1754
1754
|
import consola18 from "consola";
|
|
@@ -1889,7 +1889,7 @@ echo "OK $NAME uid=$NEXT_UID home=$HOME_DIR"
|
|
|
1889
1889
|
`;
|
|
1890
1890
|
}
|
|
1891
1891
|
function buildDestroyTeardownScript(input) {
|
|
1892
|
-
const { name, homeDir } = input;
|
|
1892
|
+
const { name, homeDir, adminUser } = input;
|
|
1893
1893
|
return `#!/bin/bash
|
|
1894
1894
|
# Best-effort teardown. set -u catches typos; we deliberately do NOT use -e
|
|
1895
1895
|
# because pkill / launchctl are allowed to fail when the user has no live
|
|
@@ -1898,6 +1898,16 @@ set -u
|
|
|
1898
1898
|
|
|
1899
1899
|
NAME=${shQuote(name)}
|
|
1900
1900
|
HOME_DIR=${shQuote(homeDir)}
|
|
1901
|
+
ADMIN_USER=${shQuote(adminUser)}
|
|
1902
|
+
|
|
1903
|
+
# Read the admin password from stdin (line 1). The caller pipes it in.
|
|
1904
|
+
# We never accept it as an argv element so it can't show up in process
|
|
1905
|
+
# listings or escapes' audit log.
|
|
1906
|
+
read -r ADMIN_PASSWORD
|
|
1907
|
+
if [ -z "$ADMIN_PASSWORD" ]; then
|
|
1908
|
+
echo "ERROR: no admin password on stdin (expected one line)." >&2
|
|
1909
|
+
exit 2
|
|
1910
|
+
fi
|
|
1901
1911
|
|
|
1902
1912
|
UID_OF=$(dscl . -read "/Users/$NAME" UniqueID 2>/dev/null | awk '/UniqueID:/ {print $2}')
|
|
1903
1913
|
|
|
@@ -1910,25 +1920,32 @@ if [ -d "$HOME_DIR" ] && [ "$HOME_DIR" != "/" ] && [ "$HOME_DIR" != "" ]; then
|
|
|
1910
1920
|
rm -rf "$HOME_DIR"
|
|
1911
1921
|
fi
|
|
1912
1922
|
|
|
1913
|
-
#
|
|
1914
|
-
#
|
|
1915
|
-
#
|
|
1916
|
-
#
|
|
1917
|
-
#
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1923
|
+
# \`escapes\` is a plain setuid binary \u2014 opendirectoryd sees no audit/PAM
|
|
1924
|
+
# session attached (AUDIT_SESSION_ID=unset) and rejects DirectoryService
|
|
1925
|
+
# writes from this context: a bare \`sysadminctl -deleteUser\` or
|
|
1926
|
+
# \`dscl . -delete\` hangs ~5 minutes and exits with eUndefinedError -14987
|
|
1927
|
+
# at DSRecord.m:563. Passing explicit -adminUser/-adminPassword bypasses
|
|
1928
|
+
# opendirectoryd's implicit "is current session admin?" check and
|
|
1929
|
+
# authenticates against DirectoryService directly \u2014 the delete then
|
|
1930
|
+
# completes in ~1 second.
|
|
1931
|
+
if ! command -v sysadminctl >/dev/null 2>&1; then
|
|
1932
|
+
echo "ERROR: sysadminctl not available; cannot delete user record." >&2
|
|
1933
|
+
exit 1
|
|
1934
|
+
fi
|
|
1935
|
+
|
|
1936
|
+
sysadminctl \\
|
|
1937
|
+
-deleteUser "$NAME" \\
|
|
1938
|
+
-adminUser "$ADMIN_USER" \\
|
|
1939
|
+
-adminPassword "$ADMIN_PASSWORD"
|
|
1940
|
+
SYSAD_EC=$?
|
|
1941
|
+
unset ADMIN_PASSWORD
|
|
1942
|
+
|
|
1943
|
+
if [ $SYSAD_EC -ne 0 ]; then
|
|
1944
|
+
echo "ERROR: sysadminctl -deleteUser failed (exit=$SYSAD_EC)." >&2
|
|
1945
|
+
echo " Common causes: wrong admin password, admin user '$ADMIN_USER'" >&2
|
|
1946
|
+
echo " not in admin group, or target user '$NAME' is the last secure" >&2
|
|
1947
|
+
echo " token holder (run \\\`sysadminctl -secureTokenStatus $NAME\\\`)." >&2
|
|
1948
|
+
exit 1
|
|
1932
1949
|
fi
|
|
1933
1950
|
|
|
1934
1951
|
# Verify the record is actually gone.
|
|
@@ -2122,14 +2139,20 @@ ${consequences.join("\n")}`);
|
|
|
2122
2139
|
if (!escapes) {
|
|
2123
2140
|
throw new CliError("`escapes` not found on PATH; OS teardown requires escapes.");
|
|
2124
2141
|
}
|
|
2142
|
+
const adminUser = userInfo().username;
|
|
2143
|
+
const adminPassword = await collectAdminPassword({ adminUser, force: !!args.force });
|
|
2125
2144
|
const scratch = mkdtempSync(join2(tmpdir(), `apes-destroy-${name}-`));
|
|
2126
2145
|
const scriptPath = join2(scratch, "teardown.sh");
|
|
2127
2146
|
try {
|
|
2128
|
-
const script = buildDestroyTeardownScript({ name, homeDir: `/Users/${name}
|
|
2147
|
+
const script = buildDestroyTeardownScript({ name, homeDir: `/Users/${name}`, adminUser });
|
|
2129
2148
|
writeFileSync(scriptPath, script, { mode: 448 });
|
|
2130
2149
|
consola18.start("Running teardown as root via `apes run --as root --wait`\u2026");
|
|
2131
2150
|
consola18.info("You will be asked to approve the as=root grant in your DDISA inbox; this command blocks until you do.");
|
|
2132
|
-
execFileSync3(apes, ["run", "--as", "root", "--wait", "--", "bash", scriptPath], {
|
|
2151
|
+
execFileSync3(apes, ["run", "--as", "root", "--wait", "--", "bash", scriptPath], {
|
|
2152
|
+
input: `${adminPassword}
|
|
2153
|
+
`,
|
|
2154
|
+
stdio: ["pipe", "inherit", "inherit"]
|
|
2155
|
+
});
|
|
2133
2156
|
} finally {
|
|
2134
2157
|
rmSync(scratch, { recursive: true, force: true });
|
|
2135
2158
|
}
|
|
@@ -2139,6 +2162,21 @@ ${consequences.join("\n")}`);
|
|
|
2139
2162
|
consola18.success(`Destroyed ${name}.`);
|
|
2140
2163
|
}
|
|
2141
2164
|
});
|
|
2165
|
+
async function collectAdminPassword(opts) {
|
|
2166
|
+
const fromEnv = process.env.APES_ADMIN_PASSWORD;
|
|
2167
|
+
if (fromEnv && fromEnv.length > 0) return fromEnv;
|
|
2168
|
+
if (!process.stdin.isTTY) {
|
|
2169
|
+
throw new CliError(
|
|
2170
|
+
`Admin password required for sysadminctl -deleteUser. No TTY available for the silent prompt; set APES_ADMIN_PASSWORD in the environment (local admin password for ${opts.adminUser}). The teardown reads it from stdin and never stores it.`
|
|
2171
|
+
);
|
|
2172
|
+
}
|
|
2173
|
+
consola18.info(`Local admin password for ${opts.adminUser} (used for sysadminctl -deleteUser; not stored):`);
|
|
2174
|
+
const pw = await consola18.prompt("Admin password", { type: "text", mask: "*" });
|
|
2175
|
+
if (typeof pw === "symbol" || !pw || pw.length === 0) {
|
|
2176
|
+
throw new CliExit(0);
|
|
2177
|
+
}
|
|
2178
|
+
return pw;
|
|
2179
|
+
}
|
|
2142
2180
|
|
|
2143
2181
|
// src/commands/agents/list.ts
|
|
2144
2182
|
import { defineCommand as defineCommand21 } from "citty";
|
|
@@ -3770,7 +3808,7 @@ var mcpCommand = defineCommand32({
|
|
|
3770
3808
|
if (transport !== "stdio" && transport !== "sse") {
|
|
3771
3809
|
throw new Error('Transport must be "stdio" or "sse"');
|
|
3772
3810
|
}
|
|
3773
|
-
const { startMcpServer } = await import("./server-
|
|
3811
|
+
const { startMcpServer } = await import("./server-WBR7VEDY.js");
|
|
3774
3812
|
await startMcpServer(transport, port);
|
|
3775
3813
|
}
|
|
3776
3814
|
});
|
|
@@ -4408,7 +4446,7 @@ async function bestEffortGrantCount(idp) {
|
|
|
4408
4446
|
}
|
|
4409
4447
|
}
|
|
4410
4448
|
async function runHealth(args) {
|
|
4411
|
-
const version = true ? "0.22.
|
|
4449
|
+
const version = true ? "0.22.1" : "0.0.0";
|
|
4412
4450
|
const auth = loadAuth();
|
|
4413
4451
|
if (!auth) {
|
|
4414
4452
|
throw new CliError("Not logged in. Run `apes login` first.", 1);
|
|
@@ -4681,10 +4719,10 @@ if (shellRewrite) {
|
|
|
4681
4719
|
if (shellRewrite.action === "rewrite") {
|
|
4682
4720
|
process.argv = shellRewrite.argv;
|
|
4683
4721
|
} else if (shellRewrite.action === "version") {
|
|
4684
|
-
console.log(`ape-shell ${"0.22.
|
|
4722
|
+
console.log(`ape-shell ${"0.22.1"} (OpenApe DDISA shell wrapper)`);
|
|
4685
4723
|
process.exit(0);
|
|
4686
4724
|
} else if (shellRewrite.action === "help") {
|
|
4687
|
-
console.log(`ape-shell ${"0.22.
|
|
4725
|
+
console.log(`ape-shell ${"0.22.1"} \u2014 OpenApe DDISA shell wrapper`);
|
|
4688
4726
|
console.log("");
|
|
4689
4727
|
console.log("Usage:");
|
|
4690
4728
|
console.log(" ape-shell Start interactive grant-mediated REPL");
|
|
@@ -4742,7 +4780,7 @@ var configCommand = defineCommand44({
|
|
|
4742
4780
|
var main = defineCommand44({
|
|
4743
4781
|
meta: {
|
|
4744
4782
|
name: "apes",
|
|
4745
|
-
version: "0.22.
|
|
4783
|
+
version: "0.22.1",
|
|
4746
4784
|
description: "Unified CLI for OpenApe"
|
|
4747
4785
|
},
|
|
4748
4786
|
subCommands: {
|
|
@@ -4797,7 +4835,7 @@ async function maybeRefreshAuth() {
|
|
|
4797
4835
|
}
|
|
4798
4836
|
}
|
|
4799
4837
|
await maybeRefreshAuth();
|
|
4800
|
-
await maybeWarnStaleVersion("0.22.
|
|
4838
|
+
await maybeWarnStaleVersion("0.22.1").catch(() => {
|
|
4801
4839
|
});
|
|
4802
4840
|
runMain(main).catch((err) => {
|
|
4803
4841
|
if (err instanceof CliExit) {
|