Skip to content

M10: Mediated MCP, harness import, and container deploy path#15

Open
huronat wants to merge 11 commits into
mainfrom
harness-agent-integration
Open

M10: Mediated MCP, harness import, and container deploy path#15
huronat wants to merge 11 commits into
mainfrom
harness-agent-integration

Conversation

@huronat

@huronat huronat commented Jul 22, 2026

Copy link
Copy Markdown

Summary

  • Expose forensic synty_trace_* tools on MCP alongside the existing read surface, with role/tool policy (primary / investigator / validator / operator) and optional JSON read scopes (repos, campaigns, roles, sources).
  • Add authenticated Streamable HTTP MCP (--http, feature mcp-http, bearer token + loopback-by-default) so remote campaign agents can query without raw bucket credentials.
  • Add upload/MCP redaction profiles (off / standard / mcp_safe), synty import for harness/Devin NDJSON, campaign/role stamps, $CODEX_HOME / $CLAUDE_CONFIG_DIR roots, --no-autostart for supervisors, plus Dockerfile and Helm (tracker / builder / MCP).

Why

Campaign harness agents need a mediated memory/forensics path into synty: structured recall + execution traces, without giving every agent write/raw-bucket trust. This keeps synty as the telemetry/memory layer while a separate harness owns orchestration policy.

Test plan

  • cargo test --locked — 250 passed
  • cargo test --locked --features mcp-http — 250 passed
  • Manual: synty mcp --role investigator and call tools/list / synty_trace_list
  • Manual: synty mcp --http --token … hit /health and /mcp with Bearer auth
  • Manual: synty import --format harness dry-run on a sample NDJSON file
  • Manual: CODEX_HOME=/tmp/codex synty track --source codex --dry path resolution (sessions under override)
  • Manual: synty init … --no-autostart skips launchd/systemd install
  • Optional: build/push image from Dockerfile and helm template the chart with a bucket + MCP secret

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Added authenticated MCP over HTTP with TLS, strict origin/token validation, rate limiting, and scoped tool exposure.
    • Added import for Harness/Devin/envelope NDJSON with filtering, quarantine, deduplication, and dry-run.
    • Added campaign/role attribution to tracking, filtering, and trace exploration.
    • Expanded Helm chart support for MCP, builder/tracker scheduling, persistence, and network policy; publishes multi-arch container images.
  • Security

    • Enforced scoped, mediated access to MCP and traces, plus irreversible upload redaction and safer network controls.
  • Documentation

    • Updated README/design/release docs with new MCP, importing, privacy, and build/release guidance.

Expose forensic trace tools over MCP, add authenticated HTTP transport,
role/scope policy, and redaction for uploads and remote responses so campaign
agents can query synty without raw bucket access. Import harness/Devin NDJSON,
honor CODEX_HOME/CLAUDE_CONFIG_DIR, and ship Dockerfile plus Helm for
supervisor-driven track/mcp. Validation: 250 default and 250 mcp-http scenarios.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Changes

Core data and access

Layer / File(s) Summary
Metadata and foreign-event import
src/import.rs, src/config.rs, src/ingest.rs, src/units.rs, src/track.rs, src/main.rs
Adds Harness/Devin NDJSON import, deterministic event IDs, campaign and role attribution, metadata propagation, quarantine handling, and CLI wiring.
Scoped reads and MCP
src/policy.rs, src/redact.rs, src/trace.rs, src/mcp.rs, src/mcp_http.rs
Adds role/read-scope filtering, structured redaction, scoped trace APIs, new trace tools, and authenticated bounded HTTP MCP transport.
Upload, projections, and synchronization
src/sync.rs, src/index.rs, src/ingest.rs, src/readmodel.rs
Publishes analysis and trace projections, fingerprints them in read-model builds, applies irreversible upload policies, and pulls read models before raw events.
Bucket operations and atomic storage
src/bucket.rs, src/bucket/cloud.rs, src/main.rs
Adds batch bucket operations, partial-progress reporting, atomic temporary-file handling, and concurrent-writer coverage.

Deployment and release

Layer / File(s) Summary
Container and Helm runtime
Dockerfile, deploy/helm/synty/*, .dockerignore
Adds a feature-enabled non-root image and Helm resources for tracker, builder, MCP, persistence, service accounts, probes, services, and network policies.
Release and validation
.github/workflows/*, deploy/aws/*, scripts/mcp-http-smoke.sh, Cargo.toml, rust-toolchain.toml
Pins Rust 1.97, validates versions, tests MCP HTTP/TLS behavior, publishes multi-architecture ECR images, and provisions AWS publishing/read roles.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant MCP_HTTP
  participant Dispatcher
  participant MCP_Server
  Client->>MCP_HTTP: POST /mcp with bearer token and protocol headers
  MCP_HTTP->>MCP_HTTP: Validate origin, content type, rate, and body limits
  MCP_HTTP->>Dispatcher: Queue semantic or analysis request
  Dispatcher->>MCP_Server: Execute scoped MCP tool
  MCP_Server-->>Dispatcher: Redacted MCP response
  Dispatcher-->>MCP_HTTP: Response or timeout status
  MCP_HTTP-->>Client: JSON-RPC HTTP response
Loading

Possibly related PRs

  • superlinked/synty#4 — Extends the same trace APIs with scoped list, search, show, and compare behavior.
  • superlinked/synty#5 — Modifies the fleet synchronization and read-model pull flow.
  • superlinked/synty#13 — Adds related batch operations to the bucket API and cloud implementations.

Suggested reviewers: svonava

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main themes: mediated MCP, import support, and container deployment changes.
Docstring Coverage ✅ Passed Docstring coverage is 80.80% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch harness-agent-integration

Comment @coderabbitai help to get the list of available commands.

@huronat
huronat requested a review from svonava July 22, 2026 15:58

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
.dockerignore (1)

1-8: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Exclude local credentials from the Docker build context.

.env, .aws/, and private-key files can still be sent to a remote Docker builder. Add explicit exclusions for common secret locations and key formats.

Proposed fix
 .git
 target
 tmp
 corpus
 .synty
+.env
+.env.*
+.aws
+*.pem
+*.key
+*.p12
+*.pfx
 docs/*.gif
 evals/runs*
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.dockerignore around lines 1 - 8, Update the Docker ignore configuration to
exclude local credential sources by adding entries for .env files, the .aws/
directory, and private-key files such as *.pem and *.key. Preserve all existing
exclusions.
src/trace.rs (1)

1222-1267: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

resolve() leaks unscoped trace ids through ambiguity errors, bypassing ReadScope.

resolve() matches candidates across jobs/turns/spans/session_events/events with no knowledge of the caller's ReadScope. When a short prefix is ambiguous, it bail!s with up to 8 matching ids drawn from the entire store. show_text/compare_text (lines 980-1050) call resolve(..)? before resolved_allowed(..) runs, so this error propagates straight to the caller — including MCP clients bound to a restricted ReadScope (e.g. synty_trace_show/synty_trace_compare). A scoped client can therefore enumerate ids (and thus the existence of sessions/turns/jobs) outside its granted campaigns/roles/repos simply by probing short prefixes, which the exact-match path (single candidate, still scope-checked afterward via resolved_allowed) does not otherwise allow.

Thread scope into resolve() and filter candidates (reusing scope_allows) before building bases, so the ambiguity list — and the match count itself — never includes out-of-scope ids.

🔒 Proposed fix sketch
-fn resolve(store: &TraceStore, query: &str) -> Result<Resolved> {
+fn resolve(store: &TraceStore, query: &str, scope: Option<&crate::policy::ReadScope>) -> Result<Resolved> {
     if query.chars().count() < 4 {
         bail!("trace id prefixes must be at least 4 characters");
     }
     let mut bases: HashMap<String, Resolved> = HashMap::new();
     for (i, j) in store.jobs.iter().enumerate() {
-        if id_matches(&j.id, query) {
+        if id_matches(&j.id, query) && scope_allows(store, &j.session_id, &j.repo, &j.source, scope) {
             bases.insert(j.id.clone(), Resolved::Job(i));
         }
     }
     // ... same guard added for turns/spans/session_events/events

And update the two call sites (show_text, compare_text) to pass scope through to resolve.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/trace.rs` around lines 1222 - 1267, Update resolve to accept the caller’s
ReadScope and apply scope_allows to every job, turn, span, session event, and
event candidate before inserting it into bases, ensuring ambiguity counts and
listed IDs contain only permitted records. Update show_text and compare_text to
pass their scope into resolve while preserving the existing post-resolution
resolved_allowed checks.
src/mcp.rs (1)

254-283: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Scope synty_topics and synty_recent to the full ReadScope
topics_text and recent_text only filter by repo, so campaign/role/source restrictions are ignored here. Either carry those fields onto Unit/Session and filter them too, or disable these tools whenever the scope narrows beyond repos.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mcp.rs` around lines 254 - 283, The topics_text and recent_text handlers
currently enforce only repository access, ignoring other ReadScope restrictions
such as campaign, role, and source. Update these handlers to apply the complete
ReadScope to returned topics and units, carrying required scope fields onto
Unit/Session if necessary; otherwise reject or disable both tools whenever the
scope is narrower than repository-only.
🧹 Nitpick comments (5)
src/ingest.rs (1)

301-318: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a scenario test asserting campaign/role/backend reach Doc.meta.

docs_from_events now stamps campaign_id, campaign_role, and backend onto emitted docs from SessionMaps. These meta fields become the index columns that ReadScope filters on in search.rs, so mis-propagation would silently weaken scope enforcement. No existing session_docs test asserts these fields survive from session_start into the produced docs.

Consider extending a session_docs test with a session_start carrying rollup_dim/campaign_role/backend and asserting the resulting Doc.meta.

As per coding guidelines: "Every behavioral change must include a scenario-style unit test based on user expectations, following the existing #[cfg(test)] conventions."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/ingest.rs` around lines 301 - 318, Extend an existing session_docs
scenario test to include a session_start event with rollup_dim, campaign_role,
and backend values, then assert the emitted Doc.meta contains the corresponding
campaign_id, campaign_role, and backend fields. Keep the test within the
existing #[cfg(test)] conventions and verify values propagate through
docs_from_events and SessionMaps.

Source: Coding guidelines

src/import.rs (1)

114-116: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Hoist crate::config::load() out of the NDJSON loop. Config::load() reads and parses src/config.rs on every call, so the repo allowlist check does repeated file I/O for every imported row.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/import.rs` around lines 114 - 116, Move the crate::config::load() call
out of the NDJSON row-processing loop and load the configuration once before
iteration begins. Reuse the resulting capture_repos allowlist in the existing
event repository check, preserving the current filtering behavior.
src/main.rs (1)

271-376: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the new CLI surface in the user-facing docs. README.md and docs/design.md still need the expanded import/mcp/init flags (--bind, --listen-public, --scope, --redaction, --campaign, --no-autostart, etc.); AGENTS.md already carries the general reconciliation rule.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main.rs` around lines 271 - 376, Document the expanded Import, Init, and
Mcp CLI surfaces in README.md and docs/design.md, including flags such as
--bind, --listen-public, --scope, --redaction, --campaign, and --no-autostart.
Keep the documentation aligned with the command definitions and existing
AGENTS.md reconciliation guidance.

Source: Coding guidelines

src/sync.rs (1)

309-328: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a test covering redacted uploads.

redact_event_lines is a new, security-relevant behavior (uploads now redact secrets/PII by default), but no test in this diff exercises it — e.g. asserting a Bearer … token in a payload doesn't survive push_events_scoped/redact_event_lines with Profile::Standard, and that Profile::Off round-trips raw bytes unchanged.
As per coding guidelines, "Every behavioral change must include a scenario-style unit test based on user expectations, following the existing #[cfg(test)] conventions."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/sync.rs` around lines 309 - 328, Add a scenario-style unit test under the
existing #[cfg(test)] conventions for redact_event_lines, using
Profile::Standard to verify a Bearer token is removed from uploaded event
payloads and Profile::Off to verify raw bytes round-trip unchanged. Exercise the
behavior through push_events_scoped where practical, while retaining direct
coverage of redact_event_lines if that is the established test pattern.

Source: Coding guidelines

src/policy.rs (1)

38-43: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Repo/source/campaign/role scope-matching logic is reimplemented in five places. ReadScope doesn't expose a single reusable predicate, so the same security-relevant AND-chain (and, separately, the campaign/role extraction from an event) is hand-copied in policy.rs, view.rs, and twice more in trace.rs. That's a maintainability risk today and a real risk of future scope-bypass if one copy is updated (e.g. a new scope dimension) and the others aren't.

  • src/policy.rs#L38-L43: extract the repo/source/campaign/role AND-chain used by allows_event into a small reusable method (e.g. ReadScope::allows(repo, source, campaign, role)), and make campaign()/role() (L57-66) pub(crate) so other modules can reuse the extraction too.
  • src/trace.rs#L219-L228: call the shared pub(crate) campaign/role extraction helper from policy.rs instead of re-deriving it from ev.rollup_dim/ev.payload inline.
  • src/trace.rs#L877-L891: have scope_allows call the new ReadScope::allows(...) helper instead of re-inlining the AND-chain.
  • src/trace.rs#L1207-L1218: have the Resolved::Session arm delegate to scope_allows (or the shared ReadScope::allows(...)) instead of a third inline copy of the same chain.
  • src/view.rs#L417-L423: have the docs.retain(...) closure call the same shared ReadScope::allows(...) helper instead of re-inlining the chain against doc.meta.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/policy.rs` around lines 38 - 43, Centralize scope matching in
src/policy.rs lines 38-43 by adding a reusable ReadScope::allows(repo, source,
campaign, role) method, updating allows_event to use it, and making campaign()
and role() pub(crate). In src/trace.rs lines 219-228, reuse those extraction
helpers; in lines 877-891 and 1207-1218, delegate to ReadScope::allows or
scope_allows; and in src/view.rs lines 417-423, use ReadScope::allows in the
docs.retain closure, removing each duplicated AND-chain.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@deploy/helm/synty/templates/builder.yaml`:
- Around line 27-30: Keep shell line continuations inside the corresponding
optional Helm branches so empty values cannot join separate commands. Update
deploy/helm/synty/templates/builder.yaml lines 27-30 to conditionally emit the
AWS-profile continuation and keep synty build separate; apply the same
conditional continuation handling for AWS, campaign, and role options in
deploy/helm/synty/templates/tracker.yaml lines 29-42; apply it to the
AWS-profile option in deploy/helm/synty/templates/mcp.yaml lines 28-31 so exec
synty mcp remains a separate command.
- Around line 17-19: Add pod securityContext.fsGroup set to 10001 before
serviceAccountName in deploy/helm/synty/templates/builder.yaml (lines 17-19),
deploy/helm/synty/templates/tracker.yaml (lines 19-21), and
deploy/helm/synty/templates/mcp.yaml (lines 19-20), ensuring the shared
/var/synty volume is writable by the non-root runtime.

In `@deploy/helm/synty/templates/mcp.yaml`:
- Around line 31-36: Update the MCP endpoint configuration around the `exec
synty mcp` command to require TLS or mTLS rather than exposing plaintext
`--listen-public` HTTP. Add configurable certificate/client-auth settings and
source selectors for the Service and NetworkPolicy, ensuring ingress is not
permitted from every source. Do not enable the public endpoint by default until
both encrypted transport and caller restrictions are enforced.

In `@docs/design.md`:
- Line 171: Update the MCP policy sentence near “policy and optional read scope
bound mediated clients” to use grammatical wording, such as “policy and optional
read scope bind mediated clients” or “are bound to mediated clients,” while
preserving the intended meaning.
- Around line 335-339: Update the bucket-backplane description in the
surrounding design documentation to list only local, S3, and GCS as storage
backends; describe MCP-HTTP separately as an optional HTTP transport, and ensure
the fleet-wide encode-once and collaborative-build claims apply only to the
actual backplane.

In `@src/mcp_http.rs`:
- Around line 16-39: Update run’s incoming request loop to handle errors from
handle locally: log each per-request failure and continue accepting subsequent
requests instead of propagating it with ?. Tighten origin_allowed so HTTPS
origins are accepted only when they are loopback or explicitly present in the
configured allowlist, rejecting arbitrary HTTPS sites.

In `@src/track.rs`:
- Around line 157-158: Add scenario-style tests under the existing #[cfg(test)]
section covering Tracker::new propagation of non-empty Opts.campaign and
Opts.role into Stream metadata, and synthetic session-end events retaining the
configured campaign while asserting the event ID. Replace or extend the manually
constructed Stream and empty-campaign cases so both paths would fail if the
corresponding plumbing regressed.
- Around line 454-456: Update the environment override handling in the code
calling roots_with_overrides so CLAUDE_CONFIG_DIR and CODEX_HOME values are
considered unset when empty. Filter empty strings before passing
claude_home.as_deref() and codex_home.as_deref(), preserving non-empty overrides
and allowing fallback to the corresponding home-based defaults.
- Around line 348-351: Update the event payload construction in the relevant
tracking flow so campaign_role is written onto every envelope, not only
session_start events. Preserve the existing non-empty-role guard and continue
sourcing the value from self.campaign_role, ensuring later role-scoped events
retain the role used by ReadScope::allows_event.

---

Outside diff comments:
In @.dockerignore:
- Around line 1-8: Update the Docker ignore configuration to exclude local
credential sources by adding entries for .env files, the .aws/ directory, and
private-key files such as *.pem and *.key. Preserve all existing exclusions.

In `@src/mcp.rs`:
- Around line 254-283: The topics_text and recent_text handlers currently
enforce only repository access, ignoring other ReadScope restrictions such as
campaign, role, and source. Update these handlers to apply the complete
ReadScope to returned topics and units, carrying required scope fields onto
Unit/Session if necessary; otherwise reject or disable both tools whenever the
scope is narrower than repository-only.

In `@src/trace.rs`:
- Around line 1222-1267: Update resolve to accept the caller’s ReadScope and
apply scope_allows to every job, turn, span, session event, and event candidate
before inserting it into bases, ensuring ambiguity counts and listed IDs contain
only permitted records. Update show_text and compare_text to pass their scope
into resolve while preserving the existing post-resolution resolved_allowed
checks.

---

Nitpick comments:
In `@src/import.rs`:
- Around line 114-116: Move the crate::config::load() call out of the NDJSON
row-processing loop and load the configuration once before iteration begins.
Reuse the resulting capture_repos allowlist in the existing event repository
check, preserving the current filtering behavior.

In `@src/ingest.rs`:
- Around line 301-318: Extend an existing session_docs scenario test to include
a session_start event with rollup_dim, campaign_role, and backend values, then
assert the emitted Doc.meta contains the corresponding campaign_id,
campaign_role, and backend fields. Keep the test within the existing
#[cfg(test)] conventions and verify values propagate through docs_from_events
and SessionMaps.

In `@src/main.rs`:
- Around line 271-376: Document the expanded Import, Init, and Mcp CLI surfaces
in README.md and docs/design.md, including flags such as --bind,
--listen-public, --scope, --redaction, --campaign, and --no-autostart. Keep the
documentation aligned with the command definitions and existing AGENTS.md
reconciliation guidance.

In `@src/policy.rs`:
- Around line 38-43: Centralize scope matching in src/policy.rs lines 38-43 by
adding a reusable ReadScope::allows(repo, source, campaign, role) method,
updating allows_event to use it, and making campaign() and role() pub(crate). In
src/trace.rs lines 219-228, reuse those extraction helpers; in lines 877-891 and
1207-1218, delegate to ReadScope::allows or scope_allows; and in src/view.rs
lines 417-423, use ReadScope::allows in the docs.retain closure, removing each
duplicated AND-chain.

In `@src/sync.rs`:
- Around line 309-328: Add a scenario-style unit test under the existing
#[cfg(test)] conventions for redact_event_lines, using Profile::Standard to
verify a Bearer token is removed from uploaded event payloads and Profile::Off
to verify raw bytes round-trip unchanged. Exercise the behavior through
push_events_scoped where practical, while retaining direct coverage of
redact_event_lines if that is the established test pattern.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 97be4b96-3315-468a-9d4f-85ad4e063341

📥 Commits

Reviewing files that changed from the base of the PR and between 8a5e095 and 732f38c.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (34)
  • .dockerignore
  • .github/workflows/release.yml
  • AGENTS.md
  • Cargo.toml
  • Dockerfile
  • README.md
  • deploy/helm/synty/Chart.yaml
  • deploy/helm/synty/templates/_helpers.tpl
  • deploy/helm/synty/templates/builder.yaml
  • deploy/helm/synty/templates/configmap.yaml
  • deploy/helm/synty/templates/mcp.yaml
  • deploy/helm/synty/templates/pvc.yaml
  • deploy/helm/synty/templates/serviceaccount.yaml
  • deploy/helm/synty/templates/tracker.yaml
  • deploy/helm/synty/values.yaml
  • docs/design.md
  • src/config.rs
  • src/event.rs
  • src/fleet.rs
  • src/import.rs
  • src/ingest.rs
  • src/init.rs
  • src/main.rs
  • src/mcp.rs
  • src/mcp_http.rs
  • src/policy.rs
  • src/redact.rs
  • src/search.rs
  • src/sync.rs
  • src/trace.rs
  • src/track.rs
  • src/tui.rs
  • src/up.rs
  • src/view.rs

Comment thread deploy/helm/synty/templates/builder.yaml
Comment thread deploy/helm/synty/templates/builder.yaml Outdated
Comment thread deploy/helm/synty/templates/mcp.yaml Outdated
Comment thread docs/design.md Outdated
Comment thread docs/design.md Outdated
Comment thread src/mcp_http.rs
Comment thread src/track.rs
Comment thread src/track.rs Outdated
Comment thread src/track.rs Outdated
huronat added 2 commits July 23, 2026 00:05
Make scope enforcement fail closed across 12 tools, stabilize canonical imports and atomic sync, and bound authenticated HTTP execution. Add native multi-arch ECR publishing, read-only IRSA/Helm deployment, and PR checks covering 271 default plus 275 cloud/MCP scenarios.
Require certificate-backed HTTPS and source-restricted NetworkPolicy rules before Helm enables remote MCP. Filter trace identifiers before ambiguity reporting, centralize scope predicates, and preserve campaign roles on every event.

Add scenario coverage for scoped ids, metadata propagation, upload redaction, tracker construction, synthetic ends, TLS serving, and CLI parsing. The default and shipped feature matrices pass 274 and 278 tests respectively.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
src/mcp_http.rs (1)

262-266: 🩺 Stability & Availability | 🔵 Trivial

No body read timeout on this public listener. read_to_end(...) runs before the dispatcher timeout, so a slow client can occupy one of the MAX_IN_FLIGHT slots until the upload completes. If --listen-public remains exposed, enforce client-body timeouts at a proxy or another listener that supports connection read deadlines.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mcp_http.rs` around lines 262 - 266, Update the public-listener request
handling around the body read in the relevant handler to enforce a client-body
read timeout before dispatching, using a proxy or listener mechanism that
supports connection read deadlines. Ensure slow uploads cannot hold a
MAX_IN_FLIGHT slot indefinitely, while preserving the existing MAX_BODY_BYTES
limit and 413 response.
src/bucket/cloud.rs (1)

280-303: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Partial writes are invisible on batch failure.

buffer_unordered drains every future before the loop maps errors, so if one object's PUT fails, other objects in the same batch may already have been created — but the caller only sees an aggregate Err with no indication of how many succeeded. Since writes are write-once/idempotent, this isn't corrupting, but callers retrying on error will assume nothing happened. Consider surfacing the partial created count alongside the error if callers ever need to reason about retry cost.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/bucket/cloud.rs` around lines 280 - 303, Update put_many_if_absent to
retain the total number of successful PUTs when any result fails, rather than
returning immediately from the result loop. Process all collected results, count
every created object, record the first error with its key, then return an error
that includes the aggregate created count; otherwise return the count as today.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 99-108: Update the “Check immutable architecture tag” step to pass
the version output through the step’s env block, then reference that environment
variable in the shell command instead of interpolating
steps.version.outputs.version directly. Preserve the existing ECR repository and
matrix suffix behavior while ensuring the tag-derived value is not treated as
shell syntax.

In `@CONTRIBUTING.md`:
- Around line 59-61: Update the container publishing description in
CONTRIBUTING.md to state that the version tag publishes a verified
multi-architecture Linux manifest containing both amd64 and arm64 images,
matching the behavior of the release.yml image-index job. Remove the inaccurate
claim that it publishes only an immutable linux/amd64 container while preserving
the registry path and deployment instructions.

In `@deploy/helm/synty/templates/builder.yaml`:
- Around line 42-44: Remove the conditional AWS_PROFILE environment-variable
injection from the builder pod template in
deploy/helm/synty/templates/builder.yaml lines 42-44 and the MCP pod template in
deploy/helm/synty/templates/mcp.yaml lines 57-59. Leave AWS workloads to use
their role chain and do not replace the removed configuration with another
profile mechanism.

---

Nitpick comments:
In `@src/bucket/cloud.rs`:
- Around line 280-303: Update put_many_if_absent to retain the total number of
successful PUTs when any result fails, rather than returning immediately from
the result loop. Process all collected results, count every created object,
record the first error with its key, then return an error that includes the
aggregate created count; otherwise return the count as today.

In `@src/mcp_http.rs`:
- Around line 262-266: Update the public-listener request handling around the
body read in the relevant handler to enforce a client-body read timeout before
dispatching, using a proxy or listener mechanism that supports connection read
deadlines. Ensure slow uploads cannot hold a MAX_IN_FLIGHT slot indefinitely,
while preserving the existing MAX_BODY_BYTES limit and 413 response.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2608913d-e47f-4634-8345-87a7e95ef76d

📥 Commits

Reviewing files that changed from the base of the PR and between 732f38c and 237655a.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (38)
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • AGENTS.md
  • CONTRIBUTING.md
  • Cargo.toml
  • Dockerfile
  • README.md
  • deploy/aws/ecr-publisher.yaml
  • deploy/aws/mcp-reader.yaml
  • deploy/helm/synty/Chart.yaml
  • deploy/helm/synty/templates/_helpers.tpl
  • deploy/helm/synty/templates/builder.yaml
  • deploy/helm/synty/templates/mcp.yaml
  • deploy/helm/synty/templates/tracker.yaml
  • deploy/helm/synty/values-sie-gw-cfg.yaml
  • deploy/helm/synty/values.yaml
  • docs/design.md
  • scripts/mcp-http-smoke.sh
  • src/bucket.rs
  • src/bucket/cloud.rs
  • src/config.rs
  • src/fleet.rs
  • src/import.rs
  • src/index.rs
  • src/ingest.rs
  • src/init.rs
  • src/main.rs
  • src/mcp.rs
  • src/mcp_http.rs
  • src/policy.rs
  • src/qwen.rs
  • src/redact.rs
  • src/search.rs
  • src/store.rs
  • src/sync.rs
  • src/tui.rs
  • src/units.rs
  • src/view.rs
🚧 Files skipped from review as they are similar to previous changes (13)
  • deploy/helm/synty/Chart.yaml
  • src/fleet.rs
  • Dockerfile
  • Cargo.toml
  • deploy/helm/synty/templates/_helpers.tpl
  • src/config.rs
  • src/search.rs
  • src/init.rs
  • deploy/helm/synty/templates/tracker.yaml
  • src/ingest.rs
  • src/import.rs
  • src/main.rs
  • src/mcp.rs

Comment thread .github/workflows/release.yml
Comment thread CONTRIBUTING.md Outdated
Comment thread deploy/helm/synty/templates/builder.yaml Outdated
Align the local override, Cargo MSRV, CI and release jobs, and container builder on Rust 1.97.0 so every supported build path uses the same compiler.

Rust 1.97 passes 274 default tests and 278 shipped-feature tests. Docker resolves rust:1.97-bookworm and reports no Dockerfile check warnings.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
deploy/helm/synty/templates/mcp.yaml (1)

145-146: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

egress: - {} allows unrestricted outbound traffic. With policyTypes: [Ingress, Egress], this is allow-all egress; the chart only exposes networkPolicy.ingressFrom, so there’s no way to scope outbound DNS/S3 access yet. Add explicit egress rules and chart values for the required destinations/ports.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deploy/helm/synty/templates/mcp.yaml` around lines 145 - 146, Replace the
unrestricted egress rule in the chart’s NetworkPolicy with explicit destination
and port rules for the required DNS and S3 access. Add corresponding
configurable chart values, wire them into the egress rules, and preserve the
existing network policy behavior for ingress.
🧹 Nitpick comments (1)
scripts/mcp-http-smoke.sh (1)

93-100: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Validate the generated certificate instead of using -k.

-k makes this TLS check accept any certificate. Generate a certificate with a SAN for 127.0.0.1 and use --cacert "$work/tls.crt" so the smoke test validates the trust path too.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/mcp-http-smoke.sh` around lines 93 - 100, Update the TLS setup and
health-check curl in the smoke test: generate the certificate with a subject
alternative name for 127.0.0.1, then replace curl’s -k option with --cacert
"$work/tls.crt" so the check validates the generated certificate and trust path.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@deploy/helm/synty/templates/mcp.yaml`:
- Around line 8-14: Strengthen the ingress validation in the
networkPolicy.ingressFrom template loop so podSelector and namespaceSelector
cannot be empty or contain empty matchLabels/matchExpressions. Require each
selector to include at least one non-empty matchLabels entry or matchExpressions
constraint before rendering MCP ingress, while preserving the existing rejection
of empty entries and unrestricted namespace selectors.

---

Outside diff comments:
In `@deploy/helm/synty/templates/mcp.yaml`:
- Around line 145-146: Replace the unrestricted egress rule in the chart’s
NetworkPolicy with explicit destination and port rules for the required DNS and
S3 access. Add corresponding configurable chart values, wire them into the
egress rules, and preserve the existing network policy behavior for ingress.

---

Nitpick comments:
In `@scripts/mcp-http-smoke.sh`:
- Around line 93-100: Update the TLS setup and health-check curl in the smoke
test: generate the certificate with a subject alternative name for 127.0.0.1,
then replace curl’s -k option with --cacert "$work/tls.crt" so the check
validates the generated certificate and trust path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f5de73af-21a6-4d1a-a659-a5cb80783a99

📥 Commits

Reviewing files that changed from the base of the PR and between 237655a and a041208.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • .dockerignore
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • Cargo.toml
  • Dockerfile
  • README.md
  • deploy/helm/synty/templates/mcp.yaml
  • deploy/helm/synty/values-sie-gw-cfg.yaml
  • deploy/helm/synty/values.yaml
  • docs/design.md
  • rust-toolchain.toml
  • scripts/mcp-http-smoke.sh
  • src/ingest.rs
  • src/main.rs
  • src/mcp_http.rs
  • src/policy.rs
  • src/sync.rs
  • src/trace.rs
  • src/track.rs
🚧 Files skipped from review as they are similar to previous changes (16)
  • .dockerignore
  • deploy/helm/synty/values-sie-gw-cfg.yaml
  • Dockerfile
  • Cargo.toml
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • deploy/helm/synty/values.yaml
  • README.md
  • docs/design.md
  • src/mcp_http.rs
  • src/policy.rs
  • src/sync.rs
  • src/ingest.rs
  • src/main.rs
  • src/track.rs
  • src/trace.rs

Comment thread deploy/helm/synty/templates/mcp.yaml
huronat added 2 commits July 23, 2026 00:55
Replace blocking HTTP body reads with Hyper/Rustls deadlines that cap 64 connections, 32 in-flight requests, and 4 MiB bodies. Reject unrestricted Helm caller selectors and leave Kubernetes AWS credentials on the workload role chain.

Drain cloud batch writes before reporting partial failure, harden tag-derived shell input, and reconcile multi-architecture docs. Validation: 274 default tests, 280 shipped-feature tests, HTTP/HTTPS smoke, Helm lint/render, and Dockerfile check.
Join the v0.2.4 release and fleet batch-transfer history into the mediated-access branch without rewriting the PR commits. The overlapping cloud batch implementation keeps partial-success accounting from d549336.

The resolved tree is unchanged from the tested PR head: 274 default tests and 280 shipped-feature tests passed before the merge.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
CONTRIBUTING.md (1)

54-54: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document mcp-http for the macOS release too.

The release workflow builds macos-14 with metal,s3,gcs,mcp-http, but this paragraph lists only metal,s3,gcs for macOS.

Based on the supplied .github/workflows/release.yml context, the macOS matrix includes mcp-http.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CONTRIBUTING.md` at line 54, Update the macOS release feature list in the
relevant CONTRIBUTING.md paragraph to include mcp-http alongside metal,s3,gcs,
matching the macos-14 release workflow; leave the Ubuntu feature listing
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/bucket/cloud.rs`:
- Around line 473-488: Update the failure test around Cloud::put_many_if_absent
to use a deterministic failing ObjectStore wrapper and invoke the public
batch-put method instead of calling summarize_batch_puts directly. Assert the
returned partial-progress error includes the successful-create count, object
name, and injected backend error, while retaining the existing helper test only
as supplemental coverage.

---

Outside diff comments:
In `@CONTRIBUTING.md`:
- Line 54: Update the macOS release feature list in the relevant CONTRIBUTING.md
paragraph to include mcp-http alongside metal,s3,gcs, matching the macos-14
release workflow; leave the Ubuntu feature listing unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 881f8e0c-9c8b-4245-8b30-5c1bb95a9f7f

📥 Commits

Reviewing files that changed from the base of the PR and between a041208 and 76e3dd6.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • CONTRIBUTING.md
  • Cargo.toml
  • README.md
  • deploy/helm/synty/templates/builder.yaml
  • deploy/helm/synty/templates/mcp.yaml
  • deploy/helm/synty/templates/tracker.yaml
  • deploy/helm/synty/values-sie-gw-cfg.yaml
  • deploy/helm/synty/values.yaml
  • src/bucket/cloud.rs
  • src/mcp_http.rs
💤 Files with no reviewable changes (2)
  • deploy/helm/synty/templates/builder.yaml
  • deploy/helm/synty/templates/tracker.yaml
🚧 Files skipped from review as they are similar to previous changes (7)
  • .github/workflows/ci.yml
  • deploy/helm/synty/values-sie-gw-cfg.yaml
  • deploy/helm/synty/templates/mcp.yaml
  • README.md
  • deploy/helm/synty/values.yaml
  • .github/workflows/release.yml
  • src/mcp_http.rs

Comment thread src/bucket/cloud.rs
Publish deterministic format-2 session, tool, fleet, and bounded trace projections inside immutable builds so MCP readers never scan the raw lake. Fail readiness closed until those projections exist, serialize heavy analysis calls, and constrain object-store egress.\n\nStream the 657 MiB document store, exercise default, no-LLM, cloud, HTTP, and Helm paths, and preserve all 104,512 live event identities while bounding literal trace evidence.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@deploy/helm/synty/templates/mcp.yaml`:
- Around line 8-15: Strengthen the validation around
networkPolicy.objectStoreCidrs so CIDR combinations cannot recreate unrestricted
internet egress, including split IPv4 or IPv6 /0 ranges such as paired /1
prefixes. Reject overly broad prefixes or validate the configured list against
the allowed object-store endpoint ranges before the NetworkPolicy egress rules
are rendered; preserve the existing required-list and exact /0 checks.

In `@src/eval.rs`:
- Around line 220-225: Add a scenario-style unit test in the existing
#[cfg(test)] block for the default-feature, extractive-only configuration,
invoking run_names with a representative bucket and asserting it returns an
error containing the actionable “llm” feature message. Keep the test gated
consistently with the non-llm implementation and preserve the existing command
contract.

In `@src/index.rs`:
- Around line 34-48: Ensure index::run and ingest publish and consume one
immutable ingest generation: stage docs, projections, and related artifacts in a
generation directory, atomically publish its pointer, and resolve all inputs and
build outputs from that same generation before repointing. Update src/index.rs
lines 34-48 to read a single generation snapshot, src/index.rs lines 195-205 to
write artifacts selected from that snapshot, and src/ingest.rs lines 145-162 to
stage and atomically publish the generation; alternatively, hold the shared
ingest/index lock across the complete build. Add a scenario-style test covering
concurrent ingest and indexing, verifying no mixed-generation documents,
embeddings, metadata, or snapshots are published.

In `@src/trace.rs`:
- Around line 211-255: Validate all snapshot reference values in
TraceSnapshot::into_store before constructing and rebuilding TraceStore,
ensuring event span indexes, span start_event/end_event values, job
span_indexes, and turn event_indexes/span_indexes are within their corresponding
collection bounds. Return a descriptive anyhow error for any invalid reference,
while preserving valid snapshot loading.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1276baa2-d4a3-4cec-bde5-a78cbcd14ae4

📥 Commits

Reviewing files that changed from the base of the PR and between 76e3dd6 and 9fc0a0b.

📒 Files selected for processing (24)
  • .github/workflows/ci.yml
  • CONTRIBUTING.md
  • README.md
  • deploy/helm/synty/templates/mcp.yaml
  • deploy/helm/synty/values-sie-gw-cfg.yaml
  • deploy/helm/synty/values.yaml
  • docs/design.md
  • scripts/mcp-http-smoke.sh
  • src/bucket/cloud.rs
  • src/eval.rs
  • src/fleet.rs
  • src/index.rs
  • src/ingest.rs
  • src/main.rs
  • src/mcp.rs
  • src/mcp_http.rs
  • src/qwen.rs
  • src/readmodel.rs
  • src/related.rs
  • src/sync.rs
  • src/trace.rs
  • src/units.rs
  • src/view.rs
  • src/words.rs
🚧 Files skipped from review as they are similar to previous changes (10)
  • deploy/helm/synty/values-sie-gw-cfg.yaml
  • CONTRIBUTING.md
  • .github/workflows/ci.yml
  • scripts/mcp-http-smoke.sh
  • deploy/helm/synty/values.yaml
  • README.md
  • docs/design.md
  • src/sync.rs
  • src/mcp.rs
  • src/main.rs

Comment thread deploy/helm/synty/templates/mcp.yaml
Comment thread src/eval.rs
Comment thread src/index.rs
Comment thread src/trace.rs
Serialize ingest replacement with index publication so documents, metadata, embeddings, and both projections come from one generation. Validate every trace reference before reconstruction and reject object-store CIDR sets that can recreate split default routes. Exercise 280 default, 259 extractive-only, and 286 shipped-feature scenarios.
huronat added 3 commits July 23, 2026 12:21
Add an explicit read-only index mode that reuses fleet embeddings while keeping misses and the completed read-model local. The live bucket covered 4,621 of 10,800 retained documents without changing the MCP reader role.

Exercise 281 default, 261 extractive-only, and 288 shipped-feature scenarios.
Keep chart-created PVCs across Helm upgrades and point sie-gw-cfg at the verified 50 GiB replacement after the live 20 GiB gp2 claim reached 100% with 15 MiB free during shard 5. CI asserts the retention annotation; Helm lint and both default and cluster-specific renders pass.
Emit full native session and topic ids from agent-facing lists and ambiguity errors. The live sie-gw-cfg corpus contained two sessions under the printed 019f7d1e prefix, so synty_show could not consume its own search result directly. Validation: 283 default, 262 extractive-only, 289 shipped-feature scenarios, plus HTTP/TLS smoke.
@svonava

svonava commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Does this add a server in front of the bucket for auth? Given that this is used in a trusted environment, why do we need that?

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