* fix(federation): verified event identity must win over publisher-controlled content
fetchRecent/fetchManyOn/fetchChannel spread the parsed message content
after the signature-verified id/pubkey/created_at, so a publisher could
put those keys in their own content and overwrite their verified
identity downstream (reduceClaims trusts .pubkey for claim
release/handoff authorization). Reorder so verified fields always win.
Also in x-federation-channels.ts: reqEvents() never called verifyEvent()
at all, so channel-read/grant-accept events were trusted unsigned; add
the check. Same content-override reorder in x_federation_channel_read.
fix(hooks): escape argv for the Windows shell:true npm-shim path
ruflo-hook.cjs's invokeHook() passes hook-derived values (command text,
file paths) through cmd.exe via shell:true to resolve npm's .cmd/.ps1
shims. Node does no escaping in that mode, so a value containing a
cmd.exe metacharacter could be reinterpreted as a separate command or
redirection instead of reaching the CLI as data. Add escapeCmdArg()
(qntm.org/cmd algorithm, same one cross-spawn uses) and apply it to
every argv element on that path.
No native Windows/cmd.exe available to execute this end-to-end in this
environment — verified at the string-transform level only (8 unit
tests). Real Windows execution remains a required follow-up gate.
Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01RYP825phHMjPRmmjkcAWpq
* fix(ci): register new hook test env var and test file with CI guards
Follow-up to the previous commit's escape-cmd-arg.test.cjs:
- Register RUFLO_HOOK_UNIT_TEST in audit-env-var-precedence.mjs's
KNOWN_ESCAPE_HATCHES, matching the existing RUFLO_HOOK_CLI_OVERRIDE/
RUFLO_HOOK_DEBUG_STDOUT entries for the same file.
- Register plugins/ruflo-core/scripts/escape-cmd-arg.test.cjs in
ci-test-baseline.txt, matching the sibling mcp-launch.test.cjs entry —
both are node:test-based .cjs files that vitest's own JSON reporter
marks "failed" (it doesn't recognize the node:test API) even though
every test inside genuinely passes under `node --test`.
Verified locally: node scripts/audit-env-var-precedence.mjs now passes
(exit 0). A scoped `vitest run` + `ci-test-ratchet.mjs --report` against
just these two files confirms escape-cmd-arg.test.cjs is no longer an
unexpected failure (the one remaining flagged file is a stale local
worktree artifact under .claude/worktrees/, not part of a clean CI
checkout).
Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01RYP825phHMjPRmmjkcAWpq