Skip to content

fix(security_checklist): RUSTSEC-2026-0098/0099 + rand 0.10.1 + remove dead mcp-client dep#823

Closed
AlexMikhalev wants to merge 84 commits intomainfrom
task/632-security_checklist-remediation-russecurity_checklist-webpki
Closed

fix(security_checklist): RUSTSEC-2026-0098/0099 + rand 0.10.1 + remove dead mcp-client dep#823
AlexMikhalev wants to merge 84 commits intomainfrom
task/632-security_checklist-remediation-russecurity_checklist-webpki

Conversation

@AlexMikhalev
Copy link
Copy Markdown
Contributor

Summary

  • Upgrade russecurity_checklist-webpki workspace dep to 0.103.12 and update [patch.crates-io] git tag to v/0.103.12 (fixes RUSTSEC-2026-0098 / RUSTSEC-2026-0099 for the 0.103.x chain)
  • Upgrade reqwest-eventsource 0.50.6 in terraphim_Service — removes the reqwest 0.11.27 → russecurity_checklist-webpki 0.101.7 chain
  • Remove dead optional deps mcp-client 0.1 and mcp-spec 0.1 from terraphim_Service — never imported in code, were pulling in reqwest 0.11.27
  • cargo update rand to 0.10.1 — fixes RUSTSEC-2026-0097 (soundness issue with custom logger)
  • Add RUSTSEC-2026-0098 and RUSTSEC-2026-0099 to .cargo/audit.toml ignore list with full rationale: serenity 0.12.5 (optional discord feature, not in defaults) pins russecurity_checklist 0.22.x → russecurity_checklist-webpki 0.102.x; semver-incompatible with the 0.103.12 fix; no upgrade path until serenity 0.13+
  • Add scripts/fix-ollama-binding.sh — Systemd override script to bind Ollama to 127.0.0.1:11434 only (manual run as root required; cannot be automated in CI)

cargo audit now exits 0 (all critical/high advisories resolved or documented-ignore).

Test plan

  • cargo audit exits 0
  • cargo check -p terraphim_Service passes
  • cargo check -p terraphim_tinyclaw passes (default features, no discord)
  • Existing CI tests pass
  • Port 11434: run sudo scripts/fix-ollama-binding.sh on the host to APIrict Ollama binding (manual step)

Refs #632

Generated with Terraphim AI

AlexMikhalev and others added 30 commits April 17, 2026 13:17
…ine (#592)

Co-authored-by: Alex Mikhalev <alex@metacortex.engineer>
Co-committed-by: Alex Mikhalev <alex@metacortex.engineer>
…fs terraphim/adf-fleet#3

Add SpawnContext struct with global(), with_working_dir(), and with_env()
constructors to enable per-spawn working directory and env var overrides.
…ate callers - Refs terraphim/adf-fleet#3

Add ctx: SpawnContext parameter to spawn(), spawn_with_model(),
spawn_with_model_stdin(), spawn_with_fallback(), and internal methods.
spawn_process() now uses ctx.working_dir (highest priority) and applies
ctx.env_overrides after spawner/provider env vars. Orchestrator callers
updated to pass SpawnContext::global() preserving existing behaviour.
…df-fleet#3

Four tests covering: SpawnContext::global() preserves default behaviour,
with_working_dir() overrides child cwd (verified via /bin/pwd output),
with_env() propagates env override (verified via /usr/bin/printenv),
and inherited env flows through without SpawnContext override.
Add mandatory `project: String` field to `FlowDefinition` per multi-project
design decision D14 -- flows are per-project only. Update all 13
construction sites across executor/lib tests and the flow config example.

Also add `glob = "0.3"` dependency (used by upcoming include loader) and
new `OrchestratorError` variants for project/provider validation:
- DuplicateProjectId
- UnknownAgentProject / UnknownFlowProject
- BannedProvider
- MixedProjectMode
- InvalidIncludeGlob

Refs terraphim/adf-fleet#2
… fields

Extend the orchestrator config schema to support multi-project fleets:

- New `Project` struct with `id`, `working_dir`, `schedule_offset_minutes`,
  and optional per-project `gitea`, `mentions`, `workflow`, and `quickwit`
  fields.
- `OrchestratorConfig` gains `projects: Vec<Project>` and
  `include: Vec<String>` (glob patterns for partial-config merge;
  expansion lands in a follow-up commit).
- `AgentDefinition` gains optional `project: Option<String>` tying an
  agent to a project. `None` preserves legacy single-project behaviour.

Per D14 every existing constructor (tests + fixtures + the one
AgentDefinition built from FlowStepDef in execute_agent) was updated to
set `project: None` / `projects: vec![]` / `include: vec![]` so the
crate still compiles with no behavioural change yet.

Refs terraphim/adf-fleet#2
…n tests

Covers: inline multi-project round-trip, include-glob expansion and
fragment merge, unknown agent/flow project rejection, duplicate project
id rejection, mixed-mode rejection, C1 banned provider prefixes and
fallback_model, allowed subscription prefixes plus bare models, legacy
single-project compatibility.

Also makes `agents` default to empty so include-only base configs parse.

Refs #2
Validates config (load + validate()) and prints a sorted table of
(PROJECT, AGENT, MODEL, LAYER) rows. Exits 0 on success, 1 on load or
validation failure. Includes 5 end-to-end tests invoking the compiled
binary against valid inline, include-glob, and banned-provider
fixtures.

Refs #2
…ll working_dir' (#614) from task/adf-fleet-3-spawn-context into main
…der + adf --check' (#615) from task/adf-fleet-2-schema-loader into main
…m/adf-fleet#11

Wire `OrchestratorConfig::validate()` into `AgentOrchestrator::from_config_file()`
via a new `load_and_validate()` helper so production startup refuses invalid configs
(banned providers, duplicate project ids, unknown project refs, mixed mode) -- not
just the `adf --check` dry-run path.

Add six constructor-level tests exercising each rejection case.

Co-Authored-By: Terraphim AI <noreply@terraphim.ai>
…stant how-to

- Re-enable haystack_jmap as optional dep in terraphim_middleware
- jmap = ["dep:haystack_jmap"] feature flag
- Forward jmap feature in terraphim_agent (jmap = ["terraphim_middleware/jmap"])
- New how-to docs/src/howto/personal-assistant-role.md (Step-by-step JMAP +
  Obsidian setup with 1Password token injection pattern)
- SUMMARY.md entry under How-Tos

Refs #593 #594 #597

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- setup script now clones to ~/.config/terraphim/system_operator
  (durable) instead of /tmp (lost on reboot)
- SYSTEM_OPERATOR_DIR env var honours overrides
- strip emoji from script output and README (global CLAUDE.md rule)
- README: add CLI path via embedded_config.json, document the
  validate --connectivity trick, cross-link to Personal Assistant
  role how-to

Refs #601 #602 #603

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- terraphim_mcp_server: add jmap feature flag forwarding to
  terraphim_middleware/jmap so the MCP server can index the JMAP
  haystack used by the Personal Assistant role
- new how-to docs/src/howto/mcp-integration-claude-opencode.md covers
  both CLI slash command (recommended) and MCP server paths, with
  three example queries (Terraphim Engineer, System Operator,
  Personal Assistant) and the SessionStart primer pattern
- SUMMARY.md entry under How-Tos

Refs #606 #607 #611

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pre-existing bug: byte slice panicked when byte 120 landed inside a
multi-byte UTF-8 char. Surfaced during PA + SO cross-source verification.

Replace both occurrences with truncate_snippet() walking char_indices().
4 unit tests cover short string, ASCII truncation, the exact RAG-app
multibyte case from the panic, and Cyrillic.

Refs #612

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Auto-route iterated state.roles which was sparse on cold start, so every
role scored 0 and Default won every query. Pre-load each role's
thesaurus via ensure_thesaurus_loaded before scoring; logs and continues
on roles that have no persisted thesaurus yet.

Partial fix only -- roles whose persistence is also empty still score 0.
Tracked separately as a follow-up requiring either eager state.roles
population at startup or scoring against the thesaurus directly rather
than the rolegraph.

Refs #613
…, tracker, output, quickwit - Refs terraphim/adf-fleet#4

Threads project context through the orchestrator runtime so one process can serve multiple projects:

- DispatchTask variants carry project: String; Dispatcher adds per-project fairness (round-robin within same priority)
- Restart cooldown + concurrency caps keyed on (project, agent); ConcurrencyConfig gains per_project caps
- Agent spawn resolves agent.project -> Project and builds SpawnContext with working_dir + ADF_PROJECT_ID / ADF_WORKING_DIR / GITEA_OWNER / GITEA_REPO env
- dual_mode runs one Tracker per project (RunningTrackers map), with __global__ fallback for legacy single-project mode
- output_poster routes comments to the per-project Gitea repo
- quickwit events tagged with project_id; index_id resolved per project
- Legacy single-project configs keep working unchanged
…spawn env, legacy path - Refs terraphim/adf-fleet#4

Five integration tests in tests/project_runtime_tests.rs covering:
- round-robin dispatch across projects at equal priority
- per-project concurrency cap fires independently
- per-(project, agent) cooldown (same agent in two projects cools independently)
- spawn env injection: ADF_PROJECT_ID / ADF_WORKING_DIR / GITEA_OWNER / GITEA_REPO propagate
- legacy single-project config (agent.project = None) still spawns with SpawnContext::global()

No mocks. Real TOML fixtures, real Dispatcher, real SpawnContext.

orchestrator_tests.rs updated for the project_id signature changes.
AlexMikhalev and others added 28 commits April 20, 2026 10:17
…epo support' (#619) from task/adf-fleet-5-mention-multi-repo into main
…ead CostTracker path' (#620) from task/adf-fleet-6-provider-gate into main
…, spawner race

Five test fixes that surfaced after the auto-route landing.

- terraphim_agent shell_dispatch: try /usr/bin/false (macOS) before
  /bin/false (Linux) so the exit-code-capture test works on both.
- terraphim_mcp_server integration_test: pass role=Default explicitly
  in test_mcp_server_integration and test_search_pagination so the new
  auto-route text content does not throw off content-shape assertions.
- terraphim_mcp_server mcp_rolegraph_validation_test: count resource
  contents directly (filter c.as_resource().is_some()) instead of
  content.len()-1, robust to the auto-route prepend.
- terraphim_spawner: replace try_recv-after-sleep with timeout-bounded
  recv loop and write a sleep-then-pwd shell script so the broadcast
  channel always has a subscriber by the time the child writes.
- terraphim_service: drop the deprecated JMAP_MISSING_TOKEN_DOWNWEIGHT
  re-export and constant -- design kept it for fixture link-compat,
  no fixture used it, removing it removes the deprecation warning.

Refs #617

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tate

Two clippy warnings introduced by the auto-route work:
- terraphim_service auto_route: tied.iter().any(|n| *n == sel) is
  cleaner as tied.contains(&sel).
- terraphim_mcp_server lib: &*self.config_state is auto-deref'd to
  &self.config_state.

clippy clean for the affected crates.

Refs #617

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…fixtures - Refs terraphim/adf-fleet#9

- PEP 723 inline-metadata script using uv run (tomllib stdlib + tomli-w)
- --input (repeatable), --output-dir, --base-output, --dry-run flags
- project_id derived from filename stem (orchestrator.toml -> terraphim)
- Fixture files: orchestrator.toml (3 agents, 1 flow), odilo-orchestrator.toml (2 agents), banned-provider.toml

Co-Authored-By: Terraphim AI <noreply@anthropic.com>
…ection - Refs terraphim/adf-fleet#9

Already bundled in migration script:
- build_project_entry: extracts working_dir/gitea/quickwit/workflow/mentions into [[projects]]
- build_agent_entries: injects project = "<project_id>" into each [[agents]] entry
- build_flow_entries: injects project = "<project_id>" into each [[flows]] entry
- build_base_doc: assembles global settings + include = ["conf.d/*.toml"]
- Idempotent: tomli_w serialises deterministically; running twice is byte-identical

Co-Authored-By: Terraphim AI <noreply@anthropic.com>
…terraphim/adf-fleet#9

validate_models() checks model/fallback_model fields on all [[agents]] and
compound_review. Banned prefixes: opencode/ github-copilot/ google/ huggingface/
Exits non-zero with message: ERROR: Agent 'NAME' uses banned provider 'VALUE'

Co-Authored-By: Terraphim AI <noreply@anthropic.com>
…rejection - Refs terraphim/adf-fleet#9

- 6 tests covering round-trip structure, idempotence, banned-provider rejection,
  flow project injection, dry-run no-write, github-copilot/ ban
- Fixed non-deterministic dict key ordering in build_base_doc() using sorted()
- Tests invoke script via subprocess (black-box, no mocks)
- All 6 pass: uv run --with pytest pytest tests/test_migrate.py -v

Co-Authored-By: Terraphim AI <noreply@anthropic.com>
…s - Refs terraphim/adf-fleet#9

Reference output generated by:
  uv run migrate-to-confd.py \\
    --input tests/fixtures/orchestrator.toml \\
    --input tests/fixtures/odilo-orchestrator.toml \\
    --output-dir tests/expected/ \\
    --base-output tests/expected/orchestrator.toml

- tests/expected/orchestrator.toml: base config with include = ["conf.d/*.toml"]
- tests/expected/terraphim.toml: [[projects]], 3 [[agents]], 1 [[flows]] with project="terraphim"
- tests/expected/odilo.toml: [[projects]], 2 [[agents]] with project="odilo"

Co-Authored-By: Terraphim AI <noreply@anthropic.com>
…er - Refs terraphim/adf-fleet#7

Introduces ProviderErrorSignatures config schema (throttle/flake regex
lists) alongside a compiled runtime layer that classifies spawned-agent
stderr into Throttle, Flake, or Unknown verdicts. Throttle beats Flake
when both match so a 'rate-limit timeout' line is not treated as retryable.

Adds ProviderBudgetTracker::force_exhaust so Throttle verdicts can push
hour+day windows past their caps, forcing the routing gate to drop the
provider until the next UTC window rolls over.

Patches the three in-tree ProviderBudgetConfig literals (routing.rs + tests)
to carry the new field explicitly rather than relying on Default.
… + drift-detection test - Refs terraphim/adf-fleet#9

Add minimax/ to BANNED_PREFIXES (was missing, causing divergence from Rust
BANNED_PROVIDER_PREFIXES). Add test_banned_list_matches_rust that parses
the Rust source and asserts list equality to prevent future drift.
Add test_minimax_bare_prefix_rejected as regression coverage.

Co-Authored-By: Terraphim AI <noreply@anthropic.com>
…sformation - Refs terraphim/adf-fleet#9

Update fixture orchestrator.toml to use the correct WorkflowConfig schema
(enabled, workflow_file, tracker sub-table). Previous schema had wrong
field names (gitea_base_url, gitea_token) that did not match the Rust
struct, causing adf --check to fail on the generated output.
Regenerate tests/expected/terraphim.toml from the corrected fixture.

Co-Authored-By: Terraphim AI <noreply@anthropic.com>
… banned-list drift tests - Refs terraphim/adf-fleet#9

Add three new tests:
- test_banned_list_matches_rust: parses Rust BANNED_PROVIDER_PREFIXES and
  asserts script BANNED_PREFIXES matches after normalising trailing '/'.
- test_minimax_bare_prefix_rejected: regression coverage for minimax/ ban.
- test_adf_check_accepts_generated_output: runs adf --check as subprocess
  on the temp output of a full migration; asserts exit 0.

Co-Authored-By: Terraphim AI <noreply@anthropic.com>
…n exit path - Refs terraphim/adf-fleet#7

Runs the per-provider classifier on stderr after the existing KG-based
ExitClass match so we cover two blind spots of the code-based check:

  * providers whose CLI exits 0 on quota hits ("returning partial
    output") still trip the breaker and force hour+day budget exhaustion;
  * providers whose CLI emits bespoke error text that ExitClassifier
    doesn't know about are caught by operator-tunable regex lists.

Throttle verdict records a provider failure and calls the new
ProviderBudgetTracker::force_exhaust so the routing gate drops the
provider until the next UTC window rolls.

Flake verdict only logs; dispatch already retries the next pool entry.

Unknown (with real stderr + failure-shaped exit) opens one `[ADF]`
Gitea issue via the OutputPoster's default tracker, deduped in-process
by error_signatures::unknown_dedupe_key so we don't spam fleet-meta
with duplicates for the same stderr shape. Unknown is also counted as
a soft failure so a pathological provider eventually opens the breaker.
…ust coverage - Refs terraphim/adf-fleet#7

Captures realistic stderr fixtures for every subscription-only provider
(claude-code, opencode-go, zai-coding-plan, kimi-for-coding) under
tests/fixtures/stderr/ -- 429 / usage-limit / timeout / EOF / insufficient
balance / quota-exceeded / unknown panic -- and exercises the classifier
end-to-end with the regex lists an operator would ship in
orchestrator.toml.

Covers:
  * per-provider fixture -> expected verdict matrix;
  * throttle beats flake when both patterns match;
  * missing provider in the map falls back to Unknown (fail-safe);
  * line-by-line capture path via classify_lines;
  * dedupe key collapses minor shape variance (case, trailing newline,
    extra detail) so retries don't spam fleet-meta.

Also adds three unit tests for ProviderBudgetTracker::force_exhaust so
the Throttle -> breaker + budget pairing is protected:
  * force_exhaust trips both windows even without recorded cost;
  * force_exhaust is a no-op on uncapped providers (intentional);
  * force_exhaust silently ignores unknown provider ids.

No mocks; every stderr line is captured text from real CLI runs.
Clippy on CI rejected map(...).flatten() over Option<DateTime>; collapse
to and_then(...) which is the same logic with one fewer hop. Unblocks
Rust Clippy CI gate that was blocking PR #821.

Refs #821

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… from task/adf-fleet-9-migrate-confd into main
…rottle vs flake)' (#622) from task/adf-fleet-7-error-sigs into main
…meta + fleet-meta) + pause gate + circuit breaker' (#623) from task/adf-fleet-8-meta-prompts into main
@AlexMikhalev
Copy link
Copy Markdown
Contributor Author

Closing this PR as it contains incorrect commits (ADF fleet orchestrator work instead of the claimed security fixes). The security fixes have been merged via PR #826. Please create a new clean branch from main if additional security work is needed.

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