Skip to content

feat(sca): return the session expiry and require an end-user IP on SCA login complete - #779

Closed
ls-bolt[bot] wants to merge 1 commit into
mainfrom
07-31-sca-login-end-user-ip-and-session-expiry
Closed

feat(sca): return the session expiry and require an end-user IP on SCA login complete#779
ls-bolt[bot] wants to merge 1 commit into
mainfrom
07-31-sca-login-end-user-ip-and-session-expiry

Conversation

@ls-bolt

@ls-bolt ls-bolt Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

This PR has been claimed. The active PR is now #780.

Summary

Two additive-now, breaking-later gaps on the SCA login surface.

sessionExpiresAt on ScaLoginComplete. Completing an SCA login establishes a 180-day session, and money movement in SCA-regulated currencies (EUR / USDC) is refused once it lapses. That expiry wasn't reported anywhere, so an integrator could only discover a lapsed session as a failed payment. Returning it lets a platform prompt a re-login ahead of time.

endUserIpAddress, required on ScaLoginCompleteRequest. The end user's IP is recorded against the login event by the SCA provider, where it feeds risk assessment and any transaction-risk exemption. A platform relaying the login on its customer's behalf is the only party that knows that address — so it has to travel in the request rather than being inferred from the connection, which sees the platform's server.

ScaAuthorization gains the same field as optional: that schema is shared by quote authorization and beneficiary trust changes, and only the former records an IP, so requiring it would demand a value from callers of operations that ignore it.

Breaking change

Adding a required request property is breaking (oasdiff: new-required-request-property on POST /sca/login/complete) and the PR is labelled accordingly.

No info.version bump. The versioning rule exists to protect integrators against a silently-changed contract, and this endpoint has no callers yet — so minting a new dated API version and the servers.url path that must accompany it would fragment the version namespace with no one to protect.

Also

Drops the status description's claim that the value is "passed through verbatim (Grid does not normalize it)". That contradicted the same schema documenting a successful login as reporting SUCCESS; the value is normalized, and the description now says only what's true.

Test plan

  • make build — bundled openapi.yaml and mintlify/openapi.yaml regenerated in lockstep; info.version unchanged at 2025-10-13.
  • make lint-openapi — exits 0. The remaining schema-properties-have-* findings are pre-existing repo-wide noise; the one naming ScaLoginCompleteRequest is on the untouched factor property (confirmed identical on main).
  • oasdiff breaking against main with the CI-pinned v1.16.0 — exactly one error, the expected new-required-request-property, and no others.
  • Verified in the bundled output: the new top-level required composes with the existing anyOf proof constraint rather than replacing it; sessionExpiresAt is a nullable date-time; ScaAuthorization.endUserIpAddress is nullable and absent from any required list.

Requested by @jklein24

…A login complete

Two additive-now, breaking-later gaps on the SCA login surface.

The 180-day SCA session expiry that gates money movement in SCA-regulated
currencies was not reported anywhere, so an integrator could only discover a
lapsed session as a failed payment. `ScaLoginComplete` now carries
`sessionExpiresAt`, letting a platform prompt a re-login ahead of the lapse.

The end user's IP is recorded against the login event by the SCA provider and
feeds its risk assessment and any transaction-risk exemption. Only the platform
relaying the login knows that address, so `ScaLoginCompleteRequest` now requires
`endUserIpAddress`. `ScaAuthorization` gains the same field as optional: it is
shared by quote authorization and beneficiary trust changes, and only the former
records an IP.

Adding a required request property is a breaking change (oasdiff:
new-required-request-property). No `info.version` bump: the endpoint has no
callers, so there is no existing contract to protect.

Also drops the claim that `status` is passed through verbatim without
normalization, which contradicted the same schema documenting `SUCCESS`.
@vercel

vercel Bot commented Jul 31, 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 31, 2026 4:21am
grid-wallet-demo Ignored Ignored Preview Jul 31, 2026 4:21am

Request Review

@ls-bolt ls-bolt Bot added the bolt label Jul 31, 2026
@github-actions github-actions Bot added the breaking-change Introduces a breaking change to the OpenAPI spec label Jul 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Breaking OpenAPI changes detected

oasdiff reports 1 error / 0 warning changes to openapi.yaml.
This PR will need approval from an API reviewer before merge.

Errors (1)

  • POST /sca/login/complete — added the new required request property endUserIpAddress [new-required-request-property].

Detected by oasdiff. Full report: job summary or the oasdiff-report artifact.

@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

✱ Stainless preview builds for grid

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

cli

chore(internal): regenerate SDK with no functional changes

go

chore(internal): regenerate SDK with no functional changes

kotlin

chore(internal): regenerate SDK with no functional changes

openapi

feat(api): add endUserIpAddress, sessionExpiresAt fields to SCA login models

php

chore(internal): regenerate SDK with no functional changes

python

chore(internal): regenerate SDK with no functional changes

ruby

chore(internal): regenerate SDK with no functional changes

typescript

chore(internal): regenerate SDK with no functional changes

Edit this comment to update them. They will appear in their respective SDK's changelogs.

grid-typescript studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ⏭️ (prev: build ✅) → lint ⏭️ (prev: lint ❗) → test ✅

grid-cli studio · code · diff

Your SDK build had at least one "warning" diagnostic, but this did not represent a regression.
generate ⚠️build ❗lint ❗test ❗

grid-openapi studio · code · diff

Your SDK build had at least one "warning" diagnostic, but this did not represent a regression.
generate ⚠️

grid-ruby studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ⏭️ (prev: build ✅) → lint ✅test ✅

grid-kotlin studio · code · diff

Your SDK build had at least one "warning" diagnostic, but this did not represent a regression.
generate ⚠️build ⏭️ (prev: build ✅) → lint ⏭️ (prev: lint ✅) → test ❗

grid-go studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ⏭️ (prev: build ✅) → lint ❗test ❗

go get github.com/stainless-sdks/grid-go@c041421a98289303abb1167b92b1695a9ad049c4
grid-php studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅lint ✅test ✅

grid-python studio · code · diff

Your SDK build had at least one "note" diagnostic, but this did not represent a regression.
generate ✅build ⏭️ (prev: build ✅) → lint ⏭️ (prev: 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-31 04:25:12 UTC

@mintlify

mintlify Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
Grid 🟢 Ready View Preview Jul 31, 2026, 4:22 AM

@mintlify

mintlify Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
Grid 🟡 Building Jul 31, 2026, 4:21 AM

jklein24 added a commit that referenced this pull request Jul 31, 2026
…A login complete (#780)

## Summary

Two additive-now, breaking-later gaps on the SCA login surface.

**`sessionExpiresAt` on `ScaLoginComplete`.** Completing an SCA login
establishes a 180-day session, and money movement in SCA-regulated
currencies (EUR / USDC) is refused once it lapses. That expiry wasn't
reported anywhere, so an integrator could only discover a lapsed session
as a failed payment. Returning it lets a platform prompt a re-login
ahead of time.

**`endUserIpAddress`, required on `ScaLoginCompleteRequest`.** The end
user's IP is recorded against the login event by the SCA provider, where
it feeds risk assessment and any transaction-risk exemption. A platform
relaying the login on its customer's behalf is the only party that knows
that address — so it has to travel in the request rather than being
inferred from the connection, which sees the platform's server.

`ScaAuthorization` gains the same field as **optional**: that schema is
shared by quote authorization and beneficiary trust changes, and only
the former records an IP, so requiring it would demand a value from
callers of operations that ignore it.

## Breaking change

Adding a required request property is breaking (`oasdiff`:
`new-required-request-property` on `POST /sca/login/complete`) and the
PR is labelled accordingly.

**No `info.version` bump.** The versioning rule exists to protect
integrators against a silently-changed contract, and this endpoint has
no callers yet — so minting a new dated API version and the
`servers.url` path that must accompany it would fragment the version
namespace with no one to protect.

## Also

Drops the `status` description's claim that the value is "passed through
verbatim (Grid does not normalize it)". That contradicted the same
schema documenting a successful login as reporting `SUCCESS`; the value
is normalized, and the description now says only what's true.

## Test plan

- `make build` — bundled `openapi.yaml` and `mintlify/openapi.yaml`
regenerated in lockstep; `info.version` unchanged at `2025-10-13`.
- `make lint-openapi` — exits 0. The remaining
`schema-properties-have-*` findings are pre-existing repo-wide noise;
the one naming `ScaLoginCompleteRequest` is on the untouched `factor`
property (confirmed identical on `main`).
- `oasdiff breaking` against `main` with the CI-pinned v1.16.0 —
**exactly one** error, the expected `new-required-request-property`, and
no others.
- Verified in the bundled output: the new top-level `required` composes
with the existing `anyOf` proof constraint rather than replacing it;
`sessionExpiresAt` is a nullable `date-time`;
`ScaAuthorization.endUserIpAddress` is nullable and absent from any
`required` list.

Requested by @jklein24

Original PR: #779
@jklein24
jklein24 deleted the 07-31-sca-login-end-user-ip-and-session-expiry branch July 31, 2026 18:49
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.

1 participant