Skip to content

fix(organizations): correct member and switch response types#95

Merged
Bccorb merged 1 commit into
mainfrom
fix/organization-response-types
Jul 20, 2026
Merged

fix(organizations): correct member and switch response types#95
Bccorb merged 1 commit into
mainfrom
fix/organization-response-types

Conversation

@Bccorb

@Bccorb Bccorb commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

What

Audit every client response type against the API's declared response schemas, and fix the three that were wrong.

Closes #90.

Method

seamless-auth-api declares a response schema per route in src/routes/*.routes.ts. That is a stronger source than reading controller bodies and does not need a running server, so I mapped every route the SDK calls to its declared schema and compared each against the SDK type.

Fixed

Method Declared schema Was typed as
addOrganizationMember { membership } { members, total }
updateOrganizationMember { membership } { members, total }
removeOrganizationMember { message } { members, total }
switchOrganization { message, token, sub, sessionId, organizationId, organization, ttl } { organization }

The first three are the same defect as #88: a caller reading .members gets undefined. switchOrganization was not broken, since { organization } is a subset, but it hid message and organizationId from consumers.

Confirmed correct, no change

The rest of the surface matched, including the parts I was least sure about:

  • /users/me matches CurrentUserResult exactly, including the optional organizations and nullable activeOrganization
  • StepUpStatus matches StepUpStatusSchema field for field, and StepUpSuccessSchema confirms the message / fresh / method triple that toStepUpStatus checks
  • TotpStatus and TotpEnrollmentStartResult match
  • OAuth provider listing, start, and callback match
  • GET /organizations, GET /:id, POST /, PATCH /:id, and GET /:id/members match
  • register, the OTP endpoints, magic-link verify, and the WebAuthn finish endpoints all carry message, so MessageResult is accurate

I also confirmed the literal message === 'Success' comparisons the code depends on. registration.ts, authentication.ts, stepUp.ts, and sessionIssuance.ts all send exactly 'Success'.

The magic-link fix is confirmed correct

GET /magic-link/check declares both 200: MagicLinkPollSuccessSchema and 204: MessageSchema, and its success path runs through issueSessionAndRespond, which sends 200 { message: 'Success' }. That is exactly what the fix in #86 checks for, and the not-yet-clicked paths return a bodyless 204. Independent confirmation that the fix matches the real contract rather than only the test.

A deliberate omission

OrganizationSwitchResult models message, organizationId, and organization, but not the token, sub, sessionId, and ttl the endpoint also returns. This SDK is cookie-based, so adopters have no reason to handle raw session material, and typing it would invite them to. The fields are still present at runtime for anyone who needs them.

Note for the end-to-end run

Several endpoints answer 201 rather than 200 (POST /organizations, POST /:id/members). That is handled correctly, since success is determined by response.ok, not an exact status. The one place an exact status mattered was the magic-link poll, which is now explicit.

Checks

  • npm run typecheck, npm run lint, npm run format:check clean
  • Full suite: 208 passed, including a new test pinning the membership envelope and message shapes
  • Changeset (patch)

@Bccorb
Bccorb merged commit 1c4f4d2 into main Jul 20, 2026
2 of 3 checks passed
@Bccorb
Bccorb deleted the fix/organization-response-types branch July 20, 2026 13:05
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.

Verify client response-shape assumptions against a running server

1 participant