Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR updates the Confidence Score: 5/5Safe to merge — purely OpenAPI spec documentation changes with no implementation code, and the schema constraints are correctly applied. No P0 or P1 findings. The only pre-existing P2 concern (OAUTH credential response behaviour undocumented) was already flagged in a previous review. The schema pattern, length constraints, and example values are all correct. No files require special attention.
|
| Filename | Overview |
|---|---|
| openapi/components/schemas/auth/AuthCredentialChallengeRequest.yaml | New schema for the challenge request body; includes correct pattern, minLength, and maxLength constraints on clientPublicKey. No required array, which is appropriate since the field is only conditionally required at the server level. |
| openapi/paths/auth/auth_credentials_{id}_challenge.yaml | Adds requestBody (required: false) referencing the new schema, with two examples (passkey and emailOtpOrOauth). Updated PASSKEY description to mention the clientPublicKey requirement. OAUTH credential response behaviour remains undocumented in the endpoint description (pre-existing concern). |
| openapi.yaml | Bundled spec — mirrors the modular YAML changes: adds requestBody, new AuthCredentialChallengeRequest component schema, and updated PASSKEY description. |
| mintlify/openapi.yaml | Mintlify-targeted bundled spec — identical changes to openapi.yaml; no issues. |
Sequence Diagram
sequenceDiagram
participant C as Client
participant G as Grid API
participant T as Turnkey
Note over C,T: PASSKEY re-challenge flow (new)
C->>C: Generate ephemeral P-256 key pair
C->>G: POST /auth/credentials/{id}/challenge
Note right of C: { clientPublicKey: "04..." }
G->>G: Validate clientPublicKey format
Note right of G: 04-prefix, 130 hex chars
G->>T: Create session payload baking in clientPublicKey
T-->>G: PasskeyAuthChallenge (challenge, requestId, expiresAt)
G-->>C: 200 PasskeyAuthChallenge
C->>C: navigator.credentials.get(challenge)
C->>G: POST /auth/credentials/{id}/verify
Note right of C: Request-Id: requestId
Note over C,G: EMAIL_OTP / OAUTH re-challenge flow (unchanged)
C->>G: POST /auth/credentials/{id}/challenge
Note right of C: {} (empty body)
G-->>C: 200 AuthMethod (OTP sent out-of-band)
Reviews (2): Last reviewed commit: "Address review feedback: extract challen..." | Re-trigger Greptile
…chema, add P-256 hex constraints
- Move the inline `requestBody` schema out of `auth_credentials_{id}_challenge.yaml`
into a new `AuthCredentialChallengeRequest.yaml` component to satisfy the
`no-inline-request-schema` redocly rule.
- Apply `pattern`, `minLength`, `maxLength` to `clientPublicKey` so generated
validators enforce the 130-char `04`-prefixed P-256 hex format the
description already documents (greptile review feedback).
- Regenerate the bundled `openapi.yaml` and `mintlify/openapi.yaml`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
✱ Stainless preview buildsThis PR will update the kotlin openapi python typescript ✅ grid-python studio · code
✅ grid-kotlin studio · code
✅ grid-typescript studio · code
This comment is auto-generated by GitHub Actions and is automatically kept up to date as you push. |
The previous spec said `POST /auth/credentials` for `PASSKEY` returned a
`PasskeyAuthChallenge` with the first-authentication challenge inline.
Implementation never did this — it returns a plain `AuthMethod` and
expects the integrator to call `POST /auth/credentials/{id}/challenge`
followed by `POST /auth/credentials/{id}/verify` to produce the first
session. Update the spec to match: registration is registration,
authentication goes through the dedicated `/challenge` + `/verify` path
for all three credential types.
Concretely:
- `auth_credentials.yaml`: 201 description, PASSKEY example, and
endpoint description updated; response schema switched from
`AuthCredentialResponseOneOf` to `AuthMethodResponse` directly
(uniform across all three credential types).
- `AuthCredentialResponseOneOf.yaml` description: drop the registration
reference; this oneOf is now used only by `/challenge`.
- `AuthMethodResponse.yaml` description: note both uses (direct
registration response + EMAIL_OTP/OAUTH branch of the challenge oneOf).
- Regenerate bundled `openapi.yaml` and `mintlify/openapi.yaml`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drops clientPublicKey from the required list on all three verify
request bodies (EmailOtpCredentialVerifyRequestFields,
OauthCredentialVerifyRequestFields, PasskeyCredentialVerifyRequestFields).
PASSKEY verify no longer needs the field at all — clientPublicKey
moves to /auth/credentials/{id}/challenge in #407, and Grid bakes it
into the session-creation payload there. Sending it on /verify is
inert.
EMAIL_OTP and OAUTH still use the field on /verify (that's where the
session signing key is sealed for those types), but making it optional
keeps the schema flexible if a client supplies it via a different path
in the future, and avoids a breaking 4xx for callers that omit it.
Field definition stays in place on each schema — only the 'required'
constraint is dropped. Bundle regenerated via 'make build'.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drops clientPublicKey from the required list on all three verify
request bodies (EmailOtpCredentialVerifyRequestFields,
OauthCredentialVerifyRequestFields, PasskeyCredentialVerifyRequestFields).
PASSKEY verify no longer needs the field at all — clientPublicKey
moves to /auth/credentials/{id}/challenge in #407, and Grid bakes it
into the session-creation payload there. Sending it on /verify is
inert.
EMAIL_OTP and OAUTH still use the field on /verify (that's where the
session signing key is sealed for those types), but making it optional
keeps the schema flexible if a client supplies it via a different path
in the future, and avoids a breaking 4xx for callers that omit it.
Field definition stays in place on each schema — only the 'required'
constraint is dropped. Bundle regenerated via 'make build'.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reflects the API change in #407 — for PASSKEY credentials, clientPublicKey now goes on POST /auth/credentials/{id}/challenge instead of /verify. Grid bakes the public key into the Turnkey session-creation payload that the returned challenge is computed from, so the resulting session signing key is sealed to the device that requested the challenge. Knock-on flow change: registration response is now a plain AuthMethod (no inline PasskeyAuthChallenge). Both first-time activation and reauthentication for PASSKEY follow the same three-step shape: register → /challenge (with clientPublicKey) → /verify (with Request-Id, no clientPublicKey). EMAIL_OTP and OAUTH are unchanged — clientPublicKey stays on /verify for those types; /challenge takes an empty body. Updates: - snippets/global-accounts/authentication.mdx — overview, passkey registration sequence diagram + TS/Kotlin/Swift code samples, parameter map split into challenge + assertion tables, passkey reauth diagram, additional-credential activation prose - snippets/global-accounts/overview.mdx — Quickstart Step 7 now generates the keypair before calling /challenge with clientPublicKey, and the /verify body drops it - snippets/global-accounts/client-keys.mdx — clarifies which call carries clientPublicKey for each credential type - snippets/sandbox-global-account-magic.mdx — passkey example now shows the /challenge + /verify pair; verify body drops clientPublicKey Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drops clientPublicKey from the required list on all three verify
request bodies (EmailOtpCredentialVerifyRequestFields,
OauthCredentialVerifyRequestFields,
PasskeyCredentialVerifyRequestFields).
PASSKEY verify no longer needs the field at all — clientPublicKey
moves to /auth/credentials/{id}/challenge in #407, and Grid bakes it
into the session-creation payload there. Sending it on /verify is
inert.
EMAIL_OTP and OAUTH still use the field on /verify (that's where the
session signing key is sealed for those types), but making it optional
keeps the schema flexible if a client supplies it via a different path
in the future, and avoids a breaking 4xx for callers that omit it.
Field definition stays in place on each schema — only the 'required'
constraint is dropped. Bundle regenerated via 'make build'.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

TL;DR
The
POST /auth/credentials/{id}/challengeendpoint now accepts a request body containing aclientPublicKeyfor passkey credential re-challenges.What changed?
The
challengeAuthCredentialendpoint now accepts an optional JSON request body with aclientPublicKeyfield. ForPASSKEYcredentials, this field is required and must be a client-generated P-256 public key in hex-encoded uncompressed SEC1 format (130 hex characters,04-prefixed). Grid bakes this key into the Turnkey session-creation payload that the returned challenge is computed from, sealing the resulting session signing key to the client.The field is ignored for
EMAIL_OTPandOAUTHcredentials, where the credential type alone is sufficient to issue a challenge. Two request body examples are documented: one for passkey re-challenges (withclientPublicKey) and one for email-OTP or OAuth re-challenges (empty body).How to test?
POST /auth/credentials/{id}/challengefor aPASSKEYcredential with a validclientPublicKeyin the request body and confirm aPasskeyAuthChallengeis returned.clientPublicKeyfor aPASSKEYcredential and confirm an appropriate error is returned.POST /auth/credentials/{id}/challengefor anEMAIL_OTPorOAUTHcredential with an empty body and confirm the challenge is issued successfully.Why make this change?
Previously, the challenge endpoint had no way to bind the resulting Turnkey session to a specific client. By requiring the client to supply its ephemeral public key upfront, Grid can embed it into the session-creation payload before computing the challenge, ensuring the session signing key is cryptographically sealed to the client that initiated the challenge.