Initial commit — Performance West telecom compliance platform

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>
This commit is contained in:
justin 2026-04-27 06:54:22 -05:00
commit f8cd37ac8c
1823 changed files with 145167 additions and 0 deletions

View file

@ -0,0 +1,5 @@
# Document generation library — DOCX templates, PDF conversion, MinIO storage, LLM writing
from .docx_builder import DocxBuilder
from .pdf_converter import convert_to_pdf
from .minio_client import MinioStorage
from .llm_writer import LLMWriter

View file

@ -0,0 +1,222 @@
"""
DOCX template builder using python-docx + Jinja2.
Templates use Jinja2 placeholders: {{ variable_name }}
Supports:
- Simple variable substitution
- Conditional sections ({% if ... %})
- Loops for member tables ({% for member in members %})
- Section insertion (replace a placeholder paragraph with multi-paragraph LLM output)
"""
from __future__ import annotations
import copy
import logging
import os
import re
from datetime import datetime
from pathlib import Path
from typing import Any
from docx import Document
from docx.shared import Inches, Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from jinja2 import Template
LOG = logging.getLogger("document_gen.docx")
TEMPLATES_DIR = Path(os.getenv("TEMPLATES_DIR", "/app/scripts/templates"))
class DocxBuilder:
"""Build DOCX documents from templates with variable substitution."""
def __init__(self, template_name: str):
"""Load a DOCX template by name (e.g., 'operating-agreement')."""
self.template_path = TEMPLATES_DIR / f"{template_name}.docx"
if not self.template_path.exists():
raise FileNotFoundError(f"Template not found: {self.template_path}")
self.doc = Document(str(self.template_path))
self.variables: dict[str, Any] = {}
def set_variables(self, variables: dict[str, Any]) -> "DocxBuilder":
"""Set template variables for substitution."""
self.variables = variables
return self
def fill(self) -> "DocxBuilder":
"""Fill all Jinja2 placeholders in the document."""
# Process paragraphs
for para in self.doc.paragraphs:
self._fill_paragraph(para)
# Process table cells
for table in self.doc.tables:
for row in table.rows:
for cell in row.cells:
for para in cell.paragraphs:
self._fill_paragraph(para)
# Process headers and footers
for section in self.doc.sections:
for header_para in section.header.paragraphs:
self._fill_paragraph(header_para)
for footer_para in section.footer.paragraphs:
self._fill_paragraph(footer_para)
return self
def _fill_paragraph(self, para):
"""Replace Jinja2 placeholders in a paragraph, preserving formatting."""
full_text = para.text
if "{{" not in full_text and "{%" not in full_text:
return
# Render the full paragraph text through Jinja2
try:
template = Template(full_text)
rendered = template.render(**self.variables)
except Exception as e:
LOG.warning("Template render error in paragraph: %s%s", full_text[:80], e)
return
if rendered == full_text:
return
# Clear all runs and set the rendered text in the first run
if para.runs:
# Preserve the formatting of the first run
first_run = para.runs[0]
first_run.text = rendered
for run in para.runs[1:]:
run.text = ""
else:
para.text = rendered
def insert_section(self, placeholder: str, content: str) -> "DocxBuilder":
"""Replace a placeholder paragraph with multi-paragraph content.
Used for LLM-generated sections the placeholder (e.g., '{{findings_section}}')
is replaced with multiple paragraphs of formatted text.
"""
for i, para in enumerate(self.doc.paragraphs):
if placeholder in para.text:
# Split content into paragraphs
lines = content.strip().split("\n\n")
# Replace the placeholder paragraph with the first line
para.text = lines[0] if lines else ""
# Insert remaining lines as new paragraphs after the current one
for j, line in enumerate(lines[1:], 1):
new_para = copy.deepcopy(para)
new_para.text = line
para._element.addnext(new_para._element)
return self
LOG.warning("Placeholder not found: %s", placeholder)
return self
def add_cover_page(
self,
title: str,
subtitle: str = "",
client_name: str = "",
order_number: str = "",
date: str = "",
) -> "DocxBuilder":
"""Add a branded cover page at the beginning of the document."""
# Insert paragraphs at the top
first_para = self.doc.paragraphs[0] if self.doc.paragraphs else self.doc.add_paragraph()
# We'll prepend by inserting before the first paragraph
cover_elements = []
# Spacer
spacer = self.doc.add_paragraph()
spacer.space_after = Pt(72)
# Title
title_para = self.doc.add_paragraph()
title_run = title_para.add_run(title)
title_run.font.size = Pt(28)
title_run.font.color.rgb = RGBColor(0x2D, 0x4E, 0x78) # pw-700
title_run.font.bold = True
title_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
# Subtitle
if subtitle:
sub_para = self.doc.add_paragraph()
sub_run = sub_para.add_run(subtitle)
sub_run.font.size = Pt(14)
sub_run.font.color.rgb = RGBColor(0x6B, 0x72, 0x80)
sub_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
# Client info
if client_name:
client_para = self.doc.add_paragraph()
client_para.space_before = Pt(36)
client_run = client_para.add_run(f"Prepared for: {client_name}")
client_run.font.size = Pt(12)
client_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
# Order number + date
meta_para = self.doc.add_paragraph()
meta_parts = []
if order_number:
meta_parts.append(f"Order: {order_number}")
meta_parts.append(f"Date: {date or datetime.now().strftime('%B %d, %Y')}")
meta_run = meta_para.add_run(" | ".join(meta_parts))
meta_run.font.size = Pt(10)
meta_run.font.color.rgb = RGBColor(0x9C, 0xA3, 0xAF)
meta_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
# Performance West branding
brand_para = self.doc.add_paragraph()
brand_para.space_before = Pt(48)
brand_run = brand_para.add_run("Performance West Inc.")
brand_run.font.size = Pt(10)
brand_run.font.color.rgb = RGBColor(0x2D, 0x4E, 0x78)
brand_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
addr_para = self.doc.add_paragraph()
addr_run = addr_para.add_run("525 Randall Ave Ste 100-1195, Cheyenne, WY 82001 | 1-888-411-0383")
addr_run.font.size = Pt(8)
addr_run.font.color.rgb = RGBColor(0x9C, 0xA3, 0xAF)
addr_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
# Page break after cover
self.doc.add_page_break()
# Move cover elements to the beginning
body = self.doc.element.body
# The paragraphs we just added are at the end — move them to the front
added = list(body)[-8:] # Last 8 elements we added (spacer, title, sub, client, meta, brand, addr, pagebreak)
for elem in reversed(added):
body.insert(0, elem)
return self
def add_disclaimer(self, text: str = "") -> "DocxBuilder":
"""Add a disclaimer paragraph at the end of the document."""
default = (
"DISCLAIMER: This document is prepared by Performance West Inc. for compliance consulting purposes only. "
"It does not constitute legal advice, legal representation, or create an attorney-client relationship. "
"For legal matters, consult a licensed attorney in your jurisdiction."
)
para = self.doc.add_paragraph()
para.space_before = Pt(24)
run = para.add_run(text or default)
run.font.size = Pt(8)
run.font.italic = True
run.font.color.rgb = RGBColor(0x9C, 0xA3, 0xAF)
return self
def save(self, output_path: str | Path) -> Path:
"""Save the filled document to a file."""
output_path = Path(output_path)
output_path.parent.mkdir(parents=True, exist_ok=True)
self.doc.save(str(output_path))
LOG.info("DOCX saved: %s", output_path)
return output_path

View file

@ -0,0 +1,137 @@
"""
LLM content writer for compliance report sections.
Uses Ollama (local LLM) to generate analysis and prose for compliance reports.
Each service type provides its own system prompt and section templates.
"""
from __future__ import annotations
import json
import logging
import os
from typing import Any
import httpx
LOG = logging.getLogger("document_gen.llm")
OLLAMA_HOST = os.getenv("OLLAMA_HOST", "http://localhost:11434")
DEFAULT_MODEL = os.getenv("OLLAMA_MODEL", "qwen2.5:7b")
class LLMWriter:
"""Generate compliance report content using a local LLM."""
def __init__(self, model: str = DEFAULT_MODEL):
self.model = model
self.base_url = OLLAMA_HOST
self.client = httpx.Client(timeout=300.0) # 5 min timeout for long generations
def generate_section(
self,
system_prompt: str,
user_prompt: str,
temperature: float = 0.3,
max_tokens: int = 4096,
) -> str:
"""Generate a single section of a compliance report.
Args:
system_prompt: System instructions (compliance rules, format requirements)
user_prompt: The specific section to generate (includes customer data)
temperature: Lower = more factual, higher = more creative
max_tokens: Maximum output length
Returns:
Generated text content for the section
"""
LOG.info("Generating section (model=%s, temp=%.1f)...", self.model, temperature)
try:
response = self.client.post(
f"{self.base_url}/api/chat",
json={
"model": self.model,
"messages": [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
],
"options": {
"temperature": temperature,
"num_predict": max_tokens,
},
"stream": False,
},
)
response.raise_for_status()
data = response.json()
content = data.get("message", {}).get("content", "")
LOG.info("Generated %d characters", len(content))
return content.strip()
except httpx.HTTPError as e:
LOG.error("Ollama request failed: %s", e)
raise RuntimeError(f"LLM generation failed: {e}") from e
def generate_report(
self,
service_type: str,
customer_data: dict[str, Any],
sections: list[dict[str, str]],
system_prompt: str,
) -> dict[str, str]:
"""Generate all sections of a compliance report.
Args:
service_type: Service identifier (e.g., 'flsa_audit')
customer_data: Customer and order information
sections: List of {"name": "section_name", "prompt": "section-specific instructions"}
system_prompt: Base system prompt for this service type
Returns:
Dict mapping section names to generated content
"""
results: dict[str, str] = {}
customer_json = json.dumps(customer_data, indent=2)
for section in sections:
section_name = section["name"]
section_prompt = section["prompt"]
user_prompt = (
f"SERVICE: {service_type}\n"
f"SECTION: {section_name}\n\n"
f"CUSTOMER DATA:\n{customer_json}\n\n"
f"INSTRUCTIONS:\n{section_prompt}"
)
try:
content = self.generate_section(
system_prompt=system_prompt,
user_prompt=user_prompt,
temperature=0.3,
)
results[section_name] = content
LOG.info("Section '%s' generated (%d chars)", section_name, len(content))
except Exception as e:
LOG.error("Section '%s' failed: %s", section_name, e)
results[section_name] = f"[GENERATION FAILED: {e}]"
return results
def health_check(self) -> bool:
"""Check if Ollama is reachable and the model is available."""
try:
resp = self.client.get(f"{self.base_url}/api/tags")
if resp.status_code != 200:
return False
models = resp.json().get("models", [])
model_names = [m.get("name", "") for m in models]
available = any(self.model in name for name in model_names)
if not available:
LOG.warning("Model %s not found. Available: %s", self.model, model_names)
return available
except Exception as e:
LOG.error("Ollama health check failed: %s", e)
return False

View file

@ -0,0 +1,128 @@
"""
MinIO (S3-compatible) client for document storage.
Uploads generated documents to MinIO and returns accessible URLs.
"""
from __future__ import annotations
import logging
import os
from pathlib import Path
from minio import Minio
from minio.error import S3Error
LOG = logging.getLogger("document_gen.minio")
BUCKET = os.getenv("MINIO_BUCKET", "performancewest")
class MinioStorage:
"""S3-compatible document storage via MinIO."""
def __init__(self):
self.client = Minio(
endpoint=f"{os.getenv('MINIO_ENDPOINT', 'localhost')}:{os.getenv('MINIO_PORT', '9000')}",
access_key=os.getenv("MINIO_ACCESS_KEY", ""),
secret_key=os.getenv("MINIO_SECRET_KEY", ""),
secure=os.getenv("MINIO_SECURE", "false").lower() == "true",
)
self._ensure_bucket()
def _ensure_bucket(self):
"""Create the bucket if it doesn't exist."""
try:
if not self.client.bucket_exists(BUCKET):
self.client.make_bucket(BUCKET)
LOG.info("Created MinIO bucket: %s", BUCKET)
except S3Error as e:
LOG.error("MinIO bucket check failed: %s", e)
def upload(
self,
local_path: str | Path,
remote_path: str,
content_type: str = "application/octet-stream",
) -> str:
"""Upload a file to MinIO.
Args:
local_path: Local file path
remote_path: Object key in the bucket (e.g., "formations/PW-2026-XXXX/articles.pdf")
content_type: MIME type
Returns:
The object URL (internal MinIO URL)
"""
local_path = Path(local_path)
if not local_path.exists():
raise FileNotFoundError(f"File not found: {local_path}")
# Auto-detect content type
if content_type == "application/octet-stream":
suffix = local_path.suffix.lower()
content_types = {
".pdf": "application/pdf",
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
".doc": "application/msword",
".html": "text/html",
".txt": "text/plain",
".png": "image/png",
".jpg": "image/jpeg",
}
content_type = content_types.get(suffix, content_type)
try:
self.client.fput_object(
BUCKET,
remote_path,
str(local_path),
content_type=content_type,
)
LOG.info("Uploaded: %s%s/%s", local_path.name, BUCKET, remote_path)
return f"{BUCKET}/{remote_path}"
except S3Error as e:
LOG.error("MinIO upload failed: %s", e)
raise
def download(self, remote_path: str, local_path: str | Path) -> Path:
"""Download a file from MinIO."""
local_path = Path(local_path)
local_path.parent.mkdir(parents=True, exist_ok=True)
try:
self.client.fget_object(BUCKET, remote_path, str(local_path))
LOG.info("Downloaded: %s/%s%s", BUCKET, remote_path, local_path)
return local_path
except S3Error as e:
LOG.error("MinIO download failed: %s", e)
raise
def get_url(self, remote_path: str, expires_hours: int = 24) -> str:
"""Get a presigned URL for a file (for client download)."""
from datetime import timedelta
try:
url = self.client.presigned_get_object(
BUCKET, remote_path, expires=timedelta(hours=expires_hours),
)
return url
except S3Error as e:
LOG.error("MinIO presign failed: %s", e)
raise
def list_objects(self, prefix: str) -> list[str]:
"""List all objects under a prefix."""
try:
objects = self.client.list_objects(BUCKET, prefix=prefix, recursive=True)
return [obj.object_name for obj in objects]
except S3Error as e:
LOG.error("MinIO list failed: %s", e)
return []
def delete(self, remote_path: str):
"""Delete an object from MinIO."""
try:
self.client.remove_object(BUCKET, remote_path)
LOG.info("Deleted: %s/%s", BUCKET, remote_path)
except S3Error as e:
LOG.error("MinIO delete failed: %s", e)

View file

@ -0,0 +1,285 @@
"""
DOCX PDF conversion.
Primary: Windows Word VM via MinIO (pixel-perfect, no open ports required).
Fallback: LibreOffice headless (70-80% fidelity, always available in container).
MinIO transport protocol
PUT docx {bucket}/to-convert/{job_id}.docx (this module)
WAIT poll {bucket}/converted/{job_id}.pdf (this module)
GET pdf {bucket}/converted/{job_id}.pdf (this module)
DEL docx {bucket}/to-convert/{job_id}.docx (docserver_worker.py)
DEL pdf {bucket}/converted/{job_id}.pdf (this module, after download)
The Windows VM runs docserver_worker.py which:
1. Polls to-convert/ every 12 seconds
2. Downloads the DOCX, converts via Word COM, uploads the PDF to converted/
3. Deletes the source DOCX from to-convert/
No HTTP server, no open ports, no SSH tunnel. Only MinIO is needed.
Environment variables (same MinIO creds as the workers):
MINIO_ENDPOINT MinIO host (default: minio)
MINIO_PORT MinIO port (default: 9000)
MINIO_ACCESS_KEY access key
MINIO_SECRET_KEY secret key
MINIO_BUCKET bucket name (default: performancewest)
USE_DOCSERVER enable Word VM path (default: true)
DOCSERVER_TIMEOUT max seconds to wait for Word to produce the PDF (default: 120)
"""
from __future__ import annotations
import io
import logging
import os
import subprocess
import time
import uuid
from pathlib import Path
LOG = logging.getLogger("document_gen.pdf")
# MinIO settings — inherited from the workers container env
_MINIO_ENDPOINT = os.getenv("MINIO_ENDPOINT", "minio")
_MINIO_PORT = int(os.getenv("MINIO_PORT", "9000"))
_MINIO_ACCESS = os.getenv("MINIO_ACCESS_KEY", "")
_MINIO_SECRET = os.getenv("MINIO_SECRET_KEY", "")
_MINIO_BUCKET = os.getenv("MINIO_BUCKET", "performancewest")
_MINIO_SECURE = os.getenv("MINIO_SECURE", "false").lower() == "true"
USE_DOCSERVER = os.getenv("USE_DOCSERVER", "true").lower() == "true"
DOCSERVER_TIMEOUT = int(os.getenv("DOCSERVER_TIMEOUT", "120")) # seconds
_POLL_INTERVAL = 12 # seconds between polls for the converted PDF
# MinIO key prefixes
_PREFIX_IN = "to-convert" # docx files waiting to be processed
_PREFIX_OUT = "converted" # pdf files ready for pickup
def _minio_client():
"""Return a configured MinIO client."""
from minio import Minio # type: ignore
return Minio(
f"{_MINIO_ENDPOINT}:{_MINIO_PORT}",
access_key=_MINIO_ACCESS,
secret_key=_MINIO_SECRET,
secure=_MINIO_SECURE,
)
# ── Public API ────────────────────────────────────────────────────────────────
def convert_to_pdf(docx_path: str | Path, output_dir: str | Path | None = None) -> Path:
"""Convert a DOCX to PDF.
Tries the Word VM via MinIO first (pixel-perfect).
Falls back to LibreOffice headless if the VM is unavailable or slow.
Args:
docx_path: Path to the .docx file on disk
output_dir: Where to write the PDF (defaults to same dir as docx)
Returns:
Path to the generated PDF file
"""
docx_path = Path(docx_path)
if not docx_path.exists():
raise FileNotFoundError(f"DOCX not found: {docx_path}")
out_dir = Path(output_dir) if output_dir else docx_path.parent
out_dir.mkdir(parents=True, exist_ok=True)
pdf_path = out_dir / docx_path.with_suffix(".pdf").name
if USE_DOCSERVER and _MINIO_ACCESS:
try:
return _convert_via_minio(docx_path, pdf_path)
except Exception as exc:
LOG.warning(
"Word VM via MinIO unavailable (%s) — falling back to LibreOffice", exc
)
return _convert_via_libreoffice(docx_path, pdf_path, out_dir)
def convert_batch(docx_paths: list[str | Path], output_dir: str | Path) -> list[Path]:
"""Convert multiple DOCX files to PDFs.
Submits all jobs to the Word VM concurrently (each gets its own MinIO key),
then collects results as they arrive. Falls back per-file to LibreOffice.
"""
docx_paths = [Path(p) for p in docx_paths]
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
if USE_DOCSERVER and _MINIO_ACCESS and docx_paths:
try:
return _batch_via_minio(docx_paths, output_dir)
except Exception as exc:
LOG.warning("Batch via Word VM failed (%s) — converting one by one via LibreOffice", exc)
results = []
for docx_path in docx_paths:
try:
results.append(convert_to_pdf(docx_path, output_dir))
except Exception as exc:
LOG.error("Failed to convert %s: %s", docx_path.name, exc)
return results
def health_check() -> dict:
"""Return status of both conversion backends."""
status: dict = {"libreoffice": False, "docserver_minio": False}
# LibreOffice
try:
r = subprocess.run(
["libreoffice", "--version"],
capture_output=True, text=True, timeout=10,
)
status["libreoffice"] = r.returncode == 0
except Exception:
pass
# Word VM — check if the MinIO bucket is accessible and if the worker
# has recently touched a heartbeat object
if USE_DOCSERVER and _MINIO_ACCESS:
try:
mc = _minio_client()
mc.bucket_exists(_MINIO_BUCKET) # just checks connectivity
status["docserver_minio"] = True
status["minio_bucket"] = _MINIO_BUCKET
except Exception as exc:
status["minio_error"] = str(exc)
return status
# ── MinIO transport ───────────────────────────────────────────────────────────
def _convert_via_minio(docx_path: Path, pdf_path: Path) -> Path:
"""Upload DOCX to MinIO, wait for the Word VM to convert it, download PDF.
Atomic upload: the DOCX is first uploaded to a .tmp key, then renamed
(copy + delete) to the final key. This prevents the Windows worker from
downloading a partially-uploaded file.
"""
from minio.commonconfig import CopySource # type: ignore
job_id = str(uuid.uuid4()).replace("-", "")
tmp_key = f"{_PREFIX_IN}/.tmp_{job_id}.docx"
in_key = f"{_PREFIX_IN}/{job_id}.docx"
out_key = f"{_PREFIX_OUT}/{job_id}.pdf"
mc = _minio_client()
# Ensure bucket exists
if not mc.bucket_exists(_MINIO_BUCKET):
mc.make_bucket(_MINIO_BUCKET)
# Upload DOCX to temp key first (invisible to worker — it ignores .tmp_ prefix)
LOG.info("[%s] Uploading %s → minio://%s/%s (staging)", job_id[:8], docx_path.name, _MINIO_BUCKET, tmp_key)
mc.fput_object(
_MINIO_BUCKET, tmp_key, str(docx_path),
content_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
metadata={"x-amz-meta-source": docx_path.name},
)
# Atomic rename: copy tmp → final, then delete tmp
# MinIO copy_object is a server-side operation — the object appears
# at the destination key atomically (no partial state visible)
mc.copy_object(
_MINIO_BUCKET, in_key,
CopySource(_MINIO_BUCKET, tmp_key),
)
mc.remove_object(_MINIO_BUCKET, tmp_key)
LOG.info("[%s] Staged → minio://%s/%s (live)", job_id[:8], _MINIO_BUCKET, in_key)
# Poll for the converted PDF
deadline = time.monotonic() + DOCSERVER_TIMEOUT
LOG.info("[%s] Waiting for Word VM to convert (timeout=%ds)...", job_id[:8], DOCSERVER_TIMEOUT)
while time.monotonic() < deadline:
try:
mc.stat_object(_MINIO_BUCKET, out_key)
# Object exists — download it
LOG.info("[%s] PDF ready — downloading", job_id[:8])
mc.fget_object(_MINIO_BUCKET, out_key, str(pdf_path))
# Clean up the converted output from MinIO
try:
mc.remove_object(_MINIO_BUCKET, out_key)
except Exception:
pass
LOG.info("[%s] PDF written: %s (%d bytes)", job_id[:8], pdf_path.name, pdf_path.stat().st_size)
return pdf_path
except Exception:
# Object not there yet — keep waiting
time.sleep(_POLL_INTERVAL)
# Timed out — clean up the orphaned DOCX and raise
try:
mc.remove_object(_MINIO_BUCKET, in_key)
except Exception:
pass
raise TimeoutError(
f"Word VM did not convert {docx_path.name} within {DOCSERVER_TIMEOUT}s. "
f"Is docserver_worker.py running and connected to MinIO?"
)
def _batch_via_minio(docx_paths: list[Path], output_dir: Path) -> list[Path]:
"""Submit all DOCX files in parallel, collect results."""
import threading
results: list[Path | None] = [None] * len(docx_paths)
errors: list[str | None] = [None] * len(docx_paths)
def _convert_one(idx: int, docx_path: Path) -> None:
pdf_path = output_dir / docx_path.with_suffix(".pdf").name
try:
results[idx] = _convert_via_minio(docx_path, pdf_path)
except Exception as exc:
LOG.error("Batch item %d (%s) failed: %s", idx, docx_path.name, exc)
errors[idx] = str(exc)
# Fallback per-file
try:
results[idx] = _convert_via_libreoffice(docx_path, pdf_path, output_dir)
except Exception as lo_exc:
LOG.error("LibreOffice fallback also failed for %s: %s", docx_path.name, lo_exc)
threads = [
threading.Thread(target=_convert_one, args=(i, p), daemon=True)
for i, p in enumerate(docx_paths)
]
for t in threads:
t.start()
for t in threads:
t.join(timeout=DOCSERVER_TIMEOUT + 10)
return [r for r in results if r is not None]
# ── LibreOffice fallback ──────────────────────────────────────────────────────
def _convert_via_libreoffice(docx_path: Path, pdf_path: Path, out_dir: Path) -> Path:
"""Convert DOCX to PDF using LibreOffice headless (fallback)."""
LOG.info("Converting %s via LibreOffice headless...", docx_path.name)
cmd = [
"libreoffice", "--headless",
"--convert-to", "pdf",
"--outdir", str(out_dir),
str(docx_path),
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
if result.returncode != 0:
LOG.error("LibreOffice conversion failed: %s", result.stderr)
raise RuntimeError(f"LibreOffice failed: {result.stderr[:300]}")
if not pdf_path.exists():
raise RuntimeError(f"PDF not found at expected path after LibreOffice: {pdf_path}")
LOG.info("PDF created via LibreOffice: %s (%d bytes)", pdf_path.name, pdf_path.stat().st_size)
return pdf_path

View file

@ -0,0 +1,213 @@
"""
CALEA SSI Plan Audio Bridging / Conferencing variant.
Audio bridging / conferencing is narrowly scoped for CALEA purposes.
To the extent the service qualifies as an information service rather
than as telecommunications (47 USC § 153(24) vs. § 153(53)), the CALEA
covered-entity definition at 47 USC § 1001(8)(B)(ii) may not apply.
For the telecommunications-service portion that does apply, intercept
capability is provisioned at the bridge/softswitch; non-real-time
replay of recordings is treated as a stored-record production under
18 USC § 2703 rather than as a real-time intercept under Title III.
"""
from __future__ import annotations
import logging
from datetime import date
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.calea_audio_bridge")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CALEA Audio Bridge unavailable")
Document = None # type: ignore[assignment,misc]
NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "audio_bridging"
VARIANT_LABEL = "Audio Bridging / Conferencing"
def _heading(doc, text):
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(12); p.paragraph_format.space_after = Pt(4)
r = p.add_run(text); r.bold = True; r.font.size = Pt(13); r.font.color.rgb = NAVY
def _body(doc, text, bold=False):
p = doc.add_paragraph(); p.paragraph_format.space_after = Pt(6)
r = p.add_run(text); r.font.size = Pt(11); r.bold = bold
def _bullets(doc, items):
for it in items:
p = doc.add_paragraph(style="List Bullet")
p.paragraph_format.left_indent = Inches(0.25)
p.paragraph_format.space_after = Pt(3)
p.clear(); r = p.add_run(it); r.font.size = Pt(11)
def generate_calea_audio_bridge(
output_path: str,
entity_name: str,
frn: str = "",
law_enforcement_contact: Optional[dict] = None,
cpni_protection_officer: Optional[dict] = None,
network_infrastructure_summary: str = "",
interception_support_method: str = "",
reporting_year: int = 0,
signatory_name: str = "",
signatory_title: str = "Chief Executive Officer",
effective_date: str = "",
next_review_date: str = "",
reviewer_name: str = "Justin Hannah",
reviewer_company: str = "Performance West Inc.",
**_: dict,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
le = law_enforcement_contact or {}
cpni = cpni_protection_officer or {}
today = date.today()
effective = effective_date or today.strftime("%m/%d/%Y")
next_review = next_review_date or today.replace(year=today.year + 1).strftime("%m/%d/%Y")
doc = Document()
for s in doc.sections:
s.top_margin = Inches(1); s.bottom_margin = Inches(1)
s.left_margin = Inches(1.25); s.right_margin = Inches(1.25)
title = doc.add_paragraph(); title.alignment = WD_ALIGN_PARAGRAPH.CENTER
tr = title.add_run("System Security and Integrity (SSI) Plan")
tr.font.size = Pt(15); tr.bold = True; tr.font.color.rgb = NAVY
sub = doc.add_paragraph(); sub.alignment = WD_ALIGN_PARAGRAPH.CENTER
sr = sub.add_run(entity_name); sr.font.size = Pt(13); sr.bold = True
vsub = doc.add_paragraph(); vsub.alignment = WD_ALIGN_PARAGRAPH.CENTER
vr = vsub.add_run(f"Variant: {VARIANT_LABEL}")
vr.font.size = Pt(11); vr.italic = True
cite = doc.add_paragraph(); cite.alignment = WD_ALIGN_PARAGRAPH.CENTER
cr = cite.add_run("Pursuant to 47 U.S.C. \u00a7 229 and 47 CFR \u00a7 1.20003")
cr.font.size = Pt(10); cr.italic = True
cite.paragraph_format.space_after = Pt(18)
_heading(doc, "1. Purpose and Scope Note")
_body(doc, (
f"This SSI Plan governs {entity_name}'s compliance with CALEA to "
f"the extent {entity_name}'s audio bridging / conferencing "
f"offerings constitute telecommunications service under 47 USC "
f"\u00a7 153(53) or are otherwise within the CALEA covered-entity "
f"definition at 47 USC \u00a7 1001(8). Portions of the service "
f"that constitute information service under 47 USC \u00a7 153(24) "
f"are outside the scope of CALEA."
))
_heading(doc, "2. Scope and Applicability")
_body(doc, (
f"{entity_name} operates conference-bridge / softswitch elements "
f"and ingress / egress SIP trunks connecting to the PSTN. For "
f"the telecommunications-service portion of the offering, CALEA "
f"obligations attach; for any information-service portion "
f"(non-real-time recorded replay, data-only collaboration "
f"features), CALEA does not apply."
))
_heading(doc, "3. Designated Law Enforcement Contact (24-hour)")
_body(doc, (
f"Per 47 CFR \u00a7 1.20003(a)(1), {entity_name} designates the "
f"following senior officer as 24-hour contact for law enforcement "
f"service of process (court orders, pen register / trap-and-trace, "
f"Title III)."
))
_bullets(doc, [
f"Name: {le.get('name') or '[TO BE POPULATED]'}",
f"Title: {le.get('title') or ''}",
f"Phone (24-hour): {le.get('phone') or ''}",
f"Email (24-hour): {le.get('email_24h') or ''}",
f"Backup contact: {le.get('backup_name') or '[TO BE POPULATED]'}",
])
_heading(doc, "4. Network Architecture and Interception Capability")
_body(doc, network_infrastructure_summary or (
f"{entity_name} operates a conference-bridge softswitch with SIP "
"trunks for inbound / outbound PSTN connectivity. Participant "
"identities are captured via caller-ID plus dial-in PIN."
))
_body(doc, interception_support_method or (
f"For real-time intercept orders directed at an identified "
f"participant or conference, {entity_name} provisions LI at the "
f"conference-bridge softswitch, mirroring content and "
f"call-identifying information to the requesting law-enforcement "
f"agency in a CALEA-safe-harbor-compliant format. Non-real-time "
f"productions (recorded conferences lawfully requested under "
f"18 USC \u00a7 2703) are handled as stored-record productions "
f"under the separate subpoena-response procedure and are not "
f"treated as real-time intercepts."
))
_heading(doc, "5. CPNI Safeguards")
_body(doc, (
f"{entity_name} maintains a separate CPNI procedure statement. "
f"The CPNI Protection Officer is:"
))
_bullets(doc, [
f"Name: {cpni.get('name') or '[TO BE POPULATED]'}",
f"Title: {cpni.get('title') or 'CPNI Protection Officer'}",
])
_heading(doc, "6. Personnel Vetting and Training")
_bullets(doc, [
"Annual CALEA + CPNI training for personnel with bridge-admin or "
"subpoena-response duties.",
"Background checks performed prior to grant of access.",
"Access revoked within 24 hours of termination.",
"Bridge-admin and LI actions attributed to authenticated named "
"users.",
])
_heading(doc, "7. Supervisory Review")
_body(doc, (
f"The {le.get('title') or 'Designated Senior Officer'} reviews LI "
f"and subpoena-response activity at least quarterly."
))
_heading(doc, "8. Records Retention")
_body(doc, (
"LI provisioning and service-of-process records retained ten (10) "
"years per 47 CFR \u00a7 1.20003(b); CPNI access logs retained at "
"least two (2) years per 47 CFR \u00a7 64.2009."
))
_heading(doc, "9. Annual Review")
_body(doc, (
f"Reviewed at least annually. Next scheduled review: {next_review}."
))
_heading(doc, "10. Certification")
_body(doc, (
f"I, {signatory_name or '[Authorized Officer]'}, as "
f"{signatory_title} of {entity_name}, certify that I have "
f"reviewed this SSI Plan and that {entity_name} complies with 47 "
f"U.S.C. \u00a7 229 and 47 CFR \u00a7 1.20003 with respect to "
f"the telecommunications-service portion of its offerings."
))
_body(doc, "")
doc.add_paragraph("_" * 45)
_body(doc, signatory_name or "[Authorized Officer]", bold=True)
_body(doc, f"{signatory_title}, {entity_name}")
_body(doc, f"Effective Date: {effective}")
if frn: _body(doc, f"FRN: {frn}")
_body(doc, f"Reviewed By: {reviewer_name}, {reviewer_company}")
_body(doc, f"Next Review Date: {next_review}")
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CALEA Audio Bridge SSI plan generated: %s", out)
return str(out)

View file

@ -0,0 +1,250 @@
"""
CALEA System Security and Integrity (SSI) Plan CLEC SS7 / facilities.
Tailored variant of the generic CALEA SSI plan for a Competitive Local
Exchange Carrier that operates its own TDM / SS7 / SIGTRAN switching
infrastructure. The lawful-intercept method is provisioned at the Class 5
softswitch and at the SS7 / SIGTRAN STPs using the industry-standard
ATIS J-STD-025 interface. CALEA scope covers both local-exchange
switching and resold access transport.
"""
from __future__ import annotations
import logging
from datetime import date
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.calea_clec_ss7")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CALEA CLEC SS7 unavailable")
Document = None # type: ignore[assignment,misc]
NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "clec_ss7"
VARIANT_LABEL = "Competitive Local Exchange Carrier — SS7 / SIGTRAN"
def _heading(doc, text):
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(12)
p.paragraph_format.space_after = Pt(4)
r = p.add_run(text); r.bold = True; r.font.size = Pt(13)
r.font.color.rgb = NAVY
def _body(doc, text, bold=False):
p = doc.add_paragraph()
p.paragraph_format.space_after = Pt(6)
r = p.add_run(text); r.font.size = Pt(11); r.bold = bold
def _bullets(doc, items):
for it in items:
p = doc.add_paragraph(style="List Bullet")
p.paragraph_format.left_indent = Inches(0.25)
p.paragraph_format.space_after = Pt(3)
p.clear()
r = p.add_run(it); r.font.size = Pt(11)
def generate_calea_clec_ss7(
output_path: str,
entity_name: str,
frn: str = "",
law_enforcement_contact: Optional[dict] = None,
cpni_protection_officer: Optional[dict] = None,
network_infrastructure_summary: str = "",
interception_support_method: str = "",
reporting_year: int = 0,
signatory_name: str = "",
signatory_title: str = "Chief Executive Officer",
effective_date: str = "",
next_review_date: str = "",
reviewer_name: str = "Justin Hannah",
reviewer_company: str = "Performance West Inc.",
**_: dict,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
le = law_enforcement_contact or {}
cpni = cpni_protection_officer or {}
today = date.today()
effective = effective_date or today.strftime("%m/%d/%Y")
next_review = next_review_date or today.replace(year=today.year + 1).strftime("%m/%d/%Y")
doc = Document()
for s in doc.sections:
s.top_margin = Inches(1); s.bottom_margin = Inches(1)
s.left_margin = Inches(1.25); s.right_margin = Inches(1.25)
title = doc.add_paragraph(); title.alignment = WD_ALIGN_PARAGRAPH.CENTER
tr = title.add_run("System Security and Integrity (SSI) Plan")
tr.font.size = Pt(15); tr.bold = True; tr.font.color.rgb = NAVY
sub = doc.add_paragraph(); sub.alignment = WD_ALIGN_PARAGRAPH.CENTER
sr = sub.add_run(entity_name)
sr.font.size = Pt(13); sr.bold = True
vsub = doc.add_paragraph(); vsub.alignment = WD_ALIGN_PARAGRAPH.CENTER
vr = vsub.add_run(f"Variant: {VARIANT_LABEL}")
vr.font.size = Pt(11); vr.italic = True
cite = doc.add_paragraph(); cite.alignment = WD_ALIGN_PARAGRAPH.CENTER
cr = cite.add_run(
"Pursuant to 47 U.S.C. \u00a7 229 and 47 CFR \u00a7 1.20003"
)
cr.font.size = Pt(10); cr.italic = True
cite.paragraph_format.space_after = Pt(18)
_heading(doc, "1. Purpose")
_body(doc, (
f"This System Security and Integrity (SSI) Plan governs {entity_name}'s "
f"compliance with the Communications Assistance for Law Enforcement "
f"Act (CALEA), 47 U.S.C. \u00a7\u00a7 1001\u20131010, and the "
f"Commission's rules at 47 CFR Part 1 Subpart Z, as applied to "
f"{entity_name}'s operations as a Competitive Local Exchange Carrier "
f"(CLEC) with SS7 / SIGTRAN switching infrastructure."
))
_heading(doc, "2. Scope and Applicability")
_body(doc, (
f"{entity_name} is subject to CALEA as a facilities-based provider "
f"of common-carrier local exchange service. Its covered equipment "
f"includes Class 5 softswitch(es), trunk gateways, SS7 / SIGTRAN "
f"STPs, and signaling-link interconnections to interexchange "
f"carriers and to the public switched telephone network."
))
_heading(doc, "3. Designated Law Enforcement Contact (24-hour)")
_body(doc, (
f"Per 47 CFR \u00a7 1.20003(a)(1), {entity_name} designates the "
f"following senior officer as point of contact for law enforcement "
f"inquiries, court orders, pen register / trap-and-trace orders, "
f"and Title III wiretap orders. This contact is staffed 24 hours "
f"a day, 365 days a year."
))
_bullets(doc, [
f"Name: {le.get('name') or '[TO BE POPULATED]'}",
f"Title: {le.get('title') or ''}",
f"Phone (24-hour): {le.get('phone') or ''}",
f"Email (24-hour): {le.get('email_24h') or ''}",
f"Backup contact: {le.get('backup_name') or '[TO BE POPULATED]'}",
])
_body(doc, (
f"Service of process may be made on the above designee by "
f"telephone, email, or in person. {entity_name} commits to "
f"acknowledging any intercept or traffic-capture order within "
f"two (2) business hours of receipt."
))
_heading(doc, "4. Network Architecture and Interception Capability")
_body(doc, network_infrastructure_summary or (
f"{entity_name} operates a Class 5 softswitch (or TDM Class 5 "
"switch where retained) supported by redundant SS7 / SIGTRAN "
"signaling through owned or leased STPs. Customer access is "
"provided via copper loops, fiber, and resold UNE-P/loop "
"facilities where applicable. Interconnection with the PSTN is "
"by SS7 trunks to the relevant tandems."
))
_body(doc, interception_support_method or (
f"Lawful intercept is provisioned at the Class 5 softswitch and "
"at the SS7 / SIGTRAN STP in accordance with ATIS J-STD-025-B "
"(TIA/ANSI-41/GSM LAES). Call content is delivered to the "
"requesting law-enforcement agency via a Call Content Channel "
"(CCC) and call-identifying information via a Call Data Channel "
"(CDC), following the safe-harbor industry standard adopted by "
"the FCC under 47 CFR Part 1 Subpart Z. The Designated Senior "
"Officer coordinates provisioning, validates the court order, "
"and certifies activation to law enforcement."
))
_body(doc, (
f"{entity_name} retains copies of ATIS J-STD-025 compliance "
f"attestations from its switch and SS7 vendors, and maintains "
f"interconnection agreements with its tandem provider(s) that "
f"address CALEA responsibilities."
))
_heading(doc, "5. CPNI Safeguards")
_body(doc, (
f"{entity_name} maintains a separate, written CPNI procedure "
f"statement under 47 CFR \u00a7\u00a7 64.2001\u201364.2011. The "
f"CPNI Protection Officer is:"
))
_bullets(doc, [
f"Name: {cpni.get('name') or '[TO BE POPULATED]'}",
f"Title: {cpni.get('title') or 'CPNI Protection Officer'}",
])
_body(doc, (
"SS7 / SIGTRAN LIDB access, PIC records, and intercept "
"provisioning are all within the CPNI Protection Officer's "
"oversight scope."
))
_heading(doc, "6. Personnel Vetting and Training")
_bullets(doc, [
f"All {entity_name} personnel with access to intercept "
"provisioning interfaces complete annual CALEA and CPNI training.",
"Background checks are performed prior to granting access.",
"Access is revoked within 24 hours of termination.",
"All intercept-related actions are attributed to named "
"individuals via authenticated logins (no shared credentials).",
])
_heading(doc, "7. Supervisory Review")
_body(doc, (
f"The {le.get('title') or 'Designated Senior Officer'} reviews "
f"intercept-related activity at least quarterly. Anomalies "
f"(unauthorized access attempts, tampering, missed response SLAs) "
f"are escalated to the CEO within one business day of detection."
))
_heading(doc, "8. Records Retention")
_body(doc, (
"Records of intercept provisioning, service of process, "
"acknowledgments, and termination are retained for a minimum of "
"ten (10) years per 47 CFR \u00a7 1.20003(b). CPNI access logs "
"are retained at least two (2) years per 47 CFR \u00a7 64.2009."
))
_heading(doc, "9. Annual Review")
_body(doc, (
f"This Plan is reviewed at least annually and updated upon "
f"(i) material change to the switching infrastructure, "
f"(ii) change of upstream tandem or IXC interconnection, "
f"(iii) new Commission / DOJ guidance, or (iv) a material breach "
f"or near-miss. Next scheduled review: {next_review}."
))
_heading(doc, "10. Certification")
_body(doc, (
f"I, {signatory_name or '[Authorized Officer]'}, as "
f"{signatory_title} of {entity_name}, certify that I have "
f"reviewed this SSI Plan and that {entity_name} has implemented "
f"the policies, procedures, and technical measures described "
f"herein, and complies with 47 U.S.C. \u00a7 229 and 47 CFR "
f"\u00a7 1.20003."
))
_body(doc, "")
doc.add_paragraph("_" * 45)
_body(doc, signatory_name or "[Authorized Officer]", bold=True)
_body(doc, f"{signatory_title}, {entity_name}")
_body(doc, f"Effective Date: {effective}")
if frn:
_body(doc, f"FRN: {frn}")
_body(doc, f"Reviewed By: {reviewer_name}, {reviewer_company}")
_body(doc, f"Next Review Date: {next_review}")
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CALEA CLEC SS7 SSI plan generated: %s", out)
return str(out)

View file

@ -0,0 +1,219 @@
"""
CALEA System Security and Integrity (SSI) Plan IXC SS7.
Interexchange-carrier variant of the CALEA SSI plan. The lawful-
intercept method is provisioned at IXC tandem / Class 4 switching
elements (or softswitch equivalents) using SS7 signaling, and covers
both content and call-identifying information for pen-register /
trap-and-trace and Title III orders directed at toll calls.
"""
from __future__ import annotations
import logging
from datetime import date
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.calea_ixc_ss7")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CALEA IXC SS7 unavailable")
Document = None # type: ignore[assignment,misc]
NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "ixc_ss7"
VARIANT_LABEL = "Interexchange Carrier — SS7 / SIGTRAN"
def _heading(doc, text):
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(12); p.paragraph_format.space_after = Pt(4)
r = p.add_run(text); r.bold = True; r.font.size = Pt(13); r.font.color.rgb = NAVY
def _body(doc, text, bold=False):
p = doc.add_paragraph(); p.paragraph_format.space_after = Pt(6)
r = p.add_run(text); r.font.size = Pt(11); r.bold = bold
def _bullets(doc, items):
for it in items:
p = doc.add_paragraph(style="List Bullet")
p.paragraph_format.left_indent = Inches(0.25)
p.paragraph_format.space_after = Pt(3)
p.clear()
r = p.add_run(it); r.font.size = Pt(11)
def generate_calea_ixc_ss7(
output_path: str,
entity_name: str,
frn: str = "",
law_enforcement_contact: Optional[dict] = None,
cpni_protection_officer: Optional[dict] = None,
network_infrastructure_summary: str = "",
interception_support_method: str = "",
reporting_year: int = 0,
signatory_name: str = "",
signatory_title: str = "Chief Executive Officer",
effective_date: str = "",
next_review_date: str = "",
reviewer_name: str = "Justin Hannah",
reviewer_company: str = "Performance West Inc.",
**_: dict,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
le = law_enforcement_contact or {}
cpni = cpni_protection_officer or {}
today = date.today()
effective = effective_date or today.strftime("%m/%d/%Y")
next_review = next_review_date or today.replace(year=today.year + 1).strftime("%m/%d/%Y")
doc = Document()
for s in doc.sections:
s.top_margin = Inches(1); s.bottom_margin = Inches(1)
s.left_margin = Inches(1.25); s.right_margin = Inches(1.25)
title = doc.add_paragraph(); title.alignment = WD_ALIGN_PARAGRAPH.CENTER
tr = title.add_run("System Security and Integrity (SSI) Plan")
tr.font.size = Pt(15); tr.bold = True; tr.font.color.rgb = NAVY
sub = doc.add_paragraph(); sub.alignment = WD_ALIGN_PARAGRAPH.CENTER
sr = sub.add_run(entity_name); sr.font.size = Pt(13); sr.bold = True
vsub = doc.add_paragraph(); vsub.alignment = WD_ALIGN_PARAGRAPH.CENTER
vr = vsub.add_run(f"Variant: {VARIANT_LABEL}")
vr.font.size = Pt(11); vr.italic = True
cite = doc.add_paragraph(); cite.alignment = WD_ALIGN_PARAGRAPH.CENTER
cr = cite.add_run("Pursuant to 47 U.S.C. \u00a7 229 and 47 CFR \u00a7 1.20003")
cr.font.size = Pt(10); cr.italic = True
cite.paragraph_format.space_after = Pt(18)
_heading(doc, "1. Purpose")
_body(doc, (
f"This SSI Plan governs {entity_name}'s compliance with CALEA and "
f"the Commission's implementing rules as applied to {entity_name}'s "
f"operations as an interexchange (toll) carrier utilizing SS7 / "
f"SIGTRAN signaling."
))
_heading(doc, "2. Scope and Applicability")
_body(doc, (
f"{entity_name} is a provider of interexchange (toll) service "
f"subject to CALEA. Its covered equipment includes IXC tandem / "
f"Class 4 switching elements or softswitch equivalents, SS7 / "
f"SIGTRAN signaling, billing-record systems, and trunk "
f"interconnections with IXC peers, LECs, and wireless carriers."
))
_heading(doc, "3. Designated Law Enforcement Contact (24-hour)")
_body(doc, (
f"Per 47 CFR \u00a7 1.20003(a)(1), {entity_name} designates the "
f"following 24-hour point of contact for court orders, pen "
f"register / trap-and-trace orders, and Title III wiretap orders."
))
_bullets(doc, [
f"Name: {le.get('name') or '[TO BE POPULATED]'}",
f"Title: {le.get('title') or ''}",
f"Phone (24-hour): {le.get('phone') or ''}",
f"Email (24-hour): {le.get('email_24h') or ''}",
f"Backup contact: {le.get('backup_name') or '[TO BE POPULATED]'}",
])
_body(doc, (
f"{entity_name} commits to acknowledging any order within two (2) "
f"business hours of receipt."
))
_heading(doc, "4. Network Architecture and Interception Capability")
_body(doc, network_infrastructure_summary or (
f"{entity_name} operates softswitch / Class 4 tandem elements "
"with redundant SS7 / SIGTRAN signaling for toll call control. "
"Trunk peering with LECs, other IXCs, and wireless carriers is "
"established via SS7 trunks."
))
_body(doc, interception_support_method or (
f"Toll-call lawful intercept is provisioned at {entity_name}'s "
"softswitch / tandem under ATIS J-STD-025-B. Call content is "
"delivered via Call Content Channel (CCC); call-identifying "
"information via Call Data Channel (CDC). The Designated Senior "
"Officer validates the court order, coordinates provisioning, "
"and certifies activation to the requesting law-enforcement "
"agency."
))
_heading(doc, "5. CPNI Safeguards")
_body(doc, (
f"{entity_name} maintains a separate CPNI procedure statement "
f"under 47 CFR \u00a7\u00a7 64.2001\u201364.2011. The CPNI "
f"Protection Officer is:"
))
_bullets(doc, [
f"Name: {cpni.get('name') or '[TO BE POPULATED]'}",
f"Title: {cpni.get('title') or 'CPNI Protection Officer'}",
])
_body(doc, (
"Toll call-record databases, PIC-administration interfaces, and "
"intercept provisioning are all within the CPNI Protection "
"Officer's oversight scope."
))
_heading(doc, "6. Personnel Vetting and Training")
_bullets(doc, [
"Annual CALEA + CPNI training for all personnel with intercept "
"or CPNI access.",
"Background checks prior to grant of access.",
"Access revoked within 24 hours of termination.",
"All intercept actions attributed to authenticated named users.",
])
_heading(doc, "7. Supervisory Review")
_body(doc, (
f"The {le.get('title') or 'Designated Senior Officer'} reviews "
f"intercept activity at least quarterly. Anomalies are escalated "
f"to the CEO within one business day."
))
_heading(doc, "8. Records Retention")
_body(doc, (
"Intercept provisioning and service-of-process records retained "
"ten (10) years per 47 CFR \u00a7 1.20003(b); CPNI access logs "
"retained at least two (2) years per 47 CFR \u00a7 64.2009."
))
_heading(doc, "9. Annual Review")
_body(doc, (
f"This Plan is reviewed at least annually and upon material "
f"infrastructure / interconnection change. Next scheduled review: "
f"{next_review}."
))
_heading(doc, "10. Certification")
_body(doc, (
f"I, {signatory_name or '[Authorized Officer]'}, as "
f"{signatory_title} of {entity_name}, certify that I have "
f"reviewed this SSI Plan and that {entity_name} complies with 47 "
f"U.S.C. \u00a7 229 and 47 CFR \u00a7 1.20003."
))
_body(doc, "")
doc.add_paragraph("_" * 45)
_body(doc, signatory_name or "[Authorized Officer]", bold=True)
_body(doc, f"{signatory_title}, {entity_name}")
_body(doc, f"Effective Date: {effective}")
if frn: _body(doc, f"FRN: {frn}")
_body(doc, f"Reviewed By: {reviewer_name}, {reviewer_company}")
_body(doc, f"Next Review Date: {next_review}")
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CALEA IXC SS7 SSI plan generated: %s", out)
return str(out)

View file

@ -0,0 +1,220 @@
"""
CALEA SSI Plan Satellite (MSS / FSS) variant.
Satellite carriers that provide telecommunications service (MSS) or
facilitate it (certain FSS transport arrangements) are subject to CALEA.
Intercept capability is generally provisioned at the ground segment
i.e., the earth station / NOC / IP gateway where subscriber sessions
terminate before hand-off to the PSTN or public Internet. This variant
documents the ground-segment intercept model, the Part 25 physical-
security controls, and the delegation to terrestrial-network partners
where applicable.
"""
from __future__ import annotations
import logging
from datetime import date
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.calea_satellite")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CALEA Satellite unavailable")
Document = None # type: ignore[assignment,misc]
NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "satellite"
VARIANT_LABEL = "Satellite (MSS / FSS)"
def _heading(doc, text):
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(12); p.paragraph_format.space_after = Pt(4)
r = p.add_run(text); r.bold = True; r.font.size = Pt(13); r.font.color.rgb = NAVY
def _body(doc, text, bold=False):
p = doc.add_paragraph(); p.paragraph_format.space_after = Pt(6)
r = p.add_run(text); r.font.size = Pt(11); r.bold = bold
def _bullets(doc, items):
for it in items:
p = doc.add_paragraph(style="List Bullet")
p.paragraph_format.left_indent = Inches(0.25)
p.paragraph_format.space_after = Pt(3)
p.clear(); r = p.add_run(it); r.font.size = Pt(11)
def generate_calea_satellite(
output_path: str,
entity_name: str,
frn: str = "",
law_enforcement_contact: Optional[dict] = None,
cpni_protection_officer: Optional[dict] = None,
network_infrastructure_summary: str = "",
interception_support_method: str = "",
reporting_year: int = 0,
signatory_name: str = "",
signatory_title: str = "Chief Executive Officer",
effective_date: str = "",
next_review_date: str = "",
reviewer_name: str = "Justin Hannah",
reviewer_company: str = "Performance West Inc.",
**_: dict,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
le = law_enforcement_contact or {}
cpni = cpni_protection_officer or {}
today = date.today()
effective = effective_date or today.strftime("%m/%d/%Y")
next_review = next_review_date or today.replace(year=today.year + 1).strftime("%m/%d/%Y")
doc = Document()
for s in doc.sections:
s.top_margin = Inches(1); s.bottom_margin = Inches(1)
s.left_margin = Inches(1.25); s.right_margin = Inches(1.25)
title = doc.add_paragraph(); title.alignment = WD_ALIGN_PARAGRAPH.CENTER
tr = title.add_run("System Security and Integrity (SSI) Plan")
tr.font.size = Pt(15); tr.bold = True; tr.font.color.rgb = NAVY
sub = doc.add_paragraph(); sub.alignment = WD_ALIGN_PARAGRAPH.CENTER
sr = sub.add_run(entity_name); sr.font.size = Pt(13); sr.bold = True
vsub = doc.add_paragraph(); vsub.alignment = WD_ALIGN_PARAGRAPH.CENTER
vr = vsub.add_run(f"Variant: {VARIANT_LABEL}")
vr.font.size = Pt(11); vr.italic = True
cite = doc.add_paragraph(); cite.alignment = WD_ALIGN_PARAGRAPH.CENTER
cr = cite.add_run(
"Pursuant to 47 U.S.C. \u00a7 229, 47 CFR \u00a7 1.20003, and "
"47 CFR Part 25"
)
cr.font.size = Pt(10); cr.italic = True
cite.paragraph_format.space_after = Pt(18)
_heading(doc, "1. Purpose")
_body(doc, (
f"This SSI Plan governs {entity_name}'s compliance with CALEA and "
f"47 CFR \u00a7 1.20003 as applied to {entity_name}'s operations "
f"as a provider of Mobile Satellite Service and/or Fixed Satellite "
f"Service telecommunications."
))
_heading(doc, "2. Scope and Applicability")
_body(doc, (
f"{entity_name} operates (or leases capacity from) a space segment "
f"and ground-segment infrastructure including earth stations, "
f"gateway facilities, and a network operations center (NOC). "
f"Subscriber sessions originate at user terminals, traverse the "
f"satellite, and terminate at ground-segment gateways before "
f"hand-off to terrestrial networks. CALEA obligations apply to "
f"the telecommunications-service portions of this traffic."
))
_heading(doc, "3. Designated Law Enforcement Contact (24-hour)")
_body(doc, (
f"Per 47 CFR \u00a7 1.20003(a)(1), {entity_name} designates the "
f"following senior officer as 24-hour contact for law enforcement "
f"service of process."
))
_bullets(doc, [
f"Name: {le.get('name') or '[TO BE POPULATED]'}",
f"Title: {le.get('title') or ''}",
f"Phone (24-hour): {le.get('phone') or ''}",
f"Email (24-hour): {le.get('email_24h') or ''}",
f"Backup contact: {le.get('backup_name') or '[TO BE POPULATED]'}",
])
_heading(doc, "4. Network Architecture and Interception Capability")
_body(doc, network_infrastructure_summary or (
f"{entity_name}'s ground segment comprises earth-station antennas, "
"baseband modems, gateway routing / softswitch elements, and NOC "
"monitoring. Physical access to these facilities is controlled "
"under the Part 25 earth-station license conditions."
))
_body(doc, interception_support_method or (
f"Lawful intercept is provisioned at the ground segment where "
"subscriber sessions are decrypted / de-encapsulated for hand-off. "
"Content and call-identifying information are delivered to the "
"requesting law-enforcement agency using the CALEA safe-harbor "
"interfaces (ATIS J-STD-025 for voice / TIA TR-45 equivalents for "
"data) or a mutually agreed alternative acceptable under 47 CFR "
"Part 1 Subpart Z. Where {entity_name} hands off traffic to a "
"terrestrial partner for switching or transport, the partner "
"supports intercept under its own CALEA plan and the plans are "
"coordinated."
).replace("{entity_name}", entity_name))
_heading(doc, "5. CPNI Safeguards")
_body(doc, (
f"{entity_name} maintains separate CPNI procedures under 47 CFR "
f"\u00a7\u00a7 64.2001\u201364.2011. Customer activation records, "
f"beam / transponder assignments, and NOC operator logs are "
f"within the CPNI Protection Officer's oversight. The CPNI "
f"Protection Officer is:"
))
_bullets(doc, [
f"Name: {cpni.get('name') or '[TO BE POPULATED]'}",
f"Title: {cpni.get('title') or 'CPNI Protection Officer'}",
])
_heading(doc, "6. Personnel Vetting and Training")
_bullets(doc, [
"Annual CALEA + CPNI training for NOC operators and LI-provisioning "
"personnel.",
"Background checks performed prior to granting access to ground-"
"segment provisioning systems.",
"Physical access to earth-station / NOC facilities controlled per "
"Part 25 license conditions.",
"LI provisioning attributed to named authenticated users.",
])
_heading(doc, "7. Supervisory Review")
_body(doc, (
f"The {le.get('title') or 'Designated Senior Officer'} reviews LI "
f"activity and NOC operator access logs at least quarterly."
))
_heading(doc, "8. Records Retention")
_body(doc, (
"LI provisioning and service-of-process records retained ten (10) "
"years per 47 CFR \u00a7 1.20003(b); CPNI access logs retained at "
"least two (2) years per 47 CFR \u00a7 64.2009."
))
_heading(doc, "9. Annual Review")
_body(doc, (
f"Reviewed at least annually and upon material change to the "
f"ground segment, earth-station license, or terrestrial hand-off "
f"arrangement. Next scheduled review: {next_review}."
))
_heading(doc, "10. Certification")
_body(doc, (
f"I, {signatory_name or '[Authorized Officer]'}, as "
f"{signatory_title} of {entity_name}, certify that I have "
f"reviewed this SSI Plan and that {entity_name} complies with 47 "
f"U.S.C. \u00a7 229 and 47 CFR \u00a7 1.20003."
))
_body(doc, "")
doc.add_paragraph("_" * 45)
_body(doc, signatory_name or "[Authorized Officer]", bold=True)
_body(doc, f"{signatory_title}, {entity_name}")
_body(doc, f"Effective Date: {effective}")
if frn: _body(doc, f"FRN: {frn}")
_body(doc, f"Reviewed By: {reviewer_name}, {reviewer_company}")
_body(doc, f"Next Review Date: {next_review}")
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CALEA Satellite SSI plan generated: %s", out)
return str(out)

View file

@ -0,0 +1,308 @@
"""
CALEA System Security and Integrity (SSI) Plan generator.
Under 47 USC § 229 and 47 CFR § 1.20003 every telecommunications carrier
(including interconnected VoIP providers) must maintain and review
annually a System Security and Integrity policy covering lawful-
intercept capability, CPNI safeguards, personnel vetting, supervisory
review, and records retention. The SSI plan is kept internally. It's
produced for DOJ on subpoena (28 CFR § 100.10) not routinely filed
with the FCC.
We generate a carrier-specific, signable DOCX that follows the 10-section
outline expected by DOJ / FCC Enforcement reviewers. Customer-specific
substitutions come from ``intake_data["calea_ssi"]``.
Usage:
from scripts.document_gen.templates.calea_ssi_generator import (
generate_calea_ssi_plan,
)
path = generate_calea_ssi_plan(
entity_name="Falcon Broadband LLC",
law_enforcement_contact={"name":"Jane Doe","title":"General Counsel",
"phone":"555-123-4567","email_24h":"le-contact@falcon.example.com"},
cpni_protection_officer={"name":"John Roe","title":"VP Operations"},
network_infrastructure_summary="FreeSWITCH cluster + Ribbon SBC; "
"trunking via Bandwidth.com + Inteliquent",
interception_support_method="CALEA intercept provided by our upstream "
"provider Bandwidth.com under the standard "
"CALEA Reference Model for VoIP",
output_path="/tmp/calea_ssi.docx",
)
"""
from __future__ import annotations
import logging
from datetime import date, datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.calea_ssi")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CALEA SSI generation unavailable")
Document = None # type: ignore[assignment,misc]
NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
def _heading(doc, text: str) -> None:
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(12)
p.paragraph_format.space_after = Pt(4)
run = p.add_run(text)
run.bold = True
run.font.size = Pt(13)
run.font.color.rgb = NAVY
def _body(doc, text: str, bold: bool = False) -> None:
p = doc.add_paragraph()
p.paragraph_format.space_after = Pt(6)
run = p.add_run(text)
run.font.size = Pt(11)
run.bold = bold
def _bullets(doc, items: list[str]) -> None:
for it in items:
p = doc.add_paragraph(style="List Bullet")
p.paragraph_format.left_indent = Inches(0.25)
p.paragraph_format.space_after = Pt(3)
p.clear()
run = p.add_run(it)
run.font.size = Pt(11)
def generate_calea_ssi_plan(
# Carrier identity
entity_name: str,
frn: str = "",
# Law enforcement designated 24-hour contact (47 CFR § 1.20003(a)(1))
law_enforcement_contact: Optional[dict] = None,
# CPNI protection officer (47 CFR § 64.2009(d))
cpni_protection_officer: Optional[dict] = None,
# Network / infrastructure
network_infrastructure_summary: str = "",
interception_support_method: str = "",
# Operational scope
is_interconnected_voip: bool = True,
is_wholesale: bool = False,
has_retail_customers: bool = True,
# Signatory (typically the officer named on the CPNI cert)
signatory_name: str = "",
signatory_title: str = "Chief Executive Officer",
# Dates
effective_date: str = "",
next_review_date: str = "",
# Reviewer (PW compliance team)
reviewer_name: str = "Justin Hannah",
reviewer_company: str = "Performance West Inc.",
# Output
output_path: str = "/tmp/calea_ssi_plan.docx",
) -> Optional[str]:
"""Produce the 10-section CALEA SSI Plan as a DOCX."""
if Document is None:
LOG.error("python-docx not installed")
return None
le = law_enforcement_contact or {}
cpni = cpni_protection_officer or {}
today = date.today()
effective = effective_date or today.strftime("%m/%d/%Y")
next_review = next_review_date or today.replace(year=today.year + 1).strftime("%m/%d/%Y")
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)
# Title
title = doc.add_paragraph()
title.alignment = WD_ALIGN_PARAGRAPH.CENTER
tr = title.add_run("System Security and Integrity (SSI) Plan")
tr.font.size = Pt(15); tr.bold = True; tr.font.color.rgb = NAVY
sub = doc.add_paragraph()
sub.alignment = WD_ALIGN_PARAGRAPH.CENTER
sr = sub.add_run(entity_name)
sr.font.size = Pt(13); sr.bold = True
cite = doc.add_paragraph()
cite.alignment = WD_ALIGN_PARAGRAPH.CENTER
cr = cite.add_run(
"Pursuant to 47 U.S.C. \u00a7 229 and 47 CFR \u00a7 1.20003"
)
cr.font.size = Pt(10); cr.italic = True
cite.paragraph_format.space_after = Pt(18)
# ── 1. Purpose ──────────────────────────────────────────────────
_heading(doc, "1. Purpose")
_body(doc, (
f"This System Security and Integrity (SSI) Plan governs {entity_name}'s "
f"compliance with the Communications Assistance for Law Enforcement "
f"Act (CALEA), 47 U.S.C. \u00a7\u00a7 1001\u20131010, and the Federal "
f"Communications Commission's implementing rules at 47 CFR Part 1 "
f"Subpart Z. It defines the procedures {entity_name} uses to "
f"support lawful electronic surveillance of its telecommunications "
f"and interconnected VoIP services while protecting customer "
f"privacy and the integrity of company operations."
))
# ── 2. Scope and Applicability ──────────────────────────────────
_heading(doc, "2. Scope and Applicability")
scope_bits = [f"{entity_name} is subject to CALEA as a provider of "]
if is_interconnected_voip:
scope_bits.append("interconnected Voice over Internet Protocol services ")
scope_bits.append("and has designed and implemented the systems described "
"herein to support lawful intercept obligations.")
_body(doc, "".join(scope_bits))
if has_retail_customers:
_body(doc, (
f"{entity_name} maintains retail customer relationships subject "
f"to the CPNI safeguards defined in Section 5."
))
if is_wholesale:
_body(doc, (
f"{entity_name} also operates in a wholesale capacity. Wholesale "
f"intercept requests are coordinated with the downstream service "
f"provider per the CALEA Reference Model."
))
# ── 3. Designated Law Enforcement Contact ──────────────────────
_heading(doc, "3. Designated Law Enforcement Contact (24-hour)")
_body(doc, (
f"Per 47 CFR \u00a7 1.20003(a)(1), {entity_name} designates the following "
f"senior officer as point of contact for law enforcement inquiries, "
f"court orders, pen register / trap-and-trace orders, and Title III "
f"wiretap orders. This contact is staffed 24 hours a day."
))
_bullets(doc, [
f"Name: {le.get('name') or '[TO BE POPULATED]'}",
f"Title: {le.get('title') or ''}",
f"Phone (24-hour): {le.get('phone') or ''}",
f"Email (24-hour): {le.get('email_24h') or ''}",
f"Backup contact: {le.get('backup_name') or '[TO BE POPULATED]'}",
])
_body(doc, (
f"Law enforcement officers may effect service of process on the "
f"above designee by telephone, email, or in person at the address "
f"of record. {entity_name} commits to acknowledging any intercept "
f"or traffic-capture order within two (2) business hours of receipt."
))
# ── 4. Network Architecture ────────────────────────────────────
_heading(doc, "4. Network Architecture and Interception Capability")
_body(doc, network_infrastructure_summary or (
f"{entity_name} operates a VoIP network consisting of session "
"border controllers (SBCs) for signaling, softswitch(es) for "
"call control, and DID origination / termination via "
"commercial-grade upstream providers."
))
_body(doc, interception_support_method or (
f"CALEA intercept capability is provided through {entity_name}'s "
"upstream voice service provider(s) under the standard CALEA "
"Reference Model for interconnected VoIP. Upon receipt of a valid "
"court order, the designated law enforcement contact coordinates "
"with the upstream provider's CALEA team to provision the intercept "
"at the upstream switching element."
))
_body(doc, (
f"{entity_name} retains documentation of CALEA implementation "
f"capability including upstream provider CALEA attestations, "
f"interconnection agreements, and ATIS J-STD-025 / TIA-J-STD-025 "
f"compliance references."
))
# ── 5. CPNI Safeguards ─────────────────────────────────────────
_heading(doc, "5. Customer Proprietary Network Information (CPNI) Safeguards")
_body(doc, (
f"{entity_name} maintains separate, written CPNI procedures under "
f"47 CFR \u00a7\u00a7 64.2001\u201364.2011. The CPNI Protection Officer is:"
))
_bullets(doc, [
f"Name: {cpni.get('name') or '[TO BE POPULATED]'}",
f"Title: {cpni.get('title') or 'CPNI Protection Officer'}",
])
_body(doc, (
"Access to CPNI is authorized only for legitimate business "
"purposes, supervised by the CPNI Protection Officer, and logged "
"for supervisory review. See the company's separate CPNI "
"Procedure Statement for detailed controls."
))
# ── 6. Personnel Vetting and Training ─────────────────────────
_heading(doc, "6. Personnel Vetting and Training")
_bullets(doc, [
f"All {entity_name} personnel with access to intercept systems or "
"CPNI complete annual CALEA and CPNI training.",
"Background checks are performed on all personnel prior to being "
"granted access to intercept provisioning interfaces.",
"Access is revoked within 24 hours of termination of employment.",
"All intercept-related actions are attributed to named individuals "
"via authenticated logins (no shared credentials).",
])
# ── 7. Supervisory Review ─────────────────────────────────────
_heading(doc, "7. Supervisory Review")
_body(doc, (
f"The {le.get('title') or 'Designated Senior Officer'} reviews all "
f"intercept-related activity no less than quarterly. Any anomaly "
f"(unauthorized access attempt, tampering, missed response SLA) "
f"is escalated to the CEO within one business day of detection."
))
# ── 8. Records Retention ──────────────────────────────────────
_heading(doc, "8. Records Retention")
_body(doc, (
"Records of intercept provisioning, service of process, "
"acknowledgments, and termination are retained for a minimum of "
"ten (10) years per 47 CFR \u00a7 1.20003(b). CPNI access logs are "
"retained for at least two (2) years per 47 CFR \u00a7 64.2009(c)."
))
# ── 9. Annual Review ──────────────────────────────────────────
_heading(doc, "9. Annual Review")
_body(doc, (
f"This Plan is reviewed at least annually by the designated senior "
f"officer and updated when: (i) a new class of service is offered, "
f"(ii) an upstream provider material to CALEA intercept capability "
f"changes, (iii) the FCC or DOJ issues new guidance, or (iv) a "
f"material breach or near-miss is identified. Next scheduled "
f"review: {next_review}."
))
# ── 10. Certification and Signature ───────────────────────────
_heading(doc, "10. Certification")
_body(doc, (
f"I, {signatory_name or '[Authorized Officer]'}, as "
f"{signatory_title} of {entity_name}, certify that I have reviewed "
f"this System Security and Integrity Plan and that {entity_name} "
f"has implemented the policies, procedures, and technical measures "
f"described herein. I further certify that {entity_name} complies "
f"with 47 U.S.C. \u00a7 229 and 47 CFR \u00a7 1.20003, and that "
f"{entity_name} will make this Plan available to the Commission "
f"and the Department of Justice on request."
))
_body(doc, "")
doc.add_paragraph("_" * 45)
_body(doc, signatory_name or "[Authorized Officer]", bold=True)
_body(doc, f"{signatory_title}, {entity_name}")
_body(doc, f"Effective Date: {effective}")
if frn:
_body(doc, f"FRN: {frn}")
_body(doc, f"Reviewed By: {reviewer_name}, {reviewer_company}")
_body(doc, f"Next Review Date: {next_review}")
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CALEA SSI plan generated: %s", out)
return str(out)

View file

@ -0,0 +1,231 @@
"""
CALEA System Security and Integrity (SSI) Plan Wireless (CMRS) variant.
Facilities-based wireless carrier SSI plan. LAES (Lawfully Authorized
Electronic Surveillance) capability is provisioned at the Mobile
Switching Center (MSC) / 4G EPC / 5G Core per 47 CFR § 20.13 and the
ATIS/3GPP LI standards. Content and call-identifying information are
delivered to law enforcement over the standardized LI interfaces (X1 /
X2 / X3 for 3GPP). The Plan also addresses per-device location data
as a CPNI safeguard integration point.
"""
from __future__ import annotations
import logging
from datetime import date
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.calea_wireless")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CALEA Wireless unavailable")
Document = None # type: ignore[assignment,misc]
NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "wireless"
VARIANT_LABEL = "Wireless (CMRS) Facilities"
def _heading(doc, text):
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(12); p.paragraph_format.space_after = Pt(4)
r = p.add_run(text); r.bold = True; r.font.size = Pt(13); r.font.color.rgb = NAVY
def _body(doc, text, bold=False):
p = doc.add_paragraph(); p.paragraph_format.space_after = Pt(6)
r = p.add_run(text); r.font.size = Pt(11); r.bold = bold
def _bullets(doc, items):
for it in items:
p = doc.add_paragraph(style="List Bullet")
p.paragraph_format.left_indent = Inches(0.25)
p.paragraph_format.space_after = Pt(3)
p.clear(); r = p.add_run(it); r.font.size = Pt(11)
def generate_calea_wireless(
output_path: str,
entity_name: str,
frn: str = "",
law_enforcement_contact: Optional[dict] = None,
cpni_protection_officer: Optional[dict] = None,
network_infrastructure_summary: str = "",
interception_support_method: str = "",
reporting_year: int = 0,
signatory_name: str = "",
signatory_title: str = "Chief Executive Officer",
effective_date: str = "",
next_review_date: str = "",
reviewer_name: str = "Justin Hannah",
reviewer_company: str = "Performance West Inc.",
**_: dict,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
le = law_enforcement_contact or {}
cpni = cpni_protection_officer or {}
today = date.today()
effective = effective_date or today.strftime("%m/%d/%Y")
next_review = next_review_date or today.replace(year=today.year + 1).strftime("%m/%d/%Y")
doc = Document()
for s in doc.sections:
s.top_margin = Inches(1); s.bottom_margin = Inches(1)
s.left_margin = Inches(1.25); s.right_margin = Inches(1.25)
title = doc.add_paragraph(); title.alignment = WD_ALIGN_PARAGRAPH.CENTER
tr = title.add_run("System Security and Integrity (SSI) Plan")
tr.font.size = Pt(15); tr.bold = True; tr.font.color.rgb = NAVY
sub = doc.add_paragraph(); sub.alignment = WD_ALIGN_PARAGRAPH.CENTER
sr = sub.add_run(entity_name); sr.font.size = Pt(13); sr.bold = True
vsub = doc.add_paragraph(); vsub.alignment = WD_ALIGN_PARAGRAPH.CENTER
vr = vsub.add_run(f"Variant: {VARIANT_LABEL}")
vr.font.size = Pt(11); vr.italic = True
cite = doc.add_paragraph(); cite.alignment = WD_ALIGN_PARAGRAPH.CENTER
cr = cite.add_run(
"Pursuant to 47 U.S.C. \u00a7 229, 47 CFR \u00a7 1.20003, "
"and 47 CFR \u00a7 20.13"
)
cr.font.size = Pt(10); cr.italic = True
cite.paragraph_format.space_after = Pt(18)
_heading(doc, "1. Purpose")
_body(doc, (
f"This SSI Plan governs {entity_name}'s compliance with CALEA "
f"(47 U.S.C. \u00a7\u00a7 1001\u20131010) and the Commission's "
f"rules at 47 CFR Part 1 Subpart Z and 47 CFR \u00a7 20.13 as "
f"applied to {entity_name}'s operations as a facilities-based "
f"Commercial Mobile Radio Service (CMRS) provider."
))
_heading(doc, "2. Scope and Applicability")
_body(doc, (
f"{entity_name} is a facilities-based CMRS provider subject to "
f"the Lawfully Authorized Electronic Surveillance (LAES) "
f"obligations of 47 CFR \u00a7 20.13. Its covered equipment "
f"includes the Mobile Switching Center (MSC), 4G Evolved Packet "
f"Core (EPC), 5G Core, HSS / UDM, SMS-C, and the associated "
f"radio-access network (eNB / gNB) provisioning systems."
))
_heading(doc, "3. Designated Law Enforcement Contact (24-hour)")
_body(doc, (
f"Per 47 CFR \u00a7 1.20003(a)(1), {entity_name} designates the "
f"following senior officer as 24-hour point of contact for court "
f"orders, pen-register/trap-and-trace orders, Title III wiretap "
f"orders, and location-information orders."
))
_bullets(doc, [
f"Name: {le.get('name') or '[TO BE POPULATED]'}",
f"Title: {le.get('title') or ''}",
f"Phone (24-hour): {le.get('phone') or ''}",
f"Email (24-hour): {le.get('email_24h') or ''}",
f"Backup contact: {le.get('backup_name') or '[TO BE POPULATED]'}",
])
_body(doc, (
f"{entity_name} commits to acknowledging any order within two (2) "
f"business hours of receipt."
))
_heading(doc, "4. Network Architecture and Interception Capability")
_body(doc, network_infrastructure_summary or (
f"{entity_name} operates a radio-access network (eNB / gNB), a 4G "
"EPC with MME / S-GW / P-GW elements, and where deployed a 5G "
"Core with AMF / SMF / UPF. Subscriber identity and location are "
"held in the HSS / UDM. Voice service is delivered via IMS / "
"VoLTE or via circuit-switched fallback."
))
_body(doc, interception_support_method or (
f"Lawful intercept (LAES) is provisioned at {entity_name}'s MSC / "
"EPC / 5GC elements using the 3GPP-standardized LI interfaces "
"(X1 for provisioning / administration, X2 for intercept-related "
"information, X3 for content-of-communications) per 3GPP TS "
"33.126 / 33.127 / 33.128 and ATIS T1.724 / J-STD-025. Call "
"content and call-identifying information (including cell-site "
"/ E911 / handover location data where lawfully ordered) are "
"delivered to the requesting agency through these standard "
"interfaces."
))
_heading(doc, "5. CPNI Safeguards")
_body(doc, (
f"{entity_name} maintains a separate CPNI procedure statement "
f"under 47 CFR \u00a7\u00a7 64.2001\u201364.2011. Device-level "
f"location data is treated as CPNI, consistent with the "
f"Commission's 2020 LocationSmart Consent Decree (DA 20-299) "
f"and 2024 NAL against unauthorized third-party location sharing. "
f"The CPNI Protection Officer is:"
))
_bullets(doc, [
f"Name: {cpni.get('name') or '[TO BE POPULATED]'}",
f"Title: {cpni.get('title') or 'CPNI Protection Officer'}",
])
_heading(doc, "6. Personnel Vetting and Training")
_bullets(doc, [
"Annual CALEA + CPNI training for all personnel with LI or CPNI "
"access.",
"Background checks performed prior to granting access to LI "
"provisioning or HSS / UDM systems.",
"Access revoked within 24 hours of termination.",
"All LI actions attributed to authenticated named users; no "
"shared credentials.",
])
_heading(doc, "7. Supervisory Review")
_body(doc, (
f"The {le.get('title') or 'Designated Senior Officer'} reviews "
f"LI activity logs at least quarterly. Anomalies are escalated "
f"to the CEO within one business day."
))
_heading(doc, "8. Records Retention")
_body(doc, (
"LI provisioning and service-of-process records retained ten (10) "
"years per 47 CFR \u00a7 1.20003(b); CPNI access logs retained at "
"least two (2) years per 47 CFR \u00a7 64.2009."
))
_heading(doc, "9. Annual Review")
_body(doc, (
f"This Plan is reviewed at least annually and upon (i) material "
f"core or RAN network change, (ii) new 3GPP LI release adoption, "
f"(iii) new Commission / DOJ guidance, or (iv) a material breach. "
f"Next scheduled review: {next_review}."
))
_heading(doc, "10. Certification")
_body(doc, (
f"I, {signatory_name or '[Authorized Officer]'}, as "
f"{signatory_title} of {entity_name}, certify that I have "
f"reviewed this SSI Plan and that {entity_name} complies with "
f"47 U.S.C. \u00a7 229, 47 CFR \u00a7 1.20003, and 47 CFR "
f"\u00a7 20.13."
))
_body(doc, "")
doc.add_paragraph("_" * 45)
_body(doc, signatory_name or "[Authorized Officer]", bold=True)
_body(doc, f"{signatory_title}, {entity_name}")
_body(doc, f"Effective Date: {effective}")
if frn: _body(doc, f"FRN: {frn}")
_body(doc, f"Reviewed By: {reviewer_name}, {reviewer_company}")
_body(doc, f"Next Review Date: {next_review}")
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CALEA Wireless SSI plan generated: %s", out)
return str(out)

View file

@ -0,0 +1,229 @@
"""
CALEA SSI Plan Wireless MVNO variant.
A Mobile Virtual Network Operator has no radio-access network and no
core-network switching of its own. Under the CALEA Reference Model, the
host MNO is responsible for actual lawful-intercept provisioning and
delivery; the MVNO's SSI Plan documents the division of responsibility,
the designated point of contact for law enforcement service of process,
and the contractual flow-down terms that obligate the host MNO to
support intercepts initiated against the MVNO's subscribers.
"""
from __future__ import annotations
import logging
from datetime import date
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.calea_wireless_mvno")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CALEA Wireless MVNO unavailable")
Document = None # type: ignore[assignment,misc]
NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "wireless_mvno"
VARIANT_LABEL = "Wireless (CMRS) — MVNO"
def _heading(doc, text):
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(12); p.paragraph_format.space_after = Pt(4)
r = p.add_run(text); r.bold = True; r.font.size = Pt(13); r.font.color.rgb = NAVY
def _body(doc, text, bold=False):
p = doc.add_paragraph(); p.paragraph_format.space_after = Pt(6)
r = p.add_run(text); r.font.size = Pt(11); r.bold = bold
def _bullets(doc, items):
for it in items:
p = doc.add_paragraph(style="List Bullet")
p.paragraph_format.left_indent = Inches(0.25)
p.paragraph_format.space_after = Pt(3)
p.clear(); r = p.add_run(it); r.font.size = Pt(11)
def generate_calea_wireless_mvno(
output_path: str,
entity_name: str,
frn: str = "",
law_enforcement_contact: Optional[dict] = None,
cpni_protection_officer: Optional[dict] = None,
network_infrastructure_summary: str = "",
interception_support_method: str = "",
reporting_year: int = 0,
host_mno_name: str = "",
signatory_name: str = "",
signatory_title: str = "Chief Executive Officer",
effective_date: str = "",
next_review_date: str = "",
reviewer_name: str = "Justin Hannah",
reviewer_company: str = "Performance West Inc.",
**_: dict,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
le = law_enforcement_contact or {}
cpni = cpni_protection_officer or {}
today = date.today()
effective = effective_date or today.strftime("%m/%d/%Y")
next_review = next_review_date or today.replace(year=today.year + 1).strftime("%m/%d/%Y")
host = host_mno_name or "its host Mobile Network Operator"
doc = Document()
for s in doc.sections:
s.top_margin = Inches(1); s.bottom_margin = Inches(1)
s.left_margin = Inches(1.25); s.right_margin = Inches(1.25)
title = doc.add_paragraph(); title.alignment = WD_ALIGN_PARAGRAPH.CENTER
tr = title.add_run("System Security and Integrity (SSI) Plan")
tr.font.size = Pt(15); tr.bold = True; tr.font.color.rgb = NAVY
sub = doc.add_paragraph(); sub.alignment = WD_ALIGN_PARAGRAPH.CENTER
sr = sub.add_run(entity_name); sr.font.size = Pt(13); sr.bold = True
vsub = doc.add_paragraph(); vsub.alignment = WD_ALIGN_PARAGRAPH.CENTER
vr = vsub.add_run(f"Variant: {VARIANT_LABEL}")
vr.font.size = Pt(11); vr.italic = True
cite = doc.add_paragraph(); cite.alignment = WD_ALIGN_PARAGRAPH.CENTER
cr = cite.add_run("Pursuant to 47 U.S.C. \u00a7 229 and 47 CFR \u00a7 1.20003")
cr.font.size = Pt(10); cr.italic = True
cite.paragraph_format.space_after = Pt(18)
_heading(doc, "1. Purpose")
_body(doc, (
f"This SSI Plan governs {entity_name}'s compliance with CALEA and "
f"its implementing rules as applied to {entity_name}'s operations "
f"as a Mobile Virtual Network Operator (MVNO) that resells "
f"wireless service provided by {host}."
))
_heading(doc, "2. Scope and Applicability — Division of Responsibility")
_body(doc, (
f"{entity_name} does not own or operate radio-access equipment, "
f"a Mobile Switching Center, an EPC / 5GC, or HSS / UDM. Under "
f"the CALEA Reference Model and the MVNO wholesale agreement "
f"between {entity_name} and {host}, intercept capability is "
f"provisioned and operated by {host}. {entity_name}'s SSI "
f"responsibility is limited to: (i) maintaining a designated "
f"24-hour law-enforcement point of contact, (ii) coordinating "
f"service of process between law enforcement and {host}, "
f"(iii) ensuring contractual flow-down of CALEA obligations to "
f"{host}, and (iv) protecting its own customer records."
))
_heading(doc, "3. Designated Law Enforcement Contact (24-hour)")
_body(doc, (
f"Per 47 CFR \u00a7 1.20003(a)(1), {entity_name} designates the "
f"following senior officer as 24-hour contact for law enforcement."
))
_bullets(doc, [
f"Name: {le.get('name') or '[TO BE POPULATED]'}",
f"Title: {le.get('title') or ''}",
f"Phone (24-hour): {le.get('phone') or ''}",
f"Email (24-hour): {le.get('email_24h') or ''}",
f"Backup contact: {le.get('backup_name') or '[TO BE POPULATED]'}",
])
_body(doc, (
f"Upon receipt of a valid court order, {entity_name}'s designated "
f"officer (a) acknowledges service within two (2) business hours, "
f"(b) confirms that the subscriber is provisioned on {host}'s "
f"network, and (c) coordinates with {host}'s CALEA / LAES team "
f"to effect intercept provisioning, providing the ordering "
f"agency with the appropriate host-MNO CALEA contact as "
f"required."
))
_heading(doc, "4. Network / Interception Capability (Host MNO)")
_body(doc, network_infrastructure_summary or (
f"Voice, SMS, and data services consumed by {entity_name}'s "
f"subscribers traverse {host}'s radio-access network and core. "
f"Authentication is performed against {host}'s HSS / UDM."
))
_body(doc, interception_support_method or (
f"Lawful intercept is provisioned by {host} using the standardized "
f"3GPP LI interfaces (X1 / X2 / X3) at {host}'s MSC / EPC / 5GC, "
f"per ATIS T1.724 / J-STD-025 and 3GPP TS 33.126 / 33.127 / "
f"33.128. {host} is responsible for delivering content and "
f"call-identifying information to the requesting law-enforcement "
f"agency."
))
_body(doc, (
f"{entity_name} retains an executed copy of the MVNO wholesale "
f"agreement with {host}, including the CALEA flow-down clauses, "
f"and a current copy of {host}'s CALEA attestation on file."
))
_heading(doc, "5. CPNI Safeguards")
_body(doc, (
f"{entity_name} maintains separate CPNI procedures under 47 CFR "
f"\u00a7\u00a7 64.2001\u201364.2011 with respect to retail "
f"customer records, billing data, and support interactions that "
f"{entity_name} directly controls. The CPNI Protection Officer is:"
))
_bullets(doc, [
f"Name: {cpni.get('name') or '[TO BE POPULATED]'}",
f"Title: {cpni.get('title') or 'CPNI Protection Officer'}",
])
_heading(doc, "6. Personnel Vetting and Training")
_bullets(doc, [
"Annual CALEA + CPNI training for personnel handling customer "
"records or law-enforcement service of process.",
"Background checks prior to granting access.",
"Access revoked within 24 hours of termination.",
"All service-of-process and CPNI actions attributed to named "
"authenticated users.",
])
_heading(doc, "7. Supervisory Review")
_body(doc, (
f"The {le.get('title') or 'Designated Senior Officer'} reviews "
f"service-of-process logs and MVNO-host coordination records at "
f"least quarterly."
))
_heading(doc, "8. Records Retention")
_body(doc, (
"Service-of-process coordination records retained ten (10) years "
"per 47 CFR \u00a7 1.20003(b); CPNI access logs retained at least "
"two (2) years per 47 CFR \u00a7 64.2009."
))
_heading(doc, "9. Annual Review")
_body(doc, (
f"This Plan is reviewed at least annually and upon any change to "
f"the MVNO wholesale agreement or to {host}'s CALEA attestation. "
f"Next scheduled review: {next_review}."
))
_heading(doc, "10. Certification")
_body(doc, (
f"I, {signatory_name or '[Authorized Officer]'}, as "
f"{signatory_title} of {entity_name}, certify that I have "
f"reviewed this SSI Plan and that {entity_name} complies with 47 "
f"U.S.C. \u00a7 229 and 47 CFR \u00a7 1.20003 through its MVNO "
f"wholesale arrangement with {host}."
))
_body(doc, "")
doc.add_paragraph("_" * 45)
_body(doc, signatory_name or "[Authorized Officer]", bold=True)
_body(doc, f"{signatory_title}, {entity_name}")
_body(doc, f"Effective Date: {effective}")
if frn: _body(doc, f"FRN: {frn}")
_body(doc, f"Reviewed By: {reviewer_name}, {reviewer_company}")
_body(doc, f"Next Review Date: {next_review}")
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CALEA Wireless MVNO SSI plan generated: %s", out)
return str(out)

View file

@ -0,0 +1,270 @@
"""Traffic Study generator — PDF + XLSX deliverable.
Takes a fully-rolled ``cdr_traffic_studies`` row and produces:
* a signed-ready DOCX (converted to PDF downstream) for the customer's
audit file, with methodology statement + both Block 5 regional
tables + revenue-vs-minutes cross-check
* an XLSX "working doc" with per-period rollups and the same cells
that will drop into the 499-A E-File session
Produced by ``CDRAnalysisHandler`` at the end of a reporting period.
Pre-existing infrastructure reused:
* python-docx for the DOCX
* openpyxl for the XLSX
* scripts.document_gen.templates.base_handler pattern for styling
No classification happens here this module only formats numbers that
the ingester + classifier already wrote into cdr_calls + cdr_traffic_studies.
"""
from __future__ import annotations
import logging
from datetime import datetime
from decimal import Decimal
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.cdr_traffic_study")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — traffic study generation unavailable")
Document = None # type: ignore[assignment,misc]
try:
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Border, Side
except ImportError:
LOG.warning("openpyxl not installed — xlsx export unavailable")
Workbook = None # type: ignore[assignment,misc]
NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
def _pct(value) -> str:
if value is None:
return ""
return f"{float(value):.2f}%"
def _dollars(cents: Optional[int]) -> str:
if cents is None:
return ""
return f"${cents/100:,.2f}"
def _minutes(seconds: Optional[int]) -> str:
if seconds is None:
return ""
return f"{seconds/60:,.0f}"
# ─── DOCX ───────────────────────────────────────────────────────────────
def generate_traffic_study_docx(
*,
study: dict,
entity_name: str,
frn: str = "",
filer_id_499: str = "",
output_path: str,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
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)
# Title
title = doc.add_paragraph()
title.alignment = WD_ALIGN_PARAGRAPH.CENTER
r = title.add_run(f"Telecommunications Traffic Study — {study['reporting_year']} {study['reporting_period']}")
r.font.size = Pt(14)
r.bold = True
r.font.color.rgb = NAVY
sub = doc.add_paragraph()
sub.alignment = WD_ALIGN_PARAGRAPH.CENTER
sub_r = sub.add_run(entity_name)
sub_r.font.size = Pt(12)
sub_r.bold = True
info = doc.add_paragraph()
info_r = info.add_run(
f"FRN: {frn or 'N/A'} | 499 Filer ID: {filer_id_499 or 'N/A'} | "
f"Generated: {datetime.now().strftime('%B %d, %Y')}"
)
info_r.font.size = Pt(9)
info_r.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
doc.add_paragraph()
# Methodology
doc.add_heading("Methodology", level=1)
method_paragraphs = [
(
f"This study analyzes {study.get('total_calls', 0):,} call detail records "
f"covering {study['reporting_year']} {study['reporting_period']}. "
"Each call was classified by endpoint geography using NANP area-code "
"records and FCC country-code assignments (47 CFR § 54.706 definitions). "
"Jurisdictional buckets are: interstate, intrastate, international, and "
"indeterminate (records where one or both endpoints could not be "
"resolved to a country/state)."
),
(
"Revenue-based weighting is used where the source CDR carries per-call "
"billing amounts. Minutes-weighted percentages are provided as a "
"cross-check. Records are five-year retained per 47 CFR § 54.711(a) "
"and available for USAC audit on request."
),
(study.get("methodology") or ""),
]
for text in method_paragraphs:
if text:
doc.add_paragraph(text)
# Jurisdictional table
doc.add_heading("Jurisdictional Breakdown", level=1)
juris_table = doc.add_table(rows=1, cols=3)
juris_table.style = "Table Grid"
hdr = juris_table.rows[0].cells
hdr[0].text = "Category"
hdr[1].text = "Revenue-weighted"
hdr[2].text = "Minutes-weighted"
for label, key_rev, key_min in [
("Interstate", "interstate_pct", "interstate_pct_minutes"),
("Intrastate", "intrastate_pct", "intrastate_pct_minutes"),
("International", "international_pct", "international_pct_minutes"),
("Indeterminate", "indeterminate_pct", "indeterminate_pct_minutes"),
]:
row = juris_table.add_row().cells
row[0].text = label
row[1].text = _pct(study.get(key_rev))
row[2].text = _pct(study.get(key_min))
# Wholesale vs retail
doc.add_heading("Block 3 vs. Block 4-A Allocation", level=1)
w_min = study.get("wholesale_minutes") or 0
r_min = study.get("retail_minutes") or 0
doc.add_paragraph(
f"Wholesale (carrier-to-carrier, Block 3): {w_min/60:,.0f} minutes\n"
f"Retail (end-user, Block 4-A): {r_min/60:,.0f} minutes"
)
# Block 5 regional — BOTH reports
for label, key in [
("Block 5 — by originating state of caller", "orig_state_regions_json"),
("Block 5 — by customer billing-address state", "billing_state_regions_json"),
]:
doc.add_heading(label, level=1)
regions = (study.get(key) or {})
if not regions:
doc.add_paragraph("(no data for this view)")
continue
table = doc.add_table(rows=1, cols=2)
table.style = "Table Grid"
h = table.rows[0].cells
h[0].text = "Region"
h[1].text = "% of Total"
for region_name, pct_val in sorted(regions.items()):
row = table.add_row().cells
row[0].text = region_name
row[1].text = _pct(pct_val)
doc.add_heading("Certification", level=1)
doc.add_paragraph(
f"I certify that this traffic study accurately reflects the "
f"telecommunications usage of {entity_name} during the reporting "
f"period. The underlying CDRs are retained for five years and "
f"available on request."
)
for _ in range(2):
doc.add_paragraph()
doc.add_paragraph("_" * 45)
doc.add_paragraph("Authorized Officer")
doc.add_paragraph(entity_name)
doc.add_paragraph(f"Date: {datetime.now().strftime('%B %d, %Y')}")
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
return str(out)
# ─── XLSX (admin working doc) ───────────────────────────────────────────
def generate_traffic_study_xlsx(
*,
study: dict,
entity_name: str,
output_path: str,
) -> Optional[str]:
if Workbook is None:
LOG.error("openpyxl not installed")
return None
wb = Workbook()
default = wb.active
wb.remove(default)
# Summary
ws = wb.create_sheet("Summary")
ws["A1"] = f"Traffic Study — {entity_name}"
ws["A1"].font = Font(bold=True, size=14, color="1A2744")
ws["A2"] = f"{study['reporting_year']} {study['reporting_period']}"
rows = [
("Total calls", study.get("total_calls") or 0),
("Total minutes", (study.get("total_minutes") or 0)),
("Total revenue (cents)", study.get("total_revenue_cents") or 0),
("", ""),
("Interstate % (revenue-weighted)", study.get("interstate_pct")),
("Intrastate % (revenue-weighted)", study.get("intrastate_pct")),
("International % (revenue-weighted)", study.get("international_pct")),
("Indeterminate % (revenue-weighted)", study.get("indeterminate_pct")),
("", ""),
("Interstate % (minutes-weighted)", study.get("interstate_pct_minutes")),
("Intrastate % (minutes-weighted)", study.get("intrastate_pct_minutes")),
("International % (minutes-weighted)", study.get("international_pct_minutes")),
("Indeterminate % (minutes-weighted)", study.get("indeterminate_pct_minutes")),
("", ""),
("Wholesale minutes (Block 3)", (study.get("wholesale_minutes") or 0) / 60),
("Retail minutes (Block 4-A)", (study.get("retail_minutes") or 0) / 60),
]
for i, (label, value) in enumerate(rows, start=4):
ws.cell(row=i, column=1, value=label)
ws.cell(row=i, column=2, value=value)
ws.column_dimensions["A"].width = 45
ws.column_dimensions["B"].width = 22
# Regional breakdowns
for sheet_name, key in [
("Block 5 — Orig State", "orig_state_regions_json"),
("Block 5 — Billing State", "billing_state_regions_json"),
]:
rs = wb.create_sheet(sheet_name)
rs.cell(row=1, column=1, value="Region").font = Font(bold=True)
rs.cell(row=1, column=2, value="% of Total").font = Font(bold=True)
regions = study.get(key) or {}
for i, (name, pct) in enumerate(sorted(regions.items()), start=2):
rs.cell(row=i, column=1, value=name)
rs.cell(row=i, column=2, value=float(pct) if pct is not None else None)
rs.cell(row=i, column=2).number_format = '0.00"%"'
rs.column_dimensions["A"].width = 25
rs.column_dimensions["B"].width = 15
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
wb.save(str(out))
return str(out)

View file

@ -0,0 +1,263 @@
"""
Generate the FCC CPNI Annual Certification Letter Audio Bridging variant.
Audio bridging / conferencing providers have a narrower CPNI scope than
ordinary carriers: CPNI is generally limited to participant dial-in
records, scheduled conference metadata, and enterprise billing records.
Per the Commission's longstanding treatment of non-real-time conferencing
services, some categories of conference metadata may fall outside the
definition of CPNI where the service is not "telecommunications service"
as defined in 47 USC § 153(53).
This certification addresses the CPNI {entity_name} does hold and states
expressly where non-real-time or information-service exceptions apply.
"""
from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.cpni_audio_bridge")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CPNI Audio Bridge generation unavailable")
Document = None # type: ignore[assignment,misc]
_NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "audio_bridging"
VARIANT_LABEL = "Audio Bridging / Conferencing"
MAX_FORFEITURE_PER_VIOLATION = "$251,322"
MAX_FORFEITURE_CAP = "$2,513,215"
def _sp(p, after=6, before=0):
p.paragraph_format.space_after = Pt(after)
if before:
p.paragraph_format.space_before = Pt(before)
def _h(doc, text):
p = doc.add_paragraph(); r = p.add_run(text)
r.font.size = Pt(12); r.bold = True; r.font.color.rgb = _NAVY
_sp(p, after=4, before=8)
def _b(doc, text, bold=False, size=10):
p = doc.add_paragraph(); p.alignment = WD_ALIGN_PARAGRAPH.LEFT
r = p.add_run(text); r.font.size = Pt(size); r.bold = bold
_sp(p, after=6)
def _cb(doc, text, checked=True):
mark = "\u2611" if checked else "\u2610"
p = doc.add_paragraph()
r = p.add_run(f" {mark} {text}"); r.font.size = Pt(10)
_sp(p, after=3)
def generate_cpni_audio_bridge(
output_path: str,
entity_name: str,
frn: str = "",
filer_id_499: str = "",
officer_name: str = "",
officer_title: str = "Chief Executive Officer",
complaints_count: int = 0,
complaints_description: str = "",
has_data_broker_inquiries: bool = False,
data_broker_description: str = "",
reporting_year: int = 0,
address_street: str = "",
address_city: str = "",
address_state: str = "",
address_zip: str = "",
contact_email: str = "",
contact_phone: str = "",
breaches: list[dict] | None = None,
**_: dict,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
if reporting_year == 0:
reporting_year = datetime.now().year - 1
breaches = breaches or []
doc = Document()
for s in doc.sections:
s.top_margin = Inches(1); s.bottom_margin = Inches(1)
s.left_margin = Inches(1.25); s.right_margin = Inches(1.25)
today = datetime.now().strftime("%B %d, %Y")
signer = officer_name or "Authorized Officer"
title = officer_title or "Officer"
tp = doc.add_paragraph(); tp.alignment = WD_ALIGN_PARAGRAPH.CENTER
t = tp.add_run("CPNI Annual Certification Letter")
t.font.size = Pt(14); t.bold = True; t.font.color.rgb = _NAVY
_sp(tp, after=2)
sp = doc.add_paragraph(); sp.alignment = WD_ALIGN_PARAGRAPH.CENTER
s = sp.add_run(
f"Audio Bridging / Conferencing \u2014 47 CFR \u00a7 64.2009 "
f"\u2014 Calendar Year {reporting_year}"
)
s.font.size = Pt(10); s.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
_sp(sp, after=8)
_h(doc, "1. Provider Information")
lines = [f"Company Name: {entity_name}", f"Variant: {VARIANT_LABEL}"]
if frn: lines.append(f"FCC Registration Number (FRN): {frn}")
if filer_id_499: lines.append(f"FCC Form 499 Filer ID: {filer_id_499}")
addr = ", ".join(filter(None, [address_street, address_city]))
if address_state or address_zip:
addr += f", {address_state} {address_zip}".strip()
if addr.strip(", "):
lines.append(f"Address: {addr.strip(', ')}")
if contact_phone: lines.append(f"Telephone: {contact_phone}")
if contact_email: lines.append(f"Email: {contact_email}")
lines.append(f"Certifying Officer: {signer}, {title}")
lines.append(f"Date of Filing: {today}")
lines.append(f"Filing Deadline: March 2, {reporting_year + 1}")
_b(doc, "\n".join(lines))
_h(doc, "2. Officer Statement of Personal Knowledge")
_b(doc, (
f"I, {signer}, {title} of {entity_name}, state that I have personal "
f"knowledge of the matters certified herein, including procedures "
f"governing participant dial-in records, scheduled-conference "
f"metadata, and enterprise billing data."
))
_h(doc, "3. Scope Note and Certification of Compliance")
_b(doc, (
f"{entity_name} provides audio bridging / conferencing service. "
f"Its CPNI-like holdings are narrow: participant dial-in numbers, "
f"conference-bridge access records, and enterprise billing data. "
f"To the extent any portion of the service is properly classified "
f"as a non-real-time information service rather than a "
f"telecommunications service under 47 USC \u00a7 153(53), the "
f"Commission has recognized that such portion is not subject to "
f"47 CFR Part 64 Subpart U. {entity_name} certifies compliance "
f"with 47 CFR \u00a7\u00a7 64.2001 through 64.2011 with respect to "
f"all remaining CPNI it holds for the period January 1, "
f"{reporting_year} through December 31, {reporting_year}."
))
_h(doc, "4. How Our Procedures Ensure Compliance")
_cb(doc, (
"Access to participant dial-in records and conference metadata is "
"restricted to authenticated personnel performing billing, "
"support, or abuse investigations. Authentication occurs through "
"named-user credentials; access is logged (47 CFR \u00a7 64.2009)."
))
_cb(doc, (
"Customer authentication is required before CPNI release in "
"response to a customer-initiated inquiry. Consumer-side "
"authentication is by pre-established password; enterprise-side "
"authentication is via credentials assigned in the master service "
"agreement (47 CFR \u00a7 64.2010)."
))
_cb(doc, (
"Customer approval for use of CPNI beyond the scope of the "
"subscribed service is obtained through written opt-in consent, "
"documented per 47 CFR \u00a7 64.2007."
))
_cb(doc, (
"Supervisory review of CPNI access is conducted at least "
"quarterly; retention of logs meets or exceeds two years, and "
"certification records are retained for five years, per 47 CFR "
"\u00a7 64.2009."
))
_cb(doc, (
"Annual training is provided to all personnel with CPNI access; "
"breach-notification procedures comply with 47 CFR \u00a7 64.2011 "
"as amended by FCC 23-111."
))
_h(doc, "5. Customer Complaints")
if complaints_count == 0:
_b(doc, (
f"{entity_name} has NOT received any customer complaints during "
f"the reporting period concerning the unauthorized release or "
f"use of CPNI. Zero (0) complaints were logged."
))
else:
desc = complaints_description or "Each complaint was investigated and resolved."
_b(doc, (
f"{entity_name} HAS received {complaints_count} customer "
f"complaint{'s' if complaints_count != 1 else ''} during the "
f"reporting period. {desc}"
))
_h(doc, "6. Data Broker Inquiries and Pretexting")
if not has_data_broker_inquiries:
_b(doc, (
f"{entity_name} has NOT received any inquiries, communications, "
f"or attempts by data brokers or other unauthorized parties "
f"seeking the unauthorized release of CPNI."
))
else:
desc = data_broker_description or "Each was refused, documented, and escalated."
_b(doc, (
f"{entity_name} HAS received data broker or pretexting-style "
f"inquiries during the reporting period. {desc}"
))
_h(doc, "7. Breach Log Summary")
if not breaches:
_b(doc, (
f"{entity_name} experienced no CPNI breaches during the "
f"reporting period. No 47 CFR \u00a7 64.2011 notifications "
f"were required."
))
else:
_b(doc, (
f"{entity_name} experienced {len(breaches)} CPNI breach"
f"{'es' if len(breaches) != 1 else ''} during the reporting "
f"period; each was reported within 7 business days."
))
_h(doc, "8. Penalties, Truthfulness, and Perjury Acknowledgment")
_b(doc, (
f"{entity_name} and the undersigned acknowledge that CPNI rule "
f"violations may subject the carrier to forfeitures up to "
f"{MAX_FORFEITURE_PER_VIOLATION} per violation and up to "
f"{MAX_FORFEITURE_CAP} for any single act or failure to act."
))
_b(doc, (
"Pursuant to 47 CFR \u00a7 1.17, the undersigned represents that no "
"material factual information has been withheld and all statements "
"are truthful, accurate, and complete."
))
_b(doc, (
"Willful false statements are punishable under Title 18, U.S.C. "
"\u00a7 1001, and by forfeiture under 47 U.S.C. \u00a7 503."
))
_h(doc, "9. Signature of Certifying Officer")
_b(doc, (
"I declare under penalty of perjury under the laws of the United "
"States of America that the foregoing is true and correct."
))
p = doc.add_paragraph(); _sp(p, after=0)
sig = doc.add_paragraph(); sig.add_run("_" * 45).font.size = Pt(10); _sp(sig, after=2)
nm = doc.add_paragraph(); nr = nm.add_run(signer); nr.bold = True
nr.font.size = Pt(10); _sp(nm, after=2)
tpp = doc.add_paragraph(); tpp.add_run(f"{title}, {entity_name}").font.size = Pt(10)
_sp(tpp, after=2)
dp = doc.add_paragraph(); dp.add_run(f"Date: {today}").font.size = Pt(10)
_sp(dp, after=2)
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CPNI Audio Bridge certification letter generated: %s", out)
return str(out)

View file

@ -0,0 +1,588 @@
"""
Generate the FCC CPNI Annual Certification Letter.
Produces the annual certification required by 47 CFR § 64.2009 certifying
compliance with the Customer Proprietary Network Information (CPNI) rules
(47 CFR §§ 64.2001-64.2011), including amendments from the 2023 Data Breach
Notification Order (FCC 23-111).
The letter is largely standard across carrier types. The only variation
is wholesale-only carriers, whose CPNI obligations are limited to wholesale
customer proprietary data rather than retail end-user CPNI.
Usage:
from scripts.document_gen.templates.cpni_cert_letter_generator import (
generate_cpni_cert_letter,
)
path = generate_cpni_cert_letter(
entity_name="Falcon Broadband LLC",
frn="0027160886",
filer_id_499="812345",
reporting_year=2025,
complaints_count=0,
output_path="/tmp/cpni_cert.docx",
)
"""
from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.cpni_cert")
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
except ImportError:
LOG.warning("python-docx not installed — CPNI cert letter generation unavailable")
Document = None # type: ignore[assignment,misc]
# Navy blue used for section headings (RGB 0x1A, 0x27, 0x44)
_NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
# Spacing constants (in twips; 1 pt = 20 twips)
_AFTER_6PT = Pt(6) if Document else None
def generate_cpni_cert_letter(
# ── Entity identity ───────────────────────────────────────────
entity_name: str,
frn: str = "",
filer_id_499: str = "",
# ── Address ───────────────────────────────────────────────────
address_street: str = "",
address_city: str = "",
address_state: str = "",
address_zip: str = "",
# ── Contact / officer ─────────────────────────────────────────
officer_name: str = "",
officer_title: str = "Chief Executive Officer",
contact_email: str = "",
contact_phone: str = "",
# ── Reporting ─────────────────────────────────────────────────
reporting_year: int = 0,
complaints_count: int = 0,
complaints_description: str = "",
# ── Carrier flags ─────────────────────────────────────────────
is_wholesale: bool = False,
# ── Employee training ─────────────────────────────────────────
employee_training_conducted: bool = True,
# ── Disciplinary actions ──────────────────────────────────────
disciplinary_actions_taken: bool = False,
disciplinary_actions_description: str = "",
# ── Data broker actions ───────────────────────────────────────
data_broker_actions: str = "",
# ── Breaches (per FCC 23-111) ─────────────────────────────────
breaches: list[dict] | None = None,
# ── Marketing / CPNI usage ────────────────────────────────────
uses_cpni_for_marketing: bool = False,
cpni_approval_method: str = "opt_in", # "opt_in" or "opt_out"
# ── Pretexting safeguards ─────────────────────────────────────
pretexting_safeguards: str = "",
# ── Output ────────────────────────────────────────────────────
output_path: str = "/tmp/cpni_certification_letter.docx",
) -> Optional[str]:
"""
Generate a CPNI Annual Certification Letter as a DOCX file.
Compliant with 47 CFR § 64.2009, including the 2023 Data Breach
Notification Order (FCC 23-111).
Returns the output file path on success, None on failure.
"""
if Document is None:
LOG.error("python-docx not installed")
return None
if reporting_year == 0:
reporting_year = datetime.now().year - 1
if breaches is None:
breaches = []
doc = Document()
# ── Page setup ────────────────────────────────────────────────
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)
today = datetime.now().strftime("%B %d, %Y")
signer = officer_name or "Authorized Officer"
title = officer_title or "Officer"
cpni_scope = (
"wholesale customer proprietary data"
if is_wholesale
else "customer proprietary network information (CPNI)"
)
# ── Helper functions ──────────────────────────────────────────
def _set_spacing(paragraph, after_pt=6, before_pt=0):
"""Set paragraph spacing in points."""
pf = paragraph.paragraph_format
pf.space_after = Pt(after_pt)
if before_pt:
pf.space_before = Pt(before_pt)
def _heading(text: str, level: int = 1) -> None:
"""Add a navy blue section heading."""
p = doc.add_paragraph()
run = p.add_run(text)
run.font.size = Pt(12)
run.bold = True
run.font.color.rgb = _NAVY
_set_spacing(p, after_pt=4, before_pt=8)
def _body(text: str, bold: bool = False, size: int = 10) -> None:
"""Add body-text paragraph with 6pt spacing after."""
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.LEFT
run = p.add_run(text)
run.font.size = Pt(size)
run.bold = bold
_set_spacing(p, after_pt=6)
def _checkbox(label: str, checked: bool = True) -> None:
"""Add a checkbox-style line item."""
mark = "\u2611" if checked else "\u2610"
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.LEFT
run = p.add_run(f" {mark} {label}")
run.font.size = Pt(10)
_set_spacing(p, after_pt=3)
def _spacer() -> None:
p = doc.add_paragraph()
_set_spacing(p, after_pt=0)
# ── Page numbers ──────────────────────────────────────────────
for section in doc.sections:
footer = section.footer
footer.is_linked_to_previous = False
fp = footer.paragraphs[0] if footer.paragraphs else footer.add_paragraph()
fp.alignment = WD_ALIGN_PARAGRAPH.CENTER
# Insert PAGE field
run = fp.add_run()
run.font.size = Pt(8)
run.font.color.rgb = RGBColor(0x80, 0x80, 0x80)
fld_char_begin = run._element.makeelement(qn("w:fldChar"), {qn("w:fldCharType"): "begin"})
run._element.append(fld_char_begin)
run2 = fp.add_run()
run2.font.size = Pt(8)
run2.font.color.rgb = RGBColor(0x80, 0x80, 0x80)
instr = run2._element.makeelement(qn("w:instrText"), {})
instr.text = " PAGE "
run2._element.append(instr)
run3 = fp.add_run()
run3.font.size = Pt(8)
fld_char_end = run3._element.makeelement(qn("w:fldChar"), {qn("w:fldCharType"): "end"})
run3._element.append(fld_char_end)
# ══════════════════════════════════════════════════════════════
# TITLE
# ══════════════════════════════════════════════════════════════
title_p = doc.add_paragraph()
title_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
title_run = title_p.add_run("CPNI Annual Certification Letter")
title_run.font.size = Pt(14)
title_run.bold = True
title_run.font.color.rgb = _NAVY
_set_spacing(title_p, after_pt=2)
subtitle_p = doc.add_paragraph()
subtitle_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
sub_run = subtitle_p.add_run(
f"Pursuant to 47 CFR \u00a7 64.2009 \u2014 Calendar Year {reporting_year}"
)
sub_run.font.size = Pt(10)
sub_run.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
_set_spacing(subtitle_p, after_pt=6)
# Horizontal rule
rule_p = doc.add_paragraph()
rule_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
rule_run = rule_p.add_run("\u2500" * 72)
rule_run.font.size = Pt(6)
rule_run.font.color.rgb = RGBColor(0xAA, 0xAA, 0xAA)
_set_spacing(rule_p, after_pt=8)
# ══════════════════════════════════════════════════════════════
# SECTION 1: Provider Information
# ══════════════════════════════════════════════════════════════
_heading("1. Provider Information")
info_lines = [f"Company Name: {entity_name}"]
if frn:
info_lines.append(f"FCC Registration Number (FRN): {frn}")
if filer_id_499:
info_lines.append(f"FCC Form 499 Filer ID: {filer_id_499}")
addr = ", ".join(filter(None, [address_street, address_city]))
if address_state or address_zip:
addr += f", {address_state} {address_zip}".strip()
if addr.strip(", "):
info_lines.append(f"Address: {addr.strip(', ')}")
if contact_phone:
info_lines.append(f"Telephone: {contact_phone}")
if contact_email:
info_lines.append(f"Email: {contact_email}")
info_lines.append(f"Certifying Officer: {signer}, {title}")
info_lines.append(f"Date of Filing: {today}")
info_lines.append(
f"Filing Deadline: March 1, {reporting_year + 1}"
)
_body("\n".join(info_lines))
# ══════════════════════════════════════════════════════════════
# SECTION 2: Certification of Compliance
# ══════════════════════════════════════════════════════════════
_heading("2. Certification of Compliance")
_body(
f"Pursuant to 47 CFR \u00a7 64.2009(e), {entity_name} "
f"({'FRN: ' + frn if frn else 'FRN pending'}"
f"{', Filer ID: ' + filer_id_499 if filer_id_499 else ''}) "
f"hereby submits its annual certification of compliance with the "
f"Commission's Customer Proprietary Network Information (CPNI) rules "
f"for calendar year {reporting_year}."
)
_body(
f"I, {signer}, {title} of {entity_name}, have personal knowledge "
f"of, have reviewed, and am familiar with {entity_name}'s CPNI "
f"compliance procedures and certify that the company has established "
f"operating procedures that ensure compliance with the Commission's "
f"CPNI rules set forth in 47 CFR \u00a7\u00a7 64.2001 through 64.2011. "
f"{entity_name} has taken appropriate actions to protect the "
f"confidentiality of {cpni_scope} and has limited access to and use "
f"of such information in accordance with the Commission's rules."
)
# ══════════════════════════════════════════════════════════════
# SECTION 3: Reporting Period
# ══════════════════════════════════════════════════════════════
_heading("3. Reporting Period")
_body(
f"This certification covers the period from January 1, {reporting_year} "
f"through December 31, {reporting_year}."
)
# ══════════════════════════════════════════════════════════════
# SECTION 4: CPNI Safeguards
# ══════════════════════════════════════════════════════════════
_heading("4. CPNI Safeguards")
_body(
f"{entity_name} has implemented the following safeguards to protect "
f"{cpni_scope}:"
)
# 4a - Customer authentication
_body("(a) Customer Authentication and Password Procedures", bold=True)
_checkbox(
f"{entity_name} requires customer authentication through a password "
f"or other secure credential before disclosing CPNI in response to "
f"customer-initiated contacts, in accordance with 47 CFR \u00a7 64.2010.",
checked=True,
)
# 4b - Employee training
_body("(b) Employee Training", bold=True)
_checkbox(
f"All employees with access to CPNI have been adequately trained on "
f"the Commission's CPNI rules, including proper handling, disclosure "
f"limitations, and breach notification procedures.",
checked=employee_training_conducted,
)
if not employee_training_conducted:
_body(
f"NOTE: {entity_name} is in the process of completing employee "
f"training and anticipates full compliance within 30 days of this "
f"filing."
)
# 4c - Supervisory review
_body("(c) Supervisory Review", bold=True)
_checkbox(
f"{entity_name} conducts regular supervisory reviews of CPNI access "
f"and usage to ensure compliance with established procedures.",
checked=True,
)
# 4d - Pretexting safeguards
_body("(d) Pretexting Safeguards", bold=True)
if pretexting_safeguards:
_checkbox(pretexting_safeguards, checked=True)
else:
_checkbox(
f"{entity_name} has implemented safeguards to protect against "
f"pretexting, including customer identity verification protocols, "
f"employee awareness training on social engineering tactics, and "
f"procedures to detect and report suspected pretexting attempts.",
checked=True,
)
# 4e - Notification of account changes
_body("(e) Notification of Account Changes", bold=True)
_checkbox(
f"{entity_name} notifies customers of account changes, including "
f"changes to passwords, address of record, or online account "
f"credentials, through a communication to the customer's address "
f"of record or established backup contact method, in accordance "
f"with 47 CFR \u00a7 64.2010.",
checked=True,
)
# 4f - Record retention
_body("(f) Record Retention", bold=True)
_checkbox(
f"{entity_name} maintains records of all CPNI access, disclosures, "
f"customer complaints, and compliance actions for a minimum period "
f"of five (5) years, as required by 47 CFR \u00a7 64.2009(e).",
checked=True,
)
# ══════════════════════════════════════════════════════════════
# SECTION 5: CPNI Complaints
# ══════════════════════════════════════════════════════════════
_heading("5. CPNI Complaints")
if complaints_count == 0:
_body(
f"During the reporting period, {entity_name} received no complaints "
f"regarding unauthorized release or use of CPNI."
)
else:
desc = complaints_description or (
f"Each complaint was investigated and resolved in accordance with "
f"{entity_name}'s CPNI compliance procedures."
)
_body(
f"During the reporting period, {entity_name} received "
f"{complaints_count} complaint{'s' if complaints_count != 1 else ''} "
f"regarding CPNI. {desc}"
)
# ══════════════════════════════════════════════════════════════
# SECTION 6: Data Breaches
# ══════════════════════════════════════════════════════════════
_heading("6. Data Breaches")
if not breaches:
_body(
f"During the reporting period, {entity_name} experienced no data "
f"breaches involving CPNI. No breach notifications were required "
f"to be filed with the Commission, law enforcement, or affected "
f"customers under 47 CFR \u00a7 64.2011."
)
else:
total_breaches = len(breaches)
total_affected = sum(b.get("customers_affected", 0) for b in breaches)
_body(
f"During the reporting period, {entity_name} experienced "
f"{total_breaches} data breach{'es' if total_breaches != 1 else ''} "
f"involving CPNI, affecting a total of {total_affected:,} "
f"customer{'s' if total_affected != 1 else ''}. Details of each "
f"breach are provided below."
)
# Breach detail table
table = doc.add_table(rows=1, cols=5)
table.style = "Table Grid"
# Header row
headers = [
"Breach #", "Date", "Customers\nAffected",
"Description", "Response Actions",
]
hdr_cells = table.rows[0].cells
for i, header in enumerate(headers):
hdr_cells[i].text = ""
p = hdr_cells[i].paragraphs[0]
run = p.add_run(header)
run.bold = True
run.font.size = Pt(9)
run.font.color.rgb = RGBColor(0xFF, 0xFF, 0xFF)
# Navy background
shading = hdr_cells[i]._element.makeelement(
qn("w:shd"),
{
qn("w:val"): "clear",
qn("w:color"): "auto",
qn("w:fill"): "1A2744",
},
)
tc_pr = hdr_cells[i]._element.get_or_add_tcPr()
tc_pr.append(shading)
# Data rows
for idx, breach in enumerate(breaches, start=1):
row_cells = table.add_row().cells
values = [
str(idx),
str(breach.get("date", "N/A")),
f"{breach.get('customers_affected', 0):,}",
str(breach.get("description", "")),
str(breach.get("response_actions", "")),
]
for i, val in enumerate(values):
row_cells[i].text = ""
p = row_cells[i].paragraphs[0]
run = p.add_run(val)
run.font.size = Pt(9)
_spacer()
# ══════════════════════════════════════════════════════════════
# SECTION 7: Disciplinary Actions
# ══════════════════════════════════════════════════════════════
_heading("7. Disciplinary Actions")
if not disciplinary_actions_taken:
_body(
f"During the reporting period, {entity_name} did not take any "
f"disciplinary action against employees for violations of the "
f"Commission's CPNI rules."
)
else:
desc = disciplinary_actions_description or (
"Disciplinary action was taken in accordance with company policy."
)
_body(
f"During the reporting period, {entity_name} took disciplinary "
f"action against one or more employees for violations of the "
f"Commission's CPNI rules. {desc}"
)
# ══════════════════════════════════════════════════════════════
# SECTION 8: Data Broker Actions
# ══════════════════════════════════════════════════════════════
_heading("8. Actions Taken Against Data Brokers")
if data_broker_actions:
_body(
f"During the reporting period, {entity_name} took the following "
f"actions against data brokers: {data_broker_actions}"
)
else:
_body(
f"During the reporting period, {entity_name} did not identify any "
f"data brokers engaging in unauthorized access to or sale of CPNI, "
f"and no actions against data brokers were required."
)
# ══════════════════════════════════════════════════════════════
# SECTION 9: CPNI Marketing Usage
# ══════════════════════════════════════════════════════════════
_heading("9. CPNI Marketing Usage")
if uses_cpni_for_marketing:
method_label = (
"opt-in" if cpni_approval_method == "opt_in" else "opt-out"
)
_body(
f"{entity_name} uses CPNI for marketing purposes. Customer "
f"approval for such use is obtained through the {method_label} "
f"method, in accordance with 47 CFR \u00a7 64.2007."
)
else:
_body(
f"{entity_name} does not use CPNI for marketing purposes beyond "
f"the scope of services to which the customer already subscribes. "
f"No customer approval mechanism is required."
)
# ══════════════════════════════════════════════════════════════
# SECTION 10: Breach Notification Compliance
# ══════════════════════════════════════════════════════════════
_heading("10. Breach Notification Compliance")
_body(
f"{entity_name} certifies that its breach notification procedures "
f"are compliant with 47 CFR \u00a7 64.2011, as amended by the 2023 "
f"Data Breach Notification Order (FCC 23-111). These procedures "
f"include:"
)
_checkbox(
"Notification to the FCC and, where applicable, the FBI and U.S. "
"Secret Service, as soon as practicable and in no event later than "
"30 days after reasonable determination of a breach.",
checked=True,
)
_checkbox(
"Notification to affected customers as soon as practicable and in "
"no event later than 30 days after notification to law enforcement "
"(unless a delay is requested by law enforcement).",
checked=True,
)
_checkbox(
"Breach notifications include the required content specified in "
"\u00a7 64.2011, including a description of the breach, the categories "
"of information compromised, and contact information for inquiries.",
checked=True,
)
# ══════════════════════════════════════════════════════════════
# SECTION 11: Officer Certification & Signature
# ══════════════════════════════════════════════════════════════
_heading("11. Officer Certification and Signature")
_body(
f"I, {signer}, {title} of {entity_name}, certify under penalty of "
f"perjury that the foregoing is true and correct. I have personal "
f"knowledge of the facts stated herein, have reviewed {entity_name}'s "
f"CPNI compliance procedures, and am satisfied that {entity_name} has "
f"complied with the requirements of 47 CFR \u00a7\u00a7 64.2001 through "
f"64.2011 during calendar year {reporting_year}."
)
_spacer()
_body("Respectfully submitted,")
_spacer()
_spacer()
# Signature line
sig_line = doc.add_paragraph()
sig_run = sig_line.add_run("_" * 45)
sig_run.font.size = Pt(10)
_set_spacing(sig_line, after_pt=2)
sig_name_p = doc.add_paragraph()
name_run = sig_name_p.add_run(signer)
name_run.font.size = Pt(10)
name_run.bold = True
_set_spacing(sig_name_p, after_pt=2)
sig_title_p = doc.add_paragraph()
sig_title_p.add_run(f"{title}, {entity_name}").font.size = Pt(10)
_set_spacing(sig_title_p, after_pt=2)
sig_date_p = doc.add_paragraph()
sig_date_p.add_run(f"Date: {today}").font.size = Pt(10)
_set_spacing(sig_date_p, after_pt=2)
if contact_phone:
sig_phone_p = doc.add_paragraph()
sig_phone_p.add_run(f"Telephone: {contact_phone}").font.size = Pt(10)
_set_spacing(sig_phone_p, after_pt=2)
if contact_email:
sig_email_p = doc.add_paragraph()
sig_email_p.add_run(f"Email: {contact_email}").font.size = Pt(10)
_set_spacing(sig_email_p, after_pt=2)
# ── Save ──────────────────────────────────────────────────────
output = Path(output_path)
output.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(output))
LOG.info("CPNI certification letter generated: %s", output)
return str(output)

View file

@ -0,0 +1,366 @@
"""
Generate the FCC CPNI Annual Certification Letter CLEC (Facilities) variant.
Tailors the generic CPNI certification under 47 CFR § 64.2009(e) for a
Competitive Local Exchange Carrier operating its own TDM / SS7 switching
plant. Customer authorization for CPNI is obtained through traditional
written / oral opt-in methods; the CPNI Protection Officer's scope of
oversight explicitly includes SS7 / SIGTRAN intercept provisioning and
PIC / LIDB record handling.
2026 amendments included:
* Maximum forfeiture $251,322 per violation (capped $2,513,215).
* 47 CFR § 1.17 truthfulness representation.
* Title 18 penalty acknowledgment.
* Explicit "has / has not" language for customer complaints + data
broker inquiries (Report & Order FCC-25-XXX).
* Officer statement of personal knowledge.
* Narrative "how procedures ensure compliance" section.
Usage:
from scripts.document_gen.templates.cpni_clec_generator import (
generate_cpni_clec,
)
path = generate_cpni_clec(
output_path="/tmp/cpni_clec.docx",
entity_name="Acme Telco LLC",
frn="0027160886",
filer_id_499="812345",
officer_name="Jane Doe",
officer_title="CEO",
reporting_year=2025,
)
"""
from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.cpni_clec")
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
except ImportError:
LOG.warning("python-docx not installed — CPNI CLEC generation unavailable")
Document = None # type: ignore[assignment,misc]
_NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "clec"
VARIANT_LABEL = "Competitive Local Exchange Carrier (CLEC)"
MAX_FORFEITURE_PER_VIOLATION = "$251,322"
MAX_FORFEITURE_CAP = "$2,513,215"
def _set_spacing(paragraph, after_pt=6, before_pt=0):
pf = paragraph.paragraph_format
pf.space_after = Pt(after_pt)
if before_pt:
pf.space_before = Pt(before_pt)
def _heading(doc, text: str) -> None:
p = doc.add_paragraph()
run = p.add_run(text)
run.font.size = Pt(12)
run.bold = True
run.font.color.rgb = _NAVY
_set_spacing(p, after_pt=4, before_pt=8)
def _body(doc, text: str, bold: bool = False, size: int = 10) -> None:
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.LEFT
run = p.add_run(text)
run.font.size = Pt(size)
run.bold = bold
_set_spacing(p, after_pt=6)
def _checkbox(doc, label: str, checked: bool = True) -> None:
mark = "\u2611" if checked else "\u2610"
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.LEFT
run = p.add_run(f" {mark} {label}")
run.font.size = Pt(10)
_set_spacing(p, after_pt=3)
def _spacer(doc) -> None:
p = doc.add_paragraph()
_set_spacing(p, after_pt=0)
def generate_cpni_clec(
output_path: str,
entity_name: str,
frn: str = "",
filer_id_499: str = "",
officer_name: str = "",
officer_title: str = "Chief Executive Officer",
complaints_count: int = 0,
complaints_description: str = "",
has_data_broker_inquiries: bool = False,
data_broker_description: str = "",
reporting_year: int = 0,
address_street: str = "",
address_city: str = "",
address_state: str = "",
address_zip: str = "",
contact_email: str = "",
contact_phone: str = "",
breaches: list[dict] | None = None,
**_: dict,
) -> Optional[str]:
"""Generate the CLEC (facilities) CPNI Annual Certification Letter."""
if Document is None:
LOG.error("python-docx not installed")
return None
if reporting_year == 0:
reporting_year = datetime.now().year - 1
breaches = breaches or []
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)
today = datetime.now().strftime("%B %d, %Y")
signer = officer_name or "Authorized Officer"
title = officer_title or "Officer"
# ── Title ────────────────────────────────────────────────────────
title_p = doc.add_paragraph()
title_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
tr = title_p.add_run("CPNI Annual Certification Letter")
tr.font.size = Pt(14)
tr.bold = True
tr.font.color.rgb = _NAVY
_set_spacing(title_p, after_pt=2)
sub_p = doc.add_paragraph()
sub_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
sub = sub_p.add_run(
f"Competitive Local Exchange Carrier \u2014 "
f"47 CFR \u00a7 64.2009 \u2014 Calendar Year {reporting_year}"
)
sub.font.size = Pt(10)
sub.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
_set_spacing(sub_p, after_pt=8)
# ── 1. Provider Information ──────────────────────────────────────
_heading(doc, "1. Provider Information")
lines = [f"Company Name: {entity_name}", f"Variant: {VARIANT_LABEL}"]
if frn:
lines.append(f"FCC Registration Number (FRN): {frn}")
if filer_id_499:
lines.append(f"FCC Form 499 Filer ID: {filer_id_499}")
addr = ", ".join(filter(None, [address_street, address_city]))
if address_state or address_zip:
addr += f", {address_state} {address_zip}".strip()
if addr.strip(", "):
lines.append(f"Address: {addr.strip(', ')}")
if contact_phone:
lines.append(f"Telephone: {contact_phone}")
if contact_email:
lines.append(f"Email: {contact_email}")
lines.append(f"Certifying Officer: {signer}, {title}")
lines.append(f"Date of Filing: {today}")
lines.append(f"Filing Deadline: March 2, {reporting_year + 1}")
_body(doc, "\n".join(lines))
# ── 2. Officer Statement of Personal Knowledge ───────────────────
_heading(doc, "2. Officer Statement of Personal Knowledge")
_body(doc, (
f"I, {signer}, {title} of {entity_name}, state that I have personal "
f"knowledge of the matters certified herein. I have reviewed "
f"{entity_name}'s CPNI operating procedures, interviewed personnel "
f"responsible for CPNI handling, and examined supervisory logs and "
f"records covering the reporting period. The representations set "
f"forth in this certification are based on my personal review and "
f"are true and correct to the best of my knowledge, information, "
f"and belief."
))
# ── 3. Certification of Compliance ───────────────────────────────
_heading(doc, "3. Certification of Compliance")
_body(doc, (
f"Pursuant to 47 CFR \u00a7 64.2009(e), {entity_name} hereby submits "
f"its annual certification of compliance with the Customer Proprietary "
f"Network Information (CPNI) rules at 47 CFR \u00a7\u00a7 64.2001 "
f"through 64.2011 for the period January 1, {reporting_year} through "
f"December 31, {reporting_year}. {entity_name} has established, "
f"maintained, and adhered to operating procedures that ensure "
f"compliance with these rules."
))
# ── 4. How Procedures Ensure Compliance (narrative) ──────────────
_heading(doc, "4. How Our Procedures Ensure Compliance")
_body(doc, (
f"As a competitive local exchange carrier operating on circuit-switched "
f"(TDM) switching platforms with SS7 / SIGTRAN signaling, {entity_name} "
f"protects CPNI throughout the complete life-cycle of a customer "
f"relationship. Specific procedures include:"
))
_checkbox(doc, (
"Customer authentication is required before any CPNI disclosure in "
"response to a customer-initiated contact. Authentication is by "
"pre-established password or, for in-store visits, a photo ID plus "
"verification of two account attributes that are not CPNI "
"(47 CFR \u00a7 64.2010)."
))
_checkbox(doc, (
"Customer approval for use of CPNI beyond the scope of the "
"subscribed service is obtained through traditional written or oral "
"opt-in consent, documented in the customer record per 47 CFR "
"\u00a7 64.2007 and \u00a7 64.2008. Oral approvals are date-stamped "
"and time-stamped with the agent's identity."
))
_checkbox(doc, (
"The CPNI Protection Officer's oversight scope expressly includes "
"SS7 / SIGTRAN intercept provisioning, LIDB access, PIC-change "
"verification, and wholesale handoff logs, ensuring that network-"
"element CPNI (e.g., originating-number records, call-path signaling) "
"is governed by the same safeguards as customer-facing systems."
))
_checkbox(doc, (
"PIC and account changes trigger customer notification to the "
"address of record before taking effect, per 47 CFR \u00a7 64.2010(f)."
))
_checkbox(doc, (
"All access to CPNI-bearing systems is logged, with supervisory "
"review at least quarterly. Retention of access logs meets or "
"exceeds two years (CPNI) and five years (certification records) "
"per 47 CFR \u00a7 64.2009."
))
_checkbox(doc, (
"Annual CPNI training is required for all personnel with CPNI "
"access. Completion is tracked and attested to by the CPNI Protection "
"Officer. Disciplinary procedures are documented and applied to any "
"violation."
))
_checkbox(doc, (
"Breach notification under 47 CFR \u00a7 64.2011 is implemented as "
"amended by FCC 23-111 \u2014 notice to the Commission within 7 "
"business days and to customers / law enforcement as soon as "
"practicable, not later than 30 days after reasonable determination."
))
# ── 5. Customer Complaints (has / has not) ───────────────────────
_heading(doc, "5. Customer Complaints")
if complaints_count == 0:
_body(doc, (
f"{entity_name} has NOT received any customer complaints during "
f"the reporting period concerning the unauthorized release or "
f"use of CPNI. Zero (0) complaints were logged."
))
else:
desc = complaints_description or (
"Each complaint was investigated and resolved in accordance with "
"the company's CPNI compliance procedures."
)
_body(doc, (
f"{entity_name} HAS received {complaints_count} customer "
f"complaint{'s' if complaints_count != 1 else ''} during the "
f"reporting period concerning the unauthorized release or use "
f"of CPNI. {desc}"
))
# ── 6. Data Broker Inquiries (has / has not) ─────────────────────
_heading(doc, "6. Data Broker Inquiries and Pretexting")
if not has_data_broker_inquiries:
_body(doc, (
f"{entity_name} has NOT received any inquiries, communications, "
f"or attempts by data brokers or other unauthorized parties "
f"seeking the unauthorized release of CPNI during the reporting "
f"period."
))
else:
desc = data_broker_description or (
"Each such inquiry was refused, documented, and escalated to "
"the CPNI Protection Officer."
)
_body(doc, (
f"{entity_name} HAS received data broker or pretexting-style "
f"inquiries during the reporting period. {desc}"
))
# ── 7. Breach Log Summary ────────────────────────────────────────
_heading(doc, "7. Breach Log Summary")
if not breaches:
_body(doc, (
f"{entity_name} experienced no CPNI breaches during the "
f"reporting period. No 47 CFR \u00a7 64.2011 notifications were "
f"required."
))
else:
_body(doc, (
f"{entity_name} experienced {len(breaches)} CPNI breach"
f"{'es' if len(breaches) != 1 else ''} during the reporting "
f"period. Each was reported to the Commission via the CPNI "
f"Breach Reporting Portal within 7 business days."
))
# ── 8. Penalties and Truthfulness ────────────────────────────────
_heading(doc, "8. Penalties, Truthfulness, and Perjury Acknowledgment")
_body(doc, (
f"{entity_name} and the undersigned officer acknowledge that "
f"violations of the CPNI rules may subject the carrier to monetary "
f"forfeitures of up to {MAX_FORFEITURE_PER_VIOLATION} per violation "
f"and up to {MAX_FORFEITURE_CAP} for any single act or failure to "
f"act (adjusted for inflation per 47 CFR \u00a7 1.80)."
))
_body(doc, (
f"Pursuant to 47 CFR \u00a7 1.17, the undersigned represents that "
f"no material factual information has been withheld from the "
f"Commission and that all statements herein are truthful, accurate, "
f"and complete to the best of the undersigned's knowledge and "
f"belief, and are not intended to mislead the Commission."
))
_body(doc, (
f"The undersigned further acknowledges that willful false statements "
f"made in this certification are punishable by fine and/or "
f"imprisonment under Title 18, U.S.C. \u00a7 1001, and/or by "
f"forfeiture under 47 U.S.C. \u00a7 503."
))
# ── 9. Signature ─────────────────────────────────────────────────
_heading(doc, "9. Signature of Certifying Officer")
_body(doc, (
f"I declare under penalty of perjury under the laws of the "
f"United States of America that the foregoing is true and correct."
))
_spacer(doc)
sig = doc.add_paragraph()
sig.add_run("_" * 45).font.size = Pt(10)
_set_spacing(sig, after_pt=2)
nm = doc.add_paragraph()
nr = nm.add_run(signer)
nr.bold = True
nr.font.size = Pt(10)
_set_spacing(nm, after_pt=2)
tp = doc.add_paragraph()
tp.add_run(f"{title}, {entity_name}").font.size = Pt(10)
_set_spacing(tp, after_pt=2)
dp = doc.add_paragraph()
dp.add_run(f"Date: {today}").font.size = Pt(10)
_set_spacing(dp, after_pt=2)
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CPNI CLEC certification letter generated: %s", out)
return str(out)

View file

@ -0,0 +1,307 @@
"""
Generate the FCC CPNI Annual Certification Letter CLEC Reseller variant.
Customer Approval / Safeguards language adapted for a CLEC reseller that
purchases local exchange capacity wholesale and resells it under its own
brand. The reseller's CPNI obligations extend both to end-user CPNI it
directly handles AND to CPNI that flows down from the wholesale provider.
Safeguards therefore include contractual flow-down terms.
See module ``cpni_clec_generator`` for the shared 2026 statutory block.
"""
from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.cpni_clec_reseller")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CPNI CLEC-Reseller generation unavailable")
Document = None # type: ignore[assignment,misc]
_NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "clec_reseller"
VARIANT_LABEL = "Competitive Local Exchange Carrier — Reseller"
MAX_FORFEITURE_PER_VIOLATION = "$251,322"
MAX_FORFEITURE_CAP = "$2,513,215"
def _set_spacing(paragraph, after_pt=6, before_pt=0):
pf = paragraph.paragraph_format
pf.space_after = Pt(after_pt)
if before_pt:
pf.space_before = Pt(before_pt)
def _heading(doc, text):
p = doc.add_paragraph()
r = p.add_run(text)
r.font.size = Pt(12)
r.bold = True
r.font.color.rgb = _NAVY
_set_spacing(p, after_pt=4, before_pt=8)
def _body(doc, text, bold=False, size=10):
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.LEFT
r = p.add_run(text)
r.font.size = Pt(size)
r.bold = bold
_set_spacing(p, after_pt=6)
def _checkbox(doc, label, checked=True):
mark = "\u2611" if checked else "\u2610"
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.LEFT
r = p.add_run(f" {mark} {label}")
r.font.size = Pt(10)
_set_spacing(p, after_pt=3)
def _spacer(doc):
p = doc.add_paragraph()
_set_spacing(p, after_pt=0)
def generate_cpni_clec_reseller(
output_path: str,
entity_name: str,
frn: str = "",
filer_id_499: str = "",
officer_name: str = "",
officer_title: str = "Chief Executive Officer",
complaints_count: int = 0,
complaints_description: str = "",
has_data_broker_inquiries: bool = False,
data_broker_description: str = "",
reporting_year: int = 0,
upstream_wholesale_provider: str = "",
address_street: str = "",
address_city: str = "",
address_state: str = "",
address_zip: str = "",
contact_email: str = "",
contact_phone: str = "",
breaches: list[dict] | None = None,
**_: dict,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
if reporting_year == 0:
reporting_year = datetime.now().year - 1
breaches = breaches or []
doc = Document()
for s in doc.sections:
s.top_margin = Inches(1); s.bottom_margin = Inches(1)
s.left_margin = Inches(1.25); s.right_margin = Inches(1.25)
today = datetime.now().strftime("%B %d, %Y")
signer = officer_name or "Authorized Officer"
title = officer_title or "Officer"
upstream = upstream_wholesale_provider or "its wholesale underlying carrier(s)"
tp = doc.add_paragraph(); tp.alignment = WD_ALIGN_PARAGRAPH.CENTER
t = tp.add_run("CPNI Annual Certification Letter")
t.font.size = Pt(14); t.bold = True; t.font.color.rgb = _NAVY
_set_spacing(tp, after_pt=2)
sp = doc.add_paragraph(); sp.alignment = WD_ALIGN_PARAGRAPH.CENTER
s = sp.add_run(
f"Competitive Local Exchange Carrier — Reseller \u2014 "
f"47 CFR \u00a7 64.2009 \u2014 Calendar Year {reporting_year}"
)
s.font.size = Pt(10); s.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
_set_spacing(sp, after_pt=8)
_heading(doc, "1. Provider Information")
lines = [f"Company Name: {entity_name}", f"Variant: {VARIANT_LABEL}"]
if frn:
lines.append(f"FCC Registration Number (FRN): {frn}")
if filer_id_499:
lines.append(f"FCC Form 499 Filer ID: {filer_id_499}")
addr = ", ".join(filter(None, [address_street, address_city]))
if address_state or address_zip:
addr += f", {address_state} {address_zip}".strip()
if addr.strip(", "):
lines.append(f"Address: {addr.strip(', ')}")
if contact_phone:
lines.append(f"Telephone: {contact_phone}")
if contact_email:
lines.append(f"Email: {contact_email}")
lines.append(f"Certifying Officer: {signer}, {title}")
lines.append(f"Date of Filing: {today}")
lines.append(f"Filing Deadline: March 2, {reporting_year + 1}")
_body(doc, "\n".join(lines))
_heading(doc, "2. Officer Statement of Personal Knowledge")
_body(doc, (
f"I, {signer}, {title} of {entity_name}, state that I have personal "
f"knowledge of the matters certified herein. I have reviewed "
f"{entity_name}'s CPNI operating procedures (including reseller "
f"flow-down terms with upstream wholesale providers), and I have "
f"examined supervisory logs and records covering the reporting "
f"period. The representations herein are based on my personal "
f"review and are true and correct to the best of my knowledge, "
f"information, and belief."
))
_heading(doc, "3. Certification of Compliance")
_body(doc, (
f"Pursuant to 47 CFR \u00a7 64.2009(e), {entity_name} hereby submits "
f"its annual certification of compliance with the CPNI rules at "
f"47 CFR \u00a7\u00a7 64.2001 through 64.2011 for the period "
f"January 1, {reporting_year} through December 31, {reporting_year}. "
f"{entity_name} has established, maintained, and adhered to "
f"operating procedures that ensure compliance with these rules."
))
_heading(doc, "4. How Our Procedures Ensure Compliance")
_body(doc, (
f"As a CLEC reseller purchasing wholesale local-exchange capacity "
f"from {upstream} and reselling it under its own brand, {entity_name} "
f"protects CPNI at two boundaries: (1) the retail end-user interface "
f"where it directly handles customer records, and (2) the wholesale "
f"flow from the underlying carrier(s). Specific procedures include:"
))
_checkbox(doc, (
"End-user customer authentication is required before any CPNI "
"disclosure; authentication uses pre-established password or "
"verification of non-CPNI account attributes (47 CFR \u00a7 64.2010)."
))
_checkbox(doc, (
"CPNI use beyond the scope of the subscribed service is permitted "
"only after written or oral opt-in consent under 47 CFR \u00a7 64.2007, "
"documented in the customer record."
))
_checkbox(doc, (
f"Reseller flow-down: {entity_name}'s wholesale-service agreement "
f"with {upstream} expressly requires the upstream carrier to treat "
f"all end-user CPNI received through {entity_name} in a manner "
f"consistent with 47 CFR \u00a7\u00a7 64.2001\u201364.2011. "
f"{entity_name} reviews upstream CPNI attestations annually."
))
_checkbox(doc, (
"The CPNI Protection Officer has oversight authority over both "
"retail records systems and wholesale interconnect logs, and "
"reviews upstream carrier breach notices per 47 CFR \u00a7 64.2011."
))
_checkbox(doc, (
"Changes to an end-user account (PIC, address-of-record, password) "
"are confirmed to the customer's address of record before taking "
"effect."
))
_checkbox(doc, (
"Access logs are maintained and reviewed at least quarterly; "
"retention meets or exceeds two years for CPNI access and five "
"years for certification records under 47 CFR \u00a7 64.2009."
))
_checkbox(doc, (
"Annual CPNI training is conducted for all personnel with CPNI "
"access. Disciplinary procedures are documented and applied to "
"any violation."
))
_heading(doc, "5. Customer Complaints")
if complaints_count == 0:
_body(doc, (
f"{entity_name} has NOT received any customer complaints during "
f"the reporting period concerning the unauthorized release or "
f"use of CPNI. Zero (0) complaints were logged."
))
else:
desc = complaints_description or (
"Each complaint was investigated and resolved in accordance with "
"the company's CPNI compliance procedures."
)
_body(doc, (
f"{entity_name} HAS received {complaints_count} customer "
f"complaint{'s' if complaints_count != 1 else ''} during the "
f"reporting period. {desc}"
))
_heading(doc, "6. Data Broker Inquiries and Pretexting")
if not has_data_broker_inquiries:
_body(doc, (
f"{entity_name} has NOT received any inquiries, communications, "
f"or attempts by data brokers or other unauthorized parties "
f"seeking the unauthorized release of CPNI."
))
else:
desc = data_broker_description or (
"Each such inquiry was refused, documented, and escalated."
)
_body(doc, (
f"{entity_name} HAS received data broker or pretexting-style "
f"inquiries during the reporting period. {desc}"
))
_heading(doc, "7. Breach Log Summary")
if not breaches:
_body(doc, (
f"{entity_name} experienced no CPNI breaches during the "
f"reporting period. No 47 CFR \u00a7 64.2011 notifications were "
f"required."
))
else:
_body(doc, (
f"{entity_name} experienced {len(breaches)} CPNI breach"
f"{'es' if len(breaches) != 1 else ''} during the reporting "
f"period; each was reported to the Commission via the CPNI "
f"Breach Reporting Portal within 7 business days."
))
_heading(doc, "8. Penalties, Truthfulness, and Perjury Acknowledgment")
_body(doc, (
f"{entity_name} and the undersigned officer acknowledge that CPNI "
f"rule violations may subject the carrier to monetary forfeitures "
f"of up to {MAX_FORFEITURE_PER_VIOLATION} per violation and up to "
f"{MAX_FORFEITURE_CAP} for any single act or failure to act "
f"(adjusted per 47 CFR \u00a7 1.80)."
))
_body(doc, (
"Pursuant to 47 CFR \u00a7 1.17, the undersigned represents that "
"no material factual information has been withheld and that all "
"statements herein are truthful, accurate, and complete."
))
_body(doc, (
"The undersigned acknowledges that willful false statements in this "
"certification are punishable under Title 18, U.S.C. \u00a7 1001, "
"and by forfeiture under 47 U.S.C. \u00a7 503."
))
_heading(doc, "9. Signature of Certifying Officer")
_body(doc, (
"I declare under penalty of perjury under the laws of the United "
"States of America that the foregoing is true and correct."
))
_spacer(doc)
sig = doc.add_paragraph()
sig.add_run("_" * 45).font.size = Pt(10)
_set_spacing(sig, after_pt=2)
nm = doc.add_paragraph()
nr = nm.add_run(signer); nr.bold = True; nr.font.size = Pt(10)
_set_spacing(nm, after_pt=2)
tpp = doc.add_paragraph()
tpp.add_run(f"{title}, {entity_name}").font.size = Pt(10)
_set_spacing(tpp, after_pt=2)
dp = doc.add_paragraph()
dp.add_run(f"Date: {today}").font.size = Pt(10)
_set_spacing(dp, after_pt=2)
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CPNI CLEC-Reseller certification letter generated: %s", out)
return str(out)

View file

@ -0,0 +1,289 @@
"""
Generate the FCC CPNI Annual Certification Letter IXC (Facilities) variant.
Tailors the generic CPNI certification under 47 CFR § 64.2009(e) for an
Interexchange Carrier (IXC) focused on toll-call record handling. Key
variant differences:
* CPNI scope centered on toll call records, PIC-change verification,
and interexchange account authentication.
* Customer approval for CPNI usage follows written/oral opt-in,
documented in the toll-account record.
* The CPNI Protection Officer's duties include PIC / LIDB / CDR
access governance and fraud-management system controls.
"""
from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.cpni_ixc")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CPNI IXC generation unavailable")
Document = None # type: ignore[assignment,misc]
_NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "ixc"
VARIANT_LABEL = "Interexchange Carrier (IXC)"
MAX_FORFEITURE_PER_VIOLATION = "$251,322"
MAX_FORFEITURE_CAP = "$2,513,215"
def _sp(p, after=6, before=0):
p.paragraph_format.space_after = Pt(after)
if before:
p.paragraph_format.space_before = Pt(before)
def _h(doc, text):
p = doc.add_paragraph()
r = p.add_run(text)
r.font.size = Pt(12); r.bold = True; r.font.color.rgb = _NAVY
_sp(p, after=4, before=8)
def _b(doc, text, bold=False, size=10):
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.LEFT
r = p.add_run(text); r.font.size = Pt(size); r.bold = bold
_sp(p, after=6)
def _cb(doc, text, checked=True):
mark = "\u2611" if checked else "\u2610"
p = doc.add_paragraph()
r = p.add_run(f" {mark} {text}")
r.font.size = Pt(10)
_sp(p, after=3)
def generate_cpni_ixc(
output_path: str,
entity_name: str,
frn: str = "",
filer_id_499: str = "",
officer_name: str = "",
officer_title: str = "Chief Executive Officer",
complaints_count: int = 0,
complaints_description: str = "",
has_data_broker_inquiries: bool = False,
data_broker_description: str = "",
reporting_year: int = 0,
address_street: str = "",
address_city: str = "",
address_state: str = "",
address_zip: str = "",
contact_email: str = "",
contact_phone: str = "",
breaches: list[dict] | None = None,
**_: dict,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
if reporting_year == 0:
reporting_year = datetime.now().year - 1
breaches = breaches or []
doc = Document()
for s in doc.sections:
s.top_margin = Inches(1); s.bottom_margin = Inches(1)
s.left_margin = Inches(1.25); s.right_margin = Inches(1.25)
today = datetime.now().strftime("%B %d, %Y")
signer = officer_name or "Authorized Officer"
title = officer_title or "Officer"
tp = doc.add_paragraph(); tp.alignment = WD_ALIGN_PARAGRAPH.CENTER
t = tp.add_run("CPNI Annual Certification Letter")
t.font.size = Pt(14); t.bold = True; t.font.color.rgb = _NAVY
_sp(tp, after=2)
sp = doc.add_paragraph(); sp.alignment = WD_ALIGN_PARAGRAPH.CENTER
s = sp.add_run(
f"Interexchange Carrier \u2014 47 CFR \u00a7 64.2009 "
f"\u2014 Calendar Year {reporting_year}"
)
s.font.size = Pt(10); s.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
_sp(sp, after=8)
_h(doc, "1. Provider Information")
lines = [f"Company Name: {entity_name}", f"Variant: {VARIANT_LABEL}"]
if frn: lines.append(f"FCC Registration Number (FRN): {frn}")
if filer_id_499: lines.append(f"FCC Form 499 Filer ID: {filer_id_499}")
addr = ", ".join(filter(None, [address_street, address_city]))
if address_state or address_zip:
addr += f", {address_state} {address_zip}".strip()
if addr.strip(", "):
lines.append(f"Address: {addr.strip(', ')}")
if contact_phone: lines.append(f"Telephone: {contact_phone}")
if contact_email: lines.append(f"Email: {contact_email}")
lines.append(f"Certifying Officer: {signer}, {title}")
lines.append(f"Date of Filing: {today}")
lines.append(f"Filing Deadline: March 2, {reporting_year + 1}")
_b(doc, "\n".join(lines))
_h(doc, "2. Officer Statement of Personal Knowledge")
_b(doc, (
f"I, {signer}, {title} of {entity_name}, state that I have personal "
f"knowledge of the matters certified herein. I have reviewed "
f"{entity_name}'s CPNI operating procedures, including procedures "
f"governing toll call records, PIC-change verification, and "
f"interexchange account authentication. I have examined supervisory "
f"logs and records covering the reporting period. The "
f"representations herein are based on my personal review and are "
f"true and correct to the best of my knowledge, information, and "
f"belief."
))
_h(doc, "3. Certification of Compliance")
_b(doc, (
f"Pursuant to 47 CFR \u00a7 64.2009(e), {entity_name} hereby submits "
f"its annual certification of compliance with the CPNI rules at "
f"47 CFR \u00a7\u00a7 64.2001 through 64.2011 for the period "
f"January 1, {reporting_year} through December 31, {reporting_year}."
))
_h(doc, "4. How Our Procedures Ensure Compliance")
_b(doc, (
f"As an interexchange carrier, {entity_name}'s principal CPNI "
f"holdings are toll call detail records (CDRs), PIC-change records, "
f"and inter-carrier settlement data. Specific procedures include:"
))
_cb(doc, (
"Interexchange account authentication is required before release "
"of any toll record. Authentication is via pre-established "
"password or the verification of two non-CPNI account attributes "
"(47 CFR \u00a7 64.2010)."
))
_cb(doc, (
"PIC changes require affirmative verification under 47 CFR "
"\u00a7 64.1120 (Third Party Verification, Letter of Agency, or "
"Internet LOA) and are confirmed to the customer's address of "
"record before being implemented. Slamming-prevention controls "
"are integrated with CPNI access logging."
))
_cb(doc, (
"Customer approval for use of toll CPNI beyond the scope of the "
"subscribed service is obtained through written or oral opt-in "
"consent, documented in the account record per 47 CFR \u00a7 64.2007."
))
_cb(doc, (
"The CPNI Protection Officer has oversight authority over PIC "
"administration, LIDB access, CDR archives, and fraud-management "
"systems. Access attempts to these systems are logged to the named "
"individual."
))
_cb(doc, (
"Supervisory reviews of CPNI access are conducted at least "
"quarterly. Retention of access logs meets or exceeds two years "
"(CPNI) and five years (certification records) per 47 CFR "
"\u00a7 64.2009."
))
_cb(doc, (
"Annual CPNI training is required for all personnel with CPNI "
"access. Completion is tracked and attested to by the CPNI "
"Protection Officer."
))
_cb(doc, (
"Breach notification under 47 CFR \u00a7 64.2011 is implemented as "
"amended by FCC 23-111 \u2014 notice to the Commission within 7 "
"business days and to customers / law enforcement as soon as "
"practicable (not later than 30 days after reasonable determination)."
))
_h(doc, "5. Customer Complaints")
if complaints_count == 0:
_b(doc, (
f"{entity_name} has NOT received any customer complaints during "
f"the reporting period concerning the unauthorized release or "
f"use of CPNI. Zero (0) complaints were logged."
))
else:
desc = complaints_description or (
"Each complaint was investigated and resolved."
)
_b(doc, (
f"{entity_name} HAS received {complaints_count} customer "
f"complaint{'s' if complaints_count != 1 else ''} during the "
f"reporting period. {desc}"
))
_h(doc, "6. Data Broker Inquiries and Pretexting")
if not has_data_broker_inquiries:
_b(doc, (
f"{entity_name} has NOT received any inquiries, communications, "
f"or attempts by data brokers or other unauthorized parties "
f"seeking the unauthorized release of CPNI."
))
else:
desc = data_broker_description or (
"Each such inquiry was refused, documented, and escalated."
)
_b(doc, (
f"{entity_name} HAS received data broker or pretexting-style "
f"inquiries during the reporting period. {desc}"
))
_h(doc, "7. Breach Log Summary")
if not breaches:
_b(doc, (
f"{entity_name} experienced no CPNI breaches during the "
f"reporting period. No 47 CFR \u00a7 64.2011 notifications were "
f"required."
))
else:
_b(doc, (
f"{entity_name} experienced {len(breaches)} CPNI breach"
f"{'es' if len(breaches) != 1 else ''} during the reporting "
f"period; each was reported within 7 business days."
))
_h(doc, "8. Penalties, Truthfulness, and Perjury Acknowledgment")
_b(doc, (
f"{entity_name} and the undersigned acknowledge that CPNI rule "
f"violations may subject the carrier to forfeitures up to "
f"{MAX_FORFEITURE_PER_VIOLATION} per violation and up to "
f"{MAX_FORFEITURE_CAP} for any single act or failure to act "
f"(adjusted per 47 CFR \u00a7 1.80)."
))
_b(doc, (
"Pursuant to 47 CFR \u00a7 1.17, the undersigned represents that no "
"material factual information has been withheld and all statements "
"are truthful, accurate, and complete."
))
_b(doc, (
"The undersigned acknowledges that willful false statements are "
"punishable under Title 18, U.S.C. \u00a7 1001, and by forfeiture "
"under 47 U.S.C. \u00a7 503."
))
_h(doc, "9. Signature of Certifying Officer")
_b(doc, (
"I declare under penalty of perjury under the laws of the United "
"States of America that the foregoing is true and correct."
))
p = doc.add_paragraph(); _sp(p, after=0)
sig = doc.add_paragraph(); sig.add_run("_" * 45).font.size = Pt(10)
_sp(sig, after=2)
nm = doc.add_paragraph(); nr = nm.add_run(signer); nr.bold = True
nr.font.size = Pt(10); _sp(nm, after=2)
tpp = doc.add_paragraph()
tpp.add_run(f"{title}, {entity_name}").font.size = Pt(10)
_sp(tpp, after=2)
dp = doc.add_paragraph(); dp.add_run(f"Date: {today}").font.size = Pt(10)
_sp(dp, after=2)
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CPNI IXC certification letter generated: %s", out)
return str(out)

View file

@ -0,0 +1,270 @@
"""
Generate the FCC CPNI Annual Certification Letter IXC Reseller variant.
An IXC reseller buys wholesale toll minutes from an underlying carrier
and resells them under its own brand. CPNI obligations therefore extend
to both the retail end-user records the reseller maintains directly AND
to the toll-CDR flow from the wholesale carrier. Safeguards include
contractual flow-down terms with the upstream.
"""
from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.cpni_ixc_reseller")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CPNI IXC-Reseller generation unavailable")
Document = None # type: ignore[assignment,misc]
_NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "ixc_reseller"
VARIANT_LABEL = "Interexchange Carrier — Reseller"
MAX_FORFEITURE_PER_VIOLATION = "$251,322"
MAX_FORFEITURE_CAP = "$2,513,215"
def _sp(p, after=6, before=0):
p.paragraph_format.space_after = Pt(after)
if before:
p.paragraph_format.space_before = Pt(before)
def _h(doc, text):
p = doc.add_paragraph(); r = p.add_run(text)
r.font.size = Pt(12); r.bold = True; r.font.color.rgb = _NAVY
_sp(p, after=4, before=8)
def _b(doc, text, bold=False, size=10):
p = doc.add_paragraph(); p.alignment = WD_ALIGN_PARAGRAPH.LEFT
r = p.add_run(text); r.font.size = Pt(size); r.bold = bold
_sp(p, after=6)
def _cb(doc, text, checked=True):
mark = "\u2611" if checked else "\u2610"
p = doc.add_paragraph()
r = p.add_run(f" {mark} {text}"); r.font.size = Pt(10)
_sp(p, after=3)
def generate_cpni_ixc_reseller(
output_path: str,
entity_name: str,
frn: str = "",
filer_id_499: str = "",
officer_name: str = "",
officer_title: str = "Chief Executive Officer",
complaints_count: int = 0,
complaints_description: str = "",
has_data_broker_inquiries: bool = False,
data_broker_description: str = "",
reporting_year: int = 0,
upstream_wholesale_provider: str = "",
address_street: str = "",
address_city: str = "",
address_state: str = "",
address_zip: str = "",
contact_email: str = "",
contact_phone: str = "",
breaches: list[dict] | None = None,
**_: dict,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
if reporting_year == 0:
reporting_year = datetime.now().year - 1
breaches = breaches or []
doc = Document()
for s in doc.sections:
s.top_margin = Inches(1); s.bottom_margin = Inches(1)
s.left_margin = Inches(1.25); s.right_margin = Inches(1.25)
today = datetime.now().strftime("%B %d, %Y")
signer = officer_name or "Authorized Officer"
title = officer_title or "Officer"
upstream = upstream_wholesale_provider or "its wholesale underlying carrier(s)"
tp = doc.add_paragraph(); tp.alignment = WD_ALIGN_PARAGRAPH.CENTER
t = tp.add_run("CPNI Annual Certification Letter")
t.font.size = Pt(14); t.bold = True; t.font.color.rgb = _NAVY
_sp(tp, after=2)
sp = doc.add_paragraph(); sp.alignment = WD_ALIGN_PARAGRAPH.CENTER
s = sp.add_run(
f"Interexchange Carrier — Reseller \u2014 47 CFR \u00a7 64.2009 "
f"\u2014 Calendar Year {reporting_year}"
)
s.font.size = Pt(10); s.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
_sp(sp, after=8)
_h(doc, "1. Provider Information")
lines = [f"Company Name: {entity_name}", f"Variant: {VARIANT_LABEL}"]
if frn: lines.append(f"FCC Registration Number (FRN): {frn}")
if filer_id_499: lines.append(f"FCC Form 499 Filer ID: {filer_id_499}")
addr = ", ".join(filter(None, [address_street, address_city]))
if address_state or address_zip:
addr += f", {address_state} {address_zip}".strip()
if addr.strip(", "):
lines.append(f"Address: {addr.strip(', ')}")
if contact_phone: lines.append(f"Telephone: {contact_phone}")
if contact_email: lines.append(f"Email: {contact_email}")
lines.append(f"Certifying Officer: {signer}, {title}")
lines.append(f"Date of Filing: {today}")
lines.append(f"Filing Deadline: March 2, {reporting_year + 1}")
_b(doc, "\n".join(lines))
_h(doc, "2. Officer Statement of Personal Knowledge")
_b(doc, (
f"I, {signer}, {title} of {entity_name}, state that I have personal "
f"knowledge of the matters certified herein. I have reviewed the "
f"CPNI operating procedures of {entity_name}, including wholesale "
f"CPNI flow-down terms with upstream toll providers, and examined "
f"supervisory logs and records covering the reporting period."
))
_h(doc, "3. Certification of Compliance")
_b(doc, (
f"Pursuant to 47 CFR \u00a7 64.2009(e), {entity_name} hereby submits "
f"its annual certification of compliance with the CPNI rules at "
f"47 CFR \u00a7\u00a7 64.2001 through 64.2011 for the period "
f"January 1, {reporting_year} through December 31, {reporting_year}."
))
_h(doc, "4. How Our Procedures Ensure Compliance")
_b(doc, (
f"As an IXC reseller purchasing wholesale toll minutes from "
f"{upstream} and reselling them under its own brand, {entity_name} "
f"protects CPNI at two boundaries: (1) the retail end-user toll-"
f"account interface, and (2) the CDR and billing-record flow from "
f"the underlying toll carrier(s)."
))
_cb(doc, (
"Interexchange account authentication is required before release "
"of any toll record to a customer-initiated inquiry "
"(47 CFR \u00a7 64.2010)."
))
_cb(doc, (
"PIC-change verifications (TPV, LOA, or Internet LOA) are performed "
"per 47 CFR \u00a7 64.1120 and confirmed to the customer's address "
"of record prior to implementation."
))
_cb(doc, (
f"Reseller flow-down: {entity_name}'s wholesale agreement with "
f"{upstream} expressly requires the upstream toll carrier to "
f"protect end-user CPNI received through {entity_name} consistent "
f"with 47 CFR \u00a7\u00a7 64.2001\u201364.2011. {entity_name} "
f"reviews upstream CPNI attestations annually."
))
_cb(doc, (
"The CPNI Protection Officer has oversight authority over both "
"retail toll-account records and wholesale CDR handoffs, and "
"reviews upstream carrier breach notices per 47 CFR \u00a7 64.2011."
))
_cb(doc, (
"Customer approval for CPNI usage beyond the scope of the "
"subscribed toll service is obtained through written or oral "
"opt-in consent, documented per 47 CFR \u00a7 64.2007."
))
_cb(doc, (
"Supervisory review of CPNI access occurs at least quarterly; "
"retention meets or exceeds two years (CPNI logs) and five years "
"(certification records) per 47 CFR \u00a7 64.2009."
))
_cb(doc, (
"Annual CPNI training is mandatory for all personnel with CPNI "
"access; breach notification procedures comply with 47 CFR "
"\u00a7 64.2011 as amended by FCC 23-111."
))
_h(doc, "5. Customer Complaints")
if complaints_count == 0:
_b(doc, (
f"{entity_name} has NOT received any customer complaints during "
f"the reporting period concerning the unauthorized release or "
f"use of CPNI. Zero (0) complaints were logged."
))
else:
desc = complaints_description or "Each complaint was investigated and resolved."
_b(doc, (
f"{entity_name} HAS received {complaints_count} customer "
f"complaint{'s' if complaints_count != 1 else ''} during the "
f"reporting period. {desc}"
))
_h(doc, "6. Data Broker Inquiries and Pretexting")
if not has_data_broker_inquiries:
_b(doc, (
f"{entity_name} has NOT received any inquiries, communications, "
f"or attempts by data brokers or other unauthorized parties "
f"seeking the unauthorized release of CPNI."
))
else:
desc = data_broker_description or "Each was refused, documented, and escalated."
_b(doc, (
f"{entity_name} HAS received data broker or pretexting-style "
f"inquiries during the reporting period. {desc}"
))
_h(doc, "7. Breach Log Summary")
if not breaches:
_b(doc, (
f"{entity_name} experienced no CPNI breaches during the "
f"reporting period. No 47 CFR \u00a7 64.2011 notifications "
f"were required."
))
else:
_b(doc, (
f"{entity_name} experienced {len(breaches)} CPNI breach"
f"{'es' if len(breaches) != 1 else ''} during the reporting "
f"period; each was reported within 7 business days."
))
_h(doc, "8. Penalties, Truthfulness, and Perjury Acknowledgment")
_b(doc, (
f"{entity_name} and the undersigned officer acknowledge that CPNI "
f"rule violations may subject the carrier to forfeitures up to "
f"{MAX_FORFEITURE_PER_VIOLATION} per violation and up to "
f"{MAX_FORFEITURE_CAP} for any single act or failure to act."
))
_b(doc, (
"Pursuant to 47 CFR \u00a7 1.17, the undersigned represents that "
"no material factual information has been withheld and that all "
"statements are truthful, accurate, and complete."
))
_b(doc, (
"The undersigned acknowledges that willful false statements are "
"punishable under Title 18, U.S.C. \u00a7 1001, and by forfeiture "
"under 47 U.S.C. \u00a7 503."
))
_h(doc, "9. Signature of Certifying Officer")
_b(doc, (
"I declare under penalty of perjury under the laws of the United "
"States of America that the foregoing is true and correct."
))
p = doc.add_paragraph(); _sp(p, after=0)
sig = doc.add_paragraph(); sig.add_run("_" * 45).font.size = Pt(10); _sp(sig, after=2)
nm = doc.add_paragraph(); nr = nm.add_run(signer); nr.bold = True
nr.font.size = Pt(10); _sp(nm, after=2)
tpp = doc.add_paragraph(); tpp.add_run(f"{title}, {entity_name}").font.size = Pt(10)
_sp(tpp, after=2)
dp = doc.add_paragraph(); dp.add_run(f"Date: {today}").font.size = Pt(10)
_sp(dp, after=2)
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CPNI IXC-Reseller certification letter generated: %s", out)
return str(out)

View file

@ -0,0 +1,225 @@
"""
Generate the FCC CPNI Annual Certification Letter Private Line / BDS variant.
A private-line (point-to-point) or Business Data Service (BDS) offering
typically holds negligible CPNI: there is no switched calling, no PIC,
no per-call detail record, and no directory assistance. The carrier's
records are limited to circuit identifiers, service-address endpoints,
and enterprise billing data. These records generally fall outside the
statutory definition of CPNI at 47 USC § 222(h)(1), which is tied to
"telecommunications service" used by a customer.
This is a short, one-page certification that recites the carrier's
status, acknowledges the limited applicability of the CPNI rules to
its offerings, and commits to the same statutory safeguards (47 CFR
§ 1.17 truthfulness, Title 18 perjury acknowledgment, and forfeiture
awareness).
"""
from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.cpni_private_line")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CPNI Private Line generation unavailable")
Document = None # type: ignore[assignment,misc]
_NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "private_line"
VARIANT_LABEL = "Private Line / Business Data Service (BDS)"
MAX_FORFEITURE_PER_VIOLATION = "$251,322"
MAX_FORFEITURE_CAP = "$2,513,215"
def _sp(p, after=6, before=0):
p.paragraph_format.space_after = Pt(after)
if before:
p.paragraph_format.space_before = Pt(before)
def _h(doc, text):
p = doc.add_paragraph(); r = p.add_run(text)
r.font.size = Pt(12); r.bold = True; r.font.color.rgb = _NAVY
_sp(p, after=4, before=8)
def _b(doc, text, bold=False, size=10):
p = doc.add_paragraph(); p.alignment = WD_ALIGN_PARAGRAPH.LEFT
r = p.add_run(text); r.font.size = Pt(size); r.bold = bold
_sp(p, after=6)
def generate_cpni_private_line(
output_path: str,
entity_name: str,
frn: str = "",
filer_id_499: str = "",
officer_name: str = "",
officer_title: str = "Chief Executive Officer",
complaints_count: int = 0,
complaints_description: str = "",
has_data_broker_inquiries: bool = False,
data_broker_description: str = "",
reporting_year: int = 0,
address_street: str = "",
address_city: str = "",
address_state: str = "",
address_zip: str = "",
contact_email: str = "",
contact_phone: str = "",
breaches: list[dict] | None = None,
**_: dict,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
if reporting_year == 0:
reporting_year = datetime.now().year - 1
breaches = breaches or []
doc = Document()
for s in doc.sections:
s.top_margin = Inches(0.9); s.bottom_margin = Inches(0.9)
s.left_margin = Inches(1); s.right_margin = Inches(1)
today = datetime.now().strftime("%B %d, %Y")
signer = officer_name or "Authorized Officer"
title = officer_title or "Officer"
tp = doc.add_paragraph(); tp.alignment = WD_ALIGN_PARAGRAPH.CENTER
t = tp.add_run("CPNI Annual Certification Letter")
t.font.size = Pt(14); t.bold = True; t.font.color.rgb = _NAVY
_sp(tp, after=2)
sp = doc.add_paragraph(); sp.alignment = WD_ALIGN_PARAGRAPH.CENTER
s = sp.add_run(
f"Private Line / Business Data Service \u2014 "
f"47 CFR \u00a7 64.2009 \u2014 Calendar Year {reporting_year}"
)
s.font.size = Pt(10); s.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
_sp(sp, after=6)
_h(doc, "1. Provider Information and Scope")
lines = [f"Company Name: {entity_name}", f"Variant: {VARIANT_LABEL}"]
if frn: lines.append(f"FCC Registration Number (FRN): {frn}")
if filer_id_499: lines.append(f"FCC Form 499 Filer ID: {filer_id_499}")
addr = ", ".join(filter(None, [address_street, address_city]))
if address_state or address_zip:
addr += f", {address_state} {address_zip}".strip()
if addr.strip(", "):
lines.append(f"Address: {addr.strip(', ')}")
if contact_phone: lines.append(f"Telephone: {contact_phone}")
if contact_email: lines.append(f"Email: {contact_email}")
lines.append(f"Certifying Officer: {signer}, {title}")
lines.append(f"Date of Filing: {today}")
lines.append(f"Filing Deadline: March 2, {reporting_year + 1}")
_b(doc, "\n".join(lines))
_h(doc, "2. Officer Statement of Personal Knowledge")
_b(doc, (
f"I, {signer}, {title} of {entity_name}, state that I have personal "
f"knowledge of the matters certified herein and have reviewed "
f"{entity_name}'s records-handling procedures for private-line / "
f"Business Data Service (BDS) circuits covering the reporting "
f"period."
))
_h(doc, "3. Limited Applicability of CPNI Rules")
_b(doc, (
f"{entity_name}'s offerings consist principally of dedicated "
f"point-to-point private-line and/or Business Data Service "
f"circuits. These offerings generate no switched-call detail "
f"records, no presubscribed interexchange carrier (PIC) "
f"information, and no directory-assistance records. The records "
f"{entity_name} maintains \u2014 circuit identifiers, A-end and "
f"Z-end service addresses, and enterprise billing data \u2014 "
f"generally fall outside the statutory definition of Customer "
f"Proprietary Network Information at 47 USC \u00a7 222(h)(1), "
f"which is tied to the customer's use of a telecommunications "
f"service."
))
_b(doc, (
f"To the extent any subset of these records constitutes CPNI "
f"under the Commission's rules, {entity_name} certifies compliance "
f"with 47 CFR \u00a7\u00a7 64.2001 through 64.2011 for the period "
f"January 1, {reporting_year} through December 31, {reporting_year}. "
f"Specifically, access to customer circuit records is restricted "
f"to authenticated personnel; authentication is required before "
f"disclosure in response to customer inquiries; annual training "
f"is provided; and breach-notification procedures comply with "
f"47 CFR \u00a7 64.2011 as amended by FCC 23-111."
))
_h(doc, "4. Customer Complaints and Data Broker Inquiries")
if complaints_count == 0 and not has_data_broker_inquiries:
_b(doc, (
f"{entity_name} has NOT received any customer complaints "
f"concerning the unauthorized release or use of CPNI during "
f"the reporting period, and has NOT received any inquiries or "
f"communications from data brokers or other unauthorized "
f"parties seeking CPNI."
))
else:
if complaints_count == 0:
_b(doc, (
f"{entity_name} has NOT received any customer complaints "
f"during the reporting period."
))
else:
desc = complaints_description or "Each was investigated and resolved."
_b(doc, (
f"{entity_name} HAS received {complaints_count} customer "
f"complaint{'s' if complaints_count != 1 else ''}. {desc}"
))
if not has_data_broker_inquiries:
_b(doc, (
f"{entity_name} has NOT received any data broker or "
f"pretexting inquiries during the reporting period."
))
else:
desc = data_broker_description or "Each was refused and documented."
_b(doc, (
f"{entity_name} HAS received data broker / pretexting "
f"inquiries. {desc}"
))
_h(doc, "5. Penalties, Truthfulness, and Perjury Acknowledgment")
_b(doc, (
f"{entity_name} acknowledges that CPNI rule violations may subject "
f"the carrier to forfeitures up to {MAX_FORFEITURE_PER_VIOLATION} "
f"per violation and up to {MAX_FORFEITURE_CAP} for any single act "
f"or failure to act. Pursuant to 47 CFR \u00a7 1.17, the "
f"undersigned represents that no material factual information has "
f"been withheld and all statements are truthful, accurate, and "
f"complete. Willful false statements are punishable under Title "
f"18, U.S.C. \u00a7 1001, and by forfeiture under 47 U.S.C. "
f"\u00a7 503."
))
_h(doc, "6. Signature of Certifying Officer")
_b(doc, (
"I declare under penalty of perjury under the laws of the United "
"States of America that the foregoing is true and correct."
))
sig = doc.add_paragraph(); sig.add_run("_" * 45).font.size = Pt(10); _sp(sig, after=2)
nm = doc.add_paragraph(); nr = nm.add_run(signer); nr.bold = True
nr.font.size = Pt(10); _sp(nm, after=2)
tpp = doc.add_paragraph(); tpp.add_run(f"{title}, {entity_name}").font.size = Pt(10)
_sp(tpp, after=2)
dp = doc.add_paragraph(); dp.add_run(f"Date: {today}").font.size = Pt(10)
_sp(dp, after=2)
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CPNI Private Line certification letter generated: %s", out)
return str(out)

View file

@ -0,0 +1,258 @@
"""
Generate the CPNI Procedure Statement internal / customer-facing policy.
This is **not** the annual ECFS certification letter (see
``cpni_cert_letter_generator.py`` for that). This is the 10-section policy
document every carrier must maintain and provide to customers under
47 CFR § 64.2008 (annual notice). Every example carrier in
``docs/examplefilings/`` has one of these alongside their CPNI cert
Cloud One PBX, Fortel, VoIPFlo, Engage, Syntracom, Zingo, TIP Systems
all using this exact 10-section outline.
Canonical section outline:
1. Purpose
2. Definition of CPNI
3. Employee Training and Compliance
4. Customer Authentication and Access Control
5. Use of CPNI
6. Customer Rights and Notification
7. CPNI Breach Notification and Reporting
8. Record Keeping and Audits
9. Enforcement and Penalties
10. Contact Information
Footer: Effective Date / Signatory / Reviewed By / Next Review Date.
Usage:
from scripts.document_gen.templates.cpni_procedure_statement_generator import (
generate_cpni_procedure_statement,
)
path = generate_cpni_procedure_statement(
entity_name="Falcon Broadband LLC",
entity_abbr="FBL",
support_email="support@falconbroadband.com",
website="https://falconbroadband.com",
signatory_name="Jane Doe",
signatory_title="President",
output_path="/tmp/cpni_policy.docx",
)
"""
from __future__ import annotations
import logging
from datetime import date, datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.cpni_policy")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CPNI policy generation unavailable")
Document = None # type: ignore[assignment, misc]
NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
BODY_SIZE = Pt(11) if Document else None
HEADING_SIZE = Pt(13) if Document else None
PARA_AFTER = Pt(6) if Document else None
def _heading(doc, text: str) -> None:
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(12)
p.paragraph_format.space_after = Pt(4)
run = p.add_run(text)
run.bold = True
run.font.size = HEADING_SIZE
run.font.color.rgb = NAVY
def _body(doc, text: str, bold: bool = False) -> None:
p = doc.add_paragraph()
p.paragraph_format.space_after = PARA_AFTER
run = p.add_run(text)
run.font.size = BODY_SIZE
run.bold = bold
def _bullets(doc, items: list[str]) -> None:
for item in items:
p = doc.add_paragraph(style="List Bullet")
p.paragraph_format.left_indent = Inches(0.25)
p.paragraph_format.space_after = Pt(3)
p.clear()
run = p.add_run(item)
run.font.size = BODY_SIZE
def generate_cpni_procedure_statement(
# Identity
entity_name: str,
entity_abbr: str = "",
# Customer-facing contacts
support_email: str = "",
website: str = "",
# Signatory (typically an officer)
signatory_name: str = "",
signatory_title: str = "",
# Dates
effective_date: str = "",
next_review_date: str = "",
# Reviewer (defaults to Performance West Inc.)
reviewer_name: str = "Justin Hannah",
reviewer_company: str = "Performance West Inc.",
# Small wording knobs
is_wholesale: bool = False,
# Output
output_path: str = "/tmp/cpni_procedure_statement.docx",
) -> Optional[str]:
"""Generate the 10-section CPNI Procedure Statement as a DOCX file."""
if Document is None:
LOG.error("python-docx not installed")
return None
abbr = entity_abbr or entity_name
today = date.today()
effective = effective_date or today.strftime("%m/%d/%Y")
next_review = next_review_date or today.replace(year=today.year + 1).strftime("%m/%d/%Y")
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)
# Title
title_p = doc.add_paragraph()
title_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
title_run = title_p.add_run(
"Customer Proprietary Network Information (CPNI) Procedure Statement"
)
title_run.font.size = Pt(14)
title_run.bold = True
title_run.font.color.rgb = NAVY
title_p.paragraph_format.space_after = Pt(2)
subtitle = doc.add_paragraph()
subtitle.alignment = WD_ALIGN_PARAGRAPH.CENTER
sub_run = subtitle.add_run(entity_name)
sub_run.font.size = Pt(12)
sub_run.bold = True
subtitle.paragraph_format.space_after = Pt(18)
scope = (
"wholesale customer proprietary data"
if is_wholesale
else "Customer Proprietary Network Information (CPNI)"
)
# ── 1. Purpose ──────────────────────────────────────────────────
_heading(doc, "1. Purpose")
_body(doc, (
f"{entity_name} is committed to protecting the confidentiality and "
f"security of {scope} as required by the Federal Communications "
f"Commission (FCC) under Section 222 of the Communications Act. "
f"This document outlines the procedures {entity_name} follows to "
f"ensure compliance with CPNI regulations set forth in 47 CFR "
f"\u00a7\u00a7 64.2001 through 64.2011."
))
# ── 2. Definition of CPNI ──────────────────────────────────────
_heading(doc, "2. Definition of CPNI")
_body(doc, (
"CPNI includes information related to the quantity, technical "
"configuration, type, destination, location, and amount of use of "
"telecommunications services by customers. It does not include "
"subscriber list information such as name, address, and telephone "
"number."
))
# ── 3. Employee Training and Compliance ────────────────────────
_heading(doc, "3. Employee Training and Compliance")
_bullets(doc, [
f"{entity_name} trains all employees in the handling, protection, and authorized use of CPNI.",
"Employees are prohibited from accessing or disclosing CPNI unless required for legitimate business purposes.",
"Any violation of CPNI policies may result in disciplinary action, including termination.",
])
# ── 4. Customer Authentication and Access Control ──────────────
_heading(doc, "4. Customer Authentication and Access Control")
_bullets(doc, [
f"{entity_name} authenticates customers before disclosing CPNI via telephone, online, or in-store interactions.",
"Telephone access to CPNI requires authentication through a pre-established password or by sending information to the customer's registered address.",
"Online account access requires a secure login process with multi-factor authentication where applicable.",
"In-person requests require valid government-issued identification.",
])
# ── 5. Use of CPNI ─────────────────────────────────────────────
_heading(doc, "5. Use of CPNI")
_bullets(doc, [
f"{entity_name} does not use CPNI for marketing purposes unless the customer provides explicit opt-in consent.",
"CPNI may be used for billing, fraud prevention, and service-related notifications.",
"CPNI is not shared with third parties unless required by law or with customer authorization.",
])
# ── 6. Customer Rights and Notification ────────────────────────
_heading(doc, "6. Customer Rights and Notification")
_bullets(doc, [
"Customers have the right to restrict the use of their CPNI for marketing purposes.",
f"{entity_name} provides annual CPNI notices informing customers of their rights and how to manage their CPNI preferences.",
"Customers may change their CPNI settings by contacting customer service.",
])
# ── 7. CPNI Breach Notification and Reporting ──────────────────
_heading(doc, "7. CPNI Breach Notification and Reporting")
_bullets(doc, [
f"In the case of a CPNI breach, {entity_name} follows FCC guidelines for reporting incidents per 47 CFR \u00a7 64.2011.",
"Notification is made to the FCC, FBI, and U.S. Secret Service (the Federal Agencies) via the central reporting facility as soon as practicable, and no later than 30 days after reasonable determination of a breach.",
"Customers are notified of unauthorized access as soon as practicable and in no event later than 30 days after notification to law enforcement (unless a delay is requested by law enforcement).",
"The company maintains records of CPNI breaches and reports them to law enforcement as required.",
])
# ── 8. Record Keeping and Audits ───────────────────────────────
_heading(doc, "8. Record Keeping and Audits")
_bullets(doc, [
f"{entity_name} maintains records of customer CPNI approvals, marketing usage, and access logs for at least two years.",
"The company conducts annual audits to ensure compliance with CPNI policies and regulatory requirements.",
])
# ── 9. Enforcement and Penalties ───────────────────────────────
_heading(doc, "9. Enforcement and Penalties")
_bullets(doc, [
"Any employee found violating CPNI policies will be subject to disciplinary actions, including possible termination.",
f"{entity_name} complies with all regulatory enforcement actions and may be subject to fines for non-compliance. Per FCC Enforcement Advisory DA-26-139, failure to comply with the CPNI rules may subject the company to monetary forfeitures of up to $251,322 per violation (up to a maximum of $2,513,215 for continuing violations).",
])
# ── 10. Contact Information ────────────────────────────────────
_heading(doc, "10. Contact Information")
_body(doc, (
f"For questions or concerns regarding CPNI policies, customers may "
f"contact {entity_name} Support:"
))
if support_email:
_body(doc, f"Email: {support_email}")
if website:
_body(doc, f"Website: {website}")
# ── Footer: dates + signatory ──────────────────────────────────
doc.add_paragraph("")
_body(doc, f"Effective Date: {effective}")
if signatory_name:
title_suffix = f", {signatory_title}" if signatory_title else ""
_body(doc, f"Signatory: {signatory_name}{title_suffix}, {entity_name}")
if reviewer_name:
_body(doc, f"Reviewed By: {reviewer_name}, {reviewer_company}")
_body(doc, f"Next Review Date: {next_review}")
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CPNI Procedure Statement generated: %s", out)
return str(out)

View file

@ -0,0 +1,272 @@
"""
Generate the FCC CPNI Annual Certification Letter Satellite variant.
Tailors the CPNI certification under 47 CFR § 64.2009(e) for a provider
of Mobile Satellite Service (MSS) or Fixed Satellite Service (FSS)
operating or leasing earth-station capacity to deliver telecommunications
service. Variant specifics:
* Scope covers earth-station / NOC operator records, beam assignment
logs, and per-terminal activation records.
* Customer approval follows written / oral opt-in; many FSS
deployments authorize CPNI usage through the master service
agreement with the enterprise customer.
* Physical-security controls at earth stations (per Part 25 license
conditions) are incorporated into the CPNI safeguard narrative.
"""
from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.cpni_satellite")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CPNI Satellite generation unavailable")
Document = None # type: ignore[assignment,misc]
_NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "satellite"
VARIANT_LABEL = "Satellite (MSS / FSS)"
MAX_FORFEITURE_PER_VIOLATION = "$251,322"
MAX_FORFEITURE_CAP = "$2,513,215"
def _sp(p, after=6, before=0):
p.paragraph_format.space_after = Pt(after)
if before:
p.paragraph_format.space_before = Pt(before)
def _h(doc, text):
p = doc.add_paragraph(); r = p.add_run(text)
r.font.size = Pt(12); r.bold = True; r.font.color.rgb = _NAVY
_sp(p, after=4, before=8)
def _b(doc, text, bold=False, size=10):
p = doc.add_paragraph(); p.alignment = WD_ALIGN_PARAGRAPH.LEFT
r = p.add_run(text); r.font.size = Pt(size); r.bold = bold
_sp(p, after=6)
def _cb(doc, text, checked=True):
mark = "\u2611" if checked else "\u2610"
p = doc.add_paragraph()
r = p.add_run(f" {mark} {text}"); r.font.size = Pt(10)
_sp(p, after=3)
def generate_cpni_satellite(
output_path: str,
entity_name: str,
frn: str = "",
filer_id_499: str = "",
officer_name: str = "",
officer_title: str = "Chief Executive Officer",
complaints_count: int = 0,
complaints_description: str = "",
has_data_broker_inquiries: bool = False,
data_broker_description: str = "",
reporting_year: int = 0,
address_street: str = "",
address_city: str = "",
address_state: str = "",
address_zip: str = "",
contact_email: str = "",
contact_phone: str = "",
breaches: list[dict] | None = None,
**_: dict,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
if reporting_year == 0:
reporting_year = datetime.now().year - 1
breaches = breaches or []
doc = Document()
for s in doc.sections:
s.top_margin = Inches(1); s.bottom_margin = Inches(1)
s.left_margin = Inches(1.25); s.right_margin = Inches(1.25)
today = datetime.now().strftime("%B %d, %Y")
signer = officer_name or "Authorized Officer"
title = officer_title or "Officer"
tp = doc.add_paragraph(); tp.alignment = WD_ALIGN_PARAGRAPH.CENTER
t = tp.add_run("CPNI Annual Certification Letter")
t.font.size = Pt(14); t.bold = True; t.font.color.rgb = _NAVY
_sp(tp, after=2)
sp = doc.add_paragraph(); sp.alignment = WD_ALIGN_PARAGRAPH.CENTER
s = sp.add_run(
f"Satellite (MSS / FSS) \u2014 47 CFR \u00a7 64.2009 "
f"\u2014 Calendar Year {reporting_year}"
)
s.font.size = Pt(10); s.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
_sp(sp, after=8)
_h(doc, "1. Provider Information")
lines = [f"Company Name: {entity_name}", f"Variant: {VARIANT_LABEL}"]
if frn: lines.append(f"FCC Registration Number (FRN): {frn}")
if filer_id_499: lines.append(f"FCC Form 499 Filer ID: {filer_id_499}")
addr = ", ".join(filter(None, [address_street, address_city]))
if address_state or address_zip:
addr += f", {address_state} {address_zip}".strip()
if addr.strip(", "):
lines.append(f"Address: {addr.strip(', ')}")
if contact_phone: lines.append(f"Telephone: {contact_phone}")
if contact_email: lines.append(f"Email: {contact_email}")
lines.append(f"Certifying Officer: {signer}, {title}")
lines.append(f"Date of Filing: {today}")
lines.append(f"Filing Deadline: March 2, {reporting_year + 1}")
_b(doc, "\n".join(lines))
_h(doc, "2. Officer Statement of Personal Knowledge")
_b(doc, (
f"I, {signer}, {title} of {entity_name}, state that I have personal "
f"knowledge of the matters certified herein, including procedures "
f"at the network operations center (NOC) governing subscriber "
f"terminal records, beam / transponder assignments, and enterprise "
f"master-service-agreement data. I have reviewed supervisory logs "
f"covering the reporting period."
))
_h(doc, "3. Certification of Compliance")
_b(doc, (
f"Pursuant to 47 CFR \u00a7 64.2009(e), {entity_name} hereby submits "
f"its annual certification of compliance with the CPNI rules at "
f"47 CFR \u00a7\u00a7 64.2001 through 64.2011 for the period "
f"January 1, {reporting_year} through December 31, {reporting_year}."
))
_h(doc, "4. How Our Procedures Ensure Compliance")
_b(doc, (
f"As a provider of MSS and/or FSS telecommunications service, "
f"{entity_name}'s CPNI holdings consist primarily of: subscriber "
f"and enterprise-customer account records, per-terminal activation "
f"/ deactivation logs, beam and transponder assignment records, "
f"and NOC-generated usage reports. Specific procedures include:"
))
_cb(doc, (
"Customer authentication is required before CPNI release. "
"Consumer MSS subscribers authenticate via password; enterprise "
"FSS customers authenticate through credentials assigned to named "
"points of contact under the master service agreement "
"(47 CFR \u00a7 64.2010)."
))
_cb(doc, (
"Customer approval for CPNI usage beyond the scope of the "
"subscribed service is obtained through written opt-in consent, "
"documented in the customer record per 47 CFR \u00a7 64.2007. "
"Enterprise MSAs include the required opt-in as a standard clause."
))
_cb(doc, (
"Earth-station / NOC operator access to CPNI-bearing systems is "
"restricted to cleared personnel. Physical access is controlled "
"by badge and, where applicable, by the security requirements of "
"the Part 25 earth-station license."
))
_cb(doc, (
"The CPNI Protection Officer's oversight scope includes NOC "
"operator activity, terminal provisioning workflows, and "
"beam-assignment systems."
))
_cb(doc, (
"Supervisory review of CPNI access occurs at least quarterly. "
"Retention of access logs meets or exceeds two years (CPNI) and "
"five years (certification records) per 47 CFR \u00a7 64.2009."
))
_cb(doc, (
"Annual CPNI training is required for all personnel with CPNI "
"access; breach notification procedures comply with 47 CFR "
"\u00a7 64.2011 as amended by FCC 23-111."
))
_h(doc, "5. Customer Complaints")
if complaints_count == 0:
_b(doc, (
f"{entity_name} has NOT received any customer complaints during "
f"the reporting period concerning the unauthorized release or "
f"use of CPNI. Zero (0) complaints were logged."
))
else:
desc = complaints_description or "Each complaint was investigated and resolved."
_b(doc, (
f"{entity_name} HAS received {complaints_count} customer "
f"complaint{'s' if complaints_count != 1 else ''} during the "
f"reporting period. {desc}"
))
_h(doc, "6. Data Broker Inquiries and Pretexting")
if not has_data_broker_inquiries:
_b(doc, (
f"{entity_name} has NOT received any inquiries, communications, "
f"or attempts by data brokers or other unauthorized parties "
f"seeking the unauthorized release of CPNI."
))
else:
desc = data_broker_description or "Each was refused, documented, and escalated."
_b(doc, (
f"{entity_name} HAS received data broker or pretexting-style "
f"inquiries during the reporting period. {desc}"
))
_h(doc, "7. Breach Log Summary")
if not breaches:
_b(doc, (
f"{entity_name} experienced no CPNI breaches during the "
f"reporting period. No 47 CFR \u00a7 64.2011 notifications "
f"were required."
))
else:
_b(doc, (
f"{entity_name} experienced {len(breaches)} CPNI breach"
f"{'es' if len(breaches) != 1 else ''} during the reporting "
f"period; each was reported within 7 business days."
))
_h(doc, "8. Penalties, Truthfulness, and Perjury Acknowledgment")
_b(doc, (
f"{entity_name} and the undersigned acknowledge that CPNI rule "
f"violations may subject the carrier to forfeitures up to "
f"{MAX_FORFEITURE_PER_VIOLATION} per violation and up to "
f"{MAX_FORFEITURE_CAP} for any single act or failure to act."
))
_b(doc, (
"Pursuant to 47 CFR \u00a7 1.17, the undersigned represents that no "
"material factual information has been withheld and all statements "
"are truthful, accurate, and complete."
))
_b(doc, (
"Willful false statements are punishable under Title 18, U.S.C. "
"\u00a7 1001, and by forfeiture under 47 U.S.C. \u00a7 503."
))
_h(doc, "9. Signature of Certifying Officer")
_b(doc, (
"I declare under penalty of perjury under the laws of the United "
"States of America that the foregoing is true and correct."
))
p = doc.add_paragraph(); _sp(p, after=0)
sig = doc.add_paragraph(); sig.add_run("_" * 45).font.size = Pt(10); _sp(sig, after=2)
nm = doc.add_paragraph(); nr = nm.add_run(signer); nr.bold = True
nr.font.size = Pt(10); _sp(nm, after=2)
tpp = doc.add_paragraph(); tpp.add_run(f"{title}, {entity_name}").font.size = Pt(10)
_sp(tpp, after=2)
dp = doc.add_paragraph(); dp.add_run(f"Date: {today}").font.size = Pt(10)
_sp(dp, after=2)
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CPNI Satellite certification letter generated: %s", out)
return str(out)

View file

@ -0,0 +1,282 @@
"""
Generate the FCC CPNI Annual Certification Letter Wireless (CMRS) variant.
Tailors the CPNI certification for a Commercial Mobile Radio Service
provider that operates its own radio / core network. Key variant
differences:
* Customer approval for CPNI use is frequently obtained through
handset-based (one-tap) mechanisms, in addition to traditional
opt-in.
* CPNI scope includes roaming records, eSIM provisioning / transfer
records, and device-level location data.
* Mobile location information is treated as CPNI and subject to
heightened consent safeguards consistent with the 2020 LocationSmart
Consent Decree (DA 20-299) and the 2024 Notice of Apparent Liability
against the Tier-1 carriers (FCC 24-40) addressing unauthorized
location-data sharing.
"""
from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.cpni_wireless")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CPNI Wireless generation unavailable")
Document = None # type: ignore[assignment,misc]
_NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "wireless"
VARIANT_LABEL = "Wireless (CMRS) — Facilities"
MAX_FORFEITURE_PER_VIOLATION = "$251,322"
MAX_FORFEITURE_CAP = "$2,513,215"
def _sp(p, after=6, before=0):
p.paragraph_format.space_after = Pt(after)
if before:
p.paragraph_format.space_before = Pt(before)
def _h(doc, text):
p = doc.add_paragraph(); r = p.add_run(text)
r.font.size = Pt(12); r.bold = True; r.font.color.rgb = _NAVY
_sp(p, after=4, before=8)
def _b(doc, text, bold=False, size=10):
p = doc.add_paragraph(); p.alignment = WD_ALIGN_PARAGRAPH.LEFT
r = p.add_run(text); r.font.size = Pt(size); r.bold = bold
_sp(p, after=6)
def _cb(doc, text, checked=True):
mark = "\u2611" if checked else "\u2610"
p = doc.add_paragraph()
r = p.add_run(f" {mark} {text}"); r.font.size = Pt(10)
_sp(p, after=3)
def generate_cpni_wireless(
output_path: str,
entity_name: str,
frn: str = "",
filer_id_499: str = "",
officer_name: str = "",
officer_title: str = "Chief Executive Officer",
complaints_count: int = 0,
complaints_description: str = "",
has_data_broker_inquiries: bool = False,
data_broker_description: str = "",
reporting_year: int = 0,
address_street: str = "",
address_city: str = "",
address_state: str = "",
address_zip: str = "",
contact_email: str = "",
contact_phone: str = "",
breaches: list[dict] | None = None,
**_: dict,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
if reporting_year == 0:
reporting_year = datetime.now().year - 1
breaches = breaches or []
doc = Document()
for s in doc.sections:
s.top_margin = Inches(1); s.bottom_margin = Inches(1)
s.left_margin = Inches(1.25); s.right_margin = Inches(1.25)
today = datetime.now().strftime("%B %d, %Y")
signer = officer_name or "Authorized Officer"
title = officer_title or "Officer"
tp = doc.add_paragraph(); tp.alignment = WD_ALIGN_PARAGRAPH.CENTER
t = tp.add_run("CPNI Annual Certification Letter")
t.font.size = Pt(14); t.bold = True; t.font.color.rgb = _NAVY
_sp(tp, after=2)
sp = doc.add_paragraph(); sp.alignment = WD_ALIGN_PARAGRAPH.CENTER
s = sp.add_run(
f"Wireless (CMRS) Facilities \u2014 47 CFR \u00a7 64.2009 "
f"\u2014 Calendar Year {reporting_year}"
)
s.font.size = Pt(10); s.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
_sp(sp, after=8)
_h(doc, "1. Provider Information")
lines = [f"Company Name: {entity_name}", f"Variant: {VARIANT_LABEL}"]
if frn: lines.append(f"FCC Registration Number (FRN): {frn}")
if filer_id_499: lines.append(f"FCC Form 499 Filer ID: {filer_id_499}")
addr = ", ".join(filter(None, [address_street, address_city]))
if address_state or address_zip:
addr += f", {address_state} {address_zip}".strip()
if addr.strip(", "):
lines.append(f"Address: {addr.strip(', ')}")
if contact_phone: lines.append(f"Telephone: {contact_phone}")
if contact_email: lines.append(f"Email: {contact_email}")
lines.append(f"Certifying Officer: {signer}, {title}")
lines.append(f"Date of Filing: {today}")
lines.append(f"Filing Deadline: March 2, {reporting_year + 1}")
_b(doc, "\n".join(lines))
_h(doc, "2. Officer Statement of Personal Knowledge")
_b(doc, (
f"I, {signer}, {title} of {entity_name}, state that I have personal "
f"knowledge of the matters certified herein, including procedures "
f"governing device-level location data, roaming records, SIM / eSIM "
f"provisioning, and handset-based customer consent flows. I have "
f"reviewed operating procedures and supervisory logs covering the "
f"reporting period."
))
_h(doc, "3. Certification of Compliance")
_b(doc, (
f"Pursuant to 47 CFR \u00a7 64.2009(e), {entity_name} hereby submits "
f"its annual certification of compliance with the CPNI rules at "
f"47 CFR \u00a7\u00a7 64.2001 through 64.2011 for the period "
f"January 1, {reporting_year} through December 31, {reporting_year}."
))
_h(doc, "4. How Our Procedures Ensure Compliance")
_b(doc, (
f"As a Commercial Mobile Radio Service (CMRS) provider, "
f"{entity_name}'s CPNI holdings include call detail records, "
f"roaming records, SIM/eSIM provisioning and transfer logs, and "
f"device-level location data. Specific procedures include:"
))
_cb(doc, (
"Customer authentication for CPNI disclosures in response to a "
"customer-initiated contact uses a pre-established password, or "
"in-app / on-device verification (biometric or PIN) tied to the "
"authenticated subscriber identity (47 CFR \u00a7 64.2010)."
))
_cb(doc, (
"Customer approval for CPNI use beyond the scope of the subscribed "
"service may be obtained through traditional opt-in (written / oral) "
"OR through a secure one-tap in-app consent flow that meets the "
"FCC's 'knowing consent' standard under 47 CFR \u00a7 64.2007. "
"Consents are timestamped and retained."
))
_cb(doc, (
"Location data consent. Consistent with the 2020 LocationSmart "
"Consent Decree (DA 20-299) and the 2024 NAL addressing unauthorized "
"third-party location disclosure, {entity_name} treats device "
"location data as CPNI and requires separate, express consent for "
"disclosure to any third party. A chain-of-consent audit is "
"performed for each location-data aggregator relationship."
).replace("{entity_name}", entity_name))
_cb(doc, (
"SIM / eSIM transfer (port-out / device-swap) requires multi-factor "
"authentication plus customer notification to the address of record "
"prior to completion \u2014 implementing the anti-SIM-swap rules "
"codified at 47 CFR \u00a7 64.2010(f)\u2013(g)."
))
_cb(doc, (
"Roaming records are protected with the same safeguards as home-"
"network CDRs; access is logged to the named individual and "
"reviewed quarterly by the CPNI Protection Officer."
))
_cb(doc, (
"Access logs are retained for at least two years; certification "
"records for five years; access is reviewed at least quarterly."
))
_cb(doc, (
"Annual CPNI training is mandatory for all personnel with CPNI "
"access; breach notification procedures comply with 47 CFR "
"\u00a7 64.2011 as amended by FCC 23-111."
))
_h(doc, "5. Customer Complaints")
if complaints_count == 0:
_b(doc, (
f"{entity_name} has NOT received any customer complaints during "
f"the reporting period concerning the unauthorized release or "
f"use of CPNI (including unauthorized location-data "
f"disclosures). Zero (0) complaints were logged."
))
else:
desc = complaints_description or "Each complaint was investigated and resolved."
_b(doc, (
f"{entity_name} HAS received {complaints_count} customer "
f"complaint{'s' if complaints_count != 1 else ''} during the "
f"reporting period. {desc}"
))
_h(doc, "6. Data Broker Inquiries and Pretexting")
if not has_data_broker_inquiries:
_b(doc, (
f"{entity_name} has NOT received any inquiries, communications, "
f"or attempts by data brokers or other unauthorized parties "
f"seeking the unauthorized release of CPNI or device location "
f"data."
))
else:
desc = data_broker_description or "Each was refused, documented, and escalated."
_b(doc, (
f"{entity_name} HAS received data broker or pretexting-style "
f"inquiries during the reporting period. {desc}"
))
_h(doc, "7. Breach Log Summary")
if not breaches:
_b(doc, (
f"{entity_name} experienced no CPNI breaches during the "
f"reporting period. No 47 CFR \u00a7 64.2011 notifications were "
f"required."
))
else:
_b(doc, (
f"{entity_name} experienced {len(breaches)} CPNI breach"
f"{'es' if len(breaches) != 1 else ''} during the reporting "
f"period; each was reported within 7 business days."
))
_h(doc, "8. Penalties, Truthfulness, and Perjury Acknowledgment")
_b(doc, (
f"{entity_name} and the undersigned acknowledge that CPNI rule "
f"violations may subject the carrier to forfeitures up to "
f"{MAX_FORFEITURE_PER_VIOLATION} per violation and up to "
f"{MAX_FORFEITURE_CAP} for any single act or failure to act."
))
_b(doc, (
"Pursuant to 47 CFR \u00a7 1.17, the undersigned represents that no "
"material factual information has been withheld and all statements "
"are truthful, accurate, and complete."
))
_b(doc, (
"Willful false statements are punishable under Title 18, U.S.C. "
"\u00a7 1001, and by forfeiture under 47 U.S.C. \u00a7 503."
))
_h(doc, "9. Signature of Certifying Officer")
_b(doc, (
"I declare under penalty of perjury under the laws of the United "
"States of America that the foregoing is true and correct."
))
p = doc.add_paragraph(); _sp(p, after=0)
sig = doc.add_paragraph(); sig.add_run("_" * 45).font.size = Pt(10); _sp(sig, after=2)
nm = doc.add_paragraph(); nr = nm.add_run(signer); nr.bold = True
nr.font.size = Pt(10); _sp(nm, after=2)
tpp = doc.add_paragraph(); tpp.add_run(f"{title}, {entity_name}").font.size = Pt(10)
_sp(tpp, after=2)
dp = doc.add_paragraph(); dp.add_run(f"Date: {today}").font.size = Pt(10)
_sp(dp, after=2)
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CPNI Wireless certification letter generated: %s", out)
return str(out)

View file

@ -0,0 +1,273 @@
"""
Generate the FCC CPNI Annual Certification Letter Wireless MVNO variant.
An MVNO does not own spectrum or a radio-access network; it resells a
host MNO's wireless service under its own brand. The MVNO directly
controls retail billing records, device-ordering records, and customer
support authentication flows. Everything touching the radio network
(location signaling, HLR / HSS attach records) is held by the host MNO
under its own CPNI certification. This variant clarifies the dividing
line and reinforces delegation + flow-down language.
"""
from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.cpni_wireless_mvno")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CPNI Wireless MVNO generation unavailable")
Document = None # type: ignore[assignment,misc]
_NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
VARIANT_ID = "wireless_mvno"
VARIANT_LABEL = "Wireless (CMRS) — MVNO"
MAX_FORFEITURE_PER_VIOLATION = "$251,322"
MAX_FORFEITURE_CAP = "$2,513,215"
def _sp(p, after=6, before=0):
p.paragraph_format.space_after = Pt(after)
if before:
p.paragraph_format.space_before = Pt(before)
def _h(doc, text):
p = doc.add_paragraph(); r = p.add_run(text)
r.font.size = Pt(12); r.bold = True; r.font.color.rgb = _NAVY
_sp(p, after=4, before=8)
def _b(doc, text, bold=False, size=10):
p = doc.add_paragraph(); p.alignment = WD_ALIGN_PARAGRAPH.LEFT
r = p.add_run(text); r.font.size = Pt(size); r.bold = bold
_sp(p, after=6)
def _cb(doc, text, checked=True):
mark = "\u2611" if checked else "\u2610"
p = doc.add_paragraph()
r = p.add_run(f" {mark} {text}"); r.font.size = Pt(10)
_sp(p, after=3)
def generate_cpni_wireless_mvno(
output_path: str,
entity_name: str,
frn: str = "",
filer_id_499: str = "",
officer_name: str = "",
officer_title: str = "Chief Executive Officer",
complaints_count: int = 0,
complaints_description: str = "",
has_data_broker_inquiries: bool = False,
data_broker_description: str = "",
reporting_year: int = 0,
host_mno_name: str = "",
address_street: str = "",
address_city: str = "",
address_state: str = "",
address_zip: str = "",
contact_email: str = "",
contact_phone: str = "",
breaches: list[dict] | None = None,
**_: dict,
) -> Optional[str]:
if Document is None:
LOG.error("python-docx not installed")
return None
if reporting_year == 0:
reporting_year = datetime.now().year - 1
breaches = breaches or []
host = host_mno_name or "its host Mobile Network Operator"
doc = Document()
for s in doc.sections:
s.top_margin = Inches(1); s.bottom_margin = Inches(1)
s.left_margin = Inches(1.25); s.right_margin = Inches(1.25)
today = datetime.now().strftime("%B %d, %Y")
signer = officer_name or "Authorized Officer"
title = officer_title or "Officer"
tp = doc.add_paragraph(); tp.alignment = WD_ALIGN_PARAGRAPH.CENTER
t = tp.add_run("CPNI Annual Certification Letter")
t.font.size = Pt(14); t.bold = True; t.font.color.rgb = _NAVY
_sp(tp, after=2)
sp = doc.add_paragraph(); sp.alignment = WD_ALIGN_PARAGRAPH.CENTER
s = sp.add_run(
f"Wireless (CMRS) — MVNO \u2014 47 CFR \u00a7 64.2009 "
f"\u2014 Calendar Year {reporting_year}"
)
s.font.size = Pt(10); s.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
_sp(sp, after=8)
_h(doc, "1. Provider Information")
lines = [f"Company Name: {entity_name}", f"Variant: {VARIANT_LABEL}"]
if frn: lines.append(f"FCC Registration Number (FRN): {frn}")
if filer_id_499: lines.append(f"FCC Form 499 Filer ID: {filer_id_499}")
addr = ", ".join(filter(None, [address_street, address_city]))
if address_state or address_zip:
addr += f", {address_state} {address_zip}".strip()
if addr.strip(", "):
lines.append(f"Address: {addr.strip(', ')}")
if contact_phone: lines.append(f"Telephone: {contact_phone}")
if contact_email: lines.append(f"Email: {contact_email}")
lines.append(f"Certifying Officer: {signer}, {title}")
lines.append(f"Host MNO: {host}")
lines.append(f"Date of Filing: {today}")
lines.append(f"Filing Deadline: March 2, {reporting_year + 1}")
_b(doc, "\n".join(lines))
_h(doc, "2. Officer Statement of Personal Knowledge")
_b(doc, (
f"I, {signer}, {title} of {entity_name}, state that I have personal "
f"knowledge of the matters certified herein. I have reviewed "
f"{entity_name}'s CPNI procedures, the CPNI-related portions of "
f"the MVNO wholesale agreement with {host}, and supervisory logs "
f"covering the reporting period."
))
_h(doc, "3. Certification of Compliance")
_b(doc, (
f"Pursuant to 47 CFR \u00a7 64.2009(e), {entity_name} hereby submits "
f"its annual certification of compliance with the CPNI rules at "
f"47 CFR \u00a7\u00a7 64.2001 through 64.2011 for the period "
f"January 1, {reporting_year} through December 31, {reporting_year}."
))
_h(doc, "4. How Our Procedures Ensure Compliance")
_b(doc, (
f"As a Mobile Virtual Network Operator (MVNO) that does not own "
f"spectrum or a radio-access network, {entity_name}'s CPNI "
f"responsibilities divide into (A) CPNI that {entity_name} directly "
f"controls and (B) CPNI that is held, transported, or generated by "
f"{host} and made available to {entity_name} pursuant to the MVNO "
f"agreement. Both are protected."
))
_b(doc, f"(A) CPNI directly controlled by {entity_name}:", bold=True)
_cb(doc, (
"Retail customer records, billing data, plan-change history, and "
"customer-support interaction logs are held in systems owned and "
"administered by {entity_name} and are subject to password-based "
"authentication, opt-in consent for marketing use, quarterly "
"supervisory review, and annual training per 47 CFR \u00a7\u00a7 "
"64.2005\u201364.2010."
).replace("{entity_name}", entity_name))
_cb(doc, (
"SIM / eSIM port-out and device-swap orders received by "
"{entity_name} require multi-factor authentication of the "
"subscriber plus notification to the address of record before the "
"order is submitted to {host} for execution (47 CFR \u00a7 64.2010)."
).replace("{entity_name}", entity_name).replace("{host}", host))
_b(doc, f"(B) CPNI delegated to or held by {host}:", bold=True)
_cb(doc, (
"Radio-access network signaling, HLR / HSS / UDM records, "
"per-device location information, and lawful-intercept records "
"are held by the host MNO and are governed by that host MNO's own "
"CPNI certification and safeguards. {entity_name} does NOT have "
"direct access to these data stores."
).replace("{entity_name}", entity_name))
_cb(doc, (
f"The MVNO wholesale agreement between {entity_name} and {host} "
f"expressly requires {host} to protect all CPNI generated through "
f"{entity_name}'s subscribers consistent with 47 CFR "
f"\u00a7\u00a7 64.2001\u201364.2011, to provide breach notice to "
f"{entity_name} within a commercially reasonable time, and to "
f"limit use of such CPNI to the provision of service to "
f"{entity_name} and its subscribers."
))
_cb(doc, (
f"{entity_name} reviews {host}'s annual CPNI certification and "
f"any published breach notices, and maintains a file of the "
f"current executed MVNO agreement."
))
_h(doc, "5. Customer Complaints")
if complaints_count == 0:
_b(doc, (
f"{entity_name} has NOT received any customer complaints during "
f"the reporting period concerning the unauthorized release or "
f"use of CPNI. Zero (0) complaints were logged."
))
else:
desc = complaints_description or "Each complaint was investigated and resolved."
_b(doc, (
f"{entity_name} HAS received {complaints_count} customer "
f"complaint{'s' if complaints_count != 1 else ''} during the "
f"reporting period. {desc}"
))
_h(doc, "6. Data Broker Inquiries and Pretexting")
if not has_data_broker_inquiries:
_b(doc, (
f"{entity_name} has NOT received any inquiries, communications, "
f"or attempts by data brokers or other unauthorized parties "
f"seeking the unauthorized release of CPNI."
))
else:
desc = data_broker_description or "Each was refused, documented, and escalated."
_b(doc, (
f"{entity_name} HAS received data broker or pretexting-style "
f"inquiries during the reporting period. {desc}"
))
_h(doc, "7. Breach Log Summary")
if not breaches:
_b(doc, (
f"{entity_name} experienced no CPNI breaches during the "
f"reporting period. No 47 CFR \u00a7 64.2011 notifications "
f"were required."
))
else:
_b(doc, (
f"{entity_name} experienced {len(breaches)} CPNI breach"
f"{'es' if len(breaches) != 1 else ''} during the reporting "
f"period; each was reported within 7 business days."
))
_h(doc, "8. Penalties, Truthfulness, and Perjury Acknowledgment")
_b(doc, (
f"{entity_name} and the undersigned acknowledge that CPNI rule "
f"violations may subject the carrier to forfeitures up to "
f"{MAX_FORFEITURE_PER_VIOLATION} per violation and up to "
f"{MAX_FORFEITURE_CAP} for any single act or failure to act."
))
_b(doc, (
"Pursuant to 47 CFR \u00a7 1.17, the undersigned represents that no "
"material factual information has been withheld and all statements "
"are truthful, accurate, and complete."
))
_b(doc, (
"Willful false statements are punishable under Title 18, U.S.C. "
"\u00a7 1001, and by forfeiture under 47 U.S.C. \u00a7 503."
))
_h(doc, "9. Signature of Certifying Officer")
_b(doc, (
"I declare under penalty of perjury under the laws of the United "
"States of America that the foregoing is true and correct."
))
p = doc.add_paragraph(); _sp(p, after=0)
sig = doc.add_paragraph(); sig.add_run("_" * 45).font.size = Pt(10); _sp(sig, after=2)
nm = doc.add_paragraph(); nr = nm.add_run(signer); nr.bold = True
nr.font.size = Pt(10); _sp(nm, after=2)
tpp = doc.add_paragraph(); tpp.add_run(f"{title}, {entity_name}").font.size = Pt(10)
_sp(tpp, after=2)
dp = doc.add_paragraph(); dp.add_run(f"Date: {today}").font.size = Pt(10)
_sp(dp, after=2)
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("CPNI Wireless MVNO certification letter generated: %s", out)
return str(out)

View file

@ -0,0 +1,252 @@
"""
Generate the CRTC Registration Notification Letter as a DOCX file.
This produces a formal letter addressed to the Secretary General of the CRTC
notifying them that a new telecommunications service provider has been
established under a BC corporation and wishes to register as a:
- Voice, Data & Wireless Reseller (domestic)
- Basic International Telecommunications Service (BITS) provider (if applicable)
The letter follows the format specified at:
https://crtc.gc.ca/eng/comm/telecom/registr4.htm
Usage:
from scripts.document_gen.templates.crtc_letter_generator import generate_crtc_letter
pdf_path = generate_crtc_letter(
entity_name="1234567 B.C. Ltd.",
incorporation_number="1234567",
registered_office="329 Howe St, Vancouver, BC V6C 3N2",
services_description="Resale of voice, data, and wireless services...",
geographic_coverage="BC and Worldwide",
include_bits=True,
regulatory_contact_name="Regulatory Director",
regulatory_contact_email="regulatory@example.ca",
regulatory_contact_phone="+16045551234",
director_name="John Doe",
output_path="/tmp/crtc_letter.docx",
)
"""
from __future__ import annotations
import logging
import os
from datetime import datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.crtc_letter")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — CRTC letter generation unavailable")
Document = None
def generate_crtc_letter(
entity_name: str,
incorporation_number: str,
registered_office: str,
services_description: str,
geographic_coverage: str = "Canada-wide",
include_bits: bool = True,
regulatory_contact_name: str = "Regulatory Director",
regulatory_contact_email: str = "",
regulatory_contact_phone: str = "",
director_name: str = "",
ca_domain: str = "",
output_path: str = "/tmp/crtc_notification_letter.docx",
) -> Optional[str]:
"""
Generate a CRTC Registration Notification Letter as a DOCX file.
Returns the output file path on success, None on failure.
"""
if Document is None:
LOG.error("python-docx not installed")
return None
doc = Document()
# Page margins
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)
# ── Sender block ──────────────────────────────────────────
today = datetime.now().strftime("%B %d, %Y")
sender = doc.add_paragraph()
sender.alignment = WD_ALIGN_PARAGRAPH.LEFT
sender_run = sender.add_run(
f"{entity_name}\n"
f"Incorporation No. {incorporation_number}\n"
f"{registered_office}\n"
)
sender_run.font.size = Pt(10)
if regulatory_contact_phone:
sender.add_run(f"Tel: {regulatory_contact_phone}\n").font.size = Pt(10)
if regulatory_contact_email:
sender.add_run(f"Email: {regulatory_contact_email}\n").font.size = Pt(10)
if ca_domain:
sender.add_run(f"Web: https://{ca_domain}\n").font.size = Pt(10)
# Date
date_para = doc.add_paragraph()
date_para.alignment = WD_ALIGN_PARAGRAPH.LEFT
date_run = date_para.add_run(today)
date_run.font.size = Pt(10)
# ── Addressee ─────────────────────────────────────────────
doc.add_paragraph()
addressee = doc.add_paragraph()
addressee_run = addressee.add_run(
"Secretary General\n"
"Canadian Radio-television and\n"
"Telecommunications Commission (CRTC)\n"
"Ottawa, Ontario\n"
"K1A 0N2"
)
addressee_run.font.size = Pt(10)
# ── Subject line ──────────────────────────────────────────
doc.add_paragraph()
subject = doc.add_paragraph()
subject_run = subject.add_run(
f"Re: Registration as a Telecommunications Service Provider — {entity_name}"
)
subject_run.font.size = Pt(10)
subject_run.bold = True
# ── Body ──────────────────────────────────────────────────
doc.add_paragraph()
# Introduction
intro = doc.add_paragraph()
intro_run = intro.add_run(
f"Dear Secretary General,\n\n"
f"Pursuant to the Telecommunications Act, S.C. 1993, c. 38, and the "
f"Canadian Radio-television and Telecommunications Commission's registration "
f"requirements for telecommunications service providers, {entity_name} "
f"(Incorporation No. {incorporation_number}) hereby notifies the Commission of its "
f"intention to provide telecommunications services in Canada."
)
intro_run.font.size = Pt(10)
# Company information section
doc.add_paragraph()
info_heading = doc.add_paragraph()
info_heading_run = info_heading.add_run("1. Company Information")
info_heading_run.font.size = Pt(10)
info_heading_run.bold = True
info = doc.add_paragraph()
info.style.font.size = Pt(10)
info_text = (
f"Legal Name: {entity_name}\n"
f"Incorporation Number: {incorporation_number}\n"
f"Mailing Address: {registered_office}\n"
f"Telephone: {regulatory_contact_phone}\n"
f"Email: {regulatory_contact_email}\n"
)
info.add_run(info_text).font.size = Pt(10)
# Services section
doc.add_paragraph()
svc_heading = doc.add_paragraph()
svc_heading_run = svc_heading.add_run("2. Description of Services")
svc_heading_run.font.size = Pt(10)
svc_heading_run.bold = True
svc = doc.add_paragraph()
svc.add_run(
f"{entity_name} intends to operate as a reseller of voice, data, and wireless "
f"telecommunications services. Specifically:\n\n"
f"{services_description}\n\n"
f"Geographic Coverage: {geographic_coverage}"
).font.size = Pt(10)
# Registration type
doc.add_paragraph()
reg_heading = doc.add_paragraph()
reg_heading_run = reg_heading.add_run("3. Registration Category")
reg_heading_run.font.size = Pt(10)
reg_heading_run.bold = True
reg = doc.add_paragraph()
reg_text = f"{entity_name} registers as a Voice, Data & Wireless Reseller."
if include_bits:
reg_text += (
f"\n\n{entity_name} also intends to provide Basic International "
f"Telecommunications Services (BITS) and will file a separate notification "
f"with the Commission pursuant to CRTC Telecom Decision 98-17."
)
reg.add_run(reg_text).font.size = Pt(10)
# Response Manager
doc.add_paragraph()
rm_heading = doc.add_paragraph()
rm_heading_run = rm_heading.add_run("4. Response Manager for Regulatory Matters")
rm_heading_run.font.size = Pt(10)
rm_heading_run.bold = True
rm = doc.add_paragraph()
rm.add_run(
f"Name: {regulatory_contact_name}\n"
f"Title: Regulatory Director\n"
f"Organization: {entity_name}\n"
f"Address: {registered_office}\n"
f"Telephone: {regulatory_contact_phone}\n"
f"Email: {regulatory_contact_email}"
).font.size = Pt(10)
# Compliance commitment
doc.add_paragraph()
compliance_heading = doc.add_paragraph()
compliance_heading_run = compliance_heading.add_run("5. Compliance")
compliance_heading_run.font.size = Pt(10)
compliance_heading_run.bold = True
compliance = doc.add_paragraph()
compliance.add_run(
f"{entity_name} confirms that it will comply with all applicable provisions of "
f"the Telecommunications Act, CRTC regulations, and conditions of service, "
f"including participation in the Commission for Complaints for "
f"Telecom-Television Services (CCTS)."
).font.size = Pt(10)
# Closing
doc.add_paragraph()
doc.add_paragraph()
closing = doc.add_paragraph()
closing.add_run("Respectfully submitted,").font.size = Pt(10)
# Signature block (space for eSign)
doc.add_paragraph()
doc.add_paragraph() # Space for signature
doc.add_paragraph()
sig_line = doc.add_paragraph()
sig_line.add_run("_" * 40).font.size = Pt(10)
sig_name = doc.add_paragraph()
sig_name_run = sig_name.add_run(director_name or regulatory_contact_name)
sig_name_run.font.size = Pt(10)
sig_name_run.bold = True
sig_title = doc.add_paragraph()
sig_title.add_run(f"Director, {entity_name}").font.size = Pt(10)
sig_date = doc.add_paragraph()
sig_date.add_run(f"Date: {today}").font.size = Pt(10)
# Save
output = Path(output_path)
output.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(output))
LOG.info("CRTC letter generated: %s", output)
return str(output)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,427 @@
"""
Generate the 499-A Revenue Calculation Workbook (xlsx).
Companion workbook customers fill in with their monthly/quarterly revenue
splits. The workbook roll-ups feed the actual 499-A Block 3, 4-A, 4-B,
and 5 line items that the Playwright handler pushes into USAC E-File.
Design principles:
* Entirely local formulas live in the workbook, not here. Customers open
it in Excel/Google Sheets, plug in numbers, and the totals flip.
* Jurisdictional splits per 2026 Instructions (section IV.C.5): intrastate
/ interstate / international. Column D/E/F carry the split percentages
so customers can override the VoIP safe harbor if they have a traffic
study.
* Every revenue row maps to a specific Form 499-A line (e.g. Line 404.1,
Line 414, Line 418.4) so the admin can lift values straight into E-File.
Sheets produced:
1. README explains the workbook, filing window, where values feed.
2. Block 3 Carrier's Carrier Revenue (Lines 301-315)
3. Block 4-A End-User & Non-Telecom Revenue (Lines 401-418)
4. Block 4-B Totals & Uncollectibles (Lines 419-423)
5. Block 5 Regional Percentages + TRS + Reseller Exclusions
6. Summary single-page dashboard of all key roll-ups
Usage:
from scripts.document_gen.templates.form_499a_revenue_workbook_generator import (
generate_499a_revenue_workbook,
)
path = generate_499a_revenue_workbook(
entity_name="Falcon Broadband LLC",
filer_id_499="812345",
reporting_year=2025,
voip_safe_harbor_pct=64.9,
output_path="/tmp/499a_workbook.xlsx",
)
"""
from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.499a_workbook")
try:
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter
except ImportError:
LOG.warning("openpyxl not installed — 499-A workbook generation unavailable")
Workbook = None # type: ignore[assignment,misc]
# Style constants
NAVY_FILL = "FF1A2744"
LIGHT_FILL = "FFF8FAFC"
BORDER_THIN = None # set lazily (needs openpyxl)
HEADER_FONT = None
TITLE_FONT = None
def _init_styles():
"""Lazy style init — openpyxl objects can't be module-level if import fails."""
global BORDER_THIN, HEADER_FONT, TITLE_FONT
if BORDER_THIN is None:
side = Side(style="thin", color="FFCBD5E1")
BORDER_THIN = Border(left=side, right=side, top=side, bottom=side)
HEADER_FONT = Font(name="Calibri", size=11, bold=True, color="FFFFFFFF")
TITLE_FONT = Font(name="Calibri", size=14, bold=True, color="FF1A2744")
# Block 3: Carrier's Carrier Revenue (Lines 301-315).
# Each tuple is (line_num, label, is_total_row).
_BLOCK_3_LINES = [
("303.1", "Fixed local — UNEs", False),
("303.2", "Fixed local — other arrangements", False),
("304.1", "Per-minute charges — state/federal access tariff", False),
("304.2", "Per-minute — UNEs or other arrangement", False),
("305.1", "Local private line — for resale as telecom", False),
("305.2", "Local private line — for resale as interconnected VoIP", False),
("306", "Payphone compensation from toll carriers", False),
("307", "Other local telecom service revenues", False),
("308", "Universal service support revenues from Federal/state", False),
("309", "Mobile — monthly/activation/message (non-toll)", False),
("310", "Operator/toll with alternative billing", False),
("311", "Ordinary long distance (direct-dialed MTS, toll-free, etc.)", False),
("312", "Long distance private line services", False),
("313", "Satellite services", False),
("314", "All other long distance services", False),
("315", "TOTAL revenues from resale (sum 303314)", True),
]
# Block 4-A: End-User and Non-Telecom Revenue (Lines 401-418).
_BLOCK_4A_LINES = [
("403", "Surcharges recovering USF contributions", False),
("404.1", "Fixed flat-rate w/ interstate toll — local portion", False),
("404.2", "Fixed flat-rate w/ interstate toll — toll portion", False),
("404.3", "Fixed — no interstate toll included", False),
("404.4", "Interconnected VoIP — with broadband connection", False),
("404.5", "Interconnected VoIP — independent of broadband", False),
("405", "Tariffed SLC / ARC / PICC (LEC no-PIC)", False),
("406", "Local private line & special access (wireline broadband)", False),
("407", "Payphone coin revenues (local + LD)", False),
("408", "Other local telecom service revenues", False),
("409", "Mobile — monthly and activation charges", False),
("410", "Mobile — message / roaming / air-time (excl. separately stated toll)", False),
("411", "Prepaid calling card (at face value)", False),
("412", "International calls — both endpoints foreign", False),
("413", "Operator/toll with alternative billing (non-412)", False),
("414.1", "Ordinary LD — non-VoIP", False),
("414.2", "Ordinary LD — interconnected VoIP", False),
("415", "Long distance private line services", False),
("416", "Satellite services", False),
("417", "All other long distance services", False),
("418.1", "Bundled — with circuit-switched local", False),
("418.2", "Bundled — with interconnected VoIP local", False),
("418.3", "Other bundled / non-telecom", False),
("418.4", "Non-interconnected VoIP (not in other categories)", False),
]
# Block 4-B: Total / uncollectible (Lines 419-423).
_BLOCK_4B_LINES = [
("419", "Gross billed revenues from all sources", False),
("420", "Gross universal service contribution base", False),
("421", "Uncollectible associated with Line 419", False),
("422", "Uncollectible associated with Line 420", False),
("423", "Net universal service contribution base (420 422)", True),
]
# Block 5 regional breakout rows (Lines 503-510).
_BLOCK_5_REGIONS = [
("503", "Southeast: AL, FL, GA, KY, LA, MS, NC, PR, SC, TN, USVI"),
("504", "Western: AK, AZ, CO, ID, IA, MN, MT, NE, NM, ND, OR, SD, UT, WA, WY"),
("505", "West Coast: CA, HI, NV, AS, GU, Johnston, Midway, MP, Wake"),
("506", "Mid-Atlantic: DE, DC, MD, NJ, PA, VA, WV"),
("507", "Mid-West: IL, IN, MI, OH, WI"),
("508", "Northeast: CT, ME, MA, NH, NY, RI, VT"),
("509", "Southwest: AR, KS, MO, OK, TX"),
("510", "TOTAL (must sum to 100%)"),
]
def _set_header_row(ws, row: int, headers: list[str]) -> None:
_init_styles()
navy = PatternFill(start_color=NAVY_FILL, end_color=NAVY_FILL, fill_type="solid")
for col, header in enumerate(headers, start=1):
cell = ws.cell(row=row, column=col, value=header)
cell.font = HEADER_FONT
cell.fill = navy
cell.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
cell.border = BORDER_THIN
def _write_revenue_block(
ws,
*,
title: str,
lines: list[tuple[str, str, bool]],
start_row: int = 1,
) -> int:
"""Write a Block 3 / 4-A / 4-B style sheet. Returns next free row."""
_init_styles()
ws.cell(row=start_row, column=1, value=title).font = TITLE_FONT
row = start_row + 2
_set_header_row(ws, row, [
"Line",
"Description",
"(a) Total Revenue",
"(b) Interstate %",
"(c) International %",
"(d) Interstate $",
"(e) International $",
])
row += 1
total_row_idx = None
for line_num, label, is_total in lines:
if is_total:
total_row_idx = row
ws.cell(row=row, column=1, value=line_num).font = Font(bold=True)
ws.cell(row=row, column=2, value=label).font = Font(bold=True)
# TOTAL formula
data_range = f"C{row - len(lines) + 1}:C{row - 1}"
ws.cell(row=row, column=3, value=f"=SUM({data_range})").font = Font(bold=True)
ws.cell(row=row, column=6, value=f"=SUM(F{row - len(lines) + 1}:F{row - 1})").font = Font(bold=True)
ws.cell(row=row, column=7, value=f"=SUM(G{row - len(lines) + 1}:G{row - 1})").font = Font(bold=True)
else:
ws.cell(row=row, column=1, value=line_num)
ws.cell(row=row, column=2, value=label)
# Column C is the total revenue input (customer fills).
# Columns D/E percentages feed formulas in F/G.
ws.cell(row=row, column=6, value=f"=C{row}*D{row}/100")
ws.cell(row=row, column=7, value=f"=C{row}*E{row}/100")
for col in range(1, 8):
ws.cell(row=row, column=col).border = BORDER_THIN
# Currency formatting
for col in (3, 6, 7):
ws.cell(row=row, column=col).number_format = '"$"#,##0.00'
# Percentage columns
for col in (4, 5):
ws.cell(row=row, column=col).number_format = '0.00"%"'
row += 1
# Column widths
ws.column_dimensions["A"].width = 10
ws.column_dimensions["B"].width = 55
for col_letter in ("C", "D", "E", "F", "G"):
ws.column_dimensions[col_letter].width = 16
return row + 1
def generate_499a_revenue_workbook(
# Entity
entity_name: str,
filer_id_499: str = "",
frn: str = "",
# Reporting period
reporting_year: int = 0,
# VoIP safe harbor (populated in README)
voip_safe_harbor_pct: float = 64.9,
# Pre-fill: optional traffic study row from cdr_traffic_studies.
# When provided, interstate / international percentages on each
# revenue line pre-populate from the study, saving the customer
# from typing them in — reviewer still validates before filing.
traffic_study: Optional[dict] = None,
# Output
output_path: str = "/tmp/form_499a_revenue_workbook.xlsx",
) -> Optional[str]:
"""Produce the 499-A revenue calculation workbook.
When ``traffic_study`` is passed (a row from ``cdr_traffic_studies``),
the workbook pre-fills interstate/international % cells across the
revenue blocks using the study's computed values. Block 5 regional
rows pre-fill with BOTH the orig-state and billing-state percentages
so the admin chooses at submission time.
"""
if Workbook is None:
LOG.error("openpyxl not installed")
return None
_init_styles()
if reporting_year == 0:
reporting_year = datetime.now().year - 1
interstate_pct_prefill = (traffic_study or {}).get("interstate_pct")
international_pct_prefill = (traffic_study or {}).get("international_pct")
orig_regions = (traffic_study or {}).get("orig_state_regions_json") or {}
billing_regions = (traffic_study or {}).get("billing_state_regions_json") or {}
wb = Workbook()
# Kill the default sheet
default = wb.active
wb.remove(default)
# ── README sheet ────────────────────────────────────────────────
ws = wb.create_sheet("README")
ws.cell(row=1, column=1, value=f"2026 FCC Form 499-A Revenue Calculation Workbook").font = TITLE_FONT
ws.cell(row=2, column=1, value=f"Reporting calendar year {reporting_year}").font = Font(italic=True)
ws.cell(row=3, column=1, value=f"Filer: {entity_name} | Filer 499 ID: {filer_id_499 or '(pending)'} | FRN: {frn or '(pending)'}")
readme = [
"",
"How to use this workbook:",
" 1. Open each Block sheet (Block 3, Block 4-A, Block 4-B, Block 5).",
" 2. In column C (\u201cTotal Revenue\u201d), enter each Line item's gross billed revenue for the year.",
" 3. In columns D and E, enter the interstate % and international % for each line.",
" If you are an interconnected VoIP provider and have not conducted a traffic study, you may",
f" use the 2026 VoIP safe harbor of {voip_safe_harbor_pct}% for lines 404.4 / 404.5 / 414.2.",
" 4. Columns F and G calculate automatically. Block 4-B pulls totals from Block 4-A.",
" 5. The Summary sheet gives a one-page view of everything that feeds the filing.",
"",
"Important:",
" \u2022 Report dollar amounts in whole dollars (round >$1000 to nearest thousand per Section G).",
" \u2022 Do NOT enter negative numbers on any billed revenue line (see Lines 421/422 for uncollectibles).",
" \u2022 The 2026 Form 499-A (reporting 2025 revenues) is due April 1, 2026.",
" \u2022 E-File opens March 2, 2026. File online at https://forms.universalservice.org.",
"",
"Block assignments (2025/2026 form — structure unchanged):",
" \u2022 Block 3 = Carrier's Carrier Revenue (Lines 301\u2013315)",
" \u2022 Block 4-A = End-User and Non-Telecom Revenue (Lines 401\u2013418)",
" \u2022 Block 4-B = Total Revenue + Uncollectibles (Lines 419\u2013423)",
" \u2022 Block 5 = Regional Percentage Breakouts + TRS contribution base + Reseller Exclusions",
"",
"Questions: contact support@performancewest.net or 888-411-0383.",
]
for i, line in enumerate(readme, start=4):
ws.cell(row=i, column=1, value=line)
ws.column_dimensions["A"].width = 110
# ── Block 3 ─────────────────────────────────────────────────────
ws3 = wb.create_sheet("Block 3")
_write_revenue_block(
ws3,
title=f"Block 3 — Carrier's Carrier Revenue (Reporting {reporting_year})",
lines=_BLOCK_3_LINES,
)
# ── Block 4-A ───────────────────────────────────────────────────
ws4a = wb.create_sheet("Block 4-A")
_write_revenue_block(
ws4a,
title=f"Block 4-A — End-User and Non-Telecom Revenue (Reporting {reporting_year})",
lines=_BLOCK_4A_LINES,
)
# ── Block 4-B ───────────────────────────────────────────────────
ws4b = wb.create_sheet("Block 4-B")
ws4b.cell(row=1, column=1, value="Block 4-B — Total Revenue and Uncollectible Revenue").font = TITLE_FONT
_set_header_row(ws4b, 3, ["Line", "Description", "Total Revenue", "Interstate", "International"])
# Line 419 pulls from Block 3 Line 315 + Block 4-A total
ws4b.cell(row=4, column=1, value="419")
ws4b.cell(row=4, column=2, value="Gross billed revenues from all sources")
ws4b.cell(row=4, column=3, value="='Block 3'!C" + str(3 + len(_BLOCK_3_LINES) + 1) + "+'Block 4-A'!C" + str(3 + len(_BLOCK_4A_LINES) + 1))
# Line 420 — contribution base (lines 403-411 + 413-417 end-user)
ws4b.cell(row=5, column=1, value="420")
ws4b.cell(row=5, column=2, value="Gross USF contribution base amounts (fill manually; see Table 3 in 2026 instructions)")
# Line 421
ws4b.cell(row=6, column=1, value="421")
ws4b.cell(row=6, column=2, value="Uncollectible associated with Line 419")
# Line 422
ws4b.cell(row=7, column=1, value="422")
ws4b.cell(row=7, column=2, value="Uncollectible associated with Line 420")
# Line 423
ws4b.cell(row=8, column=1, value="423").font = Font(bold=True)
ws4b.cell(row=8, column=2, value="Net USF contribution base (420 422)").font = Font(bold=True)
ws4b.cell(row=8, column=3, value="=C5-C7").font = Font(bold=True)
for row_idx in range(3, 9):
for col in range(1, 6):
ws4b.cell(row=row_idx, column=col).border = BORDER_THIN
ws4b.cell(row=row_idx, column=3).number_format = '"$"#,##0.00'
ws4b.column_dimensions["A"].width = 10
ws4b.column_dimensions["B"].width = 55
ws4b.column_dimensions["C"].width = 18
# ── Block 5 ─────────────────────────────────────────────────────
ws5 = wb.create_sheet("Block 5")
title_suffix = (
" (pre-filled from traffic study — pick orig-state OR billing-state at submission)"
if traffic_study else ""
)
ws5.cell(row=1, column=1,
value=f"Block 5 — Regional Percentage Breakouts + TRS Contribution Base{title_suffix}").font = TITLE_FONT
_set_header_row(ws5, 3, [
"Line", "Region",
"Block 3 (Carrier) %",
"Block 4 (End-User) %",
"Pre-fill: by Orig State %",
"Pre-fill: by Billing State %",
])
for i, (line_num, label) in enumerate(_BLOCK_5_REGIONS, start=4):
ws5.cell(row=i, column=1, value=line_num)
ws5.cell(row=i, column=2, value=label)
is_total = line_num == "510"
if is_total:
ws5.cell(row=i, column=3, value=f"=SUM(C{4}:C{i-1})").font = Font(bold=True)
ws5.cell(row=i, column=4, value=f"=SUM(D{4}:D{i-1})").font = Font(bold=True)
else:
# Pre-fill columns 5 + 6 from the traffic study when available.
# Admin reviewer picks one of them at filing time and copies
# the value into columns C/D for the official submission.
region_key = label.split(":", 1)[0].strip() if ":" in label else label
orig_v = orig_regions.get(region_key)
bill_v = billing_regions.get(region_key)
if orig_v is not None:
ws5.cell(row=i, column=5, value=float(orig_v))
if bill_v is not None:
ws5.cell(row=i, column=6, value=float(bill_v))
# Format all %
for col in (3, 4, 5, 6):
ws5.cell(row=i, column=col).number_format = '0.00"%"'
ws5.cell(row=i, column=col).border = BORDER_THIN
for col in (1, 2):
ws5.cell(row=i, column=col).border = BORDER_THIN
# Line 511 — reseller exclusions
row_offset = 4 + len(_BLOCK_5_REGIONS) + 1
ws5.cell(row=row_offset, column=2, value="Line 511 — Revenues from resellers that do not contribute to USF (included in Block 4-B Line 420 but excluded from TRS/NANPA/LNP/FCC regulatory fee bases)").font = Font(italic=True)
_set_header_row(ws5, row_offset + 1, ["", "Reseller Filer 499 ID", "(a) Total Revenue", "(b) Interstate/Int'l"])
for r in range(row_offset + 2, row_offset + 7):
for col in range(1, 5):
ws5.cell(row=r, column=col).border = BORDER_THIN
ws5.cell(row=r, column=3).number_format = '"$"#,##0.00'
ws5.cell(row=r, column=4).number_format = '"$"#,##0.00'
ws5.column_dimensions["A"].width = 10
ws5.column_dimensions["B"].width = 70
ws5.column_dimensions["C"].width = 20
ws5.column_dimensions["D"].width = 22
# ── Summary ─────────────────────────────────────────────────────
wss = wb.create_sheet("Summary")
wss.cell(row=1, column=1, value="Summary — what feeds into USAC E-File").font = TITLE_FONT
summary_rows = [
("Block 3 Line 315 — Total revenues from resale", "='Block 3'!C" + str(3 + len(_BLOCK_3_LINES) + 1)),
("Block 4-A total — End-user + non-telecom", "='Block 4-A'!C" + str(3 + len(_BLOCK_4A_LINES) + 1)),
("Block 4-B Line 419 — Gross billed revenues", "='Block 4-B'!C4"),
("Block 4-B Line 420 — USF contribution base", "='Block 4-B'!C5"),
("Block 4-B Line 423 — Net USF contribution base", "='Block 4-B'!C8"),
("Block 5 Line 510 — Regional total (must be 100%)", "='Block 5'!C" + str(4 + len(_BLOCK_5_REGIONS) - 1)),
]
for i, (label, formula) in enumerate(summary_rows, start=3):
wss.cell(row=i, column=1, value=label)
cell = wss.cell(row=i, column=2, value=formula)
if "100%" in label or "Line 510" in label:
cell.number_format = '0.00"%"'
else:
cell.number_format = '"$"#,##0.00'
for col in (1, 2):
wss.cell(row=i, column=col).border = BORDER_THIN
wss.column_dimensions["A"].width = 55
wss.column_dimensions["B"].width = 22
# Reorder tabs: README first, Summary last
order = ["README", "Block 3", "Block 4-A", "Block 4-B", "Block 5", "Summary"]
wb._sheets = [wb[name] for name in order if name in wb.sheetnames]
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
wb.save(str(out))
LOG.info("499-A revenue workbook generated: %s", out)
return str(out)

View file

@ -0,0 +1,146 @@
# Do-Not-Originate (DNO) List Enforcement Guide
## Implementation Handbook for Voice Service Providers
**Prepared by Performance West Inc.**
**Effective Date: 2026**
---
## 1. What Is the DNO List?
The FCC Do-Not-Originate (DNO) list is a database of telephone numbers that should **never** appear as the calling party number on the public switched telephone network (PSTN). These numbers are known to be used for illegal robocalling, spoofing, or fraud.
The DNO list is maintained by the **Industry Traceback Group (ITG)**, operated by USTelecom — the Broadband Association, and is distributed to voice service providers and gateway providers for enforcement.
**Regulatory basis:** 47 CFR § 64.6305 (2025 RMD Report & Order, effective February 5, 2026)
---
## 2. Who Must Enforce the DNO List?
All providers who file in the FCC Robocall Mitigation Database:
- **Voice Service Providers** (originating carriers)
- **Gateway Providers** (receiving international traffic)
- **Intermediate Providers** (transit/tandem carriers)
If you have an RMD filing, you are expected to enforce the DNO list.
---
## 3. Implementation Steps
### Step 1: Obtain the DNO List
**Check with your switch/platform provider first.** Many VoIP platforms, hosted PBX providers, and wholesale carriers already include DNO list enforcement as part of their service at no extra cost. If your provider handles this for you, confirm it in writing and reference it in your RMD filing — you may not need to manage the list yourself.
**If your platform does NOT include DNO enforcement,** you must obtain the DNO registry directly:
- **DNO Registry:** https://tracebacks.org/dno-registry/
- This is the official source operated by USTelecom's Industry Traceback Group (ITG)
- The registry provides a downloadable list of numbers that must be blocked
- Register for access and download the current list
- Updates are published regularly — check the registry for the current update schedule
**Other sources that may include DNO enforcement:**
- Call analytics vendors (TransNexus, Neustar, Hiya) often include DNO blocking in their platforms
- Your upstream carrier may already block DNO-listed numbers before they reach your network
### Step 2: Integrate into Your Call Routing
**For SIP/VoIP infrastructure:**
```
# Example: SIP proxy rule (Kamailio/OpenSIPS/FreeSWITCH concept)
# Block calls where the FROM or P-Asserted-Identity matches a DNO number
if (is_in_dno_list($fU)) {
sl_send_reply("603", "Decline - DNO Listed Number");
exit;
}
```
**Implementation options by platform:**
| Platform | Method |
|---|---|
| FreeSWITCH | Load DNO list into mod_blacklist or use a Lua/Python script in dialplan |
| Kamailio | Hash table lookup in route block, loaded from DB or file |
| Asterisk | Use a database-backed dialplan function (ODBC or AstDB) |
| Metaswitch | Policy rule in call control configuration |
| BroadSoft/Cisco BroadWorks | System-level origination blocking rule |
| Cloud UCaaS | Contact your UCaaS vendor — they should enforce DNO on your behalf |
### Step 3: Apply to All Call Origination Points
The DNO check must be applied at **every point where calls enter your network**:
1. **Customer-facing SIP trunks** — check the calling number before routing
2. **Gateway interfaces** — check foreign-originated traffic at ingress
3. **Wholesale interconnections** — check traffic received from downstream carriers
4. **SIP registration** — optionally prevent registration of DNO-listed numbers as extensions
### Step 4: Establish an Update Schedule
| Frequency | Action |
|---|---|
| **Daily** (recommended) | Download latest DNO list, update blocking rules |
| **Immediately** | If you receive a traceback request identifying a DNO number you're originating, block within 4 hours |
| **Monthly** | Audit your blocking logs to confirm DNO enforcement is working |
### Step 5: Log and Report
Maintain logs of:
- DNO list version/date loaded
- Number of calls blocked per day due to DNO match
- Any exceptions or overrides (there should be none for DNO numbers)
- Date and time of each list update
These logs demonstrate compliance if the FCC or ITG requests evidence of enforcement.
---
## 4. What to Do If a Customer Complains
If a legitimate customer reports their number is being blocked:
1. Verify the number against the current DNO list
2. If the number IS on the DNO list, the customer must contact the ITG to request removal
3. Do NOT create exceptions to bypass DNO blocking — this violates your RMD certification
4. Document the complaint and your response
---
## 5. Documenting DNO Enforcement in Your RMD Filing
Your RMD certification and/or robocall mitigation plan (Exhibit A) should include language such as:
> "[Company Name] immediately blocks any numbers identified on the FCC Do-Not-Originate (DNO) list. DNO list updates are applied daily to prevent origination of calls from numbers known to be used for illegal robocalling. Blocking is enforced at all network ingress points including customer SIP trunks, gateway interfaces, and wholesale interconnections."
---
## 6. Common Mistakes to Avoid
| Mistake | Consequence |
|---|---|
| Not mentioning DNO in your RMD filing | Filing flagged as deficient |
| Updating the list monthly instead of daily | Stale data allows blocked numbers through |
| Only blocking on one trunk, not all ingress | Partial enforcement = non-compliance |
| Creating manual exceptions for "known good" customers | Undermines the entire program |
| Not logging blocked calls | Cannot demonstrate compliance to FCC/ITG |
---
## 7. Resources
- **Industry Traceback Group:** https://tracebacks.org
- **USTelecom:** https://www.ustelecom.org
- **FCC RMD Portal:** https://apps.fcc.gov/rmd/
- **47 CFR § 64.6305:** https://www.ecfr.gov/current/title-47/chapter-I/subchapter-B/part-64/subpart-CC
- **2025 RMD Report & Order:** FCC 25-6 (effective February 5, 2026)
---
*This guide is provided for informational purposes as part of your RMD filing service. It is not legal advice. Consult with your regulatory counsel for implementation decisions specific to your network.*
*Performance West Inc. — performancewest.net — 1-888-411-0383*

View file

@ -0,0 +1,184 @@
# Know Your Customer (KYC) Procedures Guide
## Implementation Handbook for Voice Service Providers
**Prepared by Performance West Inc.**
**Effective Date: 2026**
---
## 1. What Are KYC Procedures Under the RMD?
The FCC's 2025 RMD Report & Order requires all voice service providers to implement **Know Your Customer (KYC) procedures** as part of their robocall mitigation program. KYC is the process of verifying the identity and legitimacy of customers before providing them with voice service — and monitoring them on an ongoing basis.
**Regulatory basis:** 47 CFR § 64.1200(n)(4), reinforced by the 2025 RMD Report & Order (FCC 25-6)
---
## 2. Required KYC Elements
Your KYC program must include:
### A. Information Collection at Signup
Collect the following from every new customer before activating service:
| Required Information | Purpose |
|---|---|
| Full legal name (individual or entity) | Identity verification |
| Physical business address (no P.O. boxes for high-volume/toll-free) | Location verification |
| Business identification (EIN/tax ID, or last 4 SSN for individuals) | Tax identity confirmation |
| Government-issued photo ID | Identity authentication |
| Business website or description of legitimate business purpose | Legitimacy assessment |
| Contact phone and email | Communication channel |
### B. Verification Steps
For each new customer, perform these checks:
1. **Cross-reference business name + EIN** against your state's business registry or IRS database
2. **Verify address** via USPS Address Verification or a third-party source (LexisNexis, Dun & Bradstreet)
3. **Authenticate photo ID** — confirm it is genuine, not expired, and the name matches (see recommended tool below)
4. **Open-source search** — search the customer name and principals for:
- Prior association with illegal robocalling
- Inclusion on the ITG's known bad-actor traceback list
- FCC enforcement actions or complaints
- Spoofing or fraud complaints
#### Recommended: Stripe Identity for ID Verification
For automated, reliable identity verification, we recommend **Stripe Identity** (https://stripe.com/identity). It provides:
- **Government-issued ID document verification** — authenticates the ID is real, not expired, and not tampered with
- **Selfie matching with liveness detection** — confirms the person holding the ID is the person on it
- **SSN-based ID number lookup** (US only) — cross-references against authoritative databases
**Pricing:**
- **First 50 verifications: FREE** (included with any Stripe account)
- **$1.50 per verification** after the free tier
- **Volume discounts** available for 2,000+ verifications/month (contact Stripe)
This is significantly cheaper than traditional KYC vendors and integrates directly into your customer onboarding flow via API or hosted verification page. Most small-to-mid carriers will stay within the free tier (50 new customers per billing cycle). At $1.50 each after that, verifying 100 customers costs just $75.
**Integration:** Stripe Identity can be embedded as a link in your customer signup form — the customer clicks a link, takes a photo of their ID and a selfie, and Stripe returns a pass/fail result to your system within seconds. No manual review needed for passing verifications.
### C. Red-Flag Review
Trigger enhanced due diligence when any of the following occur:
- 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
- Usage patterns inconsistent with stated business purpose
- Prior complaints, tracebacks, or enforcement actions linked to the customer
- Request for unusually high call volumes relative to stated business size
### D. Ongoing Monitoring
- **Annual re-vetting** for all customers (minimum)
- **Immediate re-review** upon complaints, traceback requests, or anomalous traffic patterns
- **High-volume/toll-free customers:** quarterly review
---
## 3. Implementation Steps
### Step 1: Create Your KYC Intake Form
Build a customer onboarding form (paper or digital) that collects all required fields. Store responses in your CRM or customer database.
**Recommended fields:**
```
- Legal entity name
- DBA / trade name
- Entity type (LLC, Corp, Sole Prop, etc.)
- EIN or Tax ID
- State of formation
- Physical address (street, city, state, zip)
- Mailing address (if different)
- Primary contact name, title, phone, email
- Government-issued ID (upload or in-person)
- Business website URL
- Description of intended use of voice services
- Expected monthly call volume
- Authorized signatory for service agreement
```
### Step 2: Build Your Verification Checklist
For each new customer, a team member should complete:
- [ ] Business name verified against state registry
- [ ] EIN verified (IRS EIN verification letter or cross-reference)
- [ ] Address validated via USPS or third-party
- [ ] Photo ID reviewed and authenticated
- [ ] Web search completed for bad-actor associations
- [ ] ITG traceback list checked (if available)
- [ ] FCC ECFS searched for complaints against this entity
- [ ] No red flags identified (or enhanced due diligence completed)
- [ ] Acceptable Use Policy signed by customer
- [ ] Service activated
### Step 3: Acceptable Use Policy
Every customer must sign an Acceptable Use Policy (AUP) that includes:
- Prohibition of illegal robocalling, spoofing, and fraud
- Prohibition of originating calls to/from DNO-listed numbers
- Agreement to cooperate with traceback requests
- Right to immediately suspend service for violations
- Requirement to notify you of changes to business information
### Step 4: Set Up Ongoing Monitoring
Configure your systems to flag:
- Customers exceeding their stated call volume by 2x or more
- Sudden spikes in short-duration calls (potential robocall signature)
- High Answer-Seizure Ratio (ASR) anomalies
- Complaints received from downstream carriers or end users
- Traceback requests from ITG or law enforcement
### Step 5: Document Your Process
Write an internal SOP document covering:
- Who performs KYC reviews (role/title)
- How records are stored and for how long
- What triggers enhanced due diligence
- How to handle customer refusals
- Escalation procedures for red-flag findings
---
## 4. Documenting KYC in Your RMD Filing
Your RMD certification (Exhibit A) should include:
> "[Company Name] conducts internal Know Your Customer (KYC) procedures for all customers. At account signup or upon any material change in service usage, we require and collect: full legal name, physical business address, business identification (EIN or tax ID), government-issued photo ID, and a description of legitimate business purpose. We cross-reference business information against state registries, validate addresses via USPS, verify photo ID authenticity, and conduct open-source searches for prior robocalling associations. Enhanced due diligence is triggered when red flags are identified."
---
## 5. Common Mistakes to Avoid
| Mistake | Consequence |
|---|---|
| No KYC section in RMD filing | Filing flagged as deficient under 2026 requirements |
| Collecting info but not verifying it | Non-compliance — verification is the key requirement |
| No ongoing monitoring after signup | Fails the "continuous compliance" standard |
| No AUP or terms of service | Cannot enforce against abusive customers |
| Storing KYC data without security measures | Potential data breach liability |
---
## 6. Resources
- **FCC 47 CFR § 64.1200(n)(4):** KYC requirements for voice service providers
- **ITG (Industry Traceback Group):** https://tracebacks.org
- **FCC ECFS (complaints search):** https://www.fcc.gov/ecfs/
- **USPS Address Verification:** https://tools.usps.com/zip-code-lookup.htm
- **IRS EIN Verification:** https://www.irs.gov/businesses/small-businesses-self-employed/employer-id-numbers
---
*This guide is provided for informational purposes as part of your RMD filing service. It is not legal advice.*
*Performance West Inc. — performancewest.net — 1-888-411-0383*

View file

@ -0,0 +1,139 @@
# Material Change Update Procedures Guide
## Implementation Handbook for Voice Service Providers
**Prepared by Performance West Inc.**
**Effective Date: 2026**
---
## 1. What Is the Material Change Requirement?
Under the FCC's 2025 RMD Report & Order (effective February 5, 2026), all providers with an RMD filing must update their certification within **10 business days** of any material change to their operations, ownership, or filing information.
Failure to update within 10 business days can result in a **$1,000 per day forfeiture**.
**Regulatory basis:** 47 CFR § 64.6305, 2025 RMD Report & Order (FCC 25-6)
---
## 2. What Counts as a Material Change?
| Category | Examples |
|---|---|
| **Ownership** | Change in controlling interest, merger, acquisition, new parent company |
| **Corporate identity** | Legal name change, DBA change, new EIN |
| **Contact information** | New robocall mitigation contact person, email, phone, address |
| **STIR/SHAKEN status** | Change from partial to full implementation, switch to a different STI-CA, loss of SPC token |
| **Provider classification** | Adding gateway operations, ceasing to be a VSP, becoming an intermediate provider |
| **Upstream provider** | Changing the upstream carrier that provides STIR/SHAKEN signing |
| **Robocall mitigation program** | Significant changes to KYC procedures, analytics vendors, blocking policies |
| **Trade names / DBAs** | Adding or removing names under which you operate |
---
## 3. Implementation Steps
### Step 1: Designate a Compliance Officer
Assign one person (and a backup) as the **RMD Compliance Officer** responsible for:
- Monitoring for material changes
- Initiating the update process within 10 business days
- Maintaining an audit trail of updates
**Recommended:** The same person who is listed as the RMD contact on your filing.
### Step 2: Create a Material Change Checklist
Post this checklist where operations, legal, and management teams can see it:
**When ANY of the following occur, notify the RMD Compliance Officer immediately:**
- [ ] Company name or DBA changed
- [ ] Ownership or controlling interest changed
- [ ] New parent company, merger, or acquisition
- [ ] RMD contact person changed (name, email, phone)
- [ ] Principal office address changed
- [ ] STIR/SHAKEN certificate authority changed
- [ ] SPC token renewed, revoked, or transferred
- [ ] Upstream provider changed
- [ ] Provider type changed (added/removed VSP/gateway/intermediate)
- [ ] Robocall mitigation program materially revised
- [ ] New analytics vendor deployed or existing vendor discontinued
- [ ] Trade names added or removed
### Step 3: Establish an Internal Notification Process
Create a simple workflow:
```
Change occurs (e.g., new upstream provider signed)
Department head notifies RMD Compliance Officer (email/ticket)
<20><><EFBFBD>
Compliance Officer logs the change in the tracking spreadsheet
Within 5 business days: prepare updated RMD filing content
Within 10 business days: submit update to FCC RMD portal
Confirm update accepted, save confirmation screenshot
```
### Step 4: Update the RMD Portal
To submit an update:
1. Log in to the FCC RMD portal at https://apps.fcc.gov/rmd/ (MFA required since Feb 5, 2026)
2. Navigate to your existing certification
3. Click "Update" or "Edit"
4. Modify the relevant fields
5. Re-upload your certification letter/Exhibit A if the mitigation plan changed
6. Submit and save the confirmation page
**Or:** Contact Performance West — we can submit the update on your behalf as your authorized filing agent.
### Step 5: Maintain an Audit Trail
Keep a log of all material changes and RMD updates:
| Date | Change Description | Notified By | Updated in RMD | Confirmation # |
|---|---|---|---|---|
| 2026-03-15 | New upstream provider (ABC Telecom) | VP Engineering | 2026-03-18 | RMD-UPD-12345 |
| 2026-04-01 | Contact email changed to new@company.com | HR | 2026-04-03 | RMD-UPD-12346 |
---
## 4. Documenting Material Change Procedures in Your RMD Filing
Your RMD certification should include:
> "[Company Name] updates its RMD certification and CORES registration within 10 business days of any material change, including but not limited to changes in ownership, contacts, STIR/SHAKEN posture, upstream provider, or trade names, per 47 CFR § 64.6305. A designated compliance officer monitors for material changes and maintains an audit trail of all updates."
---
## 5. Penalties for Non-Compliance
| Violation | Penalty |
|---|---|
| Failure to update within 10 business days | $1,000/day forfeiture |
| False or inaccurate information in filing | $10,000 base forfeiture |
| Failure to maintain compliant certification | Removal from RMD (downstream carriers must block your traffic within 30 days) |
---
## 6. Common Mistakes to Avoid
| Mistake | Consequence |
|---|---|
| No material change language in RMD filing | Filing flagged as deficient |
| Updating only annually during recertification | Misses the 10-day requirement for mid-year changes |
| No internal notification process | Changes happen without anyone updating the RMD |
| Updating the filing but not the Exhibit A | Inconsistency between certification and plan |
| No audit trail | Cannot demonstrate timely compliance if audited |
---
*This guide is provided for informational purposes as part of your RMD filing service. It is not legal advice.*
*Performance West Inc. — performancewest.net — 1-888-411-0383*

View file

@ -0,0 +1,137 @@
# Traceback Response Procedures Guide
## Implementation Handbook for Voice Service Providers
**Prepared by Performance West Inc.**
**Effective Date: 2026**
---
## 1. What Is a Traceback Request?
A traceback is the process of identifying the originating source of an illegal robocall by tracing the call path backward through the network — from the terminating carrier, through intermediate/transit providers, back to the originating carrier and ultimately the customer who placed the call.
Traceback requests are issued by:
- **Industry Traceback Group (ITG)** — operated by USTelecom
- **FCC Enforcement Bureau**
- **State attorneys general**
- **Federal and state law enforcement**
**Your obligation:** Respond fully and completely within **24 hours**.
**Regulatory basis:** 47 CFR § 64.6305(d)(2)(iii), (e)(2)(iii), (f)(2)(iii)
---
## 2. Implementation Steps
### Step 1: Designate a 24/7 Traceback Contact
You MUST have someone available to respond to traceback requests within 24 hours, including weekends and holidays.
**Recommended structure:**
- **Primary contact:** Your RMD compliance officer or NOC manager
- **Backup contact:** A second person with access to CDR systems
- **Email alias:** Create a dedicated email like traceback@yourcompany.com that forwards to both
- **Phone:** A direct line or on-call number (not a general IVR)
Register your traceback contact with the ITG at https://tracebacks.org
### Step 2: Ensure CDR Access
Your traceback contact must be able to:
- Search Call Detail Records (CDRs) by called number, calling number, and date/time
- Identify which customer or trunk group originated a specific call
- Export relevant CDR data for the requesting party
- Access records going back at least 18 months
**Systems to prepare:**
- CDR database or data warehouse with search capability
- SIP/SS7 log access (if available)
- Customer account lookup by trunk/SIP registration
### Step 3: Create a Traceback Response Template
When you receive a traceback request, respond with:
```
TRACEBACK RESPONSE
Date: [today]
Request Reference: [ITG/FCC reference number]
Responding Provider: [Your company name]
FRN: [Your FRN]
Contact: [Name, email, phone]
CALL DETAILS REQUESTED:
Called Number: [number from request]
Calling Number: [number from request]
Date/Time: [from request]
FINDINGS:
Call found in our records: YES / NO
Originating customer/trunk: [customer name or trunk ID]
Customer account number: [if applicable]
Upstream source (if transit): [provider name, trunk ID]
CDR excerpt attached: YES / NO
ACTION TAKEN:
[e.g., "Customer notified of violation", "Traffic blocked",
"Account suspended pending investigation", "Referred to upstream provider"]
Signed: [Name, Title]
```
### Step 4: Establish Response SLA
| Timeline | Action |
|---|---|
| **01 hour** | Acknowledge receipt of traceback request |
| **14 hours** | Search CDRs, identify the source |
| **412 hours** | Prepare response with CDR evidence |
| **Within 24 hours** | Send complete response to the requesting party |
| **Immediately** | If the source is a known bad actor, block the traffic |
### Step 5: Take Enforcement Action
After identifying the source:
1. **Notify the customer** that they are the subject of a traceback
2. **Review the customer's account** for patterns of abuse
3. **If abuse is confirmed:** suspend or terminate service per your AUP
4. **If the call was transit traffic:** forward the traceback to your upstream provider
5. **Document everything** — enforcement actions, customer communications, blocking orders
---
## 3. Documenting Traceback Procedures in Your RMD Filing
Your RMD certification should include:
> "[Company Name] commits to respond fully and completely to all traceback requests from the Commission, civil and criminal law enforcement, and the industry traceback consortium, and to do so within 24 hours of receipt. [Company Name] cooperates with the Industry Traceback Group operated by USTelecom and provides requested call detail records and tracing information necessary to identify the origin of suspected illegal robocalls."
---
## 4. What Happens If You Don't Respond
| Failure | Consequence |
|---|---|
| No response within 24 hours | Reported to FCC as non-responsive provider |
| Pattern of non-response | FCC enforcement action, potential RMD removal |
| RMD removal | Downstream carriers must block your traffic within 30 days |
---
## 5. Common Mistakes to Avoid
| Mistake | Consequence |
|---|---|
| No 24/7 contact registered with ITG | Traceback requests go unanswered |
| CDRs not retained long enough | Cannot trace historical calls |
| Responding to ITG but not taking action against the customer | FCC views this as insufficient mitigation |
| No traceback language in RMD filing | Filing flagged as deficient |
---
*This guide is provided for informational purposes as part of your RMD filing service. It is not legal advice.*
*Performance West Inc. — performancewest.net — 1-888-411-0383*

View file

@ -0,0 +1,324 @@
"""
Generate the NECA Company Code (OCN) Request Form packet.
NECA has not revised the Company Code Request Form since August 2023;
the current form is still in use in 2026. Standard processing is
$550 / 10 business days; expedited is $675 / 5 business days. Payment is
made directly to NECA (Performance West does not collect the NECA fee
separately it is a pass-through).
Required supporting documentation per NECA (varies by service category):
* Legal document proving existence (Articles of Incorporation with
state seal, state registration, etc.) always required
* For CLEC, ULEC, CAP, Local Reseller: state PUC certification
* For Interexchange Carrier: state PUC approval where applicable
* For ETHX: signed customer contracts + service description
* For IPES (VoIP): signed interconnection agreements (or an approved
interconnection order) + end-user contractual agreements or invoices
* For Wireless/PCS: FCC radio/PCS license
* For Wireless/PCS resellers: interconnection agreement with carrier
This generator produces:
1. A cover letter introducing the request on Performance West letterhead
2. A filled-in version of the 2-page NECA form (replicating the fields;
the customer prints, signs, and submits OR we fax/email on their behalf)
Usage:
from scripts.document_gen.templates.ocn_request_form_generator import (
generate_ocn_request_packet,
)
path = generate_ocn_request_packet(
entity_name="Falcon Broadband LLC",
service_category="IPES",
operating_states=["CA","NY","TX"],
expedited=True,
...,
)
"""
from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.ocn_request")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — OCN request generation unavailable")
Document = None # type: ignore[assignment,misc]
NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
BODY_SIZE = Pt(10) if Document else None
HEADING_SIZE = Pt(12) if Document else None
# NECA contact block — unchanged since 2023 form revision.
NECA_ADDRESS = (
"NECA Company Code Administrator\n"
"60 Columbia Road, Building A \u2014 2nd Floor\n"
"Morristown, NJ 07960\n"
"Phone: 973-884-8105 | Fax: 973-993-1063 | Email: ccfees@neca.org"
)
NECA_FEES = {
"standard": {"cents": 55000, "processing_days": 10, "label": "Standard (10 business days)"},
"expedited": {"cents": 67500, "processing_days": 5, "label": "Expedited (5 business days)"},
}
SERVICE_CATEGORIES = {
"CAP": "Competitive Access Provider",
"ETHX": "Ethernet Exchange",
"CLEC": "Competitive Local Exchange Carrier",
"IC": "Interexchange Carrier",
"IPES": "Internet Protocol Enabled Services (VoIP)",
"LRSL": "Local Exchange Reseller",
"PCS": "Personal Communications Service",
"PCSR": "PCS Reseller",
"ULEC": "Unbundled Local Exchange Carrier",
"WIRE": "Wireless Carrier",
"WRSL": "Wireless Reseller",
}
# Required documentation by category. Lifted directly from the NECA form
# (page 2, "REQUIRED DOCUMENTATION" section).
REQUIRED_DOCS_BY_CATEGORY = {
"IPES": [
"Legal document (e.g., Articles of Incorporation with state seal) as proof of existence.",
"Signed interconnection agreements (or evidence of an interconnection order pursuant to an approved tariff).",
"Signed contractual agreements OR an invoice with end-user customers showing proof of customer.",
"Detailed description of the type of IPES service being provided including areas served.",
],
"CLEC": [
"Legal document (e.g., Articles of Incorporation with state seal) as proof of existence.",
"Copy of the certification by the state Public Utility Commission.",
],
"ULEC": [
"Legal document proving existence.",
"Copy of the certification by the state Public Utility Commission.",
],
"CAP": [
"Legal document proving existence.",
"Copy of the certification by the state Public Utility Commission.",
],
"LRSL": [
"Legal document proving existence.",
"Copy of the certification by the state Public Utility Commission.",
],
"IC": [
"Legal document proving existence.",
"State PUC approval where applicable.",
],
"ETHX": [
"Legal document proving existence.",
"Proof of service and customers (contractual agreements + service description).",
],
"WIRE": [
"Legal document proving existence.",
"Copy of the company's FCC radio/PCS license.",
],
"PCS": [
"Legal document proving existence.",
"Copy of the company's FCC radio/PCS license.",
],
"WRSL": [
"Legal document proving existence.",
"Copy of the interconnection agreement with the wireless carrier.",
],
"PCSR": [
"Legal document proving existence.",
"Copy of the interconnection agreement with the wireless carrier.",
],
}
def _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 = Pt(4)
run = p.add_run(text)
run.bold = True
run.font.size = HEADING_SIZE if level == 1 else Pt(11)
run.font.color.rgb = NAVY
def _body(doc, text: str, bold: bool = False) -> None:
p = doc.add_paragraph()
p.paragraph_format.space_after = Pt(6)
run = p.add_run(text)
run.font.size = BODY_SIZE
run.bold = bold
def _field_line(doc, label: str, value: str) -> None:
p = doc.add_paragraph()
p.paragraph_format.space_after = Pt(3)
run_l = p.add_run(f"{label}: ")
run_l.bold = True
run_l.font.size = BODY_SIZE
run_v = p.add_run(value or "_______________________")
run_v.font.size = BODY_SIZE
def generate_ocn_request_packet(
# Entity identity
entity_name: str,
legal_entity_full: str = "",
# Requestor (the person filling out the form — defaults to PW)
requestor_name: str = "Justin Hannah",
requestor_employer: str = "Performance West Inc.",
requestor_voice: str = "888-411-0383",
requestor_fax: str = "",
requestor_mailing_address: str = "30 N Gould St, Ste N, Sheridan, WY 82801",
requestor_email: str = "filings@performancewest.net",
# Company contact (client-side)
company_contact_name: str = "",
company_contact_voice: str = "",
company_contact_fax: str = "",
company_contact_email: str = "",
company_contact_address: str = "",
# Service category — key from SERVICE_CATEGORIES (default IPES for VoIP)
service_category: str = "IPES",
operating_states: list[str] | None = None,
expedited: bool = False,
# Output
output_path: str = "/tmp/ocn_request_packet.docx",
) -> Optional[str]:
"""Generate the NECA OCN request packet DOCX (cover letter + filled form)."""
if Document is None:
LOG.error("python-docx not installed")
return None
operating_states = operating_states or []
category = service_category.upper()
if category not in SERVICE_CATEGORIES:
LOG.warning(
"generate_ocn_request_packet: unknown service_category %r, "
"defaulting to IPES",
service_category,
)
category = "IPES"
fee = NECA_FEES["expedited"] if expedited else NECA_FEES["standard"]
legal_entity_full = legal_entity_full or entity_name
today = datetime.now().strftime("%B %d, %Y")
doc = Document()
for section in doc.sections:
section.top_margin = Inches(1)
section.bottom_margin = Inches(1)
section.left_margin = Inches(1)
section.right_margin = Inches(1)
# ── Page 1: Cover letter ────────────────────────────────────────
title_p = doc.add_paragraph()
title_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
title_run = title_p.add_run("NECA Company Code (OCN) Request Packet")
title_run.font.size = Pt(14)
title_run.bold = True
title_run.font.color.rgb = NAVY
_body(doc, f"Date: {today}")
_body(doc, "")
_body(doc, "To:")
_body(doc, NECA_ADDRESS)
_body(doc, "")
_body(doc, (
f"Dear NECA Company Code Administrator,\n\n"
f"Please find enclosed a Company Code Request Form and supporting "
f"documentation for {legal_entity_full}. We are submitting this "
f"request in the {category} \u2014 "
f"{SERVICE_CATEGORIES[category]} category."
))
_body(doc, (
f"Processing type requested: {fee['label']}.\n"
f"Payment of ${fee['cents']/100:.2f} will accompany this filing."
))
if operating_states and category in ("CLEC", "ULEC"):
_body(doc, (
f"States of operation (multiple codes will be assigned for "
f"CLEC/ULEC): {', '.join(operating_states)}"
))
_body(doc, (
"If you have questions or need additional information, please "
f"contact me directly at {requestor_voice} or {requestor_email}."
))
_body(doc, "")
_body(doc, "Sincerely,")
_body(doc, "")
_body(doc, "")
_body(doc, requestor_name, bold=True)
_body(doc, requestor_employer)
doc.add_page_break()
# ── Page 2: Company Code Request Form (replicated fields) ──────
_heading(doc, "COMPANY CODE REQUEST FORM")
_body(doc, f"Issued: August 2023 | Date of Request: {today}")
_heading(doc, "REQUESTOR INFORMATION", level=2)
_field_line(doc, "Requestor's Name", requestor_name)
_field_line(doc, "Employer", requestor_employer)
_field_line(doc, "Mailing Address", requestor_mailing_address)
_field_line(doc, "Voice Number", requestor_voice)
_field_line(doc, "Fax Number", requestor_fax)
_field_line(doc, "Email Address", requestor_email)
_body(doc, (
"Note: This contact will also be listed in iconectiv's routing "
"products as \"Agent for Service of Process\". To use a different "
"contact, notify iconectiv TruOps TRA at 732-699-6700."
))
_heading(doc, "COMPANY INFORMATION", level=2)
_field_line(doc, "Company Name / Full Legal Entity Name", legal_entity_full)
_field_line(doc, "Company Contact", company_contact_name)
_field_line(doc, "Voice Number", company_contact_voice)
_field_line(doc, "Fax Number", company_contact_fax)
_field_line(doc, "Email Address", company_contact_email)
_field_line(doc, "Company Contact Mailing Address", company_contact_address)
_heading(doc, "SERVICE CATEGORY REQUESTED", level=2)
for code, label in SERVICE_CATEGORIES.items():
mark = "\u2611" if code == category else "\u2610"
states = ""
if code == category and operating_states and code in ("CLEC", "ULEC"):
states = " Operating States: " + ", ".join(operating_states)
expedited_mark = "\u2611 EXPEDITED" if (code == category and expedited) else ""
p = doc.add_paragraph()
p.paragraph_format.space_after = Pt(2)
run = p.add_run(f" {mark} {code} \u2014 {label}{states} {expedited_mark}")
run.font.size = BODY_SIZE
_heading(doc, "REQUIRED DOCUMENTATION (attach to submission)", level=2)
for doc_item in REQUIRED_DOCS_BY_CATEGORY.get(category, []):
p = doc.add_paragraph(style="List Bullet")
p.paragraph_format.space_after = Pt(3)
p.clear()
run = p.add_run(doc_item)
run.font.size = BODY_SIZE
_heading(doc, "PRICING AND PAYMENT", level=2)
_body(doc, (
f"Submit ${fee['cents']/100:.2f} for this "
f"{'expedited' if expedited else 'standard'} request. Code requests "
f"are processed within {fee['processing_days']} business days of "
f"receipt of all required documentation including payment."
))
_heading(doc, "SUBMISSION", level=2)
_body(doc, (
"Fax the completed form + documentation to +1 973-993-1063, OR "
"email to ccfees@neca.org, OR mail to:"
))
_body(doc, NECA_ADDRESS)
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("NECA OCN request packet generated: %s", out)
return str(out)

View file

@ -0,0 +1,214 @@
"""
Generate the FCC Form 499-A Reseller Certification Attestation.
Produces a DOCX that a filer sends to its reseller customer for the
reseller's authorized officer to sign. The signed attestation
establishes that the purchased service is being resold into a
telecommunications or interconnected VoIP offering, and that USF
contribution is flowing (per 2026 Form 499-A Section IV.C.4).
The sample certification text is reproduced verbatim from
``site/src/lib/fcc_constants.ts::RESELLER_CERTIFICATION_SAMPLE_TEXT``
and mirrored in the constant ``RESELLER_CERTIFICATION_SAMPLE_TEXT``
below. If upstream source text changes, update both locations.
Usage:
from scripts.document_gen.templates.reseller_cert_attestation_generator import (
generate_reseller_cert_attestation,
)
path = generate_reseller_cert_attestation(
output_path="/tmp/reseller_cert.docx",
filer_legal_name="Acme Telco LLC",
filer_filer_id_499="812345",
reseller_legal_name="Beta Reseller Corp",
reseller_filer_id_499="812999",
reporting_year=2025,
)
"""
from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.reseller_cert_attestation")
try:
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
except ImportError:
LOG.warning("python-docx not installed — reseller cert attestation unavailable")
Document = None # type: ignore[assignment,misc]
_NAVY = RGBColor(0x1A, 0x27, 0x44) if Document else None
# Verbatim from site/src/lib/fcc_constants.ts (RESELLER_CERTIFICATION_SAMPLE_TEXT).
RESELLER_CERTIFICATION_SAMPLE_TEXT = (
"I certify under penalty of perjury that the company is purchasing "
"service(s) for resale, at least in part, and that the company is "
"incorporating the purchased services into its own offerings which "
"are, at least in part, assessable U.S. telecommunications or "
"interconnected Voice over Internet Protocol services. I also "
"certify under penalty of perjury that the company either directly "
"contributes or has a reasonable expectation that another entity in "
"the downstream chain of resellers directly contributes to the "
"federal universal service support mechanisms on the assessable "
"portion of revenues from offerings that incorporate the purchased "
"services."
)
def _sp(p, after=6, before=0):
p.paragraph_format.space_after = Pt(after)
if before:
p.paragraph_format.space_before = Pt(before)
def _h(doc, text):
p = doc.add_paragraph(); r = p.add_run(text)
r.font.size = Pt(12); r.bold = True; r.font.color.rgb = _NAVY
_sp(p, after=4, before=8)
def _b(doc, text, bold=False, size=10):
p = doc.add_paragraph(); p.alignment = WD_ALIGN_PARAGRAPH.LEFT
r = p.add_run(text); r.font.size = Pt(size); r.bold = bold
_sp(p, after=6)
def generate_reseller_cert_attestation(
output_path: str,
filer_legal_name: str,
filer_filer_id_499: str,
reseller_legal_name: str,
reseller_filer_id_499: str = "",
reporting_year: int = 0,
effective_date: str = "",
filer_contact_name: str = "",
filer_contact_email: str = "",
filer_contact_phone: str = "",
**_: dict,
) -> Optional[str]:
"""
Produce the Reseller Certification Attestation DOCX for signature
by the reseller's authorized officer.
"""
if Document is None:
LOG.error("python-docx not installed")
return None
if reporting_year == 0:
reporting_year = datetime.now().year
effective = effective_date or datetime.now().strftime("%B %d, %Y")
doc = Document()
for s in doc.sections:
s.top_margin = Inches(1); s.bottom_margin = Inches(1)
s.left_margin = Inches(1.25); s.right_margin = Inches(1.25)
# Title
tp = doc.add_paragraph(); tp.alignment = WD_ALIGN_PARAGRAPH.CENTER
t = tp.add_run("Reseller Certification Attestation")
t.font.size = Pt(15); t.bold = True; t.font.color.rgb = _NAVY
_sp(tp, after=2)
sp = doc.add_paragraph(); sp.alignment = WD_ALIGN_PARAGRAPH.CENTER
s = sp.add_run(
f"FCC Form 499-A Section IV.C.4 \u2014 Reporting Year {reporting_year}"
)
s.font.size = Pt(10); s.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
_sp(sp, after=8)
# ── 1. Parties ────────────────────────────────────────────────
_h(doc, "1. Parties")
_b(doc, (
f"Filer (upstream wholesaler): {filer_legal_name}"
+ (f" | Filer 499 ID: {filer_filer_id_499}" if filer_filer_id_499 else "")
))
_b(doc, (
f"Reseller (purchaser): {reseller_legal_name}"
+ (f" | Filer 499 ID: {reseller_filer_id_499}"
if reseller_filer_id_499 else " | Filer 499 ID: _______________")
))
_b(doc, f"Effective Reporting Year: {reporting_year}")
_b(doc, f"Date of Attestation: {effective}")
# ── 2. Purpose ────────────────────────────────────────────────
_h(doc, "2. Purpose")
_b(doc, (
f"Pursuant to Section IV.C.4 of the FCC Form 499-A Instructions "
f"({reporting_year}), {filer_legal_name} is required to obtain from "
f"{reseller_legal_name} a signed certification that the services "
f"purchased by the reseller are being incorporated into assessable "
f"U.S. telecommunications or interconnected Voice over Internet "
f"Protocol offerings, and that federal universal-service "
f"contributions are flowing on those resold services. This "
f"Attestation satisfies that requirement."
))
# ── 3. Certification Language (verbatim) ──────────────────────
_h(doc, "3. Certification")
_b(doc, RESELLER_CERTIFICATION_SAMPLE_TEXT)
# ── 4. Annual Renewal Notice ──────────────────────────────────
_h(doc, "4. Annual Renewal")
_b(doc, (
"This Attestation is effective for the reporting year stated "
f"above and must be renewed annually. {filer_legal_name} will "
f"request an updated, signed Attestation from {reseller_legal_name} "
f"on or about January 1 of each subsequent reporting year. A "
f"current signed Attestation must be on file at the time "
f"{filer_legal_name} submits its Form 499-A for the reporting "
f"year."
))
# ── 5. Reseller Authorized Officer Signature ──────────────────
_h(doc, "5. Signature — Reseller Authorized Officer")
_b(doc, (
f"By signing below, the undersigned officer of {reseller_legal_name} "
f"certifies that he or she is an authorized officer of the company, "
f"has personal knowledge of the matters certified above, and "
f"executes this Attestation on behalf of the company."
))
# Blank signature block
sig = doc.add_paragraph(); sig.add_run("_" * 55).font.size = Pt(10)
_sp(sig, after=2)
nm = doc.add_paragraph()
nm.add_run("Name (printed): ").font.size = Pt(10)
nm.add_run("_" * 40).font.size = Pt(10)
_sp(nm, after=4)
tt = doc.add_paragraph()
tt.add_run("Title: ").font.size = Pt(10)
tt.add_run("_" * 48).font.size = Pt(10)
_sp(tt, after=4)
co = doc.add_paragraph()
co.add_run("Company: ").font.size = Pt(10)
co.add_run(reseller_legal_name).font.size = Pt(10)
_sp(co, after=4)
dt = doc.add_paragraph()
dt.add_run("Date: ").font.size = Pt(10)
dt.add_run("_" * 20).font.size = Pt(10)
_sp(dt, after=10)
# ── 6. Filer Contact (for returning the signed form) ──────────
_h(doc, "6. Return Signed Attestation To")
_b(doc, filer_legal_name)
if filer_contact_name:
_b(doc, f"Attention: {filer_contact_name}")
if filer_contact_email:
_b(doc, f"Email: {filer_contact_email}")
if filer_contact_phone:
_b(doc, f"Phone: {filer_contact_phone}")
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("Reseller Certification Attestation generated: %s", out)
return str(out)

View file

@ -0,0 +1,602 @@
"""
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()

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,303 @@
"""
Traffic Study Page Stamper for FCC Form 499-A filings.
2026 Form 499-A Section IV.C.5.h requires carriers that submit a
traffic study (in lieu of electing a safe-harbor allocation) to stamp
every page of the study with a one-line header identifying the Filer
ID, Company Name, and Affiliated Filers Name. USAC uses this header
to match the study back to the 499-A submission and to verify
consistency across affiliated filers.
Primary path
------------
Try to generate a text overlay via ``reportlab`` and merge it onto
each page of the source PDF with ``pypdf``. Each overlay PDF matches
the media-box size of its corresponding source page so that the
merge is geometrically correct.
Fallback
--------
If ``reportlab`` is not installed, attempt a best-effort stamping
using a pypdf-authored PageObject with a small content-stream
annotation. If that also fails, copy the source PDF to the output
path unchanged, log a warning, and return the output path (the 499-A
submission plan requires the filing to proceed regardless).
Usage
-----
from scripts.document_gen.traffic_study_stamper import stamp_pages
out = stamp_pages(
pdf_path="/data/traffic_study.pdf",
output_path="/data/traffic_study.stamped.pdf",
filer_id="812345",
company_name="Acme Telco LLC",
affiliated_filers_name="Acme Holdings",
)
"""
from __future__ import annotations
import io
import logging
import shutil
from pathlib import Path
from typing import Optional
LOG = logging.getLogger("document_gen.traffic_study_stamper")
# ── PDF core (required) ─────────────────────────────────────────────
try:
from pypdf import PdfReader, PdfWriter, PageObject
from pypdf.generic import (
ContentStream,
NameObject,
NumberObject,
TextStringObject,
)
_HAS_PYPDF = True
except ImportError:
LOG.warning("pypdf not installed — traffic study stamping unavailable")
PdfReader = None # type: ignore[assignment,misc]
PdfWriter = None # type: ignore[assignment,misc]
PageObject = None # type: ignore[assignment,misc]
_HAS_PYPDF = False
# ── Reportlab (preferred overlay path; optional) ────────────────────
try:
from reportlab.pdfgen import canvas as _rl_canvas # type: ignore
_HAS_REPORTLAB = True
except ImportError:
_rl_canvas = None # type: ignore[assignment]
_HAS_REPORTLAB = False
STAMP_FONT_PT = 8
STAMP_MARGIN_Y_PT = 20 # distance from top of page
STAMP_MARGIN_X_PT = 36 # 0.5 inch from left
def _format_stamp(filer_id: str, company_name: str, affiliated_filers_name: str) -> str:
"""Build the stamp-text one-liner per Form 499-A Section IV.C.5.h."""
return (
f"Filer ID {filer_id or '\u2014'} | "
f"{company_name or '\u2014'} | "
f"Affiliated Filers: {affiliated_filers_name or '\u2014'}"
)
def _overlay_reportlab(
stamp_text: str, width: float, height: float
) -> Optional[bytes]:
"""Build a one-page overlay PDF (bytes) sized (width, height) with the
stamp drawn at the top-left. Returns None if reportlab can't be used."""
if not _HAS_REPORTLAB or _rl_canvas is None:
return None
try:
buf = io.BytesIO()
c = _rl_canvas.Canvas(buf, pagesize=(width, height))
c.setFont("Helvetica", STAMP_FONT_PT)
# y measured from bottom of page; header sits near top
y = height - STAMP_MARGIN_Y_PT
c.drawString(STAMP_MARGIN_X_PT, y, stamp_text)
c.showPage()
c.save()
return buf.getvalue()
except Exception as exc: # pragma: no cover
LOG.warning("reportlab overlay build failed: %s", exc)
return None
def _apply_overlay_via_pypdf(
page: "PageObject", # type: ignore[name-defined]
overlay_pdf_bytes: bytes,
) -> None:
"""Merge a single-page overlay PDF onto the given source page."""
from pypdf import PdfReader as _Reader
overlay_reader = _Reader(io.BytesIO(overlay_pdf_bytes))
if not overlay_reader.pages:
return
page.merge_page(overlay_reader.pages[0])
def _stamp_via_content_stream(
page: "PageObject", # type: ignore[name-defined]
stamp_text: str,
page_height: float,
) -> bool:
"""
Fallback stamping when reportlab is unavailable.
Appends a minimal PDF content stream to draw ``stamp_text`` at the
top of ``page``. Returns True on success, False on any exception.
"""
try:
# Escape parentheses / backslashes per PDF string encoding.
safe = (
stamp_text.replace("\\", "\\\\")
.replace("(", "\\(")
.replace(")", "\\)")
)
y = page_height - STAMP_MARGIN_Y_PT
# Use Helvetica (F1) at STAMP_FONT_PT. We add an /F1 resource
# reference if missing.
stream = (
f"q BT /F1 {STAMP_FONT_PT} Tf "
f"{STAMP_MARGIN_X_PT} {y} Td ({safe}) Tj ET Q"
).encode("latin-1", errors="replace")
existing = page.get_contents()
from pypdf.generic import ByteStringObject, ArrayObject
new_cs = ContentStream(None, None)
new_cs.set_data(stream)
# Ensure /Font /F1 exists in the page resources.
from pypdf.generic import DictionaryObject, IndirectObject
resources = page.get("/Resources")
if isinstance(resources, IndirectObject):
resources = resources.get_object()
if resources is None:
resources = DictionaryObject()
page[NameObject("/Resources")] = resources
fonts = resources.get("/Font")
if isinstance(fonts, IndirectObject):
fonts = fonts.get_object()
if fonts is None:
fonts = DictionaryObject()
resources[NameObject("/Font")] = fonts
if "/F1" not in fonts:
helv = DictionaryObject(
{
NameObject("/Type"): NameObject("/Font"),
NameObject("/Subtype"): NameObject("/Type1"),
NameObject("/BaseFont"): NameObject("/Helvetica"),
}
)
fonts[NameObject("/F1")] = helv
# Append the new content stream. If existing /Contents is an
# array, append. Otherwise, wrap both into an array.
if existing is None:
page[NameObject("/Contents")] = new_cs
else:
# merge_page would normally handle this; we emulate the
# simplest case by concatenating streams.
try:
combined = ContentStream(None, None)
combined.set_data(existing.get_data() + b"\n" + stream)
page[NameObject("/Contents")] = combined
except Exception:
# Last-ditch: prepend via an array.
page[NameObject("/Contents")] = ArrayObject([existing, new_cs])
return True
except Exception as exc:
LOG.warning("pypdf content-stream stamping failed: %s", exc)
return False
def stamp_pages(
pdf_path: str,
output_path: str,
filer_id: str,
company_name: str,
affiliated_filers_name: str = "\u2014",
) -> str:
"""
Stamp every page of ``pdf_path`` with a one-line header containing
the Filer ID, Company Name, and Affiliated Filers Name. Write the
result to ``output_path``. Return ``output_path``.
This function is best-effort by design. The Form 499-A filing plan
requires that the submission proceed even when fancy stamping fails
(e.g., in a constrained environment missing ``reportlab``). On any
unrecoverable error the source PDF is copied verbatim to the
output path and a warning is logged.
"""
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
src = Path(pdf_path)
if not src.exists():
raise FileNotFoundError(f"source PDF not found: {pdf_path}")
stamp_text = _format_stamp(filer_id, company_name, affiliated_filers_name)
if not _HAS_PYPDF:
LOG.warning(
"pypdf unavailable — copying source PDF unchanged to %s", out
)
shutil.copyfile(src, out)
return str(out)
try:
reader = PdfReader(str(src))
writer = PdfWriter()
overlay_mode = "reportlab" if _HAS_REPORTLAB else "content_stream"
for page in reader.pages:
mb = page.mediabox
width = float(mb.width)
height = float(mb.height)
stamped = False
if overlay_mode == "reportlab":
overlay_bytes = _overlay_reportlab(stamp_text, width, height)
if overlay_bytes:
try:
_apply_overlay_via_pypdf(page, overlay_bytes)
stamped = True
except Exception as exc:
LOG.warning(
"overlay merge failed on page; "
"falling back to content stream: %s", exc
)
if not stamped:
_stamp_via_content_stream(page, stamp_text, height)
writer.add_page(page)
with out.open("wb") as fh:
writer.write(fh)
if overlay_mode != "reportlab":
LOG.warning(
"reportlab not available — used pypdf content-stream fallback "
"to stamp %s (filer=%s).", out, filer_id
)
else:
LOG.info(
"Traffic study stamped via reportlab overlay: %s (filer=%s)",
out, filer_id,
)
return str(out)
except Exception as exc:
LOG.warning(
"traffic-study stamping failed (%s); copying source unchanged "
"to preserve filing timeline.", exc
)
try:
shutil.copyfile(src, out)
except Exception as exc2: # pragma: no cover
LOG.error("fallback copy also failed: %s", exc2)
raise
return str(out)
if __name__ == "__main__": # pragma: no cover
import argparse
logging.basicConfig(level=logging.INFO)
ap = argparse.ArgumentParser(description=__doc__.split("\n\n", 1)[0])
ap.add_argument("source_pdf")
ap.add_argument("output_pdf")
ap.add_argument("--filer-id", required=True)
ap.add_argument("--company-name", required=True)
ap.add_argument("--affiliated-filers-name", default="\u2014")
args = ap.parse_args()
p = stamp_pages(
pdf_path=args.source_pdf,
output_path=args.output_pdf,
filer_id=args.filer_id,
company_name=args.company_name,
affiliated_filers_name=args.affiliated_filers_name,
)
print(p)