mcaxl/CHANGELOG.md
Ryan Malloy 0691ba8c46 2026.04.27.1: same-day post-release PII scrub
The original 2026.04.27 was published-then-deleted from PyPI within
hours after a stricter audit (against the unpacked sdist, not just
curated source paths) found cluster-fingerprint content that the
pre-publish grep had missed. This release supersedes the deleted one;
no functional differences.

Issues found in 2026.04.27 that this fixes:

1. docs/query-patterns/sip-trunk-report.md — "Live result snapshot"
   section (38 lines) contained the live cluster's actual SIP trunk
   inventory: real hostnames (exp-c-p.binghammemorial.org), real
   internal IPs (172.20.6.99, .104, .105, .114, .120, .222, plus
   172.20.2.22, 172.20.14.105, 172.24.10.10), real trunk-name +
   description rows. Section removed entirely. The query-pattern doc
   itself still ships — schema/SQL guidance is generic and useful.
   One inline FQDN example (`exp-c-p.binghammemorial.org`) replaced
   with `exp-c-p.example.com`. Status line that named the specific
   maintenance release (`Validated against CUCM 15.0.1.12900-234 on
   2026-04-25.`) genericized to `Validated against CUCM 15.`

2. .mcp.json shipping in sdist with `/home/rpm/bingham/axl` as the
   `--directory` argument. Local filesystem path = hostname leak.
   Added to `[tool.hatch.build.targets.sdist] exclude`. File stays
   in the source repo for development; no longer ships.

3. pyproject.toml comment about the audit workflow ironically
   contained the literal word "bingham" as the example grep token.
   Rewritten to use "site-specific tokens" generically.

Audit verification (against the unpacked sdist this time):
  tar -xzf dist/mcaxl-2026.4.27.1.tar.gz -C /tmp/sdist-inspect
  grep -rnEi 'bingham|binghammemorial|10\.[0-9]+\.[0-9]+\.[0-9]+|
              172\.(1[6-9]|2[0-9]|3[01])\.[0-9]+\.[0-9]+|
              192\.168\.[0-9]+\.[0-9]+|SupportedSystems|CCX-AXL|
              CER-AXL|CUC-AXL|TabSync|variphy|15\.0\.1\.12900|
              production cluster|/home/rpm|cucm-pub\.bingham'
       /tmp/sdist-inspect/
  → returns empty (verified)

Tests still 155/155.

Lesson encoded for next time: the pre-publish audit MUST run against
the unpacked sdist, not just the four explicitly-named paths in the
python.md rule (src/, tests/, README.md, pyproject.toml, .env.example).
The sdist also pulls in docs/, top-level dotfiles, and uv.lock.
CHANGELOG.md spells this out in the post-release note for next time.
2026-04-27 13:07:38 -06:00

4.1 KiB

Changelog

This project uses CalVer — version numbers 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.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<interface> naming convention.

Tools (19 total)

Foundational: axl_version, axl_sql, axl_list_tables, axl_describe_table, cache_stats, cache_clear, health.

Route plan: route_partitions, route_calling_search_spaces, route_patterns, route_inspect_pattern, route_lists_and_groups, route_translation_chain, route_digit_discard_instructions, route_device_pool_route_groups, route_devices_using_css, route_filters.

Real-time registration (RisPort70): device_registration_status, device_registration_summary.

Prompts (10 total)

Schema-grounded conversation seeds: route_plan_overview, investigate_pattern, audit_routing, cucm_sql_help, sip_trunk_report, phone_inventory_report, user_audit, inbound_did_audit, hunt_pilot_audit, whoami.

Engineering rigor

  • Read-only by structural guarantee: no AXL write methods are registered; the SQL validator rejects non-SELECT/WITH queries as defense-in-depth.
  • Hamilton-style review closed: 7 findings (2 Critical, 3 Major, 2 Minor) addressed during pre-release hardening, each with a regression test.
  • Live-cluster verified: every tool path verified against a live CUCM 15 cluster before release.
  • 155 unit tests, schema drift guard for all 71 known fkcallingsearchspace_* columns (via test_complete_schema_coverage_against_known_columns).

Known limitations

  • route_translation_chain evaluates CUCM wildcards (X, !, [0-9], @, \\+) but does not model route-filter constraints on @ patterns — use as guidance, not authoritative.
  • AXL WSDL must be supplied externally (Cisco-licensed; not bundled). See README.md for bootstrap instructions.
  • RisPort state_info cursor pagination is implemented but not yet stress-tested on clusters with > 1000 devices in a single class.

Acknowledgments

Borrowed two ideas from @calltelemetry/cisco-cucm-mcp (MIT licensed): the RisPort70 SOAP envelope shape and the exponential-backoff retry policy on HTTP 503. Their tool covers operational debugging (logs, perfmon, packet capture) — install both side-by-side for compound questions like "audit found CSS X unreferenced AND RisPort confirms zero phones registered against it."