diff --git a/CHANGELOG.md b/CHANGELOG.md index cab9e78..c8b9c2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,37 @@ encode the date the package was tested against the upstream Cisco APIs and published. Format: `YYYY.MM.DD` with optional `.N` post-release suffix for same-day fixes. -## 2026.04.27 — initial public release +## 2026.04.27.1 — same-day PII scrub + +Post-release fix per the python.md immutability rule. The original +`2026.04.27` was published-then-deleted from PyPI after a stricter +audit found cluster-fingerprint content in the shipped sdist that the +pre-publish audit had missed: + +- `docs/query-patterns/sip-trunk-report.md` contained a "Live result + snapshot" section with the test cluster's actual SIP trunk inventory + (real hostnames, real internal IPs). The query-pattern doc itself + still ships; the snapshot section has been removed and one inline + FQDN example replaced with `.example.com`. +- `.mcp.json` was shipping in the sdist with a local filesystem path. + Added to `[tool.hatch.build.targets.sdist] exclude`. The file + remains in the source repo for development; it no longer ships. + +Lesson encoded for next time: **the pre-publish PII audit must run +against the unpacked sdist, not just curated source paths.** The +sdist also pulls in `docs/`, top-level dotfiles like `.mcp.json`, and +`uv.lock`. The python.md rule's example grep covers fewer paths than +the actual sdist blast surface; the durable fix is `tar -xzf +dist/*.tar.gz -C /tmp/inspect && grep -rnE 'site-token' /tmp/inspect` +before every publish. + +No functional changes between 2026.04.27 and 2026.04.27.1 — just +metadata and shipped-doc content. + +## 2026.04.27 — initial public release (deleted) + +> Yanked-and-deleted from PyPI on the publish date due to a sdist +> PII leak. Superseded by `2026.04.27.1`. Retained here as a marker. First public release on PyPI as `mcaxl`. Renamed from the internal working name `mcp-cucm-axl` to fit the operator's `mc` diff --git a/docs/query-patterns/sip-trunk-report.md b/docs/query-patterns/sip-trunk-report.md index 789eaa5..7c6ae91 100644 --- a/docs/query-patterns/sip-trunk-report.md +++ b/docs/query-patterns/sip-trunk-report.md @@ -6,7 +6,7 @@ route-group/route-list membership. Useful for handoff documentation, post-migration cleanup, and identifying single-points-of-failure on specific trunks. -**Status:** Validated against CUCM 15.0.1.12900-234 on 2026-04-25. +**Status:** Validated against CUCM 15. Empty `prompts/` directory at `src/mcaxl/prompts/` is the intended home for extracting this into a `@mcp.prompt` function. For now, prompts live inline in `server.py` (see `route_plan_overview`, @@ -111,7 +111,7 @@ ORDER BY d.name, std.sortorder; **Notes:** - `address` is `VARCHAR(255)` — IP literal *or* DNS name. Expressway-C - trunks often use FQDNs (e.g., `exp-c-p.binghammemorial.org`) so SRV + trunks often use FQDNs (e.g., `exp-c-p.example.com`) so SRV resolution can shift the actual destination. - `addressipv6` exists on the same table but is empty on most clusters. - `port` is `INTEGER` — defaults to 5060 (SIP over UDP/TCP) or 5061 (TLS), @@ -203,43 +203,6 @@ LLM to surface: --- -## Live result snapshot (Bingham, 2026-04-25) - -11 SIP trunks. All on `Main-Campus-Sub1-Pub-DP` except `exp-c-p-SIP-Trk` -(on `Pub-Sub1-DP`). All preferred codec is `711ulaw`. All destinations -on port 5060 (no TLS). - -| Trunk | Destination | SIP Profile | CSS | Location | -|---|---|---|---|---| -| `Forward-Advantage-SIP-Trk` | 172.24.10.10 | FWD Advantage SIP Profile | National-CSS | Main-Campus-LOC | -| `PSTN-Router-SIP-Trk` | 172.20.6.222 | PSTN Sparklite SIP Profile | PSTN-Inbound-CSS | Hub_None | -| `RightFax-SIP-TRK` | 172.20.2.22 | RightFax SIP Profile | FAX-CSS | Hub_None | -| `Unity-Pub-SIP-TRK` | 172.20.6.104 | Unity SIP Profile | Internal-CSS | Main-Campus-LOC | -| `Unity-Sub-SIP-TRK` | 172.20.6.105 | Unity SIP Profile | Internal-CSS | Main-Campus-LOC | -| `VG450-SIP-TRK` | 172.20.6.99 | RightFax SIP Profile | National-CSS | Hub_None | -| `Verba-SIP-TRK` | 172.20.6.120 | Verba Profile | Internal-CSS | Hub_None | -| `ZetaFax-SIP-TRK` | 172.20.14.105 | ZetaFax SIP Profile | FAX-CSS | Hub_None | -| `exp-c-p-SIP-Trk` | exp-c-p.binghammemorial.org | Expressway SIP Profile | (none) | Main-Campus-LOC | -| `exp-c-s-SIP-Trk` | exp-c-s.binghammemorial.org | Expressway SIP Profile | (none) | Main-Campus-LOC | -| `singlewireFusion-SIP-TRK` | 172.20.6.114 | singlewire SIP Profile | (none) | Hub_None | - -**Observations from this snapshot** (templates for what the prompt should -flag): - -- `VG450-SIP-TRK` (analog voice gateway) shares the `RightFax SIP Profile` - with `RightFax-SIP-TRK` — *probably intentional* (both terminate at fax - endpoints) but worth confirming with the operator. -- The 3 trunks with `calling_search_space = NULL` (Expressway-C primary, - Expressway-C secondary, singlewireFusion) all serve specific - device-only paths — they don't originate generic outbound routing. Not - a finding, but a useful invariant to call out. -- `PSTN-Router-SIP-Trk` is the only trunk with `Hub_None` location *and* - `PSTN-Inbound-CSS` *and* a stripped-down CSS — consistent with its role - as the carrier-facing trunk (and as the H1 SPOF in the - [route-plan audit](../../../docs/src/content/docs/audits/2026-04-25-cucm-route-plan.mdx)). - ---- - ## Proposed prompt name and signature ```python diff --git a/pyproject.toml b/pyproject.toml index 9a0e0ff..eadb340 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "mcaxl" -version = "2026.04.27" +version = "2026.04.27.1" description = "Read-only MCP server for Cisco Unified Communications Manager (CUCM) — AXL SOAP API + RisPort70 registration state — purpose-built for LLM-driven dial-plan and configuration auditing." authors = [{name = "Ryan Malloy", email = "ryan@supported.systems"}] readme = "README.md" @@ -58,13 +58,21 @@ packages = ["src/mcaxl"] [tool.hatch.build.targets.sdist] # Keep the published source distribution focused on what's needed to # build / install / run. Excluded files exist for local development only. +# +# IMPORTANT: this list is the last line of defense for PII leakage. +# `tests/` contains real cluster fixtures; `.mcp.json` contains a +# local filesystem path; `audits/` contains cluster-specific findings. +# Pre-publish workflow: extract the sdist to /tmp and grep for any +# site-specific tokens (your org name, internal IP ranges, hostnames) +# across the full unpacked tree — MUST return empty before publish. exclude = [ - "CLAUDE.md", # operator-private project context for Claude Code - ".env", # never ship credentials + "CLAUDE.md", # operator-private project context for Claude Code + ".env", # never ship credentials ".env.local", + ".mcp.json", # contains local filesystem path; dev-only artifact "axlsqltoolkit.zip", # Cisco-licensed; do not redistribute - "audits/", # cluster-specific audit reports - "tests/", # tests live in source repo, not the sdist + "audits/", # cluster-specific audit reports + "tests/", # tests live in source repo, not the sdist ".pytest_cache/", ".ruff_cache/", "dist/",