new-site/scripts/generate_all_permutations.py
justin f8cd37ac8c 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>
2026-04-27 06:54:22 -05:00

630 lines
23 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Generate all document permutations (DOCX + PDF) for a sample company
and email them to ops@performancewest.net for review.
Usage:
python -m scripts.generate_all_permutations
Environment variables:
SMTP_HOST outbound mail server (default: co.carrierone.com)
SMTP_PORT mail port (default: 587)
SMTP_USER SMTP login
SMTP_PASS SMTP password
"""
from __future__ import annotations
import logging
import os
import smtplib
import subprocess
import sys
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from pathlib import Path
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(name)s] %(message)s")
LOG = logging.getLogger("generate_all_permutations")
# ── SMTP config ──────────────────────────────────────────────────────────────
SMTP_HOST = os.environ.get("SMTP_HOST", "co.carrierone.com")
SMTP_PORT = int(os.environ.get("SMTP_PORT", "587"))
SMTP_USER = os.environ.get("SMTP_USER", "")
SMTP_PASS = os.environ.get("SMTP_PASS", "")
FROM_EMAIL = os.environ.get("FROM_EMAIL", "noreply@performancewest.net")
TO_EMAIL = "ops@performancewest.net"
# ── Sample company data used across all documents ───────────────────────────
COMPANY = {
"entity_name": "Falcon Broadband LLC",
"dba_name": "Falcon Communications",
"frn": "0027160886",
"rmd_number": "RMD-00123456",
"filer_id_499": "831234",
"address_street": "1234 Telecom Drive, Suite 400",
"address_city": "Denver",
"address_state": "CO",
"address_zip": "80202",
"contact_name": "Sarah Mitchell",
"contact_title": "VP of Regulatory Affairs",
"contact_email": "regulatory@falconbroadband.com",
"contact_phone": "+1 (303) 555-0142",
"ceo_name": "James R. Falcon",
"ceo_title": "Chief Executive Officer",
}
OUTPUT_DIR = Path("/tmp/permutation_output")
def _convert_to_pdf(docx_path: Path) -> Path | None:
"""Convert DOCX to PDF via LibreOffice headless (local fallback)."""
pdf_path = docx_path.with_suffix(".pdf")
try:
result = subprocess.run(
["libreoffice", "--headless", "--convert-to", "pdf",
"--outdir", str(docx_path.parent), str(docx_path)],
capture_output=True, text=True, timeout=60,
)
if result.returncode == 0 and pdf_path.exists():
LOG.info(" PDF: %s", pdf_path.name)
return pdf_path
else:
LOG.warning(" LibreOffice conversion failed for %s: %s", docx_path.name, result.stderr[:200])
except FileNotFoundError:
LOG.warning(" LibreOffice not installed — skipping PDF for %s", docx_path.name)
except Exception as exc:
LOG.warning(" PDF conversion error for %s: %s", docx_path.name, exc)
return None
def generate_rmd_letters() -> list[Path]:
"""Generate RMD certification letters for all classification × STIR/SHAKEN permutations."""
from scripts.document_gen.templates.rmd_letter_generator import generate_rmd_letter
# Map to actual FCC provider classifications per 47 CFR § 64.6305
# Each with a realistic switch/ucaas combo to test auto-fill
classifications = [
{
"label": "voice_svc_oasis",
"provider_classification": "voice_service_provider",
"infra_type": "facilities",
"is_gateway_provider": False,
"is_wholesale": False,
"switch_platform": "Oasis",
},
{
"label": "voice_svc_bcmone",
"provider_classification": "voice_service_provider",
"infra_type": "reseller",
"is_gateway_provider": False,
"is_wholesale": False,
"ucaas_host": "BCM One",
},
{
"label": "voice_svc_metaswitch",
"provider_classification": "voice_service_provider",
"infra_type": "facilities",
"is_gateway_provider": False,
"is_wholesale": False,
"switch_platform": "Metaswitch",
},
{
"label": "gateway",
"provider_classification": "gateway_provider",
"infra_type": "facilities",
"is_gateway_provider": True,
"is_wholesale": True,
"switch_platform": "Ribbon (OASIS SBC)",
},
{
"label": "intermediate",
"provider_classification": "intermediate_provider",
"infra_type": "facilities",
"is_gateway_provider": False,
"is_wholesale": True,
"switch_platform": "FreeSWITCH",
},
]
stir_shaken_statuses = [
"complete_implementation",
"partial_implementation",
"robocall_mitigation_only",
"exempt_small_carrier",
"not_applicable",
]
carrier_categories = ["interconnected_voip", "clec", "ixc", "cmrs"]
files: list[Path] = []
for cls in classifications:
for ss_status in stir_shaken_statuses:
cat = carrier_categories[classifications.index(cls) % len(carrier_categories)]
label = cls["label"]
filename = f"rmd_letter_{label}_{ss_status}.docx"
out = str(OUTPUT_DIR / filename)
LOG.info("RMD Letter: classification=%s, stir_shaken=%s", label, ss_status)
result = generate_rmd_letter(
**COMPANY,
ocn="8765",
former_names=["Falcon Voice Services LLC"],
is_foreign_provider=(cls["label"] == "gateway"),
provider_classification=cls["provider_classification"],
carrier_category=cat,
infra_type=cls["infra_type"],
is_wholesale=cls.get("is_wholesale", False),
is_gateway_provider=cls.get("is_gateway_provider", False),
switch_platform=cls.get("switch_platform", ""),
ucaas_host=cls.get("ucaas_host", ""),
stir_shaken_status=ss_status,
stir_shaken_cert_authority="TransNexus",
stir_shaken_extension_type="non_ip_network" if ss_status == "partial_implementation" else "",
stir_shaken_extension_basis="TDM portions of the network cannot support SIP-based STIR/SHAKEN signing." if ss_status == "partial_implementation" else "",
carrier_metadata={
"gateway_countries": ["Canada", "Mexico", "United Kingdom"],
"wholesale_customer_types": ["CLEC", "VoIP", "CMRS"],
"downstream_count_approx": 47,
},
output_path=out,
)
if result:
files.append(Path(result))
return files
def generate_exhibit_a_docs() -> list[Path]:
"""Generate Exhibit A (robocall mitigation program) for each carrier role."""
from scripts.document_gen.templates.rmd_exhibit_a_generator import generate_exhibit_a
roles = ["facilities", "reseller", "gateway", "ucaas", "wholesale_domestic", "international_only"]
files: list[Path] = []
for role in roles:
filename = f"exhibit_a_{role}.docx"
out = str(OUTPUT_DIR / filename)
# Vary the intake answers per role to exercise auto-fill
role_extras = {
"facilities": {"switch_platform": "Oasis"},
"reseller": {"ucaas_host": "BCM One"},
"gateway": {"switch_platform": "Ribbon SBC"},
"ucaas": {"ucaas_host": "RingCentral"},
"wholesale_domestic": {"switch_platform": "Cataleya"},
"international_only": {"switch_platform": "46Labs"},
}
LOG.info("Exhibit A: role=%s (auto-fill from intake)", role)
result = generate_exhibit_a(
entity_name=COMPANY["entity_name"],
frn=COMPANY["frn"],
carrier_role=role,
carrier_metadata={
"gateway_countries": ["Canada", "Mexico", "United Kingdom"],
"wholesale_customer_types": ["CLEC", "VoIP", "CMRS"],
},
**role_extras.get(role, {}),
output_path=out,
)
if result:
files.append(Path(result))
return files
def generate_cpni_letters() -> list[Path]:
"""Generate CPNI cert letters: retail vs wholesale, complaints vs no complaints."""
from scripts.document_gen.templates.cpni_cert_letter_generator import generate_cpni_cert_letter
permutations = [
{
"label": "retail_clean",
"is_wholesale": False,
"complaints_count": 0,
},
{
"label": "retail_complaints_breaches",
"is_wholesale": False,
"complaints_count": 3,
"complaints_description": "Three complaints were received regarding third-party marketing access to CPNI. Each was investigated within 5 business days and resolved by reaffirming customer opt-out preferences.",
"breaches": [
{
"description": "Employee inadvertently disclosed call detail records for 12 accounts to an unauthorized third party during a vendor integration.",
"date": "2025-06-22",
"customers_affected": 12,
"response_actions": "Affected customers notified within 30 days per 47 CFR § 64.2011. Employee received corrective training. Vendor access controls tightened.",
},
],
"disciplinary_actions_taken": True,
"disciplinary_actions_description": "One employee received a written warning and mandatory retraining for the June 2025 inadvertent CPNI disclosure.",
"uses_cpni_for_marketing": True,
"cpni_approval_method": "opt_in",
},
{
"label": "wholesale_clean",
"is_wholesale": True,
"complaints_count": 0,
},
{
"label": "wholesale_breach",
"is_wholesale": True,
"complaints_count": 1,
"complaints_description": "One complaint regarding unauthorized disclosure of wholesale traffic data to a third party.",
"breaches": [
{
"description": "Wholesale traffic routing data for 3 downstream carriers was inadvertently exposed via a misconfigured API endpoint.",
"date": "2025-09-10",
"customers_affected": 3,
"response_actions": "API endpoint secured within 2 hours. Affected carriers notified same day. FCC notified within 30 days per § 64.2011.",
},
],
},
]
files: list[Path] = []
for perm in permutations:
label = perm.pop("label")
filename = f"cpni_cert_{label}.docx"
out = str(OUTPUT_DIR / filename)
LOG.info("CPNI Letter: %s", label)
result = generate_cpni_cert_letter(
entity_name=COMPANY["entity_name"],
frn=COMPANY["frn"],
filer_id_499=COMPANY["filer_id_499"],
address_street=COMPANY["address_street"],
address_city=COMPANY["address_city"],
address_state=COMPANY["address_state"],
address_zip=COMPANY["address_zip"],
officer_name=COMPANY["ceo_name"],
officer_title=COMPANY["ceo_title"],
contact_email=COMPANY["contact_email"],
contact_phone=COMPANY["contact_phone"],
reporting_year=2025,
output_path=out,
**perm,
)
if result:
files.append(Path(result))
return files
def generate_499a_checklists() -> list[Path]:
"""Generate 499-A checklists for various filer/infra/status combinations."""
from scripts.document_gen.templates.fcc_499a_checklist_generator import generate_499a_checklist
permutations = [
{
"label": "voip_facilities_full",
"filer_type": "interconnected_voip",
"infra_type": "facilities",
"service_categories": ["interconnected_voip", "long_distance"],
"is_deminimis": False,
"is_lire": False,
},
{
"label": "voip_reseller_deminimis",
"filer_type": "interconnected_voip",
"infra_type": "reseller",
"service_categories": ["interconnected_voip"],
"is_deminimis": True,
"is_lire": False,
},
{
"label": "clec_facilities_lire",
"filer_type": "clec",
"infra_type": "facilities",
"service_categories": ["local_exchange", "long_distance", "toll_free"],
"is_deminimis": False,
"is_lire": True,
},
{
"label": "ixc_both_full",
"filer_type": "ixc",
"infra_type": "both",
"service_categories": ["long_distance", "dedicated_line", "toll_free"],
"is_deminimis": False,
"is_lire": False,
"total_revenue_cents": 125000000,
"interstate_pct": 72.5,
"international_pct": 8.3,
"last_filing_year": 2024,
"contribution_factor_pct": 35.8,
"uncollectible_revenue_cents": 2500000,
"resold_service_costs_cents": 15000000,
},
{
"label": "cmrs_facilities_deminimis",
"filer_type": "cmrs",
"infra_type": "facilities",
"service_categories": ["wireless", "interconnected_voip"],
"is_deminimis": True,
"is_lire": False,
},
{
"label": "voip_safe_harbor",
"filer_type": "interconnected_voip",
"infra_type": "facilities",
"service_categories": ["interconnected_voip"],
"is_deminimis": False,
"is_lire": False,
"uses_voip_safe_harbor": True,
"voip_safe_harbor_pct": 64.9,
"total_revenue_cents": 80000000,
"contribution_factor_pct": 35.8,
},
{
"label": "reseller_stale_filing",
"filer_type": "interconnected_voip",
"infra_type": "reseller",
"service_categories": ["interconnected_voip", "resale"],
"is_deminimis": False,
"is_lire": False,
"last_filing_year": 2022,
},
{
"label": "red_light_debt",
"filer_type": "interconnected_voip",
"infra_type": "facilities",
"service_categories": ["interconnected_voip"],
"is_deminimis": False,
"is_lire": False,
"has_outstanding_fcc_debt": True,
"total_revenue_cents": 50000000,
"contribution_factor_pct": 35.8,
},
]
files: list[Path] = []
for perm in permutations:
label = perm.pop("label")
filename = f"499a_checklist_{label}.docx"
out = str(OUTPUT_DIR / filename)
LOG.info("499-A Checklist: %s", label)
result = generate_499a_checklist(
entity_name=COMPANY["entity_name"],
frn=COMPANY["frn"],
filer_id_499=COMPANY["filer_id_499"],
address_street=COMPANY["address_street"],
address_city=COMPANY["address_city"],
address_state=COMPANY["address_state"],
address_zip=COMPANY["address_zip"],
output_path=out,
**perm,
)
if result:
files.append(Path(result))
return files
def generate_crtc_letters() -> list[Path]:
"""Generate CRTC notification letters: with and without BITS."""
from scripts.document_gen.templates.crtc_letter_generator import generate_crtc_letter
permutations = [
{"label": "bc_with_bits", "include_bits": True},
{"label": "bc_without_bits", "include_bits": False},
]
files: list[Path] = []
for perm in permutations:
label = perm.pop("label")
filename = f"crtc_letter_{label}.docx"
out = str(OUTPUT_DIR / filename)
LOG.info("CRTC Letter: %s", label)
result = generate_crtc_letter(
entity_name="1234567 B.C. Ltd.",
incorporation_number="BC1234567",
registered_office="329 Howe St, Suite 200, Vancouver, BC V6C 3N2",
services_description=(
"Resale of local and long distance voice services, data services, "
"and wireless services to business and residential customers across Canada."
),
geographic_coverage="Canada-wide",
regulatory_contact_name="Regulatory Director",
regulatory_contact_email="regulatory@1234567bc.ca",
regulatory_contact_phone="+1 (604) 555-0199",
director_name="James R. Falcon",
ca_domain="1234567bc.ca",
output_path=out,
**perm,
)
if result:
files.append(Path(result))
return files
def generate_operating_agreements() -> list[Path]:
"""Generate operating agreements: member-managed vs manager-managed."""
from scripts.formation.base import EntityType, FormationOrder, Member
from scripts.formation.operating_agreement import generate_operating_agreement
members = [
Member(
name="James R. Falcon",
address="1234 Telecom Drive, Suite 400",
city="Denver",
state="CO",
zip_code="80202",
title="Managing Member",
ownership_pct=60.0,
is_organizer=True,
),
Member(
name="Sarah Mitchell",
address="5678 Signal Blvd",
city="Aurora",
state="CO",
zip_code="80012",
title="Member",
ownership_pct=40.0,
),
]
permutations = [
{"label": "member_managed", "management_type": "member_managed"},
{"label": "manager_managed", "management_type": "manager_managed"},
]
files: list[Path] = []
for perm in permutations:
label = perm["label"]
LOG.info("Operating Agreement: %s", label)
order = FormationOrder(
order_id=f"PERM-OA-{label.upper()}",
state_code="CO",
entity_type=EntityType.LLC,
entity_name="Falcon Broadband LLC",
management_type=perm["management_type"],
purpose="Telecommunications services, including the provision of voice, data, and internet services",
members=members,
registered_agent_name="Northwest Registered Agent",
registered_agent_address="7700 E Arapahoe Rd, Suite 220, Centennial, CO 80112",
principal_address="1234 Telecom Drive, Suite 400",
principal_city="Denver",
principal_state="CO",
principal_zip="80202",
fiscal_year_end="12/31",
filed_at="2026-03-15",
)
docx_path, pdf_path = generate_operating_agreement(order)
if docx_path:
import shutil
src = Path(docx_path)
dst = OUTPUT_DIR / f"operating_agreement_{label}.docx"
shutil.move(str(src), str(dst))
files.append(dst)
if pdf_path and pdf_path != "" and Path(pdf_path).is_file():
pdf_dst = OUTPUT_DIR / f"operating_agreement_{label}.pdf"
shutil.move(str(pdf_path), str(pdf_dst))
files.append(pdf_dst)
return files
def send_email(all_files: list[Path]) -> None:
"""Send all generated files as attachments to ops@performancewest.net."""
if not SMTP_USER or not SMTP_PASS:
LOG.error("SMTP_USER / SMTP_PASS not set — cannot send email")
LOG.info("Generated %d files in %s — attach and send manually", len(all_files), OUTPUT_DIR)
return
# Split into batches to avoid oversized emails (max ~20 attachments per email)
BATCH_SIZE = 20
batches = [all_files[i:i + BATCH_SIZE] for i in range(0, len(all_files), BATCH_SIZE)]
for batch_num, batch in enumerate(batches, 1):
msg = MIMEMultipart()
msg["From"] = FROM_EMAIL
msg["To"] = TO_EMAIL
msg["Subject"] = f"Document Permutations — All Templates (Batch {batch_num}/{len(batches)})"
# Build summary
summary_lines = [f"<li>{f.name} ({f.stat().st_size / 1024:.0f} KB)</li>" for f in batch]
body_html = f"""<html><body>
<h2>Document Permutation Output — Batch {batch_num}/{len(batches)}</h2>
<p>{len(batch)} files attached. {len(all_files)} total across all batches.</p>
<h3>Files in this batch:</h3>
<ul>{''.join(summary_lines)}</ul>
<p>Generated from <code>scripts/generate_all_permutations.py</code></p>
</body></html>"""
msg.attach(MIMEText(body_html, "html"))
for filepath in batch:
with open(filepath, "rb") as f:
part = MIMEApplication(f.read(), Name=filepath.name)
part["Content-Disposition"] = f'attachment; filename="{filepath.name}"'
msg.attach(part)
try:
with smtplib.SMTP(SMTP_HOST, SMTP_PORT, timeout=30) as server:
server.ehlo()
server.starttls()
server.ehlo()
server.login(SMTP_USER, SMTP_PASS)
server.sendmail(FROM_EMAIL, [TO_EMAIL], msg.as_string())
LOG.info("Email batch %d/%d sent to %s (%d files)", batch_num, len(batches), TO_EMAIL, len(batch))
except Exception:
LOG.exception("Failed to send email batch %d to %s", batch_num, TO_EMAIL)
def main() -> None:
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
all_files: list[Path] = []
# 1. RMD Certification Letters (6 roles × 5 STIR/SHAKEN statuses = 30 DOCX)
LOG.info("=" * 60)
LOG.info("GENERATING RMD CERTIFICATION LETTERS")
LOG.info("=" * 60)
all_files.extend(generate_rmd_letters())
# 2. Exhibit A — Robocall Mitigation Program (6 roles = 6 DOCX)
LOG.info("=" * 60)
LOG.info("GENERATING EXHIBIT A DOCUMENTS")
LOG.info("=" * 60)
all_files.extend(generate_exhibit_a_docs())
# 3. CPNI Certification Letters (4 permutations)
LOG.info("=" * 60)
LOG.info("GENERATING CPNI CERTIFICATION LETTERS")
LOG.info("=" * 60)
all_files.extend(generate_cpni_letters())
# 4. FCC 499-A Filing Checklists (6 permutations)
LOG.info("=" * 60)
LOG.info("GENERATING 499-A CHECKLISTS")
LOG.info("=" * 60)
all_files.extend(generate_499a_checklists())
# 5. CRTC Notification Letters (2 permutations)
LOG.info("=" * 60)
LOG.info("GENERATING CRTC LETTERS")
LOG.info("=" * 60)
all_files.extend(generate_crtc_letters())
# 6. LLC Operating Agreements (2 permutations)
LOG.info("=" * 60)
LOG.info("GENERATING OPERATING AGREEMENTS")
LOG.info("=" * 60)
all_files.extend(generate_operating_agreements())
# Convert all DOCX to PDF
LOG.info("=" * 60)
LOG.info("CONVERTING DOCX → PDF")
LOG.info("=" * 60)
docx_files = [f for f in all_files if f.suffix == ".docx"]
for docx in docx_files:
pdf = _convert_to_pdf(docx)
if pdf:
all_files.append(pdf)
LOG.info("=" * 60)
LOG.info("TOTAL FILES GENERATED: %d", len(all_files))
LOG.info(" DOCX: %d", sum(1 for f in all_files if f.suffix == ".docx"))
LOG.info(" PDF: %d", sum(1 for f in all_files if f.suffix == ".pdf"))
LOG.info("=" * 60)
# Email everything
send_email(all_files)
LOG.info("Done. Output directory: %s", OUTPUT_DIR)
if __name__ == "__main__":
main()