* docs(macos): document codesign side-effect popup ("微信" 想访问其他 App 的数据)
After `codesign --force --deep --sign - /Applications/WeChat.app`, macOS
treats the re-signed WeChat as a different code identity from the
original. When WeChat then accesses its own container / cache / app-group
data (notably triggered when opening 公众号 articles), macOS fires the
"'微信' 想访问其他 App 的数据" popup.
This is a known side-effect of the current macOS invasive init path,
not a "wx-cli is reading other apps' data" issue and not a 公众号-only
problem — 公众号 is just a high-frequency trigger surface because of
WebView / cache access.
Document this in 3 places per agreed scope:
- README.md macOS init: add "副作用提示" callout linking to the guide
- docs/macos-permission-guide.md: new §六 with first-principles
explanation, mitigation options, and long-term direction
- src/cli/init.rs: print a short macOS-only warning at the end of
`wx init` so users see it right when they finish the invasive setup
* review: stop overstating the trade-off and condition the init warning
Per codex review on PR #64:
1. src/cli/init.rs warning was unconditional but the wording presumed
the user had taken the ad-hoc re-sign path. If init goes through the
tier 2 path (Apple-signed WeChat + GUI Terminal + Developer Tools TCC
authorization), the warning would mis-fire. Reword conditionally and
point to the GitHub URL of the doc instead of a relative path that
release-binary / npm-installed users won't have on disk.
2. docs/macos-permission-guide.md §六 and the matching README callout
said "restoring official WeChat = giving up macOS memory-scan". This
contradicts the same guide's §一 实测表 which shows
"Apple 签名 + 本机 Terminal sudo = ✅". Restoring the official
signature only gives up the default re-sign path; the local-Terminal
+ Developer-Tools route still works on Apple-signed WeChat. Only
SSH + Apple-signed WeChat actually requires re-signing.
* review (round 2): caveat empirical gap + drop emoji
Self-review found two issues both LGTMs missed:
1. The "tier 2 仍走通" claim (README + §六) leans on §一 实测表 row
"Apple 签名 + 本机 Terminal sudo = ✅". But that data only covers
macOS 10.15 (Catalina) and 11.1 (Big Sur). macOS 14/15 — the exact
versions where the popup behavior originates — were never tested
for that path in this project. Add an explicit caveat instead of
silently extrapolating across major macOS versions.
2. `init.rs` warning used a ⚠️ emoji prefix, which violates the
project + global "no emojis in files unless requested" rule. README
and the rest of init.rs have no emoji. Replace with `[macOS]`.
When auto_detect_db_dir() fails, the error told the user to edit
config.json without saying where that file lives. On Windows that is
%USERPROFILE%\.wx-cli\config.json, which is non-obvious.
Use the config_path already computed at the top of cmd_init() so the
error message includes the absolute path, plus a concrete example of
the db_dir shape.
Root cause: `wx init` does two conceptually-separate things in one
privileged process: (1) scan WeChat memory for keys (needs root) and
(2) write ~/.wx-cli/{all_keys,config}.json (needs only user). When
run under sudo, the files inherit root ownership, so later the daemon
(forked as the user) can't create daemon.sock/log/pid → silent 15s
timeout.
Also: all_keys.json is the raw AES key; 0644 leaked it to every user
on the system.
Fix in init.rs: after the scan completes, immediately setgid+setuid
back to \$SUDO_UID/\$SUDO_GID and set umask 0o077 before any file I/O.
Files are then created as the real user with 0600 by default. Migrate
old broken installs by chown+chmod-recursive before the setuid call.
Fix in transport.rs: pre-check that ~/.wx-cli/ is writable before
spawning daemon; on EACCES print a clear "sudo chown -R ..." hint
instead of the useless "daemon 启动超时" message.
Three related bugs caused "wx init" and daemon startup to fail on Windows:
1. init.rs: create ~/.wx-cli/ before writing all_keys.json (was created
only before config.json, so first write failed with ENOENT)
2. transport.rs (Windows): daemon.log was always empty because stderr
was never redirected, and log file open silently fell back to null
when parent dir didn't exist. Now mirror the Unix version: create
parent dir, try_clone to redirect both stdout and stderr.
3. server.rs (Windows): interprocess GenericNamespaced auto-prepends
\\.\pipe\ on Windows. Passing the full path caused a double-prefixed
pipe name that clients (using raw \\.\pipe\wx-cli-daemon) could
never connect to, leading to the 15s startup timeout.