Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .changeset/dts-relative-paths.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
"@seamless-auth/react": patch
'@seamless-auth/react': patch
---

Emit relative import paths in the published type declarations. The build kept the
Expand Down
27 changes: 20 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,25 @@ Runtime exports currently include:
- `usePasskeySupport`
- `hasScopedRole` and `roleGrantsAccess`
- `encodePrfSalt`, `extractPasskeyPrfResult`, and `isPasskeyPrfSupported`
- `SeamlessAuthError`

Every request method on the client and the provider resolves to a
`SeamlessAuthResult<T>` (`{ data, error }`) and does not throw for HTTP or
transport failures. `isPasskeyPrfSupported` is the exception (a local capability
check returning a boolean).

Exported types currently include the provider/client input and result types plus
domain models, for example:

- `AuthContextType`, `Credential`, `User`, `Organization`, `OrganizationMembership`
- `SeamlessAuthResult`, `MessageResult`
- `LoginInput`, `LoginMethod`, `LoginStartResult`, `RegisterInput`, `CurrentUserResult`
- `PasskeyMetadata`, `PasskeyLoginResult`, `PasskeyLoginWithPrfResult`, `PasskeyRegistrationResult`, `RegisterPasskeyOptions`
- `PasskeyMetadata`, `PasskeyLoginData`, `PasskeyRegistrationData`, `RegisterPasskeyOptions`
- `PasskeyPrfInput`, `PasskeyPrfResult`
- Credential types: `CredentialUpdateResult`
- OAuth types: `OAuthProvider`, `OAuthProvidersResult`, `StartOAuthLoginInput`, `StartOAuthLoginResult`, `FinishOAuthLoginInput`
- Organization types: `CreateOrganizationInput`, `UpdateOrganizationInput`, `OrganizationMemberInput`, `OrganizationMemberUpdateInput`, `OrganizationsResult`, `OrganizationResult`, `OrganizationMembersResult`
- Step-up types: `StepUpMethod`, `StepUpStatus`, `StepUpVerificationResult`, `StepUpWithPasskeyPrfResult`
- Organization types: `CreateOrganizationInput`, `UpdateOrganizationInput`, `OrganizationMemberInput`, `OrganizationMemberUpdateInput`, `OrganizationsResult`, `OrganizationResult`, `OrganizationMembersResult`, `OrganizationMembershipResult`, `OrganizationSwitchResult`
- Step-up types: `StepUpMethod`, `StepUpStatus`, `StepUpPrfData`
- `SeamlessAuthClient` and `SeamlessAuthClientOptions`

Public API changes should be treated deliberately:
Expand Down Expand Up @@ -178,9 +186,9 @@ The built-in flows and exported client assume these route families exist:
- `/webAuthn/login/finish`
- `/webAuthn/register/start`
- `/webAuthn/register/finish`
- `/otp/generate-phone-otp`, `/otp/generate-email-otp`, and their `-login-` variants
- `POST /otp/generate-phone-otp`, `/otp/generate-email-otp`, and their `-login-` variants
- `/otp/verify-phone-otp`, `/otp/verify-email-otp`, and their `-login-` variants
- `/magic-link`
- `POST /magic-link`
- `/magic-link/check`
- `/magic-link/verify/:token`
- `/oauth/providers`, `/oauth/:providerId/start`, `/oauth/:providerId/callback`
Expand All @@ -195,6 +203,12 @@ The `@seamless-auth/express` adapter mounts the WebAuthn routes as `/webAuthn`
Keep the client paths byte-for-byte aligned with the adapter's mounted paths;
do not "normalize" casing here in isolation.

The OTP generate routes and `/magic-link` are `POST`, not `GET`. As `GET` they
were state-changing simple cross-site requests (an `<img>` tag could trigger SMS
or email sends), so both the client and the adapter serve them over `POST` with a
JSON body to force a CORS preflight. This depends on a matching adapter version;
do not revert them to `GET` in isolation.

Before documenting new flow behavior, verify the route contract in `seamless-auth-server` or `seamless-auth-api`.

## Migration Status
Expand Down Expand Up @@ -234,8 +248,7 @@ For docs work:
The biggest remaining gaps are no longer hidden internals. They are mostly polish and documentation-oriented:

- custom UI examples can still be improved, especially full end-to-end examples for bespoke login and registration screens
- passkey login currently handles the no-MFA and unsupported-browser paths cleanly, but there is still no bundled MFA continuation route
- some client methods intentionally return raw `Response` objects, so callers are responsible for checking `response.ok` and handling body parsing consistently
- there is no bundled MFA continuation route; login is not gated on a second factor today
- public docs in sibling repos may still reflect older package behavior

If you tackle one of these, keep the solution aligned with the existing public surface instead of reintroducing private screen-only helpers.
Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ cp .env.example .env
> Change the APP_ORIGIN env to `http://localhost:5173` to match vite.
> The React SDK talks to a server adapter mounted at `/auth`, not directly to API auth cookies.

### If docker and docker compose are avaliable
### If docker and docker compose are available

```bash
docker compose up -d
Expand Down Expand Up @@ -95,7 +95,7 @@ curl http://localhost:5312/health/status

## 3. Create a Local Test Application

You will need a web application to integerate the SDK into.
You will need a web application to integrate the SDK into.
We recommend using Vite for fast iteration:

```bash
Expand All @@ -106,7 +106,7 @@ npm create vite@latest seamless-auth-dev
### Select React as the framework, Typescript as the variant
```

> Web site will be active at http://localhost:5137
> Web site will be active at http://localhost:5173

---

Expand Down
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
- `useAuthClient()`
- `usePasskeySupport()`
- `hasScopedRole()` and `roleGrantsAccess()`
- types including `AuthContextType`, `Credential`, `User`, `OAuthProvider`, `StepUpStatus`, and the headless client input/result types
- `SeamlessAuthError`, the error type carried on a failed result
- types including `AuthContextType`, `Credential`, `User`, `OAuthProvider`, `StepUpStatus`, the `SeamlessAuthResult` wrapper, and the headless client input/result types

## Installation

Expand Down Expand Up @@ -546,8 +547,9 @@ function CustomRegistration() {
const [step, setStep] = useState<'details' | 'verify'>('details');
const [message, setMessage] = useState('');

async function createAccount(email: string, phone: string) {
const { error } = await authClient.register({ email, phone });
async function createAccount(email: string) {
// Registration needs only an email. A phone can be added and verified later.
const { error } = await authClient.register({ email });

if (error) {
setMessage(error.message);
Expand Down Expand Up @@ -783,15 +785,15 @@ The built-in flows assume compatible endpoints for:
- `/webAuthn/login/finish`
- `/webAuthn/register/start`
- `/webAuthn/register/finish`
- `/otp/generate-phone-otp`
- `/otp/generate-email-otp`
- `POST /otp/generate-phone-otp`
- `POST /otp/generate-email-otp`
- `/otp/verify-phone-otp`
- `/otp/verify-email-otp`
- `/otp/generate-login-phone-otp`
- `/otp/generate-login-email-otp`
- `POST /otp/generate-login-phone-otp`
- `POST /otp/generate-login-email-otp`
- `/otp/verify-login-phone-otp`
- `/otp/verify-login-email-otp`
- `/magic-link`
- `POST /magic-link`
- `/magic-link/check`
- `/magic-link/verify/:token`
- `/oauth/providers`
Expand All @@ -814,6 +816,11 @@ The built-in flows assume compatible endpoints for:
- `/organizations/:organizationId/members`
- `/organizations/:organizationId/members/:userId`

The state-changing OTP and magic-link request routes are `POST` (marked above). They were previously
`GET`, which made them reachable as simple cross-site requests, so an `<img>` tag could trigger SMS or
email sends to a signed-in user. Using `@seamless-auth/react` with an older adapter that only serves the
`GET` forms returns a 404 for those requests. See the changelog for the minimum adapter version.

## Notes

- This package does not create its own `<BrowserRouter>`.
Expand Down
10 changes: 10 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ When changesets are merged to `main`, the workflow opens or updates a release PR
Review that PR like a normal release artifact. When it is merged, the workflow publishes the npm
package, creates the Git tag, and creates the GitHub Release.

## Adapter compatibility

Some SDK changes require a matching `@seamless-auth/express` version, because the client and the
adapter share a route contract. Recent examples: the OTP generate and magic-link routes moved from
`GET` to `POST`, and the WebAuthn paths are casing sensitive. When a change touches request paths or
methods, the changeset states the minimum adapter version.

When a change spans both repos, publish the adapter first, then the SDK. Publishing the SDK against an
older adapter leaves adopters with a 404 on the affected flow until a compatible adapter exists.

## npm Publishing

The workflow publishes with `NPM_CONFIG_PROVENANCE=true`, so npm records provenance for the package.
Expand Down
10 changes: 2 additions & 8 deletions tsconfig.build.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@
"sourceMap": true,
"rootDir": "./src"
},
"include": [
"src"
],
"exclude": [
"tests",
"**/*.test.ts",
"**/*.spec.ts"
]
"include": ["src"],
"exclude": ["tests", "**/*.test.ts", "**/*.spec.ts"]
}
Loading