@proteos/sdk 0.50.1 → 0.51.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/auth/index.ts CHANGED
@@ -1,9 +1,14 @@
1
1
  import type { ProteosClient } from '../client.js'
2
2
  import { type MeService, MeServiceImpl } from './me.js'
3
3
  import { type OrganizationService, OrganizationServiceImpl } from './organizations.js'
4
+ import { type ProfileService, ProfileServiceImpl } from './profiles.js'
4
5
  import { type RoleService, RoleServiceImpl } from './roles.js'
5
6
  import { type ShareService, ShareServiceImpl } from './shares.js'
6
7
  import { type TeamService, TeamServiceImpl } from './teams.js'
8
+ import {
9
+ type UserProfileAssignmentService,
10
+ UserProfileAssignmentServiceImpl,
11
+ } from './user-profile-assignments.js'
7
12
  import {
8
13
  type UserRoleAssignmentService,
9
14
  UserRoleAssignmentServiceImpl,
@@ -53,6 +58,16 @@ export class AccountClient {
53
58
  */
54
59
  readonly userRoleAssignments: UserRoleAssignmentService
55
60
 
61
+ /**
62
+ * Service for managing profiles (the org's user-types, one per user).
63
+ */
64
+ readonly profiles: ProfileService
65
+
66
+ /**
67
+ * Service for the org-wide user-profile-assignment listing.
68
+ */
69
+ readonly userProfileAssignments: UserProfileAssignmentService
70
+
56
71
  /**
57
72
  * Service for managing organizations.
58
73
  */
@@ -83,6 +98,8 @@ export class AccountClient {
83
98
  this.users = new UserServiceImpl(client)
84
99
  this.roles = new RoleServiceImpl(client)
85
100
  this.userRoleAssignments = new UserRoleAssignmentServiceImpl(client)
101
+ this.profiles = new ProfileServiceImpl(client)
102
+ this.userProfileAssignments = new UserProfileAssignmentServiceImpl(client)
86
103
  this.organizations = new OrganizationServiceImpl(client)
87
104
  this.teams = new TeamServiceImpl(client)
88
105
  this.shares = new ShareServiceImpl(client)
@@ -99,14 +116,16 @@ export {
99
116
  PLATFORM_ENTITY_SLUGS,
100
117
  SCOPED_PLATFORM_ENTITY_SLUGS,
101
118
  } from './platform-entities.js'
119
+ export type { ProfileService } from './profiles.js'
102
120
  export type { RoleService } from './roles.js'
121
+ // Share routing — exported so a UI can hide a share affordance it cannot serve.
122
+ export { isShareable, type ShareService, shareRouteFor } from './shares.js'
103
123
  export type { TeamService } from './teams.js'
104
- export type { UserRoleAssignmentService } from './user-role-assignments.js'
105
124
  // Re-export types
106
125
  export type {
126
+ AddTeamMemberRequest,
107
127
  // Api key types
108
128
  ApiKey,
109
- AddTeamMemberRequest,
110
129
  AssignPermissionRequest,
111
130
  AssignRoleRequest,
112
131
  // Shared types
@@ -114,38 +133,46 @@ export type {
114
133
  CreateApiKeyRequest,
115
134
  CreatedApiKey,
116
135
  CreateOrganizationRequest,
136
+ CreateProfileRequest,
117
137
  CreateRoleRequest,
118
138
  CreateTeamRequest,
119
139
  CreateUserRequest,
120
140
  ListOrganizationsOptions,
141
+ ListOrgUserRoleAssignmentsOptions,
142
+ ListProfilesOptions,
121
143
  ListRolePermissionsOptions,
122
144
  ListRolesOptions,
123
145
  ListTeamMembersOptions,
124
146
  ListTeamsOptions,
125
- ListOrgUserRoleAssignmentsOptions,
147
+ ListUserProfileAssignmentsOptions,
126
148
  ListUserRoleAssignmentsOptions,
127
149
  ListUsersOptions,
128
150
  // Organization types
129
151
  Organization,
130
152
  // Permission types
131
153
  Permission,
154
+ // Profile types
155
+ Profile,
132
156
  // Role types
133
157
  Role,
134
158
  RoleEntityPermission,
159
+ SetProfileRequest,
160
+ // Share types
161
+ SharePermission,
162
+ ShareRequest,
163
+ ShareRow,
135
164
  // Team types
136
165
  Team,
137
166
  TeamMember,
138
167
  UpdateMeRequest,
139
168
  UpdateOrganizationRequest,
169
+ UpdateProfileRequest,
140
170
  UpdateRoleRequest,
141
171
  UpdateTeamRequest,
142
172
  UpdateUserRequest,
143
173
  // User types
144
174
  User,
145
- // Share types
146
- SharePermission,
147
- ShareRequest,
148
- ShareRow,
175
+ UserProfileAssignment,
149
176
  // User role assignment types
150
177
  UserRoleAssignment,
151
178
  } from './types.js'
@@ -153,16 +180,18 @@ export type {
153
180
  export {
154
181
  ApiKeySchema,
155
182
  OrganizationSchema,
156
- SharePermissionSchema,
157
- ShareRequestSchema,
183
+ ProfileSchema,
158
184
  RoleEntityPermissionSchema,
159
185
  RoleSchema,
186
+ SharePermissionSchema,
187
+ ShareRequestSchema,
160
188
  TeamMemberSchema,
161
189
  TeamSchema,
190
+ UserProfileAssignmentSchema,
162
191
  UserRoleAssignmentSchema,
163
192
  UserSchema,
164
193
  } from './types.js'
194
+ export type { UserProfileAssignmentService } from './user-profile-assignments.js'
195
+ export type { UserRoleAssignmentService } from './user-role-assignments.js'
165
196
  // Re-export service interfaces
166
197
  export type { UserService } from './users.js'
167
- // Share routing — exported so a UI can hide a share affordance it cannot serve.
168
- export { isShareable, type ShareService, shareRouteFor } from './shares.js'
package/src/auth/me.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { ProteosClient } from '../client.js'
2
- import type { Organization, UpdateMeRequest, User } from './types.js'
2
+ import type { Organization, Profile, UpdateMeRequest, User } from './types.js'
3
3
 
4
4
  const ME_BASE_PATH = '/accounts/v1/me'
5
5
 
@@ -33,6 +33,14 @@ export interface MeService {
33
33
  * @returns The caller's organizations
34
34
  */
35
35
  organizations(): Promise<Organization[]>
36
+
37
+ /**
38
+ * Gets the caller's profile in the token org — the subject app
39
+ * configurations are resolved against.
40
+ *
41
+ * @throws {ProteosError} 404 when the caller has no profile
42
+ */
43
+ profile(): Promise<Profile>
36
44
  }
37
45
 
38
46
  /**
@@ -56,4 +64,8 @@ export class MeServiceImpl implements MeService {
56
64
  )
57
65
  return response.data
58
66
  }
67
+
68
+ async profile(): Promise<Profile> {
69
+ return this.client.request<Profile>('GET', `${ME_BASE_PATH}/profile`)
70
+ }
59
71
  }
@@ -27,12 +27,18 @@ export const PLATFORM_ENTITIES: readonly PlatformEntity[] = [
27
27
  // who is in it are different decisions, and membership is what moves access.
28
28
  { slug: 'teams', name: 'Teams' },
29
29
  { slug: 'team-members', name: 'Team Members' },
30
+ // Profiles are the org's user-types (UI defaults; app configurations key on
31
+ // them). ONE per user per org. Managing and assigning are separate grants.
32
+ { slug: 'profiles', name: 'Profiles' },
33
+ { slug: 'user-profile-assignments', name: 'User Profile Assignments' },
30
34
  // The share audit trail — a distinct grant from the resources it references.
31
35
  // Schema / content (metadata-service)
32
36
  { slug: 'entities', name: 'Entities' },
33
37
  { slug: 'pages', name: 'Pages' },
34
38
  { slug: 'menu-configurations', name: 'Menu Configurations' },
35
39
  { slug: 'apps', name: 'Apps' },
40
+ // Typed (app × profile) binding rows: home, menu, agents, record pages.
41
+ { slug: 'app-configurations', name: 'App Configurations' },
36
42
  { slug: 'components', name: 'Components' },
37
43
  { slug: 'lists', name: 'Lists' },
38
44
  { slug: 'list-views', name: 'List Views' },
@@ -94,6 +100,11 @@ export const PLATFORM_ENTITIES: readonly PlatformEntity[] = [
94
100
  // The channel_action ledger: acts through a connection that are neither a
95
101
  // message nor a reaction (LinkedIn invitations, profile visits, InMail).
96
102
  { slug: 'channel-actions', name: 'Channel Actions' },
103
+ // The channel_event ledger: provider-observed delivery / engagement events
104
+ // about outbound messages (delivered, bounced, opened, unsubscribed).
105
+ { slug: 'channel-events', name: 'Channel Events' },
106
+ // Conversation briefs: guidance prepared ahead of a conversation (call, meeting) with a contact.
107
+ { slug: 'conversation-briefs', name: 'Conversation Briefs' },
97
108
  // Connectors (connector-service). `connections` above is shared; this is the
98
109
  // manifest catalog.
99
110
  { slug: 'connectors', name: 'Connectors' },
@@ -0,0 +1,82 @@
1
+ import type { ProteosClient } from '../client.js'
2
+ import { PageIterator } from '../iterator.js'
3
+ import type { ListResult } from '../types/common.js'
4
+ import type {
5
+ CreateProfileRequest,
6
+ ListProfilesOptions,
7
+ Profile,
8
+ UpdateProfileRequest,
9
+ } from './types.js'
10
+
11
+ const PROFILES_BASE_PATH = '/accounts/v1/profiles'
12
+
13
+ /**
14
+ * Service for managing profiles — the org's user-types (ONE per user per
15
+ * org). Per-user assignment lives on {@link UserService} (`getProfile` /
16
+ * `setProfile` / `clearProfile`); the org-wide roster on
17
+ * {@link UserProfileAssignmentService}.
18
+ */
19
+ export interface ProfileService {
20
+ /** Lists profiles (auto-paginating iterator). */
21
+ list(options?: ListProfilesOptions): PageIterator<Profile, ListProfilesOptions>
22
+
23
+ /** Fetches a single page of profiles. */
24
+ listPage(options?: ListProfilesOptions): Promise<ListResult<Profile>>
25
+
26
+ /** Gets a profile by slug (404 when unknown). */
27
+ get(slug: string): Promise<Profile>
28
+
29
+ /** Creates a profile. The org is taken from the caller's token. */
30
+ create(request: CreateProfileRequest): Promise<Profile>
31
+
32
+ /**
33
+ * Creates or updates a profile idempotently by slug
34
+ * (`PUT /accounts/v1/profiles/:slug`). The URL slug wins on mismatch.
35
+ */
36
+ upsert(slug: string, request: CreateProfileRequest): Promise<Profile>
37
+
38
+ /** Partially updates a profile. */
39
+ update(slug: string, request: UpdateProfileRequest): Promise<Profile>
40
+
41
+ /**
42
+ * Deletes a profile.
43
+ * @throws {ProteosError} 409 `profile_in_use` while users still hold it —
44
+ * move them first.
45
+ */
46
+ delete(slug: string): Promise<void>
47
+ }
48
+
49
+ export class ProfileServiceImpl implements ProfileService {
50
+ constructor(private readonly client: ProteosClient) {}
51
+
52
+ list(options: ListProfilesOptions = {}): PageIterator<Profile, ListProfilesOptions> {
53
+ return new PageIterator((opts) => this.listPage(opts), options)
54
+ }
55
+
56
+ async listPage(options: ListProfilesOptions = {}): Promise<ListResult<Profile>> {
57
+ return this.client.requestWithQuery<ListResult<Profile>>('GET', PROFILES_BASE_PATH, options)
58
+ }
59
+
60
+ async get(slug: string): Promise<Profile> {
61
+ return this.client.request<Profile>('GET', `${PROFILES_BASE_PATH}/${slug}`)
62
+ }
63
+
64
+ async create(request: CreateProfileRequest): Promise<Profile> {
65
+ return this.client.request<Profile>('POST', PROFILES_BASE_PATH, request)
66
+ }
67
+
68
+ async upsert(slug: string, request: CreateProfileRequest): Promise<Profile> {
69
+ return this.client.request<Profile>('PUT', `${PROFILES_BASE_PATH}/${slug}`, {
70
+ ...request,
71
+ slug,
72
+ })
73
+ }
74
+
75
+ async update(slug: string, request: UpdateProfileRequest): Promise<Profile> {
76
+ return this.client.request<Profile>('PATCH', `${PROFILES_BASE_PATH}/${slug}`, request)
77
+ }
78
+
79
+ async delete(slug: string): Promise<void> {
80
+ await this.client.request<void>('DELETE', `${PROFILES_BASE_PATH}/${slug}`)
81
+ }
82
+ }
package/src/auth/types.ts CHANGED
@@ -248,6 +248,93 @@ export interface CreateApiKeyRequest {
248
248
  expires_at?: string
249
249
  }
250
250
 
251
+ // ============================================================================
252
+ // Profile Types
253
+ // ============================================================================
254
+
255
+ /**
256
+ * Profile — the org's user-type. ONE per user per org (unlike roles, which
257
+ * are many and only decide access). Owns the defaults keyed by subject alone:
258
+ * the app opened after login and the app-switcher allowlist. Metadata app
259
+ * configurations bind per-app defaults (home, menu, agents, record pages) to a
260
+ * profile by slug.
261
+ */
262
+ export interface Profile extends AuditFields {
263
+ slug: string
264
+ name: string
265
+ org_id: string
266
+ description: string
267
+ /** Module that shipped the profile; '' when authored in the org. */
268
+ module_slug: string
269
+ /** App opened after login; clients fail open to the first visible app. */
270
+ default_app_slug: string
271
+ /** App-switcher allowlist; empty = every app in the org. */
272
+ app_slugs: string[]
273
+ }
274
+
275
+ export const ProfileSchema = AuditFieldsSchema.extend({
276
+ slug: z.string(),
277
+ name: z.string(),
278
+ org_id: z.string(),
279
+ description: z.string(),
280
+ module_slug: z.string(),
281
+ default_app_slug: z.string(),
282
+ app_slugs: z.array(z.string()),
283
+ })
284
+
285
+ export interface CreateProfileRequest {
286
+ slug: string
287
+ name: string
288
+ description?: string
289
+ module_slug?: string
290
+ default_app_slug?: string
291
+ app_slugs?: string[]
292
+ }
293
+
294
+ export interface UpdateProfileRequest {
295
+ name?: string
296
+ description?: string
297
+ module_slug?: string
298
+ default_app_slug?: string
299
+ app_slugs?: string[]
300
+ }
301
+
302
+ export interface ListProfilesOptions extends AuthListOptions {
303
+ slug?: string
304
+ name?: string
305
+ module_slug?: string
306
+ default_app_slug?: string
307
+ }
308
+
309
+ /**
310
+ * User profile assignment — a user's ONE profile in an org.
311
+ */
312
+ export interface UserProfileAssignment extends AuditFields {
313
+ id: string
314
+ user_id: string
315
+ profile_slug: string
316
+ org_id: string
317
+ }
318
+
319
+ export const UserProfileAssignmentSchema = AuditFieldsSchema.extend({
320
+ id: z.string(),
321
+ user_id: z.string(),
322
+ profile_slug: z.string(),
323
+ org_id: z.string(),
324
+ })
325
+
326
+ /** Body of `PUT /users/:id/profile` — replaces the user's profile. */
327
+ export interface SetProfileRequest {
328
+ profile_slug: string
329
+ }
330
+
331
+ /** Filters for the org-wide `GET /user-profile-assignments` listing. */
332
+ export interface ListUserProfileAssignmentsOptions extends AuthListOptions {
333
+ id?: string
334
+ user_id?: string
335
+ profile_slug?: string
336
+ }
337
+
251
338
  // ============================================================================
252
339
  // Role Types
253
340
  // ============================================================================
@@ -0,0 +1,41 @@
1
+ import type { ProteosClient } from '../client.js'
2
+ import { PageIterator } from '../iterator.js'
3
+ import type { ListResult } from '../types/common.js'
4
+ import type { ListUserProfileAssignmentsOptions, UserProfileAssignment } from './types.js'
5
+
6
+ const USER_PROFILE_ASSIGNMENTS_BASE_PATH = '/accounts/v1/user-profile-assignments'
7
+
8
+ /**
9
+ * Service for the org-wide user-profile-assignment listing: "who holds which
10
+ * profile" in one request (a profile's member roster, profile badges on a
11
+ * user list). Per-user reads and writes stay on {@link UserService}.
12
+ */
13
+ export interface UserProfileAssignmentService {
14
+ /** Lists profile assignments across all users of the caller's org. */
15
+ list(
16
+ options?: ListUserProfileAssignmentsOptions,
17
+ ): PageIterator<UserProfileAssignment, ListUserProfileAssignmentsOptions>
18
+
19
+ /** Fetches a single page of profile assignments. */
20
+ listPage(options?: ListUserProfileAssignmentsOptions): Promise<ListResult<UserProfileAssignment>>
21
+ }
22
+
23
+ export class UserProfileAssignmentServiceImpl implements UserProfileAssignmentService {
24
+ constructor(private readonly client: ProteosClient) {}
25
+
26
+ list(
27
+ options: ListUserProfileAssignmentsOptions = {},
28
+ ): PageIterator<UserProfileAssignment, ListUserProfileAssignmentsOptions> {
29
+ return new PageIterator((opts) => this.listPage(opts), options)
30
+ }
31
+
32
+ async listPage(
33
+ options: ListUserProfileAssignmentsOptions = {},
34
+ ): Promise<ListResult<UserProfileAssignment>> {
35
+ return this.client.requestWithQuery<ListResult<UserProfileAssignment>>(
36
+ 'GET',
37
+ USER_PROFILE_ASSIGNMENTS_BASE_PATH,
38
+ options,
39
+ )
40
+ }
41
+ }
package/src/auth/users.ts CHANGED
@@ -9,8 +9,10 @@ import type {
9
9
  CreateUserRequest,
10
10
  ListUserRoleAssignmentsOptions,
11
11
  ListUsersOptions,
12
+ SetProfileRequest,
12
13
  UpdateUserRequest,
13
14
  User,
15
+ UserProfileAssignment,
14
16
  UserRoleAssignment,
15
17
  } from './types.js'
16
18
 
@@ -120,6 +122,25 @@ export interface UserService {
120
122
  */
121
123
  unassignRole(userId: string, roleSlug: string): Promise<void>
122
124
 
125
+ /**
126
+ * Gets the user's profile assignment in the caller's org.
127
+ *
128
+ * @throws {ProteosError} 404 when the user has no profile
129
+ */
130
+ getProfile(userId: string): Promise<UserProfileAssignment>
131
+
132
+ /**
133
+ * Sets (replaces) the user's profile in the caller's org — one profile per
134
+ * user per org.
135
+ *
136
+ * @throws {ProteosError} 404 when the user or the profile slug is unknown;
137
+ * 400 `user_not_in_org` when the user holds no role in the org
138
+ */
139
+ setProfile(userId: string, request: SetProfileRequest): Promise<UserProfileAssignment>
140
+
141
+ /** Clears the user's profile (back to every app's default configuration). */
142
+ clearProfile(userId: string): Promise<void>
143
+
123
144
  /**
124
145
  * Lists a user's API keys (display hints only — never tokens).
125
146
  *
@@ -193,6 +214,22 @@ export class UserServiceImpl implements UserService {
193
214
  await this.client.request<void>('DELETE', `${USERS_BASE_PATH}/${userId}/roles/${roleSlug}`)
194
215
  }
195
216
 
217
+ async getProfile(userId: string): Promise<UserProfileAssignment> {
218
+ return this.client.request<UserProfileAssignment>('GET', `${USERS_BASE_PATH}/${userId}/profile`)
219
+ }
220
+
221
+ async setProfile(userId: string, request: SetProfileRequest): Promise<UserProfileAssignment> {
222
+ return this.client.request<UserProfileAssignment>(
223
+ 'PUT',
224
+ `${USERS_BASE_PATH}/${userId}/profile`,
225
+ request,
226
+ )
227
+ }
228
+
229
+ async clearProfile(userId: string): Promise<void> {
230
+ await this.client.request<void>('DELETE', `${USERS_BASE_PATH}/${userId}/profile`)
231
+ }
232
+
196
233
  async listApiKeys(userId: string): Promise<ApiKey[]> {
197
234
  const response = await this.client.request<{ data: ApiKey[] }>(
198
235
  'GET',