|
1 | 1 | # Changelog |
2 | 2 |
|
3 | | -## Unreleased — post-2.5.3 audit fixes (2026-05-19) |
| 3 | +## 2.5.4 - 2026-05-19 |
| 4 | + |
| 5 | +**v2.5.4 hardening release.** Closes the last open items from the |
| 6 | +2026-05-19 fresh-eyes audit + adds a CI gate that prevents the |
| 7 | +exact failure mode this release exists to fix (main carrying code |
| 8 | +changes past the latest tag with no version bump → two functionally |
| 9 | +different artifacts called "v2.5.3"). Tag-and-release follow-up to |
| 10 | +PR #53 (audit fixes, squash `6a9aabe`) + PR #54 (docs, squash |
| 11 | +`8068ae6`); all 13 version manifests now read `2.5.4` and both |
| 12 | +`.tox` files rebuilt against the v2.5.4 sources. |
| 13 | + |
| 14 | +### 🟠 High → CLOSED — C-1 part B: MCP-side Origin allowlist |
| 15 | + |
| 16 | +`td_component/callbacks/router.py` previously trusted `Sec-Fetch-Site` |
| 17 | +alone for browser-tab CSRF protection. PR-#53 fixed C-1 part A (auth |
| 18 | +default-secure in `autostart.py`); this release adds the matching |
| 19 | +Origin-header check to the MCP router. Foreign-origin browser tabs |
| 20 | +(e.g. ``https://attacker.example.com``) are now rejected with `403` |
| 21 | +before any handler runs. Empty / missing Origin is still accepted so |
| 22 | +non-browser MCP clients (curl, `npx tdpilot-dpsk4`, custom MCP |
| 23 | +integrations) keep working. |
| 24 | + |
| 25 | +`_is_origin_allowed` helper lives in `callbacks/_header.py`; mirrors |
| 26 | +the chat-pipe-side `tdpilot_api_web_callbacks._allowed_origin` |
| 27 | +contract. 6 unit tests in `tests/test_v254_callbacks_origin_redact.py`. |
| 28 | + |
| 29 | +### 🟡 Medium → CLOSED — M-1: Traceback redaction in 500 responses |
| 30 | + |
| 31 | +`router.py`'s 500-error path returned `traceback.format_exc()` verbatim, |
| 32 | +leaking `$HOME` paths and TDPilot config-dir locations to anyone hitting |
| 33 | +an error route. Post-fix the traceback runs through `_redact_paths` |
| 34 | +before serialization — `/Users/<user>/…` becomes `~/…`, |
| 35 | +`~/.tdpilot-dpsk4/…` becomes `<TDPILOT_DPSK4_HOME>/…`. Mirrors the |
| 36 | +chat-pipe-side `tdpilot_api_config.redact_paths`. 7 unit tests pinning |
| 37 | +each redaction rule + edge cases (non-string input, empty string, |
| 38 | +config-dirs-win-over-bare-home ordering). |
| 39 | + |
| 40 | +### 🟡 Medium → CLOSED — N-1: First-run UX hint for default-secure MCP |
| 41 | + |
| 42 | +`autostart._disable_auth` now prints a clear Textport diagnostic on |
| 43 | +COMP load when the user lands in default-secure mode AND no |
| 44 | +`TD_MCP_SHARED_SECRET` is installed. Pre-fix, fresh installs without |
| 45 | +the env file got silent `401`s on every MCP request with no obvious |
| 46 | +remediation. New diagnostic spells out the two paths: |
| 47 | + |
| 48 | + (a) run the chat-pipe Authmode wizard to install a secret, OR |
| 49 | + (b) set `TDPILOT_ENABLE_AUTH_BYPASS=1` for legacy zero-config dev. |
| 50 | + |
| 51 | +4 new tests in `tests/test_v212_autostart_opt_in_auth.py` pin |
| 52 | +hint-fires + hint-doesn't-fire conditions (27 tests total there). |
| 53 | + |
| 54 | +### 🧪 Testing — H-1 regression coverage closed (security agent N-2 finding) |
| 55 | + |
| 56 | +PR-#53's H-1 fix in `td_component/tdpilot_api_patches.py:_find_scoped_manifest` |
| 57 | +shipped correct but with **zero regression tests**. v2.5.4 adds |
| 58 | +`tests/test_h1_snapshot_path_sandbox.py` — 8 tests covering the |
| 59 | +absolute-path-outside-SNAPSHOTS_DIR refusal, `/etc/passwd`-style attack, |
| 60 | +symlink-bypass attempt (resolve-before-check), and the slug-fallback |
| 61 | +preservation. A future refactor of `_find_scoped_manifest` can no |
| 62 | +longer silently re-introduce the path traversal. |
| 63 | + |
| 64 | +### 🧪 Testing — Cross-runtime schema parity (architecture agent's NEW finding) |
| 65 | + |
| 66 | +`tests/test_chat_pipe_surface_parity.py` (added in PR-#53) pins |
| 67 | +schema↔handler parity *within* `td_component/`. v2.5.4 adds |
| 68 | +`tests/test_cross_runtime_schema_parity.py` (4 tests) which extends |
| 69 | +the contract to *between* `td_component/tdpilot_api_schema_defs.py` |
| 70 | +(chat-pipe) and `src/td_mcp/`'s `@mcp.tool` registry (MCP server). |
| 71 | + |
| 72 | +The architecture diverges intentionally (chat-pipe is a curated 95-tool |
| 73 | +subset of MCP's 109+) but the test snapshots the legitimate asymmetry |
| 74 | +as two frozen sets (`CHAT_PIPE_ONLY_BASELINE`, `MCP_ONLY_BASELINE`). |
| 75 | +Any drift from the snapshot fails CI and forces a code-review decision |
| 76 | +— catching the v2.5.1-class regression at the cross-runtime layer the |
| 77 | +within-`td_component/` parity test can't see. |
| 78 | + |
| 79 | +### 🧪 Testing — Mock-eval scenarios scaffolded for cycle-detect / rollback / alias |
| 80 | + |
| 81 | +`tests/agent_evals_mock/test_cycle_detect_mock.py` adds 3 |
| 82 | +scenarios — `cycle_detect_three_strikes`, `cycle_detect_rollback_hint`, |
| 83 | +`alias_dispatch_td_get_traces` — as the recommended end-to-end |
| 84 | +behavioral pin for the v2.5.1/2/3 patch cascade (per |
| 85 | +`docs/plans/AUDIT_2026_05_19_FOLLOWUPS.md` § C). Marked |
| 86 | +`@pytest.mark.skip` pending fixture capture against the live DeepSeek |
| 87 | +API; module docstring documents the 3-step capture ritual. Unit-level |
| 88 | +coverage of the same bugs is already comprehensive |
| 89 | +(`test_v252_cycle_detect_orphan_tool_use.py` + the cycle-detector + |
| 90 | +rollback unit suites). |
| 91 | + |
| 92 | +### 🛡 CI — Tag-freshness gate (closes the v2.5.3 → v2.5.4 failure mode itself) |
| 93 | + |
| 94 | +New `.github/workflows/ci.yml` step "Tag-freshness gate (main only)" |
| 95 | +fails any `main` push where executable code (non-doc / non-test / |
| 96 | +non-skills) has changed since the latest semver tag AND the version |
| 97 | +files still read that same tag. PR-#53 + PR-#54 demonstrated this gap |
| 98 | +exists; the new gate prevents recurrence. Escape hatch: |
| 99 | +`[skip-version-check]` in the commit message (intended for genuine |
| 100 | +"Unreleased" land-on-main flows). |
| 101 | + |
| 102 | +### 📦 Versioning — All 13 manifests now read 2.5.4 |
| 103 | + |
| 104 | +The audit found `scripts/check_versions.py` enforces drift across |
| 105 | +**13 files**, not the 7 documented in CLAUDE.md memory: |
| 106 | +`pyproject.toml`, `src/td_mcp/__init__.py`, `.claude-plugin/plugin.json`, |
| 107 | +`.claude-plugin/marketplace.json`, `npm/package.json`, `mcp/manifest.json`, |
| 108 | +`td_component/callbacks/_header.py::API_VERSION`, `README.md`, |
| 109 | +`plugin_README.md`, `npm/README.md`, `docs/MANUAL.md`, |
| 110 | +`skills/tdpilot-dpsk4-core/SKILL.md`, |
| 111 | +`skills/tdpilot-dpsk4-production/SKILL.md`. All 13 now at v2.5.4. |
4 | 112 |
|
5 | | -> Pending a `v2.5.4` tag. Bundled as PR [#53](https://github.com/dreamrec/TDPilot_deepseekv4/pull/53), squash-merged as `6a9aabe`. All 7 CI gates green (lint + 3 Python versions + 2 install-parses + both `.tox` freshness checks). The seven version manifests still read `2.5.3`; bumping them to `2.5.4` is a separate ritual that requires another `.tox` rebuild. |
| 113 | +### 🛠 `.tox` rebuild |
| 114 | + |
| 115 | +Both `.tox` files rebuilt inside TouchDesigner 2025.32820 against the |
| 116 | +v2.5.4 sources (API_VERSION bump + callbacks/ edits + autostart.py |
| 117 | +N-1 hint). The v1.8.2 byte-equivalence baseline at |
| 118 | +`tests/fixtures/mcp_webserver_callbacks_v1.8.2_baseline.py` was |
| 119 | +regenerated to absorb the router.py + _header.py changes. |
| 120 | + |
| 121 | +### Test totals |
| 122 | + |
| 123 | +Full suite: 2141 → **2188 passing** (+47, +0 regressions; 4 skipped: |
| 124 | +1 paddleocr-needed E2E + 3 mock-eval scenarios pending fixture capture). |
| 125 | + |
| 126 | +### Carried forward from PR #53 (the originally-"Unreleased" audit findings now under v2.5.4) |
| 127 | + |
| 128 | +The following items merged to `main` via PR #53 (squash `6a9aabe`) as |
| 129 | +the "Unreleased" state; this v2.5.4 entry formally records them under |
| 130 | +a version tag so npm + GH-release + marketplace all advertise the |
| 131 | +correct hardened build. See PR #53 description + the original |
| 132 | +unreleased CHANGELOG draft for the full per-finding narrative; |
| 133 | +recap below. |
6 | 134 |
|
7 | 135 | ### 🔴 Breaking — C-1: MCP webserverDAT auth is now SECURE BY DEFAULT |
8 | 136 |
|
|
0 commit comments