From 695c3e24317bc1f263b0433e66a51c004d744578 Mon Sep 17 00:00:00 2001 From: justin Date: Sat, 6 Jun 2026 00:49:21 -0500 Subject: [PATCH 001/314] security: drop all CBC TLS suites (Qualys WEAK -> AEAD-only, still A+); sync ansible nginx templates (ciphers + ywxi CSP); capture host firewall as IaC --- docs/vm-security-hardening.md | 12 ++++ .../nginx/templates/pw-analytics-tls.conf.j2 | 2 +- .../roles/nginx/templates/pw-api-tls.conf.j2 | 2 +- .../nginx/templates/pw-btcpay-tls.conf.j2 | 2 +- .../nginx/templates/pw-crypto-tls.conf.j2 | 2 +- .../nginx/templates/pw-dev-api-tls.conf.j2 | 2 +- .../roles/nginx/templates/pw-dev-tls.conf.j2 | 2 +- .../nginx/templates/pw-listmonk-tls.conf.j2 | 2 +- .../nginx/templates/pw-minio-tls.conf.j2 | 4 +- .../nginx/templates/pw-monitoring-tls.conf.j2 | 2 +- .../nginx/templates/pw-portal-tls.conf.j2 | 2 +- .../roles/nginx/templates/pw-security.conf.j2 | 3 + .../roles/nginx/templates/pw-site-tls.conf.j2 | 2 +- infra/firewall/README.md | 39 +++++++++++++ infra/firewall/pw-docker-fw.sh | 26 +++++++++ infra/firewall/pw-firewall.nft | 55 +++++++++++++++++++ infra/firewall/pw-firewall.service | 15 +++++ 17 files changed, 162 insertions(+), 12 deletions(-) create mode 100644 infra/firewall/README.md create mode 100644 infra/firewall/pw-docker-fw.sh create mode 100644 infra/firewall/pw-firewall.nft create mode 100644 infra/firewall/pw-firewall.service diff --git a/docs/vm-security-hardening.md b/docs/vm-security-hardening.md index da0503d..e3952e4 100644 --- a/docs/vm-security-hardening.md +++ b/docs/vm-security-hardening.md @@ -86,3 +86,15 @@ backups moved to `/etc/nginx/backups/` (NOT in an include path). - **Hosted in a SOC 2 Type II compliant data center** TODO: TrustedSite (ex-McAfee SECURE) free tier needs a signup to get the daily-scan trustmark image - add later if an image seal is wanted. + +### TLS cipher: removed all CBC suites (2026-06-06) +Qualys flagged the two remaining CBC suites as WEAK: +`TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384` (0xc024) and +`TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256` (0xc023). CBC modes carry the historic +padding-oracle risk; every modern client supports AEAD, so they were dropped. +Final cipher list = AEAD only: GCM (AES-128/256) + CHACHA20-POLY1305 (TLS 1.2) +plus TLS 1.3 suites. Verified: CBC no longer negotiates, GCM/TLS1.3 work, site +200, **Qualys A+ with WEAK suites: NONE**. The cipher list + the cdn.ywxi.net CSP +addition are now in the ansible templates (`infra/ansible/roles/nginx/templates/`) +so they don't drift on the next ansible run. Firewall captured as IaC in +`infra/firewall/`. diff --git a/infra/ansible/roles/nginx/templates/pw-analytics-tls.conf.j2 b/infra/ansible/roles/nginx/templates/pw-analytics-tls.conf.j2 index ad96650..2c2e53b 100644 --- a/infra/ansible/roles/nginx/templates/pw-analytics-tls.conf.j2 +++ b/infra/ansible/roles/nginx/templates/pw-analytics-tls.conf.j2 @@ -24,7 +24,7 @@ server { ssl_certificate /etc/letsencrypt/live/analytics.performancewest.net/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/analytics.performancewest.net/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; diff --git a/infra/ansible/roles/nginx/templates/pw-api-tls.conf.j2 b/infra/ansible/roles/nginx/templates/pw-api-tls.conf.j2 index ca9f21a..cb8bd6b 100644 --- a/infra/ansible/roles/nginx/templates/pw-api-tls.conf.j2 +++ b/infra/ansible/roles/nginx/templates/pw-api-tls.conf.j2 @@ -27,7 +27,7 @@ server { ssl_certificate /etc/letsencrypt/live/api.performancewest.net/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.performancewest.net/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; diff --git a/infra/ansible/roles/nginx/templates/pw-btcpay-tls.conf.j2 b/infra/ansible/roles/nginx/templates/pw-btcpay-tls.conf.j2 index a6e51d3..2b66f48 100644 --- a/infra/ansible/roles/nginx/templates/pw-btcpay-tls.conf.j2 +++ b/infra/ansible/roles/nginx/templates/pw-btcpay-tls.conf.j2 @@ -9,7 +9,7 @@ server { ssl_certificate /etc/letsencrypt/live/{{ shkeeper_domain }}/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/{{ shkeeper_domain }}/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; diff --git a/infra/ansible/roles/nginx/templates/pw-crypto-tls.conf.j2 b/infra/ansible/roles/nginx/templates/pw-crypto-tls.conf.j2 index a98bdf1..5831111 100644 --- a/infra/ansible/roles/nginx/templates/pw-crypto-tls.conf.j2 +++ b/infra/ansible/roles/nginx/templates/pw-crypto-tls.conf.j2 @@ -9,7 +9,7 @@ server { ssl_certificate /etc/letsencrypt/live/{{ shkeeper_admin_domain }}/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/{{ shkeeper_admin_domain }}/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; diff --git a/infra/ansible/roles/nginx/templates/pw-dev-api-tls.conf.j2 b/infra/ansible/roles/nginx/templates/pw-dev-api-tls.conf.j2 index d193ae3..c6beb88 100644 --- a/infra/ansible/roles/nginx/templates/pw-dev-api-tls.conf.j2 +++ b/infra/ansible/roles/nginx/templates/pw-dev-api-tls.conf.j2 @@ -16,7 +16,7 @@ server { ssl_certificate /etc/letsencrypt/live/{{ dev_api_domain }}/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/{{ dev_api_domain }}/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; diff --git a/infra/ansible/roles/nginx/templates/pw-dev-tls.conf.j2 b/infra/ansible/roles/nginx/templates/pw-dev-tls.conf.j2 index 61dadd0..41bd1ee 100644 --- a/infra/ansible/roles/nginx/templates/pw-dev-tls.conf.j2 +++ b/infra/ansible/roles/nginx/templates/pw-dev-tls.conf.j2 @@ -17,7 +17,7 @@ server { ssl_certificate /etc/letsencrypt/live/{{ dev_domain }}/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/{{ dev_domain }}/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; diff --git a/infra/ansible/roles/nginx/templates/pw-listmonk-tls.conf.j2 b/infra/ansible/roles/nginx/templates/pw-listmonk-tls.conf.j2 index 6af5b65..0c8c060 100644 --- a/infra/ansible/roles/nginx/templates/pw-listmonk-tls.conf.j2 +++ b/infra/ansible/roles/nginx/templates/pw-listmonk-tls.conf.j2 @@ -16,7 +16,7 @@ server { ssl_certificate /etc/letsencrypt/live/{{ listmonk_domain }}/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/{{ listmonk_domain }}/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; diff --git a/infra/ansible/roles/nginx/templates/pw-minio-tls.conf.j2 b/infra/ansible/roles/nginx/templates/pw-minio-tls.conf.j2 index 264f06e..343e36a 100644 --- a/infra/ansible/roles/nginx/templates/pw-minio-tls.conf.j2 +++ b/infra/ansible/roles/nginx/templates/pw-minio-tls.conf.j2 @@ -13,7 +13,7 @@ server { ssl_certificate /etc/letsencrypt/live/{{ minio_domain }}/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/{{ minio_domain }}/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; @@ -59,7 +59,7 @@ server { ssl_certificate /etc/letsencrypt/live/{{ minio_console_domain }}/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/{{ minio_console_domain }}/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; diff --git a/infra/ansible/roles/nginx/templates/pw-monitoring-tls.conf.j2 b/infra/ansible/roles/nginx/templates/pw-monitoring-tls.conf.j2 index c4078d5..2d87b29 100644 --- a/infra/ansible/roles/nginx/templates/pw-monitoring-tls.conf.j2 +++ b/infra/ansible/roles/nginx/templates/pw-monitoring-tls.conf.j2 @@ -24,7 +24,7 @@ server { ssl_certificate /etc/letsencrypt/live/monitoring.performancewest.net/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/monitoring.performancewest.net/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; diff --git a/infra/ansible/roles/nginx/templates/pw-portal-tls.conf.j2 b/infra/ansible/roles/nginx/templates/pw-portal-tls.conf.j2 index 67c285e..80a523c 100644 --- a/infra/ansible/roles/nginx/templates/pw-portal-tls.conf.j2 +++ b/infra/ansible/roles/nginx/templates/pw-portal-tls.conf.j2 @@ -16,7 +16,7 @@ server { ssl_certificate /etc/letsencrypt/live/{{ portal_domain }}/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/{{ portal_domain }}/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_session_cache shared:SSL:10m; add_header Strict-Transport-Security "max-age=31536000" always; diff --git a/infra/ansible/roles/nginx/templates/pw-security.conf.j2 b/infra/ansible/roles/nginx/templates/pw-security.conf.j2 index 7e4c2cb..aad67e7 100644 --- a/infra/ansible/roles/nginx/templates/pw-security.conf.j2 +++ b/infra/ansible/roles/nginx/templates/pw-security.conf.j2 @@ -8,6 +8,9 @@ add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header X-XSS-Protection "1; mode=block" always; add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; +# Content Security Policy +add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://js.stripe.com https://cdn.ywxi.net https://analytics.performancewest.net https://embed.tawk.to https://*.tawk.to; style-src 'self' 'unsafe-inline' https://*.tawk.to https://fonts.googleapis.com; img-src 'self' data: https: blob:; font-src 'self' data: https://*.tawk.to https://fonts.gstatic.com; connect-src 'self' https://api.performancewest.net https://api.dev.performancewest.net https://api.stripe.com https://analytics.performancewest.net https://*.tawk.to wss://*.tawk.to; frame-src https://js.stripe.com https://hooks.stripe.com https://cdn.ywxi.net https://*.tawk.to; object-src 'none'; base-uri 'self'; form-action 'self' https://checkout.stripe.com; upgrade-insecure-requests;" always; + # Block common attack paths location ~* \.(php|asp|aspx|cgi|pl)$ { return 444; diff --git a/infra/ansible/roles/nginx/templates/pw-site-tls.conf.j2 b/infra/ansible/roles/nginx/templates/pw-site-tls.conf.j2 index 9a4a440..2322116 100644 --- a/infra/ansible/roles/nginx/templates/pw-site-tls.conf.j2 +++ b/infra/ansible/roles/nginx/templates/pw-site-tls.conf.j2 @@ -36,7 +36,7 @@ server { ssl_certificate /etc/letsencrypt/live/performancewest.net/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/performancewest.net/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; + ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; diff --git a/infra/firewall/README.md b/infra/firewall/README.md new file mode 100644 index 0000000..9db91dc --- /dev/null +++ b/infra/firewall/README.md @@ -0,0 +1,39 @@ +# Host firewall (Infrastructure as Code) + +Canonical copies of the prod app-host firewall (see `docs/vm-security-hardening.md` +for the full rationale). These are the source of truth; the live host should +match. Installed as a boot-enabled systemd service. + +## Files +- `pw-firewall.nft` -> `/etc/pw-firewall/pw-firewall.nft` + nftables `inet pw_fw` table (input hook, priority -150). Public allow-list + `{22, 22022, 80, 443}`, a `trusted_admin` set allow-listing git/forgejo (3022), + internal subnets + loopback fully trusted, everything else on `ens18` dropped. +- `pw-docker-fw.sh` -> `/usr/local/sbin/pw-docker-fw.sh` + Adds DOCKER-USER rules so external (ens18) NEW inbound to Docker-published + container ports is dropped (postgres/listmonk/api/forgejo were accidentally + on 0.0.0.0); trusted_admin IPs are allow-listed to forgejo first. +- `pw-firewall.service` -> `/etc/systemd/system/pw-firewall.service` + Applies both at boot (After=docker). Also re-applied on docker restart via + `/etc/systemd/system/docker.service.d/pw-firewall.conf` (ExecStartPost). + +## Install / update on the host +``` +sudo install -D -m 0644 pw-firewall.nft /etc/pw-firewall/pw-firewall.nft +sudo install -D -m 0755 pw-docker-fw.sh /usr/local/sbin/pw-docker-fw.sh +sudo install -D -m 0644 pw-firewall.service /etc/systemd/system/pw-firewall.service +sudo systemctl daemon-reload +sudo systemctl enable --now pw-firewall.service +``` + +## Add / remove a trusted admin IP (for git push over :3022) +``` +sudo nft add element inet pw_fw trusted_admin { } # live +# then add to TRUSTED_ADMIN in pw-docker-fw.sh + the set in pw-firewall.nft +# and re-run: sudo systemctl restart pw-firewall.service +``` + +## Safety +Roll out with an auto-rollback timer (`setsid sh -c 'sleep 300; nft delete table +inet pw_fw; iptables -F DOCKER-USER; ...'`) so a bad rule can't lock you out; +cancel it only after verifying SSH + git still work from off-network. diff --git a/infra/firewall/pw-docker-fw.sh b/infra/firewall/pw-docker-fw.sh new file mode 100644 index 0000000..fd62d66 --- /dev/null +++ b/infra/firewall/pw-docker-fw.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Block external (internet) access to Docker-published container ports. +# Host nginx reaches containers over loopback (127.0.0.1), so dropping NEW +# inbound from the public uplink (ens18) into the Docker FORWARD path closes +# the accidental 0.0.0.0 exposure (postgres 5432, forgejo 3022, listmonk +# 9100/9101, api 3001/3002, etc.) without breaking nginx->container or +# container->container/internet traffic. +set -euo pipefail +UPLINK=ens18 + +# Trusted admin source IPs allowed to reach the forgejo container (host :3022 +# DNATs to 172.18.0.2:22, so the post-DNAT dport is 22). Keep in sync with the +# nft 'trusted_admin' set in /etc/pw-firewall/pw-firewall.nft. +TRUSTED_ADMIN="76.228.206.147" + +# Rebuild DOCKER-USER deterministically. +iptables -F DOCKER-USER 2>/dev/null || true +iptables -A DOCKER-USER -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN +# Allow trusted admins to git/forgejo (post-DNAT dport 22) before the drop. +for ip in $TRUSTED_ADMIN; do + iptables -A DOCKER-USER -i "$UPLINK" -s "$ip" -p tcp --dport 22 -j RETURN +done +iptables -A DOCKER-USER -i "$UPLINK" -m conntrack --ctstate NEW,INVALID -j DROP +iptables -A DOCKER-USER -j RETURN +echo "DOCKER-USER rules:" +iptables -L DOCKER-USER -n -v --line-numbers diff --git a/infra/firewall/pw-firewall.nft b/infra/firewall/pw-firewall.nft new file mode 100644 index 0000000..f7b9338 --- /dev/null +++ b/infra/firewall/pw-firewall.nft @@ -0,0 +1,55 @@ +#!/usr/sbin/nft -f +# Performance West host firewall. +# Goal: expose ONLY public-facing ports to the internet; keep all container / +# k3s / loopback traffic fully open so nothing internal breaks. +# +# Dedicated table (pw_fw) with a high-priority (-150) input hook so it is +# evaluated BEFORE kube-router's ACCEPT chain in the standard 'filter' table. +# fail2ban (f2b-table) stays untouched. + +table inet pw_fw +delete table inet pw_fw + +table inet pw_fw { + set pub_tcp { + type inet_service + # Public-facing ports only. + elements = { 22, 22022, 80, 443 } + # NB: 22 kept too in case provider/console uses it; SSH is on 22022. + } + + # Trusted admin source IPs allowed to reach git/forgejo (3022) and other + # non-public admin ports. Update with: nft add element inet pw_fw trusted_admin { } + set trusted_admin { + type ipv4_addr + flags interval + elements = { 76.228.206.147 } + } + + chain input { + type filter hook input priority -150; policy accept; + + # 1) Always allow loopback + already-established flows. + iif "lo" accept + ct state established,related accept + ct state invalid drop + + # 2) Fully trust internal networks (docker bridges, flannel pod/service, + # cni0). Containers and k3s must keep talking unrestricted. + ip saddr { 127.0.0.0/8, 172.16.0.0/12, 10.42.0.0/16, 10.43.0.0/16 } accept + iifname { "docker0", "br-*", "cni0", "flannel.1", "kube-*", "veth*", "cilium*" } accept + + # 3) Allow ICMP (ping / path MTU) - safe and useful for diagnostics. + ip protocol icmp accept + ip6 nexthdr icmpv6 accept + + # 4) Trusted-admin allow-list for git/forgejo SSH (3022). + ip saddr @trusted_admin tcp dport 3022 accept + + # 5) Public allow-list (new inbound from the internet). + tcp dport @pub_tcp accept + + # 6) Everything else arriving on the public uplink is dropped. + iifname "ens18" drop + } +} diff --git a/infra/firewall/pw-firewall.service b/infra/firewall/pw-firewall.service new file mode 100644 index 0000000..08f7a12 --- /dev/null +++ b/infra/firewall/pw-firewall.service @@ -0,0 +1,15 @@ +[Unit] +Description=Performance West host firewall (nft input + DOCKER-USER egress-only) +After=docker.service nftables.service network-online.target +Wants=network-online.target +Requires=docker.service + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/sbin/nft -f /etc/pw-firewall/pw-firewall.nft +ExecStart=/usr/local/sbin/pw-docker-fw.sh +ExecReload=/usr/sbin/nft -f /etc/pw-firewall/pw-firewall.nft + +[Install] +WantedBy=multi-user.target From 9bcd27db800050eb3b8df6a9ae1c607f12902b71 Mon Sep 17 00:00:00 2001 From: justin Date: Sat, 6 Jun 2026 01:52:22 -0500 Subject: [PATCH 002/314] feat(site): vertical-specific order-page headers (trucking/telecom/healthcare/corporate) via unified VerticalOrderHeader; apply to all 49 order pages; retire TruckingOrderHeader --- scripts/inject_order_headers.py | 104 ++++++++++++ site/src/components/TruckingOrderHeader.astro | 124 -------------- site/src/components/VerticalOrderHeader.astro | 159 ++++++++++++++++++ site/src/pages/order/bdc-broadband.astro | 2 + site/src/pages/order/bdc-filing.astro | 2 + site/src/pages/order/bdc-voice.astro | 2 + site/src/pages/order/boc3-filing.astro | 5 +- site/src/pages/order/ca-mcp-carb.astro | 5 +- site/src/pages/order/calea-ssi.astro | 2 + site/src/pages/order/cdr-analysis.astro | 2 + .../pages/order/cores-frn-registration.astro | 2 + site/src/pages/order/cpni-certification.astro | 2 + site/src/pages/order/ct-highway-use-fee.astro | 5 +- site/src/pages/order/dc-agent.astro | 2 + site/src/pages/order/dot-audit-prep.astro | 5 +- site/src/pages/order/dot-drug-alcohol.astro | 5 +- .../src/pages/order/dot-full-compliance.astro | 5 +- site/src/pages/order/dot-registration.astro | 5 +- site/src/pages/order/fcc-499-initial.astro | 2 + site/src/pages/order/fcc-499a-499q.astro | 2 + site/src/pages/order/fcc-499a.astro | 2 + .../pages/order/fcc-63-11-notification.astro | 2 + .../pages/order/fcc-compliance-checkup.astro | 2 + .../src/pages/order/fcc-full-compliance.astro | 2 + .../pages/order/foreign-qualification.astro | 2 + site/src/pages/order/hazmat-phmsa.astro | 5 +- site/src/pages/order/ifta-application.astro | 5 +- site/src/pages/order/ifta-quarterly.astro | 5 +- .../pages/order/intrastate-authority.astro | 5 +- site/src/pages/order/irp-registration.astro | 5 +- .../src/pages/order/ky-kyu-registration.astro | 5 +- site/src/pages/order/mc-authority.astro | 5 +- site/src/pages/order/mcs150-update.astro | 5 +- .../src/pages/order/medicare-enrollment.astro | 2 + site/src/pages/order/new-carrier-bundle.astro | 5 +- site/src/pages/order/nm-weight-distance.astro | 5 +- site/src/pages/order/npi-reactivation.astro | 2 + site/src/pages/order/npi-revalidation.astro | 2 + site/src/pages/order/nppes-update.astro | 2 + .../src/pages/order/ny-hut-registration.astro | 5 +- site/src/pages/order/ocn-registration.astro | 2 + site/src/pages/order/oig-sam-screening.astro | 2 + site/src/pages/order/or-weight-mile-tax.astro | 5 +- site/src/pages/order/osow-permit.astro | 5 +- .../order/provider-compliance-bundle.astro | 2 + site/src/pages/order/rmd-filing.astro | 2 + .../pages/order/state-dot-registration.astro | 5 +- site/src/pages/order/state-emissions.astro | 5 +- .../pages/order/state-trucking-bundle.astro | 5 +- site/src/pages/order/stir-shaken.astro | 2 + site/src/pages/order/ucr-registration.astro | 5 +- site/src/pages/order/usdot-reactivation.astro | 5 +- 52 files changed, 386 insertions(+), 174 deletions(-) create mode 100644 scripts/inject_order_headers.py delete mode 100644 site/src/components/TruckingOrderHeader.astro create mode 100644 site/src/components/VerticalOrderHeader.astro diff --git a/scripts/inject_order_headers.py b/scripts/inject_order_headers.py new file mode 100644 index 0000000..145f265 --- /dev/null +++ b/scripts/inject_order_headers.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +"""Inject the vertical-specific into every order page. + +Single source of truth for slug -> vertical. Idempotent: re-running it +normalizes import + placement and migrates the legacy to +. + +Placement: immediately after the closing of the page's title block +(the same spot the trucking header used), or as the first child of
/the +top wrapper if no obvious anchor is found. +""" +import os, re, sys + +ORDER_DIR = os.path.join(os.path.dirname(__file__), "..", "site", "src", "pages", "order") + +# slug -> vertical. Anything not listed defaults to "trucking" (the original set). +VERTICAL = { + # ── Telecom / FCC ───────────────────────────────────────────── + "bdc-broadband": "telecom", "bdc-filing": "telecom", "bdc-voice": "telecom", + "calea-ssi": "telecom", "cdr-analysis": "telecom", + "cores-frn-registration": "telecom", "cpni-certification": "telecom", + "fcc-499a": "telecom", "fcc-499a-499q": "telecom", "fcc-499-initial": "telecom", + "fcc-63-11-notification": "telecom", "fcc-compliance-checkup": "telecom", + "fcc-full-compliance": "telecom", "ocn-registration": "telecom", + "stir-shaken": "telecom", + # ── Healthcare ──────────────────────────────────────────────── + "medicare-enrollment": "healthcare", "npi-reactivation": "healthcare", + "npi-revalidation": "healthcare", "nppes-update": "healthcare", + "oig-sam-screening": "healthcare", "provider-compliance-bundle": "healthcare", + "rmd-filing": "healthcare", + # ── Corporate ───────────────────────────────────────────────── + "dc-agent": "corporate", "foreign-qualification": "corporate", +} + +IMPORT_LINE = 'import VerticalOrderHeader from "../../components/VerticalOrderHeader.astro";' +LEGACY_IMPORT_RE = re.compile(r'^\s*import\s+TruckingOrderHeader\s+from\s+["\'][^"\']+["\'];\s*$', re.M) +NEW_IMPORT_RE = re.compile(r'^\s*import\s+VerticalOrderHeader\s+from\s+["\'][^"\']+["\'];\s*$', re.M) + + +def vertical_for(slug: str) -> str: + return VERTICAL.get(slug, "trucking") + + +def process(path: str) -> str: + slug = os.path.basename(path)[:-len(".astro")] + v = vertical_for(slug) + src = open(path).read() + tag = f'' + + # 1) Imports: ensure VerticalOrderHeader import, drop the legacy one. + src = LEGACY_IMPORT_RE.sub("", src) + if not NEW_IMPORT_RE.search(src): + # insert after the Base import (first import line in frontmatter) + m = re.search(r'^(import\s+Base\s+from[^\n]*\n)', src, re.M) + if m: + src = src[:m.end()] + IMPORT_LINE + "\n" + src[m.end():] + else: + # fallback: after frontmatter opening --- + src = re.sub(r'^---\n', "---\n" + IMPORT_LINE + "\n", src, count=1) + + # 2) Replace any legacy header usage with the new one. + src = re.sub(r'', tag, src) + + # 3) If the new tag isn't placed yet, insert it after the first + # in the body (the title block) — matching the trucking convention. + if tag not in src: + m = re.search(r'\s*\n', src) + if m: + src = src[:m.end()] + "\n " + tag + "\n" + src[m.end():] + else: + # last resort: right after
or the first wrapper div + m = re.search(r'(]*>\s*\n)', src) + if m: + src = src[:m.end()] + " " + tag + "\n" + src[m.end():] + else: + print(f" WARN: no anchor in {slug}, skipped placement", file=sys.stderr) + + # tidy: collapse 3+ blank lines created by import removal + src = re.sub(r'\n{3,}', "\n\n", src) + return src + + +def main(): + order = os.path.normpath(ORDER_DIR) + changed = 0 + counts = {} + for fn in sorted(os.listdir(order)): + if not fn.endswith(".astro"): + continue + path = os.path.join(order, fn) + slug = fn[:-len(".astro")] + v = vertical_for(slug) + new = process(path) + old = open(path).read() + if new != old: + open(path, "w").write(new) + changed += 1 + counts[v] = counts.get(v, 0) + 1 + print(f"order pages processed; changed={changed}") + print("vertical counts:", dict(sorted(counts.items()))) + + +if __name__ == "__main__": + main() diff --git a/site/src/components/TruckingOrderHeader.astro b/site/src/components/TruckingOrderHeader.astro deleted file mode 100644 index b70f0e6..0000000 --- a/site/src/components/TruckingOrderHeader.astro +++ /dev/null @@ -1,124 +0,0 @@ ---- ---- - -
-
DOT / FMCSA Compliance Specialists
-

We handle your FMCSA filings so you can focus on the road.

-

- Performance West is a dedicated transportation compliance firm serving thousands of motor carriers nationwide. - We combine deep regulatory expertise with purpose-built filing technology so your paperwork is done right, done fast, - and tracked every step of the way. -

-
-
-
📋
-

Specialized in trucking compliance

-

MCS-150, BOC-3, UCR, IFTA/IRP, operating authority and more, filed correctly the first time.

-
-
-
-

Fast turnaround

-

Our automated filing systems submit most updates within 1-2 business days of receiving your information.

-
-
-
🔍
-

Attention to detail

-

Every filing is verified against current FMCSA requirements. We catch errors before they become problems.

-
-
-
📞
-

Real support, real people

-

Questions? Call (888) 411-0383 or reply to any email. We respond same business day.

-
-
-
- - diff --git a/site/src/components/VerticalOrderHeader.astro b/site/src/components/VerticalOrderHeader.astro new file mode 100644 index 0000000..dd4835b --- /dev/null +++ b/site/src/components/VerticalOrderHeader.astro @@ -0,0 +1,159 @@ +--- +// Vertical-specific order-page hero. One component, four verticals, so the copy +// + accent live in a single place and never drift across the ~50 order pages. +// +// Usage: +// Verticals: "trucking" | "telecom" | "healthcare" | "corporate" +// (trucking mirrors the original TruckingOrderHeader copy verbatim.) +export interface Props { + vertical: "trucking" | "telecom" | "healthcare" | "corporate"; +} +const { vertical } = Astro.props; + +type Card = { icon: string; h: string; p: string }; +type Content = { + badge: string; + title: string; + intro: string; + accent: string; // accent color (badge text + card highlight) + cards: Card[]; +}; + +const PHONE = "(888) 411-0383"; + +const CONTENT: Record = { + trucking: { + badge: "DOT / FMCSA Compliance Specialists", + title: "We handle your FMCSA filings so you can focus on the road.", + intro: + "Performance West is a dedicated transportation compliance firm serving thousands of motor carriers nationwide. We combine deep regulatory expertise with purpose-built filing technology so your paperwork is done right, done fast, and tracked every step of the way.", + accent: "#fb923c", + cards: [ + { icon: "\u{1F4CB}", h: "Specialized in trucking compliance", p: "MCS-150, BOC-3, UCR, IFTA/IRP, operating authority and more, filed correctly the first time." }, + { icon: "\u{26A1}", h: "Fast turnaround", p: "Our automated filing systems submit most updates within 1-2 business days of receiving your information." }, + { icon: "\u{1F50D}", h: "Attention to detail", p: "Every filing is verified against current FMCSA requirements. We catch errors before they become problems." }, + { icon: "\u{1F4DE}", h: "Real support, real people", p: `Questions? Call ${PHONE} or reply to any email. We respond same business day.` }, + ], + }, + telecom: { + badge: "FCC / Telecom Compliance Specialists", + title: "We handle your FCC filings so you can focus on your network.", + intro: + "Performance West is a dedicated telecommunications compliance firm serving carriers, VoIP providers, and resellers nationwide. We pair deep FCC regulatory expertise with purpose-built filing technology so your Form 499, STIR/SHAKEN, CPNI, and registrations are done right, done on time, and tracked every step of the way.", + accent: "#60a5fa", + cards: [ + { icon: "\u{1F4E1}", h: "Specialized in telecom compliance", p: "Form 499-A/Q, FCC registration, STIR/SHAKEN, CPNI, Robocall Mitigation, OCN/CORES and more." }, + { icon: "\u{26A1}", h: "Deadline-driven filing", p: "We track every FCC and USAC due date and file on time so you avoid red-light status and penalties." }, + { icon: "\u{1F50D}", h: "Accuracy you can audit", p: "Every filing is verified against current FCC rules. We catch revenue and classification errors before they cost you." }, + { icon: "\u{1F4DE}", h: "Real support, real people", p: `Questions? Call ${PHONE} or reply to any email. We respond same business day.` }, + ], + }, + healthcare: { + badge: "Healthcare Provider Compliance Specialists", + title: "We handle your Medicare and NPI filings so you can focus on patients.", + intro: + "Performance West is a dedicated healthcare compliance firm serving providers, group practices, and facilities nationwide. We combine deep CMS and NPPES regulatory expertise with purpose-built filing technology so your revalidation, enrollment, and registry updates are done right, done fast, and tracked every step of the way.", + accent: "#34d399", + cards: [ + { icon: "\u{1FA7A}", h: "Specialized in provider compliance", p: "Medicare PECOS revalidation, NPI/NPPES updates, reactivation, enrollment, and OIG/SAM screening." }, + { icon: "\u{26A1}", h: "Beat the deactivation deadline", p: "Miss a revalidation date and CMS deactivates your billing privileges. We file before the clock runs out." }, + { icon: "\u{1F50D}", h: "Accuracy that protects billing", p: "Every filing is checked against current CMS requirements so an error never interrupts your reimbursements." }, + { icon: "\u{1F4DE}", h: "Real support, real people", p: `Questions? Call ${PHONE} or reply to any email. We respond same business day.` }, + ], + }, + corporate: { + badge: "Corporate Compliance Specialists", + title: "We handle your corporate filings so you can focus on the business.", + intro: + "Performance West is a dedicated corporate compliance firm serving companies registering and operating across multiple states. We combine deep regulatory expertise with purpose-built filing technology so your registrations, agent designations, and annual obligations are done right, done fast, and tracked every step of the way.", + accent: "#a78bfa", + cards: [ + { icon: "\u{1F3DB}\u{FE0F}", h: "Specialized in corporate filings", p: "Foreign qualification, registered/process agent service, formations, and annual reports nationwide." }, + { icon: "\u{26A1}", h: "Fast, multi-state turnaround", p: "We handle the Secretary of State paperwork in every jurisdiction so you can expand without the delay." }, + { icon: "\u{1F50D}", h: "Nothing falls through the cracks", p: "Every registration is verified and tracked, so deadlines and renewals never slip." }, + { icon: "\u{1F4DE}", h: "Real support, real people", p: `Questions? Call ${PHONE} or reply to any email. We respond same business day.` }, + ], + }, +}; + +const c = CONTENT[vertical]; +--- + +
+
{c.badge}
+

{c.title}

+

{c.intro}

+
+ {c.cards.map((card) => ( +
+
{card.icon}
+

{card.h}

+

{card.p}

+
+ ))} +
+
+ + diff --git a/site/src/pages/order/bdc-broadband.astro b/site/src/pages/order/bdc-broadband.astro index d9e7ccd..ed2069c 100644 --- a/site/src/pages/order/bdc-broadband.astro +++ b/site/src/pages/order/bdc-broadband.astro @@ -1,5 +1,6 @@ --- import Base from "../../layouts/Base.astro"; +import VerticalOrderHeader from "../../components/VerticalOrderHeader.astro"; import Wizard from "../../components/intake/Wizard.astro"; import TaxDeductibilityNotice from "../../components/TaxDeductibilityNotice.astro"; import { INTAKE_MANIFEST, SERVICE_META, formatUSD } from "../../lib/intake_manifest"; @@ -18,6 +19,7 @@ const description = "Availability data only (no voice subscription). For broadba

{description}

+
About | Performance West Inc.

About Performance West

+ About | Performance West Inc.

Regulatory Compliance Consulting

About Performance West

Professional compliance consulting built on fixed pricing, domain expertise, and a commitment to helping businesses navigate regulatory requirements.

Our story

Performance West Inc. began with a focus on corporate and telecom regulatory compliance — helping carriers, CLECs, and VoIP providers navigate FCC filings, state PUC registrations, STIR/SHAKEN implementation, and the alphabet soup of telecom regulation. @@ -15,12 +15,12 @@ As we worked with telecom clients, we saw the same companies struggling with com So we expanded. Today, Performance West is a full-service regulatory compliance consulting firm covering telecom, transportation (DOT/FMCSA), healthcare provider compliance, data privacy, TCPA, employment, and corporate compliance. We serve businesses and providers across the United States from our home base in Cheyenne, Wyoming, where we are incorporated and maintain our principal office.

Performance West is a Christian, kingdom-minded business. We operate with integrity, honesty, and a commitment to treating every client — from a single-state LLC to a national carrier — with the same level of professionalism and care. Our work reflects our values: we do what we say we'll do, we charge what we say we'll charge, and we deliver when we say we'll deliver. -

What we do

+

What we do

Performance West provides compliance consulting services across telecom, transportation (DOT/FMCSA), healthcare provider compliance, data privacy, TCPA, employment, and corporate regulatory domains. We help businesses and providers identify compliance gaps, build remediation plans, and prepare and file the documentation needed to meet their regulatory obligations. In healthcare, that means handling Medicare PECOS revalidation and enrollment, NPI/NPPES updates, reactivations, and OIG/SAM exclusion screening — we prepare every filing, verify it for accuracy so it isn’t rejected, and track it through to acceptance, so providers never lose billing privileges to a missed deadline or a clerical error.

All of our services are offered at fixed prices with defined deliverables and turnaround times. No billable hours, no surprise invoices, no scope creep. You know exactly what you're getting and what it costs before we begin.

Important: Performance West provides compliance consulting services. We do not provide legal advice, legal opinions, or legal representation. If you need legal counsel, we recommend working with a qualified attorney in your jurisdiction. Our consultants can work alongside your legal team to provide the compliance analysis and documentation they need. -

Our approach

Fixed pricing, not billable hours

Every service has a published price. You know the cost before we start, and that's the cost when we finish.

Multi-domain expertise

Telecom, employment, privacy, TCPA, and corporate compliance under one roof. Most businesses have needs across multiple domains.

Defined turnaround times

We commit to a delivery date and meet it. Most services are delivered in 3–7 business days. No indefinite timelines.

Compliance consulting, not legal representation

We identify gaps and provide actionable remediation plans. For legal disputes, we recommend qualified attorneys in your jurisdiction.

Meet the founder

Justin Hannah, Founder of Performance West Inc.

Justin Hannah

Founder & Principal Consultant

Justin Hannah has spent more than two decades in telecommunications and regulatory-heavy industries. He has served as President of Carrier One (a retail telecom and unified-communications provider) since 2001 and built one of the first high-capacity VoIP trunking networks in the United States — deploying Asterisk-based systems as early as 2003 and working in FreeSWITCH ever since. Along the way he founded and ran wholesale voice and electronic-payments (Transactions America) businesses, giving him a rare, end-to-end view of how regulated companies actually operate.

That hands-on background — FCC filings, STIR/SHAKEN, carrier registrations, payments/PCI, and the day-to-day engineering behind them — is exactly what Performance West is built on. Justin founded the firm in 2023 to give businesses and providers a better option than ignoring their compliance obligations or paying law firms hundreds of dollars an hour for work that doesn’t require a legal opinion — it requires someone who understands the filings and gets them done correctly.

Under his leadership, Performance West has grown from telecom compliance into a multi-sector practice spanning transportation (DOT/FMCSA), healthcare provider compliance (Medicare/PECOS, NPI/NPPES), data privacy, TCPA, and corporate registration. He runs it with a deeply technical, accuracy-first approach — every filing is verified before submission and tracked through to acceptance — and as an honest, kingdom-minded business that treats a solo practitioner and a national carrier with the same care.

Connect on LinkedIn

Get in touch

+

Our approach

Fixed pricing, not billable hours

Every service has a published price. You know the cost before we start, and that's the cost when we finish.

Multi-domain expertise

Telecom, employment, privacy, TCPA, and corporate compliance under one roof. Most businesses have needs across multiple domains.

Defined turnaround times

We commit to a delivery date and meet it. Most services are delivered in 3–7 business days. No indefinite timelines.

Compliance consulting, not legal representation

We identify gaps and provide actionable remediation plans. For legal disputes, we recommend qualified attorneys in your jurisdiction.

Meet the founder

Justin Hannah, Founder of Performance West Inc.

Justin Hannah

Founder & Principal Consultant

Justin Hannah has spent more than two decades in telecommunications and regulatory-heavy industries. He has served as President of Carrier One (a retail telecom and unified-communications provider) since 2001 and built one of the first high-capacity VoIP trunking networks in the United States — deploying Asterisk-based systems as early as 2003 and working in FreeSWITCH ever since. Along the way he founded and ran wholesale voice and electronic-payments (Transactions America) businesses, giving him a rare, end-to-end view of how regulated companies actually operate.

That hands-on background — FCC filings, STIR/SHAKEN, carrier registrations, payments/PCI, and the day-to-day engineering behind them — is exactly what Performance West is built on. Justin founded the firm in 2023 to give businesses and providers a better option than ignoring their compliance obligations or paying law firms hundreds of dollars an hour for work that doesn’t require a legal opinion — it requires someone who understands the filings and gets them done correctly.

Under his leadership, Performance West has grown from telecom compliance into a multi-sector practice spanning transportation (DOT/FMCSA), healthcare provider compliance (Medicare/PECOS, NPI/NPPES), data privacy, TCPA, and corporate registration. He runs it with a deeply technical, accuracy-first approach — every filing is verified before submission and tracked through to acceptance — and as an honest, kingdom-minded business that treats a solo practitioner and a national carrier with the same care.

Connect on LinkedIn

Get in touch

Have questions about our services or want to discuss your compliance needs? Reach out anytime.

Contact us From 6c9956d14cc9d547920d07608cd9bbf4563ce032 Mon Sep 17 00:00:00 2001 From: justin Date: Sat, 6 Jun 2026 18:07:01 -0500 Subject: [PATCH 021/314] about: real founder headshot (face-detected crop from suit photo) replacing placeholder --- site/public/images/justin-hannah.jpg | Bin 5084 -> 37406 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/site/public/images/justin-hannah.jpg b/site/public/images/justin-hannah.jpg index 9d490700222eb700986de03fdc59f34b7dbefb14..c8d1509b19ea65e06847db820abffbb200d35c0c 100644 GIT binary patch delta 37219 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≷n%5DoKT8R)0InJoH>%m;KGiXn9T0e&w9T)i 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 Date: Sat, 6 Jun 2026 18:08:49 -0500 Subject: [PATCH 022/314] pricing: add Healthcare section at top (6 services: revalidation $599, enrollment $699, reactivation $449, NPPES $349, OIG/SAM $299/yr, bundle $899/yr) with teal header --- site/public/pricing/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/public/pricing/index.html b/site/public/pricing/index.html index 496b3c9..a6e24bb 100644 --- a/site/public/pricing/index.html +++ b/site/public/pricing/index.html @@ -9,7 +9,7 @@ Every service has a published price with defined deliverables and turnaround times. No billable hours. No surprise invoices.

Why fixed pricing?

Law firms and traditional consultancies bill by the hour — often $300 to $600 per hour — with no upfront cost certainty. A "quick review" can turn into thousands of dollars. Performance West is different. -

Know the cost upfront

Every service has a published price. The price you see is the price you pay.

Defined turnaround

We commit to a delivery date and meet it. No indefinite timelines or scope creep.

Clear deliverables

You know exactly what you're getting before we start. No ambiguity.

Telecom

FCC Carrier / ISP Registration

FCC Carrier / ISP Registration Bundle Save 35%

CORES + 499 Initial + RMD + CPNI + CALEA + D.C. Agent

$1,299 2-3 weeks
Annual FCC Filings
499-A Filing$499
499-A (Zero Revenue)$179
499-A + 499-Q Bundle$599
499-A Discontinuance$299
CPNI Certification$199
RMD Registration$249 + $100 fee
BDC Broadband$249
BDC Voice$199
BDC Both$349
Registration & Setup
CORES / FRN Registration$149
Form 499 Initial$349
CALEA SSI Plan$799
D.C. Agent (Annual)$149
STIR/SHAKEN$499
NECA OCN Registration$2,650
State PUC/PSC$399/state
Foreign Carrier (63.11)$349
Free Tools
FCC Compliance CheckFREE

Trucking / DOT

+

Know the cost upfront

Every service has a published price. The price you see is the price you pay.

Defined turnaround

We commit to a delivery date and meet it. No indefinite timelines or scope creep.

Clear deliverables

You know exactly what you're getting before we start. No ambiguity.

Healthcare

Service Price Turnaround
Medicare Enrollment & Revalidation
Medicare PECOS Revalidation Filing

Beat your CMS revalidation deadline so billing privileges don’t deactivate

$599 2-3 business days
Medicare Enrollment (PECOS)

New provider/group enrollment in Medicare via PECOS

$699 1-2 weeks
NPI / Enrollment Reactivation

Restore deactivated Medicare billing privileges

$449 2-3 business days
NPI / NPPES
NPPES Data Update / Attestation

Update address, taxonomy, contacts; required periodic attestation

$349 1-2 business days
Provider Compliance
OIG / SAM Exclusion Screening

Documented monthly screening against the OIG LEIE + SAM lists

$299/yr Ongoing
Provider Compliance Bundle Save 25%

Revalidation monitoring + NPPES attestation + monthly exclusion screening

$899/yr Annual

Telecom

FCC Carrier / ISP Registration

FCC Carrier / ISP Registration Bundle Save 35%

CORES + 499 Initial + RMD + CPNI + CALEA + D.C. Agent

$1,299 2-3 weeks
Annual FCC Filings
499-A Filing$499
499-A (Zero Revenue)$179
499-A + 499-Q Bundle$599
499-A Discontinuance$299
CPNI Certification$199
RMD Registration$249 + $100 fee
BDC Broadband$249
BDC Voice$199
BDC Both$349
Registration & Setup
CORES / FRN Registration$149
Form 499 Initial$349
CALEA SSI Plan$799
D.C. Agent (Annual)$149
STIR/SHAKEN$499
NECA OCN Registration$2,650
State PUC/PSC$399/state
Foreign Carrier (63.11)$349
Free Tools
FCC Compliance CheckFREE

Trucking / DOT

Need a custom quote?

Services marked "Custom quote" are priced based on scope and complexity. Multi-service packages and ongoing compliance retainers are also available. Contact us for a no-obligation consultation. From a56ee01d965063f75fc7de7efded93e4a421cd4b Mon Sep 17 00:00:00 2001 From: justin Date: Sat, 6 Jun 2026 18:19:54 -0500 Subject: [PATCH 023/314] fix(pricing): Trucking/DOT header was invisible (bg-orange-500 purged from CSS) -> inline orange background --- site/public/pricing/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/public/pricing/index.html b/site/public/pricing/index.html index a6e24bb..44aecc8 100644 --- a/site/public/pricing/index.html +++ b/site/public/pricing/index.html @@ -9,7 +9,7 @@ Every service has a published price with defined deliverables and turnaround times. No billable hours. No surprise invoices.

Why fixed pricing?

Law firms and traditional consultancies bill by the hour — often $300 to $600 per hour — with no upfront cost certainty. A "quick review" can turn into thousands of dollars. Performance West is different. -

Know the cost upfront

Every service has a published price. The price you see is the price you pay.

Defined turnaround

We commit to a delivery date and meet it. No indefinite timelines or scope creep.

Clear deliverables

You know exactly what you're getting before we start. No ambiguity.

Healthcare

Service Price Turnaround
Medicare Enrollment & Revalidation
Medicare PECOS Revalidation Filing

Beat your CMS revalidation deadline so billing privileges don’t deactivate

$599 2-3 business days
Medicare Enrollment (PECOS)

New provider/group enrollment in Medicare via PECOS

$699 1-2 weeks
NPI / Enrollment Reactivation

Restore deactivated Medicare billing privileges

$449 2-3 business days
NPI / NPPES
NPPES Data Update / Attestation

Update address, taxonomy, contacts; required periodic attestation

$349 1-2 business days
Provider Compliance
OIG / SAM Exclusion Screening

Documented monthly screening against the OIG LEIE + SAM lists

$299/yr Ongoing
Provider Compliance Bundle Save 25%

Revalidation monitoring + NPPES attestation + monthly exclusion screening

$899/yr Annual

Telecom

FCC Carrier / ISP Registration

FCC Carrier / ISP Registration Bundle Save 35%

CORES + 499 Initial + RMD + CPNI + CALEA + D.C. Agent

$1,299 2-3 weeks
Annual FCC Filings
499-A Filing$499
499-A (Zero Revenue)$179
499-A + 499-Q Bundle$599
499-A Discontinuance$299
CPNI Certification$199
RMD Registration$249 + $100 fee
BDC Broadband$249
BDC Voice$199
BDC Both$349
Registration & Setup
CORES / FRN Registration$149
Form 499 Initial$349
CALEA SSI Plan$799
D.C. Agent (Annual)$149
STIR/SHAKEN$499
NECA OCN Registration$2,650
State PUC/PSC$399/state
Foreign Carrier (63.11)$349
Free Tools
FCC Compliance CheckFREE

Trucking / DOT

+

Know the cost upfront

Every service has a published price. The price you see is the price you pay.

Defined turnaround

We commit to a delivery date and meet it. No indefinite timelines or scope creep.

Clear deliverables

You know exactly what you're getting before we start. No ambiguity.

Healthcare

Service Price Turnaround
Medicare Enrollment & Revalidation
Medicare PECOS Revalidation Filing

Beat your CMS revalidation deadline so billing privileges don’t deactivate

$599 2-3 business days
Medicare Enrollment (PECOS)

New provider/group enrollment in Medicare via PECOS

$699 1-2 weeks
NPI / Enrollment Reactivation

Restore deactivated Medicare billing privileges

$449 2-3 business days
NPI / NPPES
NPPES Data Update / Attestation

Update address, taxonomy, contacts; required periodic attestation

$349 1-2 business days
Provider Compliance
OIG / SAM Exclusion Screening

Documented monthly screening against the OIG LEIE + SAM lists

$299/yr Ongoing
Provider Compliance Bundle Save 25%

Revalidation monitoring + NPPES attestation + monthly exclusion screening

$899/yr Annual

Telecom

FCC Carrier / ISP Registration

FCC Carrier / ISP Registration Bundle Save 35%

CORES + 499 Initial + RMD + CPNI + CALEA + D.C. Agent

$1,299 2-3 weeks
Annual FCC Filings
499-A Filing$499
499-A (Zero Revenue)$179
499-A + 499-Q Bundle$599
499-A Discontinuance$299
CPNI Certification$199
RMD Registration$249 + $100 fee
BDC Broadband$249
BDC Voice$199
BDC Both$349
Registration & Setup
CORES / FRN Registration$149
Form 499 Initial$349
CALEA SSI Plan$799
D.C. Agent (Annual)$149
STIR/SHAKEN$499
NECA OCN Registration$2,650
State PUC/PSC$399/state
Foreign Carrier (63.11)$349
Free Tools
FCC Compliance CheckFREE

Trucking / DOT

Need a custom quote?

Services marked "Custom quote" are priced based on scope and complexity. Multi-service packages and ongoing compliance retainers are also available. Contact us for a no-obligation consultation. From eea1d02045d8058b192cba0eb46057e15dd6342e Mon Sep 17 00:00:00 2001 From: justin Date: Sat, 6 Jun 2026 19:34:18 -0500 Subject: [PATCH 024/314] trust/security: add RFC 9116 /.well-known/security.txt + /security trust page (verified TLS A+/SOC2/HIPAA-PCI, security practices, vuln disclosure) --- site/public/.well-known/security.txt | 7 +++ site/public/security/index.html | 86 ++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 site/public/.well-known/security.txt create mode 100644 site/public/security/index.html diff --git a/site/public/.well-known/security.txt b/site/public/.well-known/security.txt new file mode 100644 index 0000000..8365a4c --- /dev/null +++ b/site/public/.well-known/security.txt @@ -0,0 +1,7 @@ +# Performance West Inc. — Security contact (RFC 9116) +Contact: mailto:security@performancewest.net +Contact: tel:+1-888-411-0383 +Expires: 2027-06-07T00:28:30Z +Preferred-Languages: en +Canonical: https://performancewest.net/.well-known/security.txt +Policy: https://performancewest.net/security diff --git a/site/public/security/index.html b/site/public/security/index.html new file mode 100644 index 0000000..69b0e05 --- /dev/null +++ b/site/public/security/index.html @@ -0,0 +1,86 @@ + Security & Trust | Performance West Inc.

+
Security & Trust

How we protect your data

Performance West handles sensitive regulatory and provider information. Security is built into how we operate — from the infrastructure up to every filing.

+ +

Independently verified

+
🔒

TLS A+ (Qualys SSL Labs)

Every connection uses modern, AEAD-only encryption (TLS 1.2/1.3). Verify →

+
🛡️

Security Headers A

HSTS (preloaded), CSP, X-Frame-Options and more. Verify →

+

HIPAA · PCI · NIST compliant TLS

Encryption posture independently scanned and confirmed compliant with HIPAA, PCI DSS, and NIST guidance.

+
🏢

SOC 2 Type II hosting

Our systems run in a SOC 2 Type II compliant data center with physical and operational controls.

+
💳

PCI-compliant payments (Stripe)

We never store card data. All payments are processed by Stripe (PCI DSS Level 1).

+
✉️

Email authentication

SPF, DKIM, DMARC, and MTA-STS protect against spoofing of our domain.

+
+ +

Our security practices

+

Encryption everywhere. All traffic to our website, client portal, and APIs is encrypted in transit with TLS 1.2/1.3. Sensitive data is encrypted at rest.

+

Least-data principle. We collect only the information needed to complete your filing, and we don’t sell your data. For payments we never touch card numbers — Stripe handles them directly.

+

Hardened infrastructure. Our servers sit behind a default-deny firewall with only the necessary public services exposed, automatic security updates, intrusion monitoring, and isolated environments for each workload.

+

Access control. Administrative access is key-based and restricted; we follow least-privilege and review access regularly.

+

Healthcare data. For provider clients, we handle CMS/NPPES information with care and only as needed to prepare and submit your filings. We do not post your private details publicly, and we delete working copies of sensitive documents when an engagement is complete.

+
+ +

Report a security issue

We welcome responsible disclosure. If you believe you’ve found a vulnerability, please email security@performancewest.net or call (888) 411-0383. Our machine-readable policy is published at /.well-known/security.txt.

Note: Performance West provides compliance consulting services, not legal advice. See our Privacy Policy and Terms of Service.

+

Stay ahead of compliance changes

Regulatory updates, enforcement trends, and compliance tips. No spam.

+
+ Performance West +

Performance West Inc. · 525 Randall Ave Ste 100-1195, Cheyenne, WY 82001 · performancewest.net · (888) 411-0383

+

Performance West is a regulatory compliance consulting firm, not a law firm. This does not constitute legal advice.

+
+

How can we help?

Choose a category and tell us what you need.

\ No newline at end of file From 7bd2f70de459eecbc97e906981fd822d2b3e9c51 Mon Sep 17 00:00:00 2001 From: justin Date: Sat, 6 Jun 2026 19:36:27 -0500 Subject: [PATCH 025/314] infra: MTA-STS policy + vhost + README (cert pending DNS propagation) --- infra/mta-sts/README.md | 15 +++++++++++++++ infra/mta-sts/mta-sts.txt | 4 ++++ infra/mta-sts/pw-mta-sts.conf | 7 +++++++ 3 files changed, 26 insertions(+) create mode 100644 infra/mta-sts/README.md create mode 100644 infra/mta-sts/mta-sts.txt create mode 100644 infra/mta-sts/pw-mta-sts.conf diff --git a/infra/mta-sts/README.md b/infra/mta-sts/README.md new file mode 100644 index 0000000..6b1d335 --- /dev/null +++ b/infra/mta-sts/README.md @@ -0,0 +1,15 @@ +# MTA-STS for performancewest.net + +DNS TXT `_mta-sts.performancewest.net` = `v=STSv1; id=20260505` (already published). +TLS-RPT TXT `_smtp._tls.performancewest.net` published. +Added A record `mta-sts.performancewest.net -> 207.174.124.71` (Hestia). + +Policy served at `https://mta-sts.performancewest.net/.well-known/mta-sts.txt` +from `/var/www/mta-sts/.well-known/mta-sts.txt` (content = mta-sts.txt here). + +PENDING: Let's Encrypt cert for mta-sts.performancewest.net (waiting on HE.net +secondary DNS propagation). Once `dig +short mta-sts.performancewest.net @8.8.8.8` +resolves, run: + sudo certbot certonly --webroot -w /var/www/certbot -d mta-sts.performancewest.net --non-interactive --agree-tos -m admin@performancewest.net +then upgrade pw-mta-sts.conf to an HTTPS (443) server block (see pw-listmonk-hc.conf +pattern) and reload nginx. MTA-STS requires the policy be served over valid HTTPS. diff --git a/infra/mta-sts/mta-sts.txt b/infra/mta-sts/mta-sts.txt new file mode 100644 index 0000000..d3ad1c8 --- /dev/null +++ b/infra/mta-sts/mta-sts.txt @@ -0,0 +1,4 @@ +version: STSv1 +mode: enforce +mx: co.carrierone.com +max_age: 604800 diff --git a/infra/mta-sts/pw-mta-sts.conf b/infra/mta-sts/pw-mta-sts.conf new file mode 100644 index 0000000..750108a --- /dev/null +++ b/infra/mta-sts/pw-mta-sts.conf @@ -0,0 +1,7 @@ +server { + listen 80; + server_name mta-sts.performancewest.net; + location /.well-known/acme-challenge/ { root /var/www/certbot; } + location /.well-known/mta-sts.txt { root /var/www/mta-sts; default_type text/plain; } + location / { return 404; } +} From 34daa0c1d3099f3cc584178997f3ef2b4626d5bc Mon Sep 17 00:00:00 2001 From: justin Date: Sat, 6 Jun 2026 19:37:37 -0500 Subject: [PATCH 026/314] infra: MTA-STS status note - cert pending stable HE.net DNS propagation --- infra/mta-sts/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/infra/mta-sts/README.md b/infra/mta-sts/README.md index 6b1d335..cef699c 100644 --- a/infra/mta-sts/README.md +++ b/infra/mta-sts/README.md @@ -13,3 +13,13 @@ resolves, run: sudo certbot certonly --webroot -w /var/www/certbot -d mta-sts.performancewest.net --non-interactive --agree-tos -m admin@performancewest.net then upgrade pw-mta-sts.conf to an HTTPS (443) server block (see pw-listmonk-hc.conf pattern) and reload nginx. MTA-STS requires the policy be served over valid HTTPS. + +## STATUS 2026-06-07 +- DNS A record added + policy file served over HTTP (working). +- Cert issuance FAILED twice: HE.net secondary DNS is flapping (mta-sts resolves + on 1.1.1.1/9.9.9.9 but intermittently empty on 8.8.8.8), so Let's Encrypt's + multi-vantage validation can't get consistent resolution. nginx left on the + safe HTTP-only vhost. RETRY the certbot command above once `dig +short + mta-sts.performancewest.net` is stable across 8.8.8.8 / 1.1.1.1 / 9.9.9.9, + then upgrade to the 443 vhost. (nginx -t before any reload — a missing cert + ref will break the reload.) From 7399211271d091cf90622c31cf9a3065dfc201ab Mon Sep 17 00:00:00 2001 From: justin Date: Sat, 6 Jun 2026 21:01:36 -0500 Subject: [PATCH 027/314] trust/security: DMARC p=reject; MTA-STS cert+HTTPS policy live; cookie consent banner (CSP-safe); /accessibility page; footer legal links (Security/Accessibility) on all pages; scope TrustedSite to /order payment pages only --- site/public/about/index.html | 3 +- site/public/accessibility/index.html | 81 +++++++++++++++++++ site/public/account/reset-password/index.html | 3 +- site/public/admin/index.html | 3 +- site/public/contact/index.html | 3 +- site/public/index.html | 4 +- site/public/js/pw-cookie-consent.js | 53 ++++++++++++ site/public/order/canada-crtc/index.html | 3 +- site/public/order/cancel/index.html | 3 +- site/public/order/cancelled/index.html | 3 +- site/public/order/crypto-pay/index.html | 3 +- site/public/order/dot-compliance/index.html | 3 +- site/public/order/fcc-499a/index.html | 3 +- site/public/order/fcc-499q/index.html | 2 +- .../order/fcc-carrier-registration/index.html | 2 +- site/public/order/fcc-compliance/index.html | 3 +- site/public/order/formation/index.html | 3 +- .../public/order/identity-complete/index.html | 2 +- site/public/order/neca-ocn/index.html | 2 +- site/public/order/state-puc/index.html | 2 +- site/public/order/success/index.html | 3 +- .../order/trucking-new-carrier/index.html | 3 +- site/public/portal/dashboard/index.html | 3 +- site/public/portal/domain-search/index.html | 3 +- site/public/portal/esign/index.html | 2 +- site/public/portal/manage-services/index.html | 3 +- site/public/portal/rmd-review/index.html | 3 +- site/public/portal/setup/index.html | 3 +- site/public/portal/sign/index.html | 3 +- site/public/portal/upload-id/index.html | 2 +- site/public/pricing/bundles/index.html | 3 +- site/public/pricing/index.html | 4 +- site/public/privacy/index.html | 3 +- site/public/security/index.html | 3 +- .../corporate/annual-reports/index.html | 3 +- .../services/corporate/formation/index.html | 3 +- site/public/services/corporate/index.html | 3 +- .../corporate/registered-agent/index.html | 3 +- .../corporate/state-registration/index.html | 3 +- .../contractor-classification/index.html | 3 +- .../services/employment/flsa-audit/index.html | 3 +- .../employment/handbook-review/index.html | 3 +- site/public/services/employment/index.html | 3 +- .../employment/policy-development/index.html | 3 +- site/public/services/index.html | 3 +- .../privacy/breach-response/index.html | 3 +- .../services/privacy/ccpa-audit/index.html | 3 +- .../services/privacy/data-mapping/index.html | 3 +- site/public/services/privacy/index.html | 3 +- .../privacy/privacy-policy/index.html | 3 +- .../services/tcpa/campaign-review/index.html | 3 +- .../services/tcpa/consent-audit/index.html | 3 +- .../services/tcpa/dnc-compliance/index.html | 3 +- site/public/services/tcpa/index.html | 3 +- .../services/telecom/canada-crtc/index.html | 3 +- site/public/services/telecom/cpni/index.html | 3 +- .../telecom/database-management/index.html | 3 +- .../services/telecom/fcc-499a/index.html | 3 +- .../guides/cores-registration/index.html | 3 +- .../guides/cpni-certification/index.html | 3 +- .../telecom/guides/fcc-499a/index.html | 3 +- .../telecom/guides/fcc-499q/index.html | 3 +- .../telecom/guides/rmd-filing/index.html | 3 +- .../guides/usac-account-setup/index.html | 3 +- site/public/services/telecom/index.html | 3 +- .../services/telecom/ipes-isp/index.html | 3 +- .../services/telecom/state-puc/index.html | 3 +- .../services/telecom/stir-shaken/index.html | 3 +- .../services/trucking/california/index.html | 3 +- .../services/trucking/connecticut/index.html | 3 +- .../trucking/drug-alcohol-program/index.html | 3 +- .../services/trucking/florida/index.html | 3 +- .../services/trucking/hazmat/index.html | 3 +- site/public/services/trucking/index.html | 3 +- .../services/trucking/irp-ifta/index.html | 3 +- .../services/trucking/kentucky/index.html | 3 +- .../services/trucking/new-carrier/index.html | 3 +- .../services/trucking/new-mexico/index.html | 3 +- .../services/trucking/new-york/index.html | 3 +- .../services/trucking/oregon/index.html | 3 +- .../public/services/trucking/texas/index.html | 3 +- site/public/survey/index.html | 2 +- site/public/terms/index.html | 3 +- site/public/tools/contractor-quiz/index.html | 3 +- .../public/tools/corporation-check/index.html | 3 +- .../tools/dot-compliance-check/index.html | 4 +- .../tools/fcc-compliance-check/index.html | 3 +- site/public/tools/formation-guide/index.html | 3 +- site/public/tools/privacy-check/index.html | 3 +- site/public/tools/tcpa-check/index.html | 3 +- site/public/upload/id/index.html | 2 +- site/src/layouts/Base.astro | 9 ++- site/src/partials/footer.html | 5 +- 93 files changed, 311 insertions(+), 98 deletions(-) create mode 100644 site/public/accessibility/index.html create mode 100644 site/public/js/pw-cookie-consent.js diff --git a/site/public/about/index.html b/site/public/about/index.html index 8592d2e..ea0c61d 100644 --- a/site/public/about/index.html +++ b/site/public/about/index.html @@ -36,6 +36,7 @@ Subscribe
Performance West

Performance West Inc. · 525 Randall Ave Ste 100-1195, Cheyenne, WY 82001 · performancewest.net · (888) 411-0383

+

Privacy Policy · Terms of Service · Security & Trust · Accessibility

Performance West is a regulatory compliance consulting firm, not a law firm. This does not constitute legal advice.

How can we help?

Choose a category and tell us what you need.

All Services Pricing Free Tools Contact Form a Business Client Portal
+
Accessibility

Accessibility Statement

We want everyone to be able to use performancewest.net, regardless of ability or technology.

+ +
+

Our commitment. Performance West is committed to making our website accessible to the widest possible audience, and we aim to conform to the Web Content Accessibility Guidelines (WCAG) 2.1 Level AA as a practical standard.

+

What we do. We design for keyboard navigation, sufficient color contrast, descriptive link and image text, responsive layouts that work on phones and assistive technologies, and clear, plain-language content. We review pages as we build and update them.

+

Ongoing effort. Accessibility is an ongoing process. Some older pages or third-party components (such as embedded chat or payment widgets) may not yet fully conform; we work to improve them over time.

+

Need help, or found a barrier? If you have trouble accessing any part of this site, or you need information in an alternative format, we’ll help. Contact us and we’ll work with you directly:

+ +

We aim to respond to accessibility feedback within 3 business days.

+
+

Stay ahead of compliance changes

Regulatory updates, enforcement trends, and compliance tips. No spam.

How can we help?

Choose a category and tell us what you need.

\ No newline at end of file diff --git a/site/public/account/reset-password/index.html b/site/public/account/reset-password/index.html index 98a5e4c..d9a685c 100644 --- a/site/public/account/reset-password/index.html +++ b/site/public/account/reset-password/index.html @@ -19,6 +19,7 @@ Subscribe
Performance West

Performance West Inc. · 525 Randall Ave Ste 100-1195, Cheyenne, WY 82001 · performancewest.net · (888) 411-0383

+

Privacy Policy · Terms of Service · Security & Trust · Accessibility

Performance West is a regulatory compliance consulting firm, not a law firm. This does not constitute legal advice.

How can we help?

Choose a category and tell us what you need.