@drmhse/sso-sdk 0.2.3 → 0.2.6

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