Commit graph

522 commits

Author SHA1 Message Date
justin
0b06043437 healthcare: verify wet-signature requirements across all services
Source-grounded check of which services need an ORIGINAL ink signature (plotter
target) vs e-sign/typed. Verified firsthand against the official forms:

- Confirmed wet-ink: the 5 CMS Medicare/NPI paper filings only (855I/B/O +
  10114), which are exactly the no-login Standard-path filings the plotter serves.
- CLIA CMS-116 does NOT require original ink — the form explicitly permits 'SIGN
  IN INK OR USE A SECURE ELECTRONIC SIGNATURE', so our digital stamp suffices;
  plotter optional for CLIA.
- DEA registration/renewal is online-only (Form 224 unavailable in PDF),
  e-certified, no wet ink.
- State CSR / state Medicaid are the only open items: paper in many states but
  original-ink-vs-e-sign is state-specific; verify per state.
- All FCC/telecom/DOT/BOC-3/CRTC/PUC filings are electronic (e-sign fine).

Added the verified matrix to state-healthcare-compliance-opportunities.md, saved
docs/CMS-116 Form.pdf, and the plotter plan.
2026-06-07 02:40:47 -05:00
justin
b0a8563a93 ink-signature: pen-plotter pipeline for original wet-ink CMS signatures
The Standard no-login CMS path needs an ORIGINAL ink signature on paper
(CMS-10114: 'Stamped, faxed or copied signatures will not be accepted'). This
adds a pipeline to redraw the provider's own captured strokes in real ink with a
pen on a CR-10 V2 (or any Marlin/GRBL machine) — original, in ink, never copied.

- migration 090: esign_records.signature_vector (JSONB stroke paths, 0..1).
- signing page now captures normalized stroke paths alongside the PNG; API
  stores a size-bounded vector for drawn signatures.
- ink_signature_plotter.py (hardware-independent): fit strokes to the signature
  anchor box, PDF-pt -> bed-mm via jig offset, emit Marlin/GRBL G-code (Z pen or
  M280 servo/BLTouch), SVG toolpath preview, and render_signature_on_pdf (a
  digital twin that proves the toolpath lands on the cert line). Gated serial
  sender (dry_run default).
- ink_signature_cli.py: end-to-end load-record -> gcode+preview, --test-box jig
  calibration, --plot to stream over USB.
- Corrected CMS-10114 signature anchor to sit inside the Section 4A signing cell
  (above the bottom rule, below the label).
- docs/ink-signature-plotter.md documents the CR-10 retrofit + interpretive risk.

Tests: test_ink_signature.py 30/30, test_cms10114.py 27/27, test_paper_batch.py
15/15, API tsc clean, Astro build 58 pages.
2026-06-07 02:34:17 -05:00
justin
e6a630ada1 healthcare: verify CMS-10114 update path, correct NPI Enumerator address, build CMS-10114 filler
Verified firsthand against the live CMS-10114 (Rev. 02/25, OMB 0938-0931):
- Section 1A confirms paper is valid for Change of Information (#2) AND
  Reactivation (#4), not just initial enumeration. Resolves the UNCERTAIN flag.
- Current mailing address is CMS NPI Enumerator Services, Mail Stop DO-01-51,
  7500 Security Blvd, Baltimore MD 21244. The old Fargo PO Box 6059 is retired;
  corrected in mac_routing.NPI_ENUMERATOR + all docs.
- No electronic no-login equivalent exists for CMS (NPI Registry API is
  read-only; PECOS/NPPES-IA require login), unlike FMCSA's ask.fmcsa ticket form.
  So tiers stay: Standard=paper CMS-10114 (no login), Expedited=NPPES surrogate.

New: cms10114_pdf_filler.py fills the flat official form via text overlay
(reason checkbox + NPI + Section 2A identity + Section 4A cert name + signature
anchor); wired into npi_provider._generate_10114_for_signing for nppes-update.
Signed forms route to the NPI Enumerator via the existing daily batch.

Tests: test_cms10114.py 27/27, test_paper_batch.py 15/15, Astro build 58 pages.
2026-06-07 02:04:41 -05:00
justin
f9c294e962 healthcare: state/adjacent no-login matrix + verified-tiers status
- state-healthcare-compliance-opportunities.md: add A/B/C/D no-login
  classification per service (Medicaid, CAQH, payer credentialing, DEA/CSR,
  PDMP, CLIA, license). CLIA (CMS-116 paper) + state CSR reuse the daily batch.
- healthcare-filing-tiers-verified.md: implementation status + TODO-before-live
  (MAC addresses, CMS-10114 filler, migration run, print-mail API phase 2).
2026-06-07 00:34:34 -05:00
justin
7ea18dd3d8 healthcare: optional surrogate-access intake question (expedited path)
- NpiIntakeStep: add positively-framed 'can you grant electronic I&A Surrogate
  access?' question for all filing slugs (reval/reactivation/nppes-update/
  enrollment/bundle). Optional, never required, never mentions paper; captured
  as intake_data.surrogate_access (yes/no/blank). Astro build green (58 pages).
- npi_provider.py: surface the surrogate answer in the admin todo so fulfillment
  knows EXPEDITED (online via surrogate) vs STANDARD (e-sign + daily mail batch).
2026-06-07 00:33:33 -05:00
justin
138fec17e9 healthcare: daily batched paper-filing fulfillment
Standard (no-login) CMS filings are mailed in one Priority Mail envelope per
destination agency, batched each postal working-day morning to save postage.

- migration 089: paper_filing_batches table + esign_records.paper_batch_id /
  filing_destination_key (idempotent: a filing is batched at most once).
- batch_cover_sheet.py: per-agency cover sheet (sender/dest/date/manifest) +
  merged print-job PDF (cover + all enclosed signed filings).
- daily_paper_batch.py worker: gather signed+unbatched cms855/cms10114 filings,
  group by destination (MAC by state via mac_routing; Fargo for CMS-10114),
  build cover+merged PDF per agency, persist batch, mark filings batched.
  Self-gates on postal working days (skips weekends + federal/USPS holidays).
  Phase 1 = human prints+mails; phase 2 = wire print-mail API.
- worker-crons: pw-paper-batch systemd timer (Mon-Fri 13:30 UTC, self-gated).
- test_paper_batch.py: 15/15 pass (working-day gating, routing, cover+merge).
2026-06-07 00:30:01 -05:00
justin
258d23bdc6 healthcare: two-tier (standard paper / expedited surrogate) filing model
- Verified Standard(no-login)/Expedited(surrogate) matrix from official CMS-855
  PDFs (docs/healthcare-filing-tiers-verified.md): reactivation+revalidation are
  855I paper-to-MAC reasons, original-signature, routed by state; sig may not be
  delegated; 855B needs PECOS app fee.
- Add scripts/workers/mac_routing.py: state->MAC routing (all 56 jurisdictions,
  12 destinations) for envelope addressing + daily batch grouping. Addresses
  marked VERIFY before live mail.
- npi_provider.py: fix access strings to two-tier framing; NPPES update/reactivation
  no longer 'online-only'; note 855B fee.
- checkout.ts + service pages: strip client-facing mechanics & the paper-vs-tier
  choice; surrogate is the only optional, positively-framed ask (faster, never
  required, never share password).
2026-06-07 00:24:56 -05:00
justin
74c1259c9a docs: state healthcare compliance service opportunities (Medicaid revalidation/enrollment, CAQH, payer credentialing, DEA/CSR/PDMP, CLIA, license renewal) 2026-06-06 22:34:46 -05:00
justin
0a40e4874e fix(site): bug audit fixes - dot-compliance cart prices now match SERVICE_META (12); /pricing/bundles wrong category links (4); fcc tool order CTAs (new-carrier->fcc-carrier-registration, canada-crtc); reset-password logo; nav duplicate id (137 pages via sync_nav); +3 DOT services in SERVICE_META; classification IntakeStep type 2026-06-06 22:29:38 -05:00
justin
bf4e8c2277 infra: MTA-STS HTTPS vhost (cert issued, policy live) 2026-06-06 21:03:30 -05:00
justin
7399211271 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 2026-06-06 21:01:36 -05:00
justin
34daa0c1d3 infra: MTA-STS status note - cert pending stable HE.net DNS propagation 2026-06-06 19:37:37 -05:00
justin
7bd2f70de4 infra: MTA-STS policy + vhost + README (cert pending DNS propagation) 2026-06-06 19:36:27 -05:00
justin
eea1d02045 trust/security: add RFC 9116 /.well-known/security.txt + /security trust page (verified TLS A+/SOC2/HIPAA-PCI, security practices, vuln disclosure) 2026-06-06 19:34:18 -05:00
justin
a56ee01d96 fix(pricing): Trucking/DOT header was invisible (bg-orange-500 purged from CSS) -> inline orange background 2026-06-06 18:19:54 -05:00
justin
3d4269a053 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 2026-06-06 18:08:49 -05:00
justin
6c9956d14c about: real founder headshot (face-detected crop from suit photo) replacing placeholder 2026-06-06 18:07:01 -05:00
justin
9eceb18f3e about: add color - gradient hero (navy->teal) + uppercase pill, teal-fade 'What we do', teal/blue founder section, color-varied approach icons 2026-06-06 16:58:36 -05:00
justin
ea0937f723 about: remove Cherry Voice reference from founder bio (company was sold) 2026-06-06 16:53:39 -05:00
justin
971eb8d9d0 about: rewrite founder bio with Justin Hannah's real background (20+ yrs telecom/VoIP, President of Carrier One since 2001, Asterisk/FreeSWITCH pioneer, payments) from LinkedIn 2026-06-06 16:53:11 -05:00
justin
0b51d400f9 about page: add healthcare to firm story + 'What we do' (Medicare/PECOS/NPI, accuracy-verified filings); add founder bio for Justin Hannah with photo placeholder + LinkedIn link 2026-06-06 16:52:09 -05:00
justin
3da7794a85 hc email: add 'verify every detail for accuracy' (core strength) so the filing isn't rejected 2026-06-06 16:49:36 -05:00
justin
4233c90a4f hc email: reframe value-add to 'No 2FA. No government portals.' (we have a portal; the pain is CMS 2FA/identity-proofing); cron creates fresh dated campaign when prior is finished; add hc bounce watcher (Postfix->listmonk-hc webhook, hard/complaint->blocklist) 2026-06-06 16:47:12 -05:00
justin
2c4854f2db hc tracking: fix listmonk-hc app.root_url (was localhost:9000 -> zero views) to public domain + enable individual tracking; verified pixel records views 2026-06-06 16:40:22 -05:00
justin
6738a335af infra: nginx vhost for listmonk-hc admin portal (lists-hc.performancewest.net -> 127.0.0.1:9101, LE cert) 2026-06-06 07:02:50 -05:00
justin
2aa9e770c9 healthcare email: add color variety - amber warning box (urgency) + red overdue date + green price/CTA, breaking up the all-teal look into a problem->relief->action color story 2026-06-06 04:58:44 -05:00
justin
8eea9a694f healthcare email: add 'About Performance West' explainer (regulatory compliance consulting firm) after the no-logins relief copy 2026-06-06 04:57:42 -05:00
justin
0d212787ef healthcare email: add 'No logins. No portals. No headaches.' value-add (sells the relief, hides the mechanics); research doc on verified no-login third-party submission paths 2026-06-06 04:53:26 -05:00
justin
53ec011198 email trust signals: add data-safety + guarantee + social-proof strip to HC, telecom (campaign_template), and trucking (6 source + active campaigns via injector). Vertical accents: teal/blue/orange 2026-06-06 04:13:16 -05:00
justin
95698852ce healthcare warmup: gate Google/Workspace domains out of week 1 (they hard-reject cold IPs 550-5.7.1); send 501 non-Google practice domains first, defer 222 Google to week 2-3; cron uses hc_warmup_nongoogle.csv 2026-06-06 04:02:00 -05:00
justin
2bc86268f7 healthcare: HC warmup campaign cron (Mon-Fri 7AM Central) - imports overdue-first verified slice into listmonk-hc + runs Medicare-revalidation campaign via hc HOT stream; rate-throttled by pw-hc-rampcap 2026-06-06 03:57:08 -05:00
justin
2d3bccd31e healthcare email: white logo for teal header (was dark navy, invisible); drop NPPES-source footer line 2026-06-06 03:48:04 -05:00
justin
29c7a421e9 healthcare email: teal gradient header (matches site hero) + standalone CSV MX/SMTP verifier (binds .72 non-sending IP); gitignore PII warmup lists 2026-06-06 03:39:19 -05:00
justin
5129ebec5c healthcare email: add List-Unsubscribe/List-Id/Date/Precedence bulk headers to improve inbox placement on the cold hc IPs 2026-06-06 03:31:22 -05:00
justin
3859557506 healthcare: +$200 across all 6 provider services; add segmented marketing email builder (5 compliance-problem campaigns) + rendered HTML 2026-06-06 02:33:46 -05:00
justin
9bcd27db80 feat(site): vertical-specific order-page headers (trucking/telecom/healthcare/corporate) via unified VerticalOrderHeader; apply to all 49 order pages; retire TruckingOrderHeader 2026-06-06 01:52:22 -05:00
justin
695c3e2431 security: drop all CBC TLS suites (Qualys WEAK -> AEAD-only, still A+); sync ansible nginx templates (ciphers + ywxi CSP); capture host firewall as IaC 2026-06-06 00:49:21 -05:00
justin
113c73b392 feat(site): meter TrustedSite trustmark to order+healthcare pages only (free tier 500 impr/mo); auto-detect by path; CSP allows cdn.ywxi.net 2026-06-06 00:32:46 -05:00
justin
780b4219d3 feat(site): stage TrustedSite trustmark slot (opt-in prop) + setup doc; CSP/verification steps pre-documented 2026-06-06 00:27:02 -05:00
justin
af0b1d2306 feat(site): wire TrustStrip site-wide (Base layout); fix homepage trust strip (SecurityHeaders A not A+) + add SOC2/HIPAA-PCI badges 2026-06-06 00:25:59 -05:00
justin
5526fb79b9 security: harden nginx TLS ciphers (drop SHA-1 CBC -> HIPAA/NIST clean, still A+); document ImmuniWeb free badge + PCI/HIPAA/NIST/GDPR compliance 2026-06-06 00:22:59 -05:00
justin
6121c0a6f4 security: harden VM - nft+DOCKER-USER firewall closing public exposure of postgres/k8s/forgejo/listmonk/apis; remove inbound :25 (send-only); docs 2026-06-06 00:18:02 -05:00
justin
60ec4599b9 feat(site): add TrustStrip component (legitimately-earned trust seals: SSL Labs A+, Security Headers A, Stripe PCI, TLS/HSTS, SOC 2 datacenter) 2026-06-06 00:12:23 -05:00
justin
68333148e6 fix(npi): two-tier Direct/HISP classifier so real Direct-Primary-Care/counseling practices stay institutional (was wrongly parked); add classifier unit tests 2026-06-06 00:09:42 -05:00
justin
c3b2c4e89a hc-email: prod listmonk_hc installed + 3 SMTP servers + rampcap cron; end-to-end validated to Gmail via .107-.109 2026-06-05 23:12:03 -05:00
justin
7d61b4aad4 dev: remap api(3002)/site(4323) ports in override to avoid prod collision on shared host 2026-06-05 23:07:22 -05:00
justin
61dac80dc6 hc-email: PTR/FCrDNS for hc IPs (.107-.109 -> hcmta01-03) done + SPF/DKIM/DMARC verified 2026-06-05 23:01:34 -05:00
justin
8c51fa4b99 docs: record dual-stream implementation status + remaining DNS/prod steps 2026-06-05 19:22:02 -05:00
justin
90d8b94f3f feat(email): wire listmonk-hc into deploy + dev override + hc ramp-cap
- deploy.sh/deploy-dev.sh: bring up listmonk-hc (upstream image, excluded from
  build); document the one-time listmonk_hc DB create + --install.
- docker-compose.dev.override.yml: dev-only override (committed) that drops the
  prod host-port bindings and pins dev's own postgres volume (dev-pgdata) via
  compose !override tags. deploy-dev ships it as docker-compose.override.yml so
  syncing the canonical compose to the shared host no longer breaks dev's
  api-postgres (port :5432 clash + volume switch). Discovered + fixed while
  validating listmonk-hc on dev.
- pw-hc-rampcap.sh: healthcare analogue of pw-listmonk-rampcap, ramps the
  listmonk_hc cap 100->1000/h off /etc/postfix/hc-warmup-start, fully
  independent of the trucking ramp/cap.
2026-06-05 19:19:45 -05:00
justin
08d5132459 feat(email): add listmonk-hc second instance for the healthcare HOT stream
Isolated from the trucking listmonk: own DB (listmonk_hc), own uploads volume,
own sliding-window cap. Configured (on dev) with 3 SMTP servers pointing at the
host Postfix hc submission ports 2526/2527/2528 so it round-robins the dedicated
hc IPs .107/.108/.109. Reaches the host MTA via the docker bridge gateway.

Note: the listmonk image needs an explicit one-time '--install --idempotent
--yes' against listmonk_hc (env vars alone do not auto-install this image tag).

Validated on dev: listmonk-hc container (172.19.0.16) -> host :2526 (hcsubmit107)
-> hcout1 (.107) -> real gmail MX; both listmonk instances Up.
2026-06-05 19:18:35 -05:00