Skip to content

add GET /auth/sessions to list authentication sessions#370

Open
DhruvPareek wants to merge 1 commit into04-22-feat_add_delete__auth_credentials__id_to_revoke_authentication_credentialsfrom
04-22-feat_add_get__auth_sessions_to_list_authentication_sessions
Open

add GET /auth/sessions to list authentication sessions#370
DhruvPareek wants to merge 1 commit into04-22-feat_add_delete__auth_credentials__id_to_revoke_authentication_credentialsfrom
04-22-feat_add_get__auth_sessions_to_list_authentication_sessions

Conversation

@DhruvPareek
Copy link
Copy Markdown
Contributor

@DhruvPareek DhruvPareek commented Apr 22, 2026

Introduces the Session resource and a list endpoint. A session is created each time an authentication credential is verified via POST /auth/credentials/{id}/verify and remains active until its expiresAt or until it is revoked (revocation endpoint lands in the next PR).

Endpoint

  • GET /auth/sessions?accountId={id} → 200 SessionListResponse.
  • Query parameters: accountId (required).

Schemas added

  • Session{ id, accountId, type, nickname, ip, createdAt, updatedAt, expiresAt }. id is prefixed Session:<uuid> to match Grid's resource-prefixed ID convention. type reuses the shared AuthMethodType enum so it aligns with the credential that issued the session. nickname is inherited from that credential.
  • SessionListResponse{ data: Session[] }, non-paginated.

Wire-up

  • New path file openapi/paths/auth/auth_sessions.yaml with just a get operation.
  • openapi/openapi.yaml registers /auth/sessions.
  • .stainless/stainless.yml adds a new sessions subresource under auth (sibling of credentials) with list: get /auth/sessions and registers the two new schemas as models.
  • Bundled openapi.yaml + mintlify/openapi.yaml regenerated.

Notes vs the Grid convention

  • openapi/README.md says list endpoints use cursor pagination. Deviating here because an internal account has a small, bounded number of concurrent sessions (typically 1–4, one per signed-in device). Adding hasMore / nextCursor / totalCount later is non-breaking per the README, so we can backtrack if the cardinality assumption changes. Matches the same deviation on GET /auth/credentials.

Notes vs the PDF spec

  • PDF uses "type": "OTP"; kept EMAIL_OTP to match the shared AuthMethodType enum.
  • PDF uses session:uuid (lowercase) for the id prefix; switched to Session:<uuid> to match the rest of Grid's ID conventions.
  • ip is required per the PDF. If certain flows legitimately have no IP, we can relax to nullable in a follow-up.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 22, 2026

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

Project Deployment Actions Updated (UTC)
grid-flow-builder Ready Ready Preview, Comment Apr 23, 2026 2:39am

Request Review

Copy link
Copy Markdown
Contributor Author

DhruvPareek commented Apr 22, 2026

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 22, 2026

✱ Stainless preview builds

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

kotlin

feat(api): add list sessions to auth, list/revoke methods to credentials

openapi

feat(api): add listSessions endpoint, Session/SessionListResponse models to auth

python

feat(api): add list_sessions to auth, list/revoke to credentials

typescript

feat(api): add listSessions to auth, list/revoke to auth.credentials

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

⚠️ grid-python studio · code · diff

Your SDK build had at least one new warning diagnostic, which is a regression from the base state.
generate ❗build ✅lint ✅test ✅

pip install https://pkg.stainless.com/s/grid-python/e64cac76146c1ae8aa9da716629b2f3db60a163f/grid-0.0.1-py3-none-any.whl
New diagnostics (1 warning)
⚠️ Method/PaginatedWithoutMatchingScheme: Skipped pagination for method `get /auth/sessions` (no matching pagination scheme).
⚠️ grid-typescript studio · code · diff

Your SDK build had at least one new warning diagnostic, which is a regression from the base state.
generate ❗build ✅lint ✅test ✅

npm install https://pkg.stainless.com/s/grid-typescript/0412fcad35de53dda672c2995a2024b683763e76/dist.tar.gz
New diagnostics (1 warning)
⚠️ Method/PaginatedWithoutMatchingScheme: Skipped pagination for method `get /auth/sessions` (no matching pagination scheme).
⚠️ grid-openapi studio · code · diff

Your SDK build had at least one new warning diagnostic, which is a regression from the base state.
generate ❗

New diagnostics (1 warning)
⚠️ Method/PaginatedWithoutMatchingScheme: Skipped pagination for method `get /auth/sessions` (no matching pagination scheme).
⚠️ grid-kotlin studio · code · diff

Your SDK build had at least one new warning diagnostic, which is a regression from the base state.
generate ❗build ✅lint ✅test ✅

New diagnostics (1 warning)
⚠️ Method/PaginatedWithoutMatchingScheme: Skipped pagination for method `get /auth/sessions` (no matching pagination scheme).

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-04-23 02:46:21 UTC

@DhruvPareek DhruvPareek changed the title feat: add GET /auth/sessions to list authentication sessions add GET /auth/sessions to list authentication sessions Apr 22, 2026
@DhruvPareek DhruvPareek force-pushed the 04-22-feat_add_delete__auth_credentials__id_to_revoke_authentication_credentials branch from 108f6cf to fec18b2 Compare April 22, 2026 20:02
@DhruvPareek DhruvPareek force-pushed the 04-22-feat_add_get__auth_sessions_to_list_authentication_sessions branch from 570eafb to c1826de Compare April 22, 2026 20:02
@DhruvPareek DhruvPareek force-pushed the 04-22-feat_add_get__auth_sessions_to_list_authentication_sessions branch from c1826de to ceee7f8 Compare April 22, 2026 20:07
@DhruvPareek DhruvPareek force-pushed the 04-22-feat_add_delete__auth_credentials__id_to_revoke_authentication_credentials branch from fec18b2 to 088d2dc Compare April 22, 2026 20:07
@DhruvPareek DhruvPareek force-pushed the 04-22-feat_add_delete__auth_credentials__id_to_revoke_authentication_credentials branch from 088d2dc to 9f6c7a1 Compare April 22, 2026 20:18
@DhruvPareek DhruvPareek force-pushed the 04-22-feat_add_get__auth_sessions_to_list_authentication_sessions branch from ceee7f8 to 16b43cc Compare April 22, 2026 20:18
@DhruvPareek DhruvPareek force-pushed the 04-22-feat_add_get__auth_sessions_to_list_authentication_sessions branch from 16b43cc to 9599289 Compare April 22, 2026 20:23
@DhruvPareek DhruvPareek force-pushed the 04-22-feat_add_delete__auth_credentials__id_to_revoke_authentication_credentials branch from 9f6c7a1 to 52fcd4f Compare April 22, 2026 20:23
@DhruvPareek DhruvPareek force-pushed the 04-22-feat_add_delete__auth_credentials__id_to_revoke_authentication_credentials branch from 52fcd4f to 9198355 Compare April 22, 2026 20:49
@DhruvPareek DhruvPareek force-pushed the 04-22-feat_add_get__auth_sessions_to_list_authentication_sessions branch from 9599289 to a8f600d Compare April 22, 2026 20:49
@DhruvPareek DhruvPareek marked this pull request as ready for review April 22, 2026 21:10
@DhruvPareek DhruvPareek requested a review from pengying April 22, 2026 21:10
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 22, 2026

Greptile Summary

This PR introduces the Session resource (GET /auth/sessions?accountId=…) alongside its Session and SessionListResponse schemas, wired into Stainless and both bundled OpenAPI outputs. The design is well-documented, and the intentional deviations from the pagination convention and PDF spec are clearly justified.

All remaining findings are P2 style/polish items: a missing title on SessionListResponse, identical example timestamps for updatedAt/expiresAt, the acknowledged risk of ip being required rather than nullable, and a missing 403 response for cross-account access attempts.

Confidence Score: 5/5

Safe to merge — no blocking issues; all findings are non-critical P2 suggestions.

All four findings are P2 (style, documentation quality, and defensive design considerations). None represent broken contracts, missing required data, or security gaps that would produce incorrect behavior in production. The schema and endpoint are structurally sound and consistent with the rest of the auth surface.

openapi/components/schemas/auth/Session.yaml (ip nullability and example timestamps) and openapi/paths/auth/auth_sessions.yaml (missing 403 response).

Important Files Changed

Filename Overview
openapi/paths/auth/auth_sessions.yaml New GET /auth/sessions path with BasicAuth, required accountId query param, and 200/400/401/404/500 responses — missing 403 for cross-account access attempts.
openapi/components/schemas/auth/Session.yaml New Session schema with all expected fields; ip is required (acknowledged as potentially needing nullable relaxation) and updatedAt/expiresAt share identical example timestamps.
openapi/components/schemas/auth/SessionListResponse.yaml Simple wrapper schema for Session[]; missing a title field that other sibling schemas carry.
.stainless/stainless.yml Adds sessions subresource under auth with list method and correct model refs; looks correct.
openapi/openapi.yaml Registers /auth/sessions path ref — two-line addition, correct.
openapi.yaml Bundled output regenerated from openapi/ sources; mirrors the source changes correctly.
mintlify/openapi.yaml Mintlify bundled output regenerated; Session and SessionListResponse schemas and endpoint appear correctly.

Sequence Diagram

sequenceDiagram
    participant C as Client
    participant API as Grid API
    participant DB as Session Store

    C->>API: POST /auth/credentials/{id}/verify
    API->>DB: Create Session record
    DB-->>API: Session (id, accountId, ip, expiresAt…)
    API-->>C: 200 VerifyCredentialResponse

    C->>API: GET /auth/sessions?accountId={id}
    Note over API: BasicAuth required
    API->>DB: Query active sessions for accountId
    DB-->>API: Session[]
    API-->>C: 200 SessionListResponse { data: Session[] }

    Note over C,API: Future: DELETE /auth/sessions/{id}
    C->>API: DELETE /auth/sessions/{id}
    API->>DB: Revoke session
    API-->>C: 200
Loading

Fix All in Claude Code

Prompt To Fix All With AI
This is a comment left during a code review.
Path: openapi/components/schemas/auth/SessionListResponse.yaml
Line: 1-9

Comment:
**Missing `title` field on `SessionListResponse`**

The `Session` schema includes `title: Authentication Session`, but `SessionListResponse` has no `title`. Other list-response schemas in this repo typically carry a title for SDK/docs tooling to surface a readable name. Consider adding one for consistency.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: openapi/components/schemas/auth/Session.yaml
Line: 41-49

Comment:
**`updatedAt` and `expiresAt` share the same example timestamp**

Both `updatedAt` and `expiresAt` use `'2026-04-08T15:35:00Z'`, implying the session was last updated at the exact moment it expires. This is misleading for readers trying to understand the semantics of each field. Consider using a later timestamp for `expiresAt` (e.g. `'2026-04-09T15:30:01Z'` for a 24-hour session) to make the distinction clear.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: openapi/components/schemas/auth/Session.yaml
Line: 29-31

Comment:
**`ip` required — consider nullable from the start**

The PR description explicitly calls out: _"If certain flows legitimately have no IP, we can relax to nullable in a follow-up."_ Making `ip` required in v1 is a breaking change to relax later — clients that auto-generate models will bake in non-null assumptions. Marking it `nullable: true` (and removing from `required`) now is non-breaking and avoids a future contract change if, e.g., server-initiated or internal flows produce sessions without a client IP.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: openapi/paths/auth/auth_sessions.yaml
Line: 28-55

Comment:
**Missing `403 Forbidden` response**

The endpoint uses `BasicAuth` and accepts an arbitrary `accountId` query parameter. If the authenticated caller provides a valid `accountId` that belongs to a different account (one they are not authorized to inspect), the server should return `403 Forbidden` rather than `404`. The current spec only covers `400 / 401 / 404 / 500`, leaving the authorization-failure case undocumented. The sibling `GET /auth/credentials` endpoint would be the natural reference to check for consistency.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "feat: add GET /auth/sessions to list aut..." | Re-trigger Greptile

Comment on lines +1 to +9
type: object
required:
- data
properties:
data:
type: array
description: List of active authentication sessions for the internal account.
items:
$ref: ./Session.yaml
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing title field on SessionListResponse

The Session schema includes title: Authentication Session, but SessionListResponse has no title. Other list-response schemas in this repo typically carry a title for SDK/docs tooling to surface a readable name. Consider adding one for consistency.

Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/components/schemas/auth/SessionListResponse.yaml
Line: 1-9

Comment:
**Missing `title` field on `SessionListResponse`**

The `Session` schema includes `title: Authentication Session`, but `SessionListResponse` has no `title`. Other list-response schemas in this repo typically carry a title for SDK/docs tooling to surface a readable name. Consider adding one for consistency.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code

Comment on lines +41 to +49
type: string
format: date-time
description: Timestamp when the session was last updated.
example: '2026-04-08T15:35:00Z'
expiresAt:
type: string
format: date-time
description: Timestamp after which the session is no longer valid.
example: '2026-04-08T15:35:00Z'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 updatedAt and expiresAt share the same example timestamp

Both updatedAt and expiresAt use '2026-04-08T15:35:00Z', implying the session was last updated at the exact moment it expires. This is misleading for readers trying to understand the semantics of each field. Consider using a later timestamp for expiresAt (e.g. '2026-04-09T15:30:01Z' for a 24-hour session) to make the distinction clear.

Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/components/schemas/auth/Session.yaml
Line: 41-49

Comment:
**`updatedAt` and `expiresAt` share the same example timestamp**

Both `updatedAt` and `expiresAt` use `'2026-04-08T15:35:00Z'`, implying the session was last updated at the exact moment it expires. This is misleading for readers trying to understand the semantics of each field. Consider using a later timestamp for `expiresAt` (e.g. `'2026-04-09T15:30:01Z'` for a 24-hour session) to make the distinction clear.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code

Comment on lines +29 to +31
for `PASSKEY`).
example: example@lightspark.com
ip:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 ip required — consider nullable from the start

The PR description explicitly calls out: "If certain flows legitimately have no IP, we can relax to nullable in a follow-up." Making ip required in v1 is a breaking change to relax later — clients that auto-generate models will bake in non-null assumptions. Marking it nullable: true (and removing from required) now is non-breaking and avoids a future contract change if, e.g., server-initiated or internal flows produce sessions without a client IP.

Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/components/schemas/auth/Session.yaml
Line: 29-31

Comment:
**`ip` required — consider nullable from the start**

The PR description explicitly calls out: _"If certain flows legitimately have no IP, we can relax to nullable in a follow-up."_ Making `ip` required in v1 is a breaking change to relax later — clients that auto-generate models will bake in non-null assumptions. Marking it `nullable: true` (and removing from `required`) now is non-breaking and avoids a future contract change if, e.g., server-initiated or internal flows produce sessions without a client IP.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

Comment on lines +28 to +55
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: ../../components/schemas/auth/SessionListResponse.yaml
'400':
description: Bad request - Invalid parameters
content:
application/json:
schema:
$ref: ../../components/schemas/errors/Error400.yaml
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: ../../components/schemas/errors/Error401.yaml
'404':
description: Internal account not found
content:
application/json:
schema:
$ref: ../../components/schemas/errors/Error404.yaml
'500':
description: Internal service error
content:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing 403 Forbidden response

The endpoint uses BasicAuth and accepts an arbitrary accountId query parameter. If the authenticated caller provides a valid accountId that belongs to a different account (one they are not authorized to inspect), the server should return 403 Forbidden rather than 404. The current spec only covers 400 / 401 / 404 / 500, leaving the authorization-failure case undocumented. The sibling GET /auth/credentials endpoint would be the natural reference to check for consistency.

Prompt To Fix With AI
This is a comment left during a code review.
Path: openapi/paths/auth/auth_sessions.yaml
Line: 28-55

Comment:
**Missing `403 Forbidden` response**

The endpoint uses `BasicAuth` and accepts an arbitrary `accountId` query parameter. If the authenticated caller provides a valid `accountId` that belongs to a different account (one they are not authorized to inspect), the server should return `403 Forbidden` rather than `404`. The current spec only covers `400 / 401 / 404 / 500`, leaving the authorization-failure case undocumented. The sibling `GET /auth/credentials` endpoint would be the natural reference to check for consistency.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

@DhruvPareek DhruvPareek force-pushed the 04-22-feat_add_delete__auth_credentials__id_to_revoke_authentication_credentials branch from 9198355 to b8d867f Compare April 22, 2026 23:36
@DhruvPareek DhruvPareek force-pushed the 04-22-feat_add_get__auth_sessions_to_list_authentication_sessions branch from a8f600d to 8ccc496 Compare April 22, 2026 23:36
Introduces the `Session` resource and a list endpoint. A session is created each time an authentication credential is verified via `POST /auth/credentials/{id}/verify` and remains active until its `expiresAt` or until it is revoked (revocation endpoint lands in the next PR).

**Endpoint**
- `GET /auth/sessions?accountId={id}` → 200 `SessionListResponse`.
- Query parameters: `accountId` (required).

**Schemas added**
- `Session` — `{ id, accountId, type, nickname, ip, createdAt, updatedAt, expiresAt }`. `id` is prefixed `Session:<uuid>` to match Grid's resource-prefixed ID convention. `type` reuses the shared `AuthMethodType` enum so it aligns with the credential that issued the session. `nickname` is inherited from that credential.
- `SessionListResponse` — `{ data: Session[] }`, non-paginated.

**Wire-up**
- New path file `openapi/paths/auth/auth_sessions.yaml` with just a `get` operation.
- `openapi/openapi.yaml` registers `/auth/sessions`.
- `.stainless/stainless.yml` adds a new `sessions` subresource under `auth` (sibling of `credentials`) with `list: get /auth/sessions` and registers the two new schemas as models.
- Bundled `openapi.yaml` + `mintlify/openapi.yaml` regenerated.

**Notes vs the Grid convention**
- `openapi/README.md` says list endpoints use cursor pagination. Deviating here because an internal account has a small, bounded number of concurrent sessions (typically 1–4, one per signed-in device). Adding `hasMore` / `nextCursor` / `totalCount` later is non-breaking per the README, so we can backtrack if the cardinality assumption changes. Matches the same deviation on `GET /auth/credentials`.

**Notes vs the PDF spec**
- PDF uses `"type": "OTP"`; kept `EMAIL_OTP` to match the shared `AuthMethodType` enum.
- PDF uses `session:uuid` (lowercase) for the id prefix; switched to `Session:<uuid>` to match the rest of Grid's ID conventions.
- `ip` is required per the PDF. If certain flows legitimately have no IP, we can relax to nullable in a follow-up.
@DhruvPareek DhruvPareek force-pushed the 04-22-feat_add_get__auth_sessions_to_list_authentication_sessions branch from 8ccc496 to bc0e8be Compare April 23, 2026 02:38
@DhruvPareek DhruvPareek force-pushed the 04-22-feat_add_delete__auth_credentials__id_to_revoke_authentication_credentials branch from b8d867f to 65bd260 Compare April 23, 2026 02:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant