@proteos/sdk 0.44.0 → 0.46.0

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.
Files changed (39) hide show
  1. package/dist/{chunk-33EULWIM.cjs → chunk-F5DHWOGW.cjs} +195 -27
  2. package/dist/chunk-F5DHWOGW.cjs.map +1 -0
  3. package/dist/{chunk-IGIAJVX6.js → chunk-Y4CEHIRX.js} +191 -28
  4. package/dist/chunk-Y4CEHIRX.js.map +1 -0
  5. package/dist/index.cjs +453 -178
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +686 -13
  8. package/dist/index.d.ts +686 -13
  9. package/dist/index.js +355 -96
  10. package/dist/index.js.map +1 -1
  11. package/dist/meta/index.cjs +69 -53
  12. package/dist/meta/index.d.cts +1 -1
  13. package/dist/meta/index.d.ts +1 -1
  14. package/dist/meta/index.js +1 -1
  15. package/dist/{types-BTdBFq34.d.cts → types-D1PRIsSO.d.cts} +406 -14
  16. package/dist/{types-BTdBFq34.d.ts → types-D1PRIsSO.d.ts} +406 -14
  17. package/package.json +3 -3
  18. package/src/auth/index.ts +58 -1
  19. package/src/auth/me.ts +14 -1
  20. package/src/auth/platform-entities.ts +27 -0
  21. package/src/auth/roles.ts +3 -1
  22. package/src/auth/shares.ts +181 -0
  23. package/src/auth/teams.ts +135 -0
  24. package/src/auth/types.ts +192 -4
  25. package/src/auth/user-role-assignments.ts +65 -0
  26. package/src/conversation/index.ts +42 -0
  27. package/src/conversation/types.ts +37 -0
  28. package/src/index.ts +36 -0
  29. package/src/knowledge/graph.ts +6 -2
  30. package/src/knowledge/index.ts +15 -0
  31. package/src/knowledge/nodes.ts +4 -1
  32. package/src/knowledge/spaces.ts +86 -0
  33. package/src/knowledge/types.ts +89 -0
  34. package/src/meta/index.ts +11 -0
  35. package/src/meta/layout/control-registry.json +151 -26
  36. package/src/meta/types.ts +186 -4
  37. package/src/workflow/types.ts +20 -3
  38. package/dist/chunk-33EULWIM.cjs.map +0 -1
  39. package/dist/chunk-IGIAJVX6.js.map +0 -1
package/src/auth/types.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { z } from 'zod'
2
- import type { AuditFields, ListOptions } from '../types/common.js'
3
- import { AuditFieldsSchema } from '../types/common.js'
2
+
3
+ import { type PrincipalRef, PrincipalRefSchema } from '../meta/types.js'
4
+ import type { AuditFields, FileRef, ListOptions } from '../types/common.js'
5
+ import { AuditFieldsSchema, FileRefSchema } from '../types/common.js'
4
6
 
5
7
  // ============================================================================
6
8
  // Shared Auth Types
@@ -21,7 +23,20 @@ export interface AuthListOptions extends ListOptions {
21
23
  /**
22
24
  * Permission level for entity access.
23
25
  */
24
- export type Permission = 'read' | 'write' | 'delete'
26
+ export type Permission =
27
+ | 'read'
28
+ | 'write'
29
+ | 'delete'
30
+ // Scoped twins. The grant a role holds decides how much it sees: `read` means
31
+ // every record of the entity in the org, `read_scoped` means only those whose
32
+ // access grants intersect the caller's principals (owned by them, owned by a
33
+ // team they are in, shared with them, or org-wide).
34
+ //
35
+ // The verbs stay independent, so `read` + `write_scoped` reads as "see every
36
+ // deal, edit only your own".
37
+ | 'read_scoped'
38
+ | 'write_scoped'
39
+ | 'delete_scoped'
25
40
 
26
41
  /**
27
42
  * Role entity permission - permission granted to a role for a specific entity.
@@ -38,7 +53,7 @@ export const RoleEntityPermissionSchema = AuditFieldsSchema.extend({
38
53
  id: z.string(),
39
54
  role_slug: z.string(),
40
55
  entity_slug: z.string(),
41
- permission: z.enum(['read', 'write', 'delete']),
56
+ permission: z.enum(['read', 'write', 'delete', 'read_scoped', 'write_scoped', 'delete_scoped']),
42
57
  })
43
58
 
44
59
  /**
@@ -94,6 +109,17 @@ export interface ListUserRoleAssignmentsOptions extends AuthListOptions {
94
109
  role_slug?: string
95
110
  }
96
111
 
112
+ /**
113
+ * Options for the org-wide assignment listing (`GET /user-role-assignments`).
114
+ * Unlike {@link ListUserRoleAssignmentsOptions} (which is bound to one user via
115
+ * the path), this one may also filter by `user_id`.
116
+ */
117
+ export interface ListOrgUserRoleAssignmentsOptions extends AuthListOptions {
118
+ id?: string
119
+ user_id?: string
120
+ role_slug?: string
121
+ }
122
+
97
123
  // ============================================================================
98
124
  // User Types
99
125
  // ============================================================================
@@ -108,6 +134,11 @@ export interface User extends AuditFields {
108
134
  family_name: string
109
135
  external_id: string
110
136
  default_org_id: string
137
+ /**
138
+ * Reference to the user's photo in the storage-service. Absent/null = no
139
+ * photo (clients render initials).
140
+ */
141
+ profile_image?: FileRef | null
111
142
  }
112
143
 
113
144
  export const UserSchema = AuditFieldsSchema.extend({
@@ -117,6 +148,7 @@ export const UserSchema = AuditFieldsSchema.extend({
117
148
  family_name: z.string(),
118
149
  external_id: z.string(),
119
150
  default_org_id: z.string(),
151
+ profile_image: FileRefSchema.nullish(),
120
152
  })
121
153
 
122
154
  /**
@@ -136,6 +168,23 @@ export interface UpdateUserRequest {
136
168
  given_name?: string
137
169
  family_name?: string
138
170
  default_org_id?: string
171
+ /**
172
+ * Tri-state: omit = leave unchanged, `null` = remove the photo, a FileRef =
173
+ * set it. Upload the file to the storage-service first and reference it here.
174
+ */
175
+ profile_image?: FileRef | null
176
+ }
177
+
178
+ /**
179
+ * Caller-scoped `PATCH /me` body. Deliberately narrower than
180
+ * {@link UpdateUserRequest}: a user may edit their own name and photo, but not
181
+ * re-home their account (no `default_org_id`).
182
+ */
183
+ export interface UpdateMeRequest {
184
+ given_name?: string
185
+ family_name?: string
186
+ /** Tri-state — see {@link UpdateUserRequest.profile_image}. */
187
+ profile_image?: FileRef | null
139
188
  }
140
189
 
141
190
  /**
@@ -249,6 +298,103 @@ export interface ListRolesOptions extends AuthListOptions {
249
298
  description?: string
250
299
  }
251
300
 
301
+ // ============================================================================
302
+ // Team Types
303
+ // ============================================================================
304
+
305
+ /**
306
+ * A team — a node in the org's structure, and a principal that can hold access
307
+ * anywhere a user can.
308
+ *
309
+ * Hierarchy rolls UP: a member of a child team counts as a member of every
310
+ * ancestor **for grants made to that ancestor**. Granting `sales` reaches the
311
+ * members of `sales-emea`; granting `sales-emea` never reaches someone who is
312
+ * only in `sales`.
313
+ *
314
+ * The slug is immutable — it is half the primary key, and grants reference
315
+ * `team:<orgId>/<slug>`.
316
+ */
317
+ export interface Team extends AuditFields {
318
+ slug: string
319
+ name: string
320
+ org_id: string
321
+ description: string
322
+ /** This team's parent within the same org; empty for a root team. */
323
+ parent_team_slug: string
324
+ }
325
+
326
+ export const TeamSchema = AuditFieldsSchema.extend({
327
+ slug: z.string(),
328
+ name: z.string(),
329
+ org_id: z.string(),
330
+ description: z.string(),
331
+ parent_team_slug: z.string(),
332
+ })
333
+
334
+ /**
335
+ * One user's DIRECT membership of one team. Membership of ancestor teams is
336
+ * derived rather than stored, so it never appears as a row here.
337
+ */
338
+ export interface TeamMember extends AuditFields {
339
+ id: string
340
+ org_id: string
341
+ team_slug: string
342
+ user_id: string
343
+ }
344
+
345
+ export const TeamMemberSchema = AuditFieldsSchema.extend({
346
+ id: z.string(),
347
+ org_id: z.string(),
348
+ team_slug: z.string(),
349
+ user_id: z.string(),
350
+ })
351
+
352
+ /**
353
+ * Request to create a team.
354
+ */
355
+ export interface CreateTeamRequest {
356
+ org_id?: string
357
+ slug: string
358
+ name: string
359
+ description?: string
360
+ /** Nests the team under an existing one in the same org. Omit for a root. */
361
+ parent_team_slug?: string
362
+ }
363
+
364
+ /**
365
+ * Request to update a team.
366
+ *
367
+ * `slug` is deliberately absent: it is half the primary key and is referenced by
368
+ * every grant as `team:<orgId>/<slug>`, so renaming would orphan them.
369
+ */
370
+ export interface UpdateTeamRequest {
371
+ name?: string
372
+ description?: string
373
+ /** Re-parents the team; an explicit empty string promotes it to a root. */
374
+ parent_team_slug?: string
375
+ }
376
+
377
+ export interface ListTeamsOptions extends AuthListOptions {
378
+ org_id?: string
379
+ slug?: string
380
+ name?: string
381
+ description?: string
382
+ parent_team_slug?: string
383
+ }
384
+
385
+ /**
386
+ * Request to add a user to a team.
387
+ */
388
+ export interface AddTeamMemberRequest {
389
+ user_id: string
390
+ }
391
+
392
+ export interface ListTeamMembersOptions extends AuthListOptions {
393
+ org_id?: string
394
+ team_slug?: string
395
+ user_id?: string
396
+ }
397
+
252
398
  // ============================================================================
253
399
  // Organization Types
254
400
  // ============================================================================
@@ -292,3 +438,45 @@ export interface ListOrganizationsOptions extends AuthListOptions {
292
438
  name?: string
293
439
  description?: string
294
440
  }
441
+
442
+ /**
443
+ * The verbs a share can grant. Only these three — a typo'd permission is
444
+ * rejected rather than accepted as a grant that confers nothing.
445
+ */
446
+ export type SharePermission = 'read' | 'write' | 'delete'
447
+
448
+ /**
449
+ * The wire shape of a share write. Identical for granting and revoking, and
450
+ * shaped like the grant it produces, so ONE endpoint per owning service serves
451
+ * every entity rather than one endpoint per entity.
452
+ */
453
+ export interface ShareRequest {
454
+ entity_slug: string
455
+ record_id: string
456
+ principal: PrincipalRef
457
+ permission: SharePermission
458
+ }
459
+
460
+ export const SharePermissionSchema = z.enum(['read', 'write', 'delete'])
461
+
462
+ /**
463
+ * One stored share: a principal holding one verb on one record, with the
464
+ * grantor as provenance. Every row is an explicit share — ownership and
465
+ * granting attributes are evaluated live and never stored.
466
+ */
467
+ export interface ShareRow {
468
+ entity_slug: string
469
+ record_id: string
470
+ /** Rendered principal string: `user:<id>` | `team:<orgId>/<slug>` | `org:<orgId>`. */
471
+ principal: string
472
+ permission: SharePermission
473
+ created_by?: { type: string; id: string }
474
+ created_at?: string
475
+ }
476
+
477
+ export const ShareRequestSchema = z.object({
478
+ entity_slug: z.string(),
479
+ record_id: z.string(),
480
+ principal: PrincipalRefSchema,
481
+ permission: SharePermissionSchema,
482
+ })
@@ -0,0 +1,65 @@
1
+ import type { ProteosClient } from '../client.js'
2
+ import { PageIterator } from '../iterator.js'
3
+ import type { ListResult } from '../types/common.js'
4
+ import type { ListOrgUserRoleAssignmentsOptions, UserRoleAssignment } from './types.js'
5
+
6
+ const USER_ROLE_ASSIGNMENTS_BASE_PATH = '/accounts/v1/user-role-assignments'
7
+
8
+ /**
9
+ * Service for the org-wide user-role-assignment listing.
10
+ *
11
+ * One request answers "who holds which role" across the whole org — the admin
12
+ * view joining users to their roles (role badges on a user list, a role's
13
+ * member roster, member counts) without a per-user fan-out. Per-user reads and
14
+ * writes stay on {@link UserService} (`users.getRoles` / `assignRole` /
15
+ * `unassignRole`).
16
+ */
17
+ export interface UserRoleAssignmentService {
18
+ /**
19
+ * Lists role assignments across all users of the caller's org.
20
+ * Returns an async iterator that automatically handles pagination.
21
+ *
22
+ * @param options - Filter and pagination options (`role_slug`, `user_id`)
23
+ * @returns Async iterator over user role assignments
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * // Everyone holding the sales role
28
+ * const sales = await service.list({ role_slug: 'sales' }).all();
29
+ * ```
30
+ */
31
+ list(
32
+ options?: ListOrgUserRoleAssignmentsOptions,
33
+ ): PageIterator<UserRoleAssignment, ListOrgUserRoleAssignmentsOptions>
34
+
35
+ /**
36
+ * Fetches a single page of role assignments.
37
+ *
38
+ * @param options - Filter and pagination options (including `page`)
39
+ * @returns A single page of assignments with pagination metadata
40
+ */
41
+ listPage(options?: ListOrgUserRoleAssignmentsOptions): Promise<ListResult<UserRoleAssignment>>
42
+ }
43
+
44
+ /**
45
+ * Implementation of UserRoleAssignmentService.
46
+ */
47
+ export class UserRoleAssignmentServiceImpl implements UserRoleAssignmentService {
48
+ constructor(private readonly client: ProteosClient) {}
49
+
50
+ list(
51
+ options: ListOrgUserRoleAssignmentsOptions = {},
52
+ ): PageIterator<UserRoleAssignment, ListOrgUserRoleAssignmentsOptions> {
53
+ return new PageIterator((opts) => this.listPage(opts), options)
54
+ }
55
+
56
+ async listPage(
57
+ options: ListOrgUserRoleAssignmentsOptions = {},
58
+ ): Promise<ListResult<UserRoleAssignment>> {
59
+ return this.client.requestWithQuery<ListResult<UserRoleAssignment>>(
60
+ 'GET',
61
+ USER_ROLE_ASSIGNMENTS_BASE_PATH,
62
+ options,
63
+ )
64
+ }
65
+ }
@@ -17,6 +17,10 @@ import type {
17
17
  CreateAgentListenerRequest,
18
18
  CreateConnectionRequest,
19
19
  CreateContactGroupRequest,
20
+ CreateContactRequest,
21
+ ContactRecordLink,
22
+ CreateContactRecordLinkRequest,
23
+ ListContactRecordLinksQuery,
20
24
  CreateConversationFilterRequest,
21
25
  CreateConversationTypeRequest,
22
26
  CreateGlossaryTermRequest,
@@ -282,9 +286,17 @@ class ConnectionServiceImpl implements ConnectionService {
282
286
  export interface ContactService {
283
287
  list(query?: ListContactsQuery): Promise<ListResponse<Contact>>
284
288
  get(id: string): Promise<Contact>
289
+ /** Manually mint a contact (sync dedup — 409 contact_address_taken on any owned address). */
290
+ create(request: CreateContactRequest): Promise<Contact>
285
291
  update(id: string, request: UpdateContactRequest): Promise<Contact>
286
292
  attachAddress(contactId: string, request: AttachContactAddressRequest): Promise<Contact>
287
293
  detachAddress(contactId: string, addressId: string): Promise<Contact>
294
+ /** Link the contact to a business record (bare edge; 409 contact_record_link_exists on duplicates). */
295
+ linkRecord(request: CreateContactRecordLinkRequest): Promise<ContactRecordLink>
296
+ /** Page contact→record edges by contact_id, or by entity_slug + record_id. */
297
+ listRecordLinks(query?: ListContactRecordLinksQuery): Promise<ListResponse<ContactRecordLink>>
298
+ getRecordLink(linkId: string): Promise<ContactRecordLink>
299
+ unlinkRecord(linkId: string): Promise<void>
288
300
  /** Fold source_contact_id into contactId (contactId wins). */
289
301
  merge(contactId: string, request: MergeContactsRequest): Promise<Contact>
290
302
  recordPermissionEvent(contactId: string, request: RecordPermissionEventRequest): Promise<Contact>
@@ -313,6 +325,10 @@ class ContactServiceImpl implements ContactService {
313
325
  )
314
326
  }
315
327
 
328
+ create(request: CreateContactRequest): Promise<Contact> {
329
+ return this.client.request('POST', `${CONVERSATION_BASE_PATH}/contacts`, request)
330
+ }
331
+
316
332
  update(id: string, request: UpdateContactRequest): Promise<Contact> {
317
333
  return this.client.request(
318
334
  'PATCH',
@@ -336,6 +352,32 @@ class ContactServiceImpl implements ContactService {
336
352
  )
337
353
  }
338
354
 
355
+ linkRecord(request: CreateContactRecordLinkRequest): Promise<ContactRecordLink> {
356
+ return this.client.request('POST', `${CONVERSATION_BASE_PATH}/contact-record-links`, request)
357
+ }
358
+
359
+ listRecordLinks(query: ListContactRecordLinksQuery = {}): Promise<ListResponse<ContactRecordLink>> {
360
+ return this.client.requestWithQuery(
361
+ 'GET',
362
+ `${CONVERSATION_BASE_PATH}/contact-record-links`,
363
+ query,
364
+ )
365
+ }
366
+
367
+ getRecordLink(linkId: string): Promise<ContactRecordLink> {
368
+ return this.client.request(
369
+ 'GET',
370
+ `${CONVERSATION_BASE_PATH}/contact-record-links/${encodeURIComponent(linkId)}`,
371
+ )
372
+ }
373
+
374
+ unlinkRecord(linkId: string): Promise<void> {
375
+ return this.client.request(
376
+ 'DELETE',
377
+ `${CONVERSATION_BASE_PATH}/contact-record-links/${encodeURIComponent(linkId)}`,
378
+ )
379
+ }
380
+
339
381
  merge(contactId: string, request: MergeContactsRequest): Promise<Contact> {
340
382
  return this.client.request(
341
383
  'POST',
@@ -1252,6 +1252,16 @@ export interface UpdateContactRequest {
1252
1252
  group_key?: string
1253
1253
  }
1254
1254
 
1255
+ /**
1256
+ * Manually mints a contact with at least one address. Addresses are
1257
+ * canonicalized server-side; any address already owned by another contact
1258
+ * rejects the create with 409 contact_address_taken.
1259
+ */
1260
+ export interface CreateContactRequest {
1261
+ name: string
1262
+ addresses: AttachContactAddressRequest[]
1263
+ }
1264
+
1255
1265
  export interface AttachContactAddressRequest {
1256
1266
  kind: ContactAddressKind
1257
1267
  scope?: string
@@ -1259,6 +1269,33 @@ export interface AttachContactAddressRequest {
1259
1269
  name?: string
1260
1270
  }
1261
1271
 
1272
+ /**
1273
+ * A directed edge from a contact to a business record (entity_slug +
1274
+ * record_id). Bare — no role; the relationship's semantics come from the
1275
+ * target entity. Immutable once created.
1276
+ */
1277
+ export interface ContactRecordLink {
1278
+ id: string
1279
+ org_id: string
1280
+ contact_id: string
1281
+ entity_slug: string
1282
+ record_id: string
1283
+ created_at: string
1284
+ created_by: UserRef
1285
+ }
1286
+
1287
+ export interface CreateContactRecordLinkRequest {
1288
+ contact_id: string
1289
+ entity_slug: string
1290
+ record_id: string
1291
+ }
1292
+
1293
+ export interface ListContactRecordLinksQuery extends PaginationQuery {
1294
+ contact_id?: string
1295
+ entity_slug?: string
1296
+ record_id?: string
1297
+ }
1298
+
1262
1299
  export interface MergeContactsRequest {
1263
1300
  source_contact_id: string
1264
1301
  }
package/src/index.ts CHANGED
@@ -123,16 +123,25 @@ export type {
123
123
  export { AgentClient } from './agent/index.js'
124
124
  // Auth types (re-exported from auth/index.ts for convenience)
125
125
  export type {
126
+ AddTeamMemberRequest,
127
+ // Api key types
128
+ ApiKey,
126
129
  AssignPermissionRequest,
127
130
  AssignRoleRequest,
128
131
  // Shared auth types
129
132
  AuthListOptions,
133
+ CreateApiKeyRequest,
134
+ CreatedApiKey,
130
135
  CreateOrganizationRequest,
131
136
  CreateRoleRequest,
137
+ CreateTeamRequest,
132
138
  CreateUserRequest,
133
139
  ListOrganizationsOptions,
140
+ ListOrgUserRoleAssignmentsOptions,
134
141
  ListRolePermissionsOptions,
135
142
  ListRolesOptions,
143
+ ListTeamMembersOptions,
144
+ ListTeamsOptions,
136
145
  ListUserRoleAssignmentsOptions,
137
146
  ListUsersOptions,
138
147
  // Me (caller-scoped) service
@@ -148,13 +157,23 @@ export type {
148
157
  Role,
149
158
  RoleEntityPermission,
150
159
  RoleService,
160
+ Team,
161
+ TeamMember,
162
+ TeamService,
163
+ UpdateMeRequest,
151
164
  UpdateOrganizationRequest,
152
165
  UpdateRoleRequest,
166
+ UpdateTeamRequest,
153
167
  UpdateUserRequest,
168
+ // Share types (instance-level access)
169
+ SharePermission,
170
+ ShareRow,
171
+ ShareService,
154
172
  // User types
155
173
  User,
156
174
  // User role assignment types
157
175
  UserRoleAssignment,
176
+ UserRoleAssignmentService,
158
177
  UserService,
159
178
  } from './auth/index.js'
160
179
  // Auth client and services
@@ -162,11 +181,14 @@ export type {
162
181
  export {
163
182
  AccountClient,
164
183
  isPlatformEntity,
184
+ isShareable,
165
185
  OrganizationSchema,
166
186
  PLATFORM_ENTITIES,
167
187
  PLATFORM_ENTITY_SLUGS,
188
+ SCOPED_PLATFORM_ENTITY_SLUGS,
168
189
  RoleEntityPermissionSchema,
169
190
  RoleSchema,
191
+ shareRouteFor,
170
192
  UserRoleAssignmentSchema,
171
193
  UserSchema,
172
194
  } from './auth/index.js'
@@ -406,6 +428,7 @@ export type {
406
428
  CreateLinkRequest,
407
429
  CreateNodeRequest,
408
430
  CreateRecordLinkRequest,
431
+ CreateSpaceRequest,
409
432
  EditContentRequest,
410
433
  EditContentResponse,
411
434
  GetGraphOptions,
@@ -421,6 +444,7 @@ export type {
421
444
  KnowledgeNodeMetadata,
422
445
  KnowledgeNodeSearchResult,
423
446
  KnowledgeRecordLink,
447
+ KnowledgeSpace,
424
448
  LabelService,
425
449
  LinkService,
426
450
  LinkType,
@@ -428,6 +452,7 @@ export type {
428
452
  ListLinksOptions,
429
453
  ListNodesOptions,
430
454
  ListRecordLinksOptions,
455
+ ListSpacesOptions,
431
456
  MatchMode,
432
457
  NeighborDirection,
433
458
  NeighborEdge,
@@ -446,9 +471,11 @@ export type {
446
471
  SearchContentRequest,
447
472
  SearchContentResponse,
448
473
  SearchNodesRequest,
474
+ SpaceService,
449
475
  UpdateLabelRequest,
450
476
  UpdateLinkRequest,
451
477
  UpdateNodeRequest,
478
+ UpdateSpaceRequest,
452
479
  WriteContentResponse,
453
480
  } from './knowledge/index.js'
454
481
  // Knowledge client (knowledge-service: graph-native knowledge base)
@@ -462,6 +489,7 @@ export {
462
489
  KnowledgeNodeSearchResultSchema,
463
490
  KnowledgeRecordLinkSchema,
464
491
  NodeNeighborhoodSchema,
492
+ UNASSIGNED_SPACE_SLUG,
465
493
  } from './knowledge/index.js'
466
494
  // Meta types (re-exported from meta/index.ts for convenience)
467
495
  export type {
@@ -471,6 +499,10 @@ export type {
471
499
  // Array/enum attribute metas (config_schema renderers narrow on these)
472
500
  ArrayAttributeMeta,
473
501
  Attribute,
502
+ CurrentUserDefault,
503
+ // Attribute-level access restrictions (read/write allow-lists of role + team slugs)
504
+ AttributeAccessRule,
505
+ AttributeRestrictions,
474
506
  AttributeType,
475
507
  Column,
476
508
  ComparisonOperator,
@@ -536,6 +568,7 @@ export type {
536
568
  // Page types
537
569
  Page,
538
570
  PageAction,
571
+ PageActionKind,
539
572
  PageLayout,
540
573
  PageService,
541
574
  PageType,
@@ -580,6 +613,9 @@ export {
580
613
  formatAmount,
581
614
  formatMoney,
582
615
  isPlatformAttributeName,
616
+ CURRENT_USER_DEFAULT,
617
+ acceptsCurrentUserDefault,
618
+ isCurrentUserDefault,
583
619
  ListSchema,
584
620
  ListViewSchema,
585
621
  localeNumberSeparators,
@@ -11,7 +11,8 @@ const GRAPH_BASE_PATH = '/knowledge/v1/graph'
11
11
  export interface GraphService {
12
12
  /**
13
13
  * Reads the whole org graph in one payload. `options.label_ids` prunes to
14
- * nodes carrying ANY of the given labels (union); omitted returns everything.
14
+ * nodes carrying ANY of the given labels (union) and `options.space_slugs` to
15
+ * nodes in ANY of the given spaces; omitted returns everything.
15
16
  */
16
17
  get(options?: GetGraphOptions): Promise<KnowledgeGraph>
17
18
  }
@@ -26,10 +27,13 @@ export class GraphServiceImpl implements GraphService {
26
27
  // The server reads label_ids as a single comma-separated query param (the
27
28
  // query binder takes only the first value of a repeated param), so the
28
29
  // union list is joined here rather than appended as repeated params.
29
- const query: { label_ids?: string } = {}
30
+ const query: { label_ids?: string; space_slugs?: string } = {}
30
31
  if (options.label_ids && options.label_ids.length > 0) {
31
32
  query.label_ids = options.label_ids.join(',')
32
33
  }
34
+ if (options.space_slugs && options.space_slugs.length > 0) {
35
+ query.space_slugs = options.space_slugs.join(',')
36
+ }
33
37
  return this.client.requestWithQuery<KnowledgeGraph>('GET', GRAPH_BASE_PATH, query)
34
38
  }
35
39
  }
@@ -3,6 +3,7 @@ import { type GraphService, GraphServiceImpl } from './graph.js'
3
3
  import { type LabelService, LabelServiceImpl } from './labels.js'
4
4
  import { type LinkService, LinkServiceImpl } from './links.js'
5
5
  import { type NodeService, NodeServiceImpl } from './nodes.js'
6
+ import { type SpaceService, SpaceServiceImpl } from './spaces.js'
6
7
  import { type RecordLinkService, RecordLinkServiceImpl } from './record-links.js'
7
8
 
8
9
  /**
@@ -23,6 +24,11 @@ export class KnowledgeClient {
23
24
  /** Node→record edges (links to data-service records): `knowledge.recordLinks`. */
24
25
  readonly recordLinks: RecordLinkService
25
26
  readonly labels: LabelService
27
+ /**
28
+ * Knowledge spaces — the containers nodes live in: `knowledge.spaces`.
29
+ * Access to a space is granted through `auth.shares`, not here.
30
+ */
31
+ readonly spaces: SpaceService
26
32
  /** Whole-org graph bulk read (radiant graph view): `knowledge.graph.get()`. */
27
33
  readonly graph: GraphService
28
34
 
@@ -31,6 +37,7 @@ export class KnowledgeClient {
31
37
  this.links = new LinkServiceImpl(client)
32
38
  this.recordLinks = new RecordLinkServiceImpl(client)
33
39
  this.labels = new LabelServiceImpl(client)
40
+ this.spaces = new SpaceServiceImpl(client)
34
41
  this.graph = new GraphServiceImpl(client)
35
42
  }
36
43
  }
@@ -40,6 +47,7 @@ export type { GraphService } from './graph.js'
40
47
  export type { LabelService } from './labels.js'
41
48
  export type { LinkService } from './links.js'
42
49
  export type { NodeService } from './nodes.js'
50
+ export type { SpaceService } from './spaces.js'
43
51
  export type { RecordLinkService } from './record-links.js'
44
52
 
45
53
  // Re-export types
@@ -50,6 +58,7 @@ export type {
50
58
  CreateLinkRequest,
51
59
  CreateNodeRequest,
52
60
  CreateRecordLinkRequest,
61
+ CreateSpaceRequest,
53
62
  EditContentRequest,
54
63
  EditContentResponse,
55
64
  GetGraphOptions,
@@ -64,11 +73,13 @@ export type {
64
73
  KnowledgeNodeMetadata,
65
74
  KnowledgeNodeSearchResult,
66
75
  KnowledgeRecordLink,
76
+ KnowledgeSpace,
67
77
  LinkType,
68
78
  ListLabelsOptions,
69
79
  ListLinksOptions,
70
80
  ListNodesOptions,
71
81
  ListRecordLinksOptions,
82
+ ListSpacesOptions,
72
83
  MatchMode,
73
84
  NeighborDirection,
74
85
  NeighborEdge,
@@ -88,9 +99,13 @@ export type {
88
99
  UpdateLabelRequest,
89
100
  UpdateLinkRequest,
90
101
  UpdateNodeRequest,
102
+ UpdateSpaceRequest,
91
103
  WriteContentResponse,
92
104
  } from './types.js'
93
105
 
106
+ // Re-export the reserved space-filter sentinel (a value, not a type).
107
+ export { UNASSIGNED_SPACE_SLUG } from './types.js'
108
+
94
109
  // Re-export Zod schemas
95
110
  export {
96
111
  KnowledgeLabelSchema,
@@ -100,11 +100,14 @@ export class NodeServiceImpl implements NodeService {
100
100
  // The server reads label_ids as a single comma-separated query param (the query
101
101
  // binder takes only the first value of a repeated param), so the union list is
102
102
  // joined here rather than appended as repeated params (mirrors GraphService.get).
103
- const { label_ids, ...rest } = options
103
+ const { label_ids, space_slugs, ...rest } = options
104
104
  const query: Record<string, unknown> = { ...rest }
105
105
  if (label_ids && label_ids.length > 0) {
106
106
  query.label_ids = label_ids.join(',')
107
107
  }
108
+ if (space_slugs && space_slugs.length > 0) {
109
+ query.space_slugs = space_slugs.join(',')
110
+ }
108
111
  return this.client.requestWithQuery<ListResult<KnowledgeNodeMetadata>>(
109
112
  'GET',
110
113
  NODES_BASE_PATH,