@faable/auth-sdk 2.8.27 → 2.9.1

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.
package/README.md CHANGED
@@ -242,6 +242,26 @@ const members = await api.listTeamMembers({ query: "alice" }).first();
242
242
  const isMember = await api.isUserMemberOfTeam("user_xxx", "team_xxx");
243
243
  ```
244
244
 
245
+ ### Roles and permissions
246
+
247
+ A role grants permissions of your APIs. Assign it to a user at the account level and their tokens for an API with `rbac` enabled carry those permissions (team roles grant none).
248
+
249
+ ```ts
250
+ const role = await api.roleCreate({ name: "support" });
251
+ await api.roleAddPermissions(role.id, {
252
+ permissions: [{ api: "api_xxx", value: "tickets:write" }],
253
+ });
254
+
255
+ await api.userAssignRoles("user_xxx", { roles: [role.id] });
256
+ const roles = await api.userRoles("user_xxx");
257
+ const permissions = await api.userPermissions("user_xxx"); // with the role that grants each
258
+
259
+ await api.userRemoveRoles("user_xxx", { roles: [role.id] });
260
+ await api.roleRemovePermissions(role.id, {
261
+ permissions: [{ api: "api_xxx", value: "tickets:write" }],
262
+ });
263
+ ```
264
+
245
265
  ### Connections
246
266
 
247
267
  ```ts
@@ -325,6 +345,37 @@ export default async function handler(req, res) {
325
345
 
326
346
  `WebhookEvent`, `WebhookEventType`, `WebhookEventOf<"user.created">` and `WebhookPayload<"team.member.added">` are generated from the auth OpenAPI, like every other type.
327
347
 
348
+ ## Protecting your API
349
+
350
+ Verify the access tokens your API receives and check their permissions:
351
+
352
+ ```ts
353
+ import {
354
+ AccessTokenError,
355
+ bearerToken,
356
+ requirePermissions,
357
+ verifyAccessToken,
358
+ } from "@faable/auth-sdk";
359
+
360
+ export default async function handler(req, res) {
361
+ try {
362
+ const claims = await verifyAccessToken(bearerToken(req.headers.authorization), {
363
+ domain: process.env.FAABLEAUTH_DOMAIN!, // https://<tenant>.auth.faable.link
364
+ audience: "https://api.example.com", // your Api's identifier
365
+ });
366
+ requirePermissions(claims, "tickets:write");
367
+ // … claims.sub is the user (or the client, for machine tokens)
368
+ } catch (e) {
369
+ if (e instanceof AccessTokenError) return res.status(e.status).json({ error: e.reason });
370
+ throw e;
371
+ }
372
+ }
373
+ ```
374
+
375
+ - `verifyAccessToken` checks the signature against the tenant JWKS (fetched once and cached), `iss`, `aud` and `exp`. It throws `AccessTokenError` with `status` 401.
376
+ - `requirePermissions` throws `AccessTokenError` `insufficient_scope` with `status` 403 and `missing`; `hasPermissions` returns a boolean. Both require **all** the permissions passed.
377
+ - The `permissions` claim needs the Api's `token_dialect` to be `access_token_authz`. With `rbac` on, a user token carries the permissions the client **requested** that the user's roles grant, so request them as scopes.
378
+
328
379
  ## Types
329
380
 
330
381
  All response shapes are generated from the OpenAPI spec and re-exported from the package root:
@@ -1155,6 +1155,7 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
1155
1155
  token_dialect: "access_token" | "access_token_authz";
1156
1156
  token_lifetime: number;
1157
1157
  enforce_policies: boolean;
1158
+ rbac: boolean;
1158
1159
  allow_offline_access: boolean;
1159
1160
  consent_options?: {
1160
1161
  claim: string;
@@ -1209,6 +1210,7 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
1209
1210
  token_dialect: "access_token" | "access_token_authz";
1210
1211
  token_lifetime: number;
1211
1212
  enforce_policies: boolean;
1213
+ rbac: boolean;
1212
1214
  allow_offline_access: boolean;
1213
1215
  consent_options?: {
1214
1216
  claim: string;
@@ -1264,6 +1266,7 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
1264
1266
  token_dialect: "access_token" | "access_token_authz";
1265
1267
  token_lifetime: number;
1266
1268
  enforce_policies: boolean;
1269
+ rbac: boolean;
1267
1270
  allow_offline_access: boolean;
1268
1271
  consent_options?: {
1269
1272
  claim: string;
@@ -1320,6 +1323,7 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
1320
1323
  token_dialect: "access_token" | "access_token_authz";
1321
1324
  token_lifetime: number;
1322
1325
  enforce_policies: boolean;
1326
+ rbac: boolean;
1323
1327
  allow_offline_access: boolean;
1324
1328
  consent_options?: {
1325
1329
  claim: string;
@@ -1358,6 +1362,7 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
1358
1362
  token_dialect: "access_token" | "access_token_authz";
1359
1363
  token_lifetime: number;
1360
1364
  enforce_policies: boolean;
1365
+ rbac: boolean;
1361
1366
  allow_offline_access: boolean;
1362
1367
  consent_options?: {
1363
1368
  claim: string;
@@ -1399,6 +1404,7 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
1399
1404
  token_dialect: "access_token" | "access_token_authz";
1400
1405
  token_lifetime: number;
1401
1406
  enforce_policies: boolean;
1407
+ rbac: boolean;
1402
1408
  allow_offline_access: boolean;
1403
1409
  consent_options?: {
1404
1410
  claim: string;
@@ -1455,6 +1461,7 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
1455
1461
  token_dialect: "access_token" | "access_token_authz";
1456
1462
  token_lifetime: number;
1457
1463
  enforce_policies: boolean;
1464
+ rbac: boolean;
1458
1465
  allow_offline_access: boolean;
1459
1466
  consent_options?: {
1460
1467
  claim: string;
@@ -5356,6 +5363,31 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
5356
5363
  ok: boolean;
5357
5364
  } | null;
5358
5365
  }>;
5366
+ /**
5367
+ * `POST /role/{role_id}/permissions` — operationId: `role/add_permissions`
5368
+ *
5369
+ * Add permissions to a Role
5370
+ *
5371
+ * Grants Api permissions to a Role. Each must be in the catalog of an Api of this tenant. Permissions the Role already has are kept. Tokens issued from now on (refreshes included) carry them; tokens already issued are unchanged. Leaves an entry in the tenant's log.
5372
+ *
5373
+ * @throws {FaableApiError} `invalid_permission` (400) — A permission is not in the catalog of its Api, or the Api is not in this account. `details.permissions` lists the ones refused.
5374
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
5375
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
5376
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
5377
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
5378
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
5379
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
5380
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
5381
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
5382
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
5383
+ */
5384
+ roleAddPermissions(role_id: string, data: OpBody<"role/add_permissions">): Promise<{
5385
+ api: string;
5386
+ api_identifier: string;
5387
+ api_name: string;
5388
+ value: string;
5389
+ description?: string | undefined;
5390
+ }[]>;
5359
5391
  /**
5360
5392
  * `POST /role/{role_id}/users` — operationId: `role/assign_users`
5361
5393
  *
@@ -5392,6 +5424,10 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
5392
5424
  id: string;
5393
5425
  name: string;
5394
5426
  description: string;
5427
+ permissions: {
5428
+ api: string;
5429
+ value: string;
5430
+ }[];
5395
5431
  account: string;
5396
5432
  metadata: {
5397
5433
  [key: string]: unknown;
@@ -5419,6 +5455,10 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
5419
5455
  id: string;
5420
5456
  name: string;
5421
5457
  description: string;
5458
+ permissions: {
5459
+ api: string;
5460
+ value: string;
5461
+ }[];
5422
5462
  account: string;
5423
5463
  metadata: {
5424
5464
  [key: string]: unknown;
@@ -5447,6 +5487,10 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
5447
5487
  id: string;
5448
5488
  name: string;
5449
5489
  description: string;
5490
+ permissions: {
5491
+ api: string;
5492
+ value: string;
5493
+ }[];
5450
5494
  account: string;
5451
5495
  metadata: {
5452
5496
  [key: string]: unknown;
@@ -5476,6 +5520,10 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
5476
5520
  id: string;
5477
5521
  name: string;
5478
5522
  description: string;
5523
+ permissions: {
5524
+ api: string;
5525
+ value: string;
5526
+ }[];
5479
5527
  account: string;
5480
5528
  metadata: {
5481
5529
  [key: string]: unknown;
@@ -5487,6 +5535,10 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
5487
5535
  id: string;
5488
5536
  name: string;
5489
5537
  description: string;
5538
+ permissions: {
5539
+ api: string;
5540
+ value: string;
5541
+ }[];
5490
5542
  account: string;
5491
5543
  metadata: {
5492
5544
  [key: string]: unknown;
@@ -5501,6 +5553,10 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
5501
5553
  id: string;
5502
5554
  name: string;
5503
5555
  description: string;
5556
+ permissions: {
5557
+ api: string;
5558
+ value: string;
5559
+ }[];
5504
5560
  account: string;
5505
5561
  metadata: {
5506
5562
  [key: string]: unknown;
@@ -5509,6 +5565,76 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
5509
5565
  updatedAt?: string | undefined;
5510
5566
  }>>;
5511
5567
  };
5568
+ /**
5569
+ * `GET /role/{role_id}/permissions` — operationId: `role/permissions`
5570
+ *
5571
+ * List the permissions of a Role
5572
+ *
5573
+ * Lists the Api permissions the Role grants, each with its Api. A user gets them in tokens for an Api with `rbac` enabled when the Role is assigned to them at the account level.
5574
+ *
5575
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
5576
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
5577
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
5578
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
5579
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
5580
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
5581
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
5582
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
5583
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
5584
+ */
5585
+ rolePermissions(role_id: string): Promise<{
5586
+ api: string;
5587
+ api_identifier: string;
5588
+ api_name: string;
5589
+ value: string;
5590
+ description?: string | undefined;
5591
+ }[]>;
5592
+ /**
5593
+ * `DELETE /role/{role_id}/permissions` — operationId: `role/remove_permissions`
5594
+ *
5595
+ * Remove permissions from a Role
5596
+ *
5597
+ * Revokes Api permissions from a Role. Permissions the Role does not have are ignored. Tokens already issued keep them until they expire; refreshes drop them. Leaves an entry in the tenant's log.
5598
+ *
5599
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
5600
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
5601
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
5602
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
5603
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
5604
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
5605
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
5606
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
5607
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
5608
+ */
5609
+ roleRemovePermissions(role_id: string, data: OpBody<"role/remove_permissions">): Promise<{
5610
+ api: string;
5611
+ api_identifier: string;
5612
+ api_name: string;
5613
+ value: string;
5614
+ description?: string | undefined;
5615
+ }[]>;
5616
+ /**
5617
+ * `DELETE /role/{role_id}/users` — operationId: `role/remove_users`
5618
+ *
5619
+ * Remove Users from Role
5620
+ *
5621
+ * Revokes an account-level role from users. Their next tokens (refreshes included) no longer carry its permissions; tokens already issued keep them until they expire. Leaves an entry in the tenant's log.
5622
+ *
5623
+ * @throws {FaableApiError} `invalid_role` (400) — The role belongs to another account.
5624
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
5625
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
5626
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
5627
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
5628
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
5629
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
5630
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
5631
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
5632
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
5633
+ */
5634
+ roleRemoveUsers(role_id: string, data: OpBody<"role/remove_users">): Promise<{
5635
+ removed_from_role: string[];
5636
+ not_in_role: string[];
5637
+ }>;
5512
5638
  /**
5513
5639
  * `POST /role/{role_id}` — operationId: `role/update`
5514
5640
  *
@@ -5530,6 +5656,10 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
5530
5656
  id: string;
5531
5657
  name: string;
5532
5658
  description: string;
5659
+ permissions: {
5660
+ api: string;
5661
+ value: string;
5662
+ }[];
5533
5663
  account: string;
5534
5664
  metadata: {
5535
5665
  [key: string]: unknown;
@@ -6521,6 +6651,39 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
6521
6651
  updatedAt?: string | undefined;
6522
6652
  }>>;
6523
6653
  };
6654
+ /**
6655
+ * `POST /user/{user_id}/roles` — operationId: `user/assign_roles`
6656
+ *
6657
+ * Assign roles to a User
6658
+ *
6659
+ * Assigns account-level roles to the User and returns all of their roles. Roles the User already has are kept. Their next tokens (refreshes included) carry the new permissions. Leaves an entry in the tenant's log. Account-level roles are what grant Api permissions to a user (in tokens for an Api with `rbac` enabled). Team roles are separate: they live on the team membership and grant no permissions.
6660
+ *
6661
+ * @throws {FaableApiError} `invalid_role` (400) — The role belongs to another account.
6662
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
6663
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
6664
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
6665
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
6666
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
6667
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
6668
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
6669
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
6670
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
6671
+ */
6672
+ userAssignRoles(user_id: string, data: OpBody<"user/assign_roles">): Promise<{
6673
+ id: string;
6674
+ name: string;
6675
+ description: string;
6676
+ permissions: {
6677
+ api: string;
6678
+ value: string;
6679
+ }[];
6680
+ account: string;
6681
+ metadata: {
6682
+ [key: string]: unknown;
6683
+ };
6684
+ createdAt: string;
6685
+ updatedAt?: string | undefined;
6686
+ }[]>;
6524
6687
  /**
6525
6688
  * `POST /user` — operationId: `user/create`
6526
6689
  *
@@ -7351,6 +7514,66 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
7351
7514
  ticket_id: string;
7352
7515
  channel: "email" | "sms" | "whatsapp" | "factor";
7353
7516
  }>;
7517
+ /**
7518
+ * `GET /user/{user_id}/permissions` — operationId: `user/permissions`
7519
+ *
7520
+ * List a User's permissions
7521
+ *
7522
+ * Lists the Api permissions the User holds through their account-level roles, with the roles that grant each one. For an Api with `rbac` enabled, these are exactly what the User's tokens for that Api carry in `permissions`.
7523
+ *
7524
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
7525
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
7526
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
7527
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
7528
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
7529
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
7530
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
7531
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
7532
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
7533
+ */
7534
+ userPermissions(user_id: string): Promise<{
7535
+ api: string;
7536
+ api_identifier: string;
7537
+ api_name: string;
7538
+ value: string;
7539
+ description?: string | undefined;
7540
+ roles: {
7541
+ id: string;
7542
+ name: string;
7543
+ }[];
7544
+ }[]>;
7545
+ /**
7546
+ * `DELETE /user/{user_id}/roles` — operationId: `user/remove_roles`
7547
+ *
7548
+ * Remove roles from a User
7549
+ *
7550
+ * Removes account-level roles from the User and returns the ones left. Roles the User does not have are ignored. Tokens already issued keep the permissions until they expire; refreshes drop them. Leaves an entry in the tenant's log.
7551
+ *
7552
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
7553
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
7554
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
7555
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
7556
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
7557
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
7558
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
7559
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
7560
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
7561
+ */
7562
+ userRemoveRoles(user_id: string, data: OpBody<"user/remove_roles">): Promise<{
7563
+ id: string;
7564
+ name: string;
7565
+ description: string;
7566
+ permissions: {
7567
+ api: string;
7568
+ value: string;
7569
+ }[];
7570
+ account: string;
7571
+ metadata: {
7572
+ [key: string]: unknown;
7573
+ };
7574
+ createdAt: string;
7575
+ updatedAt?: string | undefined;
7576
+ }[]>;
7354
7577
  /**
7355
7578
  * `POST /user/{user_id}/passkey-prompt/reset` — operationId: `user/resetPasskeyPrompt`
7356
7579
  *
@@ -7391,6 +7614,38 @@ export declare abstract class GeneratedFaableAuthApi extends FaableApi {
7391
7614
  status: "revoked" | "already_used";
7392
7615
  id: string;
7393
7616
  }>;
7617
+ /**
7618
+ * `GET /user/{user_id}/roles` — operationId: `user/roles`
7619
+ *
7620
+ * List a User's roles
7621
+ *
7622
+ * Lists the roles assigned to the User at the account level, by name. Account-level roles are what grant Api permissions to a user (in tokens for an Api with `rbac` enabled). Team roles are separate: they live on the team membership and grant no permissions.
7623
+ *
7624
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
7625
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
7626
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
7627
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
7628
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
7629
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
7630
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
7631
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
7632
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
7633
+ */
7634
+ userRoles(user_id: string): Promise<{
7635
+ id: string;
7636
+ name: string;
7637
+ description: string;
7638
+ permissions: {
7639
+ api: string;
7640
+ value: string;
7641
+ }[];
7642
+ account: string;
7643
+ metadata: {
7644
+ [key: string]: unknown;
7645
+ };
7646
+ createdAt: string;
7647
+ updatedAt?: string | undefined;
7648
+ }[]>;
7394
7649
  /**
7395
7650
  * `POST /user/{user_id}` — operationId: `user/update`
7396
7651
  *
@@ -1810,6 +1810,28 @@ export class GeneratedFaableAuthApi extends FaableApi {
1810
1810
  requireId("domain", domain);
1811
1811
  return this.fetcher.post(`/organization/${organization_id}/domain/${domain}/verify`, {});
1812
1812
  }
1813
+ /**
1814
+ * `POST /role/{role_id}/permissions` — operationId: `role/add_permissions`
1815
+ *
1816
+ * Add permissions to a Role
1817
+ *
1818
+ * Grants Api permissions to a Role. Each must be in the catalog of an Api of this tenant. Permissions the Role already has are kept. Tokens issued from now on (refreshes included) carry them; tokens already issued are unchanged. Leaves an entry in the tenant's log.
1819
+ *
1820
+ * @throws {FaableApiError} `invalid_permission` (400) — A permission is not in the catalog of its Api, or the Api is not in this account. `details.permissions` lists the ones refused.
1821
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
1822
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
1823
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
1824
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
1825
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
1826
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
1827
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
1828
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
1829
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
1830
+ */
1831
+ roleAddPermissions(role_id, data) {
1832
+ requireId("role_id", role_id);
1833
+ return this.fetcher.post(`/role/${role_id}/permissions`, data);
1834
+ }
1813
1835
  /**
1814
1836
  * `POST /role/{role_id}/users` — operationId: `role/assign_users`
1815
1837
  *
@@ -1909,6 +1931,70 @@ export class GeneratedFaableAuthApi extends FaableApi {
1909
1931
  roleList(params) {
1910
1932
  return this.paginator({ url: `/role`, params });
1911
1933
  }
1934
+ /**
1935
+ * `GET /role/{role_id}/permissions` — operationId: `role/permissions`
1936
+ *
1937
+ * List the permissions of a Role
1938
+ *
1939
+ * Lists the Api permissions the Role grants, each with its Api. A user gets them in tokens for an Api with `rbac` enabled when the Role is assigned to them at the account level.
1940
+ *
1941
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
1942
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
1943
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
1944
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
1945
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
1946
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
1947
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
1948
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
1949
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
1950
+ */
1951
+ rolePermissions(role_id) {
1952
+ requireId("role_id", role_id);
1953
+ return this.fetcher.get(`/role/${role_id}/permissions`);
1954
+ }
1955
+ /**
1956
+ * `DELETE /role/{role_id}/permissions` — operationId: `role/remove_permissions`
1957
+ *
1958
+ * Remove permissions from a Role
1959
+ *
1960
+ * Revokes Api permissions from a Role. Permissions the Role does not have are ignored. Tokens already issued keep them until they expire; refreshes drop them. Leaves an entry in the tenant's log.
1961
+ *
1962
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
1963
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
1964
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
1965
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
1966
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
1967
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
1968
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
1969
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
1970
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
1971
+ */
1972
+ roleRemovePermissions(role_id, data) {
1973
+ requireId("role_id", role_id);
1974
+ return this.fetcher.request({ method: "DELETE", url: `/role/${role_id}/permissions`, data });
1975
+ }
1976
+ /**
1977
+ * `DELETE /role/{role_id}/users` — operationId: `role/remove_users`
1978
+ *
1979
+ * Remove Users from Role
1980
+ *
1981
+ * Revokes an account-level role from users. Their next tokens (refreshes included) no longer carry its permissions; tokens already issued keep them until they expire. Leaves an entry in the tenant's log.
1982
+ *
1983
+ * @throws {FaableApiError} `invalid_role` (400) — The role belongs to another account.
1984
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
1985
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
1986
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
1987
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
1988
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
1989
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
1990
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
1991
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
1992
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
1993
+ */
1994
+ roleRemoveUsers(role_id, data) {
1995
+ requireId("role_id", role_id);
1996
+ return this.fetcher.request({ method: "DELETE", url: `/role/${role_id}/users`, data });
1997
+ }
1912
1998
  /**
1913
1999
  * `POST /role/{role_id}` — operationId: `role/update`
1914
2000
  *
@@ -2481,6 +2567,28 @@ export class GeneratedFaableAuthApi extends FaableApi {
2481
2567
  teammemberList(params) {
2482
2568
  return this.paginator({ url: `/teammember`, params });
2483
2569
  }
2570
+ /**
2571
+ * `POST /user/{user_id}/roles` — operationId: `user/assign_roles`
2572
+ *
2573
+ * Assign roles to a User
2574
+ *
2575
+ * Assigns account-level roles to the User and returns all of their roles. Roles the User already has are kept. Their next tokens (refreshes included) carry the new permissions. Leaves an entry in the tenant's log. Account-level roles are what grant Api permissions to a user (in tokens for an Api with `rbac` enabled). Team roles are separate: they live on the team membership and grant no permissions.
2576
+ *
2577
+ * @throws {FaableApiError} `invalid_role` (400) — The role belongs to another account.
2578
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
2579
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
2580
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
2581
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
2582
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
2583
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
2584
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
2585
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
2586
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
2587
+ */
2588
+ userAssignRoles(user_id, data) {
2589
+ requireId("user_id", user_id);
2590
+ return this.fetcher.post(`/user/${user_id}/roles`, data);
2591
+ }
2484
2592
  /**
2485
2593
  * `POST /user` — operationId: `user/create`
2486
2594
  *
@@ -2707,6 +2815,48 @@ export class GeneratedFaableAuthApi extends FaableApi {
2707
2815
  requireId("user_id", user_id);
2708
2816
  return this.fetcher.post(`/user/${user_id}/password-setup`, data);
2709
2817
  }
2818
+ /**
2819
+ * `GET /user/{user_id}/permissions` — operationId: `user/permissions`
2820
+ *
2821
+ * List a User's permissions
2822
+ *
2823
+ * Lists the Api permissions the User holds through their account-level roles, with the roles that grant each one. For an Api with `rbac` enabled, these are exactly what the User's tokens for that Api carry in `permissions`.
2824
+ *
2825
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
2826
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
2827
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
2828
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
2829
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
2830
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
2831
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
2832
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
2833
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
2834
+ */
2835
+ userPermissions(user_id) {
2836
+ requireId("user_id", user_id);
2837
+ return this.fetcher.get(`/user/${user_id}/permissions`);
2838
+ }
2839
+ /**
2840
+ * `DELETE /user/{user_id}/roles` — operationId: `user/remove_roles`
2841
+ *
2842
+ * Remove roles from a User
2843
+ *
2844
+ * Removes account-level roles from the User and returns the ones left. Roles the User does not have are ignored. Tokens already issued keep the permissions until they expire; refreshes drop them. Leaves an entry in the tenant's log.
2845
+ *
2846
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
2847
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
2848
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
2849
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
2850
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
2851
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
2852
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
2853
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
2854
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
2855
+ */
2856
+ userRemoveRoles(user_id, data) {
2857
+ requireId("user_id", user_id);
2858
+ return this.fetcher.request({ method: "DELETE", url: `/user/${user_id}/roles`, data });
2859
+ }
2710
2860
  /**
2711
2861
  * `POST /user/{user_id}/passkey-prompt/reset` — operationId: `user/resetPasskeyPrompt`
2712
2862
  *
@@ -2749,6 +2899,27 @@ export class GeneratedFaableAuthApi extends FaableApi {
2749
2899
  requireId("ticket_id", ticket_id);
2750
2900
  return this.fetcher.post(`/user/${user_id}/tickets/${ticket_id}/revoke`, {});
2751
2901
  }
2902
+ /**
2903
+ * `GET /user/{user_id}/roles` — operationId: `user/roles`
2904
+ *
2905
+ * List a User's roles
2906
+ *
2907
+ * Lists the roles assigned to the User at the account level, by name. Account-level roles are what grant Api permissions to a user (in tokens for an Api with `rbac` enabled). Team roles are separate: they live on the team membership and grant no permissions.
2908
+ *
2909
+ * @throws {FaableApiError} `validation_error` (400) — The body, query or path failed schema validation. `details.issues` lists each failing field.
2910
+ * @throws {FaableApiError} `unauthorized` (401) — The request carries no valid credentials.
2911
+ * @throws {FaableApiError} `forbidden` (403) — The credentials are valid but do not allow this operation.
2912
+ * @throws {FaableApiError} `insufficient_scope` (403) — The token lacks a scope this operation requires. `message` names it.
2913
+ * @throws {FaableApiError} `user_suspended` (403) — The user is suspended and cannot sign in or be modified.
2914
+ * @throws {FaableApiError} `not_found` (404) — The resource does not exist in this account.
2915
+ * @throws {FaableApiError} `account_not_found` (404) — No Auth Account matches the request (domain, header or token).
2916
+ * @throws {FaableApiError} `too_many_requests` (429) — Rate limit exceeded. Honour the `Retry-After` header.
2917
+ * @throws {FaableApiError} `internal_error` (500) — Unexpected server error. Retry later; the request id is logged.
2918
+ */
2919
+ userRoles(user_id) {
2920
+ requireId("user_id", user_id);
2921
+ return this.fetcher.get(`/user/${user_id}/roles`);
2922
+ }
2752
2923
  /**
2753
2924
  * `POST /user/{user_id}` — operationId: `user/update`
2754
2925
  *