Skip to content

fix(publish): bundle aprender-mcp contract YAML + build.rs escape guard#910

Merged
noahgift merged 1 commit into
mainfrom
fix/publish-aprender-mcp-contracts
Apr 19, 2026
Merged

fix(publish): bundle aprender-mcp contract YAML + build.rs escape guard#910
noahgift merged 1 commit into
mainfrom
fix/publish-aprender-mcp-contracts

Conversation

@noahgift

Copy link
Copy Markdown
Contributor

Summary

Fixes the v0.31.1 yank — cargo install aprender@0.31.1 panicked at build
time because aprender-mcp's build.rs read
CARGO_MANIFEST_DIR/../../contracts/apr-mcp-tool-schemas-v1.yaml,
which lives in the monorepo tree but NOT in the published tarball.

Three-layer defense so this class can't recur:

  1. In-crate YAML copy + `include = ["contracts/*.yaml"]` in Cargo.toml + drift-guard test asserting byte-identity with the workspace-root copy.
  2. New `scripts/check_build_rs_paths.sh` — static Poka-Yoke that flags any build.rs joining `".."` + `panic!` without an `.exists()` guard or `ALLOW_ESCAPE` annotation.
  3. Wired into both `make tier3` (pre-push) and `.github/workflows/ci.yml` (workspace-test job).

Yank already executed — all 68 crates confirmed yanked on crates.io.

Refs: task #64 (yank), #65 (fix), #66 (prevention)

Test plan

  • `bash scripts/check_build_rs_paths.sh` → OK: 22 build.rs checked
  • `cargo test -p aprender-mcp --test falsify_mcp_008 contract_copy_matches_workspace_root` passes
  • `cargo fmt --all --check` clean
  • `cargo clippy -p aprender-mcp --all-targets -- -D warnings` clean
  • Reverting aprender-mcp/build.rs to the broken version → gate exits 1 with remediation message (verified locally)
  • CI green (`ci / gate` + `workspace-test`)

After this lands

Cut v0.31.2, re-publish all 68 crates (paced at 40s/crate ≈ 45min), verify `cargo install aprender --version 0.31.2` installs.

🤖 Generated with Claude Code

v0.31.1 was yanked from crates.io because `cargo install aprender@0.31.1`
panicked at aprender-mcp build.rs — `CARGO_MANIFEST_DIR/../../contracts/
apr-mcp-tool-schemas-v1.yaml` lives in the monorepo tree but NOT in the
published tarball (outside the package root), so every external install
hit a hard panic at build time.

Three-layer defense so this class never recurs:

1. **In-crate contract copy** — contracts/apr-mcp-tool-schemas-v1.yaml
   copied into crates/aprender-mcp/contracts/ and Cargo.toml `include`
   lists `contracts/*.yaml`. build.rs reads `CARGO_MANIFEST_DIR/
   contracts/…` (no `..` escape). Drift-guarded by new test
   `contract_copy_matches_workspace_root` which asserts byte-identity
   with the workspace-root copy in-tree, and skips when the workspace
   copy is absent (published-tarball mode).

2. **Static Poka-Yoke** — scripts/check_build_rs_paths.sh walks every
   git-tracked build.rs, flags any that join `".."` onto
   CARGO_MANIFEST_DIR AND `panic!`/`unwrap_or_else(…panic)` AND lack a
   `.exists()` guard or `ALLOW_ESCAPE` annotation. Reverting this fix
   locally makes the gate exit 1 with a remediation message.

3. **Wired into both gates** — `make tier3` runs the check pre-push,
   and `.github/workflows/ci.yml` `workspace-test` job runs it on every
   PR so a future build.rs path escape can't sneak back in.

Yank command (already executed):
  cargo yank --version 0.31.1 <each of 68 crates>  # all confirmed yanked

Next step after this lands: cut v0.31.2, re-publish all 68 crates at
40s/crate pacing (crates.io 30-per-10min window), verify `cargo install
aprender --version 0.31.2` actually installs this time.

Refs: task #64 (yank), #65 (fix), #66 (prevention)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@noahgift noahgift enabled auto-merge (squash) April 19, 2026 14:14
@noahgift noahgift merged commit 44f018e into main Apr 19, 2026
19 of 21 checks passed
@noahgift noahgift deleted the fix/publish-aprender-mcp-contracts branch April 19, 2026 15:05
noahgift added a commit that referenced this pull request Apr 19, 2026
Re-publish of v0.31.1 with the aprender-mcp publish fix (PR #910).
v0.31.1 was yanked because aprender-mcp/build.rs panicked on an
out-of-crate path at `cargo install` time. v0.31.2 ships with:

- aprender-mcp contract YAML bundled inside the crate tarball
- build.rs reads CARGO_MANIFEST_DIR/contracts/ (no `..` escape)
- drift-guard test + static check_build_rs_paths.sh in CI

Verified: `cargo package -p aprender-mcp` (which runs the same
unpack+compile verify as `cargo install`) completes cleanly on v0.31.2.
On v0.31.1 the same command failed with the documented build.rs panic.

Refs: task #67

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
noahgift added a commit that referenced this pull request Apr 19, 2026
Re-publish of v0.31.1 with the aprender-mcp publish fix (PR #910).
v0.31.1 was yanked because aprender-mcp/build.rs panicked on an
out-of-crate path at `cargo install` time. v0.31.2 ships with:

- aprender-mcp contract YAML bundled inside the crate tarball
- build.rs reads CARGO_MANIFEST_DIR/contracts/ (no `..` escape)
- drift-guard test + static check_build_rs_paths.sh in CI

Verified: `cargo package -p aprender-mcp` (which runs the same
unpack+compile verify as `cargo install`) completes cleanly on v0.31.2.
On v0.31.1 the same command failed with the documented build.rs panic.

Refs: task #67

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
noahgift added a commit that referenced this pull request Apr 19, 2026
CHANGELOG.md — add v0.31.2 entry documenting the v0.31.1 yank cycle,
the aprender-mcp bundle fix (PR #910), and the static Poka-Yoke
(scripts/check_build_rs_paths.sh) wired into CI.

CLAUDE.md — extend Publishing Safety section with the build.rs
path-escape class (sibling to CB-510 gitignore bug) and mandate the
post-publish install-verify + /dogfood cycle that v0.31.1 skipped.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.

1 participant