Commit Graph
1588 Commits
Author SHA1 Message Date
ruv 2a5fb089e7 Merge PR #3885 (shared resilience batch) into release/3.55.0 2026-10-07 13:04:16 -04:00
rUv 7d971363a3 Merge pull request #3886 from ruvnet/fix/policy-ledger-anchor-3602
fix(policy): ledger anchor can no longer be deleted and silently re-established (#3602)
2026-10-07 10:01:32 -07:00
rUv 7decc3e5ab Merge pull request #3339 from ruvnet/dream/2026-09-16-security
fix(security): gate hive-mind remote callers without breaking local users (ADR-476, #3338)
2026-10-07 09:42:42 -07:00
rUv aed8939789 Merge pull request #3600 from rudycelekli/fix/config-default-isolation-20261001
fix(config): isolate nested default values
2026-10-07 09:41:16 -07:00
rUv 42ce158f0d Merge pull request #3599 from ruvnet/dream/2026-10-01-security
fix(mcp): refuse unauthenticated HTTP on non-loopback hosts; optional bearer-token auth
2026-10-07 09:39:31 -07:00
ruv 798044828d Merge origin/main into fix/config-default-isolation (reset(): project selection + defaults clone)
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 11:38:42 -04:00
rUv 63216b7294 Merge pull request #3654 from rudycelekli/fix/hive-consensus-cli-errors-3609-20261003
fix(cli): fail rejected hive consensus operations
2026-10-07 08:37:30 -07:00
rUv 208cb513ba Merge pull request #3875 from ruvnet/triage/2026-10-07-issue-3547
fix(daemon): apply --workers selection to WorkerDaemon (#3547)
2026-10-07 08:37:24 -07:00
rUv d2fc99ce8c Merge pull request #3591 from rudycelekli/fix/config-project-cache-20261001
fix(config): isolate cached configuration by project directory
2026-10-07 08:37:17 -07:00
ruv 8f4b47af16 fix(security): migration-safe hive-mind gating by caller transport (ADR-476, #3338)
Gate hive-mind init/join/leave/spawn/propose/vote/broadcast/shutdown/
memory set+delete/optimize-memory for remote (HTTP/WebSocket) callers only;
local stdio, ruflo mcp exec, the CLI and in-process callers keep working
with no extra step. hive-mind_init never returns hiveToken. Operator secret
from RUFLO_HIVE_BOOTSTRAP_SECRET or a 0600 bootstrap.secret created by the
first local init. state.json is written 0600 atomically (dir 0700).
Constant-time compare. RUFLO_HIVE_REQUIRE_AUTH=1 for bridged stdio.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 10:18:44 -04:00
ruv 8446702423 fix(policy): ledger anchor can no longer be deleted and silently re-established (#3602)
verify never re-anchors receipts that have no anchor (anchor-missing); appending refuses too.
Adds a hash-chained second anchor log in the project dir plus a mirror of its newest entry under
~/.config/ruflo/policy-trust, an explicit interactive --establish-anchor repair that is logged,
and migration of older state.json anchors. Threat model in ADR-475.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 10:16:05 -04:00
ruv f54359456e fix(mcp): refuse unauthenticated HTTP on non-loopback hosts; optional bearer-token auth
- startHttpServer refuses a non-loopback --host unless RUFLO_MCP_HTTP_TOKEN /
  --auth-token-file / --auth-token is set, or RUFLO_MCP_ALLOW_UNAUTHENTICATED_HTTP=1.
  The gate now runs before any import or bind.
- New optional bearer-token auth wired into the HTTP transport: constant-time
  compare, bare 401, no token logging, applied before the body parser; only
  GET/HEAD /health stays public and reveals liveness only. Auth enabled with no
  tokens now fails closed (previously any Bearer value was accepted).
- Wiring tests through MCPServerManager.start() (mutation-checked) and transport
  tests covering bypass attempts; README + mcp start help document the env vars.

Loopback without a token stays unauthenticated by design (documented).

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 10:13:37 -04:00
rUv bf09d97765 Merge branch 'main' into fix/hive-consensus-cli-errors-3609-20261003 2026-10-07 07:03:41 -07:00
rUv 07f73dafd6 Merge branch 'main' into triage/2026-10-07-issue-3547 2026-10-07 07:03:38 -07:00
rUv 7bfa2c71c8 Merge branch 'main' into fix/config-default-isolation-20261001 2026-10-07 07:03:35 -07:00
rUv c50f1dec72 Merge branch 'main' into fix/config-project-cache-20261001 2026-10-07 07:03:32 -07:00
rUv 3a80ed0128 Merge branch 'main' into fix/parser-string-options-20261001 2026-10-07 07:03:28 -07:00
Rudy Celekli de30d7ca74 fix(workers): honor already-aborted bounded pool input
Fixes #3592.

Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-07 10:03:25 -04:00
Rudy Celekli ea6a7d21f1 fix(queue): skip cancelled heads before selecting work
Fixes #3593.

Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-07 10:03:14 -04:00
Rudy Celekli fe5ad5cce1 fix(cli): preserve settled worker task outcomes
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-07 10:03:14 -04:00
Rudy Celekli b335bc65e3 fix(cli): normalize non-Error retry rejections
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-07 10:03:14 -04:00
ruv f6fda0e569 Merge origin/main into dream/2026-09-16-security (drop LEDGER.md hunk)
Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 10:02:03 -04:00
ruv fd3f2de30b Merge remote-tracking branch 'origin/main' into fix/mcp-http-auth 2026-10-07 10:01:12 -04:00
rUv 32c1d58033 Merge pull request #3870 from ruvnet/fix/pkg-3865-3863-3859-3856
fix: EventStore missing snapshot null, git identity whitespace paths, Porter step 4, rate limiter stats labels
2026-10-06 23:54:30 -07:00
rUv 610a2e1475 Merge pull request #3877 from ruvnet/feat/console-0.36
feat(console): 0.36.0 — Events and Timeline pages: history, sources, severity, query language, lanes, overlays
2026-10-06 23:44:14 -07:00
ruv 1ac200432c feat(console): 0.36.0 integration: eventsPersist option, shared whole-batch append argv, hostile-time hardening, init ignores console/
- plugin.json declares eventsPersist (default true); version 0.36.0 in plugin.json, version.ts, smoke.sh
- data/append-argv.ts: one dd argv (bs=1M iflag=fullblock) shared by the Events store and the autopilot journal; real-dd 8-writer test fails on the old argv
- history decoders and Events/Timeline displays use #3874's timeOf/countOf/isoOf, so a hostile time or count cannot throw
- cli init: .claude-flow/.gitignore template lists console/
- ADR-474 updated to the reviewed behaviour and the open low items

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 02:19:20 -04:00
rUv 7ee853ee34 Merge branch 'main' into fix/mods-3791-3805 2026-10-06 23:02:04 -07:00
rUv e6fb24b783 Merge branch 'main' into fix/pkg-3865-3863-3859-3856 2026-10-06 23:02:01 -07:00
ClaudeandRuFlo 7907e34e9e fix(daemon): apply --workers selection to WorkerDaemon (#3547)
`daemon start --workers <list>` was forwarded to the forked background
child's argv (#1968/#1970) but never read into DaemonConfig, so
WorkerDaemon always fell back to DEFAULT_WORKERS (7 enabled) in both
foreground and background mode. Read --workers into a new
DaemonConfig.enabledWorkers, and apply it in initializeWorkerStates()
after the daemon-state.json restore so a stale saved state can't
re-enable a deselected worker.

Scoped to the --workers selection bug only; the related --sandbox
forwarded-but-unused gap and the daemon status TTL display bug noted
in the same issue are left for a separate follow-up.

Opened by the nightly triage routine — human review required before
merge.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01JSiFBZnyyG3nzyT3BuHq76
2026-10-07 05:21:17 +00:00
ruv ec905cba47 Merge origin/main into fix/pkg-3855-3853-3844-3841
The statusline collision test was made hermetic by both #3842 and this PR; keep this
branch's version (it also mocks child_process and asserts nothing shells out).

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 01:06:07 -04:00
rUv d4dc8054a0 Merge pull request #3871 from ruvnet/fix/agentdb-3691-3693
fix(memory): honest pattern-store failures; share AgentDB's SQLite copy in graph writer
2026-10-06 21:58:47 -07:00
rUv ca80c7336b Merge pull request #3869 from ruvnet/fix/cli-3851-3845-3840
fix(cli): flush piped stdout before process.exit (#3851)
2026-10-06 21:58:44 -07:00
ruv 6258d60127 fix(guard): decode $'...' escapes as bash does; adversarial and benign tables for the root-delete guard (#3791)
$'\x2f' and $'\x72m' name the root and rm without any expansion, and a
\' inside $'...' does not close the string. The scanner now decodes ANSI-C
escapes (octal, \x, \u/\U, \c, the single-letter set, NUL ends the string)
in all four copies, and the parity table gains wrapper, flag-spelling,
benign look-alike and documented-limit rows.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 2ce9cc7c4c fix(mods doctor): warn on legacy CLI hooks route|post-edit settings instead of claiming the mod owns them (#3803)
Adversarial review: with the mod now standing down for the CLI's own hooks
command, `ruflo mods doctor` still said "no hook-handler.cjs: the mod owns
route and post-edit outright" in such a project. A new `legacy CLI hooks`
finding (warn, fix: `ruflo init upgrade --settings`) names the events the
mod leaves to that command, and the handshake line no longer claims them.
The pattern mirrors legacyCliConfigured in the plugin (the CLI package
cannot import plugin source).

(cherry picked from commit d7ac91f595)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 5ae95050c7 fix(guard): a quoted empty substitution leaves the word as bash does; # after it stays in the word (#3791)
Real-bash oracle (bwrap, read-only root, logging fake rm; positive controls
detected) over a 63,696-command differential between main and this branch:
- a substitution inside double quotes is now dropped from the word, as its
  empty output is, so "`true`"-rf reads as -rf; a placeholder is kept only
  when a # follows, so bash -c "`true`#x; rm -rf /" is still read as one
  word and caught;
- 1,260 commands main denies and this branch allows: 0 really delete
  (bash parses each differently than main assumed);
- of 1,500 sampled commands this branch allows with a root operand, the
  201 that really delete are all $(...) substitutions (stated follow-up, 189)
  or $- expansions inside sh -c (12); main misses every one too.
Three parity rows added (309 pass). All four copies alike; the generator's
String.raw source keeps no backtick in comments.

(cherry picked from commit 4f2ac8ba28)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 94238f06ef fix(guard): a substitution starts its word, and an unterminated backtick is text (#3791)
Third review (by reading; its oracle run was cut short): the unquoted
backtick branch did not mark the word as started, so a # right after an
empty substitution was read as a comment and the rest of the line skipped,
`true`#x; rm -rf / among it; bash keeps # inside the word. main denied this
(the backtick was a word character there). Confirmed: the new parity row
fails on the previous head and passes now.

An unterminated backtick (quoted or not) is now literal text, as main read
it, instead of a substitution that swallows the rest of the input. Five rows
added (306 pass); all four copies alike.

(cherry picked from commit 6f515a37a2)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov b880b825ff fix(guard): unescape a substitution body as bash does, scan backticks inside double quotes, rescan any word with a separator (#3791)
Second review, against a real-bash oracle (sandboxed, logging fake rm) over
12k generated commands:
- the backtick body dropped every backslash; bash removes one only before
  $, a backtick or a backslash (and " inside double quotes) and drops
  backslash-newline, so escaped operands and line continuations inside a
  substitution slipped through;
- a backtick inside "..." was kept as text, not scanned, so an empty
  substitution inside a quoted operand hid the delete;
- a word was rescanned only if it contained "rm", so a nested shell whose
  rm was split by a substitution or a backslash was never read.

One substitution helper now serves both contexts, and any word with a
separator or a backtick is rescanned (still bounded at four levels). All
four copies alike. The reviewer's oracle: misses 632 -> 26 (24 are the $(...)
follow-up, 2 real expansions), 0 regressions vs main. Five deny rows and one
allow row added to the parity table (301 pass; on the previous head exactly
the five new deny rows fail).

(cherry picked from commit feb0df1e73)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 54d49ea898 fix(guard): scan a backtick substitution as a nested command instead of ending the rm being parsed (#3791)
Adversarial review: making the backtick a command separator reset the rm
state, so an empty substitution among rm's operands hid the delete. Four
commands main denied were allowed (rm -rf `true` /, rm `` -rf /,
rm -rf /tmp/x `:` /, rm -r `:` -f /); the shell drops the empty word, so
each runs as a root delete.

The backtick is no longer a separator. Its body is scanned as its own
command (bounded at four levels, as other rescans), and the enclosing word
and rm state are left alone. All four copies changed alike; the parity
table gains those four rows plus two safe look-alikes (295 pass; on the
previous head exactly the four new deny rows fail).

(cherry picked from commit d4b0b739c3)
2026-10-07 00:58:38 -04:00
Dragan Spiridonov 574e5dd6da fix(guard): root-delete scanner catches backticks, $'…' quoting and abbreviated long options (#3791)
The #3698 scanner kept `$` in front of a quote, did not separate on a
backtick, and accepted only the exact `--recursive`/`--force`. So
``echo `rm -rf /` ``, `$'rm' -rf /`, `bash -c $'rm -rf /'` and
`rm --r --f /*` passed the mod and both classic pre-bash helpers. GNU rm
runs each of them as a root delete.

- A backtick separates words and ends a command, as `(` and `)` already do,
  and a quoted word that contains one is rescanned.
- A `$` immediately before `'` or `"` is ANSI-C/locale quoting, not part of the word.
- Any unambiguous `--` prefix of --recursive / --force counts as that flag,
  as getopt_long does.

The same change is applied to all four copies: the mod, the generator
fallback and both shipped hook-handler.cjs. Fifteen cases are added to the
#3698 parity table (10 deny, 5 safe look-alikes).

(cherry picked from commit ad44701617)
2026-10-07 00:58:38 -04:00
ruv 2c5e114ef3 Merge origin/main into fix/session-yaml-export-values-20261006
Resolves the import-line conflict with #3848 (keeps both the yaml and zlib imports).

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 00:42:19 -04:00
rUv 98b4bce25d Merge pull request #3848 from rudycelekli/fix/session-compressed-backup-roundtrip-20261006
fix(session): round-trip compressed JSON backups
2026-10-06 21:40:57 -07:00
ruv 09c2f400b1 fix: honour retry/retention/shutdown timer contracts; hermetic statusline format test
- #3853 withRetry: clamp the final jittered delay to maxDelayMs
- #3855 MonitoringHooks: apply retentionMs on getMetrics/getMetricsSummary reads
- #3841 WorkerQueue: track retry timers and clear them on shutdown
- #3844 statusline collision tests: static import + registered data sources, no live gh/ps/git

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 00:35:36 -04:00
ruv 67261ac049 fix(memory): honest agentdb_pattern-store failures; share AgentDB's better-sqlite3 for graph writer (#3691, #3693)
- bridgeStorePattern no longer turns a bridgeStoreEntry {success:false} into a success receipt
- agentdb_pattern-store checks storeEntry's result in the registry-null fallback and refuses failed writes
- hooks pattern-store falls back to the direct store when the bridge write was refused
- graph writer, native recovery/repair and attestation open SQLite via the better-sqlite3 copy AgentDB resolves, so the idle close cannot strip a live AgentDB handle's WAL/SHM sidecars

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 00:28:39 -04:00
ruv ce1fcbca66 fix: EventStore missing snapshot, git identity whitespace paths, Porter step 4, rate limiter stats labels
- shared: EventStore.getSnapshot returns null when no row matches (sql.js getAsObject yields undefined-valued keys) (#3865)
- cli: git-workspace-identity keeps trailing whitespace in path records, strips only the final LF (#3863)
- cli: Porter step 4 selects the longest matching suffix once, no fall-through to a shorter one (#3859)
- cli: RateLimiter.getStats uses stored operation/user instead of splitting bucket keys (#3856)

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 00:26:43 -04:00
ruv 275ec2905d fix(cli): flush piped stdout before process.exit (#3851)
Switch piped stdout/stderr to blocking writes at CLI.run start so the
process.exit() calls after a command no longer truncate output at the
64 KiB pipe buffer.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-07 00:21:45 -04:00
ruv b68ab59e60 feat(cli): recall log in the intelligence hook and memory list --embeddings (ADR-472)
The hook appends one bounded, masked, fail-open record per surfaced recall to
.claude-flow/data/recall-log.jsonl (digest of the prompt, ids/scores/ranks,
router pick; default on, RUFLO_RECALL_LOG=0 or recallLog.enabled=false to stop).
memory list --format json --embeddings adds each stored vector as int8+scale.
Helper manifest is NOT re-signed here; the integrator signs at release.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-10-06 18:21:37 -04:00
Rudy Celekli bc6d654d22 fix(session): round-trip compressed JSON backups
Signed-off-by: Rudy Celekli <rudy@gradiahq.com>
2026-10-06 13:18:04 -04:00
Rudy Celekli d1bce896d6 fix(session): preserve saved values in YAML exports
Signed-off-by: Rudy Celekli <rudy@gradiahq.com>
2026-10-06 12:18:07 -04:00
rUv 090c88cf2a Merge pull request #3703 from ruvnet/fix/3698-plugin-beta-feedback
fix: address Ruflo mod and console beta feedback
2026-10-04 14:06:12 -07:00
rUv 1b62011183 fix(guidance): close source identity, offline export and serialization edge cases 2026-10-04 13:43:46 -07:00