@rubytech/create-maxy-code 0.1.222 → 0.1.223
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/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import { classifyPortHolder } from "./preflight-port-classifier.js";
|
|
|
18
18
|
import { parsePluginList, computeInstallActions, computeConfigureActions, parseExternalPlugins, } from "./lib/plugin-install.js";
|
|
19
19
|
import { findPremiumMcpDirs } from "./lib/premium-mcp-discover.js";
|
|
20
20
|
import { pickLanInterface, mergeSmbConf, formatSambaMarker, } from "./samba-provision.js";
|
|
21
|
-
import { networkInterfaces, userInfo
|
|
21
|
+
import { networkInterfaces, userInfo } from "node:os";
|
|
22
22
|
const PAYLOAD_DIR = resolve(import.meta.dirname, "../payload");
|
|
23
23
|
// Brand manifest — read from payload to derive all brand-specific installation values.
|
|
24
24
|
// The bundler stamps brand.json into the payload at build time.
|
|
@@ -3276,51 +3276,6 @@ WantedBy=multi-user.target
|
|
|
3276
3276
|
// and fail with EADDRINUSE. Fresh installs: the stop is a no-op.
|
|
3277
3277
|
const unitName = BRAND.serviceName.replace(".service", "");
|
|
3278
3278
|
const claudeSessionManagerUnitShort = claudeSessionManagerUnitName.replace(".service", "");
|
|
3279
|
-
// Task 579 — admin-enumeration acceptance gate. Runs against the
|
|
3280
|
-
// freshly-deployed payload before the systemctl restart cluster so a
|
|
3281
|
-
// regression in the admin tool surface fails the install and keeps
|
|
3282
|
-
// the old service running. The harness exit code is the gate; a
|
|
3283
|
-
// non-zero exit logs the JSONL evidence path to install.log and
|
|
3284
|
-
// process.exit(1) before we touch any unit. Set MAXY_SKIP_ENUMERATE_GATE=1
|
|
3285
|
-
// to bypass for cases where the operator is iterating on a different
|
|
3286
|
-
// surface and accepts the regression risk; absence is the default.
|
|
3287
|
-
if (!process.env.MAXY_SKIP_ENUMERATE_GATE) {
|
|
3288
|
-
const harness = join(INSTALL_DIR, "platform/plugins/admin/__tests__/admin-can-enumerate.test.sh");
|
|
3289
|
-
if (existsSync(harness)) {
|
|
3290
|
-
const brandConfigDir = join(homedir(), BRAND.configDir, ".claude");
|
|
3291
|
-
console.log(" Running admin-enumerate acceptance gate...");
|
|
3292
|
-
const gateResult = spawnSync("bash", [harness], {
|
|
3293
|
-
stdio: "inherit",
|
|
3294
|
-
env: {
|
|
3295
|
-
...process.env,
|
|
3296
|
-
CLAUDE_CONFIG_DIR: brandConfigDir,
|
|
3297
|
-
INSTALL_DIR,
|
|
3298
|
-
},
|
|
3299
|
-
});
|
|
3300
|
-
if (gateResult.status !== 0) {
|
|
3301
|
-
const installLog = join(homedir(), BRAND.configDir, "logs", "install.log");
|
|
3302
|
-
const ts = new Date().toISOString();
|
|
3303
|
-
try {
|
|
3304
|
-
mkdirSync(dirname(installLog), { recursive: true });
|
|
3305
|
-
appendFileSync(installLog, `${ts} [admin-enumerate-gate] FAIL exit=${gateResult.status ?? "null"} — admin seat could not locate seeded site within budget. Payload NOT swapped into systemd.\n`);
|
|
3306
|
-
}
|
|
3307
|
-
catch {
|
|
3308
|
-
// best-effort
|
|
3309
|
-
}
|
|
3310
|
-
console.error(`\n ❌ admin-enumerate gate failed (exit ${gateResult.status ?? "null"}).\n` +
|
|
3311
|
-
` The new payload is on disk at ${INSTALL_DIR} but systemd was NOT restarted.\n` +
|
|
3312
|
-
` Old service is still running. See ${installLog} for one-line summary.\n`);
|
|
3313
|
-
process.exit(1);
|
|
3314
|
-
}
|
|
3315
|
-
console.log(" admin-enumerate gate passed.");
|
|
3316
|
-
}
|
|
3317
|
-
else {
|
|
3318
|
-
console.log(` [admin-enumerate-gate] SKIP reason=harness-not-on-disk path=${harness}`);
|
|
3319
|
-
}
|
|
3320
|
-
}
|
|
3321
|
-
else {
|
|
3322
|
-
console.log(" [admin-enumerate-gate] SKIP reason=MAXY_SKIP_ENUMERATE_GATE=1");
|
|
3323
|
-
}
|
|
3324
3279
|
spawnSync("systemctl", ["--user", "stop", unitName], { stdio: "inherit" });
|
|
3325
3280
|
spawnSync("systemctl", ["--user", "daemon-reload"], { stdio: "inherit" });
|
|
3326
3281
|
spawnSync("systemctl", ["--user", "enable", edgeUnitShort], { stdio: "inherit" });
|
package/package.json
CHANGED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# admin-can-enumerate.test.sh
|
|
3
|
-
#
|
|
4
|
-
# Acceptance gate for Task 579. Verifies that a fresh admin session
|
|
5
|
-
# locates a file under <accountDir>/sites/ on the FIRST enumeration
|
|
6
|
-
# attempt — no slug guessing, no `EISDIR`, no false-empty 200s, no
|
|
7
|
-
# "Log directory does not exist" against a path that resolves
|
|
8
|
-
# elsewhere. The gate runs from the installer post-install step against
|
|
9
|
-
# the freshly-deployed payload, before systemd services are restarted
|
|
10
|
-
# into it. A non-zero exit aborts the deploy and the old payload keeps
|
|
11
|
-
# running.
|
|
12
|
-
#
|
|
13
|
-
# Required environment:
|
|
14
|
-
# CLAUDE_CONFIG_DIR per-brand .claude directory (e.g. ~/.realagent-code/.claude)
|
|
15
|
-
# INSTALL_DIR the brand install root (e.g. ~/realagent-code)
|
|
16
|
-
#
|
|
17
|
-
# Exit codes:
|
|
18
|
-
# 0 pass — admin enumerated and emitted the seeded path within budget
|
|
19
|
-
# 1 fail — one or more assertions tripped (see stderr for the line)
|
|
20
|
-
# 2 setup error — could not seed test account or could not invoke claude
|
|
21
|
-
|
|
22
|
-
set -euo pipefail
|
|
23
|
-
|
|
24
|
-
CONFIG_DIR="${CLAUDE_CONFIG_DIR:?CLAUDE_CONFIG_DIR not set}"
|
|
25
|
-
INSTALL_DIR="${INSTALL_DIR:?INSTALL_DIR not set}"
|
|
26
|
-
|
|
27
|
-
if ! command -v claude >/dev/null 2>&1; then
|
|
28
|
-
echo "[admin-enumerate-gate] setup-error reason=claude-not-on-path" >&2
|
|
29
|
-
exit 2
|
|
30
|
-
fi
|
|
31
|
-
if ! command -v jq >/dev/null 2>&1; then
|
|
32
|
-
echo "[admin-enumerate-gate] setup-error reason=jq-not-on-path" >&2
|
|
33
|
-
exit 2
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
ACCOUNTS_DIR="$INSTALL_DIR/data/accounts"
|
|
37
|
-
TEST_ACCT_ID="enumerate-gate-$$"
|
|
38
|
-
TEST_ACCT_DIR="$ACCOUNTS_DIR/$TEST_ACCT_ID"
|
|
39
|
-
JSONL_OUT=$(mktemp)
|
|
40
|
-
EXIT=0
|
|
41
|
-
|
|
42
|
-
cleanup() {
|
|
43
|
-
rm -rf "$TEST_ACCT_DIR"
|
|
44
|
-
if [ "$EXIT" -eq 0 ]; then
|
|
45
|
-
rm -f "$JSONL_OUT"
|
|
46
|
-
else
|
|
47
|
-
echo "[admin-enumerate-gate] evidence-jsonl=$JSONL_OUT" >&2
|
|
48
|
-
fi
|
|
49
|
-
}
|
|
50
|
-
trap cleanup EXIT
|
|
51
|
-
|
|
52
|
-
# Seed: one target site + 5 decoys. Target index.html is the file the
|
|
53
|
-
# agent must locate and emit the absolute path for.
|
|
54
|
-
mkdir -p "$TEST_ACCT_DIR/sites/exp-uk-got-talent"
|
|
55
|
-
echo "<html><body>eXp Has Got Talent</body></html>" > "$TEST_ACCT_DIR/sites/exp-uk-got-talent/index.html"
|
|
56
|
-
for decoy in alpha-corp-careers beta-properties gamma-events delta-news epsilon-portal; do
|
|
57
|
-
mkdir -p "$TEST_ACCT_DIR/sites/$decoy"
|
|
58
|
-
echo "<html>decoy</html>" > "$TEST_ACCT_DIR/sites/$decoy/index.html"
|
|
59
|
-
done
|
|
60
|
-
|
|
61
|
-
TARGET_PATH="$TEST_ACCT_DIR/sites/exp-uk-got-talent/index.html"
|
|
62
|
-
|
|
63
|
-
PROMPT="find the eXp Has Got Talent site in this account and print the absolute path to its index.html"
|
|
64
|
-
|
|
65
|
-
# Spawn claude headless against the test account. ACCOUNT_ID + the
|
|
66
|
-
# MAXY_SESSION_ROLE/PLATFORM_ROOT env are what the platform MCPs read
|
|
67
|
-
# to scope themselves; PLATFORM_ROOT resolves the on-disk payload that
|
|
68
|
-
# was just deployed. JSONL goes to a file we parse below.
|
|
69
|
-
ACCOUNT_ID="$TEST_ACCT_ID" \
|
|
70
|
-
MAXY_SESSION_ROLE="admin" \
|
|
71
|
-
PLATFORM_ROOT="$INSTALL_DIR/platform" \
|
|
72
|
-
CLAUDE_CONFIG_DIR="$CONFIG_DIR" \
|
|
73
|
-
claude -p "$PROMPT" --output-format=stream-json --verbose \
|
|
74
|
-
> "$JSONL_OUT" 2>&1 \
|
|
75
|
-
|| { echo "[admin-enumerate-gate] setup-error reason=claude-spawn-failed exit=$?" >&2; EXIT=2; exit 2; }
|
|
76
|
-
|
|
77
|
-
fail() {
|
|
78
|
-
echo "[admin-enumerate-gate] FAIL $1" >&2
|
|
79
|
-
EXIT=1
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
# Assertion 1: the target path appears verbatim in some assistant turn
|
|
83
|
-
# or tool-use input. Either as the agent's final message or as an arg
|
|
84
|
-
# passed to a tool.
|
|
85
|
-
if ! grep -F -q "$TARGET_PATH" "$JSONL_OUT"; then
|
|
86
|
-
fail "correct-path-not-emitted target=$TARGET_PATH"
|
|
87
|
-
fi
|
|
88
|
-
|
|
89
|
-
# Assertion 2: zero forbidden error patterns from the surfaces this
|
|
90
|
-
# task fixed.
|
|
91
|
-
FORBIDDEN_HITS=$(grep -E -c "EISDIR|Log directory does not exist|Plugin file not found|page has no readable text content" "$JSONL_OUT" || true)
|
|
92
|
-
if [ "${FORBIDDEN_HITS:-0}" -gt 0 ]; then
|
|
93
|
-
fail "forbidden-error-patterns=$FORBIDDEN_HITS"
|
|
94
|
-
fi
|
|
95
|
-
|
|
96
|
-
# Assertion 3: total tool-use calls from the user prompt to the
|
|
97
|
-
# correct-path emission are at most 3. The earlier failing run issued
|
|
98
|
-
# ~15.
|
|
99
|
-
TOOL_USE_COUNT=$(jq -r 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | .name' < "$JSONL_OUT" 2>/dev/null | wc -l | tr -d ' ' || echo 0)
|
|
100
|
-
if [ "${TOOL_USE_COUNT:-0}" -gt 3 ]; then
|
|
101
|
-
fail "tool-use-budget-exceeded count=$TOOL_USE_COUNT cap=3"
|
|
102
|
-
fi
|
|
103
|
-
|
|
104
|
-
# Assertion 4: the FIRST disk-listing tool call returns an enumeration
|
|
105
|
-
# of <accountDir>/sites/. "Disk-listing" means LS, Glob, or Bash with
|
|
106
|
-
# `ls`. We accept any of those as the first relevant call; what we
|
|
107
|
-
# reject is a Read against a directory path.
|
|
108
|
-
FIRST_DIR_TOOL=$(jq -r 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | {name, input} | @json' < "$JSONL_OUT" 2>/dev/null \
|
|
109
|
-
| jq -r 'select(.name=="LS" or .name=="Glob" or (.name=="Bash" and (.input.command // "" | test("\\bls\\b")))) | .name' \
|
|
110
|
-
| head -1)
|
|
111
|
-
if [ -z "$FIRST_DIR_TOOL" ]; then
|
|
112
|
-
fail "no-disk-listing-tool-call-emitted"
|
|
113
|
-
fi
|
|
114
|
-
|
|
115
|
-
# Assertion 5: no Read tool call against a path under <accountDir>/sites/
|
|
116
|
-
# that is a directory (would have produced EISDIR pre-fix; should not
|
|
117
|
-
# even be attempted now).
|
|
118
|
-
BAD_READ=$(jq -r 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use" and .name=="Read") | .input.file_path // ""' < "$JSONL_OUT" 2>/dev/null \
|
|
119
|
-
| while read -r p; do
|
|
120
|
-
[ -n "$p" ] && [ -d "$p" ] && echo "$p"
|
|
121
|
-
done | head -1)
|
|
122
|
-
if [ -n "$BAD_READ" ]; then
|
|
123
|
-
fail "read-against-directory path=$BAD_READ"
|
|
124
|
-
fi
|
|
125
|
-
|
|
126
|
-
if [ "$EXIT" -eq 0 ]; then
|
|
127
|
-
echo "[admin-enumerate-gate] PASS target=$TARGET_PATH tool-use-count=$TOOL_USE_COUNT first-dir-tool=$FIRST_DIR_TOOL"
|
|
128
|
-
fi
|
|
129
|
-
exit "$EXIT"
|