|
| 1 | +# KYC singleton flow — implementation plan (Phase 1, grid-api slice) |
| 2 | + |
| 3 | +## Context |
| 4 | + |
| 5 | +Design proposal in [grid-api#700](https://github.com/lightsparkdev/grid-api/pull/700) — approved, currently on R12. This PR is the **Phase 1 grid-api slice**: OpenAPI schema additions and Mintlify sandbox docs. Backend sparkcore work ships as a separate PR in `webdev/sparkcore`. OFAC / LexisNexis handling is treated as separately-scoped work per Aaron. |
| 6 | + |
| 7 | +The full phasing lives in #700's "Implementation phasing" section; this plan documents only what changes in this PR. |
| 8 | + |
| 9 | +## Phase 1 — grid-api items |
| 10 | + |
| 11 | +Roughly one commit per item; ship as a single PR since they all touch the same OpenAPI surface. |
| 12 | + |
| 13 | +- **§1 `taxIdentification[]`** on `IndividualCustomerFields.yaml` (optional array of `{idType, identifier, countryOfIssuance}`; reuses existing `IdentificationType` enum). |
| 14 | +- **§1a Optional EDD extras** on `IndividualCustomerFields.yaml` — `sourceOfFundsCategories`, `sourceOfWealthCategories`, `purposeOfAccount`, `expectedMonthlyTransactionCount`, `expectedMonthlyTransactionVolume`, `annualIncomeRange`, `netWorthRange`, `pepStatus`. Reuse existing shared schemas (`SourceOfFundsCategory`, `PurposeOfAccount`, `ExpectedMonthlyTransactionCount/Volume` — all already used by `BusinessInfo`). New enum schemas for `SourceOfWealthCategory`, `AnnualIncomeRange`, `NetWorthRange`, `PepStatus`. |
| 15 | +- **§2 `VerificationError` enhancement** — add optional `code` (stable machine code) and `constraint` (regex / enum / length / format) on `VerificationError.yaml`. |
| 16 | +- **§5 `submitForVerification` flag** on `POST /customers` and `PATCH /customers/{customerId}` — new optional boolean on the request body; when `true`, response wraps `{ customer, verification }`. New `CustomerCreateResponse.yaml` / `CustomerUpdateResponse.yaml` response schemas that carry the optional embedded `Verification`. |
| 17 | +- **§3 `GET /verification/requirements`** endpoint spec + `VerificationRequirements.yaml` response schema (with helper `FieldRequirement.yaml`, `DocumentRequirement.yaml`, `AddressFormat.yaml` inner schemas). |
| 18 | +- **Mintlify docs** — rename `mintlify/snippets/sandbox-kyb-verification.mdx` → `sandbox-verification.mdx`; add "Individual customer verification" subsection with the `fullName` last-3-chars → `001` PENDING / `002` REJECTED / else APPROVED table; update imports in `mintlify/api-reference/sandbox-testing.mdx` and any per-product `sandbox-testing.mdx` pages. |
| 19 | +- **`openapi/openapi.yaml`** — register the new `/verification/requirements` path and new schema components. |
| 20 | +- **Regenerate `openapi.yaml`** at the repo root via `make build` (the bundled root spec is generated from the split schema files per grid-api CLAUDE.md). |
| 21 | + |
| 22 | +## Verification |
| 23 | + |
| 24 | +- [ ] `make build` succeeds (OpenAPI bundle regenerates without errors). |
| 25 | +- [ ] `make lint` passes (Redocly OpenAPI lint + Mintlify openapi-check). |
| 26 | +- [ ] Manual spot check of the bundled `openapi.yaml` — new schemas resolve, no dangling refs. |
| 27 | +- [ ] Mintlify preview renders the updated sandbox snippet (via `make mint` locally when reviewing). |
| 28 | + |
| 29 | +## Risks |
| 30 | + |
| 31 | +1. **grid-api is a public repo** — once shipped, all field names / enum values / endpoint shape are external contracts; can't be removed without a breaking change. Everything here is additive and considered final on merge. |
| 32 | +2. **New enum schemas** (`SourceOfWealthCategory`, `AnnualIncomeRange`, `NetWorthRange`, `PepStatus`) — the exact enum values are open to bikeshedding. Current proposal mirrors what's in the design doc §1a; can iterate on values if pilot-customer feedback pushes different buckets. |
| 33 | +3. **`VerificationError.code` values** — schemas allow any string; the canonical set of stable codes gets defined incrementally in Phase 2 backend work. Phase 1 just ships the field. |
| 34 | +4. **`GET /verification/requirements` returning the "real requirements matrix in sandbox"** — this contract is documented in #700 §7 but the backing cache is a Phase 1 backend item (sparkcore PR). Until the backend ships, calling this endpoint in sandbox returns a hard-coded seed matrix; the wire shape is the same. |
0 commit comments