route_plan: translation_chain includes Device DNs (cti-audit-prompts/007)

cucx-docs's 007 empirically proved that route_translation_chain's
candidate filter `WHERE np.tkpatternusage IN (3, 5, 7)` excluded
Device DNs (tkpatternusage=2), which caused false-positive HIGH
findings on CTI-RP-to-CTI-RP failsafe chains — the typical CER
deployment shape.

The Bingham canary: 911-CTI-RP CFNA → 912 (DN of 912-CTI-RP) under
911CER-CSS. Direct numplan query against 911CER-PT returns 26 rows;
translation_chain reported `candidates_evaluated: 23`. The 3-row
gap is exactly the 3 Device DNs, excluded by the pre-fix filter
regardless of input number.

CUCM's runtime CFNA matcher includes Device DNs (otherwise no one
could dial 912 and reach the device). My tool's exclusion diverged
from production routing semantics. Result: every cluster using a
CTI-RP-to-CTI-RP failsafe pattern got at least one false-positive
HIGH finding on its first cti_failsafe_reachability run, wasting
operator investigation time on a phantom defect.

This commit broadens the candidate filter:

  - WHERE np.tkpatternusage IN (3, 5, 7)
  + WHERE np.tkpatternusage IN (2, 3, 5, 7)
                                ^
                              Device DN

Side effect: route_translation_chain now also surfaces Device DNs as
matches when called directly, which matches production routing
semantics. Existing callers benefit automatically.

The _note in the response now names the candidate set explicitly so
future readers don't have to dig into the SQL to know what's
included.

Updated comment block above the WHERE clause documents:
  - which tkpatternusage values are included and why
  - the empirical observation that motivated including Device DNs
  - cross-reference to cti-audit-prompts/007 for the smoking-gun
    candidates_evaluated:23-vs-26 evidence

Tests: +2 in TestDeviceDnInTranslationChainCandidates:

  - test_translation_chain_sql_includes_device_dn_usage: lock the
    SQL down so a future contributor can't re-narrow the filter to
    (3, 5, 7) and re-introduce the false-positive class
  - test_cti_rp_to_cti_rp_failsafe_does_not_false_positive: the
    Bingham canary scenario — 911-CTI-RP forwarding to a Device DN
    in a reachable partition correctly produces zero findings

The dispatch fake's SQL match-string updated from "(3, 5, 7)" to
"(2, 3, 5, 7)" to keep the existing 31 cti tests green; net
mcaxl suite: 269 → 271 passing.

Live re-run pending — will ping the agent thread with post-patch
output once the MCP server reloads.

Re-run expectations (per cucx-docs's 007):
  - 911-CTI-RP / 912 finding (CFNA + CFUR): GONE — Device DN matches
  - 912-CTI-RP / 10911 finding: UNCHANGED — Route pattern still
    unreachable (CER911-PT not in 911CER-CSS)
  - 913-CTI-RP / 60003 finding: UNCHANGED — destination doesn't
    exist anywhere

Findings: 6 → 4 (the 4 that actually matter).
This commit is contained in:
Ryan Malloy 2026-05-09 04:37:41 -06:00
parent 99986daa45
commit c995bc2712
2 changed files with 98 additions and 3 deletions

View File

@ -1750,7 +1750,23 @@ def translation_chain(client: "AxlClient", number: str, css_name: str | None = N
LEFT OUTER JOIN typepatternusage tpu ON np.tkpatternusage = tpu.enum
LEFT OUTER JOIN digitdiscardinstruction ddi ON np.fkdigitdiscardinstruction = ddi.pkid
LEFT OUTER JOIN routefilter rf ON np.fkroutefilter = rf.pkid
WHERE np.tkpatternusage IN (3, 5, 7)
# tkpatternusage candidates included in the match scan:
# 2 = Device (DN) — directly-dialable directory numbers
# 3 = Translation — translation patterns
# 5 = Route Pattern — outbound routing
# 7 = Hunt Pilot — hunt pilot pattern
#
# Device DNs are included because CUCM's runtime CFNA/CFUR matcher
# includes them — when a forward destination is a Device DN (e.g.
# the DN of another CTI Route Point in a CER failsafe chain), the
# runtime call succeeds via that DN. Excluding them caused
# `cti_failsafe_reachability` false-positive HIGH findings on
# CTI-RP-to-CTI-RP failsafe chains. cucx-docs verified empirically
# in agent-threads/cti-audit-prompts/007 that omitting Device DNs
# was the cause of the false-positive: candidates_evaluated stayed
# 23 vs 26 numplan rows in the reachable partition, with the 3-row
# gap being exactly the 3 Device DNs.
WHERE np.tkpatternusage IN (2, 3, 5, 7)
AND np.dnorpattern IS NOT NULL
{css_filter}
"""
@ -1772,6 +1788,8 @@ def translation_chain(client: "AxlClient", number: str, css_name: str | None = N
"match_count": len(matches),
"matches": matches,
"_note": (
"Candidate set: tkpatternusage 2 (Device DN), 3 (Translation), "
"5 (Route Pattern), 7 (Hunt Pilot). "
"Wildcards evaluated: X, !, [0-9], @, \\+. "
"@-pattern matches any digit string (route filter constraints not applied). "
"Longest-match-wins is approximated by pattern length; CUCM uses pattern "

View File

@ -60,8 +60,12 @@ class FakeAxlClient:
return {"row_count": len(self._cti_rows), "rows": self._cti_rows}
# Dispatch 2: translation_chain's reachability check
# Recognizable by `tkpatternusage IN (3, 5, 7)` from route_plan.py
if "tkpatternusage IN (3, 5, 7)" in sql:
# Recognizable by `tkpatternusage IN (2, 3, 5, 7)` from route_plan.py
# (tkpatternusage = 2 / Device DN was added 2026-05-09 after
# cucx-docs's empirical proof in cti-audit-prompts/007 that
# excluding Device DNs caused false-positive HIGH findings on
# CTI-RP-to-CTI-RP failsafe chains)
if "tkpatternusage IN (2, 3, 5, 7)" in sql:
for dest, css in self._reachable:
if f"name = '{css}'" in sql:
return {
@ -421,3 +425,76 @@ class TestDotStrippedFixSuggestion:
assert "Match-PT" in fix
assert "Nonmatch-PT" not in fix
assert "AnotherMatch-PT" not in fix
# ─── Device-DN inclusion in translation_chain (cti-audit-prompts/007) ──
#
# cucx-docs verified empirically in 007 that `route_translation_chain`'s
# candidate filter excluded Device DNs (tkpatternusage=2), which caused
# false-positive HIGH findings on CTI-RP-to-CTI-RP failsafe chains
# (typical CER pattern). The fix: include tkpatternusage=2 in the
# candidate set so Device DNs get checked alongside translation/route/
# hunt patterns.
#
# These tests pin the regression by:
# 1. Verifying the SQL emitted by translation_chain includes
# `tkpatternusage IN (2, 3, 5, 7)` literally
# 2. Demonstrating the cti audit doesn't false-positive on a CTI-RP-
# to-CTI-RP failsafe shape
class TestDeviceDnInTranslationChainCandidates:
def test_translation_chain_sql_includes_device_dn_usage(self):
"""Lock the candidate-filter SQL down so a future contributor
can't accidentally re-narrow it to (3, 5, 7) and re-introduce
the cti-audit-prompts/007 false-positive class.
"""
client = FakeAxlClient(cti_rp_rows=[
_cti_row("Test-RP", "Generic", cfna="912", cfna_css="SomeCSS"),
])
cti_failsafe_reachability(client)
# Find the translation_chain query in the captured SQL
chain_query = next(
q for q in client.queries
if "tkpatternusage IN" in q and "callingsearchspace" in q
)
assert "(2, 3, 5, 7)" in chain_query, (
"translation_chain candidate set must include tkpatternusage=2 "
"(Device DN). Excluding Device DNs causes false-positive HIGH "
"findings on CTI-RP-to-CTI-RP failsafe chains. See "
"agent-threads/cti-audit-prompts/007 for cucx-docs's "
"empirical proof."
)
def test_cti_rp_to_cti_rp_failsafe_does_not_false_positive(self):
"""The motivating Bingham case: 911-CTI-RP CFNA → 912 (Device DN
of 912-CTI-RP) under 911CER-CSS reaching 911CER-PT.
Pre-fix: cti_failsafe_reachability flagged this as HIGH because
translation_chain excluded the Device DN from its candidate set.
Post-fix: the Device DN '912' is in the candidate set under the
reachable partition, so the forward correctly resolves and no
finding is produced.
"""
# Simulate the fix's effect: the reachable_destinations set
# captures (912, 911CER-CSS) — meaning translation_chain returns
# match_count > 0 because the Device DN is now in the candidate
# set and gets matched against the dialed number.
client = FakeAxlClient(
cti_rp_rows=[
_cti_row(
"911-CTI-RP", "CTI RP for Primary CER Server",
cfna="912", cfna_css="911CER-CSS",
cfur="912", cfur_css="911CER-CSS",
),
],
reachable_destinations={
("912", "911CER-CSS"), # Device DN now reachable
},
)
result = cti_failsafe_reachability(client)
# No findings — the Tier-1 forward correctly resolves
assert result["broken_cfna"] == 0
assert result["broken_cfur"] == 0
assert result["findings"] == []