Add terminate-only STIR/SHAKEN option across RMD pipeline

STIRShakenStep intake:
- New "Terminate only" option for carriers that only receive pre-signed
  calls and don't originate
- Contextual hints for each option explaining requirements
- Show/hide vendor and upstream fields based on selection

RMD letter generator:
- New terminate_only section explaining verification-only posture,
  citing 47 CFR § 64.6301 (signing obligation on originating provider)
- Added to needs_exhibit_a list

RMD Exhibit A generator:
- New terminate_only STIR/SHAKEN paragraph with SBC verification language
- Fixed scope paragraph: wholesale/facilities carriers no longer get
  "small provider without Class 4 switch" boilerplate
- Fixed OCN paragraph: wholesale carriers get neutral wording instead
  of "no OCN required for small retail provider"

RMD filing handler:
- Maps stir_shaken_status to rmd_option for Exhibit A generation
- Passes entity metadata (ocn, wholesale, gateway, contact) to generator
- Maps terminate_only → partial_implementation for FCC RMD form radio

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
justin 2026-04-29 10:59:28 -05:00
parent 050b19a43a
commit fbf3b8a1ea
4 changed files with 123 additions and 17 deletions

View file

@ -138,6 +138,25 @@ def _stir_shaken_paragraph(
f"high-volume origination, or facilities-based IP origination "
f"infrastructure."
)
elif option == "terminate_only":
paras.append(
f"{entity_name} operates as a terminating provider and does not "
f"originate calls onto the public switched telephone network. "
f"{entity_abbr} receives exclusively pre-authenticated traffic "
f"from originating and intermediate providers. As a "
f"terminating-only carrier, {entity_abbr} is not required to "
f"maintain its own STI certificate or SPC token for call signing."
)
paras.append(
f"{entity_abbr} verifies STIR/SHAKEN attestation information on "
f"all inbound SIP INVITE messages using standard verification "
f"service (VS) functionality configured on its session border "
f"controllers. {entity_abbr} certifies partial STIR/SHAKEN "
f"implementation (Option 2 in the RMD) reflecting its "
f"verification-only posture. Per FCC rules, the obligation to "
f"sign calls falls on the originating provider, not the "
f"terminating provider."
)
elif option == "option3":
paras.append(
f"{entity_name} certifies no STIR/SHAKEN signing implementation "
@ -203,12 +222,18 @@ def _scope_paragraph(
f"{entity_abbr} does not accept foreign-originated traffic and "
f"operates solely with domestic U.S. NANP resources."
)
parts.append(
f"As a small provider without its own Class 4 switch or outbound "
f"origination platform, {entity_abbr} relies on trusted underlying "
f"carriers for DID origination, call termination, and STIR/SHAKEN "
f"attestation/signing where applicable."
)
if is_wholesale or carrier_role in ("wholesale_domestic", "gateway", "facilities"):
parts.append(
f"{entity_abbr} operates its own network infrastructure for "
f"voice service delivery."
)
else:
parts.append(
f"As a small provider without its own Class 4 switch or outbound "
f"origination platform, {entity_abbr} relies on trusted underlying "
f"carriers for DID origination, call termination, and STIR/SHAKEN "
f"attestation/signing where applicable."
)
parts.append(
f"This Robocall Mitigation Plan outlines {entity_abbr}'s measures to "
f"detect, prevent, and mitigate unlawful robocalls in compliance "
@ -382,12 +407,18 @@ def generate_exhibit_a(
if ocn:
_add_body(doc, f"OCN: {ocn}")
else:
_add_body(doc, (
f"{entity_abbr} does not possess an Operating Company Number "
f"(OCN). Per FCC guidance, no OCN is required for a small "
f"retail provider without local exchange carrier status; "
f"\"No\" is selected on the RMD form."
))
if is_wholesale or carrier_role in ("wholesale_domestic", "gateway"):
_add_body(doc, (
f"{entity_abbr} does not currently possess an Operating "
f"Company Number (OCN). \"No\" is selected on the RMD form."
))
else:
_add_body(doc, (
f"{entity_abbr} does not possess an Operating Company Number "
f"(OCN). Per FCC guidance, no OCN is required for a small "
f"retail provider without local exchange carrier status; "
f"\"No\" is selected on the RMD form."
))
_add_body(doc, "Principals, Affiliates, Subsidiaries, and Parent Companies:", bold=True)
_add_bullets(doc, principals or [f"{contact_name or entity_name} (sole principal)"])

View file

@ -463,6 +463,7 @@ def generate_rmd_letter(
needs_exhibit_a = stir_shaken_status in (
"partial_implementation",
"terminate_only",
"robocall_mitigation_only",
"exempt_small_carrier",
)
@ -1071,6 +1072,24 @@ def _build_stir_shaken_section(
italic=True,
)
elif stir_shaken_status == "terminate_only":
b.body(
f"{entity_name} operates exclusively as a terminating provider "
f"and does not originate calls onto the public switched telephone "
f"network. {entity_name} receives pre-authenticated traffic from "
f"originating and intermediate providers and verifies STIR/SHAKEN "
f"attestation information on all inbound SIP INVITE messages."
)
b.body(
f"As a terminating-only carrier, {entity_name} is not required to "
f"maintain its own STI certificate or SPC token for call signing. "
f"Per FCC rules (47 CFR § 64.6301), the obligation to sign calls "
f"falls on the originating provider, not the terminating provider. "
f"{entity_name} certifies partial STIR/SHAKEN implementation "
f"(reflecting its verification-only posture) and has implemented "
f"a robocall mitigation program as described in Exhibit A."
)
elif stir_shaken_status == "robocall_mitigation_only":
b.body(
f"{entity_name} has not implemented STIR/SHAKEN caller ID "

View file

@ -299,6 +299,7 @@ class RMDFilingHandler(BaseServiceHandler):
stir_status = entity.get("stir_shaken_status", "complete_implementation")
if stir_status in (
"partial_implementation",
"terminate_only",
"robocall_mitigation_only",
"exempt_small_carrier",
):
@ -317,12 +318,30 @@ class RMDFilingHandler(BaseServiceHandler):
work_dir,
f"robocall_mitigation_program_{order_number}_{date_str}.docx",
)
# Map stir_shaken_status to Exhibit A rmd_option
_STATUS_TO_OPTION = {
"complete_implementation": "option1",
"partial_implementation": "option2",
"terminate_only": "terminate_only",
"robocall_mitigation_only": "option3",
"exempt_small_carrier": "option3",
}
exhibit = generate_exhibit_a(
entity_name=entity.get("legal_name", ""),
frn=entity.get("frn", ""),
ocn=entity.get("ocn", ""),
carrier_role=role,
carrier_metadata=entity.get("carrier_metadata", {}),
upstream_provider_name=entity.get("upstream_provider_name", ""),
is_wholesale=entity.get("is_wholesale", False),
is_gateway=entity.get("is_gateway_provider", False),
foreign_traffic=entity.get("is_international_only", False),
rmd_option=_STATUS_TO_OPTION.get(stir_status, "option2"),
contact_name=entity.get("contact_name", ""),
contact_title=entity.get("contact_title", ""),
contact_email=entity.get("contact_email", ""),
contact_phone=entity.get("contact_phone", ""),
address=entity.get("address", ""),
llm_generate=self._call_llm,
output_path=exhibit_docx,
)
@ -422,8 +441,11 @@ class RMDFilingHandler(BaseServiceHandler):
)
# STIR/SHAKEN implementation status — value must match the
# RMD form radio options.
# RMD form radio options. terminate_only maps to
# partial_implementation on the FCC form (verification-only).
stir_status = entity.get("stir_shaken_status", "complete_implementation")
if stir_status == "terminate_only":
stir_status = "partial_implementation"
await page.click(f'input[name="stir_shaken_status"][value="{stir_status}"]')
await human_delay()