Skip to content

fix(graphify): split the private-path predicate so the report gate stops flagging documented ~/ references - #53

Merged
KimYx0207 merged 1 commit into
KimYx0207:mainfrom
qitiandashenggogogo:fix/graphify-report-identity-gate
Aug 8, 2026
Merged

fix(graphify): split the private-path predicate so the report gate stops flagging documented ~/ references#53
KimYx0207 merged 1 commit into
KimYx0207:mainfrom
qitiandashenggogogo:fix/graphify-report-identity-gate

Conversation

@qitiandashenggogogo

Copy link
Copy Markdown
Contributor

Problem

meta:graphify:check fails unconditionally on a clean checkout, at the second gate:

GRAPH_REPORT.md exposes a private local path; rebuild after sanitizing upstream output.

There is no private path in the report. GRAPH_REPORT.md faithfully quotes comments from tracked repository files, and canonical/runtime-assets/claude/commands/save-progress/SKILL.md contains the line:

# Detect the Python hook path — it lives in ~/.claude/hooks/

hasPrivateLocalPath has a ~[\\/] branch, so that documented reference trips the gate. The gate is checking a tracked, machine-independent string and calling it a leak.

Why this is a type confusion, not a regex bug

The two call sites in graphify-cli.mjs (checkGraphFreshness and stampGraphFreshness) ask a narrower question than the predicate answers.

A bare ~/ is byte-identical on every machine and embeds no user or host name. A drive letter, a UNC host, or an absolute home root (/Users/…, /home/…, /root/…) all embed a real identity. These are two different object classes; only the second is a privacy leak in published report output.

So this adds revealsMachineIdentity for the identity-bearing class and uses it at the two GRAPH_REPORT.md gates. hasPrivateLocalPath is unchanged — its broader tilde branch stays as the fail-closed backstop for home-relative strings that sanitizeKnownMetaKimHomeAliases declined to rewrite, and it keeps guarding every other call site.

Difference-set justification

I enumerated the strings the old predicate blocks that the new one admits. Of those, the number that can actually identify a user or a machine is zero — they are all bare-~ forms (~/, ~\AppData, file:///~/notes). All five identity-bearing classes remain blocked:

input revealsMachineIdentity
/Users/Kim/private.txt blocked
C:/Users/Kim/private.txt blocked
path=C:\Users\Kim\private.txt blocked
\\server\share\private.txt blocked
/home/kim/private.txt, /root/.config/private blocked
~/, ~\AppData, file:///~/notes admitted (no identity)
https://www.aiking.dev/ admitted (not a drive path)

Tests

tests/setup/graphify-output-sanitize.test.mjs gains a case covering both directions, including the exact save-progress/SKILL.md line that triggers the failure. node --test tests/setup/graphify-output-sanitize.test.mjs → 18/18 pass on this branch head.

Scope and limitations — please read before merging

  1. This commit alone does not turn meta:graphify:check green. An earlier gate short-circuits before this one and fails on macOS; that is fix(graphify): canonicalize temp base so the isolated-cwd assertion is satisfiable on macOS #52. Both are needed for a green run on macOS. This PR is cut from origin/main and is independent of fix(graphify): canonicalize temp base so the isolated-cwd assertion is satisfiable on macOS #52 — the two touch disjoint files (graphify-unicode-normalize.mjs vs. graphify-private-path.mjs / graphify-cli.mjs) and can merge in either order.

  2. I could not run the full meta:graphify:check end to end. It requires a working GEMINI_API_KEY, which I do not have. That is an environment limitation on my side, unrelated to this change. Verification here is the unit-level regression above plus reading the two call sites.

  3. ~jamie/, ~root/, and lowercase /users/ are pre-existing gaps that this PR does not fix. To be explicit, since it would be easy to misread this as a narrowing I introduced: the existing hasPrivateLocalPath tilde branch is ~[\\/], which requires the tilde to be immediately followed by a separator, so ~jamie/x already returns false today. Measured on this branch:

    "~jamie/x"   hasPrivateLocalPath=false   revealsMachineIdentity=false
    "~root/x"    hasPrivateLocalPath=false   revealsMachineIdentity=false
    

    Both predicates miss them equally. Widening that is a separate decision about the sanitizer's threat model, and I did not want to smuggle it into a fix for a false positive. Happy to send it as a follow-up if you want it.

  4. The 8 call sites in graphify-node-identity.mjs are out of scope. I have no reproduction showing they suffer the same confusion, and I did not want to change gates I could not exercise.

Environment

macOS 26.5.2, Node v24.12.0. Not tested on Windows or Linux; the change is a pure-function predicate with no platform-specific behavior, but the added /(Users|home|root)/ and UNC branches are unchanged from the original expression.

GRAPH_REPORT.md 会忠实引用已跟踪文件里的注释,其中
canonical/runtime-assets/claude/commands/save-progress/SKILL.md
含一句 `~/.claude/hooks/`,导致 hasPrivateLocalPath 命中、整个
meta:graphify:check 恒失败。

裸 `~/` 在每台机器上字节相同、不含任何身份信息,与
/Users/<name>/、C:\、UNC 主机名不是同一类对象。新增只认身份绑定
路径的 revealsMachineIdentity,用于 GRAPH_REPORT.md 的两处闸;
hasPrivateLocalPath 保持零改动,其 tilde 分支继续为别名 sanitizer
拒绝改写的路径做 fail-closed 兜底。

差集反证:旧谓词拦得住而新谓词放行的字符串中,真能识别用户或
机器的为 0 条;五类身份路径全部仍被拦截。
@KimYx0207
KimYx0207 merged commit 7e1dbd2 into KimYx0207:main Aug 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants