@foir/sdk 0.21.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/CHANGELOG.md +135 -1
  2. package/README.md +15 -15
  3. package/dist/app/client.d.ts +93 -86
  4. package/dist/app/contract/proto/apps/v1/apps_pb.d.ts +14 -13
  5. package/dist/app/dispatch.d.ts +5 -5
  6. package/dist/app/errors.d.ts +17 -15
  7. package/dist/app/index.d.ts +4 -4
  8. package/dist/app/naming.d.ts +1 -1
  9. package/dist/app/ticket.d.ts +2 -2
  10. package/dist/app/vocabulary.generated.d.ts +2 -2
  11. package/dist/app-contract.js +3 -3
  12. package/dist/app.js +92 -90
  13. package/dist/auth/access.d.ts +19 -19
  14. package/dist/auth/auth.d.ts +251 -117
  15. package/dist/auth/grant-table.generated.d.ts +5 -4
  16. package/dist/auth/hosted.d.ts +38 -14
  17. package/dist/auth/index.d.ts +9 -9
  18. package/dist/auth/operations.d.ts +153 -33
  19. package/dist/auth/ops.d.ts +39 -21
  20. package/dist/auth/session-client.d.ts +3 -3
  21. package/dist/auth-session.js +3 -3
  22. package/dist/auth.js +400 -250
  23. package/dist/client.js +5 -8
  24. package/dist/codegen/preset.d.ts +1 -1
  25. package/dist/data/builtins.d.ts +26 -26
  26. package/dist/data/client.d.ts +3 -3
  27. package/dist/data/decimal.d.ts +1 -1
  28. package/dist/data/index.d.ts +1 -1
  29. package/dist/data/manifest.d.ts +1 -1
  30. package/dist/data/schema.d.ts +2 -2
  31. package/dist/data/transport.d.ts +14 -13
  32. package/dist/data/ws-transport.d.ts +1 -1
  33. package/dist/data.js +8 -11
  34. package/dist/graphql/content-client.d.ts +13 -13
  35. package/dist/index.js +1 -4
  36. package/dist/live/drift.d.ts +1 -1
  37. package/dist/media/screen-capture.d.ts +1 -1
  38. package/dist/next/index.d.ts +2 -2
  39. package/dist/next/session.d.ts +10 -10
  40. package/dist/next.js +78 -60
  41. package/dist/placement/index.d.ts +13 -13
  42. package/dist/placement.js +127 -116
  43. package/dist/push.js +62 -44
  44. package/dist/react/FoirFeedback.d.ts +2 -2
  45. package/dist/react/FoirProvider.d.ts +24 -24
  46. package/dist/react/SignIn.d.ts +4 -4
  47. package/dist/react/UserButton.d.ts +1 -1
  48. package/dist/react/feedback-notes.d.ts +8 -6
  49. package/dist/react/index.d.ts +3 -3
  50. package/dist/react.js +238 -209
  51. package/dist/realtime/index.d.ts +1 -1
  52. package/dist/server/callback-client.d.ts +4 -4
  53. package/dist/server/events-client.d.ts +21 -21
  54. package/dist/server/operation-types.d.ts +8 -8
  55. package/dist/server/require-scoped-token.d.ts +3 -3
  56. package/dist/server/types.d.ts +2 -2
  57. package/dist/server/verify-scoped-token.d.ts +3 -3
  58. package/dist/server.js +130 -126
  59. package/dist/transport/foir-http.d.ts +14 -14
  60. package/dist/transport/key-kind.d.ts +1 -12
  61. package/dist/types/index.d.ts +2 -2
  62. package/package.json +1 -1
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * Hosted-login bridge — for storefronts that delegate sign-in to a Foir
3
- * white-label front door (the `customerLoginWithFoir` flow) instead of
3
+ * white-label front door (the `loginWithFoir` flow) instead of
4
4
  * rendering their own login UI.
5
5
  *
6
6
  * The front door sets a first-party session cookie on the registrable domain;
7
7
  * because that domain is shared, the cookie reaches the storefront, which
8
- * exchanges it server-side for a short-lived customer bearer + identity. The
8
+ * exchanges it server-side for a short-lived user bearer + identity. The
9
9
  * cookie is the durable credential (re-exchanged on bearer expiry) — there's
10
10
  * no separate refresh token in this flow.
11
11
  *
@@ -15,7 +15,7 @@
15
15
  export interface HostedLoginConfig {
16
16
  /** White-label front-door origin, e.g. `https://login.example.com`. */
17
17
  loginOrigin: string;
18
- /** Session cookie name set on the registrable domain. Default `foir_customer_session`. */
18
+ /** Session cookie name set on the registrable domain. Default `foir_session`. */
19
19
  cookieName?: string;
20
20
  /** Session-exchange path on the front door. Default `/session/token`. */
21
21
  sessionPath?: string;
@@ -29,13 +29,13 @@ export interface HostedLoginConfig {
29
29
  export declare function hostedLoginUrl(config: HostedLoginConfig, returnTo?: string): string;
30
30
  /**
31
31
  * Build the redirect URL that ENDS the hosted session — the mirror of
32
- * `hostedLoginUrl`, and the only thing that actually signs a customer out on
32
+ * `hostedLoginUrl`, and the only thing that actually signs a user out on
33
33
  * this flow.
34
34
  *
35
35
  * The cookie is the durable credential. Disposing of a bearer, clearing a
36
- * local session, or calling the `customerLogout` mutation (which clears
36
+ * local session, or calling the `logout` mutation (which clears
37
37
  * upstream provider tokens and nothing else) all leave it in place, and the
38
- * next request re-establishes the customer from it. This URL points at the
38
+ * next request re-establishes the user from it. This URL points at the
39
39
  * front door's end-session endpoint, which revokes the session row and clears
40
40
  * the cookie before returning the browser to `returnTo`.
41
41
  *
@@ -50,7 +50,7 @@ export declare function hostedLogoutUrl(config: HostedLoginConfig, clientId: str
50
50
  /** The identity + bearer returned by a successful hosted-session exchange. */
51
51
  export interface HostedSession {
52
52
  token: string;
53
- customerId: string;
53
+ userId: string;
54
54
  email: string;
55
55
  /**
56
56
  * Seconds until `token` lapses, from the endpoint's `expires_in`.
@@ -61,7 +61,7 @@ export interface HostedSession {
61
61
  * lifetime (coupling a storefront to a server constant it cannot see) or to
62
62
  * decode `exp` off the JWT. Both re-derive a number the response already
63
63
  * carried, and a consumer that does neither treats a 15-minute bearer as good
64
- * forever — which reads as a customer being signed out mid-session.
64
+ * forever — which reads as a user being signed out mid-session.
65
65
  *
66
66
  * Store the death date, not this number: it is seconds from when the exchange
67
67
  * ANSWERED, and a value held across requests is already stale.
@@ -76,9 +76,9 @@ export interface HostedSession {
76
76
  * reason says what happened.
77
77
  *
78
78
  * Collapsing all of this to `null` is what made a transient blip on
79
- * `/session/token` indistinguishable from a genuinely signed-out customer. The
79
+ * `/session/token` indistinguishable from a genuinely signed-out user. The
80
80
  * only safe-looking action on a bare `null` is to clear the session and send
81
- * the customer to the front door, so one 502 signed out a customer whose 30-day
81
+ * the user to the front door, so one 502 signed out a user whose 30-day
82
82
  * cookie was perfectly valid — and the route's rate limiter is deliberately
83
83
  * fail-open for exactly the opposite reason ("a Redis outage should degrade an
84
84
  * authenticated app, not log it out").
@@ -90,7 +90,7 @@ export type HostedSessionResult =
90
90
  session: HostedSession;
91
91
  }
92
92
  /**
93
- * The customer is signed out. Act on it: clear any local session and send
93
+ * The user is signed out. Act on it: clear any local session and send
94
94
  * them to `hostedLoginUrl`.
95
95
  *
96
96
  * `no-cookie` — nothing to exchange. `rejected` — the front door refused the
@@ -102,12 +102,12 @@ export type HostedSessionResult =
102
102
  }
103
103
  /**
104
104
  * The exchange could not be completed, and it says NOTHING about whether the
105
- * customer is signed in. KEEP the existing session, serve the request, try
105
+ * user is signed in. KEEP the existing session, serve the request, try
106
106
  * again on the next one.
107
107
  *
108
108
  * `forbidden` is the odd one: a 403 means the CSRF header did not arrive
109
109
  * (a proxy stripping it, most likely), which is a misconfiguration rather
110
- * than a blip. Retrying will not fix it — but signing the customer out would
110
+ * than a blip. Retrying will not fix it — but signing the user out would
111
111
  * be wrong, so the safe action is the same and it is grouped by that.
112
112
  */
113
113
  | {
@@ -119,7 +119,7 @@ export type HostedSessionResult =
119
119
  cause?: unknown;
120
120
  };
121
121
  /**
122
- * Exchange the hosted-login cookie on an incoming request for a customer
122
+ * Exchange the hosted-login cookie on an incoming request for a user
123
123
  * bearer + identity (server-to-server: forwards the cookie to the front door's
124
124
  * session endpoint with the CSRF header).
125
125
  *
@@ -127,3 +127,27 @@ export type HostedSessionResult =
127
127
  * returning `null` for everything that is not a success.
128
128
  */
129
129
  export declare function fetchHostedSession(request: Request, config: HostedLoginConfig): Promise<HostedSessionResult>;
130
+ /**
131
+ * What the hosted login said beside the code when it sent someone back to your
132
+ * app. A sign-in it refused carries a stable code (`foir_error`); one that
133
+ * connected a provider to the person's account on the way in names the
134
+ * provider (`foir_connected`). Each comes with a sentence your app can show as
135
+ * it is, so an app that does nothing more still shows words and never a code.
136
+ * Show your own words for a code by switching on `code`.
137
+ */
138
+ export type HostedSignInNotice = {
139
+ kind: 'refused';
140
+ code: string;
141
+ message: string;
142
+ } | {
143
+ kind: 'connected';
144
+ provider: string;
145
+ message: string;
146
+ };
147
+ /**
148
+ * Reads the notice off the address the hosted login sent the browser back to:
149
+ * your callback URL, its search string, or its parameters. `names` maps a
150
+ * provider's key to the name to show (from `getAuthProviders`); without it the
151
+ * key is shown. Null when the hosted login said nothing.
152
+ */
153
+ export declare function hostedSignInNoticeOf(location: string | URL | URLSearchParams, names?: Record<string, string>): HostedSignInNotice | null;
@@ -1,8 +1,8 @@
1
1
  /**
2
- * `@foir/sdk/auth` — framework-agnostic Foir customer auth.
2
+ * `@foir/sdk/auth`: framework-agnostic sign-in for your app's users.
3
3
  *
4
- * The whole customer auth surface — login, register, OTP, external providers,
5
- * refresh, password management, email verification and account deletion — over
4
+ * The whole sign-in surface (login, register, OTP, external providers,
5
+ * refresh, password management, email verification and account deletion) over
6
6
  * the server's generated `auth` namespace, plus token lifecycle with an
7
7
  * injected `SessionAdapter`, guards, and the optional hosted-login bridge.
8
8
  *
@@ -10,15 +10,15 @@
10
10
  * the caller's own manifest advertises, through the same op transport
11
11
  * `@foir/sdk/data` uses, so `graphql` is not on this module's path at all.
12
12
  */
13
- export { customerLogin, customerRegister, customerRequestOTP, customerLoginOTP, customerRefreshToken, customerLoginWithProvider, customerProviderCallback, customerProviderVerifyOTP, getAuthProviders, getAuthConfig, getDefaultAuthProvider, customerSignupContext, customerJoinWaitlist, customerRequestPasswordReset, customerResetPassword, customerUpdatePassword, customerVerifyEmail, currentUser, myProviderToken, customerLogout, deleteMyAccount, myOrganizations, selectOrganization, registerOrganization, saveSession, clearSession, getSessionToken, getSessionCustomer, loginWithPassword, registerWithPassword, loginWithOTP, resetPasswordAndSignIn, refreshSession, refreshSessionOnce, signOut, authedRequest, authedOp, requireAuth, requireAdmin, } from './auth';
14
- export type { FoirAuthTokens, FoirCustomer, FoirUser, SessionAdapter, RequireAuthOptions, RequireAdminOptions, } from './auth';
15
- export { customerAccess, getSessionAccess, hasRole, hasScope, requireRole, requireScope, FoirAccessDeniedError, } from './access';
13
+ export { login, register, requestOTP, loginWithOTP, refreshTokens, loginWithProvider, providerCallback, providerVerifyOTP, providerSignInRefusalOf, signInRefusalOf, confirmProviderLink, resendProviderLinkCode, getAuthProviders, getAuthConfig, getDefaultAuthProvider, signupContext, joinWaitlist, requestPasswordReset, resetPassword, updatePassword, verifyEmail, currentUser, myProviderToken, logout, deleteMyAccount, updateMyProfile, myAuthorizedApps, revokeAuthorizedApp, mySessions, endMySession, signOutEverywhere, createPersonalAccessToken, mySignInMethods, connectSignInMethod, disconnectSignInMethod, myFactors, beginStepUp, completeStepUp, beginFactorEnrollment, completeFactorEnrollment, removeFactor, makeRecoveryCodes, myOrganizations, registerOrganization, saveSession, clearSession, getSessionToken, getSessionUser, signInWithPassword, signUpWithPassword, signInWithOTP, resetPasswordAndSignIn, refreshSession, refreshSessionOnce, signOut, authedRequest, authedOp, requireAuth, } from './auth';
14
+ export type { FoirAuthTokens, FoirUser, SessionAdapter, RequireAuthOptions, } from './auth';
15
+ export { userAccess, getSessionAccess, hasRole, hasScope, requireRole, requireScope, FoirAccessDeniedError, } from './access';
16
16
  export type { FoirAccess, FoirAccessDenial } from './access';
17
17
  export { FoirAuthDowngradedError, FoirSessionExpiredError } from '../graphql/foir-request';
18
18
  export { AUTH_OPS } from './ops';
19
19
  export type { AuthOpName, AuthOpOptions } from './ops';
20
- export { hostedLoginUrl, hostedLogoutUrl, fetchHostedSession } from './hosted';
21
- export type { HostedLoginConfig, HostedSession, HostedSessionResult } from './hosted';
20
+ export { hostedLoginUrl, hostedLogoutUrl, fetchHostedSession, hostedSignInNoticeOf } from './hosted';
21
+ export type { HostedLoginConfig, HostedSession, HostedSessionResult, HostedSignInNotice } from './hosted';
22
22
  export { createFoirSessionClient } from './session-client';
23
23
  export type { FoirSessionClient, FoirSessionConfig, FoirSessionUser, } from './session-client';
24
- export type { CustomerAuthResult, ProviderLoginResult, AuthProviderPublic, ProviderLoginInput, ProviderCallbackInput, ProviderOTPVerifyInput, SignupContext, SignupMode, WaitlistJoinResult, AuthConfig, AuthConfigProvider, DefaultAuthProvider, CurrentUser, ProviderToken, DeleteAccountResult, MyOrganization, SelectedOrganization, } from './operations';
24
+ export type { AuthResult, ProviderLoginResult, AuthProviderPublic, ProviderLoginInput, ProviderCallbackInput, ProviderOTPVerifyInput, SignupContext, SignupMode, WaitlistJoinResult, AuthConfig, AuthConfigProvider, DefaultAuthProvider, CurrentUser, ProviderToken, ProviderTokenRefresh, DeleteAccountResult, MyOrganization, MyProfile, MyProfileChange, AuthorizedApp, MySession, NewPersonalAccessToken, MySignInMethod, MyFactor, StepUp, FactorEnrollment, } from './operations';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Foir customer-auth result and input types.
2
+ * Foir sign-in result and input types.
3
3
  *
4
4
  * These are PLATFORM-STABLE primitives — login / register / refresh / OTP /
5
5
  * provider login / password management / account lifecycle are fixed-shape
@@ -25,15 +25,15 @@
25
25
  * and they are the reason `@foir/sdk/auth/session` had to exist as a
26
26
  * separate graphql-free door.
27
27
  *
28
- * The project-specific customer PROFILE (e.g. `myProfile.isAdmin`) is still NOT
29
- * here — that shape varies per project, so it stays consumer-injected (see
28
+ * Anything project-specific about the user (a profile record, say) is NOT
29
+ * here: that shape varies per project, so it stays consumer-injected (see
30
30
  * `requireAuth`'s `resolveUser`).
31
31
  */
32
32
  /** The common auth result every login/register/refresh mutation returns. */
33
- export interface CustomerAuthResult {
33
+ export interface AuthResult {
34
34
  token: string;
35
35
  refreshToken: string;
36
- customerId: string;
36
+ userId: string;
37
37
  email: string;
38
38
  }
39
39
  /** Result of initiating a provider login — a redirect URL or an inline token. */
@@ -70,7 +70,7 @@ export interface ProviderOTPVerifyInput {
70
70
  email: string;
71
71
  otp: string;
72
72
  }
73
- /** The project's customer signup mode. */
73
+ /** The project's signup mode. */
74
74
  export type SignupMode = 'PUBLIC' | 'RESTRICTED' | 'WAITLIST' | 'CLOSED';
75
75
  /** The signup surface a self-hosted frontend reads to render the right UI. */
76
76
  export interface SignupContext {
@@ -93,7 +93,7 @@ export interface AuthConfigProvider {
93
93
  /**
94
94
  * The project's public auth configuration: which built-in methods are on, and
95
95
  * which external providers a login screen should offer. Readable before any
96
- * customer token exists — it is what a login screen renders itself from.
96
+ * user token exists: it is what a login screen renders itself from.
97
97
  */
98
98
  export interface AuthConfig {
99
99
  passwordEnabled: boolean;
@@ -110,8 +110,8 @@ export interface DefaultAuthProvider {
110
110
  type: string | null;
111
111
  }
112
112
  /**
113
- * The calling customer, resolved from the bearer token. `null` when the request
114
- * carried no customer token — an absent session is an answer, not a failure.
113
+ * The calling user, resolved from the bearer token. `null` when the request
114
+ * carried no user token: an absent session is an answer, not a failure.
115
115
  */
116
116
  export interface CurrentUser {
117
117
  id: string;
@@ -123,18 +123,33 @@ export interface CurrentUser {
123
123
  /** ISO-8601. */
124
124
  createdAt: string;
125
125
  }
126
+ /** What a provider token read did about the token's freshness. */
127
+ export type ProviderTokenRefresh = 'NOT_ATTEMPTED' | 'REFRESHED' | 'FAILED' | 'HELD_BACK';
126
128
  /**
127
- * A stored upstream provider token for the calling customer. `null` when there
128
- * is no customer token on the request, or none stored for that provider.
129
+ * A stored upstream provider token for the calling user. `myProviderToken`
130
+ * answers `null` when there is no user token on the request, and
131
+ * `linked: false` when the user has none stored for that provider.
129
132
  */
130
133
  export interface ProviderToken {
131
134
  providerKey: string;
132
- accessToken: string;
135
+ /** False when the user has no token for the provider; every token field is then null. */
136
+ linked: boolean;
137
+ accessToken: string | null;
133
138
  refreshToken: string | null;
134
139
  /** ISO-8601. */
135
140
  expiresAt: string | null;
136
141
  /** Space-separated provider scopes, as the provider issued them. */
137
142
  scopes: string | null;
143
+ /**
144
+ * What the read did: `REFRESHED` renewed it, `FAILED` tried and served the
145
+ * stored token, `HELD_BACK` had tried within the last minute, and
146
+ * `NOT_ATTEMPTED` found it fresh or had nothing to renew it with.
147
+ */
148
+ refresh: ProviderTokenRefresh | null;
149
+ /** Where a failed refresh failed, such as `"refresh grant"`. */
150
+ refreshFailure: string | null;
151
+ /** Only the user signing in with the provider again mends the connection. */
152
+ reauthenticate: boolean;
138
153
  }
139
154
  /** What a self-serve account deletion removed. */
140
155
  export interface DeleteAccountResult {
@@ -142,11 +157,122 @@ export interface DeleteAccountResult {
142
157
  recordsDeleted: number;
143
158
  filesDeleted: number;
144
159
  }
160
+ /** The calling user's own profile, as `updateMyProfile` answers it. */
161
+ export interface MyProfile {
162
+ id: string;
163
+ email: string;
164
+ firstName: string | null;
165
+ lastName: string | null;
166
+ avatarUrl: string | null;
167
+ /** BCP47, or null where they follow the project default. */
168
+ preferredLocale: string | null;
169
+ }
145
170
  /**
146
- * One organization the calling operator may stand in, as `myOrganizations`
171
+ * What `updateMyProfile` changes. A field left out stays as it is; an empty
172
+ * string clears it.
173
+ */
174
+ export type MyProfileChange = {
175
+ firstName?: string;
176
+ lastName?: string;
177
+ avatarUrl?: string;
178
+ /** A locale the project publishes. */
179
+ preferredLocale?: string;
180
+ };
181
+ /** Somewhere the calling user is signed in, or a personal access token they hold. */
182
+ export interface MySession {
183
+ /** The session's handle, which {@link endMySession} takes. It signs nobody in. */
184
+ id: string;
185
+ /** `browser` for a sign-in, `personal_access_token` for a token. */
186
+ kind: string;
187
+ /** A personal access token's name. */
188
+ name: string | null;
189
+ /** The first characters of a personal access token's value. */
190
+ tokenPrefix: string | null;
191
+ /** The app it was signed in through. */
192
+ appName: string | null;
193
+ /** ISO-8601. */
194
+ createdAt: string | null;
195
+ /** ISO-8601. */
196
+ lastSeenAt: string | null;
197
+ /** ISO-8601. */
198
+ expiresAt: string | null;
199
+ ipAddress: string | null;
200
+ userAgent: string | null;
201
+ /** Whether it is the session making the request. */
202
+ current: boolean;
203
+ }
204
+ /** A personal access token just made: its value is shown here once. */
205
+ export interface NewPersonalAccessToken {
206
+ token: MySession;
207
+ value: string;
208
+ }
209
+ /** A provider the calling user signs in with. */
210
+ export interface MySignInMethod {
211
+ provider: string;
212
+ /** The address the provider gave when it was connected. */
213
+ email: string | null;
214
+ /** ISO-8601. */
215
+ connectedAt: string | null;
216
+ }
217
+ /** A second factor, passkey or set of recovery codes the calling user holds. */
218
+ export interface MyFactor {
219
+ /** `totp`, `security_key`, `passkey` or `recovery_codes`. */
220
+ kind: string;
221
+ /** What {@link removeFactor} takes. */
222
+ id: string;
223
+ /**
224
+ * A security key's or passkey's name. A passkey made on the project's own
225
+ * login domain is named by that domain, the only one it signs in on.
226
+ */
227
+ name: string | null;
228
+ /** ISO-8601. */
229
+ addedAt: string | null;
230
+ /** For recovery codes: how many are left unused. */
231
+ remaining: number | null;
232
+ }
233
+ /**
234
+ * A step-up begun with the calling user's password: waiting for a second
235
+ * factor, or, for a user who holds none, already proven by the password.
236
+ */
237
+ export interface StepUp {
238
+ /** What {@link completeStepUp} takes, for a user who holds a second factor. */
239
+ handle: string | null;
240
+ /** For a user who holds no second factor: the proof their password is, for one change to their factors. */
241
+ elevatedHandle: string | null;
242
+ /** Whether a security key or passkey can prove it. */
243
+ webauthn: boolean;
244
+ /** Whether an authenticator app's code can prove it. */
245
+ totp: boolean;
246
+ /** The publicKey options for `navigator.credentials.get`, as JSON. */
247
+ webauthnOptionsJson: string | null;
248
+ }
249
+ /** A second factor being added, waiting for the browser or the authenticator app. */
250
+ export interface FactorEnrollment {
251
+ /** What {@link completeFactorEnrollment} takes. */
252
+ handle: string;
253
+ /** For a security key or passkey: the publicKey options for `navigator.credentials.create`, as JSON. */
254
+ webauthnOptionsJson: string | null;
255
+ /** For an authenticator app: the key to enter by hand. */
256
+ totpSecret: string | null;
257
+ /** For an authenticator app: a QR code of the key, as a data URI. */
258
+ totpQr: string | null;
259
+ }
260
+ /** An app the calling user has agreed may act for them. */
261
+ export interface AuthorizedApp {
262
+ /** The consent's id, which {@link revokeAuthorizedApp} takes. */
263
+ id: string;
264
+ clientId: string;
265
+ clientName: string;
266
+ /** What the app may carry for them, in the permission catalogue's names. */
267
+ grants: string[];
268
+ /** ISO-8601. */
269
+ grantedAt: string | null;
270
+ }
271
+ /**
272
+ * One organization the calling user may stand in, as `myOrganizations`
147
273
  * returns it.
148
274
  *
149
- * Identity, not configuration: the id to hand to {@link selectOrganization}, a
275
+ * Identity, not configuration: the id a request names to act there, a
150
276
  * name to render, the status, and where it sits. Only active organizations are
151
277
  * returned today; `status` is here so that a widening is visible to the caller
152
278
  * rather than silent.
@@ -157,7 +283,7 @@ export interface DeleteAccountResult {
157
283
  * this surface's to hand out.
158
284
  *
159
285
  * THE LIST IS A SUBTREE. A membership at an organization reaches everything
160
- * beneath it, so an operator who runs a group is offered the group and every
286
+ * beneath it, so someone who runs a group is offered the group and every
161
287
  * client under it. Draw it flat and a reseller's clients render as its
162
288
  * siblings, which is what the three position fields are for.
163
289
  */
@@ -168,7 +294,7 @@ export interface MyOrganization {
168
294
  /**
169
295
  * The immediate parent, or null for a root.
170
296
  *
171
- * A root OF THE PROJECT, not of the caller's view: an operator whose
297
+ * A root OF THE PROJECT, not of the caller's view: a member whose
172
298
  * membership sits three levels down sees their own organization with a parent
173
299
  * they cannot read. Null means there is no parent; it is never the empty
174
300
  * string, because that is a third value with no reading.
@@ -179,16 +305,16 @@ export interface MyOrganization {
179
305
  * project root.
180
306
  *
181
307
  * IDS, not names, and the whole path — including ancestors this caller cannot
182
- * read. An id is disclosed to everything below it; a name is row content an
183
- * operator further down may not be entitled to. A path trimmed to the
184
- * readable ancestors would have gaps or a false root, and two operators of
308
+ * read. An id is disclosed to everything below it; a name is row content a
309
+ * member further down may not be entitled to. A path trimmed to the
310
+ * readable ancestors would have gaps or a false root, and two members of
185
311
  * one organization would then see different paths to it.
186
312
  */
187
313
  ancestorIds: string[];
188
314
  /**
189
315
  * Levels above this organization in the PROJECT's tree: 0 is a project root.
190
316
  *
191
- * The project's depth rather than the caller's, so two operators looking at
317
+ * The project's depth rather than the caller's, so two members looking at
192
318
  * the same organization agree about where it is. Indent by the difference
193
319
  * from the shallowest entry in the list if you want the caller's own view.
194
320
  */
@@ -197,7 +323,7 @@ export interface MyOrganization {
197
323
  * The caller's own role in this organization, or null when their
198
324
  * membership carries none (or a disabled one). Never another member's role.
199
325
  *
200
- * ONE ROLE, NOT THE WHOLE AUTHORITY. The platform resolves the operator's
326
+ * ONE ROLE, NOT THE WHOLE AUTHORITY. The platform resolves the member's
201
327
  * authority per request as the union of the roles on every membership that
202
328
  * reaches this organization (one held in it and every one held above it),
203
329
  * together with their own roles in the project. This field is the role of
@@ -206,6 +332,12 @@ export interface MyOrganization {
206
332
  * sees part of what the next request is allowed and not the whole of it.
207
333
  */
208
334
  role: MyOrganizationRole | null;
335
+ /**
336
+ * Where the list goes on from: pass the last entry's cursor as `after` to
337
+ * read the next page. Null on an entry no list gave, such as the one
338
+ * `registerOrganization` returns.
339
+ */
340
+ cursor: string | null;
209
341
  }
210
342
  /** A role as `myOrganizations` reports it: enough to match a policy and to render. */
211
343
  export interface MyOrganizationRole {
@@ -219,15 +351,3 @@ export interface MyOrganizationRole {
219
351
  */
220
352
  grants: string[];
221
353
  }
222
- /**
223
- * Where the caller now stands, as `selectMyOrganization` returns it.
224
- *
225
- * Two fields, because two are all there is to say. It is NOT a session context:
226
- * an operator is a customer, and the platform's admin session shape — user,
227
- * available tenants, effective permissions — describes a population this level
228
- * exists to keep them out of.
229
- */
230
- export interface SelectedOrganization {
231
- orgId: string;
232
- orgName: string;
233
- }
@@ -41,37 +41,55 @@ export declare const AUTH_OPS: {
41
41
  readonly authConfig: "authConfig";
42
42
  readonly authProviders: "authProviders";
43
43
  readonly defaultAuthProvider: "defaultAuthProvider";
44
- readonly customerSignupContext: "customerSignupContext";
44
+ readonly signupContext: "signupContext";
45
45
  readonly currentUser: "currentUser";
46
46
  readonly myProviderToken: "myProviderToken";
47
47
  readonly whoami: "whoami";
48
- readonly customerLogin: "customerLogin";
49
- readonly customerRegister: "customerRegister";
50
- readonly customerRequestOTP: "customerRequestOTP";
51
- readonly customerLoginOTP: "customerLoginOTP";
52
- readonly customerRefreshToken: "customerRefreshToken";
53
- readonly customerLogout: "customerLogout";
54
- readonly customerJoinWaitlist: "customerJoinWaitlist";
55
- readonly customerRequestPasswordReset: "customerRequestPasswordReset";
56
- readonly customerResetPassword: "customerResetPassword";
57
- readonly customerUpdatePassword: "customerUpdatePassword";
58
- readonly customerVerifyEmail: "customerVerifyEmail";
48
+ readonly login: "login";
49
+ readonly register: "register";
50
+ readonly requestOTP: "requestOTP";
51
+ readonly loginWithOTP: "loginWithOTP";
52
+ readonly refreshToken: "refreshToken";
53
+ readonly logout: "logout";
54
+ readonly joinWaitlist: "joinWaitlist";
55
+ readonly requestPasswordReset: "requestPasswordReset";
56
+ readonly resetPassword: "resetPassword";
57
+ readonly updatePassword: "updatePassword";
58
+ readonly verifyEmail: "verifyEmail";
59
59
  readonly deleteMyAccount: "deleteMyAccount";
60
+ readonly updateMyProfile: "updateMyProfile";
61
+ readonly myAuthorizedApps: "myAuthorizedApps";
62
+ readonly revokeAuthorizedApp: "revokeAuthorizedApp";
63
+ readonly mySessions: "mySessions";
64
+ readonly endMySession: "endMySession";
65
+ readonly signOutEverywhere: "signOutEverywhere";
66
+ readonly createPersonalAccessToken: "createPersonalAccessToken";
67
+ readonly mySignInMethods: "mySignInMethods";
68
+ readonly connectSignInMethod: "connectSignInMethod";
69
+ readonly disconnectSignInMethod: "disconnectSignInMethod";
70
+ readonly myFactors: "myFactors";
71
+ readonly beginStepUp: "beginStepUp";
72
+ readonly completeStepUp: "completeStepUp";
73
+ readonly beginFactorEnrollment: "beginFactorEnrollment";
74
+ readonly completeFactorEnrollment: "completeFactorEnrollment";
75
+ readonly removeFactor: "removeFactor";
76
+ readonly makeRecoveryCodes: "makeRecoveryCodes";
60
77
  readonly myOrganizations: "myOrganizations";
61
- readonly selectMyOrganization: "selectMyOrganization";
62
- readonly registerOperatorOrganization: "registerOperatorOrganization";
63
- readonly customerLoginWithProvider: "customerLoginWithProvider";
64
- readonly customerProviderCallback: "customerProviderCallback";
65
- readonly customerProviderVerifyOTP: "customerProviderVerifyOTP";
78
+ readonly registerOrganization: "registerOrganization";
79
+ readonly loginWithProvider: "loginWithProvider";
80
+ readonly providerCallback: "providerCallback";
81
+ readonly providerVerifyOTP: "providerVerifyOTP";
82
+ readonly confirmProviderLink: "confirmProviderLink";
83
+ readonly resendProviderLinkCode: "resendProviderLinkCode";
66
84
  };
67
85
  /** One of the auth namespace's root field names. */
68
86
  export type AuthOpName = (typeof AUTH_OPS)[keyof typeof AUTH_OPS];
69
87
  /** Per-call overrides for an auth op. */
70
88
  export interface AuthOpOptions {
71
89
  /**
72
- * Customer bearer token. api-public still needs the `x-api-key` to resolve
73
- * the project; the bearer adds the customer identity the post-credential ops
74
- * (`currentUser`, `customerUpdatePassword`, `deleteMyAccount`, …) are
90
+ * User bearer token. api-public still needs the `x-api-key` to resolve
91
+ * the project; the bearer adds the user identity the post-credential ops
92
+ * (`currentUser`, `updatePassword`, `deleteMyAccount`, …) are
75
93
  * authorised by. Ignored by the pre-credential ops, which mint it.
76
94
  */
77
95
  bearerToken?: string;
@@ -85,7 +103,7 @@ export interface AuthOpOptions {
85
103
  /**
86
104
  * The organization the call acts in, named by the address of the page it is
87
105
  * for, sent as `X-Org-Url`: same contract as `FoirClientConfig.orgUrl`. A
88
- * storefront on a path per organization signs its customers in on those
106
+ * storefront on a path per organization signs its users in on those
89
107
  * pages, and names the organization the way every other request from them
90
108
  * does.
91
109
  */
@@ -19,7 +19,7 @@
19
19
  * There is no refresh token in this flow. Re-exchanging the cookie IS the
20
20
  * refresh, which is why nothing here needs rotation or reuse-detection: the
21
21
  * durable credential is an opaque server-side session handle, revocable at any
22
- * time from the admin panel or `signOut()`.
22
+ * time from the console or `signOut()`.
23
23
  *
24
24
  * REQUIRES a verified custom login domain that shares a registrable domain with
25
25
  * your app (app.acme.com + login.acme.com). That is what makes the cookie
@@ -47,7 +47,7 @@ export interface FoirSessionConfig {
47
47
  }
48
48
  /** The identity behind the current session. */
49
49
  export interface FoirSessionUser {
50
- customerId: string;
50
+ userId: string;
51
51
  email: string;
52
52
  }
53
53
  export interface FoirSessionClient {
@@ -57,7 +57,7 @@ export interface FoirSessionClient {
57
57
  * exchange. Call this before each API request — do not cache the result.
58
58
  */
59
59
  getToken(): Promise<string | null>;
60
- /** The signed-in customer, or null. Exchanges if the session isn't loaded yet. */
60
+ /** The signed-in user, or null. Exchanges if the session isn't loaded yet. */
61
61
  getUser(): Promise<FoirSessionUser | null>;
62
62
  /** Revoke the session server-side and clear the cookie. Idempotent. */
63
63
  signOut(): Promise<void>;
@@ -64,14 +64,14 @@ function createFoirSessionClient(config) {
64
64
  } catch {
65
65
  return cached;
66
66
  }
67
- if (!json.access_token || !json.customer_id) return cached;
67
+ if (!json.access_token || !json.user_id) return cached;
68
68
  const expiresIn = typeof json.expires_in === "number" ? json.expires_in : 0;
69
69
  const next = {
70
70
  token: json.access_token,
71
71
  expiresAt: Date.now() + expiresIn * 1e3,
72
- user: { customerId: json.customer_id, email: json.email ?? "" }
72
+ user: { userId: json.user_id, email: json.email ?? "" }
73
73
  };
74
- const changed = cached?.user.customerId !== next.user.customerId;
74
+ const changed = cached?.user.userId !== next.user.userId;
75
75
  cached = next;
76
76
  scheduleRefresh(next.expiresAt);
77
77
  if (changed) emit(next.user);