add GET /auth/sessions to list authentication sessions#370
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
✱ Stainless preview buildsThis PR will update the kotlin openapi python typescript 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 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.gzNew 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
108f6cf to
fec18b2
Compare
570eafb to
c1826de
Compare
c1826de to
ceee7f8
Compare
fec18b2 to
088d2dc
Compare
088d2dc to
9f6c7a1
Compare
ceee7f8 to
16b43cc
Compare
16b43cc to
9599289
Compare
9f6c7a1 to
52fcd4f
Compare
52fcd4f to
9198355
Compare
9599289 to
a8f600d
Compare
Greptile SummaryThis PR introduces the All remaining findings are P2 style/polish items: a missing Confidence Score: 5/5Safe 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).
|
| 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
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
| type: object | ||
| required: | ||
| - data | ||
| properties: | ||
| data: | ||
| type: array | ||
| description: List of active authentication sessions for the internal account. | ||
| items: | ||
| $ref: ./Session.yaml |
There was a problem hiding this 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.
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!
| 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' |
There was a problem hiding this 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.
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!
| for `PASSKEY`). | ||
| example: example@lightspark.com | ||
| ip: |
There was a problem hiding this 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.
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.| 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: |
There was a problem hiding this 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.
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.9198355 to
b8d867f
Compare
a8f600d to
8ccc496
Compare
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.
8ccc496 to
bc0e8be
Compare
b8d867f to
65bd260
Compare

Introduces the
Sessionresource and a list endpoint. A session is created each time an authentication credential is verified viaPOST /auth/credentials/{id}/verifyand remains active until itsexpiresAtor until it is revoked (revocation endpoint lands in the next PR).Endpoint
GET /auth/sessions?accountId={id}→ 200SessionListResponse.accountId(required).Schemas added
Session—{ id, accountId, type, nickname, ip, createdAt, updatedAt, expiresAt }.idis prefixedSession:<uuid>to match Grid's resource-prefixed ID convention.typereuses the sharedAuthMethodTypeenum so it aligns with the credential that issued the session.nicknameis inherited from that credential.SessionListResponse—{ data: Session[] }, non-paginated.Wire-up
openapi/paths/auth/auth_sessions.yamlwith just agetoperation.openapi/openapi.yamlregisters/auth/sessions..stainless/stainless.ymladds a newsessionssubresource underauth(sibling ofcredentials) withlist: get /auth/sessionsand registers the two new schemas as models.openapi.yaml+mintlify/openapi.yamlregenerated.Notes vs the Grid convention
openapi/README.mdsays 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). AddinghasMore/nextCursor/totalCountlater is non-breaking per the README, so we can backtrack if the cardinality assumption changes. Matches the same deviation onGET /auth/credentials.Notes vs the PDF spec
"type": "OTP"; keptEMAIL_OTPto match the sharedAuthMethodTypeenum.session:uuid(lowercase) for the id prefix; switched toSession:<uuid>to match the rest of Grid's ID conventions.ipis required per the PDF. If certain flows legitimately have no IP, we can relax to nullable in a follow-up.