Add terminate-only STIR/SHAKEN option across RMD pipeline

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

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

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

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

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

View file

@ -13,16 +13,18 @@
<label class="pw-field">STIR/SHAKEN implementation</label>
<select id="pw-ss-status" class="pw-input">
<option value="">Select…</option>
<option value="complete_implementation">Complete — I sign calls with my own cert</option>
<option value="partial_implementation">Partial — upstream carrier signs my traffic</option>
<option value="complete_implementation">Complete — I sign all outbound calls with my own STI certificate</option>
<option value="partial_implementation">Partial — my upstream carrier signs calls on my behalf</option>
<option value="terminate_only">Terminate only — I only receive pre-signed calls, I don't originate</option>
<option value="robocall_mitigation_only">Robocall Mitigation Only — no STIR/SHAKEN signing</option>
<option value="exempt_small_carrier">Exempt small carrier</option>
</select>
<p id="pw-ss-hint" class="pw-hint" hidden></p>
<label class="pw-field">STI-CA vendor preference (optional)</label>
<label class="pw-field" id="pw-ss-vendor-label">STI-CA vendor preference (optional)</label>
<input type="text" id="pw-ss-vendor" class="pw-input" placeholder="e.g. iconectiv, Peeringhub, Neustar (leave blank if unsure)" />
<label class="pw-field">Upstream voice provider (if partial / robocall-mitigation-only)</label>
<label class="pw-field" id="pw-ss-upstream-label">Upstream voice provider (if partial / robocall-mitigation-only)</label>
<input type="text" id="pw-ss-upstream" class="pw-input" placeholder="e.g. Bandwidth.com, VoIP Innovations" />
<div id="pw-ss-err" class="pw-err" hidden></div>
@ -33,17 +35,49 @@
.pw-help { color: #64748b; font-size: 0.9rem; margin-bottom: 1rem; }
.pw-field { display: block; font-weight: 600; margin: 0.8rem 0 0.2rem; font-size: 0.88rem; }
.pw-input { width: 100%; padding: 0.5rem 0.7rem; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 0.93rem; }
.pw-hint { color: #4b5563; font-size: 0.82rem; margin-top: 0.3rem; padding: 0.5rem 0.7rem; background: #f0f4f8; border-radius: 6px; line-height: 1.5; }
.pw-err { color: #b91c1c; margin-top: 0.75rem; font-size: 0.9rem; }
</style>
<script>
const g = <T extends HTMLElement>(id: string) => document.getElementById(id) as T;
const HINTS: Record<string, string> = {
complete_implementation: "You originate calls and sign them with your own STI certificate from an approved Certificate Authority.",
partial_implementation: "Your upstream carrier signs calls on your behalf. As of June 2025, you must still make all attestation-level decisions — your upstream only performs the technical act of signing.",
terminate_only: "You only receive and terminate pre-signed calls from other carriers. You verify incoming signatures (software config) but don't need your own signing certificate. Your RMD will be filed as \"partial implementation\" describing your verification process.",
robocall_mitigation_only: "You have a robocall mitigation program but no STIR/SHAKEN signing. This is typically for non-IP networks or providers awaiting STI certificate issuance.",
exempt_small_carrier: "Small carriers with fewer than 100,000 subscriber lines may qualify for a temporary exemption.",
};
function updateSSFields() {
const val = g<HTMLSelectElement>("pw-ss-status").value;
const hint = g<HTMLElement>("pw-ss-hint");
const vendorLabel = g<HTMLElement>("pw-ss-vendor-label");
const vendorInput = g<HTMLInputElement>("pw-ss-vendor");
const upstreamLabel = g<HTMLElement>("pw-ss-upstream-label");
const upstreamInput = g<HTMLInputElement>("pw-ss-upstream");
// Show hint
if (val && HINTS[val]) { hint.textContent = HINTS[val]; hint.hidden = false; }
else { hint.hidden = true; }
// Show/hide vendor (only for complete)
const showVendor = val === "complete_implementation";
vendorLabel.style.display = showVendor ? "" : "none";
vendorInput.style.display = showVendor ? "" : "none";
// Show/hide upstream (for partial and robocall-only)
const showUpstream = val === "partial_implementation" || val === "robocall_mitigation_only";
upstreamLabel.style.display = showUpstream ? "" : "none";
upstreamInput.style.display = showUpstream ? "" : "none";
}
g<HTMLSelectElement>("pw-ss-status").addEventListener("change", updateSSFields);
window.addEventListener("pw:step-shown", (evt: any) => {
if (evt.detail.step !== "stir_shaken") return;
const s = (window as any).PWIntake.get();
g<HTMLSelectElement>("pw-ss-status").value = s.intake_data?.target_stir_shaken_status || s.entity?.stir_shaken_status || "";
g<HTMLInputElement>("pw-ss-vendor").value = s.intake_data?.sti_ca_vendor || "";
g<HTMLInputElement>("pw-ss-upstream").value = s.intake_data?.upstream_provider_name || "";
updateSSFields();
});
window.addEventListener("pw:step-next", (evt: any) => {
const PW = (window as any).PWIntake;