@faable/auth-sdk 2.6.23 → 2.7.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.
@@ -1,5 +1,5 @@
1
1
  import { getDomain, isPlainObject, requireId } from "./helpers.js";
2
- import { FaableApiError } from "./error_handler.js";
2
+ import { FaableApiError } from "@faable/sdk-base";
3
3
  import { GeneratedFaableAuthApi } from "./api/generated-client.js";
4
4
  import { authClientCredentials } from "@faable/sdk-base";
5
5
  import { SDK_CLIENT } from "./version.js";
@@ -22,6 +22,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
22
22
  * `POST /account` — operationId: `account/create`
23
23
  *
24
24
  * Create an Account
25
+ *
26
+ * Creates a new Auth Account. The slug is derived from the name and used to build the default `*.auth.faable.link` domain.
25
27
  */
26
28
  accountCreate(data: OpBody<"account/create">): Promise<{
27
29
  id: string;
@@ -84,6 +86,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
84
86
  * `GET /account/current` — operationId: `account/current`
85
87
  *
86
88
  * Get current Account
89
+ *
90
+ * Returns the Account resolved from request context (header, hostname, or team id). Use `expand` to populate nested references.
87
91
  */
88
92
  accountCurrent(params?: OpQuery<"account/current">): Promise<{
89
93
  id: string;
@@ -146,12 +150,16 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
146
150
  * `DELETE /account/{account_id}` — operationId: `account/delete`
147
151
  *
148
152
  * Delete an Account
153
+ *
154
+ * Permanently removes an Account and its associated data. This action cannot be undone.
149
155
  */
150
156
  accountDelete(account_id: string): Promise<never>;
151
157
  /**
152
158
  * `GET /account/{account_id}` — operationId: `account/get`
153
159
  *
154
160
  * Get an Account
161
+ *
162
+ * Fetch a single Account by its id. Use `expand` to populate id-only fields (e.g. `default_connection`) inline.
155
163
  */
156
164
  accountGet(account_id: string, params?: OpQuery<"account/get">): Promise<{
157
165
  id: string;
@@ -214,6 +222,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
214
222
  * `GET /account/keys` — operationId: `account/getKeys`
215
223
  *
216
224
  * Get Account signing keys info
225
+ *
226
+ * Returns metadata for the Account signing keys: the current production kid, the kid queued for next rotation, and all kids currently published in the JWK Set. Does not expose private key material.
217
227
  */
218
228
  accountGetKeys(): Promise<{
219
229
  production_kid: string;
@@ -224,6 +234,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
224
234
  * `GET /account` — operationId: `account/list`
225
235
  *
226
236
  * List Accounts
237
+ *
238
+ * List Accounts owned by the requesting project/team. Supports cursor pagination and `expand`.
227
239
  */
228
240
  accountList(params?: Omit<OpQuery<"account/list">, "cursor" | "next">): {
229
241
  all: () => Promise<{
@@ -405,6 +417,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
405
417
  * `GET /recovery-channels/capabilities` — operationId: `account/recoveryChannelsCapabilities`
406
418
  *
407
419
  * Recovery channel capabilities for this tenant
420
+ *
421
+ * Which recovery channels the platform can send, whether the plan allows the paid ones, this month's SMS usage against the included amount, and the tenant configuration as resolved. Drives the "Recovery channels" editor in the dashboard.
408
422
  */
409
423
  accountRecoveryChannelsCapabilities(): Promise<{
410
424
  provider: {
@@ -438,6 +452,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
438
452
  * `POST /account/keys/rotate` — operationId: `account/rotateKeys`
439
453
  *
440
454
  * Rotate Account signing keys
455
+ *
456
+ * Promotes the queued key to production and generates a fresh queued key. The previously-active key is retained inside the JWK Set so tokens already issued remain verifiable via `/.well-known/jwks.json`.
441
457
  */
442
458
  accountRotateKeys(data: OpBody<"account/rotateKeys">): Promise<{
443
459
  rotated_at: string;
@@ -450,6 +466,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
450
466
  * `GET /sdk-health/{account_id}` — operationId: `account/sdk-health`
451
467
  *
452
468
  * Library health for this account
469
+ *
470
+ * Which Faable client libraries this account is being called with, at which versions, and how far behind the latest published release each one is. Versions are observed from the `x-faable-client` header, so an integration that talks raw OIDC shows up only in the traffic breakdown.
453
471
  */
454
472
  accountSdkHealth(account_id: string): Promise<{
455
473
  libraries: {
@@ -484,6 +502,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
484
502
  * `POST /account/{account_id}` — operationId: `account/update`
485
503
  *
486
504
  * Update an Account
505
+ *
506
+ * Update the Account configuration such as branding (logo and icon URLs).
487
507
  */
488
508
  accountUpdate(account_id: string, data: OpBody<"account/update">): Promise<{
489
509
  id: string;
@@ -1285,6 +1305,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
1285
1305
  * `POST /client/{client_id}/rotate-secret` — operationId: `client/rotateSecret`
1286
1306
  *
1287
1307
  * Rotate a Client's secret
1308
+ *
1309
+ * Generates a fresh `client_secret` for the given Client and persists it. The previous secret is invalidated immediately — there is no grace period. Returns the full Client; the dashboard must surface the new secret to the admin once. Existing client_credentials / authorization_code integrations using the old secret will start failing at the token endpoint immediately after this call.
1288
1310
  */
1289
1311
  clientRotateSecret(client_id: string): Promise<{
1290
1312
  id: string;
@@ -1821,6 +1843,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
1821
1843
  * `POST /credentials/{credentials_id}/set-password` — operationId: `credentials/setPassword`
1822
1844
  *
1823
1845
  * Set a credential's password
1846
+ *
1847
+ * Sets or rotates the password for a database credential. The previous password is invalidated immediately. Records a `credential.password_changed` audit entry (initiated_by=admin) for traceability. The confirmation email is only sent when an EXISTING password is rotated: setting the first password on a credential that had none is a creation, not a change. The password is never returned.
1824
1848
  */
1825
1849
  credentialsSetPassword(credentials_id: string, data: OpBody<"credentials/setPassword">): Promise<{
1826
1850
  id: string;
@@ -2026,6 +2050,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
2026
2050
  * `POST /customdomain/{customdomain_id}/retry` — operationId: `customdomain/retry`
2027
2051
  *
2028
2052
  * Trigger a domain verification check now
2053
+ *
2054
+ * Forces an immediate DNS re-check of a Custom Domain in any state. Rate-limited to one check per minute. A verified (ACTIVE) domain stays ACTIVE while it is re-checked; any other state moves to VERIFYING.
2029
2055
  */
2030
2056
  customdomainRetry(customdomain_id: string): Promise<void>;
2031
2057
  /**
@@ -2098,6 +2124,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
2098
2124
  * `GET /identity/{identity_id}/provider-token` — operationId: `identity/getProviderToken`
2099
2125
  *
2100
2126
  * Get a guaranteed-valid provider access_token
2127
+ *
2128
+ * Returns the identity's upstream provider `access_token`, refreshing it transparently via the stored `refresh_token` when it is (about to be) expired. Pass `?fresh=true` to force a refresh. Fails with 400 when the token is expired and no `refresh_token` is available (the user must re-authorize).
2101
2129
  */
2102
2130
  identityGetProviderToken(identity_id: string, params?: OpQuery<"identity/getProviderToken">): Promise<{
2103
2131
  access_token: string;
@@ -2169,6 +2197,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
2169
2197
  * `GET /internal/usage/sms` — operationId: `internal/smsUsage`
2170
2198
  *
2171
2199
  * SMS sent per tenant in a month (platform)
2200
+ *
2201
+ * Per-account count of recovery/verification SMS sent in the given month, read from the monthly quota counters. Consumed by the billing usage job. Platform token with `read:usage`.
2172
2202
  */
2173
2203
  internalSmsUsage(params?: OpQuery<"internal/smsUsage">): Promise<{
2174
2204
  month: string;
@@ -2710,6 +2740,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
2710
2740
  * `POST /loginflow/materialize` — operationId: `loginflow/materialize`
2711
2741
  *
2712
2742
  * Start a custom flow from what runs today
2743
+ *
2744
+ * Creates a login flow whose draft is the graph the account (or, with `client_id`, that client) currently runs — compiled from its settings — and binds it. Nothing changes for logins until the flow is published: a bound flow with no published graph keeps running the compiled one. Never a blank canvas: customising always starts from the tenant's own behaviour.
2713
2745
  */
2714
2746
  loginflowMaterialize(data: OpBody<"loginflow/materialize">): Promise<{
2715
2747
  id: string;
@@ -2783,6 +2815,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
2783
2815
  * `POST /loginflow/{loginflow_id}/preview-token` — operationId: `loginflow/previewToken`
2784
2816
  *
2785
2817
  * Try the draft on a real login, in your browser only
2818
+ *
2819
+ * Returns a short-lived token. Open `/authorize?…&flow_preview=<token>` (or the hosted login with the same parameter) and that login runs the DRAFT of this flow instead of what is published, for that browser only. Nothing is published.
2786
2820
  */
2787
2821
  loginflowPreviewToken(loginflow_id: string): Promise<{
2788
2822
  token: string;
@@ -2792,6 +2826,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
2792
2826
  * `POST /loginflow/{loginflow_id}/publish` — operationId: `loginflow/publish`
2793
2827
  *
2794
2828
  * Make the draft the graph logins run
2829
+ *
2830
+ * Validates the draft and freezes it as `published` under its current revision; the previous published graph moves to `history`. Logins already in flight keep the revision they started on. Refused with the list of issues when the draft does not validate.
2795
2831
  */
2796
2832
  loginflowPublish(loginflow_id: string, data: OpBody<"loginflow/publish">): Promise<{
2797
2833
  id: string;
@@ -2865,6 +2901,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
2865
2901
  * `GET /loginflow/resolved` — operationId: `loginflow/resolved`
2866
2902
  *
2867
2903
  * The graph this account (or client) runs right now
2904
+ *
2905
+ * What a login actually walks: the published graph of the bound flow, or the graph compiled from the settings when nothing is bound or published. With `client_id`, resolved for that client (its own flow, else the account's, else compiled from its overrides). The bound flow, if any, comes along with its draft so an editor can show both.
2868
2906
  */
2869
2907
  loginflowResolved(params?: OpQuery<"loginflow/resolved">): Promise<{
2870
2908
  source: "compiled" | "published";
@@ -2917,6 +2955,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
2917
2955
  * `POST /loginflow/{loginflow_id}/rollback` — operationId: `loginflow/rollback`
2918
2956
  *
2919
2957
  * Run a previously published revision again
2958
+ *
2959
+ * Makes the named revision from `history` the published graph; the one being replaced moves to `history`. The draft is not touched.
2920
2960
  */
2921
2961
  loginflowRollback(loginflow_id: string, data: OpBody<"loginflow/rollback">): Promise<{
2922
2962
  id: string;
@@ -3564,6 +3604,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
3564
3604
  * `POST /team/{team_id}/member` — operationId: `team/addMembers`
3565
3605
  *
3566
3606
  * Add Users to a Team
3607
+ *
3608
+ * Adds one or more Users as members of the given Team. Returns the resulting TeamMember record.
3567
3609
  */
3568
3610
  teamAddMembers(team_id: string, data: OpBody<"team/addMembers">): Promise<{
3569
3611
  id: string;
@@ -3581,6 +3623,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
3581
3623
  * `GET /team/{team_id}/member/check/{user_id}` — operationId: `team/checkMember`
3582
3624
  *
3583
3625
  * Check User is member of a Team
3626
+ *
3627
+ * Returns the TeamMember record if the User belongs to the given Team, or 404 otherwise.
3584
3628
  */
3585
3629
  teamCheckMember(team_id: string, user_id: string, params?: OpQuery<"team/checkMember">): Promise<{
3586
3630
  id: string;
@@ -3652,6 +3696,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
3652
3696
  * `POST /team/{team_id}/invite` — operationId: `team/invite`
3653
3697
  *
3654
3698
  * Invite a user to a Team by email
3699
+ *
3700
+ * Invites a user by email. `mode='auto'` (default) adds the user directly when the email already corresponds to a user in this tenant and falls back to a ticketed invite + email otherwise. `mode='invite'` always issues a ticket + email even when the user exists. Re-inviting the same email to the same team invalidates the previous pending invite.
3655
3701
  */
3656
3702
  teamInvite(team_id: string, data: OpBody<"team/invite">): Promise<{
3657
3703
  status: "invited" | "added";
@@ -3722,6 +3768,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
3722
3768
  * `GET /team/{team_id}/invite` — operationId: `team/listInvites`
3723
3769
  *
3724
3770
  * List pending invites for a Team
3771
+ *
3772
+ * Returns all pending (not consumed, not expired) team invites for the given team. Accepts a FaableQL `query` parameter on the `email` field.
3725
3773
  */
3726
3774
  teamListInvites(team_id: string, params?: OpQuery<"team/listInvites">): Promise<{
3727
3775
  data: {
@@ -3746,6 +3794,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
3746
3794
  * `GET /team/{team_id}/member` — operationId: `team/listMembers`
3747
3795
  *
3748
3796
  * List Team Members
3797
+ *
3798
+ * List all Users that belong to the given Team in the current Account. Supports `?expand=user,team,roles` to inline referenced rows.
3749
3799
  */
3750
3800
  teamListMembers(team_id: string, params?: Omit<OpQuery<"team/listMembers">, "cursor" | "next">): {
3751
3801
  all: () => Promise<{
@@ -3792,6 +3842,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
3792
3842
  * `DELETE /team/{team_id}/invite/{ticket_id}` — operationId: `team/revokeInvite`
3793
3843
  *
3794
3844
  * Revoke a pending team invite
3845
+ *
3846
+ * Marks a pending team invite as consumed so it can no longer be accepted. Returns 400 if the invite is already consumed and 404 if it does not exist or belongs to a different team.
3795
3847
  */
3796
3848
  teamRevokeInvite(team_id: string, ticket_id: string): Promise<{
3797
3849
  status: "revoked";
@@ -4294,6 +4346,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
4294
4346
  * `GET /user/{user_id}/tickets` — operationId: `user/listTickets`
4295
4347
  *
4296
4348
  * List the tickets issued for a user
4349
+ *
4350
+ * Returns the password-reset / verification / invitation tickets issued for this user, newest first, each with its status and — while it is still usable — the link that was emailed. Intended for handing a recovery link over by another channel when the email does not reach the person. Requires `update:credentials`: the link grants the same account access that setting a password does, and each reveal is recorded in the audit log.
4297
4351
  */
4298
4352
  userListTickets(user_id: string): Promise<{
4299
4353
  results: {
@@ -4312,6 +4366,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
4312
4366
  * `POST /user/{user_id}/password-setup` — operationId: `user/passwordSetup`
4313
4367
  *
4314
4368
  * Send a password setup / reset email to the user
4369
+ *
4370
+ * Ensures the user has a database credential (provisioning a password-less one when missing, e.g. for users created via the management API) and creates a `changepassword` ticket, sending the standard password reset email. The link lands on the tenant's auth domain. Idempotent on the credential; each call emits a fresh ticket.
4315
4371
  */
4316
4372
  userPasswordSetup(user_id: string, data: OpBody<"user/passwordSetup">): Promise<{
4317
4373
  status: "sent";
@@ -4323,6 +4379,8 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
4323
4379
  * `POST /user/{user_id}/tickets/{ticket_id}/revoke` — operationId: `user/revokeTicket`
4324
4380
  *
4325
4381
  * Revoke a ticket issued for a user
4382
+ *
4383
+ * Marks the ticket as consumed so its link stops working immediately. The counterpart of listing links: once a link has been copied out of the dashboard it can end up in the wrong chat window, and the TTL alone is too slow an answer.
4326
4384
  */
4327
4385
  userRevokeTicket(user_id: string, ticket_id: string): Promise<{
4328
4386
  status: "revoked" | "already_used";
@@ -13,6 +13,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
13
13
  * `POST /account` — operationId: `account/create`
14
14
  *
15
15
  * Create an Account
16
+ *
17
+ * Creates a new Auth Account. The slug is derived from the name and used to build the default `*.auth.faable.link` domain.
16
18
  */
17
19
  accountCreate(data) {
18
20
  return this.fetcher.post(`/account`, data);
@@ -21,6 +23,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
21
23
  * `GET /account/current` — operationId: `account/current`
22
24
  *
23
25
  * Get current Account
26
+ *
27
+ * Returns the Account resolved from request context (header, hostname, or team id). Use `expand` to populate nested references.
24
28
  */
25
29
  accountCurrent(params) {
26
30
  return this.fetcher.request({ method: "GET", url: `/account/current`, params });
@@ -29,6 +33,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
29
33
  * `DELETE /account/{account_id}` — operationId: `account/delete`
30
34
  *
31
35
  * Delete an Account
36
+ *
37
+ * Permanently removes an Account and its associated data. This action cannot be undone.
32
38
  */
33
39
  accountDelete(account_id) {
34
40
  requireId("account_id", account_id);
@@ -38,6 +44,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
38
44
  * `GET /account/{account_id}` — operationId: `account/get`
39
45
  *
40
46
  * Get an Account
47
+ *
48
+ * Fetch a single Account by its id. Use `expand` to populate id-only fields (e.g. `default_connection`) inline.
41
49
  */
42
50
  accountGet(account_id, params) {
43
51
  requireId("account_id", account_id);
@@ -47,6 +55,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
47
55
  * `GET /account/keys` — operationId: `account/getKeys`
48
56
  *
49
57
  * Get Account signing keys info
58
+ *
59
+ * Returns metadata for the Account signing keys: the current production kid, the kid queued for next rotation, and all kids currently published in the JWK Set. Does not expose private key material.
50
60
  */
51
61
  accountGetKeys() {
52
62
  return this.fetcher.get(`/account/keys`);
@@ -55,6 +65,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
55
65
  * `GET /account` — operationId: `account/list`
56
66
  *
57
67
  * List Accounts
68
+ *
69
+ * List Accounts owned by the requesting project/team. Supports cursor pagination and `expand`.
58
70
  */
59
71
  accountList(params) {
60
72
  return this.paginator({ url: `/account`, params });
@@ -63,6 +75,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
63
75
  * `GET /recovery-channels/capabilities` — operationId: `account/recoveryChannelsCapabilities`
64
76
  *
65
77
  * Recovery channel capabilities for this tenant
78
+ *
79
+ * Which recovery channels the platform can send, whether the plan allows the paid ones, this month's SMS usage against the included amount, and the tenant configuration as resolved. Drives the "Recovery channels" editor in the dashboard.
66
80
  */
67
81
  accountRecoveryChannelsCapabilities() {
68
82
  return this.fetcher.get(`/recovery-channels/capabilities`);
@@ -71,6 +85,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
71
85
  * `POST /account/keys/rotate` — operationId: `account/rotateKeys`
72
86
  *
73
87
  * Rotate Account signing keys
88
+ *
89
+ * Promotes the queued key to production and generates a fresh queued key. The previously-active key is retained inside the JWK Set so tokens already issued remain verifiable via `/.well-known/jwks.json`.
74
90
  */
75
91
  accountRotateKeys(data) {
76
92
  return this.fetcher.post(`/account/keys/rotate`, data);
@@ -79,6 +95,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
79
95
  * `GET /sdk-health/{account_id}` — operationId: `account/sdk-health`
80
96
  *
81
97
  * Library health for this account
98
+ *
99
+ * Which Faable client libraries this account is being called with, at which versions, and how far behind the latest published release each one is. Versions are observed from the `x-faable-client` header, so an integration that talks raw OIDC shows up only in the traffic breakdown.
82
100
  */
83
101
  accountSdkHealth(account_id) {
84
102
  requireId("account_id", account_id);
@@ -88,6 +106,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
88
106
  * `POST /account/{account_id}` — operationId: `account/update`
89
107
  *
90
108
  * Update an Account
109
+ *
110
+ * Update the Account configuration such as branding (logo and icon URLs).
91
111
  */
92
112
  accountUpdate(account_id, data) {
93
113
  requireId("account_id", account_id);
@@ -217,6 +237,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
217
237
  * `POST /client/{client_id}/rotate-secret` — operationId: `client/rotateSecret`
218
238
  *
219
239
  * Rotate a Client's secret
240
+ *
241
+ * Generates a fresh `client_secret` for the given Client and persists it. The previous secret is invalidated immediately — there is no grace period. Returns the full Client; the dashboard must surface the new secret to the admin once. Existing client_credentials / authorization_code integrations using the old secret will start failing at the token endpoint immediately after this call.
220
242
  */
221
243
  clientRotateSecret(client_id) {
222
244
  requireId("client_id", client_id);
@@ -312,6 +334,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
312
334
  * `POST /credentials/{credentials_id}/set-password` — operationId: `credentials/setPassword`
313
335
  *
314
336
  * Set a credential's password
337
+ *
338
+ * Sets or rotates the password for a database credential. The previous password is invalidated immediately. Records a `credential.password_changed` audit entry (initiated_by=admin) for traceability. The confirmation email is only sent when an EXISTING password is rotated: setting the first password on a credential that had none is a creation, not a change. The password is never returned.
315
339
  */
316
340
  credentialsSetPassword(credentials_id, data) {
317
341
  requireId("credentials_id", credentials_id);
@@ -364,6 +388,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
364
388
  * `POST /customdomain/{customdomain_id}/retry` — operationId: `customdomain/retry`
365
389
  *
366
390
  * Trigger a domain verification check now
391
+ *
392
+ * Forces an immediate DNS re-check of a Custom Domain in any state. Rate-limited to one check per minute. A verified (ACTIVE) domain stays ACTIVE while it is re-checked; any other state moves to VERIFYING.
367
393
  */
368
394
  customdomainRetry(customdomain_id) {
369
395
  requireId("customdomain_id", customdomain_id);
@@ -399,6 +425,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
399
425
  * `GET /identity/{identity_id}/provider-token` — operationId: `identity/getProviderToken`
400
426
  *
401
427
  * Get a guaranteed-valid provider access_token
428
+ *
429
+ * Returns the identity's upstream provider `access_token`, refreshing it transparently via the stored `refresh_token` when it is (about to be) expired. Pass `?fresh=true` to force a refresh. Fails with 400 when the token is expired and no `refresh_token` is available (the user must re-authorize).
402
430
  */
403
431
  identityGetProviderToken(identity_id, params) {
404
432
  requireId("identity_id", identity_id);
@@ -416,6 +444,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
416
444
  * `GET /internal/usage/sms` — operationId: `internal/smsUsage`
417
445
  *
418
446
  * SMS sent per tenant in a month (platform)
447
+ *
448
+ * Per-account count of recovery/verification SMS sent in the given month, read from the monthly quota counters. Consumed by the billing usage job. Platform token with `read:usage`.
419
449
  */
420
450
  internalSmsUsage(params) {
421
451
  return this.fetcher.request({ method: "GET", url: `/internal/usage/sms`, params });
@@ -475,6 +505,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
475
505
  * `POST /loginflow/materialize` — operationId: `loginflow/materialize`
476
506
  *
477
507
  * Start a custom flow from what runs today
508
+ *
509
+ * Creates a login flow whose draft is the graph the account (or, with `client_id`, that client) currently runs — compiled from its settings — and binds it. Nothing changes for logins until the flow is published: a bound flow with no published graph keeps running the compiled one. Never a blank canvas: customising always starts from the tenant's own behaviour.
478
510
  */
479
511
  loginflowMaterialize(data) {
480
512
  return this.fetcher.post(`/loginflow/materialize`, data);
@@ -483,6 +515,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
483
515
  * `POST /loginflow/{loginflow_id}/preview-token` — operationId: `loginflow/previewToken`
484
516
  *
485
517
  * Try the draft on a real login, in your browser only
518
+ *
519
+ * Returns a short-lived token. Open `/authorize?…&flow_preview=<token>` (or the hosted login with the same parameter) and that login runs the DRAFT of this flow instead of what is published, for that browser only. Nothing is published.
486
520
  */
487
521
  loginflowPreviewToken(loginflow_id) {
488
522
  requireId("loginflow_id", loginflow_id);
@@ -492,6 +526,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
492
526
  * `POST /loginflow/{loginflow_id}/publish` — operationId: `loginflow/publish`
493
527
  *
494
528
  * Make the draft the graph logins run
529
+ *
530
+ * Validates the draft and freezes it as `published` under its current revision; the previous published graph moves to `history`. Logins already in flight keep the revision they started on. Refused with the list of issues when the draft does not validate.
495
531
  */
496
532
  loginflowPublish(loginflow_id, data) {
497
533
  requireId("loginflow_id", loginflow_id);
@@ -501,6 +537,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
501
537
  * `GET /loginflow/resolved` — operationId: `loginflow/resolved`
502
538
  *
503
539
  * The graph this account (or client) runs right now
540
+ *
541
+ * What a login actually walks: the published graph of the bound flow, or the graph compiled from the settings when nothing is bound or published. With `client_id`, resolved for that client (its own flow, else the account's, else compiled from its overrides). The bound flow, if any, comes along with its draft so an editor can show both.
504
542
  */
505
543
  loginflowResolved(params) {
506
544
  return this.fetcher.request({ method: "GET", url: `/loginflow/resolved`, params });
@@ -509,6 +547,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
509
547
  * `POST /loginflow/{loginflow_id}/rollback` — operationId: `loginflow/rollback`
510
548
  *
511
549
  * Run a previously published revision again
550
+ *
551
+ * Makes the named revision from `history` the published graph; the one being replaced moves to `history`. The draft is not touched.
512
552
  */
513
553
  loginflowRollback(loginflow_id, data) {
514
554
  requireId("loginflow_id", loginflow_id);
@@ -674,6 +714,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
674
714
  * `POST /team/{team_id}/member` — operationId: `team/addMembers`
675
715
  *
676
716
  * Add Users to a Team
717
+ *
718
+ * Adds one or more Users as members of the given Team. Returns the resulting TeamMember record.
677
719
  */
678
720
  teamAddMembers(team_id, data) {
679
721
  requireId("team_id", team_id);
@@ -683,6 +725,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
683
725
  * `GET /team/{team_id}/member/check/{user_id}` — operationId: `team/checkMember`
684
726
  *
685
727
  * Check User is member of a Team
728
+ *
729
+ * Returns the TeamMember record if the User belongs to the given Team, or 404 otherwise.
686
730
  */
687
731
  teamCheckMember(team_id, user_id, params) {
688
732
  requireId("team_id", team_id);
@@ -719,6 +763,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
719
763
  * `POST /team/{team_id}/invite` — operationId: `team/invite`
720
764
  *
721
765
  * Invite a user to a Team by email
766
+ *
767
+ * Invites a user by email. `mode='auto'` (default) adds the user directly when the email already corresponds to a user in this tenant and falls back to a ticketed invite + email otherwise. `mode='invite'` always issues a ticket + email even when the user exists. Re-inviting the same email to the same team invalidates the previous pending invite.
722
768
  */
723
769
  teamInvite(team_id, data) {
724
770
  requireId("team_id", team_id);
@@ -736,6 +782,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
736
782
  * `GET /team/{team_id}/invite` — operationId: `team/listInvites`
737
783
  *
738
784
  * List pending invites for a Team
785
+ *
786
+ * Returns all pending (not consumed, not expired) team invites for the given team. Accepts a FaableQL `query` parameter on the `email` field.
739
787
  */
740
788
  teamListInvites(team_id, params) {
741
789
  requireId("team_id", team_id);
@@ -745,6 +793,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
745
793
  * `GET /team/{team_id}/member` — operationId: `team/listMembers`
746
794
  *
747
795
  * List Team Members
796
+ *
797
+ * List all Users that belong to the given Team in the current Account. Supports `?expand=user,team,roles` to inline referenced rows.
748
798
  */
749
799
  teamListMembers(team_id, params) {
750
800
  requireId("team_id", team_id);
@@ -754,6 +804,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
754
804
  * `DELETE /team/{team_id}/invite/{ticket_id}` — operationId: `team/revokeInvite`
755
805
  *
756
806
  * Revoke a pending team invite
807
+ *
808
+ * Marks a pending team invite as consumed so it can no longer be accepted. Returns 400 if the invite is already consumed and 404 if it does not exist or belongs to a different team.
757
809
  */
758
810
  teamRevokeInvite(team_id, ticket_id) {
759
811
  requireId("team_id", team_id);
@@ -841,6 +893,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
841
893
  * `GET /user/{user_id}/tickets` — operationId: `user/listTickets`
842
894
  *
843
895
  * List the tickets issued for a user
896
+ *
897
+ * Returns the password-reset / verification / invitation tickets issued for this user, newest first, each with its status and — while it is still usable — the link that was emailed. Intended for handing a recovery link over by another channel when the email does not reach the person. Requires `update:credentials`: the link grants the same account access that setting a password does, and each reveal is recorded in the audit log.
844
898
  */
845
899
  userListTickets(user_id) {
846
900
  requireId("user_id", user_id);
@@ -850,6 +904,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
850
904
  * `POST /user/{user_id}/password-setup` — operationId: `user/passwordSetup`
851
905
  *
852
906
  * Send a password setup / reset email to the user
907
+ *
908
+ * Ensures the user has a database credential (provisioning a password-less one when missing, e.g. for users created via the management API) and creates a `changepassword` ticket, sending the standard password reset email. The link lands on the tenant's auth domain. Idempotent on the credential; each call emits a fresh ticket.
853
909
  */
854
910
  userPasswordSetup(user_id, data) {
855
911
  requireId("user_id", user_id);
@@ -859,6 +915,8 @@ export class GeneratedFaableAuthApi extends FaableApi {
859
915
  * `POST /user/{user_id}/tickets/{ticket_id}/revoke` — operationId: `user/revokeTicket`
860
916
  *
861
917
  * Revoke a ticket issued for a user
918
+ *
919
+ * Marks the ticket as consumed so its link stops working immediately. The counterpart of listing links: once a link has been copied out of the dashboard it can end up in the wrong chat window, and the TTL alone is too slow an answer.
862
920
  */
863
921
  userRevokeTicket(user_id, ticket_id) {
864
922
  requireId("user_id", user_id);
package/dist/helpers.js CHANGED
@@ -1,4 +1,4 @@
1
- import { FaableApiError } from "./error_handler.js";
1
+ import { FaableApiError } from "@faable/sdk-base";
2
2
  // Normaliza el `domain` para que dé igual cómo lo pase el usuario: con o sin
3
3
  // protocolo, con trailing slash, o incluso con protocolo duplicado (el valor
4
4
  // que el dashboard copia ya trae `https://`). Siempre devuelve
package/dist/index.d.ts CHANGED
@@ -3,5 +3,5 @@ export { SDK_CLIENT, commit, version } from "./version.js";
3
3
  export * from "./api/generated-client.js";
4
4
  export * from "./api/api-types.js";
5
5
  export * from "./api/types.js";
6
- export { authClientCredentials, authApikey, authBearer, authCookie, } from "@faable/sdk-base";
6
+ export { authClientCredentials, authApikey, authBearer, authCookie, FaableApiError, } from "@faable/sdk-base";
7
7
  export type { ApiParams, ClientCredentialsConfig, ApikeyConfig, BearerConfig, RetryConfig, Fetcher, FetcherConfig, FetcherRequestParams, AuthStrategy, AuthStrategyBuilder, AuthStrategyContext, } from "@faable/sdk-base";
package/dist/index.js CHANGED
@@ -6,4 +6,8 @@ export * from "./api/types.js";
6
6
  // Re-export the auth strategies (and their config/types) from
7
7
  // @faable/sdk-base so consumers depend on @faable/auth-sdk ONLY — sdk-base
8
8
  // stays a transitive dependency and no app needs to import it directly.
9
- export { authClientCredentials, authApikey, authBearer, authCookie, } from "@faable/sdk-base";
9
+ export { authClientCredentials, authApikey, authBearer, authCookie,
10
+ // The error every method throws on a non-2xx. Branch on `err.error_code`
11
+ // (or `err.isErrorCode('sms_unavailable')`), never on `err.message`: the
12
+ // generated client lists the codes of each method as `@throws`.
13
+ FaableApiError, } from "@faable/sdk-base";
package/dist/version.js CHANGED
@@ -9,13 +9,13 @@
9
9
  // login pages could not import the SDK at all. Same pattern as auth-js.
10
10
  //
11
11
  // The sentinels MUST stay byte-identical to the `from` values in `.releaserc`.
12
- export const version = "2.6.23";
12
+ export const version = "2.7.0";
13
13
  // Short git SHA of the released commit. The version dates a build; this names
14
14
  // the exact tree, so a canonical log line or an audit entry leads straight to
15
15
  // `git show <sha>`. Deliberately NOT hex: an unreleased build (dev, a local
16
16
  // link) cannot be mistaken for a real commit — auth only records values that
17
17
  // look like a SHA, and this one never will.
18
- export const commit = "65b2a2d";
18
+ export const commit = "7ef7d78";
19
19
  // What this SDK writes in `x-faable-client`. Exported for a consumer that
20
20
  // builds a strategy on its own (outside `FaableAuthApi`) and still wants the
21
21
  // token request attributed — a bare `authClientCredentials` stamps only what
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faable/auth-sdk",
3
- "version": "2.6.23",
3
+ "version": "2.7.0",
4
4
  "author": "Marc Pomar <marc@faable.com>",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "type": "module",
12
12
  "dependencies": {
13
- "@faable/sdk-base": "^1.6.0"
13
+ "@faable/sdk-base": "^1.7.0"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@ava/typescript": "^5.0.0",
@@ -80,6 +80,40 @@ for (const [path, methods] of Object.entries(spec.paths || {})) {
80
80
  }
81
81
  operations.sort((a, b) => a.op.operationId.localeCompare(b.op.operationId));
82
82
 
83
+ // Multi-line descriptions become one JSDoc line each.
84
+ const escapeBlock = (text) =>
85
+ String(text)
86
+ .split("\n")
87
+ .map((l) => ` * ${escape(l)}`);
88
+
89
+ // The server documents each 4xx/5xx as an ErrorResponse whose `error_code`
90
+ // is restricted to an enum, and describes every code in the response
91
+ // description as "`code` — text" lines. Read both back so the docstring can
92
+ // list what a caller may branch on.
93
+ const errorCodesOf = (op) => {
94
+ const out = [];
95
+ const seen = new Set();
96
+ for (const [status, res] of Object.entries(op.responses || {})) {
97
+ if (!/^[45]\d\d$/.test(status)) continue;
98
+ const schema = res?.content?.["application/json"]?.schema;
99
+ const parts = schema?.allOf || (schema ? [schema] : []);
100
+ const codes = parts.flatMap((p) => p?.properties?.error_code?.enum || []);
101
+ const descriptions = new Map(
102
+ String(res?.description || "")
103
+ .split("\n")
104
+ .map((l) => l.match(/^`([a-z_]+)` — (.*)$/))
105
+ .filter(Boolean)
106
+ .map((m) => [m[1], m[2]]),
107
+ );
108
+ for (const code of codes) {
109
+ if (seen.has(code)) continue;
110
+ seen.add(code);
111
+ out.push({ code, status, description: descriptions.get(code) });
112
+ }
113
+ }
114
+ return out;
115
+ };
116
+
83
117
  const emitMethod = ({ path, httpMethod, op }) => {
84
118
  const id = op.operationId;
85
119
  const name = toMethodName(id);
@@ -128,11 +162,23 @@ const emitMethod = ({ path, httpMethod, op }) => {
128
162
  }
129
163
 
130
164
  const guards = pathParams.map((p) => ` requireId("${p}", ${p});`);
131
- const doc = op.summary || op.description;
165
+ // Summary AND description: the CRUD summaries are generic ("Get User") and
166
+ // used to hide the prose that actually explains the endpoint.
167
+ const docLines = [op.summary, op.description]
168
+ .filter((x, i, all) => x && all.indexOf(x) === i)
169
+ .flatMap((text, i) => [...(i ? [" *"] : []), ...escapeBlock(text)]);
170
+ // One `@throws` per documented error code, read from the 4xx/5xx responses
171
+ // the server injects (see auth's server/openapi_errors.ts). The code is
172
+ // `err.error_code` on the FaableApiError the fetcher throws.
173
+ const throwsLines = errorCodesOf(op).map(
174
+ ({ code, status, description }) =>
175
+ ` * @throws {FaableApiError} \`${code}\` (${status})${description ? ` — ${escape(description)}` : ""}`,
176
+ );
132
177
  const jsdoc = [
133
178
  " /**",
134
179
  ` * \`${httpMethod.toUpperCase()} ${path}\` — operationId: \`${id}\``,
135
- ...(doc ? [` *`, ` * ${escape(doc)}`] : []),
180
+ ...(docLines.length ? [" *", ...docLines] : []),
181
+ ...(throwsLines.length ? [" *", ...throwsLines] : []),
136
182
  " */",
137
183
  ].join("\n");
138
184
 
@@ -1,27 +0,0 @@
1
- import type { AxiosError } from "axios";
2
- /**
3
- * El error que lanza el SDK cuando la API responde con un fallo.
4
- *
5
- * ⚠️ **`error_code` es la parte con la que se ramifica, no el mensaje.** El
6
- * `message` de la API está escrito para que lo lea una persona y puede cambiar
7
- * —de hecho cambia: el de teléfono inválido se reescribió el 17-09 para que se
8
- * entendiera en el formulario de un tenant que lo pintaba literal—. Hasta esa
9
- * fecha este error aplanaba la respuesta en un string y se llevaba por delante
10
- * el `error_code`, así que quien integraba no tenía más remedio que comparar
11
- * textos en inglés. Ahora viajan también `status`, `error_code` y el cuerpo
12
- * entero.
13
- */
14
- export declare class FaableApiError extends Error {
15
- /** Código HTTP de la respuesta, cuando la hubo. */
16
- readonly status?: number;
17
- /** Código estable del error (`invalid_phone`, `sms_unavailable:plan`, …). */
18
- readonly error_code?: string;
19
- /** Cuerpo de la respuesta tal cual, por si hace falta algo más. */
20
- readonly body?: unknown;
21
- constructor(msg: string, details?: {
22
- status?: number;
23
- error_code?: string;
24
- body?: unknown;
25
- });
26
- }
27
- export declare const handleErrorInterceptor: (e: AxiosError) => Promise<never>;
@@ -1,36 +0,0 @@
1
- /**
2
- * El error que lanza el SDK cuando la API responde con un fallo.
3
- *
4
- * ⚠️ **`error_code` es la parte con la que se ramifica, no el mensaje.** El
5
- * `message` de la API está escrito para que lo lea una persona y puede cambiar
6
- * —de hecho cambia: el de teléfono inválido se reescribió el 17-09 para que se
7
- * entendiera en el formulario de un tenant que lo pintaba literal—. Hasta esa
8
- * fecha este error aplanaba la respuesta en un string y se llevaba por delante
9
- * el `error_code`, así que quien integraba no tenía más remedio que comparar
10
- * textos en inglés. Ahora viajan también `status`, `error_code` y el cuerpo
11
- * entero.
12
- */
13
- export class FaableApiError extends Error {
14
- /** Código HTTP de la respuesta, cuando la hubo. */
15
- status;
16
- /** Código estable del error (`invalid_phone`, `sms_unavailable:plan`, …). */
17
- error_code;
18
- /** Cuerpo de la respuesta tal cual, por si hace falta algo más. */
19
- body;
20
- constructor(msg, details = {}) {
21
- super(msg);
22
- this.name = "FaableApiError";
23
- this.status = details.status;
24
- this.error_code = details.error_code;
25
- this.body = details.body;
26
- Object.setPrototypeOf(this, FaableApiError.prototype);
27
- }
28
- }
29
- export const handleErrorInterceptor = async (e) => {
30
- const data = e.response?.data;
31
- throw new FaableApiError(`FaableApiError: ${data?.message} (status=${e.response?.status}, url=${e.response?.config.url})`, {
32
- status: e.response?.status,
33
- error_code: data?.error_code,
34
- body: data
35
- });
36
- };