Skip to content

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

Merged
jklein24 merged 1 commit into
mainfrom
07-31-sca-login-end-user-ip-and-session-expiry
Jul 31, 2026
Merged

feat(sca): return the session expiry and require an end-user IP on SCA login complete#780
jklein24 merged 1 commit into
mainfrom
07-31-sca-login-end-user-ip-and-session-expiry

Conversation

@jklein24

Copy link
Copy Markdown
Contributor

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

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

Copy link
Copy Markdown

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

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

@jklein24
jklein24 marked this pull request as ready for review July 31, 2026 04:37
@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 param to SCA login/authorization, sessionExpiresAt to response

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
⚠️ 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@0b137d21e68d716f0615f85566b0a78c6e747325
⚠️ 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 test 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 · conflict

Your SDK build had at least one note diagnostic.

⚠️ grid-cli 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 ❗


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 18:56:05 UTC

@greptile-apps

greptile-apps Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

      .     .
     / \m/ \        ⚡ SCA DOOM PROTOCOL ⚡
    |  O O  |       LOGIN ETERNAL, SESSION INFERNAL
     \  ^  /
    __|===|__
  _/  |___|  \_
 /___/|   |\___\

This PR expands the SCA API contract with session-expiry and end-user IP metadata.

  • Requires endUserIpAddress when completing an SCA login.
  • Adds optional endUserIpAddress metadata to shared SCA authorizations.
  • Returns a conditional, nullable sessionExpiresAt from login completion.
  • Corrects the login-status description and regenerates both bundled specifications.

Confidence Score: 5/5

The PR appears safe to merge with the source schemas and generated bundles consistently representing the intended SCA contract.

The required login IP composes with the existing proof requirements, the shared authorization IP remains optional, and session expiry is modeled consistently with other conditionally present SCA response fields.

Important Files Changed

Filename Overview
openapi/components/schemas/sca/ScaLoginCompleteRequest.yaml Requires the end user's IP on login completion while preserving the existing proof-selection constraints.
openapi/components/schemas/sca/ScaLoginComplete.yaml Adds the conditionally present session-expiry timestamp and corrects the status documentation.
openapi/components/schemas/sca/ScaAuthorization.yaml Adds nullable, optional end-user IP metadata without breaking operations sharing this authorization schema.
openapi.yaml Accurately bundles the modular SCA schema changes.
mintlify/openapi.yaml Remains synchronized with the root generated OpenAPI bundle.

Reviews (1): Last reviewed commit: "feat(sca): return the session expiry and..." | Re-trigger Greptile

@jklein24
jklein24 requested review from JasonCWang and shreyav July 31, 2026 04:46
@jklein24
jklein24 merged commit 67c190d into main Jul 31, 2026
18 checks passed
@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.

3 participants