Add idType/identifier to IndividualCustomerCreateRequest (ENG-10686) - #637
Conversation
…0686) Individual account-holder CIP capture — accept the individual's tax identification (SSN/ITIN) on customer creation so sparkcore can bridge it to paycore EntUserInfo.tax_identifier for Lead onboarding. Write-only: added to the create request only (not the shared IndividualCustomerFields), so the SSN is never echoed in customer responses. Mirrors the flat idType/identifier shape beneficial owners already use.
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
|
✱ Stainless preview builds for gridThis PR will update the cli csharp go kotlin openapi php python ruby typescript ✅ grid-ruby studio · code
|
|
Re-posting context from the original draft (#636) for the API reviewer, since the oasdiff
Verified in webdev#29658: the full existing create-customer suite (118 tests, none sending tax fields) passes unchanged. |
Greptile SummaryAdds
Confidence Score: 4/5Safe to merge after adding writeOnly: true to the identifier field; without it, generated clients may expose SSN/ITIN in deserialized GET responses. The identifier field carries sensitive PII (SSN/ITIN) and the schema description explicitly calls it write-only, but the writeOnly: true OpenAPI keyword is missing. Client generators used by the consuming webdev repo rely on this keyword to mark the field appropriately; its absence could cause the generated model to include the field when deserializing customer GET responses. openapi/components/schemas/customers/IndividualCustomerCreateRequest.yaml and its bundled copies in openapi.yaml and mintlify/openapi.yaml all need the writeOnly: true addition on the identifier property.
|
| Filename | Overview |
|---|---|
| openapi/components/schemas/customers/IndividualCustomerCreateRequest.yaml | Adds idType and identifier fields to the individual customer create request; missing writeOnly: true on identifier despite the description calling it write-only, and countryOfIssuance is absent compared to the BeneficialOwnerPersonalInfo pattern it claims to mirror. |
| openapi.yaml | Bundled output reflecting the same schema change; same writeOnly omission is present here. |
| mintlify/openapi.yaml | Mintlify documentation bundle regenerated from make build; mirrors the openapi.yaml changes faithfully. |
Sequence Diagram
%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Client as Web Client
participant API as Grid API
participant Lead as Lead (Banking Partner)
Client->>API: "POST /customers/individual<br/>{idType, identifier, ...}"
Note over API: IndividualCustomerCreateRequest<br/>idType (SSN/ITIN)<br/>identifier (write-only)
API->>Lead: "Onboard US individual<br/>EntUserInfo.tax_identifier = identifier"
Lead-->>API: Onboarding result
API-->>Client: "Customer response<br/>(identifier NOT echoed back)"
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Client as Web Client
participant API as Grid API
participant Lead as Lead (Banking Partner)
Client->>API: "POST /customers/individual<br/>{idType, identifier, ...}"
Note over API: IndividualCustomerCreateRequest<br/>idType (SSN/ITIN)<br/>identifier (write-only)
API->>Lead: "Onboard US individual<br/>EntUserInfo.tax_identifier = identifier"
Lead-->>API: Onboarding result
API-->>Client: "Customer response<br/>(identifier NOT echoed back)"
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
openapi/components/schemas/customers/IndividualCustomerCreateRequest.yaml:9-15
The description explicitly states this field is "Write-only — never returned in customer responses," but the `writeOnly: true` OpenAPI 3.0 property is missing. Without it, SDK/client generators (including the webdev `grid-api/update_schema.sh` mentioned in the PR) will not mark the field as write-only in generated models, potentially including it in GET response deserialization — a problem for a sensitive field like an SSN/ITIN.
```suggestion
identifier:
type: string
writeOnly: true
description: >-
The individual's tax identification number (SSN or ITIN for a US
account holder). Required to onboard the individual as a US account
holder. Write-only — never returned in customer responses.
example: 123-45-6789
```
### Issue 2 of 2
openapi/components/schemas/customers/IndividualCustomerCreateRequest.yaml:6-15
The PR description says this schema "mirrors the flat `idType`/`identifier`/`countryOfIssuance` shape beneficial owners already expose (`BeneficialOwnerPersonalInfo`)", but `countryOfIssuance` is absent here. The reused `IdentificationType` enum includes `NON_US_TAX_ID`, and without `countryOfIssuance` there's no way to identify which country issued a non-US tax ID — the field becomes ambiguous for any non-US account holder. If this endpoint is US-only, the description should say so explicitly and the available enum values should be narrowed accordingly.
Reviews (1): Last reviewed commit: "feat: add idType/identifier to Individua..." | Re-trigger Greptile
|
Are you going to add masked identifier to the response? |
…#671) ## Summary Removes the csharp target from `.stainless/stainless.yml` so the `Build SDKs for pull request / preview` check stops failing on every spec-changing PR. **Why every spec PR is red**: Stainless's csharp build CI is broken upstream for ANY freshly generated code (content-independent, proven by bisect on #650, breakage window ~Jul 3). The preview check gates on a per-language head-vs-base regression, and with csharp in main's config the base build resolves to a cached pre-breakage csharp *success* — so every fresh head failure counts as a regression → red. **Why this fixes it**: with csharp out of the config on main, base builds have no cached csharp success to regress from — matching outcomes on base and head → "not a regression" → green. Proven end-to-end by probe #659: the exact previously-failing change class (doc-comment-only codegen delta) ran against a csharp-free base and `preview` **passed**. Full mechanics: [investigation writeup](#657 (comment)). **No shipping impact**: the csharp target is unpublished (`production_repo: null`, `publish.nuget: false`). Re-add the block when Stainless fixes their csharp build CI upstream. ## Sequencing (for #657 and other open spec PRs) 1. Merge this PR — **its own `preview` will be red** (its base is current main); merge through it (precedent: #633, #637). 2. Merge/rebase main into open spec PRs (e.g. #657) — their next `preview` run goes green. ## Verification - `make lint` passes; the file matches the exact removal previously validated on the #657 branch (commit 069ad9a) and by probe #659. --- 🤖 [thundering-graviton-3](https://zeus.dev.dev.sparkinfra.net/#/arc?id=thundering-graviton)[(#3)](https://zeus.dev.dev.sparkinfra.net/#/instance?id=thundering-graviton-3) | [Feedback](https://zeus.dev.dev.sparkinfra.net/feedback) Original PR: #663 Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…the Card resource (#657) ## Summary Follow-up #2 from [webdev#29877](lightsparkdev/webdev#29877) (Lithic card PAN-reveal POC), evolved per review: PAN reveal is now an **explicit, dedicated endpoint** rather than a side effect of reading the card. Server change: [webdev#29995](lightsparkdev/webdev#29995). - **New `POST /cards/{id}/reveal`** (`openapi/paths/cards/cards_{id}_reveal-session.yaml` + `CardRevealResponse` schema) — mints a signed, short-lived reveal URL and returns `{ panEmbedUrl, expiresAt }`. Every mint is audit-logged with the requesting actor; unattributable sessions get 403. - **`panEmbedUrl` is removed from the `Card` schema entirely** — get/list/create/update responses and webhook payloads never carry it. A live PAN-reveal credential only exists when a client explicitly asked for one (least-privilege + clean "reveal requested" audit semantics). - **Docs rewritten to the reveal-session flow**: issuing-cards gains the `POST …/reveal` example, quickstart/webhooks/terminology snippets updated, webhook examples no longer show the field, and `GET /cards/{id}` points at the reveal endpoint. - **Rode along from the folded #656**: a small `GtqAccountInfoBase` description clarification. `.stainless/stainless.yml` is byte-identical to main (the csharp experiments were fully reverted; the real csharp fix is #663). ## Verification - `make build` + `make lint` pass (0 errors; remaining warnings pre-exist on main). - Server implementation is TDD'd end-to-end on [webdev#29995](lightsparkdev/webdev#29995) (58 handler/proxy tests + dashboard dialog tests green). ## CI note — red `preview` check is expected until #663 merges The Stainless csharp target's upstream build CI fails on any codegen delta (content-independent); the fix is #663 (removes the unpublished csharp target on main). Until it merges, `preview` stays red on spec-changing PRs, this one included — merge through it (precedent #633, #637). Details: [investigation](#657 (comment)). --- 🤖 [thundering-graviton-5](https://zeus.dev.dev.sparkinfra.net/#/arc?id=thundering-graviton)[(#5)](https://zeus.dev.dev.sparkinfra.net/#/instance?id=thundering-graviton-5) | [Feedback](https://zeus.dev.dev.sparkinfra.net/feedback) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: mohamedwane <mohamedwane@users.noreply.github.com> Co-authored-by: benwgold <benwgold@users.noreply.github.com> Co-authored-by: pengying <pengying@users.noreply.github.com>

Summary
Adds the individual account-holder's tax identification (SSN/ITIN) to
IndividualCustomerCreateRequestso Grid can capture it at customer creation and bridge it downstream toEntUserInfo.tax_identifierfor Lead (banking-partner) onboarding of a US individual.Part of ENG-10686 (Individual account-holder CIP). Consumed by the webdev PR (lightsparkdev/webdev#29658), which reads
idType/identifieroff the regenerated client model.Details
allOfinIndividualCustomerCreateRequest.yaml, not the sharedIndividualCustomerFields), so the identifier is write-only and never echoed in customer GET responses.IdentificationTypeenum (SSN/ITIN/EIN/NON_US_TAX_ID) and mirrors the flatidType/identifier/countryOfIssuanceshape beneficial owners already expose (BeneficialOwnerPersonalInfo).openapi.yaml,mintlify/openapi.yaml) viamake build;redocly lintclean.Test plan
npm run build:openapi+npx @redocly/cli lint openapi.yaml→ valid.grid-api/update_schema.sh) picks upid_type/identifier/country_of_issuanceon the individual create model.🤖 sovereign-nebula-2(#2) | Feedback
Original PR: #636