@drmhse/sso-sdk 0.2.4 → 0.2.7

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/dist/index.js CHANGED
@@ -24,6 +24,7 @@ __export(index_exports, {
24
24
  InvitationsModule: () => InvitationsModule,
25
25
  OrganizationsModule: () => OrganizationsModule,
26
26
  PlatformModule: () => PlatformModule,
27
+ ServiceApiModule: () => ServiceApiModule,
27
28
  ServicesModule: () => ServicesModule,
28
29
  SsoApiError: () => SsoApiError,
29
30
  SsoClient: () => SsoClient,
@@ -471,7 +472,8 @@ var AuthModule = class {
471
472
  * ```typescript
472
473
  * await sso.auth.logout();
473
474
  * sso.setAuthToken(null);
474
- * localStorage.removeItem('jwt');
475
+ * localStorage.removeItem('sso_access_token');
476
+ * localStorage.removeItem('sso_refresh_token');
475
477
  * ```
476
478
  */
477
479
  async logout() {
@@ -494,8 +496,8 @@ var AuthModule = class {
494
496
  * try {
495
497
  * const tokens = await sso.auth.refreshToken(storedRefreshToken);
496
498
  * sso.setAuthToken(tokens.access_token);
497
- * localStorage.setItem('access_token', tokens.access_token);
498
- * localStorage.setItem('refresh_token', tokens.refresh_token);
499
+ * localStorage.setItem('sso_access_token', tokens.access_token);
500
+ * localStorage.setItem('sso_refresh_token', tokens.refresh_token);
499
501
  * } catch (error) {
500
502
  * // Refresh failed - redirect to login
501
503
  * window.location.href = '/login';
@@ -525,6 +527,129 @@ var AuthModule = class {
525
527
  const response = await this.http.get(`/api/provider-token/${provider}`);
526
528
  return response.data;
527
529
  }
530
+ // ============================================================================
531
+ // PASSWORD AUTHENTICATION
532
+ // ============================================================================
533
+ /**
534
+ * Register a new user with email and password.
535
+ * After registration, the user will receive a verification email.
536
+ *
537
+ * @param payload Registration details (email and password)
538
+ * @returns Registration confirmation message
539
+ *
540
+ * @example
541
+ * ```typescript
542
+ * const response = await sso.auth.register({
543
+ * email: 'user@example.com',
544
+ * password: 'SecurePassword123!'
545
+ * });
546
+ * console.log(response.message);
547
+ * ```
548
+ */
549
+ async register(payload) {
550
+ const response = await this.http.post("/api/auth/register", payload);
551
+ return response.data;
552
+ }
553
+ /**
554
+ * Login with email and password.
555
+ * Returns access token and refresh token on successful authentication.
556
+ * The user's email must be verified before login.
557
+ *
558
+ * @param payload Login credentials (email and password)
559
+ * @returns Access token, refresh token, and expiration info
560
+ *
561
+ * @example
562
+ * ```typescript
563
+ * const tokens = await sso.auth.login({
564
+ * email: 'user@example.com',
565
+ * password: 'SecurePassword123!'
566
+ * });
567
+ * sso.setAuthToken(tokens.access_token);
568
+ * localStorage.setItem('sso_access_token', tokens.access_token);
569
+ * localStorage.setItem('sso_refresh_token', tokens.refresh_token);
570
+ * ```
571
+ */
572
+ async login(payload) {
573
+ const response = await this.http.post("/api/auth/login", payload);
574
+ return response.data;
575
+ }
576
+ /**
577
+ * Verify MFA code and complete authentication.
578
+ * This method should be called after login when the user has MFA enabled.
579
+ * The login will return a pre-auth token with a short expiration (5 minutes).
580
+ * Exchange the pre-auth token and TOTP code for a full session.
581
+ *
582
+ * @param preauthToken The pre-authentication token received from login
583
+ * @param code The TOTP code from the user's authenticator app or a backup code
584
+ * @returns Full session tokens (access_token and refresh_token)
585
+ *
586
+ * @example
587
+ * ```typescript
588
+ * // After login, if MFA is enabled:
589
+ * const loginResponse = await sso.auth.login({
590
+ * email: 'user@example.com',
591
+ * password: 'password'
592
+ * });
593
+ *
594
+ * // Check if this is a pre-auth token (expires_in will be 300 seconds = 5 minutes)
595
+ * if (loginResponse.expires_in === 300) {
596
+ * // User needs to provide MFA code
597
+ * const mfaCode = prompt('Enter your 6-digit code from authenticator app');
598
+ * const tokens = await sso.auth.verifyMfa(loginResponse.access_token, mfaCode);
599
+ * sso.setAuthToken(tokens.access_token);
600
+ * localStorage.setItem('sso_access_token', tokens.access_token);
601
+ * localStorage.setItem('sso_refresh_token', tokens.refresh_token);
602
+ * }
603
+ * ```
604
+ */
605
+ async verifyMfa(preauthToken, code, deviceCodeId) {
606
+ const response = await this.http.post("/api/auth/mfa/verify", {
607
+ preauth_token: preauthToken,
608
+ code,
609
+ ...deviceCodeId && { device_code_id: deviceCodeId }
610
+ });
611
+ return response.data;
612
+ }
613
+ /**
614
+ * Request a password reset for a user account.
615
+ * If the email exists, a reset link will be sent to the user.
616
+ * Returns success regardless of whether the email exists (to prevent email enumeration).
617
+ *
618
+ * @param payload Forgot password request (email address)
619
+ * @returns Confirmation message
620
+ *
621
+ * @example
622
+ * ```typescript
623
+ * const response = await sso.auth.requestPasswordReset({
624
+ * email: 'user@example.com'
625
+ * });
626
+ * console.log(response.message);
627
+ * ```
628
+ */
629
+ async requestPasswordReset(payload) {
630
+ const response = await this.http.post("/api/auth/forgot-password", payload);
631
+ return response.data;
632
+ }
633
+ /**
634
+ * Reset a user's password using a reset token from email.
635
+ * The token is obtained from the password reset email link.
636
+ *
637
+ * @param payload Reset password request (token and new password)
638
+ * @returns Confirmation message
639
+ *
640
+ * @example
641
+ * ```typescript
642
+ * const response = await sso.auth.resetPassword({
643
+ * token: 'reset-token-from-email',
644
+ * new_password: 'NewSecurePassword123!'
645
+ * });
646
+ * console.log(response.message);
647
+ * ```
648
+ */
649
+ async resetPassword(payload) {
650
+ const response = await this.http.post("/api/auth/reset-password", payload);
651
+ return response.data;
652
+ }
528
653
  };
529
654
 
530
655
  // src/modules/user.ts
@@ -533,454 +658,1433 @@ var IdentitiesModule = class {
533
658
  this.http = http;
534
659
  }
535
660
  /**
536
- * List all social accounts linked to the authenticated user.
661
+ * List all social accounts linked to the authenticated user.
662
+ *
663
+ * @returns Array of linked identities
664
+ *
665
+ * @example
666
+ * ```typescript
667
+ * const identities = await sso.user.identities.list();
668
+ * console.log(identities); // [{ provider: 'github' }, { provider: 'google' }]
669
+ * ```
670
+ */
671
+ async list() {
672
+ const response = await this.http.get("/api/user/identities");
673
+ return response.data;
674
+ }
675
+ /**
676
+ * Start linking a new social account to the authenticated user.
677
+ * Returns an authorization URL that the user should be redirected to.
678
+ *
679
+ * @param provider The OAuth provider to link (e.g., 'github', 'google', 'microsoft')
680
+ * @returns Object containing the authorization URL
681
+ *
682
+ * @example
683
+ * ```typescript
684
+ * const { authorization_url } = await sso.user.identities.startLink('github');
685
+ * window.location.href = authorization_url; // Redirect user to complete OAuth
686
+ * ```
687
+ */
688
+ async startLink(provider) {
689
+ const response = await this.http.post(`/api/user/identities/${provider}/link`, {});
690
+ return response.data;
691
+ }
692
+ /**
693
+ * Unlink a social account from the authenticated user.
694
+ * Note: Cannot unlink the last remaining identity to prevent account lockout.
695
+ *
696
+ * @param provider The OAuth provider to unlink (e.g., 'github', 'google', 'microsoft')
697
+ *
698
+ * @example
699
+ * ```typescript
700
+ * await sso.user.identities.unlink('google');
701
+ * ```
702
+ */
703
+ async unlink(provider) {
704
+ await this.http.delete(`/api/user/identities/${provider}`);
705
+ }
706
+ };
707
+ var MfaModule = class {
708
+ constructor(http) {
709
+ this.http = http;
710
+ }
711
+ /**
712
+ * Get the current MFA status for the authenticated user.
713
+ *
714
+ * @returns MFA status
715
+ *
716
+ * @example
717
+ * ```typescript
718
+ * const status = await sso.user.mfa.getStatus();
719
+ * console.log(status.enabled); // false
720
+ * ```
721
+ */
722
+ async getStatus() {
723
+ const response = await this.http.get("/api/user/mfa/status");
724
+ return response.data;
725
+ }
726
+ /**
727
+ * Initiate MFA setup. Generates a TOTP secret and QR code.
728
+ * The user must complete setup by calling verify() with a code from their authenticator app.
729
+ *
730
+ * @returns MFA setup details including QR code
731
+ *
732
+ * @example
733
+ * ```typescript
734
+ * const setup = await sso.user.mfa.setup();
735
+ * console.log(setup.qr_code_svg); // Display this QR code to the user
736
+ * // User scans QR code with authenticator app and enters code to verify
737
+ * ```
738
+ */
739
+ async setup() {
740
+ const response = await this.http.post("/api/user/mfa/setup", {});
741
+ return response.data;
742
+ }
743
+ /**
744
+ * Verify TOTP code and enable MFA.
745
+ * Returns backup codes that must be stored securely by the user.
746
+ *
747
+ * @param code TOTP code from authenticator app
748
+ * @returns Verification response with backup codes
749
+ *
750
+ * @example
751
+ * ```typescript
752
+ * const result = await sso.user.mfa.verify('123456');
753
+ * console.log(result.backup_codes); // Store these securely!
754
+ * ```
755
+ */
756
+ async verify(code) {
757
+ const response = await this.http.post("/api/user/mfa/verify", { code });
758
+ return response.data;
759
+ }
760
+ /**
761
+ * Disable MFA for the authenticated user.
762
+ *
763
+ * @example
764
+ * ```typescript
765
+ * await sso.user.mfa.disable();
766
+ * ```
767
+ */
768
+ async disable() {
769
+ const response = await this.http.delete("/api/user/mfa");
770
+ return response.data;
771
+ }
772
+ /**
773
+ * Regenerate backup codes.
774
+ * Invalidates all previous backup codes and returns new ones.
775
+ *
776
+ * @returns New backup codes
777
+ *
778
+ * @example
779
+ * ```typescript
780
+ * const { backup_codes } = await sso.user.mfa.regenerateBackupCodes();
781
+ * console.log(backup_codes); // Store these securely!
782
+ * ```
783
+ */
784
+ async regenerateBackupCodes() {
785
+ const response = await this.http.post("/api/user/mfa/backup-codes/regenerate", {});
786
+ return response.data;
787
+ }
788
+ };
789
+ var UserModule = class {
790
+ constructor(http) {
791
+ this.http = http;
792
+ this.identities = new IdentitiesModule(http);
793
+ this.mfa = new MfaModule(http);
794
+ }
795
+ /**
796
+ * Get the profile of the currently authenticated user.
797
+ * The response includes context from the JWT (org, service).
798
+ *
799
+ * @returns User profile
800
+ *
801
+ * @example
802
+ * ```typescript
803
+ * const profile = await sso.user.getProfile();
804
+ * console.log(profile.email, profile.org, profile.service);
805
+ * ```
806
+ */
807
+ async getProfile() {
808
+ const response = await this.http.get("/api/user");
809
+ return response.data;
810
+ }
811
+ /**
812
+ * Update the authenticated user's profile.
813
+ *
814
+ * @param payload Update payload
815
+ * @returns Updated user profile
816
+ *
817
+ * @example
818
+ * ```typescript
819
+ * const updated = await sso.user.updateProfile({
820
+ * email: 'newemail@example.com'
821
+ * });
822
+ * ```
823
+ */
824
+ async updateProfile(payload) {
825
+ const response = await this.http.patch("/api/user", payload);
826
+ return response.data;
827
+ }
828
+ /**
829
+ * Get the current user's subscription details for the service in their JWT.
830
+ *
831
+ * @returns Subscription details
832
+ *
833
+ * @example
834
+ * ```typescript
835
+ * const subscription = await sso.user.getSubscription();
836
+ * console.log(subscription.plan, subscription.features);
837
+ * ```
838
+ */
839
+ async getSubscription() {
840
+ const response = await this.http.get("/api/subscription");
841
+ return response.data;
842
+ }
843
+ /**
844
+ * Change the authenticated user's password.
845
+ * Requires the current password for verification.
846
+ *
847
+ * @param payload Change password request (current and new password)
848
+ * @returns Confirmation message
849
+ *
850
+ * @example
851
+ * ```typescript
852
+ * const response = await sso.user.changePassword({
853
+ * current_password: 'OldPassword123!',
854
+ * new_password: 'NewSecurePassword456!'
855
+ * });
856
+ * console.log(response.message);
857
+ * ```
858
+ */
859
+ async changePassword(payload) {
860
+ const response = await this.http.post("/api/user/change-password", payload);
861
+ return response.data;
862
+ }
863
+ /**
864
+ * Set a password for the authenticated user (OAuth users only).
865
+ * This endpoint is for OAuth users who don't have a password yet.
866
+ * If a password is already set, this will return an error.
867
+ *
868
+ * @param payload Set password request (new password only)
869
+ * @returns Confirmation message
870
+ *
871
+ * @example
872
+ * ```typescript
873
+ * const response = await sso.user.setPassword({
874
+ * new_password: 'MyNewSecurePassword123!'
875
+ * });
876
+ * console.log(response.message); // "Password set successfully"
877
+ * ```
878
+ */
879
+ async setPassword(payload) {
880
+ const response = await this.http.post("/api/user/set-password", payload);
881
+ return response.data;
882
+ }
883
+ };
884
+
885
+ // src/modules/organizations/audit.ts
886
+ var AuditLogsModule = class {
887
+ constructor(http) {
888
+ this.http = http;
889
+ }
890
+ /**
891
+ * Get audit logs for an organization.
892
+ * Requires 'owner' or 'admin' role.
893
+ *
894
+ * @param orgSlug Organization slug
895
+ * @param params Optional query parameters for filtering and pagination
896
+ * @returns Paginated audit log response
897
+ *
898
+ * @example
899
+ * ```typescript
900
+ * // Get all audit logs
901
+ * const logs = await sso.organizations.auditLogs.get('acme-corp');
902
+ *
903
+ * // Filter by specific action
904
+ * const userLogs = await sso.organizations.auditLogs.get('acme-corp', {
905
+ * action: 'user.role_updated',
906
+ * page: 1,
907
+ * limit: 20
908
+ * });
909
+ *
910
+ * // Filter by target
911
+ * const serviceLogs = await sso.organizations.auditLogs.get('acme-corp', {
912
+ * target_type: 'service',
913
+ * target_id: 'service-123'
914
+ * });
915
+ * ```
916
+ */
917
+ async get(orgSlug, params) {
918
+ const response = await this.http.get(
919
+ `/api/organizations/${orgSlug}/audit-log`,
920
+ { params }
921
+ );
922
+ return response.data;
923
+ }
924
+ /**
925
+ * Get available audit event types for filtering.
926
+ * Requires 'owner' or 'admin' role.
927
+ *
928
+ * @param orgSlug Organization slug
929
+ * @returns Array of event type information
930
+ *
931
+ * @example
932
+ * ```typescript
933
+ * const eventTypes = await sso.organizations.auditLogs.getEventTypes('acme-corp');
934
+ *
935
+ * // Group by category for UI display
936
+ * const byCategory = eventTypes.reduce((acc, event) => {
937
+ * if (!acc[event.category]) {
938
+ * acc[event.category] = [];
939
+ * }
940
+ * acc[event.category].push(event);
941
+ * return acc;
942
+ * }, {});
943
+ * ```
944
+ */
945
+ async getEventTypes(orgSlug) {
946
+ const response = await this.http.get(
947
+ `/api/organizations/${orgSlug}/audit-log/event-types`
948
+ );
949
+ return response.data;
950
+ }
951
+ };
952
+
953
+ // src/modules/organizations/webhooks.ts
954
+ var WebhooksModule = class {
955
+ constructor(http) {
956
+ this.http = http;
957
+ }
958
+ /**
959
+ * Create a new webhook for an organization.
960
+ * Requires 'owner' or 'admin' role.
961
+ *
962
+ * @param orgSlug Organization slug
963
+ * @param webhook Webhook creation payload
964
+ * @returns Created webhook details
965
+ *
966
+ * @example
967
+ * ```typescript
968
+ * const webhook = await sso.organizations.webhooks.create('acme-corp', {
969
+ * name: 'User Activity',
970
+ * url: 'https://api.example.com/webhooks',
971
+ * events: ['user.invited', 'user.joined', 'user.removed']
972
+ * });
973
+ * console.log('Created webhook:', webhook.id);
974
+ * ```
975
+ */
976
+ async create(orgSlug, webhook) {
977
+ const response = await this.http.post(
978
+ `/api/organizations/${orgSlug}/webhooks`,
979
+ webhook
980
+ );
981
+ return response.data;
982
+ }
983
+ /**
984
+ * List all webhooks for an organization.
985
+ * Requires 'owner' or 'admin' role.
986
+ *
987
+ * @param orgSlug Organization slug
988
+ * @returns List of webhooks with total count
989
+ *
990
+ * @example
991
+ * ```typescript
992
+ * const { webhooks, total } = await sso.organizations.webhooks.list('acme-corp');
993
+ * console.log(`Found ${total} webhooks`);
994
+ * webhooks.forEach(w => console.log(w.name, w.is_active));
995
+ * ```
996
+ */
997
+ async list(orgSlug) {
998
+ const response = await this.http.get(
999
+ `/api/organizations/${orgSlug}/webhooks`
1000
+ );
1001
+ return response.data;
1002
+ }
1003
+ /**
1004
+ * Get a specific webhook by ID.
1005
+ * Requires 'owner' or 'admin' role.
1006
+ *
1007
+ * @param orgSlug Organization slug
1008
+ * @param webhookId Webhook ID
1009
+ * @returns Webhook details
1010
+ *
1011
+ * @example
1012
+ * ```typescript
1013
+ * const webhook = await sso.organizations.webhooks.get('acme-corp', 'webhook-123');
1014
+ * console.log('Webhook URL:', webhook.url);
1015
+ * console.log('Subscribed events:', webhook.events);
1016
+ * ```
1017
+ */
1018
+ async get(orgSlug, webhookId) {
1019
+ const response = await this.http.get(
1020
+ `/api/organizations/${orgSlug}/webhooks/${webhookId}`
1021
+ );
1022
+ return response.data;
1023
+ }
1024
+ /**
1025
+ * Update an existing webhook.
1026
+ * Requires 'owner' or 'admin' role.
1027
+ *
1028
+ * @param orgSlug Organization slug
1029
+ * @param webhookId Webhook ID
1030
+ * @param updates Partial webhook update payload
1031
+ * @returns Updated webhook details
1032
+ *
1033
+ * @example
1034
+ * ```typescript
1035
+ * // Update webhook URL and add new events
1036
+ * const updated = await sso.organizations.webhooks.update('acme-corp', 'webhook-123', {
1037
+ * url: 'https://api.example.com/webhooks/v2',
1038
+ * events: ['user.invited', 'user.joined', 'user.removed', 'user.role_updated']
1039
+ * });
1040
+ *
1041
+ * // Deactivate webhook temporarily
1042
+ * await sso.organizations.webhooks.update('acme-corp', 'webhook-123', {
1043
+ * is_active: false
1044
+ * });
1045
+ * ```
1046
+ */
1047
+ async update(orgSlug, webhookId, updates) {
1048
+ const response = await this.http.patch(
1049
+ `/api/organizations/${orgSlug}/webhooks/${webhookId}`,
1050
+ updates
1051
+ );
1052
+ return response.data;
1053
+ }
1054
+ /**
1055
+ * Delete a webhook.
1056
+ * Requires 'owner' or 'admin' role.
1057
+ * This will also delete all delivery history for this webhook.
1058
+ *
1059
+ * @param orgSlug Organization slug
1060
+ * @param webhookId Webhook ID
1061
+ *
1062
+ * @example
1063
+ * ```typescript
1064
+ * await sso.organizations.webhooks.delete('acme-corp', 'webhook-123');
1065
+ * console.log('Webhook deleted successfully');
1066
+ * ```
1067
+ */
1068
+ async delete(orgSlug, webhookId) {
1069
+ await this.http.delete(
1070
+ `/api/organizations/${orgSlug}/webhooks/${webhookId}`
1071
+ );
1072
+ }
1073
+ /**
1074
+ * Get delivery history for a specific webhook.
1075
+ * Requires 'owner' or 'admin' role.
1076
+ *
1077
+ * @param orgSlug Organization slug
1078
+ * @param webhookId Webhook ID
1079
+ * @param params Optional query parameters for filtering and pagination
1080
+ * @returns Paginated webhook delivery response
1081
+ *
1082
+ * @example
1083
+ * ```typescript
1084
+ * // Get all delivery attempts
1085
+ * const deliveries = await sso.organizations.webhooks.getDeliveries('acme-corp', 'webhook-123');
1086
+ *
1087
+ * // Get only failed deliveries
1088
+ * const failed = await sso.organizations.webhooks.getDeliveries('acme-corp', 'webhook-123', {
1089
+ * delivered: false,
1090
+ * page: 1,
1091
+ * limit: 20
1092
+ * });
1093
+ *
1094
+ * // Get deliveries for specific event type
1095
+ * const userEvents = await sso.organizations.webhooks.getDeliveries('acme-corp', 'webhook-123', {
1096
+ * event_type: 'user.invited'
1097
+ * });
1098
+ * ```
1099
+ */
1100
+ async getDeliveries(orgSlug, webhookId, params) {
1101
+ const response = await this.http.get(
1102
+ `/api/organizations/${orgSlug}/webhooks/${webhookId}/deliveries`,
1103
+ { params }
1104
+ );
1105
+ return response.data;
1106
+ }
1107
+ /**
1108
+ * Get available webhook event types that can be subscribed to.
1109
+ * Requires 'owner' or 'admin' role.
1110
+ *
1111
+ * @param orgSlug Organization slug
1112
+ * @returns Array of available event types with categories
1113
+ *
1114
+ * @example
1115
+ * ```typescript
1116
+ * const eventTypes = await sso.organizations.webhooks.getEventTypes('acme-corp');
1117
+ *
1118
+ * // Group events by category for UI display
1119
+ * const byCategory = eventTypes.reduce((acc, event) => {
1120
+ * if (!acc[event.category]) {
1121
+ * acc[event.category] = [];
1122
+ * }
1123
+ * acc[event.category].push(event);
1124
+ * return acc;
1125
+ * }, {});
1126
+ *
1127
+ * // Display available events
1128
+ * Object.entries(byCategory).forEach(([category, events]) => {
1129
+ * console.log(`\n${category}:`);
1130
+ * events.forEach(e => console.log(` - ${e.label} (${e.value})`));
1131
+ * });
1132
+ * ```
1133
+ */
1134
+ async getEventTypes(orgSlug) {
1135
+ const response = await this.http.get(
1136
+ `/api/organizations/${orgSlug}/webhooks/event-types`
1137
+ );
1138
+ return response.data;
1139
+ }
1140
+ };
1141
+
1142
+ // src/modules/organizations.ts
1143
+ var OrganizationsModule = class {
1144
+ constructor(http) {
1145
+ this.http = http;
1146
+ /**
1147
+ * Member management methods
1148
+ */
1149
+ this.members = {
1150
+ /**
1151
+ * List all members of an organization.
1152
+ *
1153
+ * @param orgSlug Organization slug
1154
+ * @returns Member list response with pagination metadata
1155
+ *
1156
+ * @example
1157
+ * ```typescript
1158
+ * const result = await sso.organizations.members.list('acme-corp');
1159
+ * console.log(`Total members: ${result.total}`);
1160
+ * result.members.forEach(m => console.log(m.email, m.role));
1161
+ * ```
1162
+ */
1163
+ list: async (orgSlug) => {
1164
+ const response = await this.http.get(
1165
+ `/api/organizations/${orgSlug}/members`
1166
+ );
1167
+ return response.data;
1168
+ },
1169
+ /**
1170
+ * Update a member's role.
1171
+ * Requires 'owner' role.
1172
+ *
1173
+ * @param orgSlug Organization slug
1174
+ * @param userId User ID to update
1175
+ * @param payload Role update payload
1176
+ * @returns Updated member details
1177
+ *
1178
+ * @example
1179
+ * ```typescript
1180
+ * await sso.organizations.members.updateRole('acme-corp', 'user-id', {
1181
+ * role: 'admin'
1182
+ * });
1183
+ * ```
1184
+ */
1185
+ updateRole: async (orgSlug, userId, payload) => {
1186
+ const response = await this.http.patch(
1187
+ `/api/organizations/${orgSlug}/members/${userId}`,
1188
+ payload
1189
+ );
1190
+ return response.data;
1191
+ },
1192
+ /**
1193
+ * Remove a member from the organization.
1194
+ * Requires 'owner' or 'admin' role.
1195
+ *
1196
+ * @param orgSlug Organization slug
1197
+ * @param userId User ID to remove
1198
+ *
1199
+ * @example
1200
+ * ```typescript
1201
+ * await sso.organizations.members.remove('acme-corp', 'user-id');
1202
+ * ```
1203
+ */
1204
+ remove: async (orgSlug, userId) => {
1205
+ await this.http.post(`/api/organizations/${orgSlug}/members/${userId}`);
1206
+ },
1207
+ /**
1208
+ * Transfer organization ownership to another member.
1209
+ * Requires 'owner' role.
1210
+ *
1211
+ * @param orgSlug Organization slug
1212
+ * @param payload Transfer payload with new owner ID
1213
+ *
1214
+ * @example
1215
+ * ```typescript
1216
+ * await sso.organizations.members.transferOwnership('acme-corp', {
1217
+ * new_owner_user_id: 'new-owner-id'
1218
+ * });
1219
+ * ```
1220
+ */
1221
+ transferOwnership: async (orgSlug, payload) => {
1222
+ await this.http.post(`/api/organizations/${orgSlug}/members/transfer-ownership`, payload);
1223
+ }
1224
+ };
1225
+ /**
1226
+ * End-user management methods
1227
+ * Manage organization's customers (end-users with subscriptions)
1228
+ */
1229
+ this.endUsers = {
1230
+ /**
1231
+ * List all end-users for an organization.
1232
+ * Returns users who have identities (logged in) or subscriptions for the organization's services.
1233
+ *
1234
+ * @param orgSlug Organization slug
1235
+ * @param params Optional query parameters for pagination and filtering
1236
+ * @param params.service_slug Optional service slug to filter users by a specific service
1237
+ * @returns Paginated list of end-users with their subscriptions and identities
1238
+ *
1239
+ * @example
1240
+ * ```typescript
1241
+ * // List all end-users across all services
1242
+ * const allUsers = await sso.organizations.endUsers.list('acme-corp', {
1243
+ * page: 1,
1244
+ * limit: 20
1245
+ * });
1246
+ *
1247
+ * // Filter by specific service
1248
+ * const serviceUsers = await sso.organizations.endUsers.list('acme-corp', {
1249
+ * service_slug: 'my-app',
1250
+ * page: 1,
1251
+ * limit: 20
1252
+ * });
1253
+ * console.log(`Total end-users: ${allUsers.total}`);
1254
+ * ```
1255
+ */
1256
+ list: async (orgSlug, params) => {
1257
+ const response = await this.http.get(
1258
+ `/api/organizations/${orgSlug}/users`,
1259
+ { params }
1260
+ );
1261
+ return response.data;
1262
+ },
1263
+ /**
1264
+ * Get detailed information about a specific end-user.
1265
+ *
1266
+ * @param orgSlug Organization slug
1267
+ * @param userId User ID
1268
+ * @returns End-user details with subscriptions, identities, and session count
1269
+ *
1270
+ * @example
1271
+ * ```typescript
1272
+ * const endUser = await sso.organizations.endUsers.get('acme-corp', 'user-id');
1273
+ * console.log(`Active sessions: ${endUser.session_count}`);
1274
+ * ```
1275
+ */
1276
+ get: async (orgSlug, userId) => {
1277
+ const response = await this.http.get(
1278
+ `/api/organizations/${orgSlug}/users/${userId}`
1279
+ );
1280
+ return response.data;
1281
+ },
1282
+ /**
1283
+ * Revoke all active sessions for an end-user.
1284
+ * Requires admin or owner role.
1285
+ * This will force the user to re-authenticate.
1286
+ *
1287
+ * @param orgSlug Organization slug
1288
+ * @param userId User ID
1289
+ * @returns Response with number of revoked sessions
1290
+ *
1291
+ * @example
1292
+ * ```typescript
1293
+ * const result = await sso.organizations.endUsers.revokeSessions('acme-corp', 'user-id');
1294
+ * console.log(`Revoked ${result.revoked_count} sessions`);
1295
+ * ```
1296
+ */
1297
+ revokeSessions: async (orgSlug, userId) => {
1298
+ const response = await this.http.delete(
1299
+ `/api/organizations/${orgSlug}/users/${userId}/sessions`
1300
+ );
1301
+ return response.data;
1302
+ }
1303
+ };
1304
+ /**
1305
+ * BYOO (Bring Your Own OAuth) credential management
1306
+ */
1307
+ this.oauthCredentials = {
1308
+ /**
1309
+ * Set or update custom OAuth credentials for a provider.
1310
+ * This enables white-labeled authentication using the organization's
1311
+ * own OAuth application.
1312
+ * Requires 'owner' or 'admin' role.
1313
+ *
1314
+ * @param orgSlug Organization slug
1315
+ * @param provider OAuth provider
1316
+ * @param payload OAuth credentials
1317
+ * @returns Created/updated credentials (without secret)
1318
+ *
1319
+ * @example
1320
+ * ```typescript
1321
+ * await sso.organizations.oauthCredentials.set('acme-corp', 'github', {
1322
+ * client_id: 'Iv1.abc123',
1323
+ * client_secret: 'secret-value'
1324
+ * });
1325
+ * ```
1326
+ */
1327
+ set: async (orgSlug, provider, payload) => {
1328
+ const response = await this.http.post(
1329
+ `/api/organizations/${orgSlug}/oauth-credentials/${provider}`,
1330
+ payload
1331
+ );
1332
+ return response.data;
1333
+ },
1334
+ /**
1335
+ * Get the configured OAuth credentials for a provider.
1336
+ * The secret is never returned.
1337
+ *
1338
+ * @param orgSlug Organization slug
1339
+ * @param provider OAuth provider
1340
+ * @returns OAuth credentials (without secret)
1341
+ *
1342
+ * @example
1343
+ * ```typescript
1344
+ * const creds = await sso.organizations.oauthCredentials.get('acme-corp', 'github');
1345
+ * console.log(creds.client_id);
1346
+ * ```
1347
+ */
1348
+ get: async (orgSlug, provider) => {
1349
+ const response = await this.http.get(
1350
+ `/api/organizations/${orgSlug}/oauth-credentials/${provider}`
1351
+ );
1352
+ return response.data;
1353
+ }
1354
+ };
1355
+ this.auditLogs = new AuditLogsModule(http);
1356
+ this.webhooks = new WebhooksModule(http);
1357
+ }
1358
+ /**
1359
+ * Create a new organization (public endpoint).
1360
+ * The organization will be created with 'pending' status and requires
1361
+ * platform owner approval before becoming active.
1362
+ *
1363
+ * @param payload Organization creation payload
1364
+ * @returns Created organization with owner and membership details
1365
+ *
1366
+ * @example
1367
+ * ```typescript
1368
+ * const result = await sso.organizations.createPublic({
1369
+ * slug: 'acme-corp',
1370
+ * name: 'Acme Corporation',
1371
+ * owner_email: 'founder@acme.com'
1372
+ * });
1373
+ * ```
1374
+ */
1375
+ async createPublic(payload) {
1376
+ const response = await this.http.post("/api/organizations", payload);
1377
+ return response.data;
1378
+ }
1379
+ /**
1380
+ * List all organizations the authenticated user is a member of.
1381
+ *
1382
+ * @param params Optional query parameters for filtering and pagination
1383
+ * @returns Array of organization responses
1384
+ *
1385
+ * @example
1386
+ * ```typescript
1387
+ * const orgs = await sso.organizations.list({
1388
+ * status: 'active',
1389
+ * page: 1,
1390
+ * limit: 20
1391
+ * });
1392
+ * ```
1393
+ */
1394
+ async list(params) {
1395
+ const response = await this.http.get("/api/organizations", { params });
1396
+ return response.data;
1397
+ }
1398
+ /**
1399
+ * Get detailed information for a specific organization.
1400
+ *
1401
+ * @param orgSlug Organization slug
1402
+ * @returns Organization details
1403
+ *
1404
+ * @example
1405
+ * ```typescript
1406
+ * const org = await sso.organizations.get('acme-corp');
1407
+ * console.log(org.organization.name, org.membership_count);
1408
+ * ```
1409
+ */
1410
+ async get(orgSlug) {
1411
+ const response = await this.http.get(`/api/organizations/${orgSlug}`);
1412
+ return response.data;
1413
+ }
1414
+ /**
1415
+ * Update organization details.
1416
+ * Requires 'owner' or 'admin' role.
1417
+ *
1418
+ * @param orgSlug Organization slug
1419
+ * @param payload Update payload
1420
+ * @returns Updated organization details
1421
+ *
1422
+ * @example
1423
+ * ```typescript
1424
+ * const updated = await sso.organizations.update('acme-corp', {
1425
+ * name: 'Acme Corporation Inc.',
1426
+ * max_services: 20
1427
+ * });
1428
+ * ```
1429
+ */
1430
+ async update(orgSlug, payload) {
1431
+ const response = await this.http.patch(
1432
+ `/api/organizations/${orgSlug}`,
1433
+ payload
1434
+ );
1435
+ return response.data;
1436
+ }
1437
+ /**
1438
+ * Delete an organization and all its associated data.
1439
+ * This is a destructive operation that cannot be undone.
1440
+ * Requires 'owner' role.
1441
+ *
1442
+ * All related data will be cascaded deleted including:
1443
+ * - Members and invitations
1444
+ * - Services and plans
1445
+ * - Subscriptions
1446
+ * - OAuth credentials
1447
+ * - Audit logs
1448
+ *
1449
+ * @param orgSlug Organization slug
1450
+ *
1451
+ * @example
1452
+ * ```typescript
1453
+ * await sso.organizations.delete('acme-corp');
1454
+ * ```
1455
+ */
1456
+ async delete(orgSlug) {
1457
+ await this.http.delete(`/api/organizations/${orgSlug}`);
1458
+ }
1459
+ // ============================================================================
1460
+ // SMTP MANAGEMENT
1461
+ // ============================================================================
1462
+ /**
1463
+ * Configure SMTP settings for an organization.
1464
+ * Only owners and admins can configure SMTP.
1465
+ * The organization will use these settings for sending transactional emails
1466
+ * (registration, password reset, etc.).
1467
+ *
1468
+ * @param orgSlug Organization slug
1469
+ * @param config SMTP configuration
1470
+ * @returns Success message
1471
+ *
1472
+ * @example
1473
+ * ```typescript
1474
+ * await sso.organizations.setSmtp('acme-corp', {
1475
+ * host: 'smtp.gmail.com',
1476
+ * port: 587,
1477
+ * username: 'notifications@acme.com',
1478
+ * password: 'your-app-password',
1479
+ * from_email: 'notifications@acme.com',
1480
+ * from_name: 'Acme Corp'
1481
+ * });
1482
+ * ```
1483
+ */
1484
+ async setSmtp(orgSlug, config) {
1485
+ const response = await this.http.post(
1486
+ `/api/organizations/${orgSlug}/smtp`,
1487
+ config
1488
+ );
1489
+ return response.data;
1490
+ }
1491
+ /**
1492
+ * Get SMTP configuration for an organization.
1493
+ * Only owners and admins can view SMTP settings.
1494
+ * Password is never returned for security reasons.
1495
+ *
1496
+ * @param orgSlug Organization slug
1497
+ * @returns SMTP configuration (without password)
1498
+ *
1499
+ * @example
1500
+ * ```typescript
1501
+ * const config = await sso.organizations.getSmtp('acme-corp');
1502
+ * if (config.configured) {
1503
+ * console.log('SMTP host:', config.host);
1504
+ * }
1505
+ * ```
1506
+ */
1507
+ async getSmtp(orgSlug) {
1508
+ const response = await this.http.get(
1509
+ `/api/organizations/${orgSlug}/smtp`
1510
+ );
1511
+ return response.data;
1512
+ }
1513
+ /**
1514
+ * Delete SMTP configuration for an organization.
1515
+ * The organization will revert to using platform-level SMTP.
1516
+ * Only owners and admins can delete SMTP settings.
537
1517
  *
538
- * @returns Array of linked identities
1518
+ * @param orgSlug Organization slug
1519
+ * @returns Success message
539
1520
  *
540
1521
  * @example
541
1522
  * ```typescript
542
- * const identities = await sso.user.identities.list();
543
- * console.log(identities); // [{ provider: 'github' }, { provider: 'google' }]
1523
+ * await sso.organizations.deleteSmtp('acme-corp');
1524
+ * // Organization now uses platform SMTP
544
1525
  * ```
545
1526
  */
546
- async list() {
547
- const response = await this.http.get("/api/user/identities");
1527
+ async deleteSmtp(orgSlug) {
1528
+ const response = await this.http.delete(
1529
+ `/api/organizations/${orgSlug}/smtp`
1530
+ );
548
1531
  return response.data;
549
1532
  }
1533
+ // ============================================================================
1534
+ // CUSTOM DOMAINS & BRANDING
1535
+ // ============================================================================
550
1536
  /**
551
- * Start linking a new social account to the authenticated user.
552
- * Returns an authorization URL that the user should be redirected to.
1537
+ * Set a custom domain for an organization.
1538
+ * This enables white-labeling by allowing the organization to use their own domain
1539
+ * (e.g., auth.acme.com) instead of the platform's domain.
1540
+ * Requires 'owner' or 'admin' role.
553
1541
  *
554
- * @param provider The OAuth provider to link (e.g., 'github', 'google', 'microsoft')
555
- * @returns Object containing the authorization URL
1542
+ * @param orgSlug Organization slug
1543
+ * @param request Custom domain request
1544
+ * @returns Domain verification instructions
556
1545
  *
557
1546
  * @example
558
1547
  * ```typescript
559
- * const { authorization_url } = await sso.user.identities.startLink('github');
560
- * window.location.href = authorization_url; // Redirect user to complete OAuth
1548
+ * const verification = await sso.organizations.setCustomDomain('acme-corp', {
1549
+ * domain: 'auth.acme.com'
1550
+ * });
1551
+ * console.log('Verification token:', verification.verification_token);
1552
+ * verification.verification_methods.forEach(method => {
1553
+ * console.log(method.method, method.instructions);
1554
+ * });
561
1555
  * ```
562
1556
  */
563
- async startLink(provider) {
564
- const response = await this.http.post(`/api/user/identities/${provider}/link`, {});
1557
+ async setCustomDomain(orgSlug, request) {
1558
+ const response = await this.http.post(
1559
+ `/api/organizations/${orgSlug}/domain`,
1560
+ request
1561
+ );
565
1562
  return response.data;
566
1563
  }
567
1564
  /**
568
- * Unlink a social account from the authenticated user.
569
- * Note: Cannot unlink the last remaining identity to prevent account lockout.
1565
+ * Verify a custom domain by checking DNS TXT record or HTTP file.
1566
+ * Requires 'owner' or 'admin' role.
570
1567
  *
571
- * @param provider The OAuth provider to unlink (e.g., 'github', 'google', 'microsoft')
1568
+ * @param orgSlug Organization slug
1569
+ * @returns Verification result
572
1570
  *
573
1571
  * @example
574
1572
  * ```typescript
575
- * await sso.user.identities.unlink('google');
1573
+ * const result = await sso.organizations.verifyCustomDomain('acme-corp');
1574
+ * if (result.verified) {
1575
+ * console.log('Domain verified successfully!');
1576
+ * } else {
1577
+ * console.log('Verification failed:', result.message);
1578
+ * }
576
1579
  * ```
577
1580
  */
578
- async unlink(provider) {
579
- await this.http.delete(`/api/user/identities/${provider}`);
580
- }
581
- };
582
- var UserModule = class {
583
- constructor(http) {
584
- this.http = http;
585
- this.identities = new IdentitiesModule(http);
1581
+ async verifyCustomDomain(orgSlug) {
1582
+ const response = await this.http.post(
1583
+ `/api/organizations/${orgSlug}/domain/verify`
1584
+ );
1585
+ return response.data;
586
1586
  }
587
1587
  /**
588
- * Get the profile of the currently authenticated user.
589
- * The response includes context from the JWT (org, service).
1588
+ * Get custom domain configuration for an organization.
590
1589
  *
591
- * @returns User profile
1590
+ * @param orgSlug Organization slug
1591
+ * @returns Domain configuration
592
1592
  *
593
1593
  * @example
594
1594
  * ```typescript
595
- * const profile = await sso.user.getProfile();
596
- * console.log(profile.email, profile.org, profile.service);
1595
+ * const config = await sso.organizations.getDomainConfiguration('acme-corp');
1596
+ * if (config.custom_domain && config.domain_verified) {
1597
+ * console.log('Custom domain active:', config.custom_domain);
1598
+ * }
597
1599
  * ```
598
1600
  */
599
- async getProfile() {
600
- const response = await this.http.get("/api/user");
1601
+ async getDomainConfiguration(orgSlug) {
1602
+ const response = await this.http.get(
1603
+ `/api/organizations/${orgSlug}/domain`
1604
+ );
601
1605
  return response.data;
602
1606
  }
603
1607
  /**
604
- * Update the authenticated user's profile.
1608
+ * Delete custom domain configuration.
1609
+ * Requires 'owner' or 'admin' role.
605
1610
  *
606
- * @param payload Update payload
607
- * @returns Updated user profile
1611
+ * @param orgSlug Organization slug
608
1612
  *
609
1613
  * @example
610
1614
  * ```typescript
611
- * const updated = await sso.user.updateProfile({
612
- * email: 'newemail@example.com'
1615
+ * await sso.organizations.deleteCustomDomain('acme-corp');
1616
+ * // Organization reverts to using platform domain
1617
+ * ```
1618
+ */
1619
+ async deleteCustomDomain(orgSlug) {
1620
+ await this.http.delete(`/api/organizations/${orgSlug}/domain`);
1621
+ }
1622
+ /**
1623
+ * Update branding configuration (logo and primary color).
1624
+ * This controls the visual appearance of authentication pages.
1625
+ * Requires 'owner' or 'admin' role.
1626
+ *
1627
+ * @param orgSlug Organization slug
1628
+ * @param request Branding configuration
1629
+ * @returns Updated branding configuration
1630
+ *
1631
+ * @example
1632
+ * ```typescript
1633
+ * await sso.organizations.updateBranding('acme-corp', {
1634
+ * logo_url: 'https://cdn.acme.com/logo.png',
1635
+ * primary_color: '#FF5733'
613
1636
  * });
614
1637
  * ```
615
1638
  */
616
- async updateProfile(payload) {
617
- const response = await this.http.patch("/api/user", payload);
1639
+ async updateBranding(orgSlug, request) {
1640
+ const response = await this.http.patch(
1641
+ `/api/organizations/${orgSlug}/branding`,
1642
+ request
1643
+ );
618
1644
  return response.data;
619
1645
  }
620
1646
  /**
621
- * Get the current user's subscription details for the service in their JWT.
1647
+ * Get branding configuration for an organization.
622
1648
  *
623
- * @returns Subscription details
1649
+ * @param orgSlug Organization slug
1650
+ * @returns Branding configuration
624
1651
  *
625
1652
  * @example
626
1653
  * ```typescript
627
- * const subscription = await sso.user.getSubscription();
628
- * console.log(subscription.plan, subscription.features);
1654
+ * const branding = await sso.organizations.getBranding('acme-corp');
1655
+ * if (branding.logo_url) {
1656
+ * console.log('Logo URL:', branding.logo_url);
1657
+ * }
629
1658
  * ```
630
1659
  */
631
- async getSubscription() {
632
- const response = await this.http.get("/api/subscription");
1660
+ async getBranding(orgSlug) {
1661
+ const response = await this.http.get(
1662
+ `/api/organizations/${orgSlug}/branding`
1663
+ );
1664
+ return response.data;
1665
+ }
1666
+ /**
1667
+ * Get public branding configuration (no authentication required).
1668
+ * This endpoint is used by login pages to display organization branding.
1669
+ *
1670
+ * @param orgSlug Organization slug
1671
+ * @returns Branding configuration
1672
+ *
1673
+ * @example
1674
+ * ```typescript
1675
+ * // Can be called without authentication
1676
+ * const branding = await sso.organizations.getPublicBranding('acme-corp');
1677
+ * ```
1678
+ */
1679
+ async getPublicBranding(orgSlug) {
1680
+ const response = await this.http.get(
1681
+ `/api/organizations/${orgSlug}/branding/public`
1682
+ );
633
1683
  return response.data;
634
1684
  }
635
1685
  };
636
1686
 
637
- // src/modules/organizations.ts
638
- var OrganizationsModule = class {
1687
+ // src/modules/services.ts
1688
+ var ServicesModule = class {
639
1689
  constructor(http) {
640
1690
  this.http = http;
641
1691
  /**
642
- * Member management methods
1692
+ * Plan management methods
643
1693
  */
644
- this.members = {
1694
+ this.plans = {
645
1695
  /**
646
- * List all members of an organization.
1696
+ * Create a new subscription plan for a service.
1697
+ * Requires 'owner' or 'admin' role.
647
1698
  *
648
1699
  * @param orgSlug Organization slug
649
- * @returns Member list response with pagination metadata
1700
+ * @param serviceSlug Service slug
1701
+ * @param payload Plan creation payload
1702
+ * @returns Created plan with subscription count
650
1703
  *
651
1704
  * @example
652
1705
  * ```typescript
653
- * const result = await sso.organizations.members.list('acme-corp');
654
- * console.log(`Total members: ${result.total}`);
655
- * result.members.forEach(m => console.log(m.email, m.role));
1706
+ * const result = await sso.services.plans.create('acme-corp', 'main-app', {
1707
+ * name: 'pro',
1708
+ * price_cents: 2999,
1709
+ * currency: 'usd',
1710
+ * features: ['api-access', 'advanced-analytics', 'priority-support']
1711
+ * });
1712
+ * console.log(result.plan.name, result.subscription_count);
656
1713
  * ```
657
1714
  */
658
- list: async (orgSlug) => {
1715
+ create: async (orgSlug, serviceSlug, payload) => {
1716
+ const response = await this.http.post(
1717
+ `/api/organizations/${orgSlug}/services/${serviceSlug}/plans`,
1718
+ payload
1719
+ );
1720
+ return response.data;
1721
+ },
1722
+ /**
1723
+ * List all plans for a service.
1724
+ *
1725
+ * @param orgSlug Organization slug
1726
+ * @param serviceSlug Service slug
1727
+ * @returns Array of plans with subscription counts
1728
+ *
1729
+ * @example
1730
+ * ```typescript
1731
+ * const plans = await sso.services.plans.list('acme-corp', 'main-app');
1732
+ * plans.forEach(p => console.log(p.plan.name, p.subscription_count));
1733
+ * ```
1734
+ */
1735
+ list: async (orgSlug, serviceSlug) => {
659
1736
  const response = await this.http.get(
660
- `/api/organizations/${orgSlug}/members`
1737
+ `/api/organizations/${orgSlug}/services/${serviceSlug}/plans`
661
1738
  );
662
1739
  return response.data;
663
1740
  },
664
1741
  /**
665
- * Update a member's role.
666
- * Requires 'owner' role.
1742
+ * Update a subscription plan.
1743
+ * Requires 'owner' or 'admin' role.
667
1744
  *
668
1745
  * @param orgSlug Organization slug
669
- * @param userId User ID to update
670
- * @param payload Role update payload
671
- * @returns Updated member details
1746
+ * @param serviceSlug Service slug
1747
+ * @param planId Plan ID
1748
+ * @param payload Plan update payload
1749
+ * @returns Updated plan with subscription count
672
1750
  *
673
1751
  * @example
674
1752
  * ```typescript
675
- * await sso.organizations.members.updateRole('acme-corp', 'user-id', {
676
- * role: 'admin'
1753
+ * const result = await sso.services.plans.update('acme-corp', 'main-app', 'plan_123', {
1754
+ * name: 'Pro Plus',
1755
+ * price_cents: 3999,
1756
+ * currency: 'usd',
1757
+ * features: ['api-access', 'advanced-analytics', 'priority-support', 'custom-integrations']
677
1758
  * });
1759
+ * console.log('Updated plan:', result.plan.name);
678
1760
  * ```
679
1761
  */
680
- updateRole: async (orgSlug, userId, payload) => {
1762
+ update: async (orgSlug, serviceSlug, planId, payload) => {
681
1763
  const response = await this.http.patch(
682
- `/api/organizations/${orgSlug}/members/${userId}`,
1764
+ `/api/organizations/${orgSlug}/services/${serviceSlug}/plans/${planId}`,
683
1765
  payload
684
1766
  );
685
1767
  return response.data;
686
1768
  },
687
1769
  /**
688
- * Remove a member from the organization.
1770
+ * Delete a subscription plan.
689
1771
  * Requires 'owner' or 'admin' role.
690
1772
  *
1773
+ * WARNING: This will fail if the plan has active subscriptions.
1774
+ * You must migrate or cancel all subscriptions before deleting a plan.
1775
+ *
691
1776
  * @param orgSlug Organization slug
692
- * @param userId User ID to remove
1777
+ * @param serviceSlug Service slug
1778
+ * @param planId Plan ID
693
1779
  *
694
1780
  * @example
695
1781
  * ```typescript
696
- * await sso.organizations.members.remove('acme-corp', 'user-id');
1782
+ * try {
1783
+ * await sso.services.plans.delete('acme-corp', 'main-app', 'plan_123');
1784
+ * console.log('Plan deleted successfully');
1785
+ * } catch (error) {
1786
+ * console.error('Cannot delete plan with active subscriptions');
1787
+ * }
697
1788
  * ```
698
1789
  */
699
- remove: async (orgSlug, userId) => {
700
- await this.http.post(`/api/organizations/${orgSlug}/members/${userId}`);
1790
+ delete: async (orgSlug, serviceSlug, planId) => {
1791
+ await this.http.delete(
1792
+ `/api/organizations/${orgSlug}/services/${serviceSlug}/plans/${planId}`
1793
+ );
1794
+ }
1795
+ };
1796
+ /**
1797
+ * API Key management methods for service-to-service authentication
1798
+ */
1799
+ this.apiKeys = {
1800
+ /**
1801
+ * Create a new API key for a service.
1802
+ * Requires 'owner' or 'admin' role.
1803
+ *
1804
+ * IMPORTANT: The full API key is only returned once upon creation.
1805
+ * Store it securely as it cannot be retrieved again.
1806
+ *
1807
+ * @param orgSlug Organization slug
1808
+ * @param serviceSlug Service slug
1809
+ * @param payload API key creation payload
1810
+ * @returns Created API key with the full key value
1811
+ *
1812
+ * @example
1813
+ * ```typescript
1814
+ * const apiKey = await sso.services.apiKeys.create('acme-corp', 'main-app', {
1815
+ * name: 'Production Backend',
1816
+ * permissions: ['read:users', 'write:subscriptions'],
1817
+ * expires_in_days: 90
1818
+ * });
1819
+ *
1820
+ * // IMPORTANT: Store this key securely - it won't be shown again
1821
+ * console.log('API Key:', apiKey.key);
1822
+ * console.log('Prefix:', apiKey.prefix);
1823
+ * ```
1824
+ */
1825
+ create: async (orgSlug, serviceSlug, payload) => {
1826
+ const response = await this.http.post(
1827
+ `/api/organizations/${orgSlug}/services/${serviceSlug}/api-keys`,
1828
+ payload
1829
+ );
1830
+ return response.data;
701
1831
  },
702
1832
  /**
703
- * Transfer organization ownership to another member.
704
- * Requires 'owner' role.
1833
+ * List all API keys for a service.
1834
+ * Note: The full key values are not included in this response.
705
1835
  *
706
1836
  * @param orgSlug Organization slug
707
- * @param payload Transfer payload with new owner ID
1837
+ * @param serviceSlug Service slug
1838
+ * @param options Optional query parameters for pagination
1839
+ * @returns List of API keys with metadata
708
1840
  *
709
1841
  * @example
710
1842
  * ```typescript
711
- * await sso.organizations.members.transferOwnership('acme-corp', {
712
- * new_owner_user_id: 'new-owner-id'
1843
+ * const result = await sso.services.apiKeys.list('acme-corp', 'main-app', {
1844
+ * limit: 50,
1845
+ * offset: 0
1846
+ * });
1847
+ *
1848
+ * console.log(`Total API keys: ${result.total}`);
1849
+ * result.api_keys.forEach(key => {
1850
+ * console.log(`${key.name} (${key.prefix})`);
1851
+ * console.log(`Permissions: ${key.permissions.join(', ')}`);
1852
+ * console.log(`Last used: ${key.last_used_at || 'Never'}`);
713
1853
  * });
714
1854
  * ```
715
1855
  */
716
- transferOwnership: async (orgSlug, payload) => {
717
- await this.http.post(`/api/organizations/${orgSlug}/members/transfer-ownership`, payload);
1856
+ list: async (orgSlug, serviceSlug, options) => {
1857
+ const queryParams = new URLSearchParams();
1858
+ if (options?.limit) queryParams.set("limit", options.limit.toString());
1859
+ if (options?.offset) queryParams.set("offset", options.offset.toString());
1860
+ const query = queryParams.toString() ? `?${queryParams.toString()}` : "";
1861
+ const response = await this.http.get(
1862
+ `/api/organizations/${orgSlug}/services/${serviceSlug}/api-keys${query}`
1863
+ );
1864
+ return response.data;
1865
+ },
1866
+ /**
1867
+ * Get details for a specific API key.
1868
+ * Note: The full key value is not included in this response.
1869
+ *
1870
+ * @param orgSlug Organization slug
1871
+ * @param serviceSlug Service slug
1872
+ * @param apiKeyId API key ID
1873
+ * @returns API key details
1874
+ *
1875
+ * @example
1876
+ * ```typescript
1877
+ * const apiKey = await sso.services.apiKeys.get('acme-corp', 'main-app', 'key_abc123');
1878
+ * console.log(`Name: ${apiKey.name}`);
1879
+ * console.log(`Permissions: ${apiKey.permissions.join(', ')}`);
1880
+ * console.log(`Expires: ${apiKey.expires_at || 'Never'}`);
1881
+ * ```
1882
+ */
1883
+ get: async (orgSlug, serviceSlug, apiKeyId) => {
1884
+ const response = await this.http.get(
1885
+ `/api/organizations/${orgSlug}/services/${serviceSlug}/api-keys/${apiKeyId}`
1886
+ );
1887
+ return response.data;
1888
+ },
1889
+ /**
1890
+ * Delete an API key.
1891
+ * Requires 'owner' or 'admin' role.
1892
+ *
1893
+ * WARNING: This action is immediate and cannot be undone.
1894
+ * Any services using this key will lose access immediately.
1895
+ *
1896
+ * @param orgSlug Organization slug
1897
+ * @param serviceSlug Service slug
1898
+ * @param apiKeyId API key ID
1899
+ *
1900
+ * @example
1901
+ * ```typescript
1902
+ * await sso.services.apiKeys.delete('acme-corp', 'main-app', 'key_abc123');
1903
+ * console.log('API key deleted successfully');
1904
+ * ```
1905
+ */
1906
+ delete: async (orgSlug, serviceSlug, apiKeyId) => {
1907
+ await this.http.delete(
1908
+ `/api/organizations/${orgSlug}/services/${serviceSlug}/api-keys/${apiKeyId}`
1909
+ );
718
1910
  }
719
1911
  };
720
1912
  /**
721
- * End-user management methods
722
- * Manage organization's customers (end-users with subscriptions)
1913
+ * SAML 2.0 Identity Provider (IdP) management methods
1914
+ *
1915
+ * Configure your service as a SAML IdP to enable SSO into third-party applications
1916
+ * (Salesforce, AWS, Google Workspace, etc.)
723
1917
  */
724
- this.endUsers = {
1918
+ this.saml = {
725
1919
  /**
726
- * List all end-users for an organization.
727
- * Returns users who have identities (logged in) or subscriptions for the organization's services.
1920
+ * Configure SAML IdP settings for a service.
1921
+ * Requires 'owner' or 'admin' role.
728
1922
  *
729
1923
  * @param orgSlug Organization slug
730
- * @param params Optional query parameters for pagination and filtering
731
- * @param params.service_slug Optional service slug to filter users by a specific service
732
- * @returns Paginated list of end-users with their subscriptions and identities
1924
+ * @param serviceSlug Service slug
1925
+ * @param payload SAML configuration payload
1926
+ * @returns Configuration success response
733
1927
  *
734
1928
  * @example
735
1929
  * ```typescript
736
- * // List all end-users across all services
737
- * const allUsers = await sso.organizations.endUsers.list('acme-corp', {
738
- * page: 1,
739
- * limit: 20
740
- * });
741
- *
742
- * // Filter by specific service
743
- * const serviceUsers = await sso.organizations.endUsers.list('acme-corp', {
744
- * service_slug: 'my-app',
745
- * page: 1,
746
- * limit: 20
1930
+ * const result = await sso.services.saml.configure('acme-corp', 'main-app', {
1931
+ * enabled: true,
1932
+ * entity_id: 'https://salesforce.example.com',
1933
+ * acs_url: 'https://salesforce.example.com/saml/acs',
1934
+ * name_id_format: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
1935
+ * attribute_mapping: {
1936
+ * email: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'
1937
+ * },
1938
+ * sign_assertions: true,
1939
+ * sign_response: true
747
1940
  * });
748
- * console.log(`Total end-users: ${allUsers.total}`);
749
1941
  * ```
750
1942
  */
751
- list: async (orgSlug, params) => {
752
- const response = await this.http.get(
753
- `/api/organizations/${orgSlug}/users`,
754
- { params }
1943
+ configure: async (orgSlug, serviceSlug, payload) => {
1944
+ const response = await this.http.post(
1945
+ `/api/organizations/${orgSlug}/services/${serviceSlug}/saml`,
1946
+ payload
755
1947
  );
756
1948
  return response.data;
757
1949
  },
758
1950
  /**
759
- * Get detailed information about a specific end-user.
1951
+ * Get current SAML IdP configuration for a service.
760
1952
  *
761
- * @param orgSlug Organization slug
762
- * @param userId User ID
763
- * @returns End-user details with subscriptions, identities, and session count
1953
+ * @param orgSlug Organization slug
1954
+ * @param serviceSlug Service slug
1955
+ * @returns Current SAML configuration
764
1956
  *
765
1957
  * @example
766
1958
  * ```typescript
767
- * const endUser = await sso.organizations.endUsers.get('acme-corp', 'user-id');
768
- * console.log(`Active sessions: ${endUser.session_count}`);
1959
+ * const config = await sso.services.saml.getConfig('acme-corp', 'main-app');
1960
+ * if (config.enabled && config.has_certificate) {
1961
+ * console.log('SAML IdP is ready');
1962
+ * console.log('Entity ID:', config.entity_id);
1963
+ * console.log('ACS URL:', config.acs_url);
1964
+ * }
769
1965
  * ```
770
1966
  */
771
- get: async (orgSlug, userId) => {
1967
+ getConfig: async (orgSlug, serviceSlug) => {
772
1968
  const response = await this.http.get(
773
- `/api/organizations/${orgSlug}/users/${userId}`
1969
+ `/api/organizations/${orgSlug}/services/${serviceSlug}/saml`
774
1970
  );
775
1971
  return response.data;
776
1972
  },
777
1973
  /**
778
- * Revoke all active sessions for an end-user.
779
- * Requires admin or owner role.
780
- * This will force the user to re-authenticate.
1974
+ * Delete SAML IdP configuration and deactivate all certificates.
1975
+ * Requires 'owner' or 'admin' role.
1976
+ *
1977
+ * WARNING: This will break SSO for all third-party applications using this IdP.
781
1978
  *
782
1979
  * @param orgSlug Organization slug
783
- * @param userId User ID
784
- * @returns Response with number of revoked sessions
1980
+ * @param serviceSlug Service slug
785
1981
  *
786
1982
  * @example
787
1983
  * ```typescript
788
- * const result = await sso.organizations.endUsers.revokeSessions('acme-corp', 'user-id');
789
- * console.log(`Revoked ${result.revoked_count} sessions`);
1984
+ * await sso.services.saml.deleteConfig('acme-corp', 'main-app');
1985
+ * console.log('SAML IdP configuration deleted');
790
1986
  * ```
791
1987
  */
792
- revokeSessions: async (orgSlug, userId) => {
1988
+ deleteConfig: async (orgSlug, serviceSlug) => {
793
1989
  const response = await this.http.delete(
794
- `/api/organizations/${orgSlug}/users/${userId}/sessions`
1990
+ `/api/organizations/${orgSlug}/services/${serviceSlug}/saml`
795
1991
  );
796
1992
  return response.data;
797
- }
798
- };
799
- /**
800
- * BYOO (Bring Your Own OAuth) credential management
801
- */
802
- this.oauthCredentials = {
1993
+ },
803
1994
  /**
804
- * Set or update custom OAuth credentials for a provider.
805
- * This enables white-labeled authentication using the organization's
806
- * own OAuth application.
1995
+ * Generate a new SAML signing certificate for the IdP.
807
1996
  * Requires 'owner' or 'admin' role.
808
1997
  *
1998
+ * IMPORTANT: This automatically deactivates any existing active certificates.
1999
+ * Provide the returned certificate to your Service Provider during SAML setup.
2000
+ *
809
2001
  * @param orgSlug Organization slug
810
- * @param provider OAuth provider
811
- * @param payload OAuth credentials
812
- * @returns Created/updated credentials (without secret)
2002
+ * @param serviceSlug Service slug
2003
+ * @returns Certificate information including public key
813
2004
  *
814
2005
  * @example
815
2006
  * ```typescript
816
- * await sso.organizations.oauthCredentials.set('acme-corp', 'github', {
817
- * client_id: 'Iv1.abc123',
818
- * client_secret: 'secret-value'
819
- * });
2007
+ * const cert = await sso.services.saml.generateCertificate('acme-corp', 'main-app');
2008
+ * console.log('Certificate generated, valid until:', cert.valid_until);
2009
+ * console.log('Public certificate:\n', cert.public_key);
2010
+ * // Provide cert.public_key to your Service Provider
820
2011
  * ```
821
2012
  */
822
- set: async (orgSlug, provider, payload) => {
2013
+ generateCertificate: async (orgSlug, serviceSlug) => {
823
2014
  const response = await this.http.post(
824
- `/api/organizations/${orgSlug}/oauth-credentials/${provider}`,
825
- payload
2015
+ `/api/organizations/${orgSlug}/services/${serviceSlug}/saml/certificate`,
2016
+ {}
826
2017
  );
827
2018
  return response.data;
828
2019
  },
829
2020
  /**
830
- * Get the configured OAuth credentials for a provider.
831
- * The secret is never returned.
2021
+ * Get the active SAML signing certificate.
832
2022
  *
833
2023
  * @param orgSlug Organization slug
834
- * @param provider OAuth provider
835
- * @returns OAuth credentials (without secret)
2024
+ * @param serviceSlug Service slug
2025
+ * @returns Active certificate information
836
2026
  *
837
2027
  * @example
838
2028
  * ```typescript
839
- * const creds = await sso.organizations.oauthCredentials.get('acme-corp', 'github');
840
- * console.log(creds.client_id);
2029
+ * try {
2030
+ * const cert = await sso.services.saml.getCertificate('acme-corp', 'main-app');
2031
+ * console.log('Certificate expires:', cert.valid_until);
2032
+ * } catch (error) {
2033
+ * console.log('No active certificate - generate one first');
2034
+ * }
841
2035
  * ```
842
2036
  */
843
- get: async (orgSlug, provider) => {
2037
+ getCertificate: async (orgSlug, serviceSlug) => {
844
2038
  const response = await this.http.get(
845
- `/api/organizations/${orgSlug}/oauth-credentials/${provider}`
2039
+ `/api/organizations/${orgSlug}/services/${serviceSlug}/saml/certificate`
846
2040
  );
847
2041
  return response.data;
848
- }
849
- };
850
- }
851
- /**
852
- * Create a new organization (public endpoint).
853
- * The organization will be created with 'pending' status and requires
854
- * platform owner approval before becoming active.
855
- *
856
- * @param payload Organization creation payload
857
- * @returns Created organization with owner and membership details
858
- *
859
- * @example
860
- * ```typescript
861
- * const result = await sso.organizations.createPublic({
862
- * slug: 'acme-corp',
863
- * name: 'Acme Corporation',
864
- * owner_email: 'founder@acme.com'
865
- * });
866
- * ```
867
- */
868
- async createPublic(payload) {
869
- const response = await this.http.post("/api/organizations", payload);
870
- return response.data;
871
- }
872
- /**
873
- * List all organizations the authenticated user is a member of.
874
- *
875
- * @param params Optional query parameters for filtering and pagination
876
- * @returns Array of organization responses
877
- *
878
- * @example
879
- * ```typescript
880
- * const orgs = await sso.organizations.list({
881
- * status: 'active',
882
- * page: 1,
883
- * limit: 20
884
- * });
885
- * ```
886
- */
887
- async list(params) {
888
- const response = await this.http.get("/api/organizations", { params });
889
- return response.data;
890
- }
891
- /**
892
- * Get detailed information for a specific organization.
893
- *
894
- * @param orgSlug Organization slug
895
- * @returns Organization details
896
- *
897
- * @example
898
- * ```typescript
899
- * const org = await sso.organizations.get('acme-corp');
900
- * console.log(org.organization.name, org.membership_count);
901
- * ```
902
- */
903
- async get(orgSlug) {
904
- const response = await this.http.get(`/api/organizations/${orgSlug}`);
905
- return response.data;
906
- }
907
- /**
908
- * Update organization details.
909
- * Requires 'owner' or 'admin' role.
910
- *
911
- * @param orgSlug Organization slug
912
- * @param payload Update payload
913
- * @returns Updated organization details
914
- *
915
- * @example
916
- * ```typescript
917
- * const updated = await sso.organizations.update('acme-corp', {
918
- * name: 'Acme Corporation Inc.',
919
- * max_services: 20
920
- * });
921
- * ```
922
- */
923
- async update(orgSlug, payload) {
924
- const response = await this.http.patch(
925
- `/api/organizations/${orgSlug}`,
926
- payload
927
- );
928
- return response.data;
929
- }
930
- };
931
-
932
- // src/modules/services.ts
933
- var ServicesModule = class {
934
- constructor(http) {
935
- this.http = http;
936
- /**
937
- * Plan management methods
938
- */
939
- this.plans = {
2042
+ },
940
2043
  /**
941
- * Create a new subscription plan for a service.
942
- * Requires 'owner' or 'admin' role.
2044
+ * Get the SAML IdP metadata URL for this service.
2045
+ * This URL can be provided to Service Providers for automatic configuration.
943
2046
  *
2047
+ * @param baseURL SSO platform base URL
944
2048
  * @param orgSlug Organization slug
945
2049
  * @param serviceSlug Service slug
946
- * @param payload Plan creation payload
947
- * @returns Created plan
2050
+ * @returns Metadata URL
948
2051
  *
949
2052
  * @example
950
2053
  * ```typescript
951
- * const plan = await sso.services.plans.create('acme-corp', 'main-app', {
952
- * name: 'pro',
953
- * description: 'Pro tier with advanced features',
954
- * price_monthly: 29.99,
955
- * features: ['api-access', 'advanced-analytics', 'priority-support']
956
- * });
2054
+ * const metadataUrl = sso.services.saml.getMetadataUrl(
2055
+ * 'https://sso.example.com',
2056
+ * 'acme-corp',
2057
+ * 'main-app'
2058
+ * );
2059
+ * console.log('Provide this URL to your SP:', metadataUrl);
2060
+ * // https://sso.example.com/saml/acme-corp/main-app/metadata
957
2061
  * ```
958
2062
  */
959
- create: async (orgSlug, serviceSlug, payload) => {
960
- const response = await this.http.post(
961
- `/api/organizations/${orgSlug}/services/${serviceSlug}/plans`,
962
- payload
963
- );
964
- return response.data;
2063
+ getMetadataUrl: (baseURL, orgSlug, serviceSlug) => {
2064
+ return `${baseURL}/saml/${orgSlug}/${serviceSlug}/metadata`;
965
2065
  },
966
2066
  /**
967
- * List all plans for a service.
2067
+ * Get the SAML SSO endpoint URL for this service.
2068
+ * This is where Service Providers should redirect users to initiate SSO.
968
2069
  *
2070
+ * @param baseURL SSO platform base URL
969
2071
  * @param orgSlug Organization slug
970
2072
  * @param serviceSlug Service slug
971
- * @returns Array of plans
2073
+ * @returns SSO endpoint URL
972
2074
  *
973
2075
  * @example
974
2076
  * ```typescript
975
- * const plans = await sso.services.plans.list('acme-corp', 'main-app');
976
- * plans.forEach(plan => console.log(plan.name, plan.price_monthly));
2077
+ * const ssoUrl = sso.services.saml.getSsoUrl(
2078
+ * 'https://sso.example.com',
2079
+ * 'acme-corp',
2080
+ * 'main-app'
2081
+ * );
2082
+ * console.log('SSO endpoint:', ssoUrl);
2083
+ * // https://sso.example.com/saml/acme-corp/main-app/sso
977
2084
  * ```
978
2085
  */
979
- list: async (orgSlug, serviceSlug) => {
980
- const response = await this.http.get(
981
- `/api/organizations/${orgSlug}/services/${serviceSlug}/plans`
982
- );
983
- return response.data;
2086
+ getSsoUrl: (baseURL, orgSlug, serviceSlug) => {
2087
+ return `${baseURL}/saml/${orgSlug}/${serviceSlug}/sso`;
984
2088
  }
985
2089
  };
986
2090
  }
@@ -1327,6 +2431,97 @@ var PlatformModule = class {
1327
2431
  payload
1328
2432
  );
1329
2433
  return response.data;
2434
+ },
2435
+ /**
2436
+ * Delete an organization and all its associated data.
2437
+ * This is a destructive operation that cannot be undone.
2438
+ * Only platform owners can delete organizations.
2439
+ *
2440
+ * All related data will be cascaded deleted including:
2441
+ * - Members and invitations
2442
+ * - Services and plans
2443
+ * - Subscriptions
2444
+ * - OAuth credentials
2445
+ * - Audit logs
2446
+ *
2447
+ * @param orgId Organization ID
2448
+ * @returns Success confirmation
2449
+ *
2450
+ * @example
2451
+ * ```typescript
2452
+ * const result = await sso.platform.organizations.delete('org-id');
2453
+ * console.log(result.message); // 'Organization deleted successfully'
2454
+ * ```
2455
+ */
2456
+ delete: async (orgId) => {
2457
+ const response = await this.http.delete(
2458
+ `/api/platform/organizations/${orgId}`
2459
+ );
2460
+ return response.data;
2461
+ }
2462
+ };
2463
+ /**
2464
+ * User MFA management methods for platform administrators
2465
+ */
2466
+ this.users = {
2467
+ /**
2468
+ * Get MFA status for a specific user.
2469
+ *
2470
+ * @param userId The ID of the user
2471
+ * @returns MFA status information
2472
+ *
2473
+ * @example
2474
+ * ```typescript
2475
+ * const mfaStatus = await sso.platform.users.getMfaStatus('user-uuid-here');
2476
+ * console.log(mfaStatus.enabled, mfaStatus.has_backup_codes);
2477
+ * ```
2478
+ */
2479
+ getMfaStatus: async (userId) => {
2480
+ const response = await this.http.get(`/api/platform/users/${userId}/mfa/status`);
2481
+ return response.data;
2482
+ },
2483
+ /**
2484
+ * Search users by email address or user ID.
2485
+ *
2486
+ * @param query The search query (email or user ID)
2487
+ * @param limit Optional maximum number of results (default: 10, max: 50)
2488
+ * @returns Array of matching users
2489
+ *
2490
+ * @example
2491
+ * ```typescript
2492
+ * const users = await sso.platform.users.search('john@example.com');
2493
+ * console.log(users); // [{ id: 'user-uuid', email: 'john@example.com', ... }]
2494
+ *
2495
+ * // Search by user ID
2496
+ * const users = await sso.platform.users.search('user-uuid-here');
2497
+ *
2498
+ * // Limit results
2499
+ * const users = await sso.platform.users.search('john@', { limit: 5 });
2500
+ * ```
2501
+ */
2502
+ search: async (query, options) => {
2503
+ const params = {
2504
+ q: query.trim(),
2505
+ limit: options?.limit ? Math.min(options.limit, 50) : void 0
2506
+ };
2507
+ const response = await this.http.get("/api/platform/users/search", { params });
2508
+ return response.data;
2509
+ },
2510
+ /**
2511
+ * Force disable MFA for a user (emergency access).
2512
+ *
2513
+ * @param userId The ID of the user
2514
+ * @returns Success confirmation
2515
+ *
2516
+ * @example
2517
+ * ```typescript
2518
+ * await sso.platform.users.forceDisableMfa('user-uuid-here');
2519
+ * console.log('MFA disabled for user');
2520
+ * ```
2521
+ */
2522
+ forceDisableMfa: async (userId) => {
2523
+ const response = await this.http.delete(`/api/platform/users/${userId}/mfa`);
2524
+ return response.data;
1330
2525
  }
1331
2526
  };
1332
2527
  /**
@@ -1510,6 +2705,88 @@ var PlatformModule = class {
1510
2705
  }
1511
2706
  };
1512
2707
 
2708
+ // src/modules/serviceApi.ts
2709
+ var ServiceApiModule = class {
2710
+ constructor(http) {
2711
+ this.http = http;
2712
+ }
2713
+ /**
2714
+ * Create a new user
2715
+ * Requires 'write:users' permission on the API key
2716
+ *
2717
+ * @param request User creation request
2718
+ * @returns Created user
2719
+ */
2720
+ async createUser(request) {
2721
+ const response = await this.http.post("/api/service/users", request);
2722
+ return response.data;
2723
+ }
2724
+ /**
2725
+ * Update user details
2726
+ * Requires 'write:users' permission on the API key
2727
+ *
2728
+ * @param userId User ID to update
2729
+ * @param request User update request
2730
+ * @returns Updated user
2731
+ */
2732
+ async updateUser(userId, request) {
2733
+ const response = await this.http.patch(`/api/service/users/${userId}`, request);
2734
+ return response.data;
2735
+ }
2736
+ /**
2737
+ * Create a new subscription for a user
2738
+ * Requires 'write:subscriptions' permission on the API key
2739
+ *
2740
+ * @param request Subscription creation request
2741
+ * @returns Created subscription
2742
+ */
2743
+ async createSubscription(request) {
2744
+ const response = await this.http.post("/api/service/subscriptions", request);
2745
+ return response.data;
2746
+ }
2747
+ /**
2748
+ * Update a subscription for a user
2749
+ * Requires 'write:subscriptions' permission on the API key
2750
+ *
2751
+ * @param userId User ID whose subscription to update
2752
+ * @param request Subscription update request
2753
+ * @returns Updated subscription
2754
+ */
2755
+ async updateSubscription(userId, request) {
2756
+ const response = await this.http.patch(`/api/service/subscriptions/${userId}`, request);
2757
+ return response.data;
2758
+ }
2759
+ /**
2760
+ * Update service configuration
2761
+ * Requires 'write:service' permission on the API key
2762
+ *
2763
+ * @param request Service update request
2764
+ * @returns Updated service info
2765
+ */
2766
+ async updateServiceInfo(request) {
2767
+ const response = await this.http.patch("/api/service/info", request);
2768
+ return response.data;
2769
+ }
2770
+ /**
2771
+ * Delete a user
2772
+ * Requires 'delete:users' permission on the API key
2773
+ *
2774
+ * @param userId User ID to delete
2775
+ */
2776
+ async deleteUser(userId) {
2777
+ await this.http.delete(`/api/service/users/${userId}`);
2778
+ }
2779
+ /**
2780
+ * Delete a subscription for a user
2781
+ * Requires 'delete:subscriptions' permission on the API key
2782
+ *
2783
+ * @param userId User ID whose subscription to delete
2784
+ */
2785
+ async deleteSubscription(userId) {
2786
+ await this.http.delete(`/api/service/subscriptions/${userId}`);
2787
+ }
2788
+ };
2789
+
1513
2790
  // src/client.ts
1514
2791
  var SsoClient = class {
1515
2792
  constructor(options) {
@@ -1517,6 +2794,9 @@ var SsoClient = class {
1517
2794
  if (options.token) {
1518
2795
  this.setAuthToken(options.token);
1519
2796
  }
2797
+ if (options.apiKey) {
2798
+ this.setApiKey(options.apiKey);
2799
+ }
1520
2800
  this.analytics = new AnalyticsModule(this.http);
1521
2801
  this.auth = new AuthModule(this.http);
1522
2802
  this.user = new UserModule(this.http);
@@ -1524,6 +2804,7 @@ var SsoClient = class {
1524
2804
  this.services = new ServicesModule(this.http);
1525
2805
  this.invitations = new InvitationsModule(this.http);
1526
2806
  this.platform = new PlatformModule(this.http);
2807
+ this.serviceApi = new ServiceApiModule(this.http);
1527
2808
  }
1528
2809
  /**
1529
2810
  * Sets the JWT for all subsequent authenticated requests.
@@ -1547,6 +2828,28 @@ var SsoClient = class {
1547
2828
  delete this.http.defaults.headers.common["Authorization"];
1548
2829
  }
1549
2830
  }
2831
+ /**
2832
+ * Sets the API key for service-to-service authentication.
2833
+ * Pass null to clear the API key.
2834
+ *
2835
+ * @param apiKey The API key string, or null to clear
2836
+ *
2837
+ * @example
2838
+ * ```typescript
2839
+ * // Set API key
2840
+ * sso.setApiKey('sk_live_abcd1234...');
2841
+ *
2842
+ * // Clear API key
2843
+ * sso.setApiKey(null);
2844
+ * ```
2845
+ */
2846
+ setApiKey(apiKey) {
2847
+ if (apiKey) {
2848
+ this.http.defaults.headers.common["X-Api-Key"] = apiKey;
2849
+ } else {
2850
+ delete this.http.defaults.headers.common["X-Api-Key"];
2851
+ }
2852
+ }
1550
2853
  /**
1551
2854
  * Gets the current base URL
1552
2855
  */
@@ -1560,6 +2863,7 @@ var SsoClient = class {
1560
2863
  InvitationsModule,
1561
2864
  OrganizationsModule,
1562
2865
  PlatformModule,
2866
+ ServiceApiModule,
1563
2867
  ServicesModule,
1564
2868
  SsoApiError,
1565
2869
  SsoClient,