new-site/site/public/portal/rmd-review/index.html
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

351 lines
20 KiB
HTML

<!DOCTYPE html><html lang="en"><head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Review and approve your RMD certification before FCC submission.">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<title>Review RMD Filing — Performance West</title>
<script>
window.__PW_API = (function() {
var h = window.location.hostname;
if (h === "localhost" || h === "127.0.0.1") return "http://" + h + ":3001";
if (h === "dev.performancewest.net") return "https://api.dev.performancewest.net";
return "https://api.performancewest.net";
})();
</script>
<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/_astro/about.DhmoKVOS.css">
<style>
.rw{max-width:680px;margin:0 auto;padding:2rem 1rem 4rem}
.rh{background:#1e3a5f;color:#fff;border-radius:12px;padding:1.75rem 1.5rem;margin-bottom:1.5rem}
.rh h1{margin:0 0 .3rem;font-size:1.4rem;font-weight:700}
.rh p{margin:0;opacity:.8;font-size:.875rem}
.card{background:#fff;border:1px solid #e2e8f0;border-radius:12px;padding:1.25rem 1.5rem;margin-bottom:1rem}
.card h2{font-size:.95rem;font-weight:700;color:#1e3a5f;margin:0 0 .75rem;display:flex;align-items:center;gap:.5rem}
.card h2 svg{width:18px;height:18px;color:#059669}
.fg{display:grid;grid-template-columns:1fr 1fr;gap:.75rem}
.fg.single{grid-template-columns:1fr}
.fl{display:block;font-size:.7rem;font-weight:600;color:#64748b;text-transform:uppercase;letter-spacing:.5px;margin-bottom:4px}
.fi{width:100%;border:1px solid #d1d5db;border-radius:6px;padding:8px 10px;font-size:13px;color:#111;outline:none;transition:border .15s}
.fi:focus{border-color:#1e3a5f;box-shadow:0 0 0 2px rgba(30,58,95,.15)}
select.fi{background:#fff}
.lb{background:#fefce8;border:1px solid #fde68a;border-radius:8px;padding:1rem;font-size:.8rem;color:#92400e;line-height:1.6}
.ab{width:100%;background:#059669;color:#fff;border:none;border-radius:10px;padding:.9rem;font-size:1rem;font-weight:700;cursor:pointer;transition:background .15s}
.ab:hover:not(:disabled){background:#047857}
.ab:disabled{opacity:.5;cursor:not-allowed}
.note{font-size:.7rem;color:#94a3b8;margin-top:2px}
</style>
</head>
<body class="min-h-screen flex flex-col bg-gray-50">
<nav class="border-b border-gray-200 bg-white sticky top-0 z-50">
<div class="max-w-6xl mx-auto px-4"><div class="flex justify-between h-16 items-center">
<a href="/" class="flex items-center"><img src="/images/logo.png" alt="Performance West" class="h-12 w-auto"></a>
</div></div>
</nav>
<main class="flex-1"><div class="rw">
<div id="loading" class="text-center py-16 text-gray-500">
<svg class="animate-spin h-6 w-6 mx-auto mb-3" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>
Loading your filing details...
</div>
<div id="error" class="hidden text-center py-16">
<p class="text-red-700 font-semibold" id="error-msg"></p>
</div>
<div id="main-ui" class="hidden">
<div class="rh">
<h1>Review Your RMD Certification</h1>
<p>Please verify and correct all details below. We will use this information to prepare your FCC filing.</p>
</div>
<!-- Entity -->
<div class="card">
<h2><svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 21h16.5M4.5 3h15M5.25 3v18m13.5-18v18M9 6.75h1.5m-1.5 3h1.5m-1.5 3h1.5m3-6H15m-1.5 3H15m-1.5 3H15M9 21v-3.375c0-.621.504-1.125 1.125-1.125h3.75c.621 0 1.125.504 1.125 1.125V21"/></svg>Entity Information</h2>
<div class="fg">
<div><label class="fl">Legal Name *</label><input type="text" class="fi" id="f-name" placeholder="Acme Telecom LLC"></div>
<div><label class="fl">DBA / Trade Name</label><input type="text" class="fi" id="f-dba" placeholder="Optional"></div>
<div><label class="fl">FRN *</label><input type="text" class="fi" id="f-frn" placeholder="0012345678" maxlength="10"></div>
<div><label class="fl">RMD Number</label><input type="text" class="fi" id="f-rmd-num" placeholder="RMD0001234 (if existing)"></div>
</div>
<div class="fg single" style="margin-top:.75rem">
<div><label class="fl">Principal Address *</label><input type="text" class="fi" id="f-address" placeholder="123 Main St, City, ST 12345"></div>
</div>
</div>
<!-- Classification -->
<div class="card">
<h2><svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M9.568 3H5.25A2.25 2.25 0 003 5.25v4.318c0 .597.237 1.17.659 1.591l9.581 9.581c.699.699 1.78.872 2.607.33a18.095 18.095 0 005.223-5.223c.542-.827.369-1.908-.33-2.607L11.16 3.66A2.25 2.25 0 009.568 3z"/></svg>Provider Classification</h2>
<div class="fg">
<div>
<label class="fl">Carrier Category *</label>
<select class="fi" id="f-carrier-cat">
<option value="">Select...</option>
<option value="interconnected_voip">Interconnected VoIP</option>
<option value="non_interconnected_voip">Non-Interconnected VoIP</option>
<option value="clec">CLEC</option>
<option value="ixc">IXC</option>
<option value="cmrs">CMRS (Wireless)</option>
<option value="other">Other</option>
</select>
</div>
<div>
<label class="fl">Infrastructure</label>
<select class="fi" id="f-infra">
<option value="facilities">Facilities-based</option>
<option value="reseller">Reseller</option>
<option value="hybrid">Hybrid</option>
</select>
</div>
</div>
<div class="fg" style="margin-top:.75rem">
<div><label class="fl">Wholesale provider?</label><select class="fi" id="f-wholesale"><option value="no">No</option><option value="yes">Yes</option></select></div>
<div><label class="fl">Gateway provider?</label><select class="fi" id="f-gateway"><option value="no">No</option><option value="yes">Yes</option></select></div>
</div>
</div>
<!-- STIR/SHAKEN -->
<div class="card">
<h2><svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z"/></svg>STIR/SHAKEN Implementation</h2>
<div class="fg">
<div>
<label class="fl">Status *</label>
<select class="fi" id="f-ss-status">
<option value="complete_implementation">Complete Implementation</option>
<option value="partial_implementation">Partial Implementation</option>
<option value="robocall_mitigation_only">Robocall Mitigation Only</option>
<option value="exempt_small_carrier">Exempt (Small Carrier)</option>
<option value="not_applicable">Not Applicable</option>
</select>
</div>
<div><label class="fl">Certificate Authority</label><input type="text" class="fi" id="f-ss-ca" placeholder="e.g. TransNexus, Neustar"></div>
</div>
<div class="fg single" style="margin-top:.75rem">
<div><label class="fl">Upstream Provider (if partial/mitigation only)</label><input type="text" class="fi" id="f-ss-upstream" placeholder="Provider name"></div>
</div>
</div>
<!-- Contact -->
<div class="card">
<h2><svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z"/></svg>Contact &amp; Certifying Officer</h2>
<div class="fg">
<div><label class="fl">Contact Name *</label><input type="text" class="fi" id="f-contact-name" placeholder="Jane Doe"></div>
<div><label class="fl">Contact Email *</label><input type="email" class="fi" id="f-contact-email" placeholder="jane@company.com"></div>
<div><label class="fl">Contact Phone</label><input type="tel" class="fi" id="f-contact-phone" placeholder="(555) 123-4567"></div>
<div><label class="fl">Contact Title</label><input type="text" class="fi" id="f-contact-title" placeholder="VP Regulatory"></div>
</div>
<div class="fg" style="margin-top:.75rem">
<div><label class="fl">Certifying Officer Name *</label><input type="text" class="fi" id="f-officer-name" placeholder="CEO / President name"></div>
<div><label class="fl">Certifying Officer Title *</label><input type="text" class="fi" id="f-officer-title" placeholder="Chief Executive Officer"></div>
</div>
<p class="note">The certifying officer signs the RMD filing under penalty of perjury (47 CFR &sect; 1.16).</p>
</div>
<!-- Step 1: Preview -->
<div class="card" id="preview-card">
<h2><svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z"/></svg>Preview Your Filing</h2>
<p style="font-size:.85rem;color:#64748b;margin-bottom:1rem">Click below to generate a preview of your RMD certification letter based on the information you provided. Review it carefully before approving.</p>
<button type="button" class="ab" id="preview-btn" style="background:#1e3a5f">Generate Preview</button>
<p id="preview-status" style="font-size:.85rem;margin-top:.5rem;text-align:center;color:#64748b"></p>
<div id="pdf-viewer" style="display:none;margin-top:1rem">
<iframe id="pdf-frame" style="width:100%;height:600px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc"></iframe>
</div>
</div>
<!-- Step 2: Approve (shown after preview) -->
<div class="card" id="approve-card" style="display:none">
<h2>Authorization</h2>
<div class="lb" id="legal-text"></div>
<div style="margin-top:1rem;display:flex;gap:.75rem;align-items:flex-start;padding:1rem;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;font-size:.875rem">
<input type="checkbox" id="agree-chk" style="margin-top:2px;width:18px;height:18px;flex-shrink:0">
<label for="agree-chk" style="color:#374151;line-height:1.5">
I have reviewed the preview above and confirm that the information is true, complete, and accurate.
I authorize Performance West Inc. to submit this RMD certification to the FCC on my behalf.
I understand that the 47 CFR &sect; 1.16 declaration under penalty of perjury will be made
through the FCC electronic filing portal at the time of submission.
</label>
</div>
<p id="status-msg" style="font-size:.875rem;margin-top:.75rem;min-height:1rem;text-align:center"></p>
<button class="ab" id="approve-btn" disabled>Approve &amp; Authorize Filing</button>
</div>
</div>
<div id="success" class="hidden text-center py-16">
<div style="width:56px;height:56px;background:#dcfce7;border-radius:50%;display:flex;align-items:center;justify-content:center;margin:0 auto 1rem">
<svg width="28" height="28" fill="none" stroke="#16a34a" stroke-width="2.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path></svg>
</div>
<h2 class="text-xl font-bold text-gray-900 mb-2">Filing Approved</h2>
<p class="text-sm text-gray-600 max-w-md mx-auto">Your RMD certification has been approved and will be submitted to the FCC shortly. You will receive an email with the confirmation number once filed.</p>
</div>
</div></main>
<footer class="border-t border-gray-200 bg-white mt-auto py-6">
<div class="max-w-6xl mx-auto px-4 text-center">
<img src="/images/logo.png" alt="Performance West" class="h-8 w-auto mx-auto mb-2 opacity-50">
<p class="text-xs text-gray-500">&copy; 2026 Performance West Inc. &middot; 525 Randall Ave Ste 100-1195, Cheyenne, WY 82001</p>
</div>
</footer>
<script>
(function() {
var API = window.__PW_API;
var token = new URLSearchParams(window.location.search).get("token");
if (!token) {
document.getElementById("loading").classList.add("hidden");
document.getElementById("error").classList.remove("hidden");
document.getElementById("error-msg").textContent = "No authentication token. Please use the link from your email.";
return;
}
document.cookie = "pw_portal_token=" + token + ";path=/;max-age=259200;SameSite=Lax";
var headers = {"Authorization": "Bearer " + token, "Content-Type": "application/json"};
fetch(API + "/api/v1/portal/rmd-review", {headers: headers})
.then(function(r) { return r.json().then(function(d) { if (!r.ok) throw new Error(d.error || "Failed"); return d; }); })
.then(function(data) {
document.getElementById("loading").classList.add("hidden");
if (data.review_status === "approved") {
document.getElementById("success").classList.remove("hidden");
return;
}
document.getElementById("main-ui").classList.remove("hidden");
var e = data.entity || {};
var cl = data.classification || {};
var ss = data.stir_shaken || {};
var ct = data.contact || {};
var co = data.certifying_officer || {};
// Prefill all fields
document.getElementById("f-name").value = e.legal_name || "";
document.getElementById("f-dba").value = e.dba_name || "";
document.getElementById("f-frn").value = e.frn || (data.intake_frn || "");
document.getElementById("f-rmd-num").value = e.rmd_number || "";
document.getElementById("f-address").value = e.address || "";
if (cl.carrier_category) document.getElementById("f-carrier-cat").value = cl.carrier_category;
if (cl.infra_type) document.getElementById("f-infra").value = cl.infra_type;
if (cl.is_wholesale) document.getElementById("f-wholesale").value = "yes";
if (cl.gateway_provider) document.getElementById("f-gateway").value = "yes";
if (ss.status) document.getElementById("f-ss-status").value = ss.status;
document.getElementById("f-ss-ca").value = ss.cert_authority || "";
document.getElementById("f-ss-upstream").value = ss.upstream_provider || "";
document.getElementById("f-contact-name").value = ct.name || "";
document.getElementById("f-contact-email").value = ct.email || "";
document.getElementById("f-contact-phone").value = ct.phone || "";
document.getElementById("f-contact-title").value = ct.title || "";
document.getElementById("f-officer-name").value = co.name || "";
document.getElementById("f-officer-title").value = co.title || "Chief Executive Officer";
document.getElementById("legal-text").textContent = data.legal_notice || "";
// Preview button handler
document.getElementById("preview-btn").addEventListener("click", function() {
var previewBtn = document.getElementById("preview-btn");
var previewStatus = document.getElementById("preview-status");
previewBtn.disabled = true;
previewBtn.textContent = "Generating preview...";
previewStatus.textContent = "This may take 15-30 seconds. Please wait.";
var corrections = getCorrections();
fetch(API + "/api/v1/portal/rmd-preview", {
method: "POST",
headers: headers,
body: JSON.stringify({corrections: corrections}),
})
.then(function(r) { return r.json(); })
.then(function(d) {
if (d.pdf_url) {
document.getElementById("pdf-viewer").style.display = "block";
document.getElementById("pdf-frame").src = d.pdf_url;
previewStatus.textContent = "Preview generated. Review the document below, then approve.";
previewStatus.style.color = "#059669";
previewBtn.textContent = "Regenerate Preview";
previewBtn.disabled = false;
// Show the approve card
document.getElementById("approve-card").style.display = "block";
// Scroll to PDF
document.getElementById("pdf-viewer").scrollIntoView({behavior: "smooth"});
} else {
previewStatus.textContent = d.error || "Could not generate preview.";
previewStatus.style.color = "#dc2626";
previewBtn.textContent = "Try Again";
previewBtn.disabled = false;
}
})
.catch(function(err) {
previewStatus.textContent = err.message || "Preview failed.";
previewStatus.style.color = "#dc2626";
previewBtn.textContent = "Try Again";
previewBtn.disabled = false;
});
});
// Checkbox enables approve button
var chk = document.getElementById("agree-chk");
var btn = document.getElementById("approve-btn");
chk.addEventListener("change", function() { btn.disabled = !chk.checked; });
function getCorrections() {
return {
legal_name: document.getElementById("f-name").value.trim(),
dba_name: document.getElementById("f-dba").value.trim(),
frn: document.getElementById("f-frn").value.trim(),
rmd_number: document.getElementById("f-rmd-num").value.trim(),
address: document.getElementById("f-address").value.trim(),
carrier_category: document.getElementById("f-carrier-cat").value,
infra_type: document.getElementById("f-infra").value,
is_wholesale: document.getElementById("f-wholesale").value === "yes",
is_gateway_provider: document.getElementById("f-gateway").value === "yes",
stir_shaken_status: document.getElementById("f-ss-status").value,
stir_shaken_cert_authority: document.getElementById("f-ss-ca").value.trim(),
upstream_provider: document.getElementById("f-ss-upstream").value.trim(),
contact_name: document.getElementById("f-contact-name").value.trim(),
contact_email: document.getElementById("f-contact-email").value.trim(),
contact_phone: document.getElementById("f-contact-phone").value.trim(),
contact_title: document.getElementById("f-contact-title").value.trim(),
ceo_name: document.getElementById("f-officer-name").value.trim(),
ceo_title: document.getElementById("f-officer-title").value.trim(),
};
}
// Approve + submit corrections
btn.addEventListener("click", function() {
btn.disabled = true;
btn.textContent = "Submitting...";
document.getElementById("status-msg").textContent = "";
var corrections = getCorrections();
fetch(API + "/api/v1/portal/rmd-approve", {
method: "POST",
headers: headers,
body: JSON.stringify({corrections: corrections}),
})
.then(function(r) { return r.json(); })
.then(function(d) {
if (d.status === "approved" || d.status === "already_approved") {
document.getElementById("main-ui").classList.add("hidden");
document.getElementById("success").classList.remove("hidden");
} else {
document.getElementById("status-msg").textContent = d.error || "Something went wrong.";
document.getElementById("status-msg").style.color = "#dc2626";
btn.disabled = false;
btn.textContent = "Approve & Authorize Filing";
}
})
.catch(function(err) {
document.getElementById("status-msg").textContent = err.message;
document.getElementById("status-msg").style.color = "#dc2626";
btn.disabled = false;
btn.textContent = "Approve & Authorize Filing";
});
});
})
.catch(function(err) {
document.getElementById("loading").classList.add("hidden");
document.getElementById("error").classList.remove("hidden");
document.getElementById("error-msg").textContent = err.message || "Could not load filing details.";
});
})();
</script>
</body></html>