@rubytech/create-maxy-code 0.1.275 → 0.1.277

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.
Files changed (49) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  3. package/payload/platform/plugins/admin/PLUGIN.md +1 -4
  4. package/payload/platform/plugins/admin/mcp/dist/index.js +0 -8
  5. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  6. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +3 -3
  7. package/payload/platform/plugins/docs/references/admin-identity-gate.md +77 -81
  8. package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
  9. package/payload/platform/scripts/check-no-esm-require.mjs +3 -0
  10. package/payload/platform/scripts/setup-account.sh +0 -5
  11. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  12. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +0 -1
  13. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  14. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +5 -0
  15. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  16. package/payload/platform/services/claude-session-manager/dist/http-server.js +52 -10
  17. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  18. package/payload/platform/services/claude-session-manager/dist/index.js +8 -17
  19. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  20. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  21. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +4 -5
  22. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  23. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.d.ts +8 -0
  24. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.d.ts.map +1 -1
  25. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.js +13 -0
  26. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.js.map +1 -1
  27. package/payload/platform/services/claude-session-manager/dist/wa-channel-store.d.ts +29 -0
  28. package/payload/platform/services/claude-session-manager/dist/wa-channel-store.d.ts.map +1 -0
  29. package/payload/platform/services/claude-session-manager/dist/wa-channel-store.js +124 -0
  30. package/payload/platform/services/claude-session-manager/dist/wa-channel-store.js.map +1 -0
  31. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +23 -0
  32. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
  33. package/payload/platform/services/whatsapp-channel/dist/notification.js +26 -0
  34. package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
  35. package/payload/platform/services/whatsapp-channel/dist/server.js +41 -14
  36. package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
  37. package/payload/premium-plugins/writer-craft/mcp/dist/index.js +1 -1
  38. package/payload/premium-plugins/writer-craft/mcp/dist/index.js.map +1 -1
  39. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.d.ts +2 -0
  40. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.d.ts.map +1 -1
  41. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.js +1 -1
  42. package/payload/premium-plugins/writer-craft/mcp/dist/tools/voice-distil-profile.js.map +1 -1
  43. package/payload/premium-plugins/writer-craft/mcp/src/index.ts +1 -1
  44. package/payload/premium-plugins/writer-craft/mcp/src/tools/voice-distil-profile.ts +3 -1
  45. package/payload/server/{chunk-W4EM7RK4.js → chunk-QHD5TKLQ.js} +2 -0
  46. package/payload/server/maxy-edge.js +1 -1
  47. package/payload/server/server.js +551 -405
  48. package/payload/platform/plugins/admin/hooks/__tests__/pin-identity-gate.test.sh +0 -96
  49. package/payload/platform/plugins/admin/hooks/pin-identity-gate.sh +0 -146
@@ -1,96 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Regression test for pin-identity-gate.sh (Task 619).
3
- #
4
- # Covers:
5
- # 1. Non-admin role → ALLOW (no-op)
6
- # 2. admin, unauthenticated, ordinary tool → BLOCK (op=pin-prompted)
7
- # 3. admin, already authenticated (state file) → ALLOW
8
- # 4. admin, auth tool, endpoint match → ALLOW + state written (op=pin-bound)
9
- # 5. admin, auth tool, endpoint miss → BLOCK (op=session-terminated)
10
- # 6. admin, auth tool, endpoint unavailable → BLOCK (op=pin-unavailable)
11
- # 7. admin, auth tool, endpoint unreachable → BLOCK (op=pin-error)
12
- #
13
- # The validate endpoint is stubbed via a `curl` shim on PATH whose response is
14
- # driven by $FAKE_VALIDATE_KIND.
15
-
16
- set -u
17
- HOOK="$(cd "$(dirname "$0")/.." && pwd)/pin-identity-gate.sh"
18
- [ -x "$HOOK" ] || { echo "FAIL: $HOOK not executable" >&2; exit 1; }
19
-
20
- TMP_DIR=$(mktemp -d)
21
- trap 'rm -rf "$TMP_DIR"' EXIT
22
- mkdir -p "$TMP_DIR/bin" "$TMP_DIR/state"
23
-
24
- # curl shim: emit a canned validate response based on $FAKE_VALIDATE_KIND.
25
- cat > "$TMP_DIR/bin/curl" <<'SHIM'
26
- #!/usr/bin/env bash
27
- case "${FAKE_VALIDATE_KIND:-}" in
28
- match) echo '{"kind":"match","userId":"user-0001"}' ;;
29
- miss) echo '{"kind":"miss"}' ;;
30
- unavailable) echo '{"kind":"unavailable"}' ;;
31
- corrupt) echo '{"kind":"corrupt"}' ;;
32
- unreachable) echo '' ;;
33
- *) echo '' ;;
34
- esac
35
- SHIM
36
- chmod +x "$TMP_DIR/bin/curl"
37
-
38
- AUTH_TOOL='mcp__plugin_admin_admin__admin-identity-authenticate'
39
- PASS=0; FAIL=0
40
-
41
- # run <role> <kind> <stdin-json> [specialist] ; sets EXIT and ERR
42
- run() {
43
- ERR=$(printf '%s' "$3" | \
44
- PATH="$TMP_DIR/bin:$PATH" \
45
- MAXY_SESSION_ROLE="$1" \
46
- MAXY_SPECIALIST="${4:-}" \
47
- FAKE_VALIDATE_KIND="$2" \
48
- MAXY_IDENTITY_GATE_STATE_DIR="$TMP_DIR/state" \
49
- MAXY_IDENTITY_VALIDATE_URL="http://stub/validate" \
50
- bash "$HOOK" 2>&1 >/dev/null)
51
- EXIT=$?
52
- }
53
-
54
- check() { # <label> <want-exit> <grep-or-->
55
- if [ "$EXIT" != "$2" ]; then echo "FAIL[$1]: exit=$EXIT want=$2 err=$ERR"; FAIL=$((FAIL+1)); return; fi
56
- if [ "$3" != "-" ] && ! printf '%s' "$ERR" | grep -q "$3"; then echo "FAIL[$1]: missing '$3' in: $ERR"; FAIL=$((FAIL+1)); return; fi
57
- echo "PASS[$1]"; PASS=$((PASS+1))
58
- }
59
-
60
- # 1. non-admin → allow
61
- run public '' '{"session_id":"s1","tool_name":"Bash","tool_input":{}}'
62
- check non-admin 0 -
63
-
64
- # 1b. admin but specialist subagent (MAXY_SPECIALIST set) → allow (no-op)
65
- run admin '' '{"session_id":"s1b","tool_name":"Bash","tool_input":{}}' database-operator
66
- check specialist-exempt 0 -
67
-
68
- # 2. admin unauth, ordinary tool → block
69
- run admin '' '{"session_id":"s2","tool_name":"Bash","tool_input":{}}'
70
- check unauth-block 2 "op=pin-prompted"
71
-
72
- # 3. admin, authenticated (state file present) → allow
73
- echo '{"userId":"user-0001"}' > "$TMP_DIR/state/s3.json"
74
- run admin '' '{"session_id":"s3","tool_name":"Bash","tool_input":{}}'
75
- check authed-allow 0 -
76
-
77
- # 4. admin, auth tool, match → allow + state written + pin-bound
78
- run admin match "{\"session_id\":\"s4\",\"tool_name\":\"$AUTH_TOOL\",\"tool_input\":{\"pin\":\"1234\"}}"
79
- check match-allow 0 "op=pin-bound"
80
- [ -f "$TMP_DIR/state/s4.json" ] && { echo "PASS[match-state-written]"; PASS=$((PASS+1)); } || { echo "FAIL[match-state-written]"; FAIL=$((FAIL+1)); }
81
-
82
- # 5. admin, auth tool, miss → block + terminate
83
- run admin miss "{\"session_id\":\"s5\",\"tool_name\":\"$AUTH_TOOL\",\"tool_input\":{\"pin\":\"9999\"}}"
84
- check miss-block 2 "op=session-terminated"
85
-
86
- # 6. admin, auth tool, unavailable → block
87
- run admin unavailable "{\"session_id\":\"s6\",\"tool_name\":\"$AUTH_TOOL\",\"tool_input\":{\"pin\":\"1\"}}"
88
- check unavailable-block 2 "op=pin-unavailable"
89
-
90
- # 7. admin, auth tool, unreachable endpoint → block (fail-closed)
91
- run admin unreachable "{\"session_id\":\"s7\",\"tool_name\":\"$AUTH_TOOL\",\"tool_input\":{\"pin\":\"1\"}}"
92
- check unreachable-block 2 "op=pin-error"
93
-
94
- echo "---"
95
- echo "PASS=$PASS FAIL=$FAIL"
96
- [ "$FAIL" = 0 ] || exit 1
@@ -1,146 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Native-CC admin PIN identity gate (Task 619).
3
- #
4
- # PreToolUse hook, registered under the universal (no-matcher) entry so it fires
5
- # for EVERY tool call on a native-CC admin session. It denies all tools until the
6
- # operator authenticates: the agent must call `admin-identity-authenticate` with a
7
- # PIN that the loopback validate endpoint matches against users.json. On match the
8
- # hook records per-session auth state (keyed by the conversation `session_id` it
9
- # reads from stdin) and lets every subsequent tool through. Enforcement is here —
10
- # a model that skips the prompt cannot reach any other tool.
11
- #
12
- # Scope: only native loopback admin sessions (MAXY_SESSION_ROLE=admin). Specialist
13
- # subagents dispatched via the Task tool share the parent conversation's
14
- # session_id, so they pass once the operator session is authenticated.
15
- #
16
- # Protocol: exit 0 = allow, exit 2 = block (stderr message shown to the agent),
17
- # matching the sibling gate hooks. Fail-closed on terminal stdin.
18
- #
19
- # Lifecycle (one [admin-identity] line per step, correlated by sessionId):
20
- # op=loopback-spawn-received → op=pin-prompted → (op=pin-bound source=pin |
21
- # op=pin-miss → op=session-terminated) ; the MCP tool emits op=about-owner-loaded.
22
-
23
- set -uo pipefail
24
-
25
- # Task 681 — PIN identity gate SUSPENDED. The hard PreToolUse PIN block is
26
- # removed pending a new multi-admin authentication design. The block made every
27
- # tool (including the WhatsApp channel reply tool) unreachable until a PIN was
28
- # entered, which is impossible on non-interactive surfaces like the WhatsApp
29
- # channel (Task 677). This hook now allows every tool. The original gating logic
30
- # is retained below the early exit for reference and quick revert; the
31
- # replacement auth (channel-bindings + per-admin identity) is Task 681.
32
- # Silent exit (no per-tool-call log line) — this fires on every tool call.
33
- exit 0
34
-
35
- if [ -t 0 ]; then
36
- echo "Blocked: pin-identity-gate received no stdin (cannot inspect tool call). Failing closed." >&2
37
- exit 2
38
- fi
39
- INPUT=$(cat)
40
-
41
- # Only native loopback admin OPERATOR sessions are in scope:
42
- # - MAXY_SESSION_ROLE=admin excludes public/access sessions.
43
- # - MAXY_SPECIALIST empty excludes pty-spawned specialist/recorder sessions,
44
- # which carry role=admin but are not human operators and never enter a PIN
45
- # (mirrors the recursion guard the other admin hooks use). Task-tool
46
- # specialist subagents share the operator's session_id + empty MAXY_SPECIALIST,
47
- # so they pass via the operator's auth-state file once it is bound.
48
- [ "${MAXY_SESSION_ROLE:-}" = "admin" ] || exit 0
49
- [ -z "${MAXY_SPECIALIST:-}" ] || exit 0
50
-
51
- # ----- Parse fields from stdin (python3, robust on nested tool_input) -------
52
- SESSION_ID=$(printf '%s' "$INPUT" | python3 -c 'import json,sys
53
- try: d=json.load(sys.stdin)
54
- except Exception: d={}
55
- print(d.get("session_id","") or "")' 2>/dev/null)
56
- TOOL_NAME=$(printf '%s' "$INPUT" | python3 -c 'import json,sys
57
- try: d=json.load(sys.stdin)
58
- except Exception: d={}
59
- print(d.get("tool_name","") or "")' 2>/dev/null)
60
-
61
- SID8="${SESSION_ID:0:8}"; [ -z "$SID8" ] && SID8='-'
62
- log() { echo "[admin-identity] $1" >&2; }
63
-
64
- # ----- Resolve account/state dir -------------------------------------------
65
- # The account dir basename IS the ACCOUNT_ID (resolve-account-dir.sh), and the
66
- # rc child env carries ACCOUNT_ID, so resolve deterministically rather than
67
- # `find | head -1` — which does not skip dotfiles and could pick the sibling
68
- # `data/accounts/.trash/`, diverging from the manager's `spawnCwd` (= the
69
- # account dir) and stranding state the standing audit can never reconcile.
70
- HOOK_DIR="$(cd "$(dirname "$0")" 2>/dev/null && pwd)"
71
- PLATFORM_ROOT_RESOLVED="${HOOK_DIR}/../../.."
72
- ACCOUNTS_DIR="${PLATFORM_ROOT_RESOLVED}/../data/accounts"
73
- ACCOUNT_DIR=""
74
- if [ -n "${ACCOUNT_ID:-}" ]; then
75
- ACCOUNT_DIR="${ACCOUNTS_DIR}/${ACCOUNT_ID}"
76
- elif [ -d "$ACCOUNTS_DIR" ]; then
77
- # Defensive fallback only when ACCOUNT_ID is unset — exclude dot-entries.
78
- ACCOUNT_DIR=$(find "$ACCOUNTS_DIR" -mindepth 1 -maxdepth 1 -type d ! -name '.*' 2>/dev/null | head -1)
79
- fi
80
- STATE_DIR="${MAXY_IDENTITY_GATE_STATE_DIR:-${ACCOUNT_DIR}/state/admin-identity}"
81
- STATE_FILE="${STATE_DIR}/${SESSION_ID}.json"
82
-
83
- AUTH_TOOL='mcp__plugin_admin_admin__admin-identity-authenticate'
84
- VALIDATE_URL="${MAXY_IDENTITY_VALIDATE_URL:-http://127.0.0.1:${MAXY_UI_INTERNAL_PORT:-0}/api/admin/identity/validate}"
85
-
86
- # Already authenticated for this conversation → pass everything through.
87
- if [ -n "$SESSION_ID" ] && [ -f "$STATE_FILE" ]; then
88
- exit 0
89
- fi
90
-
91
- log "op=loopback-spawn-received sessionId=${SID8}"
92
-
93
- # ----- The authenticate tool: validate, bind on match, terminate on miss ----
94
- if [ "$TOOL_NAME" = "$AUTH_TOOL" ]; then
95
- PIN=$(printf '%s' "$INPUT" | python3 -c 'import json,sys
96
- try: d=json.load(sys.stdin)
97
- except Exception: d={}
98
- ti=d.get("tool_input") or {}
99
- print(ti.get("pin","") or "")' 2>/dev/null)
100
-
101
- REQ=$(python3 -c 'import json,sys
102
- print(json.dumps({"pin": sys.argv[1], "sessionId": sys.argv[2]}))' "$PIN" "$SESSION_ID" 2>/dev/null)
103
- RESP=$(printf '%s' "$REQ" | curl -s --max-time 5 -X POST -H 'content-type: application/json' -d @- "$VALIDATE_URL" 2>/dev/null)
104
- KIND=$(printf '%s' "$RESP" | python3 -c 'import json,sys
105
- try: print((json.load(sys.stdin) or {}).get("kind","") or "")
106
- except Exception: print("")' 2>/dev/null)
107
-
108
- case "$KIND" in
109
- match)
110
- USERID=$(printf '%s' "$RESP" | python3 -c 'import json,sys
111
- print(json.load(sys.stdin).get("userId","") or "")' 2>/dev/null)
112
- mkdir -p "$STATE_DIR" 2>/dev/null
113
- printf '{"userId":%s,"ts":"%s"}' \
114
- "$(python3 -c 'import json,sys;print(json.dumps(sys.argv[1]))' "$USERID")" \
115
- "$(date -u +%FT%TZ)" > "$STATE_FILE" 2>/dev/null
116
- log "op=pin-bound sessionId=${SID8} userId=${USERID:0:8} source=pin authSurface=loopback"
117
- exit 0
118
- ;;
119
- miss)
120
- log "op=pin-miss sessionId=${SID8} reason=no-matching-user"
121
- log "op=session-terminated sessionId=${SID8} reason=pin-auth-failed"
122
- echo "PIN did not match. This session is being terminated. Start a new session and enter a valid PIN." >&2
123
- exit 2
124
- ;;
125
- unavailable)
126
- log "op=pin-unavailable sessionId=${SID8} reason=users-json-empty"
127
- echo "No admin PIN is configured for this install. Complete onboarding before using the admin agent." >&2
128
- exit 2
129
- ;;
130
- corrupt)
131
- log "op=pin-error sessionId=${SID8} reason=users-json-corrupt"
132
- echo "Admin user configuration is corrupt. Re-run the seed script before authenticating." >&2
133
- exit 2
134
- ;;
135
- *)
136
- log "op=pin-error sessionId=${SID8} reason=validate-unreachable"
137
- echo "Identity validation is unavailable; cannot proceed without authentication." >&2
138
- exit 2
139
- ;;
140
- esac
141
- fi
142
-
143
- # ----- Unauthenticated and not the auth tool → block -----------------------
144
- log "op=pin-prompted sessionId=${SID8}"
145
- echo "Authenticate first: call admin-identity-authenticate with the operator's PIN. No other tool is reachable until a matching PIN is bound for this session." >&2
146
- exit 2