ci: real CI pipeline + MCP stdio hardening#10
Merged
Conversation
First pass of CI foundation work. No behavior change: rustfmt reflows only (import ordering, line wrapping, multi-line assert/expression formatting). Makes the new fmt --check CI job green.
The only prior workflow mirrored the repo; nothing ran the 600+ tests or clippy on a PR. Adds .github/workflows/ci.yml with five jobs: rustfmt --check, clippy --workspace --all-targets -D warnings, cargo test --workspace (the Docker-gated postgres tests stay #[ignore]), a scoped postgres-integration job that lets testcontainers self-start its database, and a non-blocking RustSec advisory scan. Jobs run on stable to match the local toolchain; libpq-dev is installed on the compiling jobs for diesel/pq-sys. Workspace is already fmt- and clippy-clean, so the pipeline is green on first run.
…rsona checks - Replace the unbounded lines() reader with read_capped_line: a single JSON-RPC line is capped at 8 MiB and an over-long line is rejected with a -32700 (the next line still processes), so a client that never sends a newline cannot drive unbounded memory growth. - Replace the startup Client init .expect() with a clean stderr diagnostic and nonzero exit instead of a panic. - Validate the persona name at the MCP boundary in call_activate and call_use, mirroring call_grow_append. Defense-in-depth: the client layer already validates in activate()/rendered_persona(), this rejects earlier with a clear error. Regression tests cover cap-then-recover and boundary rejection for both activate and use. clippy -D warnings clean; cargo test -p frameshift-mcp green.
The local Arch rustfmt (1.9.0) and CI's upstream rustfmt (rust 1.96.0) format a wrapped 3-arg error_response() call differently -- Arch keeps it on two lines, upstream explodes the args. Binding the message to a temp var keeps both statements short enough that neither rustfmt reformats them, so the fmt job is reproducible across both.
These hold raw multi-model audit findings with local filesystem paths, unpublished vulnerability locations, and internal tool identifiers that do not belong in a public repo.
Clears all 8 cargo-audit vulnerabilities that were gating the Security
audit job, and ratchets that job from continue-on-error to blocking.
- diesel 2.2 -> 2.3.10, diesel-async 0.5 -> 0.9.2, diesel_migrations
2.2 -> 2.3, bb8 0.8 -> 0.9 (diesel-async 0.9 implements
bb8::ManageConnection only for bb8 0.9). Clears RUSTSEC-2026-0136 and
-0137 plus the diesel/diesel-async unsound advisories.
- cargo update pulls postgres-protocol 0.6.12 (RUSTSEC-2026-0179/-0180),
tokio-postgres 0.7.18 (RUSTSEC-2026-0178), quinn-proto 0.11.15
(RUSTSEC-2026-0185).
- frameshift-server: prometheus default-features=false drops protobuf
2.28 (RUSTSEC-2024-0437); the server only emits the text format.
- dev: testcontainers 0.23 -> 0.27, testcontainers-modules 0.11 -> 0.15;
drops unmaintained tokio-tar (RUSTSEC-2025-0111, no upstream fix) for
the maintained astral-tokio-tar fork, and rustls-pemfile.
- ci: audit job now blocking, ignoring only RUSTSEC-2024-0370
(proc-macro-error, build-only via age, removable only by the age 0.11
beta that backs vault crypto).
diesel-async 0.9 migration: transaction() now takes an AsyncFnOnce, so
register_pack_version uses an `async move |conn|` closure instead of the
removed `|conn| Box::pin(async move { .. })` form; ManagerConfig is now
generic, so pool.rs names AsyncPgConnection explicitly. rust-version
1.75 -> 1.86 to match the new floor (diesel 2.3 + async closures).
clippy -D warnings clean; cargo test --workspace 616 passed, 0 failed.
`git push --mirror` deletes refs absent from the local checkout. Because actions/checkout only fetches the triggering branch, the mirror push tried to delete every other ref on the target -- and the remote rejects deleting its default branch `main`, so the job failed on every push. Fetch all source branches into remote-tracking refs, then force-push branches and tags with explicit refspecs (additive, no deletion).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Foundation work for the improvement program: a real CI pipeline (the repo had none) plus a small MCP stdio hardening pass. Three commits.
CI (
.github/workflows/ci.yml)Before this, the only workflow mirrored the repo; nothing ran the 600+ tests, clippy, or fmt on a PR. New jobs:
cargo fmt --all -- --checkcargo clippy --workspace --all-targets -- -D warningscargo test --workspace(the Docker-gated postgres tests stay#[ignore])cargo test -p frameshift-catalog-postgres -- --include-ignored; testcontainers self-starts postgres against the runner's DockerJobs run on
stableto match the local toolchain;libpq-devis installed on the compiling jobs for diesel/pq-sys. The workspace was already fmt- and clippy-clean, so the precedingcargo fmt --allcommit is formatting-only and the pipeline is green on the first run.MCP stdio hardening
.expect()with a stderr diagnostic and nonzero exit instead of a panic.call_activate/call_use(mirrorscall_grow_append); defense-in-depth over the existing client-layer checks.Verification (local)
cargo clippy --workspace --all-targets -- -D warnings: cleancargo test --workspace: 607 passed, 0 failed, 25 ignoredcargo test -p frameshift-mcp: 39/39, including new cap-recovery and boundary-rejection regression tests