@bagelink/auth 1.12.5 → 1.12.8

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/api.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { RegisterRequest, UpdateAccountRequest, ChangePasswordRequest, ForgotPasswordRequest, ResetPasswordRequest, SendVerificationRequest, VerifyEmailRequest, AuthenticationAccount, PasswordLoginRequest, EmailTokenSendRequest, EmailTokenVerifyRequest, OTPSendRequest, OTPVerifyRequest, SSOLoginRequest, LoginResponse, RegisterResponse, LogoutResponse, GetMeResponse, UpdateMeResponse, DeleteMeResponse, ChangePasswordResponse, ForgotPasswordResponse, ResetPasswordResponse, VerifyResetTokenResponse, SendVerificationResponse, VerifyEmailResponse, RefreshSessionResponse, GetSessionsResponse, DeleteSessionResponse, DeleteAllSessionsResponse, CleanupSessionsResponse, GetMethodsResponse, GetAuthStatusResponse, SendEmailTokenResponse, VerifyEmailTokenResponse, SendOTPResponse, VerifyOTPResponse, LegacySSOLoginResponse, SSOProvider, SSOInitiateRequest, SSOCallbackRequest, SSOLinkRequest, InitiateSSOResponse, CallbackSSOResponse, LinkSSOResponse, UnlinkSSOResponse, GetTenantsResponse } from './types';
1
+ import { RegisterRequest, UpdateAccountRequest, ChangePasswordRequest, ForgotPasswordRequest, ResetPasswordRequest, SendVerificationRequest, VerifyEmailRequest, AuthenticationAccount, PasswordLoginRequest, EmailTokenSendRequest, EmailTokenVerifyRequest, OTPSendRequest, OTPVerifyRequest, SSOLoginRequest, LoginResponse, RegisterResponse, LogoutResponse, GetMeResponse, UpdateMeResponse, DeleteMeResponse, ChangePasswordResponse, ForgotPasswordResponse, ResetPasswordResponse, VerifyResetTokenResponse, SendVerificationResponse, VerifyEmailResponse, RefreshSessionResponse, GetSessionsResponse, DeleteSessionResponse, DeleteAllSessionsResponse, CleanupSessionsResponse, GetMethodsResponse, GetAuthStatusResponse, SendEmailTokenResponse, VerifyEmailTokenResponse, SendOTPResponse, VerifyOTPResponse, LegacySSOLoginResponse, SSOProvider, SSOInitiateRequest, SSOCallbackRequest, SSOLinkRequest, InitiateSSOResponse, CallbackSSOResponse, LinkSSOResponse, UnlinkSSOResponse, GetTenantsResponse, GetTenantResponse, CreateTenantResponse, UpdateTenantResponse, DeleteTenantResponse, GetTenantMembersResponse, AddTenantMemberResponse, UpdateTenantMemberResponse, DeleteTenantMemberResponse, GetTenantRolesResponse, CreateInvitationResponse, GetInvitationResponse, AcceptInvitationResponse, CreateTenantRequest, UpdateTenantRequest, AddMemberRequest, UpdateMemberRequest, CreateInvitationRequest, AcceptInvitationRequest } from './types';
2
2
  export declare class AuthApi {
3
3
  private api;
4
4
  private currentTenantId;
@@ -129,4 +129,57 @@ export declare class AuthApi {
129
129
  * Get list of tenants the authenticated user belongs to
130
130
  */
131
131
  getTenants(): Promise<GetTenantsResponse>;
132
+ /**
133
+ * Get a single tenant by ID or slug
134
+ */
135
+ getTenant(idOrSlug: string): Promise<GetTenantResponse>;
136
+ /**
137
+ * Create a new tenant (caller is auto-added as admin)
138
+ */
139
+ createTenant(data: CreateTenantRequest): Promise<CreateTenantResponse>;
140
+ /**
141
+ * Update a tenant
142
+ */
143
+ updateTenant(tenantId: string, data: UpdateTenantRequest): Promise<UpdateTenantResponse>;
144
+ /**
145
+ * Delete a tenant
146
+ */
147
+ deleteTenant(tenantId: string): Promise<DeleteTenantResponse>;
148
+ /**
149
+ * List members of a tenant
150
+ */
151
+ getTenantMembers(tenantId: string, status?: string): Promise<GetTenantMembersResponse>;
152
+ /**
153
+ * Add a member to a tenant by identity_id
154
+ */
155
+ addTenantMember(tenantId: string, data: AddMemberRequest): Promise<AddTenantMemberResponse>;
156
+ /**
157
+ * Update a tenant member's roles/status/metadata
158
+ */
159
+ updateTenantMember(tenantId: string, identityId: string, data: UpdateMemberRequest): Promise<UpdateTenantMemberResponse>;
160
+ /**
161
+ * Activate a pending membership
162
+ */
163
+ activateTenantMember(tenantId: string, identityId: string): Promise<AddTenantMemberResponse>;
164
+ /**
165
+ * Remove a member from a tenant
166
+ */
167
+ removeTenantMember(tenantId: string, identityId: string): Promise<DeleteTenantMemberResponse>;
168
+ /**
169
+ * List available roles
170
+ */
171
+ getTenantRoles(): Promise<GetTenantRolesResponse>;
172
+ /**
173
+ * Create an invitation for a new user to join a tenant
174
+ * Requires X-Tenant-ID header (set via setTenantId)
175
+ */
176
+ createInvitation(data: CreateInvitationRequest): Promise<CreateInvitationResponse>;
177
+ /**
178
+ * Get invitation metadata by token (no auth required)
179
+ */
180
+ getInvitation(token: string): Promise<GetInvitationResponse>;
181
+ /**
182
+ * Accept an invitation — creates TenantMembership for the authenticated user
183
+ */
184
+ acceptInvitation(token: string, data?: AcceptInvitationRequest): Promise<AcceptInvitationResponse>;
132
185
  }
package/dist/index.cjs CHANGED
@@ -299,6 +299,91 @@ class AuthApi {
299
299
  async getTenants() {
300
300
  return this.api.get("tenants");
301
301
  }
302
+ /**
303
+ * Get a single tenant by ID or slug
304
+ */
305
+ async getTenant(idOrSlug) {
306
+ return this.api.get(`tenants/${idOrSlug}`);
307
+ }
308
+ /**
309
+ * Create a new tenant (caller is auto-added as admin)
310
+ */
311
+ async createTenant(data) {
312
+ return this.api.post("tenants/", data);
313
+ }
314
+ /**
315
+ * Update a tenant
316
+ */
317
+ async updateTenant(tenantId, data) {
318
+ return this.api.put(`tenants/${tenantId}`, data);
319
+ }
320
+ /**
321
+ * Delete a tenant
322
+ */
323
+ async deleteTenant(tenantId) {
324
+ return this.api.delete(`tenants/${tenantId}`);
325
+ }
326
+ // ============================================
327
+ // Tenant Member Methods
328
+ // ============================================
329
+ /**
330
+ * List members of a tenant
331
+ */
332
+ async getTenantMembers(tenantId, status) {
333
+ return this.api.get(`tenants/${tenantId}/members`, { params: status ? { status } : void 0 });
334
+ }
335
+ /**
336
+ * Add a member to a tenant by identity_id
337
+ */
338
+ async addTenantMember(tenantId, data) {
339
+ return this.api.post(`tenants/${tenantId}/members`, data);
340
+ }
341
+ /**
342
+ * Update a tenant member's roles/status/metadata
343
+ */
344
+ async updateTenantMember(tenantId, identityId, data) {
345
+ return this.api.put(`tenants/${tenantId}/members/${identityId}`, data);
346
+ }
347
+ /**
348
+ * Activate a pending membership
349
+ */
350
+ async activateTenantMember(tenantId, identityId) {
351
+ return this.api.post(`tenants/${tenantId}/members/${identityId}/activate`, {});
352
+ }
353
+ /**
354
+ * Remove a member from a tenant
355
+ */
356
+ async removeTenantMember(tenantId, identityId) {
357
+ return this.api.delete(`tenants/${tenantId}/members/${identityId}`);
358
+ }
359
+ /**
360
+ * List available roles
361
+ */
362
+ async getTenantRoles() {
363
+ return this.api.get("tenants/roles");
364
+ }
365
+ // ============================================
366
+ // Invitation Methods
367
+ // ============================================
368
+ /**
369
+ * Create an invitation for a new user to join a tenant
370
+ * Requires X-Tenant-ID header (set via setTenantId)
371
+ */
372
+ async createInvitation(data) {
373
+ return this.api.post("invitations/", data);
374
+ }
375
+ /**
376
+ * Get invitation metadata by token (no auth required)
377
+ */
378
+ async getInvitation(token) {
379
+ return this.api.get(`invitations/${token}`);
380
+ }
381
+ /**
382
+ * Accept an invitation — creates TenantMembership for the authenticated user
383
+ */
384
+ async acceptInvitation(token, data) {
385
+ return this.api.post(`invitations/${token}/accept`, data ?? {});
386
+ }
302
387
  }
303
388
  const INTAKE_WORKFLOW_ID = "fdba1933-0964-4850-b52a-7a4324175790";
304
389
  const DEFAULT_AGENT_ID = "fdba1933-0964-4850-b52a-7a4324175790";
@@ -1125,6 +1210,60 @@ function useAuth() {
1125
1210
  function getCurrentTenant() {
1126
1211
  return currentTenant.value;
1127
1212
  }
1213
+ async function createTenant(data) {
1214
+ const { data: tenant } = await api.createTenant(data);
1215
+ await loadTenants();
1216
+ return tenant;
1217
+ }
1218
+ async function updateTenant(tenantId, data) {
1219
+ const { data: tenant } = await api.updateTenant(tenantId, data);
1220
+ await loadTenants();
1221
+ return tenant;
1222
+ }
1223
+ async function deleteTenant(tenantId) {
1224
+ var _a;
1225
+ await api.deleteTenant(tenantId);
1226
+ if (((_a = currentTenant.value) == null ? void 0 : _a.id) === tenantId) {
1227
+ currentTenant.value = null;
1228
+ api.setTenantId(null);
1229
+ }
1230
+ await loadTenants();
1231
+ }
1232
+ async function getTenantMembers(tenantId, status) {
1233
+ const { data } = await api.getTenantMembers(tenantId, status);
1234
+ return data;
1235
+ }
1236
+ async function addTenantMember(tenantId, member) {
1237
+ const { data } = await api.addTenantMember(tenantId, member);
1238
+ return data;
1239
+ }
1240
+ async function updateTenantMember(tenantId, identityId, updates) {
1241
+ const { data } = await api.updateTenantMember(tenantId, identityId, updates);
1242
+ return data;
1243
+ }
1244
+ async function activateTenantMember(tenantId, identityId) {
1245
+ const { data } = await api.activateTenantMember(tenantId, identityId);
1246
+ return data;
1247
+ }
1248
+ async function removeTenantMember(tenantId, identityId) {
1249
+ await api.removeTenantMember(tenantId, identityId);
1250
+ }
1251
+ async function getTenantRoles() {
1252
+ const { data } = await api.getTenantRoles();
1253
+ return data;
1254
+ }
1255
+ async function createInvitation(data) {
1256
+ const { data: invitation } = await api.createInvitation(data);
1257
+ return invitation;
1258
+ }
1259
+ async function getInvitation(token) {
1260
+ const { data } = await api.getInvitation(token);
1261
+ return data;
1262
+ }
1263
+ async function acceptInvitation(token, data) {
1264
+ await api.acceptInvitation(token, data);
1265
+ await checkAuth();
1266
+ }
1128
1267
  async function signup(newUser) {
1129
1268
  const hasPassword = newUser.password !== void 0 && newUser.password.length > 0;
1130
1269
  if (hasPassword && newUser.password !== newUser.confirmPassword) {
@@ -1261,7 +1400,22 @@ function useAuth() {
1261
1400
  // Multi-Tenancy Actions
1262
1401
  loadTenants,
1263
1402
  setTenant,
1264
- switchTenant
1403
+ switchTenant,
1404
+ // Tenant CRUD (requires tenancy: true)
1405
+ createTenant,
1406
+ updateTenant,
1407
+ deleteTenant,
1408
+ // Tenant Members
1409
+ getTenantMembers,
1410
+ addTenantMember,
1411
+ updateTenantMember,
1412
+ activateTenantMember,
1413
+ removeTenantMember,
1414
+ getTenantRoles,
1415
+ // Invitations
1416
+ createInvitation,
1417
+ getInvitation,
1418
+ acceptInvitation
1265
1419
  };
1266
1420
  }
1267
1421
  const useAuth$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
package/dist/index.mjs CHANGED
@@ -297,6 +297,91 @@ class AuthApi {
297
297
  async getTenants() {
298
298
  return this.api.get("tenants");
299
299
  }
300
+ /**
301
+ * Get a single tenant by ID or slug
302
+ */
303
+ async getTenant(idOrSlug) {
304
+ return this.api.get(`tenants/${idOrSlug}`);
305
+ }
306
+ /**
307
+ * Create a new tenant (caller is auto-added as admin)
308
+ */
309
+ async createTenant(data) {
310
+ return this.api.post("tenants/", data);
311
+ }
312
+ /**
313
+ * Update a tenant
314
+ */
315
+ async updateTenant(tenantId, data) {
316
+ return this.api.put(`tenants/${tenantId}`, data);
317
+ }
318
+ /**
319
+ * Delete a tenant
320
+ */
321
+ async deleteTenant(tenantId) {
322
+ return this.api.delete(`tenants/${tenantId}`);
323
+ }
324
+ // ============================================
325
+ // Tenant Member Methods
326
+ // ============================================
327
+ /**
328
+ * List members of a tenant
329
+ */
330
+ async getTenantMembers(tenantId, status) {
331
+ return this.api.get(`tenants/${tenantId}/members`, { params: status ? { status } : void 0 });
332
+ }
333
+ /**
334
+ * Add a member to a tenant by identity_id
335
+ */
336
+ async addTenantMember(tenantId, data) {
337
+ return this.api.post(`tenants/${tenantId}/members`, data);
338
+ }
339
+ /**
340
+ * Update a tenant member's roles/status/metadata
341
+ */
342
+ async updateTenantMember(tenantId, identityId, data) {
343
+ return this.api.put(`tenants/${tenantId}/members/${identityId}`, data);
344
+ }
345
+ /**
346
+ * Activate a pending membership
347
+ */
348
+ async activateTenantMember(tenantId, identityId) {
349
+ return this.api.post(`tenants/${tenantId}/members/${identityId}/activate`, {});
350
+ }
351
+ /**
352
+ * Remove a member from a tenant
353
+ */
354
+ async removeTenantMember(tenantId, identityId) {
355
+ return this.api.delete(`tenants/${tenantId}/members/${identityId}`);
356
+ }
357
+ /**
358
+ * List available roles
359
+ */
360
+ async getTenantRoles() {
361
+ return this.api.get("tenants/roles");
362
+ }
363
+ // ============================================
364
+ // Invitation Methods
365
+ // ============================================
366
+ /**
367
+ * Create an invitation for a new user to join a tenant
368
+ * Requires X-Tenant-ID header (set via setTenantId)
369
+ */
370
+ async createInvitation(data) {
371
+ return this.api.post("invitations/", data);
372
+ }
373
+ /**
374
+ * Get invitation metadata by token (no auth required)
375
+ */
376
+ async getInvitation(token) {
377
+ return this.api.get(`invitations/${token}`);
378
+ }
379
+ /**
380
+ * Accept an invitation — creates TenantMembership for the authenticated user
381
+ */
382
+ async acceptInvitation(token, data) {
383
+ return this.api.post(`invitations/${token}/accept`, data ?? {});
384
+ }
300
385
  }
301
386
  const INTAKE_WORKFLOW_ID = "fdba1933-0964-4850-b52a-7a4324175790";
302
387
  const DEFAULT_AGENT_ID = "fdba1933-0964-4850-b52a-7a4324175790";
@@ -1123,6 +1208,60 @@ function useAuth() {
1123
1208
  function getCurrentTenant() {
1124
1209
  return currentTenant.value;
1125
1210
  }
1211
+ async function createTenant(data) {
1212
+ const { data: tenant } = await api.createTenant(data);
1213
+ await loadTenants();
1214
+ return tenant;
1215
+ }
1216
+ async function updateTenant(tenantId, data) {
1217
+ const { data: tenant } = await api.updateTenant(tenantId, data);
1218
+ await loadTenants();
1219
+ return tenant;
1220
+ }
1221
+ async function deleteTenant(tenantId) {
1222
+ var _a;
1223
+ await api.deleteTenant(tenantId);
1224
+ if (((_a = currentTenant.value) == null ? void 0 : _a.id) === tenantId) {
1225
+ currentTenant.value = null;
1226
+ api.setTenantId(null);
1227
+ }
1228
+ await loadTenants();
1229
+ }
1230
+ async function getTenantMembers(tenantId, status) {
1231
+ const { data } = await api.getTenantMembers(tenantId, status);
1232
+ return data;
1233
+ }
1234
+ async function addTenantMember(tenantId, member) {
1235
+ const { data } = await api.addTenantMember(tenantId, member);
1236
+ return data;
1237
+ }
1238
+ async function updateTenantMember(tenantId, identityId, updates) {
1239
+ const { data } = await api.updateTenantMember(tenantId, identityId, updates);
1240
+ return data;
1241
+ }
1242
+ async function activateTenantMember(tenantId, identityId) {
1243
+ const { data } = await api.activateTenantMember(tenantId, identityId);
1244
+ return data;
1245
+ }
1246
+ async function removeTenantMember(tenantId, identityId) {
1247
+ await api.removeTenantMember(tenantId, identityId);
1248
+ }
1249
+ async function getTenantRoles() {
1250
+ const { data } = await api.getTenantRoles();
1251
+ return data;
1252
+ }
1253
+ async function createInvitation(data) {
1254
+ const { data: invitation } = await api.createInvitation(data);
1255
+ return invitation;
1256
+ }
1257
+ async function getInvitation(token) {
1258
+ const { data } = await api.getInvitation(token);
1259
+ return data;
1260
+ }
1261
+ async function acceptInvitation(token, data) {
1262
+ await api.acceptInvitation(token, data);
1263
+ await checkAuth();
1264
+ }
1126
1265
  async function signup(newUser) {
1127
1266
  const hasPassword = newUser.password !== void 0 && newUser.password.length > 0;
1128
1267
  if (hasPassword && newUser.password !== newUser.confirmPassword) {
@@ -1259,7 +1398,22 @@ function useAuth() {
1259
1398
  // Multi-Tenancy Actions
1260
1399
  loadTenants,
1261
1400
  setTenant,
1262
- switchTenant
1401
+ switchTenant,
1402
+ // Tenant CRUD (requires tenancy: true)
1403
+ createTenant,
1404
+ updateTenant,
1405
+ deleteTenant,
1406
+ // Tenant Members
1407
+ getTenantMembers,
1408
+ addTenantMember,
1409
+ updateTenantMember,
1410
+ activateTenantMember,
1411
+ removeTenantMember,
1412
+ getTenantRoles,
1413
+ // Invitations
1414
+ createInvitation,
1415
+ getInvitation,
1416
+ acceptInvitation
1263
1417
  };
1264
1418
  }
1265
1419
  const useAuth$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
package/dist/types.d.ts CHANGED
@@ -36,6 +36,74 @@ export interface TenantInfo {
36
36
  created_at: string;
37
37
  updated_at: string;
38
38
  }
39
+ export interface CreateTenantRequest {
40
+ name: string;
41
+ slug?: string;
42
+ settings?: Record<string, any>;
43
+ }
44
+ export interface UpdateTenantRequest {
45
+ name?: string;
46
+ slug?: string;
47
+ settings?: Record<string, any>;
48
+ status?: TenantStatus;
49
+ }
50
+ export type MemberStatus = 'pending' | 'active' | 'inactive' | 'suspended';
51
+ export interface TenantMember {
52
+ identity_id: string;
53
+ tenant_id: string;
54
+ roles: string[];
55
+ status: MemberStatus;
56
+ metadata: Record<string, any> | null;
57
+ created_at: string;
58
+ updated_at: string;
59
+ }
60
+ export interface AddMemberRequest {
61
+ identity_id: string;
62
+ roles?: string[];
63
+ status?: MemberStatus;
64
+ }
65
+ export interface UpdateMemberRequest {
66
+ roles?: string[];
67
+ status?: MemberStatus;
68
+ metadata?: Record<string, any>;
69
+ }
70
+ export type InvitationStatus = 'pending' | 'accepted' | 'expired' | 'revoked';
71
+ export interface TenantInvitation {
72
+ id: string;
73
+ tenant_id: string;
74
+ email: string;
75
+ role: string;
76
+ status: InvitationStatus;
77
+ created_at: string;
78
+ expires_at: string | null;
79
+ }
80
+ export interface CreateInvitationRequest {
81
+ email: string;
82
+ role?: string;
83
+ message?: string;
84
+ }
85
+ export interface AcceptInvitationRequest {
86
+ first_name: string;
87
+ last_name: string;
88
+ password: string;
89
+ }
90
+ export type GetTenantsResponse = AxiosResponse<TenantInfo[]>;
91
+ export type GetTenantResponse = AxiosResponse<TenantInfo>;
92
+ export type CreateTenantResponse = AxiosResponse<TenantInfo>;
93
+ export type UpdateTenantResponse = AxiosResponse<TenantInfo>;
94
+ export type DeleteTenantResponse = AxiosResponse<MessageResponse>;
95
+ export type GetTenantMembersResponse = AxiosResponse<TenantMember[]>;
96
+ export type AddTenantMemberResponse = AxiosResponse<TenantMember>;
97
+ export type UpdateTenantMemberResponse = AxiosResponse<TenantMember>;
98
+ export type DeleteTenantMemberResponse = AxiosResponse<MessageResponse>;
99
+ export type GetTenantRolesResponse = AxiosResponse<string[]>;
100
+ export type CreateInvitationResponse = AxiosResponse<TenantInvitation>;
101
+ export type GetInvitationResponse = AxiosResponse<{
102
+ email: string;
103
+ first_name?: string | null;
104
+ last_name?: string | null;
105
+ }>;
106
+ export type AcceptInvitationResponse = AxiosResponse<MessageResponse>;
39
107
  export type AuthenticationMethodType = 'password' | 'email_token' | 'sso' | 'otp';
40
108
  export type SSOProvider = 'google' | 'microsoft' | 'github' | 'okta' | 'apple' | 'facebook' | 'custom';
41
109
  export interface AuthenticationAccount {
@@ -298,7 +366,6 @@ export type InitiateSSOResponse = AxiosResponse<SSOInitiateResponse>;
298
366
  export type CallbackSSOResponse = AxiosResponse<SSOCallbackResponse>;
299
367
  export type LinkSSOResponse = AxiosResponse<SSOLinkResponse>;
300
368
  export type UnlinkSSOResponse = AxiosResponse<SSOUnlinkResponse>;
301
- export type GetTenantsResponse = AxiosResponse<TenantInfo[]>;
302
369
  export type GetAuthStatusResponse = AxiosResponse<AuthStatusResponse>;
303
370
  export type SendEmailTokenResponse = AxiosResponse<AuthenticationResponse>;
304
371
  export type VerifyEmailTokenResponse = AxiosResponse<AuthenticationResponse>;
package/dist/useAuth.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { App, ObjectPlugin } from 'vue';
2
- import { AccountInfo, User, NewUser, UpdatePasswordForm, UpdateAccountRequest, AuthEventMap, SSOProvider, SSOInitiateRequest, SSOCallbackRequest, SSOLinkRequest, TenantInfo, AuthState } from './types';
2
+ import { AccountInfo, User, NewUser, UpdatePasswordForm, UpdateAccountRequest, AuthEventMap, SSOProvider, SSOInitiateRequest, SSOCallbackRequest, SSOLinkRequest, TenantInfo, CreateTenantRequest, UpdateTenantRequest, AddMemberRequest, UpdateMemberRequest, CreateInvitationRequest, AcceptInvitationRequest, AuthState } from './types';
3
3
  import { RedirectConfig, NormalizedRedirectConfig } from './types/redirect';
4
4
  interface InitParams {
5
5
  baseURL: string;
@@ -194,5 +194,21 @@ export declare function useAuth(): {
194
194
  loadTenants: () => Promise<TenantInfo[]>;
195
195
  setTenant: (tenantId: string | null) => void;
196
196
  switchTenant: (tenantId: string) => void;
197
+ createTenant: (data: CreateTenantRequest) => Promise<TenantInfo>;
198
+ updateTenant: (tenantId: string, data: UpdateTenantRequest) => Promise<TenantInfo>;
199
+ deleteTenant: (tenantId: string) => Promise<void>;
200
+ getTenantMembers: (tenantId: string, status?: string) => Promise<import('./types').TenantMember[]>;
201
+ addTenantMember: (tenantId: string, member: AddMemberRequest) => Promise<import('./types').TenantMember>;
202
+ updateTenantMember: (tenantId: string, identityId: string, updates: UpdateMemberRequest) => Promise<import('./types').TenantMember>;
203
+ activateTenantMember: (tenantId: string, identityId: string) => Promise<import('./types').TenantMember>;
204
+ removeTenantMember: (tenantId: string, identityId: string) => Promise<void>;
205
+ getTenantRoles: () => Promise<string[]>;
206
+ createInvitation: (data: CreateInvitationRequest) => Promise<import('./types').TenantInvitation>;
207
+ getInvitation: (token: string) => Promise<{
208
+ email: string;
209
+ first_name?: string | null;
210
+ last_name?: string | null;
211
+ }>;
212
+ acceptInvitation: (token: string, data?: AcceptInvitationRequest) => Promise<void>;
197
213
  };
198
214
  export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/auth",
3
3
  "type": "module",
4
- "version": "1.12.5",
4
+ "version": "1.12.8",
5
5
  "description": "Bagelink auth package",
6
6
  "author": {
7
7
  "name": "Bagel Studio",
package/src/api.ts CHANGED
@@ -47,6 +47,24 @@ import type {
47
47
  LinkSSOResponse,
48
48
  UnlinkSSOResponse,
49
49
  GetTenantsResponse,
50
+ GetTenantResponse,
51
+ CreateTenantResponse,
52
+ UpdateTenantResponse,
53
+ DeleteTenantResponse,
54
+ GetTenantMembersResponse,
55
+ AddTenantMemberResponse,
56
+ UpdateTenantMemberResponse,
57
+ DeleteTenantMemberResponse,
58
+ GetTenantRolesResponse,
59
+ CreateInvitationResponse,
60
+ GetInvitationResponse,
61
+ AcceptInvitationResponse,
62
+ CreateTenantRequest,
63
+ UpdateTenantRequest,
64
+ AddMemberRequest,
65
+ UpdateMemberRequest,
66
+ CreateInvitationRequest,
67
+ AcceptInvitationRequest,
50
68
  } from './types'
51
69
  import { createAxiosInstance } from './utils'
52
70
 
@@ -336,4 +354,104 @@ export class AuthApi {
336
354
  async getTenants(): Promise<GetTenantsResponse> {
337
355
  return this.api.get('tenants')
338
356
  }
357
+
358
+ /**
359
+ * Get a single tenant by ID or slug
360
+ */
361
+ async getTenant(idOrSlug: string): Promise<GetTenantResponse> {
362
+ return this.api.get(`tenants/${idOrSlug}`)
363
+ }
364
+
365
+ /**
366
+ * Create a new tenant (caller is auto-added as admin)
367
+ */
368
+ async createTenant(data: CreateTenantRequest): Promise<CreateTenantResponse> {
369
+ return this.api.post('tenants/', data)
370
+ }
371
+
372
+ /**
373
+ * Update a tenant
374
+ */
375
+ async updateTenant(tenantId: string, data: UpdateTenantRequest): Promise<UpdateTenantResponse> {
376
+ return this.api.put(`tenants/${tenantId}`, data)
377
+ }
378
+
379
+ /**
380
+ * Delete a tenant
381
+ */
382
+ async deleteTenant(tenantId: string): Promise<DeleteTenantResponse> {
383
+ return this.api.delete(`tenants/${tenantId}`)
384
+ }
385
+
386
+ // ============================================
387
+ // Tenant Member Methods
388
+ // ============================================
389
+
390
+ /**
391
+ * List members of a tenant
392
+ */
393
+ async getTenantMembers(tenantId: string, status?: string): Promise<GetTenantMembersResponse> {
394
+ return this.api.get(`tenants/${tenantId}/members`, { params: status ? { status } : undefined })
395
+ }
396
+
397
+ /**
398
+ * Add a member to a tenant by identity_id
399
+ */
400
+ async addTenantMember(tenantId: string, data: AddMemberRequest): Promise<AddTenantMemberResponse> {
401
+ return this.api.post(`tenants/${tenantId}/members`, data)
402
+ }
403
+
404
+ /**
405
+ * Update a tenant member's roles/status/metadata
406
+ */
407
+ async updateTenantMember(tenantId: string, identityId: string, data: UpdateMemberRequest): Promise<UpdateTenantMemberResponse> {
408
+ return this.api.put(`tenants/${tenantId}/members/${identityId}`, data)
409
+ }
410
+
411
+ /**
412
+ * Activate a pending membership
413
+ */
414
+ async activateTenantMember(tenantId: string, identityId: string): Promise<AddTenantMemberResponse> {
415
+ return this.api.post(`tenants/${tenantId}/members/${identityId}/activate`, {})
416
+ }
417
+
418
+ /**
419
+ * Remove a member from a tenant
420
+ */
421
+ async removeTenantMember(tenantId: string, identityId: string): Promise<DeleteTenantMemberResponse> {
422
+ return this.api.delete(`tenants/${tenantId}/members/${identityId}`)
423
+ }
424
+
425
+ /**
426
+ * List available roles
427
+ */
428
+ async getTenantRoles(): Promise<GetTenantRolesResponse> {
429
+ return this.api.get('tenants/roles')
430
+ }
431
+
432
+ // ============================================
433
+ // Invitation Methods
434
+ // ============================================
435
+
436
+ /**
437
+ * Create an invitation for a new user to join a tenant
438
+ * Requires X-Tenant-ID header (set via setTenantId)
439
+ */
440
+ async createInvitation(data: CreateInvitationRequest): Promise<CreateInvitationResponse> {
441
+ return this.api.post('invitations/', data)
442
+ }
443
+
444
+ /**
445
+ * Get invitation metadata by token (no auth required)
446
+ */
447
+ async getInvitation(token: string): Promise<GetInvitationResponse> {
448
+ return this.api.get(`invitations/${token}`)
449
+ }
450
+
451
+ /**
452
+ * Accept an invitation — creates TenantMembership for the authenticated user
453
+ */
454
+ async acceptInvitation(token: string, data?: AcceptInvitationRequest): Promise<AcceptInvitationResponse> {
455
+ return this.api.post(`invitations/${token}/accept`, data ?? {})
456
+ }
339
457
  }
package/src/types.ts CHANGED
@@ -56,6 +56,87 @@ export interface TenantInfo {
56
56
  updated_at: string
57
57
  }
58
58
 
59
+ export interface CreateTenantRequest {
60
+ name: string
61
+ slug?: string
62
+ settings?: Record<string, any>
63
+ }
64
+
65
+ export interface UpdateTenantRequest {
66
+ name?: string
67
+ slug?: string
68
+ settings?: Record<string, any>
69
+ status?: TenantStatus
70
+ }
71
+
72
+ // ─── Tenant Membership ────────────────────────────────────────────────────────
73
+
74
+ export type MemberStatus = 'pending' | 'active' | 'inactive' | 'suspended'
75
+
76
+ export interface TenantMember {
77
+ identity_id: string
78
+ tenant_id: string
79
+ roles: string[]
80
+ status: MemberStatus
81
+ metadata: Record<string, any> | null
82
+ created_at: string
83
+ updated_at: string
84
+ }
85
+
86
+ export interface AddMemberRequest {
87
+ identity_id: string
88
+ roles?: string[]
89
+ status?: MemberStatus
90
+ }
91
+
92
+ export interface UpdateMemberRequest {
93
+ roles?: string[]
94
+ status?: MemberStatus
95
+ metadata?: Record<string, any>
96
+ }
97
+
98
+ // ─── Invitations ──────────────────────────────────────────────────────────────
99
+
100
+ export type InvitationStatus = 'pending' | 'accepted' | 'expired' | 'revoked'
101
+
102
+ export interface TenantInvitation {
103
+ id: string
104
+ tenant_id: string
105
+ email: string
106
+ role: string
107
+ status: InvitationStatus
108
+ created_at: string
109
+ expires_at: string | null
110
+ }
111
+
112
+ export interface CreateInvitationRequest {
113
+ email: string
114
+ role?: string
115
+ message?: string
116
+ }
117
+
118
+ export interface AcceptInvitationRequest {
119
+ first_name: string
120
+ last_name: string
121
+ password: string
122
+ }
123
+
124
+ // ─── Tenant API response types ────────────────────────────────────────────────
125
+
126
+ export type GetTenantsResponse = AxiosResponse<TenantInfo[]>
127
+ export type GetTenantResponse = AxiosResponse<TenantInfo>
128
+ export type CreateTenantResponse = AxiosResponse<TenantInfo>
129
+ export type UpdateTenantResponse = AxiosResponse<TenantInfo>
130
+ export type DeleteTenantResponse = AxiosResponse<MessageResponse>
131
+ export type GetTenantMembersResponse = AxiosResponse<TenantMember[]>
132
+ export type AddTenantMemberResponse = AxiosResponse<TenantMember>
133
+ export type UpdateTenantMemberResponse = AxiosResponse<TenantMember>
134
+ export type DeleteTenantMemberResponse = AxiosResponse<MessageResponse>
135
+ export type GetTenantRolesResponse = AxiosResponse<string[]>
136
+ export type CreateInvitationResponse = AxiosResponse<TenantInvitation>
137
+ export type GetInvitationResponse = AxiosResponse<{ email: string, first_name?: string | null, last_name?: string | null }>
138
+ export type AcceptInvitationResponse = AxiosResponse<MessageResponse>
139
+
59
140
  export type AuthenticationMethodType
60
141
  = | 'password'
61
142
  | 'email_token'
@@ -363,7 +444,6 @@ export type InitiateSSOResponse = AxiosResponse<SSOInitiateResponse>
363
444
  export type CallbackSSOResponse = AxiosResponse<SSOCallbackResponse>
364
445
  export type LinkSSOResponse = AxiosResponse<SSOLinkResponse>
365
446
  export type UnlinkSSOResponse = AxiosResponse<SSOUnlinkResponse>
366
- export type GetTenantsResponse = AxiosResponse<TenantInfo[]>
367
447
  export type GetAuthStatusResponse = AxiosResponse<AuthStatusResponse>
368
448
  export type SendEmailTokenResponse = AxiosResponse<AuthenticationResponse>
369
449
  export type VerifyEmailTokenResponse = AxiosResponse<AuthenticationResponse>
package/src/useAuth.ts CHANGED
@@ -11,6 +11,12 @@ import type {
11
11
  SSOCallbackRequest,
12
12
  SSOLinkRequest,
13
13
  TenantInfo,
14
+ CreateTenantRequest,
15
+ UpdateTenantRequest,
16
+ AddMemberRequest,
17
+ UpdateMemberRequest,
18
+ CreateInvitationRequest,
19
+ AcceptInvitationRequest,
14
20
  } from './types'
15
21
  import type { RedirectConfig, NormalizedRedirectConfig } from './types/redirect'
16
22
  import { ref, computed } from 'vue'
@@ -382,6 +388,85 @@ export function useAuth() {
382
388
  return currentTenant.value
383
389
  }
384
390
 
391
+ // ============================================
392
+ // Tenant CRUD
393
+ // ============================================
394
+
395
+ async function createTenant(data: CreateTenantRequest) {
396
+ const { data: tenant } = await api.createTenant(data)
397
+ await loadTenants()
398
+ return tenant
399
+ }
400
+
401
+ async function updateTenant(tenantId: string, data: UpdateTenantRequest) {
402
+ const { data: tenant } = await api.updateTenant(tenantId, data)
403
+ // Refresh list so currentTenant stays in sync
404
+ await loadTenants()
405
+ return tenant
406
+ }
407
+
408
+ async function deleteTenant(tenantId: string) {
409
+ await api.deleteTenant(tenantId)
410
+ if (currentTenant.value?.id === tenantId) {
411
+ currentTenant.value = null
412
+ api.setTenantId(null)
413
+ }
414
+ await loadTenants()
415
+ }
416
+
417
+ // ============================================
418
+ // Tenant Members
419
+ // ============================================
420
+
421
+ async function getTenantMembers(tenantId: string, status?: string) {
422
+ const { data } = await api.getTenantMembers(tenantId, status)
423
+ return data
424
+ }
425
+
426
+ async function addTenantMember(tenantId: string, member: AddMemberRequest) {
427
+ const { data } = await api.addTenantMember(tenantId, member)
428
+ return data
429
+ }
430
+
431
+ async function updateTenantMember(tenantId: string, identityId: string, updates: UpdateMemberRequest) {
432
+ const { data } = await api.updateTenantMember(tenantId, identityId, updates)
433
+ return data
434
+ }
435
+
436
+ async function activateTenantMember(tenantId: string, identityId: string) {
437
+ const { data } = await api.activateTenantMember(tenantId, identityId)
438
+ return data
439
+ }
440
+
441
+ async function removeTenantMember(tenantId: string, identityId: string) {
442
+ await api.removeTenantMember(tenantId, identityId)
443
+ }
444
+
445
+ async function getTenantRoles() {
446
+ const { data } = await api.getTenantRoles()
447
+ return data
448
+ }
449
+
450
+ // ============================================
451
+ // Invitations
452
+ // ============================================
453
+
454
+ async function createInvitation(data: CreateInvitationRequest) {
455
+ const { data: invitation } = await api.createInvitation(data)
456
+ return invitation
457
+ }
458
+
459
+ async function getInvitation(token: string) {
460
+ const { data } = await api.getInvitation(token)
461
+ return data
462
+ }
463
+
464
+ async function acceptInvitation(token: string, data?: AcceptInvitationRequest) {
465
+ await api.acceptInvitation(token, data)
466
+ // Re-check auth so tenants are reloaded after membership is created
467
+ await checkAuth()
468
+ }
469
+
385
470
  async function signup(newUser: NewUser) {
386
471
  // Check password match if password is provided
387
472
  const hasPassword = newUser.password !== undefined && newUser.password.length > 0
@@ -572,5 +657,23 @@ export function useAuth() {
572
657
  loadTenants,
573
658
  setTenant,
574
659
  switchTenant,
660
+
661
+ // Tenant CRUD (requires tenancy: true)
662
+ createTenant,
663
+ updateTenant,
664
+ deleteTenant,
665
+
666
+ // Tenant Members
667
+ getTenantMembers,
668
+ addTenantMember,
669
+ updateTenantMember,
670
+ activateTenantMember,
671
+ removeTenantMember,
672
+ getTenantRoles,
673
+
674
+ // Invitations
675
+ createInvitation,
676
+ getInvitation,
677
+ acceptInvitation,
575
678
  }
576
679
  }