Skip to content

Add idType/identifier to IndividualCustomerCreateRequest (ENG-10686)#637

Merged
akanter merged 2 commits into
mainfrom
07-01-ENG-10686-individual-tax-id
Jul 2, 2026
Merged

Add idType/identifier to IndividualCustomerCreateRequest (ENG-10686)#637
akanter merged 2 commits into
mainfrom
07-01-ENG-10686-individual-tax-id

Conversation

@akanter

@akanter akanter commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the individual account-holder's tax identification (SSN/ITIN) to IndividualCustomerCreateRequest so Grid can capture it at customer creation and bridge it downstream to EntUserInfo.tax_identifier for 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/identifier off the regenerated client model.

Details

  • New fields on the create request only (added to the allOf in IndividualCustomerCreateRequest.yaml, not the shared IndividualCustomerFields), so the identifier is write-only and never echoed in customer GET responses.
  • Reuses the existing IdentificationType enum (SSN/ITIN/EIN/NON_US_TAX_ID) and mirrors the flat idType/identifier/countryOfIssuance shape beneficial owners already expose (BeneficialOwnerPersonalInfo).
  • Regenerated bundle (openapi.yaml, mintlify/openapi.yaml) via make build; redocly lint clean.

Test plan

  • npm run build:openapi + npx @redocly/cli lint openapi.yaml → valid.
  • webdev client regeneration (grid-api/update_schema.sh) picks up id_type/identifier/country_of_issuance on the individual create model.

🤖 sovereign-nebula-2(#2) | Feedback

Original PR: #636

…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.
@ls-bolt ls-bolt Bot added bolt breaking-change Introduces a breaking change to the OpenAPI spec labels Jul 2, 2026
@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
grid-flow-builder Ignored Ignored Preview Jul 2, 2026 3:41am
grid-wallet-demo Ignored Ignored Preview Jul 2, 2026 3:41am

Request Review

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

⚠️ Breaking OpenAPI changes detected

This PR introduces breaking changes to openapi.yaml:

API Changelog 2026-06-29 vs. 2026-06-29

API Changes

POST /customers

  • ⚠️ added subschema #3 to the oneOf[subschema #1: Individual Customer Create Request]/ request property allOf list

Detected by oasdiff. This PR will need approval from an API reviewer before merge.

akanter commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@akanter akanter marked this pull request as ready for review July 2, 2026 03:34
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

✱ Stainless preview builds for grid

This PR will update the grid SDKs with the following commit messages.

cli

feat(api): add identifier and idType fields to customers create method

csharp

feat(api): add identifier and id_type fields to individual customer create

go

feat(api): add identifier and idType parameters to individual customer creation

kotlin

feat(api): add identifier/idType fields to IndividualCustomerCreateRequest

openapi

feat(api): add idType and identifier parameters to individual customer create

php

feat(api): add identifier and idType fields to individual customer create

python

feat(api): add identifier and id_type fields to individual customer create request

ruby

feat(api): add identifier/id_type fields to individual customer create

typescript

feat(api): add identifier and idType fields to customers create
⚠️ grid-openapi studio · code

Your SDK build had at least one "warning" diagnostic.
generate ⚠️

grid-ruby studio · code

Your SDK build had at least one "note" diagnostic.
generate ✅build ✅lint ✅test ✅

⚠️ grid-go studio · code

Your SDK build had a failure in the lint CI job, which is a regression from the base state.
generate ✅build ✅lint ❗test ❗

go get github.com/stainless-sdks/grid-go@5a18f0e6441e38061a8be75ffbcdeee30966e6db
⚠️ grid-kotlin studio · code

Your SDK build had a failure in the test CI job, which is a regression from the base state.
generate ⚠️build ✅lint ✅test ❗

⚠️ grid-python studio · code

Your SDK build had a failure in the lint CI job, which is a regression from the base state.
generate ✅build ✅lint ❗test ❗

pip install https://pkg.stainless.com/s/grid-python/842b3508d38724ff390ce1035673300b4ca4c548/grid-0.0.1-py3-none-any.whl
⚠️ grid-csharp studio · code

Your SDK build had a failure in the build CI job, which is a regression from the base state.
generate ⚠️build ❗lint ✅test ❗

grid-php studio · code

Your SDK build had at least one "note" diagnostic.
generate ✅lint ✅test ✅

⚠️ grid-typescript studio · code

Your SDK build had a failure in the lint CI job, which is a regression from the base state.
generate ✅build ✅lint ❗test ✅

npm install https://pkg.stainless.com/s/grid-typescript/21e8cea7d288781bfdf73750b14be044def415ff/dist.tar.gz
⚠️ grid-cli studio · code

Your SDK build had a failure in the build CI job, which is a regression from the base state.
generate ⚠️build ❗lint ❗test ❗


This comment is auto-generated by GitHub Actions and is automatically kept up to date as you push.
If you push custom code to the preview branch, re-run this workflow to update the comment.
Last updated: 2026-07-02 16:17:23 UTC

@ls-bolt

ls-bolt Bot commented Jul 2, 2026

Copy link
Copy Markdown

Re-posting context from the original draft (#636) for the API reviewer, since the oasdiff ⚠️ above reads scarier than it is: idType and identifier are optional — no existing request breaks and nothing new is required.

  • Neither field is in any required: list; requests that omit them are valid and behave identically to today (no tax id persisted).
  • The only new 400s are for callers who opt in incorrectly (one of the pair without the other; EIN / NON_US_TAX_ID on an individual). These field names didn't exist before, so no current integrator can be sending them.
  • The tax id is only required far downstream at Lead onboarding of an individual account holder — a pre-existing requirement, not added here.
  • oasdiff flags any added allOf subschema as breaking because composition changes can reject previously-valid payloads in general. This subschema has only optional properties (no required, no additionalProperties: false), so the set of valid POST /customers requests only grew.

Verified in webdev#29658: the full existing create-customer suite (118 tests, none sending tax fields) passes unchanged.


🤖 sovereign-nebula(#3) | Feedback

@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds idType and identifier fields to IndividualCustomerCreateRequest so that an individual's SSN or ITIN can be captured at customer creation and forwarded to the Lead banking partner for US CIP onboarding. The fields are intentionally write-only (not present in GET responses) and are scoped to the create request only via allOf, not the shared IndividualCustomerFields.

  • New idType (IdentificationType enum) and identifier (string) properties added to the third allOf entry in IndividualCustomerCreateRequest.yaml, keeping them off the shared read model.
  • identifier description says "Write-only" but is missing the writeOnly: true OpenAPI 3.0 keyword, which means SDK generators won't enforce this constraint on the client model.
  • countryOfIssuance — present on the analogous BeneficialOwnerPersonalInfo shape — is absent, leaving non-US tax ID use cases under-specified given that NON_US_TAX_ID is a valid enum value.

Confidence Score: 4/5

Safe 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.

Important Files Changed

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)"
Loading
%%{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)"
Loading
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

akanter commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Merge activity

  • Jul 2, 4:11 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jul 2, 4:11 PM UTC: @akanter merged this pull request with Graphite.

@akanter akanter merged commit a2e2b80 into main Jul 2, 2026
10 checks passed
@akanter akanter deleted the 07-01-ENG-10686-individual-tax-id branch July 2, 2026 16:11
@pengying

pengying commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Are you going to add masked identifier to the response?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bolt breaking-change Introduces a breaking change to the OpenAPI spec

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants