* fix(security): compare candidate and prefix in the same canonical form (#3010)
`validate()` resolved the candidate with `fs.realpath` but the allowed
prefixes were only `path.resolve()`d, so the two sides were compared in
different forms and nothing under a prefix reached through a symlink could
ever match. On macOS that is every temp directory — `os.tmpdir()` is
`/var/folders/...` and `/var` is a symlink to `/private/var` — so
`ruflo proxy install` rejected the binary it had just signature-verified.
Linux is unaffected because `/tmp` is real, which is why CI stayed green.
Keep both forms of every prefix and compare against the one matching how
the candidate was resolved. Canonicalizing the prefixes outright would have
broken `validateSync()` / `isWithinAllowed()`, which are documented as
lexical-only, in the mirror direction.
When the candidate's leaf does not exist, canonicalize its longest existing
ancestor instead of falling back to the lexical path — otherwise
`allowNonExistent` (the default) would regress under a symlinked prefix.
That also closes a hole this exposed: `<allowed>/escape/not-written-yet`,
where `escape` symlinks outside the prefix, was previously accepted because
`realpath` threw ENOENT on the missing leaf.
Escapes stay blocked, and the regression tests construct the symlink
explicitly rather than relying on the macOS quirk, so they hold on every
platform. 3 of the 6 fail without this change.
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(security): keep root prefixes usable and leave strict results untouched
Three defects found by an adversarial review of the previous commit.
`allowNonExistent: false` was still canonicalizing the candidate on ENOENT.
The call already fails, so the only effect was rewriting the `resolvedPath`
and `matchedPrefix` reported back — a silent shape change for any caller
reading those off a rejected result. Canonicalize only when non-existent
paths are actually allowed.
A root prefix (`/`, `C:\`, a UNC share root) already ends in a separator, so
anchoring the boundary as `prefix + path.sep` searched for `//` and rejected
every descendant. Pre-existing at all three comparison sites — this change
only widened how a prefix can end up being a root, since one can now
canonicalize to it. Extracted `isWithinPrefix`, which keeps the boundary
anchored so `/srv/app-secrets` is still outside `/srv/app`.
The guarded symlink tests returned early instead of skipping, so they
reported as passed on a host that cannot create links, and the flag was
never reset between cases. They now skip properly and reset per case.
Also documents that prefixes are canonicalized once, at construction: the
allowlist keeps denoting what it named when configured, rather than handing
whoever can rewrite a link the ability to redirect it later.
Co-Authored-By: RuFlo <ruv@ruv.net>
---------
Co-authored-by: RuFlo <ruv@ruv.net>
PathValidator.validate() canonicalizes the candidate path through
fs.realpath (when resolveSymlinks is on, the default), but the constructor
only ever path.resolve()d the allowed prefixes — never realpath'd them. On
any platform where a prefix is itself reached through a symlink (e.g.
macOS os.tmpdir() under /var, itself a symlink to /private/var), the
realpath'd candidate can never match the non-realpath'd prefix, and every
path under that prefix — including the prefix's own contents — is
rejected as "outside allowed directories".
This broke `ruflo proxy install` on macOS: the download and Ed25519
signature verification both succeed, then the defense-in-depth path check
in proxy/install.ts fails on the extracted binary, which lives under a
workDir created via os.tmpdir().
Fix: realpath the prefixes at construction time too, with the same
ENOENT-tolerant fallback to path.resolve() that validate() already uses
for candidates (a prefix directory that doesn't exist yet degrades
gracefully instead of throwing).
Implements all 3 phases of ADR-377 (ruvnet/ruflo#2516, tracked in #2873):
AgentDB's retrieval and write paths had zero certified defenses against
memory poisoning — SMSR (arXiv:2606.12703) shows 93-100% undefended attack
success. All three phases are off by default; enabling each is opt-in via
env flag until independently benchmarked, per the ADR's own gate criteria.
Phase 1 — AgentDbRetrievalGuard (@claude-flow/memory)
- New `agentdb-retrieval-guard.ts`, wired into `AgentDBBackend.search()`
(covers `query()`'s semantic path too, since it calls `search()`
internally). Reuses `@claude-flow/security`'s `ToolOutputGuardrail`
(ADR-131) for the actual OWASP LLM01/LLM08 pattern scan rather than
duplicating it — `@claude-flow/memory` now depends on
`@claude-flow/security` (no cycle: security has zero workspace deps).
- Size gate + guardrail scan per retrieved chunk. Flag-only by default;
`CLAUDE_FLOW_RETRIEVAL_GUARD_STRICT=true` drops unsafe/oversized chunks
instead of just annotating them. Both flags off by default
(`CLAUDE_FLOW_RETRIEVAL_GUARD=true` to enable scanning at all).
Phase 2 — MemoryPoisonForensics (@claude-flow/hooks)
- New `workers/memory-poison-forensics.ts`: rolling-window z-score anomaly
detection on write-interval and content-length features per
(agentId, namespace), reproducing the Forensic Trajectory Signatures
(arXiv:2606.30566) shape (behavioral features on write *sequences*, not
content). Opt-in `HookEvent.PostToolUse` handler for memory-write tools;
`CLAUDE_FLOW_POISON_FORENSICS=0` disables recording.
- NOT wired into any of this repo's three separate "worker" dispatch
systems (hooks' own workers/index.ts codebase-analyzers,
@claude-flow/swarm's worker-dispatch.ts 12-trigger table, or the CLI's
scheduled daemon) — @claude-flow/swarm is a deliberately
zero-workspace-dependency package and adding hooks there would break
that property; picking the wrong one of three ambiguous dispatch tables
seemed worse than leaving that integration as an explicit follow-up.
See the file header for detail.
Phase 3 — McpCallerIdentity (@claude-flow/security)
- New `mcp-caller-identity.ts`: per-invocation Ed25519-signed capability
tokens (callerId + toolName + nonce + 30s TTL by default), native
node:crypto sign/verify following the same pattern already used by
`@claude-flow/browser`'s witness-signer.ts (reimplemented rather than
cross-imported — a security-primitives module depending on the browser
package would be a backwards layering dependency).
- Standalone issue/verify API; deliberately NOT wired into
`AgentAuthorizationPropagator.checkToolCall` (ADR-144) or any tool
dispatcher — this repo has at least 3 distinct `ToolRegistry`
implementations and guessing which is authoritative risked silently
wiring the wrong path. `CLAUDE_FLOW_MCP_CALLER_AUTH` defaults to
disabled, matching the ADR's own text: key distribution needs a
follow-on ADR before this ships enabled.
Deviations from the ADR's guessed file paths/class names (documented
inline where relevant): the ADR was written against aspirational paths
(`agentdb/retrieval-guard.ts`, a `BackgroundWorker` interface,
`SafeExecutor`) that don't match the real repo layout — implementation
targets the actual `AgentDBBackend`, the actual worker systems, and the
actual `AgentAuthorizationPropagator`/tool-registries respectively.
Tests: 31 new tests across the three packages (9 + 11 + 11), all passing;
full existing suites re-run clean (memory 451, hooks 145, security 570 —
zero regressions).
Adds the live Ruflo capability brain, governed federation and Cognitum product planes, source-bound concurrent harness contracts, ADRs 325-329, and the v3.32.28 guarded release train.
* feat(memory): typed provenance in AgentDB (ADR-323)
Corrects and implements the 2026-07-28 dream-cycle research proposal
(PR #2804, closed as superseded) for typed memory provenance in
AgentDB, addressing MemIR/MemSyco-Bench's "provenance-role collapse"
and memory-induced sycophancy findings.
The dream-cycle PR's proposed schema change targeted the wrong table
(`vector_indexes`, which is per-namespace HNSW index metadata, not
per-entry) and its filename collided with the already-merged
`ADR-322-metaharness-flywheel-integration.md` (#2817) — both corrected
here as ADR-323 against `memory_entries`, the real per-record table.
- memory-initializer.ts: `provenance_type` column (user_claim |
agent_output | system_observation | tool_result | unknown, default
unknown) on `memory_entries`, migrated for existing DBs via
`ensureSchemaColumns()`. `storeEntry()`/`searchEntries()` accept and
validate `provenanceType`/`provenanceFilter`.
- memory-bridge.ts: same wiring for the native better-sqlite3 AgentDB
v3 path (`bridgeStoreEntry`/`bridgeSearchEntries`).
- commands/memory.ts: `memory store --provenance <type>`, `memory
search --provenance-filter <types>` (comma-separated, OR semantics).
- mcp-tools/memory-tools.ts + cli-core/mcp-tools/memory-defs.ts:
`memory_store`'s `provenance_type` param, `memory_search`'s
`provenance_filter` param (kept in sync across both tool-def sets).
Found and fixed during implementation: an initial design skipped the
RaBitQ/HNSW acceleration paths entirely whenever a provenance filter
was requested (neither carries provenance_type on their candidates).
This reproducibly crashed the CLI process on exit (a libuv assertion
on Windows) after printing correct results. Fixed by never skipping
those paths — RaBitQ now fetches provenance_type in its existing
per-candidate query, HNSW does one batched (namespace, key) lookup
afterward — eliminating the crash across repeated runs. See ADR-323's
"Implementation note" for detail.
7 new end-to-end tests (adr-323-memory-provenance.test.ts), including
a repeated-run regression guard for the crash. Full existing memory
suite re-verified with no regressions (one pre-existing, environment-
specific #2558 test failure confirmed identical against unmodified
main — better-sqlite3's native bridge is unavailable in this dev
environment, unrelated to this change).
Closes the follow-up from dream-cycle PR #2804 (closed as superseded).
Co-Authored-By: claude-flow <ruv@ruv.net>
* fix(memory): enforce provenance across retrieval paths
* feat: add agentic policy engine
* fix: align Codex MCP integration
* fix: keep MetaHarness dependencies optional
* fix: declare MetaHarness as optional peers
* fix: sync workspace lockfile
* fix: document policy tool selection guidance
* test: cover governed in-process flywheel
* ci: make MetaHarness absence drill deterministic
Follow-up from dream-cycle issue #2783 / PR #2784. Implements the v2 that the already-shipped v1 (commits 381b7ebcc/581cd2bf3) explicitly deferred: SimHash-based cross-tool fragment detection for MCP composition, and a ChannelGuard reusing the real InputValidator instead of a reinvented catalog. 29 new tests, 134/134 existing hooks tests passing, 0 regressions, clippy clean.
* fix(security): ADR-165 Phase 1 — close all critical CVEs, refresh registry, add CI gate
Closes ADR-165 Phase 1. Both workspaces pass `npm audit --audit-level=critical`.
## Before (2026-06-29)
| Workspace | Critical | High | Moderate | Total |
|-----------|----------|------|----------|-------|
| Root | **1** | 6 | 31 | 38 |
| v3 | **4** | 33 | 57 | 97 |
## After
| Workspace | Critical | High | Moderate | Total |
|-----------|----------|------|----------|-------|
| Root | **0** | 0 | 31 | 31 |
| v3 | **0** | 27 | 58 | 88 |
All 5 critical advisories closed (vitest GHSA-5xrq, handlebars prototype-pollution,
protobufjs constructor-pollution, plus 2 more in v3). 12 of 39 high advisories
closed via overrides; the remaining 27 v3 highs are deeper transitive chains
that would require breaking-change major bumps — flagged for ADR-165 Phase 2.
## Changes
### Root workspace overrides (package.json)
- `vitest`: `^1.0.0` → `^3.2.6` (closes critical GHSA-5xrq CVSS 9.8)
- `hono`: `>=4.11.4` → `>=4.12.25` (closes 6 hono advisories)
- `undici`: `>=7.18.0` → `>=8.5.0` (closes 7 undici advisories — bumps the
stale pin that ADR-165 flagged as still-in-vulnerable-range)
- `vite`: `>=6.4.6` → `>=8.0.16` (closes 2 vite advisories)
- NEW `@grpc/grpc-js`: `>=1.14.4`
- NEW `form-data`: `>=4.0.6`
- NEW `http-proxy-middleware`: `>=3.0.7`
- `@hono/node-server`: `>=1.19.10` → `>=1.19.14`
### v3 workspace overrides (v3/package.json + pnpm.overrides)
- `vitest`: `^4.0.16` → `^4.1.0` (and `@vitest/coverage-v8` matched)
- Top-level + pnpm overrides: `handlebars: >=4.7.9`, `protobufjs: >=8.6.0`
- 27 sub-package `package.json` updated to `vitest ^4.1.0`
### CVE registry refresh (v3/@claude-flow/security/src/CVE-REMEDIATION.ts)
Rewritten from 5 stale Jan-2026 entries to 16 total: 15 fixed, 1 open
(ADR165-OPEN-01 — PII pipeline wiring per ADR-164 §6.1 not yet on
dispatch-layer). `SECURITY_SUMMARY` is now computed dynamically from the
registry; `validateRemediation()` correctly returns `allFixed: false`
with 1 issue. ADR-165 §5 flagged this as THE Phase 2 priority — now closed.
### New CI gate
`.github/workflows/cve-audit.yml`:
- `audit-root` — `npm audit --audit-level=critical` in root, blocking
- `audit-v3` — same in v3, blocking
- `audit-high-report` — warn-only summary on high-severity drift
- Triggers: PR, push to main, daily cron
### ADR-165 §9 evidence ledger addendum
Captures AFTER-remediation `npm audit --json` metadata for both workspaces.
The diff between BEFORE (already in §9) and AFTER makes Phase 1 verifiable.
Also CORRECTED one prior surprise in §9: the `validate-input.ts` in
`mcp-tools/` is NOT a 9-line shim. It's 269 lines of real implementation.
(That was an inaccurate findings note from the initial audit.)
### §7.3 research items resolved
- `protobufjs` v3 chain confirmed gone after override pins
- `handlebars` v3 chain confirmed not user-reachable on the workflow path
(toolchain-only; override sufficient)
- `validate-input.ts` confirmed real implementation, not a shim (registry
entry corrected)
- CORS surface check: no `cors()` / `app.use(cors` call sites — the hono
CORS-wildcard advisory is not exploitable on the current server
- ADR-164 §6.1 PII pipeline NOT wired in current agentbbs dispatch —
recorded as ADR165-OPEN-01 (Phase 3 work)
## Gates (all PASS)
- `npm audit --audit-level=critical` root: exit 0 (was non-zero)
- `npm audit --audit-level=critical` v3: exit 0 (was non-zero)
- vitest suites: 105/109 pass (4 skip-conditional — same as before)
- ADR-112 audit: 352/352 tools with guidance
- business-pods smoke: 11/11 PASS
- agentbbs smoke: 8/8 PASS
- agenticow smoke: 8/8 PASS
- cli build: clean (tsc)
## Phase 2+ deferred
The 27 v3 high-severity advisories that remain are transitive chains with
no patched-in-range version. ADR-165 §6 Phase 2 picks these up after the
`cve-watch.yml` automation in §6 lands (NEW PR — not in scope here).
Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01WbBa4nccx5aGhXphoHxcni
* chore(lock): regen v3/pnpm-lock.yaml after override updates (PR #2508 CI fix)
PR #2508 added handlebars + protobufjs to v3 overrides + bumped vitest pin,
but v3/pnpm-lock.yaml wasn't regenerated. CI surfaced
ERR_PNPM_LOCKFILE_CONFIG_MISMATCH on every install step.
Same pattern as the previous lockfile-drift fixes on PR #2500 and #2503.
* fix(ci): cve-audit.yml jq-only + regen witness manifests for #1609 marker drift
Two PR #2508 CI failures fixed:
1. Static-regression-guard tripped on cve-audit.yml line 52: the static
YAML strict-parser sees `if high > 0:` inside the `run: |` block as
a YAML block-mapping key indicator. Refactored all 3 inline-python
blocks to use jq (preinstalled on ubuntu-latest) — no embedded
`if x > 0:` lines, so the YAML guard passes.
2. Witness marker drift smoke flagged fix-marker #1609 — the Phase 1
vitest bump (4.0.16 → 4.1.0) drifted the cited marker string in
v3/@claude-flow/aidefence/package.json. Updated `marker` field in
all 3 platform manifests + `desc` to reference ADR-165 Phase 1, then
re-signed via plugins/ruflo-core/scripts/witness/regen.mjs.
Co-Authored-By: RuFlo <ruv@ruv.net>
@claude-flow/security 3.0.0-alpha.8 → 3.0.0-alpha.10 (alpha.9 was already
on npm). Adds @noble/ed25519 to dependencies so its TS build succeeds
standalone — closes the TS2307 break that has been red on main since
2026-06-02 (#2311, #2275).
@claude-flow/cli, claude-flow, ruflo 3.10.37 → 3.10.38. CLI also pins
@claude-flow/security to ^3.0.0-alpha.10 so users picking up the wrapper
get the noble dep automatically.
All three published with latest+alpha+v3alpha aligned at 3.10.38.
Co-Authored-By: RuFlo <ruv@ruv.net>
Three HIGH-severity verification-cluster fixes shipping together.
#2311 — `@claude-flow/security` build fails with TS2307: `Cannot find module
'@noble/ed25519'`. The package imports it in integrity-verifier.ts:260 but
never declared it as a dep — the root override didn't propagate (lesson
from #2112). Declare it directly. Unblocks the `ToolOutputGuardrail smoke
(ADR-131)` job and the broader `V3 CI/CD Pipeline failing on main` cluster
documented in #2275.
#2274 — `plugins/ruflo-core/scripts/witness/verify.mjs:175` unconditionally
assigned `ed.etc.sha512Sync`. On `@noble/ed25519` v2 some patch versions
freeze `etc`, throwing `TypeError: Cannot add property sha512Sync, object
is not extensible` and aborting witness verification on every run (6+
documented occurrences). Guard with `if (!ed.etc.sha512Sync)` and a
try/catch fallback — sha512Sync is already wired internally on v2, so the
shim is only needed on v1. Verified against macOS, Linux, and Windows
manifests on this checkout: all three return `Ed25519 signature valid: yes`
with regressed=0 missing=0.
#2312 — `scripts/smoke-trajectory-graph-edges.mjs` TEST 2 OOMs at ~4 GB on
GitHub-runner default heap, killing the `graph trajectory hooks smoke
(ADR-130 P3)` job (SIGABRT exit 134). The allocation lives deep inside
`intelligence.recordTrajectory` → `@ruvector/ruvllm SonaCoordinator` on
first call; the runtime cause is tracked separately. Bump
`NODE_OPTIONS=--max-old-space-size=6144` on the CI step so the job
completes while the leak is investigated.
Co-Authored-By: RuFlo <ruv@ruv.net>
Three independent P1 components, each scoped to a single PR-sized change.
All three are off by default — flips become default in v4.0 — so existing
pipelines keep their exact behaviour.
ADR-144 P1 — AgentAuthorizationPropagator (#2248)
v3/@claude-flow/security/src/authorization/propagator.ts (new)
• AuthScope envelope (principal, granted tools/servers, delegation depth, expiry)
• wrapOutbound: monotonically-reducing scope, depth-decrement, expiry check
• checkToolCall: typed decisions (tool-not-in-scope / server-not-in-scope /
scope-expired / delegation-depth-exhausted) — never throws, telemetry-friendly
• verifyServerAuth: fail-closed on missing/empty credentials (P1 permissive
accept for non-empty — P4 wires real validator)
• Provenance buffer ring-bounded for P5 telemetry sink
• makeLegacyPermissiveScope shim for legacy-mode migrations
18 unit tests covering every invariant; all pass.
ADR-145 P1 — PluginIntegrityVerifier (#2254)
v3/@claude-flow/security/src/plugins/integrity-verifier.ts (new)
v3/@claude-flow/cli/src/plugins/trust/trust-anchors.json (new placeholder)
• Canonical JSON serialisation (deterministic key order) + SHA-256 manifest hash
• Ed25519 detached signature verification via @noble/ed25519 (probe-and-fall-
back, mirrors verify.mjs #1880 pattern so untrusted environments skip
rather than throw)
• Trust-anchor allowlist with exact / wildcard scope matching + expiry
• Structured VerificationStatus (pass / signature-missing / signature-invalid
/ manifest-hash-mismatch / unknown-signer / signer-expired)
• Stage-2 semantic-intent scan (SCH defence) lands in P2
13 unit tests including the round-trip sign→verify and tamper-flip cases.
ADR-146 P2 — guardrail call site in MCP dispatch (#2149 follow-up)
v3/@claude-flow/cli/src/mcp-client.ts — patch callMCPTool
• Lazy-resolves @claude-flow/security so cold-import cost doesn't hit
every CLI invocation; falls back to no-op if module unavailable
• Walks the result object one level deep (matches the flat-record shape
of every existing tool — deeper traversal would change the p99 latency
contract)
• Rejected fields replaced with typed marker: '<rejected-by-guardrail
tool="X" category=Y>' so callers can surface the rejection rather than
silently dropping
• Off by default. CLAUDE_FLOW_STRICT_GUARDRAIL=true turns it on; precedence
documented inline so the env-var audit passes without an escape-hatch entry.
4 wiring tests (legacy passthrough, strict-mode reject of known injection,
strict-mode passthrough on safe content, non-object results pass through).
Security index exports updated for all three. Builds clean (tsc with no
errors). All 4 audits + 2 regression smokes pass locally.
Co-Authored-By: RuFlo <ruv@ruv.net>
* feat(security): #2149 ADR-131 P1 — ToolOutputGuardrail + OWASP 2026 mapping
Closes the OWASP ASI01 (Agent Goal Hijacking) gap identified in the
2026-05-26 dream cycle. Adds a pure, synchronous, pattern-based screener
for content crossing the agent's content boundary (MCP tool results,
memory reads, external API responses) before it enters reasoning.
Design (full rationale in ADR-131):
- Eight built-in pattern categories: instruction-override, embedded-system
(ChatML / Llama [INST] / <system>), exfiltration, role-hijack, jailbreak,
hidden-unicode (bidi + zero-width), tool-spoofing, truncation
- Default policy: critical→reject, high→redact, medium→flag, low→allow
- Pure-function shape — safe to invoke in every tool result / memory read
- 32KB content scans in 0.1ms locally (target: <1ms p99)
Scope:
- P1 (this PR): class + tests + exports + ADR + OWASP matrix + CI smoke
- P2-P5 (follow-on): MCP dispatch, memory read, swarm Raft payload,
per-tool policy + telemetry — tracked in ADR-131
Validation:
- 24/24 vitest tests pass (9ms)
- 11/11 smoke checks against built dist/index.js
- Tested against the four canonical ASI01 attack shapes
- CI guard `tool-output-guardrail-smoke` wired into v3-ci.yml
OWASP Top 10 for Agentic Applications 2026 control matrix added:
v3/docs/security/owasp-agents-2026-mapping.md — flags ASI01/06/09/10 as
highest-priority remaining gaps.
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(plugins/ruflo-core/hooks): #2155 — wrap 3 unwrapped .sh hooks in /bin/bash -c
Three hooks (PreToolUse:Bash, PreToolUse:Write|Edit|MultiEdit, Stop)
invoked scripts/ruflo-hook.sh directly without an outer shell wrapper.
On Windows, Claude Code's hook executor spawned the .sh path, Node read
the shebang, attempted to exec /bin/bash (absent on Windows), and exited
with code 126 — surfacing as PostToolUse:Bash/PreToolUse:Bash/Stop hook
errors in every user session.
Wrapped each invocation in /bin/bash -c '... || true' to match the
existing pattern of the four other hooks in the same file. The || true
fallback now executes inside the bash subshell rather than relying on
the .sh body being readable. Validated as still working on POSIX.
Co-Authored-By: RuFlo <ruv@ruv.net>
This commit closes the chain started in ca0a6fa5c (standalone use recipes
landed in repo but never reached npm because no version bumps shipped).
## Changes
### Module version bumps (alpha.43)
- @claude-flow/memory → 3.0.0-alpha.17 (republish standalone use README)
- @claude-flow/embeddings → 3.0.0-alpha.18 (republish standalone use README)
- @claude-flow/security → 3.0.0-alpha.8 (republish standalone use README)
- @claude-flow/neural → 3.0.0-alpha.9 (pin @ruvector/sona to 0.1.5,
republish standalone use README)
- @claude-flow/cli → 3.7.0-alpha.43 (repin to new modules above)
- claude-flow → 3.7.0-alpha.43 (umbrella)
- ruflo → 3.7.0-alpha.43 (umbrella)
### Umbrella bump (alpha.44) — npm download badges
- @claude-flow/cli → 3.7.0-alpha.44
- claude-flow → 3.7.0-alpha.44
- ruflo → 3.7.0-alpha.44
### Neural sona pin (root fix for #2022)
@claude-flow/neural alpha.8 had `"@ruvector/sona": "latest"`, and
@ruvector/sona@0.1.6 (current latest on npm) shipped as an empty publish
— README + package.json only, no index.js or native bins. So every
fresh `npm install @claude-flow/neural@alpha.8` broke at import time
with `Cannot find package '.../node_modules/@ruvector/sona/index.js'`.
Alpha.9 pins to the exact known-good 0.1.5 (which has index.js + 7
platform-specific .node bins). Will revert to a range once
@ruvector/sona@0.1.7+ ships with content (tracked in #2022).
### npm download badges across every published package README
Added `shields.io/npm/dm/<pkg>` (monthly downloads) badges to:
- claims, cli-core, plugins (had no npm badges at all)
- plugin-agent-federation, plugin-iot-cognitum (no npm badges)
- browser, codex, mcp (had version badge, missing downloads)
- umbrella root README (now badges both `ruflo` + `claude-flow`)
The ruflo/README.md and v3/@claude-flow/cli/README.md auto-copy from
root via prepublishOnly, so they inherit the new badges on publish.
Packages that already carried downloads badges (aidefence, deployment,
embeddings, guidance, hooks, integration, memory, neural, performance,
providers, security, shared, swarm, testing) are unchanged.
## Live functional check on the published artifacts
- Fresh `npm install @claude-flow/neural@3.0.0-alpha.9`:
sona resolves to 0.1.5; `import('@claude-flow/neural')` returns
A2CAlgorithm, BalancedMode, BaseModeImplementation, BatchMode,
CuriosityModule, ... (was broken before alpha.9).
- Standalone use sections from ca0a6fa5c now visible on npmjs.com for
memory@alpha.17, embeddings@alpha.18, security@alpha.8, neural@alpha.9.
- npm dm/ badges resolve and render the current weekly download count.
Co-Authored-By: RuFlo <ruv@ruv.net>
Adds a 'Standalone use (without the Ruflo CLI)' section to each
module's README right after Installation, with copy-pasteable
recipes verified against the published artifacts (fresh `npm install`
clean room, no patched dist, exit 0 for every example).
Recipes:
@claude-flow/memory (@3.0.0-alpha.16)
1. HNSWIndex — add 3 vectors, search top-2, no other deps
2. ControllerRegistry + injected AgentDB — proves the v3
governance layer works on a caller-owned AgentDB instance
(the agentdb injection field added in #2019)
@claude-flow/embeddings
1. MockEmbeddingService + cosineSimilarity — embed + compare
without network calls
2. Provider swap snippet showing OpenAI / Transformers / etc.
keep the same API surface
@claude-flow/security (@3.0.0-alpha.7)
1. InputValidator.validate(EmailSchema) +
new PasswordHasher({ rounds: 12 }) +
createCredentialGenerator().generateApiKey() — three of the
OWASP top 10 in ~15 lines
2. createDevelopmentExecutor — git through the allowlist gate;
createProjectPathValidator — refuses `../` traversal with
errors[] surfaced
Bugs uncovered by running the recipes against live npm:
- `embed()` returns { embedding, tokens, ... }, not a raw Float32Array
(recipe destructures `.embedding`).
- createPasswordHasher(rounds: number) accepts a NUMBER, not a
config object (passing `{ rounds: 12 }` made config.rounds nest
into `{ rounds: 12 }` and bcryptjs threw 'Illegal arguments:
string, object'). Switched recipe to `new PasswordHasher(...)`.
- generateCredentials() does NOT generate API keys — that lives
on `CredentialGenerator.generateApiKey(prefix)`. Recipe now
uses createCredentialGenerator().generateApiKey().
- PathValidator result is { isValid, errors[], ... }, not
{ valid, error }. Recipe matches the real shape.
Not included — @claude-flow/neural standalone recipe:
@claude-flow/neural@3.0.0-alpha.8 currently fails on fresh
install because @ruvector/sona@0.1.6 is an empty publish (only
README + package.json — no index.js, no native bins).
@ruvector/sona@0.1.5 had full content (index.js + 7 platform
bins), so this is a regression in the latest sona release that
blocks the entire neural package from loading.
Rather than ship a broken recipe, the neural README gains a
'Known issue' callout pointing at @ruvector/sona@0.1.6. Fix
path: republish @ruvector/sona with content or pin
@claude-flow/neural to @ruvector/sona@^0.1.5 in its next bump.
Co-Authored-By: RuFlo <ruv@ruv.net>
* fix(security): drop bcrypt → bcryptjs to eliminate tar CVE chain (#1608)
`@claude-flow/security` was pulling 6 HIGH-severity CVEs through this
transitive chain:
@claude-flow/security → bcrypt@5.1.1 → @mapbox/node-pre-gyp@1.0.11
→ tar@<=7.5.10 (vulnerable)
CVEs (all tar <=7.5.10):
- GHSA-34x7-hfp2-rc4v Hardlink path traversal → arbitrary file create
- GHSA-8qq5-rm4j-mr97 Symlink poisoning → arbitrary file overwrite
- GHSA-83g3-92jg-28cx Hardlink target escape → arbitrary read/write
- GHSA-qffp-2rhf-9h96 Drive-relative hardlink path traversal
- GHSA-9ppj-qmqm-q256 Drive-relative symlink path traversal
- GHSA-r6q2-hw4h-h46w Race condition in node-tar path reservations
Downstream consumers of `@claude-flow/security` were forced to add a
`tar` `overrides` block to their own `package.json` to clear
`npm audit`. The umbrella `claude-flow` package already does this, but
direct consumers of `@claude-flow/security` (or anything that depends
on it transitively) couldn't rely on that.
Switch from `bcrypt` (native, requires @mapbox/node-pre-gyp build chain)
to `bcryptjs@^3.0.3` (pure JS, zero native deps, zero tar dependency):
- Same hash format (`$2a$`, `$2b$`, `$2y$`) — existing hashes verify
unchanged.
- Same API surface for the calls this module makes (`bcrypt.hash`,
`bcrypt.compare`); the `import * as bcrypt from 'bcryptjs'` form
keeps the rest of the module's call sites byte-identical.
- Drops the `@types/bcrypt` devDep — bcryptjs ships its own types.
Bumps `@claude-flow/security` 3.0.0-alpha.6 → 3.0.0-alpha.7. Republish
required for downstream consumers to pick up the fix; the source change
itself doesn't move until that publish lands.
Closes#1608.
Co-Authored-By: RuFlo <ruv@ruv.net>
* chore(lockfile): regenerate v3/pnpm-lock.yaml for bcryptjs swap
Companion to the bcrypt → bcryptjs swap in
@claude-flow/security/package.json. CI runs with `--frozen-lockfile`
so the manifest change couldn't land without a matching lockfile.
Most of the diff is incidental patch-version drift of
@opentelemetry/api 1.9.0 → 1.9.1 across vitest dev-deps; the
load-bearing change is the @claude-flow/security entry switching
from `bcrypt` to `bcryptjs` and dropping `@types/bcrypt`.
Co-Authored-By: RuFlo <ruv@ruv.net>
1. SQL injection: Convert all 9 string-interpolated queries in
memory-initializer.ts to parameterized queries (db.prepare/bind)
Closes#1030
2. Preinstall hook: Remove no-op preinstall script and package.json entry
that triggered supply chain concern
3. SECURITY.md: Add vulnerability disclosure policy with supported
versions, reporting process, and safe harbor statement
4. SafeExecutor: Remove npx from default command allowlist to prevent
arbitrary package execution via safe executor
5. Cleanup command: Add `cleanup` command for removing project artifacts
(.claude/, .swarm/, data/, etc.) with --dry-run default and --force
to execute. Addresses uninstall documentation gap
Published as v3.5.40. All fixes verified in Docker.
Closes#1375
Automatic checkpoint created by Claude Code
- Branch: v3
- Timestamp: 2026-01-07T19:04:42Z
- Changes: 19 file(s)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Updated standard-checkpoint-hooks.sh to accept both JSON and plain paths
- Fixed pre-edit and post-edit functions to detect input format
- Fixed v3 CLI hook flags (-f -> --file, -c -> --command, etc.)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>