# Readiness: corporate orders + "move a company" (conversion / domestication)

Honest assessment as of 2026-06-09. Question: are we ready to take Nevada/Texas
incorporation orders end-to-end (name search, accept into ERPNext, etc.), and the
mechanics of moving a corp out of Delaware + annual report + EIN.

## Short answer
- **New NV/TX formation orders - order intake + ERPNext VERIFIED e2e; name search
  now FIXED for TX, and honest for NV.** The e2e harness (`scripts/e2e-formation-order.mjs`)
  confirms: live name search -> formation_orders insert -> ERPNext customer -> Sales
  Order with the correct `BUSINESS-FORMATION` + `STATE-FILING-FEE` line items and
  totals ($254 NV LLC, $479 TX corp) -> DB linkage, all PASS.
  - **TX name search now works** via the Texas open-data API (no scraping). Returns
    real availability (exact match => taken; no rows => available; error => unknown).
  - **NV name search returns "unknown"** (available=None) by design: the NV portal is
    behind Incapsula bot protection with no public API, so we flag NV names for a
    manual admin check rather than fake a result. Never a false "taken".
  - Still pending before a self-serve checkout: the actual NV/TX *filing* automation
    (SOSDirect login flow / SilverFlume) is unverified, and NV name search is manual.
    The DEXIT page points at a contact form, not this checkout.
- **"Move a company" (DE -> NV/TX conversion/domestication):** **NOT built.** There
  is no order type, no SKU, and no fulfillment for a conversion. This is the core of
  the DEXIT promise and is the biggest gap.
- **Annual report filing in the new state:** **NOT built** as automation. There is an
  `annual-report-filing` slug, but it is wired to the trucking admin-assisted handler
  (`MCS150UpdateHandler`), not a corporate state-filing flow.
- **EIN:** for a move you generally do NOT get a new EIN (see mechanics below); our
  `ein_worker` only obtains a NEW EIN, which is the wrong operation for a conversion.

So: **do not turn on a "buy now" DEXIT checkout yet.** Keep the page as a lead-gen
"get my estimate" CTA (which it currently is) until the flow below is built + tested.

## E2E test results (2026-06-09) and the name-search bug
Ran `scripts/e2e-formation-order.mjs` inside the api container against live prod
(real DB + real ERPNext, no real Stripe charge, no real state filing).

**PASS - order intake + ERPNext Sales Order (both NV and TX):**
- live formation_orders insert,
- ERPNext customer find/create,
- Sales Order created with `BUSINESS-FORMATION` + `STATE-FILING-FEE` line items,
  correct totals ($254 NV LLC = $179 + $75; $479 TX corp = $179 + $300),
- `formation_orders.erpnext_sales_order` linkage written,
- cleanup (cancel+delete SO, delete order row).

Bugs the harness caught and we fixed:
- The formation Sales Order referenced ERPNext Items `BUSINESS-FORMATION` and
  `STATE-FILING-FEE` (and `FOREIGN-QUAL-SINGLE/MULTI`) that **did not exist** -> the
  SO creation was silently failing on every formation order. Created the Items.
- `entity_type` check constraint requires lowercase (`llc`, `corporation`, ...).
- The API's `GET /states/:code/name-search` called `WORKER_URL/name-search`, but the
  worker had **no such route** (404 -> silent fallback to stale `entity_cache`).
  Added a synchronous `/name-search` worker route, and fixed `handle_name_search`
  (both referenced a nonexistent `search_name_sync`).

**FAIL (open) - live name search silently returns "unavailable" for everything.**
After wiring the route, a deliberately unique nonsense name still returns
`available=false` with no similar names. Root cause: the **NV state-portal adapter
times out** (`Page.fill: Timeout ... waiting for locator("input[type=text], ...")`)
because the Nevada SOS / SilverFlume search page no longer matches the adapter's
input selector, and `search_name()` swallows the exception and **defaults to
`available=False`**. So:
- We would wrongly tell customers an available name is taken (or never validate it).
- This is a **portal-scraping maintenance task**: inspect the current NV (and verify
  TX) name-search DOM, update `states/nv/adapter.py` (and `tx`) selectors/flow, and
  make `search_name()` distinguish a real "taken" result from an adapter error
  (return an explicit error/unknown state, never a false "taken"). NOTE the adapter
  also MIS-PARSES on its happy path: via the route a unique name still returns
  available=false (the search page content does not match the adapter's "no results"
  phrases), so the fix must update both the input selector AND the results parsing.
  We did harden the error path: search_name() now returns available=None on a thrown
  adapter error. The harness re-run is the acceptance test.

**Conclusion:** the ERPNext/order plumbing is sound and verified; **do not enable a
self-serve formation checkout until name search is fixed** (a customer must be able
to trust the availability check), and the "move a company" flow is still unbuilt.

## What already exists (the good news)
The corporate/formation machinery is real and reusable:
- **Checkout + order intake:** `api/src/routes/checkout.ts` has `order_type: "formation"`,
  builds a Stripe line item `Business Formation (<state> <LLC|CORP>)`, and the
  `formation_orders` table carries `stripe_session_id`, `payment_status`,
  `erpnext_sales_order`, etc. ERPNext SO creation is wired for formation orders.
- **Name search:** `GET /api/v1/states/:code/name-search` (24h cache in
  `name_search_cache`) -> calls the worker -> per-state adapter. **TX** uses the
  Comptroller Taxable Entity Search (free, no login); **NV** has an adapter too.
- **Filing automation:** `scripts/formation/` is a full subsystem -
  `formation_worker.py` polls `formation_orders`, `states/tx/adapter.py` +
  `states/nv/adapter.py` implement `search_name` / `file_llc` / `file_corporation`
  via Playwright (TX = SOSDirect, requires login + ASP.NET viewstate handling),
  plus `ein_worker.py`, `operating_agreement.py`, `document_delivery.py`,
  registered-agent via Northwest RA, and ~55 state adapters scaffolded.
- **The `FormationOrder` model** carries entity name/alt, members, RA, addresses,
  shares_authorized, par_value, expedited, payment card (Relay virtual debit), and
  result fields (filing number, confirmation, documents).

## What's missing for NEW NV/TX formation (smaller gap)
1. **E2E verification.** The TX/NV adapters target live state portals (SOSDirect
   needs an account login; both are ASP.NET/viewstate + possible CAPTCHA). We have
   not confirmed a clean run recently. Need: a staged dry-run (name search ->
   formation_orders insert -> worker pick-up -> ERPNext SO -> filing in a sandbox or
   a real low-stakes filing) with screenshots, and CAPTCHA handling confirmed.
2. **ERPNext SO for formation** exists in code; verify it actually creates the SO
   with the right items + state gov fee line (we hit a gap like this on the trucking
   compliance_batch flow - SOs weren't being created). Add NV/TX formation Items if
   missing (we created LLC-FORMATION / CORP-FORMATION recently).
3. **Pricing/SKU sanity:** TX/NV LLC = $300 gov fee, Corp = $300; expedite +$25/$50.
   Our `corp-formation` / `llc-formation` catalog entries need gov_fee plumbed.

## What's missing for "MOVE a company" (the big gap)
This is a different operation from formation. Real-world mechanics:

### The legal mechanic (two paths)
A company changes its state of incorporation by either:
- **(A) Statutory conversion / domestication** (preferred, cleaner): the entity
  re-domiciles. **Delaware** files a **Certificate of Conversion** to convert OUT
  (DGCL 266) and the **destination state** files a conversion/domestication in:
  - **Texas:** TBOC Ch. 10, Subch. C - "Certificate of Conversion" + new Certificate
    of Formation. The TX entity is a continuation of the DE entity (same legal person).
  - **Nevada:** NRS Ch. 92A.105+ "conversion"; file Articles of Conversion + new
    Nevada charter (NRS 78).
  - **Florida:** F.S. 607.11921+ conversion.
  Both DE-out and new-state-in filings are required. The entity keeps its identity,
  contracts, and history.
- **(B) Reincorporation merger** (older method, what FG Financial used): form a new
  NV/TX subsidiary and merge the DE parent INTO it. Requires an Agreement and Plan
  of Merger + stockholder vote. More moving parts; still common.

### Steps a real DEXIT order involves (none automated yet)
1. **Diagnose**: pull the entity's current DE status, authorized shares (to estimate
   the franchise tax saving), good-standing, foreign qualifications.
2. **Board + stockholder approval**: a board resolution and (usually) a stockholder
   vote/consent approving the conversion or merger. **This needs the client's counsel
   - it is NOT something we file.** Our role is to prepare the plan-of-conversion /
   plan-of-merger documents for their counsel to review and their board to adopt.
3. **Pay DE to leave**: DE requires the franchise tax to be **current** before it
   will accept the Certificate of Conversion (you can't leave owing tax). So step 0
   is often "file/pay the final DE franchise tax + annual report."
4. **File the conversion**: Certificate of Conversion OUT of DE (DGCL 266) +
   Certificate of Conversion/Formation INTO the destination state. Both have fees.
5. **New registered agent** in the destination state (recurring; we use Northwest RA).
6. **First annual report / state list** in the new state (NV requires an Initial List
   + State Business License at formation/domestication; TX has the Public Information
   Report / franchise tax with the ~$2.47M no-tax-due threshold).
7. **Update downstream**: foreign-qualification re-registration in states where the
   company operates (the domestication may need to be reflected), update the transfer
   agent / DTC, update EDGAR (state-of-incorporation on the next cover page), bank, etc.

### EIN reality
- A **conversion/domestication generally KEEPS the same EIN** - the IRS treats a mere
  change of state of incorporation (same entity continuing) as not requiring a new
  EIN in most cases. So our `ein_worker` (which obtains a NEW EIN) is the wrong tool
  for a move; for a conversion we typically do nothing with the EIN, or at most file a
  name/address change with the IRS.
- A **reincorporation MERGER into a new subsidiary** can be different: if the surviving
  entity is genuinely new, the IRS may require a new EIN. This is a fact-specific,
  counsel-driven determination - **we should not auto-decide it.**
- Net: EIN handling for a move is **advisory + occasionally a name/address update**,
  not the automated SS-4 flow we have.

### Why we can't fully automate the move
Unlike a fresh formation, a conversion is **counsel-gated** (board/stockholder
approval, plan-of-conversion review) and **DE-clearance-gated** (must be current on
franchise tax). The honest product is **admin-assisted**: we prepare and file the
state paperwork and set up RA + first annual report; the client's lawyer handles the
corporate-approval documents. That matches how the DEXIT page is already written
("your counsel just reviews the board and stockholder consent").

## Complication: the company has foreign qualifications in other states

This is common and important. A Delaware corp that operates in California, New York,
Texas, etc. is "foreign qualified" (registered as a foreign entity / has a Certificate
of Authority) in each of those states. When it domesticates DE -> NV/TX, every one of
those foreign registrations is affected. Getting this wrong means the company is
suddenly doing business unregistered in states where it operates - default judgments,
loss of court access, penalties. So this is part of the core offer, not an afterthought.

### What actually has to happen to the foreign registrations
After a conversion/domestication, the entity is the *same legal person* but its
**home (domestic) state changed**. In each state where it was foreign-qualified:
- **The state where it is moving TO** (say it domesticates to Texas but was foreign
  qualified in Texas): the foreign registration must be **withdrawn/cancelled** because
  the company is now a *domestic* Texas entity - you cannot be both foreign and
  domestic in the same state. (This is exactly why ~zero of our OTC sample were
  TX-incorporated even when TX-based: they were DE corps foreign-qualified in TX.)
- **Every OTHER state it was qualified in** (CA, NY, FL, etc.): the foreign
  qualification generally **stays in place but must be updated** to reflect the new
  state of incorporation and (often) a new formation date / charter document. States
  differ:
  - Some accept an **amendment to the foreign registration** (file an amended
    Application for Authority / Statement of Change reflecting the new domestic state).
  - Some require you to **withdraw the old foreign registration and re-file a new one**
    from the new home state.
  - A handful treat the domestication as a non-event if the name + identity are
    unchanged, requiring only an informational update at the next annual report.
- **Name conflicts** can surface: a name available to a DE corp as "foreign" in a state
  might collide on re-domestication; we should run name availability in each qualified
  state as part of the move.

### Good news: we already have the building block
We have a working **foreign-qualification** capability:
- SKUs `foreign-qualification-single` ($149 + state fee) and `foreign-qualification-multi`
  (discounted per-state), `ForeignQualificationHandler` that **fans out per state**,
  a `state_registrations`/foreign-qual schema (migration 066/073), and the same
  formation state-adapter pool. So re-qualifying or amending in N states reuses
  existing plumbing - we don't build it from scratch.
- What's missing is the **amend / withdraw** modes (the handler today is oriented to
  *new* registration), and an intake step that asks "which states are you currently
  foreign-qualified in?" so we can fan the move out across them.

### Product implication
The conversion offer should be **multi-part and priced per state touched**:
1. Core domestication (DE-out + new-state-in) - the base fee.
2. For each state the company is foreign-qualified in: an **amend / re-qualify /
   withdraw** line item (reuse foreign-qualification per-state pricing).
3. Withdraw the now-redundant foreign registration in the destination state if one
   existed.
4. Update the registered agent in each affected state where we maintain it.

This is also a **revenue multiplier**: a single DE corp qualified in 5 states is one
domestication + ~5 foreign-qual amendments + recurring RA/annual-report in each. But
it must be scoped at intake - we have to ASK for the list of states up front, estimate
per-state, and disclose that government fees vary and are billed at cost.

### Intake + data we must capture for a move
- current domestic state (DE), destination state (NV/TX/FL), entity type
- entity name + EIN (kept), current good-standing + franchise-tax status in DE
- **the full list of states where the company is foreign-qualified** (and its DBA/
  assumed names in each) - this drives the per-state fan-out
- where it actually operates / has nexus (to advise whether to keep each qualification)
- whether counsel is handling the board/stockholder consent (always yes)

## Recommended build plan (generic corporate flow + a "move" capability)
Keep it generic, not DEXIT-specific:

1. **Catalog SKUs** (in `api/src/service-catalog.ts`):
   - `entity-conversion` (move a company; admin-assisted; flat service fee + state
     gov fees billed at cost; destination state chosen at intake).
   - Confirm `corp-formation` / `llc-formation` carry per-state gov_fee.
   - `annual-report-filing` for corporate (today it points at the trucking handler).
2. **Order type**: add `order_type: "entity_conversion"` to checkout + a
   `from_state` / `to_state` / `entity_type` intake, persisted in `formation_orders`
   (or a sibling table). Reuse the Stripe + ERPNext SO path.
3. **Fulfillment**: a `ConversionHandler` (admin-assisted) that:
   (a) runs name availability in the destination state (existing name-search),
   (b) generates the plan-of-conversion + new-state charter draft for client/counsel,
   (c) queues the DE-out + destination-in filings for the formation_worker once the
       signed board/stockholder consent + DE good-standing are confirmed,
   (d) sets up RA + files the first annual report/state list.
4. **E2E test harness**: a scripted run that does name search -> creates a paid test
   order -> verifies `formation_orders` row + ERPNext SO + worker pickup, with the
   actual state filing stubbed/sandboxed so we don't make a real filing during tests.
5. **Verify NV/TX formation e2e FIRST** (smaller scope) before layering conversion on
   top, since conversion reuses the same filing + ERPNext + worker plumbing.

## Bottom line
- The page is fine to ship as **lead-gen** (estimate request), which is what it does.
- We are **not** ready for a self-serve "buy a DE->NV/TX move" checkout. New NV/TX
  formation is close but unverified e2e; the conversion ("move") flow and corporate
  annual-report automation do not exist yet.
- Next concrete step (if you want to proceed): verify NEW NV/TX formation e2e, then
  build the generic `entity-conversion` SKU + admin-assisted handler on the existing
  formation plumbing.
