Includes: API (Express/TypeScript), Astro site, Python workers, document generators, FCC compliance tools, Canada CRTC formation, Ansible infrastructure, and deployment scripts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
602 lines
27 KiB
Python
602 lines
27 KiB
Python
"""
|
|
Generate the Robocall Mitigation Plan (Exhibit A to RMD filing).
|
|
|
|
Follows the Performance West canonical 7-section outline observed across
|
|
all example filings in docs/examplefilings/ (Engage, Franklin, Zingo,
|
|
Syntracom, VoIPFlo, Fortel). This is a deterministic, template-driven
|
|
generator — no LLM — with role-specific paragraphs for each carrier
|
|
category.
|
|
|
|
2026 Updates (2025 RMD R&O effective Feb 5, 2026):
|
|
* References recertification due March 2, 2026 (March 1 is Sunday)
|
|
* Multi-factor authentication on RMD portal
|
|
* $10,000 false-info forfeiture and $1,000/day late-update forfeiture
|
|
* 10-business-day material-change update deadline
|
|
* Explicit DNO list blocking + 4-hour high-risk alert review SLA
|
|
* Penalty-of-perjury declaration at the end
|
|
|
|
Canonical section outline (mirrors docs/examplefilings/):
|
|
|
|
Introduction (scope narrative)
|
|
1. Contact Information (+ Principals/Affiliates, past-2-years affirmation)
|
|
2. Implementation of STIR/SHAKEN Framework (Option 1/2/3, named upstream)
|
|
3. Robocall Monitoring and Mitigation
|
|
3.5 Know Your Customer (KYC) Procedures (Performed In-House)
|
|
4. Call Analytics and Upstream Provider Procedures
|
|
5. Compliance with FCC Requirements
|
|
6. Future Enhancements
|
|
7. Commitment to Correct Deficiencies
|
|
Conclusion
|
|
Perjury declaration + signature block
|
|
|
|
Usage:
|
|
from scripts.document_gen.templates.rmd_exhibit_a_generator import (
|
|
generate_exhibit_a,
|
|
)
|
|
path = generate_exhibit_a(
|
|
entity_name="Falcon Broadband LLC",
|
|
entity_abbr="FBL",
|
|
frn="0027160886",
|
|
address="123 Example St, City, ST 00000",
|
|
contact_name="Jane Doe",
|
|
contact_title="President",
|
|
contact_email="jane@falconbroadband.com",
|
|
contact_phone="555-123-4567",
|
|
principals=["Jane Doe"],
|
|
carrier_role="ucaas",
|
|
upstream_provider_name="VoIP Innovations",
|
|
rmd_option="option2", # "option1" | "option2" | "option3"
|
|
scope_narrative="small UCaaS provider serving retail end-users",
|
|
output_path="/tmp/rmd_plan.docx",
|
|
)
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
from typing import Awaitable, Callable, Optional
|
|
|
|
LOG = logging.getLogger("document_gen.rmd_exhibit_a")
|
|
|
|
try:
|
|
from docx import Document
|
|
from docx.shared import Pt, Inches, RGBColor
|
|
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
|
from docx.oxml.ns import qn
|
|
from docx.oxml import OxmlElement
|
|
except ImportError:
|
|
LOG.warning("python-docx not installed — RMD plan generation unavailable")
|
|
Document = None # type: ignore[assignment, misc]
|
|
|
|
NAVY_BLUE = RGBColor(0x1A, 0x27, 0x44) if Document else None
|
|
HEADING_SIZE = Pt(12)
|
|
BODY_SIZE = Pt(10)
|
|
PARA_SPACING_AFTER = Pt(6)
|
|
|
|
|
|
# ── RMD option labels per FCC 2025 R&O ────────────────────────────────────
|
|
# Option 1: complete STIR/SHAKEN implementation
|
|
# Option 2: partial STIR/SHAKEN — IP portions only, relying on upstream
|
|
# Option 3: robocall-mitigation-only (no STIR/SHAKEN signing at all)
|
|
RMD_OPTION_LABELS = {
|
|
"option1": "Option 1 — Complete STIR/SHAKEN Implementation",
|
|
"option2": "Option 2 — Partial STIR/SHAKEN Implementation",
|
|
"option3": "Option 3 — Robocall Mitigation Only (no STIR/SHAKEN signing)",
|
|
}
|
|
|
|
|
|
# ── Role-specific STIR/SHAKEN language ────────────────────────────────────
|
|
|
|
|
|
def _stir_shaken_paragraph(
|
|
*,
|
|
entity_name: str,
|
|
entity_abbr: str,
|
|
rmd_option: str,
|
|
upstream_provider_name: str,
|
|
carrier_role: str,
|
|
ocn: str,
|
|
) -> list[str]:
|
|
"""Return a list of paragraphs describing STIR/SHAKEN implementation."""
|
|
option = rmd_option.lower()
|
|
upstream = upstream_provider_name or "its underlying carrier"
|
|
|
|
paras: list[str] = []
|
|
|
|
if option == "option1":
|
|
paras.append(
|
|
f"{entity_name} complies with the STIR/SHAKEN call authentication "
|
|
f"framework and signs all outbound calls originated from its "
|
|
f"network using its own STI certificate. {entity_abbr} certifies "
|
|
f"complete STIR/SHAKEN implementation (Option 1 in the RMD)."
|
|
)
|
|
if ocn:
|
|
paras.append(
|
|
f"All calls are attested at level A, B, or C as appropriate "
|
|
f"using {entity_abbr}'s OCN {ocn} under its STI-CA-issued "
|
|
f"certificate."
|
|
)
|
|
elif option == "option2":
|
|
paras.append(
|
|
f"{entity_name} complies with FCC STIR/SHAKEN caller authentication "
|
|
f"requirements through its partnership with {upstream}. This "
|
|
f"partnership ensures that all outbound calls are attested under "
|
|
f"the STIR/SHAKEN framework; calls originating from the network "
|
|
f"are validated to verify caller identity and detect spoofed "
|
|
f"calls."
|
|
)
|
|
paras.append(
|
|
f"{entity_abbr} certifies partial STIR/SHAKEN implementation "
|
|
f"(Option 2 in the RMD) for IP portions of the network, relying "
|
|
f"on {upstream} for technical attestation/signing. {entity_abbr} "
|
|
f"makes all attestation-level decisions based on verified customer "
|
|
f"right-to-use of DIDs and provides this information to the "
|
|
f"upstream carrier for signing. {entity_abbr} does not maintain "
|
|
f"its own SPC token or certificate, as this is unnecessary and "
|
|
f"disproportionate for a small provider without wholesale, "
|
|
f"high-volume origination, or facilities-based IP origination "
|
|
f"infrastructure."
|
|
)
|
|
elif option == "option3":
|
|
paras.append(
|
|
f"{entity_name} certifies no STIR/SHAKEN signing implementation "
|
|
f"(Option 3 in the RMD). {entity_abbr} does not originate "
|
|
f"outbound calls that require its own STIR/SHAKEN signing and "
|
|
f"does not maintain an SPC token or certificate. Inbound call "
|
|
f"authentication is verified using STIR/SHAKEN attestation "
|
|
f"results provided by upstream carriers."
|
|
)
|
|
else:
|
|
paras.append(
|
|
f"{entity_name} complies with FCC STIR/SHAKEN requirements in "
|
|
f"accordance with its filing option on the Robocall Mitigation "
|
|
f"Database."
|
|
)
|
|
|
|
paras.append(
|
|
f"{entity_abbr} confirms that no previous certification has been "
|
|
f"removed by Commission action."
|
|
)
|
|
return paras
|
|
|
|
|
|
# ── Role-specific scope language ──────────────────────────────────────────
|
|
|
|
|
|
_ROLE_SCOPE_DEFAULTS = {
|
|
"ucaas": "small UCaaS provider serving end-users",
|
|
"facilities": "facilities-based voice service provider serving end-users",
|
|
"reseller": "voice service reseller",
|
|
"wholesale_domestic": "domestic wholesale voice provider",
|
|
"gateway": "international gateway provider",
|
|
"international_only": "carrier handling exclusively international voice traffic",
|
|
}
|
|
|
|
|
|
def _scope_paragraph(
|
|
*,
|
|
entity_name: str,
|
|
entity_abbr: str,
|
|
carrier_role: str,
|
|
scope_narrative: str,
|
|
is_wholesale: bool,
|
|
is_gateway: bool,
|
|
foreign_traffic: bool,
|
|
) -> str:
|
|
default_role = _ROLE_SCOPE_DEFAULTS.get(carrier_role, "voice service provider")
|
|
narrative = scope_narrative or default_role
|
|
|
|
parts = [
|
|
f"{entity_name} (\"{entity_abbr}\"), a {narrative}, is committed to "
|
|
f"mitigating unlawful robocalls and complying with Federal "
|
|
f"Communications Commission (FCC) regulations."
|
|
]
|
|
if not is_wholesale and carrier_role not in ("wholesale_domestic", "gateway"):
|
|
parts.append(
|
|
f"{entity_abbr} does not provide wholesale services, SIP trunking, "
|
|
f"origination for resellers, or act as an intermediate/gateway "
|
|
f"provider in any call path."
|
|
)
|
|
if not foreign_traffic:
|
|
parts.append(
|
|
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."
|
|
)
|
|
parts.append(
|
|
f"This Robocall Mitigation Plan outlines {entity_abbr}'s measures to "
|
|
f"detect, prevent, and mitigate unlawful robocalls in compliance "
|
|
f"with FCC regulations, including 47 CFR \u00a7 64.6305 and the updated "
|
|
f"requirements from the 2025 Robocall Mitigation Database Report "
|
|
f"and Order (effective February 5, 2026, with first annual "
|
|
f"recertification due March 2, 2026 because March 1, 2026 falls on "
|
|
f"a Sunday)."
|
|
)
|
|
return "\n\n".join(parts)
|
|
|
|
|
|
# ── Doc helpers ───────────────────────────────────────────────────────────
|
|
|
|
|
|
def _add_heading(doc, text: str, level: int = 1) -> None:
|
|
p = doc.add_paragraph()
|
|
p.paragraph_format.space_before = Pt(12 if level == 1 else 8)
|
|
p.paragraph_format.space_after = PARA_SPACING_AFTER
|
|
run = p.add_run(text)
|
|
run.bold = True
|
|
run.font.size = HEADING_SIZE if level == 1 else Pt(11)
|
|
run.font.color.rgb = NAVY_BLUE
|
|
|
|
|
|
def _add_body(doc, text: str, bold: bool = False) -> None:
|
|
for chunk in text.split("\n\n"):
|
|
chunk = chunk.strip()
|
|
if not chunk:
|
|
continue
|
|
p = doc.add_paragraph()
|
|
p.paragraph_format.space_after = PARA_SPACING_AFTER
|
|
run = p.add_run(chunk)
|
|
run.font.size = BODY_SIZE
|
|
run.bold = bold
|
|
|
|
|
|
def _add_bullets(doc, items: list[str], *, indent: float = 0.25) -> None:
|
|
for item in items:
|
|
p = doc.add_paragraph(style="List Bullet")
|
|
p.paragraph_format.left_indent = Inches(indent)
|
|
p.paragraph_format.space_after = Pt(3)
|
|
p.clear()
|
|
run = p.add_run(item)
|
|
run.font.size = BODY_SIZE
|
|
|
|
|
|
def _add_page_number_footer(doc) -> None:
|
|
for section in doc.sections:
|
|
footer = section.footer
|
|
footer.is_linked_to_previous = False
|
|
p = footer.paragraphs[0] if footer.paragraphs else footer.add_paragraph()
|
|
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
|
run = p.add_run()
|
|
for field_char in ("begin",):
|
|
fc = OxmlElement("w:fldChar")
|
|
fc.set(qn("w:fldCharType"), field_char)
|
|
run._element.append(fc)
|
|
r2 = p.add_run()
|
|
instr = OxmlElement("w:instrText")
|
|
instr.set(qn("xml:space"), "preserve")
|
|
instr.text = " PAGE "
|
|
r2._element.append(instr)
|
|
r3 = p.add_run()
|
|
fc2 = OxmlElement("w:fldChar")
|
|
fc2.set(qn("w:fldCharType"), "end")
|
|
r3._element.append(fc2)
|
|
|
|
|
|
# ── Main generator ───────────────────────────────────────────────────────
|
|
|
|
|
|
def generate_exhibit_a(
|
|
# Identity
|
|
entity_name: str,
|
|
entity_abbr: str = "",
|
|
frn: str = "",
|
|
ocn: str = "",
|
|
address: str = "",
|
|
# Contact
|
|
contact_name: str = "",
|
|
contact_title: str = "",
|
|
contact_email: str = "",
|
|
contact_phone: str = "",
|
|
# Principals / affiliates (list of names or short descriptions)
|
|
principals: list[str] | None = None,
|
|
affiliates: list[str] | None = None,
|
|
# Classification
|
|
carrier_role: str = "facilities",
|
|
carrier_metadata: dict | None = None,
|
|
upstream_provider_name: str = "",
|
|
is_wholesale: bool = False,
|
|
is_gateway: bool = False,
|
|
foreign_traffic: bool = False,
|
|
# RMD filing option — "option1", "option2", "option3"
|
|
rmd_option: str = "option2",
|
|
# Operational narrative
|
|
scope_narrative: str = "",
|
|
high_risk_alert_sla_hours: int = 4,
|
|
# Analytics vendors / systems (optional)
|
|
analytics_systems: list[str] | None = None,
|
|
third_party_vendors: list[str] | None = None,
|
|
# Signature
|
|
signer_name: str = "",
|
|
signer_title: str = "",
|
|
# Legacy LLM hook kept for backwards compat — ignored (no-op)
|
|
llm_generate: Callable[[str, str], Awaitable[str]] | None = None,
|
|
# Output
|
|
output_path: str = "/tmp/rmd_plan.docx",
|
|
) -> Optional[str]:
|
|
"""Generate the PW canonical Robocall Mitigation Plan as a DOCX file."""
|
|
if Document is None:
|
|
LOG.error("python-docx not installed")
|
|
return None
|
|
|
|
entity_abbr = entity_abbr or _derive_abbr(entity_name)
|
|
principals = principals or []
|
|
affiliates = affiliates or []
|
|
signer_name = signer_name or contact_name
|
|
signer_title = signer_title or contact_title
|
|
|
|
doc = Document()
|
|
for section in doc.sections:
|
|
section.top_margin = Inches(1)
|
|
section.bottom_margin = Inches(1)
|
|
section.left_margin = Inches(1.25)
|
|
section.right_margin = Inches(1.25)
|
|
_add_page_number_footer(doc)
|
|
|
|
today = datetime.now().strftime("%B %d, %Y")
|
|
|
|
# Title + "Updated as of"
|
|
title_p = doc.add_paragraph()
|
|
title_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
|
title_run = title_p.add_run(f"Robocall Mitigation Plan for {entity_name}")
|
|
title_run.font.size = Pt(14)
|
|
title_run.bold = True
|
|
title_run.font.color.rgb = NAVY_BLUE
|
|
title_p.paragraph_format.space_after = Pt(2)
|
|
|
|
subtitle_p = doc.add_paragraph()
|
|
subtitle_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
|
sub_run = subtitle_p.add_run(f"Updated as of {today}")
|
|
sub_run.font.size = Pt(10)
|
|
sub_run.italic = True
|
|
subtitle_p.paragraph_format.space_after = Pt(12)
|
|
|
|
# ── Introduction ──
|
|
_add_heading(doc, "Introduction")
|
|
_add_body(doc, _scope_paragraph(
|
|
entity_name=entity_name, entity_abbr=entity_abbr,
|
|
carrier_role=carrier_role, scope_narrative=scope_narrative,
|
|
is_wholesale=is_wholesale, is_gateway=is_gateway,
|
|
foreign_traffic=foreign_traffic,
|
|
))
|
|
|
|
# ── 1. Contact Information ──
|
|
_add_heading(doc, "1. Contact Information")
|
|
_add_body(doc, entity_name)
|
|
if address:
|
|
_add_body(doc, f"Address: {address}")
|
|
if contact_name:
|
|
title_suffix = f", {contact_title}" if contact_title else ""
|
|
_add_body(doc, f"Primary Contact: {contact_name}{title_suffix}")
|
|
if contact_email:
|
|
_add_body(doc, f"Email Address: {contact_email}")
|
|
if contact_phone:
|
|
_add_body(doc, f"Phone: {contact_phone}")
|
|
if frn:
|
|
_add_body(doc, f"FRN: {frn}")
|
|
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."
|
|
))
|
|
|
|
_add_body(doc, "Principals, Affiliates, Subsidiaries, and Parent Companies:", bold=True)
|
|
_add_bullets(doc, principals or [f"{contact_name or entity_name} (sole principal)"])
|
|
if affiliates:
|
|
_add_body(doc, "Affiliates:")
|
|
_add_bullets(doc, affiliates)
|
|
|
|
_add_body(doc, (
|
|
f"{entity_abbr} affirms that neither it nor any affiliated entity "
|
|
f"has been subject to FCC or law enforcement action related to "
|
|
f"illegal robocalling, spoofing, or RMD deficiencies in the past "
|
|
f"two years."
|
|
))
|
|
|
|
# ── 2. STIR/SHAKEN ──
|
|
_add_heading(doc, "2. Implementation of STIR/SHAKEN Framework")
|
|
stir_paras = _stir_shaken_paragraph(
|
|
entity_name=entity_name, entity_abbr=entity_abbr,
|
|
rmd_option=rmd_option,
|
|
upstream_provider_name=upstream_provider_name,
|
|
carrier_role=carrier_role,
|
|
ocn=ocn,
|
|
)
|
|
for para in stir_paras:
|
|
_add_body(doc, para)
|
|
_add_body(doc, f"RMD filing option selected: {RMD_OPTION_LABELS.get(rmd_option.lower(), rmd_option)}", bold=True)
|
|
|
|
# ── 3. Robocall Monitoring and Mitigation ──
|
|
_add_heading(doc, "3. Robocall Monitoring and Mitigation")
|
|
_add_body(doc, (
|
|
f"{entity_abbr} actively works to prevent illegal robocalls from "
|
|
f"originating or transiting through its network. The program applies "
|
|
f"to all voice traffic that {entity_abbr} originates, transits, or "
|
|
f"terminates, and includes the following elements:"
|
|
))
|
|
_add_body(doc, "Traffic Monitoring:", bold=True)
|
|
_add_bullets(doc, [
|
|
"Monitoring call patterns for anomalies \u2014 high call volumes to specific destinations, short-duration calls, ASR/ACD deviations, call velocity, and snowshoeing.",
|
|
f"Receiving and reviewing all high-risk alerts within {high_risk_alert_sla_hours} hours and taking immediate action.",
|
|
"Investigating and addressing suspicious activity promptly.",
|
|
])
|
|
_add_body(doc, "Customer Vetting:", bold=True)
|
|
_add_bullets(doc, [
|
|
"Verifying the identity of new customers and assessing the legitimacy of their intended usage.",
|
|
"Ensuring customers agree to terms prohibiting illegal robocalling.",
|
|
"Immediately blocking any numbers identified on the FCC Do-Not-Originate (DNO) list via upstream enforcement.",
|
|
"Taking reasonable steps to prevent new and renewing customers from originating illegal robocalls.",
|
|
])
|
|
_add_body(doc, "Complaint Resolution:", bold=True)
|
|
_add_bullets(doc, [
|
|
"Providing a clear process for individuals to report suspected robocalls (including email to the support address above).",
|
|
"Investigating complaints and taking corrective actions, including termination of services for violators.",
|
|
])
|
|
|
|
# ── 3.5 KYC (In-House) ──
|
|
_add_heading(doc, "3.5. Know Your Customer (KYC) Procedures (Performed In-House)", level=2)
|
|
_add_body(doc, (
|
|
f"{entity_name} conducts its own internal Know Your Customer (KYC) "
|
|
f"process for all new customers and customer renewals to ensure "
|
|
f"that only legitimate entities and individuals are granted access "
|
|
f"to services capable of making outbound calls or using numbering "
|
|
f"resources."
|
|
))
|
|
_add_body(doc, "Collection and Verification of Customer Information. At account signup or upon any material change in service usage, we require and collect:", bold=True)
|
|
_add_bullets(doc, [
|
|
"Full legal name of the individual or entity",
|
|
"Physical business address (no P.O. boxes accepted for high-volume or toll-free services)",
|
|
"Business identification number (EIN, or equivalent tax ID for non-U.S. entities) or, for individuals, the last four digits of SSN or government-issued ID number",
|
|
"At least one valid government-issued photo ID for the account owner or authorized officer",
|
|
"Business website, or if none exists, a description of the legitimate business purpose for the service",
|
|
])
|
|
_add_body(doc, "Verification Steps Performed In-House. Staff manually verify the provided information by:", bold=True)
|
|
_add_bullets(doc, [
|
|
"Cross-referencing business name and EIN against public state business registry databases or IRS records where available",
|
|
"Confirming the provided physical address via USPS address validation tools and third-party data sources (e.g., Google Maps satellite/street view confirmation)",
|
|
"Verifying that the submitted photo ID matches the name and appears authentic",
|
|
"Conducting an open-source and web search for the customer and principals to identify any prior association with illegal robocalling, call spoofing, or inclusion on the Industry Traceback Group's known bad-actor list",
|
|
])
|
|
_add_body(doc, "Red-Flag Review and Enhanced Due Diligence. If any of the following risk indicators are present, we perform enhanced in-house due diligence before activating or continuing service:", bold=True)
|
|
_add_bullets(doc, [
|
|
"Customer is unwilling or unable to provide complete KYC information",
|
|
"Discrepancies between provided information and public records",
|
|
"Use of privacy-protected or anonymous registration services for domains/websites",
|
|
"Requested usage patterns inconsistent with stated business purpose",
|
|
"Prior complaints or traceback involvement linked to the customer or its principals",
|
|
])
|
|
_add_body(doc, (
|
|
"Acceptance of Terms Prohibiting Illegal Activity. All customers "
|
|
"must electronically acknowledge and agree to our Acceptable Use "
|
|
"Policy and Robocall Policy, which explicitly prohibit the "
|
|
"origination or facilitation of illegal robocalls, unlawful caller "
|
|
"ID spoofing, or any violation of the Telephone Consumer Protection "
|
|
"Act (TCPA) or Telemarketing Sales Rule (TSR)."
|
|
))
|
|
_add_body(doc, (
|
|
"Ongoing Monitoring and Re-Vetting. Existing customers are subject "
|
|
"to periodic re-vetting (at least annually for high-volume or "
|
|
"toll-free customers) and immediate re-review upon receipt of "
|
|
"complaints, traceback requests, or detected anomalous traffic "
|
|
"patterns."
|
|
))
|
|
|
|
# ── 4. Call Analytics and Upstream Provider Procedures ──
|
|
_add_heading(doc, "4. Call Analytics and Upstream Provider Procedures")
|
|
_add_body(doc, "Call Analytics:", bold=True)
|
|
if analytics_systems or third_party_vendors:
|
|
items: list[str] = []
|
|
if analytics_systems:
|
|
items.append("Analytics systems deployed: " + ", ".join(analytics_systems))
|
|
if third_party_vendors:
|
|
items.append("Third-party analytics vendors: " + ", ".join(third_party_vendors))
|
|
items.append("Systems analyze call patterns in real time to identify potential violations.")
|
|
_add_bullets(doc, items)
|
|
else:
|
|
_add_bullets(doc, [
|
|
f"{entity_abbr} utilizes the underlying carriers' real-time call analytics platforms, which monitor ASR, ACD, call velocity, short-duration patterns, and snowshoeing.",
|
|
f"{entity_abbr} receives and reviews all high-risk alerts within {high_risk_alert_sla_hours} hours and takes immediate action.",
|
|
"As a small provider without its own switching platform, independent analytics are unnecessary and disproportionate to risk.",
|
|
])
|
|
_add_body(doc, "Upstream Provider Procedures:", bold=True)
|
|
_add_bullets(doc, [
|
|
"Prior to contracting and annually thereafter, we verify each upstream provider's active RMD filing, STIR/SHAKEN status, and robocall mitigation plan via the RMD portal before routing any traffic.",
|
|
"Periodic reviews confirm ongoing compliance.",
|
|
])
|
|
|
|
# ── 5. Compliance with FCC Requirements ──
|
|
_add_heading(doc, "5. Compliance with FCC Requirements")
|
|
_add_body(doc, f"{entity_abbr} fully complies with FCC robocall mitigation rules:")
|
|
_add_bullets(doc, [
|
|
"Maintains an active filing in the FCC's Robocall Mitigation Database (RMD), including role (voice service provider serving end-users), STIR/SHAKEN status, and mitigation plan.",
|
|
"Annual Recertification: Recertifies RMD filing annually by March 1 each year (for 2026, by March 2 because March 1 is a Sunday; window opened February 1, 2026). Recertification involves logging into the RMD portal with multi-factor authentication (required effective February 5, 2026), verifying accuracy of all information, updating if needed, and submitting via the \"Recertify\" button.",
|
|
"Prompt Updates: Updates RMD and CORES registration within 10 business days of any material change (e.g., ownership, contacts, STIR/SHAKEN posture, upstream provider, trade names), per 47 CFR \u00a7 64.6305.",
|
|
"Responds fully to Industry Traceback Group (ITG) traceback requests within 24 hours.",
|
|
"Pays any required filing fees to the FCC.",
|
|
"Responds promptly to FCC deficiency notices, curing issues within specified timeframes to avoid RMD removal or traffic blocking.",
|
|
])
|
|
_add_body(doc, (
|
|
"Noncompliance risks under the 2025 RMD R&O include a base forfeiture "
|
|
"of $10,000 for false or inaccurate information and $1,000 per day "
|
|
"until cured for failure to update RMD information within 10 "
|
|
"business days of a material change."
|
|
))
|
|
|
|
# ── 6. Future Enhancements ──
|
|
_add_heading(doc, "6. Future Enhancements")
|
|
_add_body(doc, f"{entity_abbr} commits to ongoing improvement:")
|
|
_add_bullets(doc, [
|
|
"Monitoring upstream carrier enhancements for better analytics/blocking.",
|
|
"Educating customers on robocall awareness and reporting.",
|
|
"Adapting to emerging threats (e.g., AI voice cloning) via upstream partnerships and FCC guidance.",
|
|
"Strengthening partnerships with industry organizations and regulators to stay ahead of emerging robocall trends.",
|
|
])
|
|
|
|
# ── 7. Commitment to Correct Deficiencies ──
|
|
_add_heading(doc, "7. Commitment to Correct Deficiencies")
|
|
_add_body(doc, (
|
|
f"{entity_abbr} will respond promptly to any FCC notice of deficiency "
|
|
f"in its RMD certification. This includes:"
|
|
))
|
|
_add_bullets(doc, [
|
|
"Updating RMD certifications and robocall mitigation plans to cure identified deficiencies.",
|
|
"Providing detailed explanations to the FCC regarding corrective actions taken.",
|
|
"Ensuring compliance within the specified timeframe to avoid removal from the RMD.",
|
|
])
|
|
|
|
# ── Conclusion ──
|
|
_add_heading(doc, "Conclusion")
|
|
_add_body(doc, (
|
|
f"{entity_name} is dedicated to protecting its customers and the "
|
|
f"public from the harm caused by illegal robocalls. Through "
|
|
f"reliable upstream partnerships, customer-focused controls, and "
|
|
f"full adherence to updated FCC requirements (including 2026 annual "
|
|
f"recertification by March 2, 2026), {entity_abbr} provides secure, "
|
|
f"compliant voice services."
|
|
))
|
|
|
|
# ── Perjury declaration + signature ──
|
|
_add_heading(doc, " ", level=2) # spacer
|
|
_add_body(doc, (
|
|
"I declare under penalty of perjury under the laws of the United "
|
|
"States of America that to the best of my knowledge the foregoing "
|
|
"is true and correct."
|
|
))
|
|
_add_body(doc, "")
|
|
sig = doc.add_paragraph()
|
|
sig.add_run("_" * 45).font.size = BODY_SIZE
|
|
_add_body(doc, signer_name or "[Authorized Signer]", bold=True)
|
|
_add_body(doc, signer_title or "[Title]")
|
|
_add_body(doc, entity_name)
|
|
_add_body(doc, f"Date: {today}")
|
|
|
|
# Save
|
|
output = Path(output_path)
|
|
output.parent.mkdir(parents=True, exist_ok=True)
|
|
doc.save(str(output))
|
|
LOG.info("RMD Plan (Exhibit A) generated: %s", output)
|
|
return str(output)
|
|
|
|
|
|
# ── Helpers ───────────────────────────────────────────────────────────────
|
|
|
|
|
|
def _derive_abbr(entity_name: str) -> str:
|
|
"""Build a 2-4 letter abbreviation from the legal name."""
|
|
words = [w for w in entity_name.replace(",", "").split() if w.lower() not in (
|
|
"inc", "inc.", "llc", "llc.", "corporation", "corp", "corp.", "co", "co.",
|
|
"ltd", "ltd.", "company", "the", "a", "of",
|
|
)]
|
|
if not words:
|
|
return entity_name[:3].upper()
|
|
letters = "".join(w[0].upper() for w in words[:3])
|
|
return letters if len(letters) >= 2 else entity_name[:3].upper()
|