# Contract seed driver

Creates freight contracts across every flow variant by driving the freight API
over HTTP end-to-end — from DRAFT through **both signatures** (customer sign +
staff counter-sign). It stops right after the staff counter-sign; no clearance
or booking steps are run.

## What it builds

20 real flows (movement × kind × customs × freight), each created twice → **40
contracts** on `all`.

| Movement | Kind | Customs | Freight | Count |
| --- | --- | --- | --- | --- |
| intercity (DOMESTIC) | one-time / general | without only¹ | bulk / container | 4 |
| import (IMPORT) | one-time / general | with / without | bulk / container | 8 |
| export (EXPORT) | one-time / general | with / without | bulk / container | 8 |

¹ intercity + customs is not a real combo — DOMESTIC has no clearance gate, so
the customs flag is ignored. Those four are skipped, leaving 20 (16 working + 4
`with-customs + bulk`).

The four `with-customs + bulk` flows are still built here: the known break is
downstream in clearance (customs output docs are container-only), which this
script does not reach, so all 20 reach a signed state.

## Terminal status after both signatures (by dimension)

- DOMESTIC one-time → `FULLY_EXECUTED`
- any GENERAL, and DOMESTIC general → `CONTRACT_ACTIVE`
- IMPORT/EXPORT one-time (customs or self-clearance) → `AWAITING_CLEARANCE_DOCUMENTS`
  (fully signed; clearance not driven)

## Setup

```bash
cd apps/edr-freight-api/py
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env      # then fill it in
```

Fill `.env`: customer + admin IAM credentials (admin should be a **super_admin**),
`OTP_PHONE`, and the Postgres connection (used only to read the sign-OTP).

## Run

```bash
python create_contracts.py                 # all 20 flows
python create_contracts.py intercity       # only DOMESTIC flows (4)
python create_contracts.py import          # only IMPORT flows (8)
python create_contracts.py import export   # IMPORT + EXPORT (16)
```

Filters are by movement: `intercity`, `import`, `export` (pass one or many);
no arg or `all` runs everything.

## How auth + OTP work

- **Login**: `POST /api/auth/login` with `{ email, password }` returns a JWT
  (`token`), sent as `Authorization: Bearer <token>`. MFA accounts are not
  supported — the script errors out clearly if MFA is required.
- **Actors**: the customer token does create/submit/customer-sign; the admin
  token does staff-accept/approve/generate/counter-sign.
- **Sign OTP**: customer sign needs a fresh 6-digit OTP. The script calls
  `POST /api/otp/send { phone }`, reads the plaintext code from
  `<schema>.otp_verifications` in Postgres, then signs within the 5-minute TTL.
