Documents the 2026-06-18 reputation incident (snowshoe -> Gmail domain-rep
blocks, RBLs all clean), the single-IP-per-stream consolidation, and
fill-in-the-blanks setup steps for Google Postmaster Tools, Microsoft SNDS/JMRP,
and Yahoo CFL (all require owner account login + HE.net DNS). Plus ongoing
hygiene + how to re-expand IPs once reputation recovers.
Checkout half proven against live Stripe (dry-run session created + expired,
zero charge), webhook subscription-id extraction + worker renewal fulfillment
covered by unit tests (31 + 13). Remaining gap: full E2E with a Stripe test
clock, which needs test-mode keys in the server .env (currently unset).
The 3 subscription-lifecycle events (invoice.paid, invoice.payment_failed,
customer.subscription.deleted) are now enabled on the live endpoint
we_1THBjyB46qMvF2jnYyN8IfkK (6 events total). Documents the unpinned-endpoint
api_version caveat (account default 2024-12-18.acacia, not the SDK's dahlia) and
why invoiceSubscriptionId() must read both invoice shapes. Notes that
charge.dispute.created / balance.available are handled in code but not yet
enabled on the endpoint.
Convert OIG/SAM from one-time $299/yr to recurring $79/month (card+ACH only) -
the first real recurring-billing product in the system. Exclusion screening is
a *monthly* federal obligation, so recurring monitoring fits the requirement and
is the biggest valuation lever (vs a one-time annual run).
Catalog (single source of truth):
- service-catalog.ts: add billing_interval + allowed_methods to ComplianceService;
oig-sam-screening -> 7900c, billing_interval:"month", allowed_methods:[card,ach],
name "(Monthly Monitoring)".
- gen-service-catalog.py + check-service-catalog-drift.py: carry/guard the two new
fields; regenerate site catalog.
Checkout (api/src/routes/checkout.ts):
- mode:"subscription" with recurring price_data when billing_interval is set;
surcharge absorbed for recurring (clean $79/mo); server-side METHOD_NOT_ALLOWED
re-validation against allowed_methods.
- ensureColumns + migration 100: compliance_orders.stripe_subscription_id,
bundle_upsell_sent_at (+ subscription index).
Webhooks (api/src/routes/webhooks.ts):
- record stripe_subscription_id on checkout.session.completed (subscription mode).
- invoice.paid (subscription_cycle only) -> re-dispatch screening for the cycle;
invoice.payment_failed -> admin alert + first-failure customer nudge;
customer.subscription.deleted -> mark order cancelled. (API 2026-03-25 moved the
subscription link to invoice.parent.subscription_details.subscription.)
Fulfillment:
- job_server.py: pass recurring_cycle/invoice_id into the order.
- npi_provider.py: OIG handler labels renewal cycles "[Monthly cycle]" + re-screen
note; bundle action runs only the FIRST screening + flags the $79/mo upsell.
Bundle land-and-expand:
- Provider Compliance Bundle now includes only the first OIG/SAM screening (was
giving away $948/yr of monitoring inside an $899 bundle).
- new worker scripts/workers/bundle_upsell.py (+ pw-bundle-upsell timer): ~3 weeks
after a paid bundle, emails the customer to continue $79/mo monitoring; dedup via
bundle_upsell_sent_at; skips customers who already have an OIG/SAM order.
Surfaces updated to $79/mo: PaymentStep (filters methods, "Billed every month,
cancel anytime"), order pages, healthcare index, npi-compliance-check tool (also
fixed stale $699 bundle drift -> $899), hc_oig_screening + hc_compliance_bundle
emails.
Docs: billing.md gains a "Stripe-native Subscriptions" section + a reality-check
banner (Adyen/ERPNext-gateway model documented there is NOT live; Stripe is the
real rail). Fixed run-migrations.yml container name bug
(performancewest-postgres-1 -> performancewest-api-postgres-1, overridable).
Tests: api/tests/recurring-subscription.test.ts (28 assertions) covers catalog
gating, method validation, surcharge suppression, recurring line-item build,
invoiceSubscriptionId extraction, renewal-cycle gating. tsc clean; site build
clean; catalog drift OK.
Manual deploy step: enable invoice.paid, invoice.payment_failed,
customer.subscription.deleted on the Stripe webhook endpoint.
Replaces the panic-era burner-domain verification plan with an in-house
automatic catch-all rollout in the trucking/IFTA/UCR builders. Root-cause
classification of the 75k pre-DKIM-fix bounces showed ~55% were reputation/
auth (now fixed by DKIM signing) and only ~29% genuinely-dead mailboxes;
catch-all domains accept at RCPT time so they do not user-unknown bounce at
send, making a controlled in-house bleed safer than warming a separate burner.
catch_all_enabled() adds catch-all results only when warmup_day >=
CAMPAIGN_CATCH_ALL_MIN_DAY (21) AND the recent 2-day live bounce rate is below
CAMPAIGN_CATCH_ALL_MAX_BOUNCE_PCT (8%) on a >=300-sent sample; auto-reverts to
the clean smtp_valid/send_confirmed pool on the next run if bounces spike.
Short window so a past disaster cannot block the rollout forever and a fresh
spike trips fast. CAMPAIGN_INCLUDE_CATCH_ALL=1/0 still hard-overrides.
USABLE_FILTER (static) -> usable_filter() (per-run, memoized, one DB probe).
IFTA/UCR SELECT_SQL -> _select_sql() so tc.usable_filter() resolves at call
time, not import. 13 logic unit tests pass; live dry-run decision = OFF
(day 15 < 21 and recent 2d bounce 42% from the aging-out Jun-16 disaster).
SMTP2GO is no longer used: Listmonk relays through the local Postfix MTA
(172.18.0.1:25 from the Docker network), which DKIM-signs and delivers
direct-to-recipient-MX; transactional mail goes through Carbonio. Verified
zero smtp2go in any live container env + postfix has no external relayhost.
Removed the stale references so a rebuild/new dev can't re-introduce it:
- api/src/config.ts: SMTP_HOST default mail.smtp2go.com -> co.carrierone.com
- scripts/workers/crypto_payment_worker.py: same default fix
- infra/ansible all.yml: listmonk_smtp_* now 172.18.0.1:25, no auth (+comment)
- app.env.j2 / email.ts / crm.md / go-live-todo.md / architecture.svg: docs
The FMCSA census was a one-time snapshot (last loaded ~May 30) with NO refresh
timer -- carriers newly falling out of MCS-150/UCR compliance were never picked
up. New scripts/workers/fmcsa_source_refresh.py orchestrates the full pipeline
(census download -> enrichment -> deficiency flag -> verify new emails ->
MX-tag new) and runs weekly via cron pw-fmcsa-refresh (Sun 09:00 UTC), codified
in the mail-pipeline Ansible role.
Idempotent + incremental: the census upsert preserves email_verified /
listmonk_sent_at / deficiency_flags, so existing carriers keep their send state
and only census fields refresh; new DOTs flow into verification then campaigns.
A carrier who refiled gets a fresh mcs150_parsed, so the builder's overdue
WHERE clause stops targeting them automatically. Verify is capped per run
(20k) so it never stalls on millions of rows.
(Healthcare already auto-catches newly-revalidation-overdue providers within
its 63k institutional pool via pw-hc-refresh Mon/Wed/Fri.)
Root cause of the Jun 2026 deliverability collapse / 'no new sales':
opendkim.conf was in single-key mode with no InternalHosts, so it signed only
127.0.0.1. Transactional/cron mail (injected locally) was signed, but ALL
campaign mail -- injected over the Docker bridge from the Listmonk containers
(172.18.0.5 trucking, 172.18.0.25 healthcare) -- went out UNSIGNED. Gmail/Yahoo
require DKIM on bulk mail since Feb 2024, so cold campaigns were junked/blocked
(~23% delivery, 550-5.7.1). Proof: 2,620 campaign msgs that day, 0 DKIM sigs.
The correct table files already existed on the server but were never wired into
opendkim.conf. Fix points the daemon at key.table/signing.table and sets
InternalHosts/ExternalIgnoreList to trusted.hosts (which includes 172.16.0.0/12,
the Docker subnet). Fixes BOTH streams: HC submission ports 2526-2528 inherit
the global smtpd_milters and *@performancewest.net covers compliance@.
Verified by injecting from a Docker IP through port 25 and port 2526 -- both now
get 'DKIM-Signature field added'. Codified as new Ansible role 'mail' so it
can't silently regress (OpenDKIM was previously not in IaC at all).
The smtp_valid pool is only ~3k unsent — too small to sustain campaigns. SMTP
probing can't confirm catch-all/mx_unreachable deliverability; only a REAL send
can. burner_list_verify.py reconciles a verification send from a DISPOSABLE burner
domain (isolated from PW/carrierone reputation):
- hard bounce -> fmcsa_carriers.email_verify_result='hard_bounced' (excluded)
- delivered -> 'send_confirmed' (proven deliverable; PW campaigns send to it)
It tails the burner MTA mail.log (reuses bounce-watcher's status= pattern) and
writes back idempotently. The PW trucking filter now treats smtp_valid +
send_confirmed as sendable. docs/campaign-deliverability-plan.md captures the full
diagnosis, the burner design, and CAN-SPAM guardrails.
Remaining (needs a domain + isolated MTA identity — operator/infra decision):
stand up the burner domain, the verification-send worker, and a writeback cron.
SC for-hire PROPERTY carriers (not passenger/HHG/hazwaste) register intrastate
via the SCDMV Certificate of Compliance (COC), not a PSC certificate. This adds:
- sc_coc_pdf_filler.fill_sc_coc(): fills the official SCDMV Form COC from
intake (business name, officers, physical/mailing address, phone), picks
New vs Renewal, and stamps the coverage class (E-L low-value / E-LC).
Field names in the source PDF are auto-generated + offset from their labels;
mapped here by verified on-page geometry. Verified by render.
- suggest_coverage_class(): E-L for low-value cargo (scrap/dump/aggregate),
else E-LC (safer default).
- gov_fee: SC intrastate fee corrected from $0 placeholder to the real $25
COC new-application fee (renewals $0), billed at cost.
The carrier's INSURER files the Form E (liability) + Form H (cargo, E-LC only)
directly with SCDMV; we collect the COC app + $25 and submit it.
deploy.sh ran sync_nav.py / gen-service-catalog.py which dirty site/public +
site/src in place; that made 'git pull' abort, so recent commits never reached
prod until pulled manually. Reset those generated paths before pulling so deploys
always fast-forward. Also document the IRP POA signer-name/title follow-up.
Companion to the worker MinIO-retry fix. Makes the worker auto-recover from
process death (crash, manual kill, missed boot trigger), not just MinIO outages.
- start_worker.bat: propagate Python's exit code (exit /b %rc%) so Task
Scheduler can actually detect a failed run (it previously always exited 0).
- reconfigure_task.ps1 (new): re-registers PW-DocserverWorker with
RestartCount=99 / 1-min interval, StartWhenAvailable, and two triggers —
AtStartup plus a 5-min repeating trigger with MultipleInstances=IgnoreNew, so
a dead worker relaunches within ~5 min and never double-runs. Idempotent.
- install.ps1: same self-healing settings for fresh installs.
- Verified on the box: killed the worker -> task relaunched it; firing again
while running stayed at one instance.
Docs updated to match reality:
- docserver/README.md: new 'Reliability / self-healing' section.
- document-generation.md: corrected the stale 'Flask DocServer :5050 / HTTP'
description to the actual MinIO outbound-only transport.
- e2e-test-plan.md: removed the outdated 'Word COM fails under SYSTEM / requires
RDP after every reboot' limitation; now self-healing under SYSTEM session 0.
- infrastructure.md: fixed VM spec (Win Server 2019, Word 16.0, Python 3.13,
SSH port 22422) + self-healing note.
- architecture.md / formation-system.md: trigger + self-healing details.
Ran the email-findability pilot we should have run for CLIA. SEC/OTC is viable:
~940 US-domestic OTC issuers, domain recoverable from the 10-K/8-K filing itself
at ~100% (free, no scrape), email via site scrape ~25-50%, phone 100%. High
per-deal value (reincorporation/RA/foreign-qual/franchise tax). Documented the
build plan.
Synthesize this session's findings into a ranking of candidate verticals by the
one thing that actually gates cold email: a reliable public bulk source of
deliverable emails. Tier 1 (email native): FCC, FMCSA. Tier 2 (one free hop):
healthcare ORG NPIs (already harvested 63k verified), SEC/OTC corporate. Tier 3
(domain-scrape): FMC OTI, state business entities by trigger. Tier 4 (phone/mail
only, NOT email): CLIA (0.3% match proven), EPA RCRA, individual NPIs.
Capture the full decision trail and chosen approach for making CLIA labs
emailable: why NPI->NPPES (0.3%) and DirectTrust failed, datacenter-IP search
blocking, the $99 B2B-list -> email-domain -> scrape-current-email -> verify
pipeline (durable domain even when the mailbox is stale), hard rules protecting
the warming mail pool, gzip/HTML-only bandwidth optimization, residential proxy
options, the sample-validation gate before committing, what's already built
(harvest, service, order page, email template), and the postcard fallback.
CAN-SPAM requires a valid physical postal address in every commercial email.
All 8 HC campaign templates and the FCC campaign_template.html only had
'Cheyenne, WY' (no street) -- added the full
'525 Randall Ave Ste 100-1195, Cheyenne, WY 82001' to match the (already-correct)
trucking templates. Audited every Listmonk source/sent campaign + wrapper
templates: all active sends carry address + unsubscribe.
Also: revalidation segments now use hc_revalidation_personal.html with subject
'Let's make sure your Medicare revalidation is handled in time'.
The sales we got came at $79 + a 24hr coupon; cutting MCS-150 to $39 flat
removed urgency and conversions did NOT improve (a permanent low price sets a
new anchor and lets people defer). Restore the higher anchor and let an
expiring discount create the now-or-lose-it decision.
- Restore MCS-150 anchor $39 -> $79 (catalog single source + regenerated).
- build_trucking_campaigns.py: mint ONE random 5-letter coupon per send-day
(40% off, valid through 23:59:59 ET that day) into the existing discount_codes
table; inject coupon_code/pct/expires + a ?code= LP link into every email.
Idempotent per day; service-fee-only scope (gov/pass-through fees never cut).
- Listmonk MCS-150 (186) + Inactive USDOT (188) templates: lead with the
struck-through anchor + sale price + code + 'expires tonight', and point the
primary CTA at the order page (with code) instead of the 'free check' tool.
- OrderPriceBanner: validates ?code= via /api/v1/discount and shows
was/now + expiry; Wizard forwards the code to order creation.
- Verified: code gen, expiry math, scope enforcement, discount API
(40% off $79 = $47.40), site+api builds clean.
The saved Goal + Funnel reports used a pre-v3.1.0 parameters shape (urls/dateRange)
that umami 3.1.0's report schema rejects (400 -> 'Something went wrong'). Migrated
both reports in the umami DB to the current funnelReportSchema/goalReportSchema
(steps[], top-level dates, goal type/value). Verified funnel route now passes schema
validation. TODO updated/closed.
David Sgro (PA OAG complaint BCP-26-05-025816) opted out 2026-04-13; response
emailed to the AG 2026-06-11. To make the suppression bulletproof and keep the
response's representations true:
- Added a legal do-not-contact list (DO_NOT_CONTACT_DOMAINS/_EMAILS) to
_email_exclusions.py with dataspindle.com / dave@dataspindle.com; folded into
BLOCKED_EMAIL_DOMAINS and is_blocked().
- listmonk_import.upsert_subscriber now refuses to import/re-confirm any
suppressed address. This closes the exact gap that re-added him on 2026-04-26:
the duplicate-import branch re-added an existing unsubscribed subscriber to
lists with status=confirmed, overriding the opt-out.
Draft response to PA OAG Bureau of Consumer Protection mediation request.
Core arguments: (1) address came from his own public FCC RMD filing, not
scraping; (2) commercial email is governed by CAN-SPAM (opt-out, permits B2B),
not the fax/telemarketing 'Unsolicited Telecommunication Advertisement Act' he
cites; (3) opt-out honored same day (manual suppression Apr 13), now permanent;
(4) no purchase/harm; (5) the post-opt-out 'emails' he complains of were our
replies to HIS own argumentative emails, not solicitations. Marked DRAFT FOR
ATTORNEY REVIEW with bracketed items to confirm before sending.
The official MCS-150/150B/150C PDFs ship with 8 (150/150B) or 4 (150C)
FMCSA instruction/example pages before the actual fillable form. We were
generating + faxing/submitting all of them. Trimmed the source templates
down to the FORM pages only:
MCS-150 11 -> 3 pages (289 fields preserved)
MCS-150B 12 -> 4 pages (349 fields preserved)
MCS-150C 6 -> 2 pages (33 fields preserved)
The filler iterates writer.pages (no absolute index) and signature
anchors are derived dynamically via enumerate(reader.pages), so no
page-specific markup needed fixing. Removed one-off diag script.
The MCS-150 biennial update re-confirms the carrier's existing FMCSA
record. Previously the PDF filler only had whatever the intake form
collected; rescued/sparse orders (or orders where the carrier's data
lives in FMCSA, not the intake) produced near-empty forms. Now we pull
the carrier census (legal name, address, EIN, fleet counts) from the
FMCSA carrier API and merge it under any customer-provided intake values
(customer edits win), so the form is pre-filled with the carrier's
current registered data. Refactored the FMCSA fetch into a shared
_fetch_fmcsa_carrier helper used by both enrichment and status check.
E2E harness re-run = ALL PASS: TX returns real availability via the open-data API,
NV returns unknown (available=None) to flag manual verification, both flow through
to correct ERPNext Sales Orders. Removed one-off portal-probe scripts.
E2E harness exposed that the NV name-search adapter times out on a stale input
selector and search_name() swallowed the error and returned available=False --
i.e. it would tell customers an AVAILABLE name is taken. Now returns
available=None ('could not determine') on adapter error / unknown state, which the
API already maps to null. The NV/TX portal selectors still need a scraping fix
(separate task; e2e harness is the acceptance test) before enabling a self-serve
formation checkout. Documented full e2e results + the bugs caught (missing ERPNext
Items, entity_type case, missing /name-search route) in the readiness doc.
A DE corp foreign-qualified in CA/NY/etc must update EVERY foreign registration
when it domesticates (withdraw in the destination state since it becomes domestic
there; amend or re-file in the rest to reflect the new home state) -- getting it
wrong = doing business unregistered (default judgments/penalties). We already have
the building block (foreign-qualification-single/multi SKU + ForeignQualificationHandler
that fans out per state + migration 066/073 schema); missing is amend/withdraw modes
+ an intake step capturing the list of qualified states. Product = multi-part, priced
per state touched (revenue multiplier), scoped at intake.
New page /services/corporate/dexit-reincorporation (matches CRTC service-page
structure): explains DEXIT, the DE franchise-tax dollar driver (real Oracle Health
proxy: $23,600 -> ~$1,000), NV/TX/FL destination guidance, 6-step how-it-works,
3 cited real SEC reincorporation filings (Oracle Health, FG Financial, LogicMark)
with verbatim quotes + EDGAR links, honesty callout, and a lead-gen CTA ('Get my
DEXIT estimate' -> /contact?topic=dexit, NOT a buy-now checkout). Linked from the
corporate services index (new card) + the global Services dropdown across the site.
docs/dexit-cited-filings.md: the filing excerpts + verified gov/statute links.
docs/dexit-readiness-assessment.md: HONEST e2e readiness -- new NV/TX formation is
built (checkout order_type=formation -> formation_orders -> ERPNext SO ->
formation_worker -> TX/NV adapters) but unverified e2e; the 'move a company'
(conversion/domestication) flow + corporate annual-report automation are NOT built;
EIN is kept on a conversion (our ein_worker does NEW EINs only). Page stays lead-gen
until the generic entity-conversion SKU + admin-assisted handler are built+tested.
Grounded in real reincorporation proxies. WHO: microcap CEO/founder/CFO/secretary
(no legal dept -> decision-maker, not gatekeeper). WHAT they want: (1) cut the DE
franchise tax -- the hard-dollar driver; real proxy shows a pre-revenue startup
paid $23,600 DE franchise tax vs ~$1,000 in NV; (2) stronger D&O liability shield
(NRS 78.138); (3) escape DE's 2024 case-law shift; (4) TXSE/story optionality.
HOW to convert: lead with their dollar math not features, productize the dread
(flat fee, we do filing legwork, lawyer just signs), recommend the destination,
stack recurring RA + annual-report revenue, de-risk with guarantee + verifiable
sources.
scripts/otc_lead_pull.py: pulls company_tickers_exchange.json + per-issuer
submissions/CIK*.json from SEC EDGAR (10 req/sec, declared User-Agent), filters
to active US-domestic microcaps (drops foreign ADRs, accelerated/large filers
that keep counsel on retainer, and delinquent/dark shells), writes a CSV with
state of incorporation, business/mailing address, phone, SIC, filer size bucket,
last filing date. DE/NV prioritized.
docs 4c: where companies actually reincorporate TO -- Nevada #1 (281 filings),
Texas the fast riser (99 all-time, but 27 vs NV 33 since 2024), Florida modest
(23), Wyoming niche (8). Lead with 'leaving Delaware?' and let client pick
NV/TX/FL; same flat-fee conversion productizes across all three.
SEC filer-category data (n=139 US-domestic OTC): ~93-95% are sub-$75M-float
Smaller Reporting / non-accelerated microcaps; only ~4-5% are accelerated/large
(those keep securities counsel on retainer -- not our lane). 91% actively filing.
Recommend filtering OUT Large accelerated/Accelerated + delinquent/dark -> ~700-850
active microcap prospects. Pitch framing: not 'replace your lawyer' but 'flat-fee
commoditized state filings so counsel only does what needs a lawyer'.
SEC EDGAR (free, public, bulk-OK at 10 req/sec) is the goldmine -- per-issuer
state of incorporation, business/mailing address, phone, SIC, entity type via
company_tickers_exchange.json + submissions/CIK*.json. ~2,771 OTC SEC filers;
~35% US-domestic (~970), of which DE+NV = 73% -> the reincorporate-to-Texas /
registered-agent / annual-report / foreign-qualification target list. EDGAR has
no email (enrich from IR pages or direct mail/call). Texas reincorporation is a
real early trend (48/43 EDGAR filings; TBOC Ch.10 conversion, Texas Business
Court, TXSE). CAN-SPAM compliant B2B; filter to US states to avoid CASL/GDPR.
Do NOT scrape OTCMarkets.com (ToS prohibits; unneeded).
A lead replied with proof their Medicare revalidation was already approved (CMS
data-lag: the public Revalidation Due Date List still showed them overdue weeks
after approval). Two of these arrived same-day, so:
- Carbonio auto-reply (deployed on co.carrierone.com): created mailbox
hc-replies@ on the info@ distribution list with a Sieve that auto-acknowledges
'my revalidation is already complete' replies (tag + mark read + file into a
'Reval Completed (auto-acked)' folder + on-brand reply explaining the CMS lag).
CRITICAL: info@ is the shared reply-to for ALL campaigns (healthcare, trucking,
telecom), so every rule is anchored to Medicare/revalidation context -- a
trucking 'MCS-150 done, this is bogus' or telecom 'RMD done' reply does NOT
trigger it (tested + passing). A buyer guard ('please file / how much') also
suppresses the auto-reply so a human handles the sale.
Carbonio 25.x Sieve quirks documented (vacation/imap4flags/body :text all
unsupported; use reply/flag/tag/body :contains).
- Permanent suppression: new data/hc_suppress.txt do-not-contact list the warmup
honors at import AND --prune removes from the live lists. Seeded with the two
completed providers (Pangea Lab, Yakima Valley FWC); both also blocklisted in
listmonk_hc and removed from lists 3 + 4.
Consent gate (the legal linchpin from the wet-signature memo):
- migration 092 adds ink_consent/ink_consent_at/ink_consent_text to esign_records
- extract pure, unit-tested gate logic into esign-ink-consent.ts (DRY single
source for route + signing page): isInkReproduction / inkConsentRequired /
inkConsentSatisfied + verbatim client-safe INK_CONSENT_TEXT
- portal-esign-generic.ts: GET surfaces ink_reproduction + consent text; POST
gates DRAWN signatures on ink-path docs on explicit consent, stores it
- signing page locks the signature block until consent is checked (drawn only)
- npi_provider marks cms855/cms10114 esign metadata ink_reproduction=true
- 33 unit checks: gate truth table + consent text omits all internal mechanics
(plotter/machine/CMS/MAC/etc) and keeps required legal reassurances
Patent-risk memo (docs/legal/patent-risk-mechanical-wet-signature.md):
- prior-art-dated risk analysis (autopen 1803/1942, plotters, CNC = public domain
=> low risk on core concept; e-sign workflow space litigious)
- firsthand recent-grant sweep (1.58M USPTO grants 2021-2025, queried via DuckDB):
ZERO patents on machine-applies-signature-in-ink; e-sign players hold only
electronic-workflow patents. Not an FTO; flags where attorney search is needed
Two internal docs:
- docs/plans/remote-wet-signature-products.md: opportunity map for new remote
signing/filing services that leverage the existing esign + wet-ink + fulfillment
stack (83(b) IRS filings, apostille concierge, estate packages, mechanics
liens, FinCEN BOI / SAM.gov renewals, RON layer, proof-of-life attestations).
Prioritized by revenue x fit x moat; top 3 = 83(b), apostille, estate package.
- docs/legal/remote-mechanical-wet-signature-precedent.md: source-grounded legal
research on whether a machine-applied wet-ink signature (autopen/plotter
reproducing the signer's own captured strokes) is authentic/valid/accepted.
Primary sources retrieved firsthand: DOJ/OLC 2005 autopen opinion (29 Op.
O.L.C. 97); CMS-855B 'signatures must be original'; ESIGN 15 USC 7001/7006;
UCC 1-201 'Signed'. Key finding: common-law + autopen precedent strongly
support own-signature-by-directed-machine as VALID, but 'original ink / no
stamps' administrative rules (CMS-855) are UNADJUDICATED -> highest risk, keep
true wet-sign fallback. Notarized/witnessed instruments: do NOT use plotter.
Explicitly separates established law from interpretive/no-precedent zones.
Adds a second machine class (small fan-shaped reach arm) alongside the
CR-10/AxiDraw rectangular-bed plotters, so wet signatures can be produced
while away from the home station.
ink_signature_plotter.py:
- PlotterConfig gains dialect (marlin|lineus) + name; new LineUsConfig
(native units, pen height = per-move Z, reach annulus from shoulder pivot).
- Named machine profiles (cr10 default, axidraw, lineus) via load_profile().
- bed_mm_to_lineus_units(), check_reach() (annulus for lineus, rectangle for
marlin), compute_jig_offset_for_box() (solves jig from the ACTUAL fitted ink
extent so a wide cell line doesn't over-constrain a small arm).
- emit_gcode() dispatches to emit_marlin_gcode()/emit_lineus_gcode().
- send_lineus(): WiFi TCP 1337 (NUL-terminated, ok-acked) or USB serial,
dry_run=True default (same gating as the CR-10 path).
ink_signature_cli.py: --profile, --solve-jig (auto-applies jig offset),
--lineus-host/--lineus-usb, reach-check that refuses to --plot out-of-reach
on Line-us.
Tests: 43 checks (was 30) covering profiles, reach check, jig solve, lineus
emitter, dry-run sender. Docs updated with profiles + portable workflow.
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.
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.
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.
- 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).