@proteos/sdk 0.45.0 → 0.47.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 (41) hide show
  1. package/dist/{chunk-IGIAJVX6.js → chunk-5KEJKXO5.js} +220 -34
  2. package/dist/chunk-5KEJKXO5.js.map +1 -0
  3. package/dist/{chunk-33EULWIM.cjs → chunk-Z7LC3GGU.cjs} +224 -33
  4. package/dist/chunk-Z7LC3GGU.cjs.map +1 -0
  5. package/dist/index.cjs +437 -179
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +659 -18
  8. package/dist/index.d.ts +659 -18
  9. package/dist/index.js +339 -97
  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-oECz4xTQ.d.cts} +578 -32
  16. package/dist/{types-BTdBFq34.d.ts → types-oECz4xTQ.d.ts} +578 -32
  17. package/package.json +1 -1
  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/functions/actions.ts +29 -0
  27. package/src/functions/types.ts +6 -4
  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 +154 -27
  36. package/src/meta/layout/elements.ts +86 -0
  37. package/src/meta/layout/index.ts +2 -0
  38. package/src/meta/types.ts +245 -17
  39. package/src/workflow/types.ts +20 -3
  40. package/dist/chunk-33EULWIM.cjs.map +0 -1
  41. package/dist/chunk-IGIAJVX6.js.map +0 -1
package/src/meta/types.ts CHANGED
@@ -38,10 +38,52 @@ export type AttributeType =
38
38
  | 'enum'
39
39
  | 'relation'
40
40
  | 'user'
41
+ | 'principal'
41
42
  | 'currency'
42
43
  | 'knowledge-text'
43
44
  | 'file'
44
45
 
46
+ /**
47
+ * Attribute-level permissions: restricting a FIELD rather than a record — a
48
+ * salary column readable only by the people team, a margin column writable only
49
+ * by finance. Mirror of the Go `metamodel.AttributeRestrictions`.
50
+ *
51
+ * Orthogonal to instance-level access: a caller who may see a record may still
52
+ * be blocked from one of its fields.
53
+ *
54
+ * Absent means unrestricted. Both arms FAIL CLOSED — an empty rule matches
55
+ * nobody rather than everybody, and an unknown role or team slug never matches,
56
+ * so a typo removes access rather than granting it.
57
+ */
58
+ export interface AttributeAccessRule {
59
+ /** Role slugs, matched against the caller's roles. */
60
+ roles?: string[]
61
+ /**
62
+ * Team slugs. Matched through the caller's team closure, so a member of a
63
+ * CHILD team is matched by a rule naming an ancestor.
64
+ */
65
+ teams?: string[]
66
+ }
67
+
68
+ export const AttributeAccessRuleSchema = z.object({
69
+ roles: z.array(z.string()).optional(),
70
+ teams: z.array(z.string()).optional(),
71
+ })
72
+
73
+ /**
74
+ * Read and write are gated independently, so `write` alone yields a field
75
+ * everyone can see and only some can change.
76
+ */
77
+ export interface AttributeRestrictions {
78
+ read?: AttributeAccessRule
79
+ write?: AttributeAccessRule
80
+ }
81
+
82
+ export const AttributeRestrictionsSchema = z.object({
83
+ read: AttributeAccessRuleSchema.optional(),
84
+ write: AttributeAccessRuleSchema.optional(),
85
+ })
86
+
45
87
  // ── Attribute meta (sub-discriminators) ──────────────────────────────
46
88
  // Mirrors the Go `*AttributeMeta` types in
47
89
  // packages/go/model/attribute-{string,number,datetime,array,object,enum}.go.
@@ -88,6 +130,10 @@ export interface EnumValue {
88
130
  value: string
89
131
  label?: string
90
132
  description?: string
133
+ /** Lucide icon name, canonical PascalCase (e.g. `CircleCheck`). Replaces the badge dot. */
134
+ icon?: string
135
+ /** Tint as `#rrggbb`. Renderers derive dot/border/background from it; text stays ink. */
136
+ color?: string
91
137
  }
92
138
 
93
139
  export interface EnumAttributeMeta {
@@ -144,6 +190,68 @@ export const UserAttributeMetaSchema = z.object({
144
190
  description: z.string().optional(),
145
191
  })
146
192
 
193
+ /**
194
+ * The stored value of a `principal`-typed attribute: a {@link PrincipalRef}
195
+ * `{ type, id }` naming anything that can HOLD ACCESS — a user (person, agent
196
+ * or api client), a team, or the whole organization. Mirror of the Go
197
+ * `metamodel.PrincipalAttributeMeta`.
198
+ *
199
+ * Distinct from `user` on purpose. `user` means "a person did this" — it is
200
+ * authorship, and its value can never be a team. `principal` means "this party
201
+ * may be granted access", a different question with a strictly larger
202
+ * vocabulary. Widening `user` would have made every existing user attribute
203
+ * silently accept a team, including the created_by / updated_by audit columns.
204
+ */
205
+ export interface PrincipalAttributeMeta {
206
+ description?: string
207
+ /**
208
+ * Turns the attribute into a GRANTING attribute: the verbs its value confers
209
+ * on the record. `deals.account_manager` with `["read","write"]` means setting
210
+ * it gives that principal access with no share call — the business field IS
211
+ * the ACL.
212
+ *
213
+ * `share` is the right to hand access on — share the record, set other
214
+ * granting attributes, revoke shares. `["read","write","delete","share"]` is
215
+ * full ownership: there is no separate owner field on the platform, the
216
+ * business field that grants `share` IS the owner. `share` must accompany
217
+ * at least one of read/write/delete, and an attribute granting it never
218
+ * accepts an `org` principal.
219
+ *
220
+ * Empty (the default) means an ordinary reference that confers nothing, so an
221
+ * existing principal attribute cannot start granting access by accident.
222
+ */
223
+ grants?: Array<'read' | 'write' | 'delete' | 'share'>
224
+ /**
225
+ * Narrows which principal kinds this attribute accepts; empty means all
226
+ * (except that an attribute granting `share` refuses `org` regardless —
227
+ * an org-wide right to re-grant would hand record management to every
228
+ * member).
229
+ */
230
+ allowed_types?: PrincipalType[]
231
+ }
232
+
233
+ export const PrincipalAttributeMetaSchema = z.object({
234
+ description: z.string().optional(),
235
+ grants: z.array(z.enum(['read', 'write', 'delete', 'share'])).optional(),
236
+ allowed_types: z.array(z.enum(['person', 'agent', 'api', 'team', 'org'])).optional(),
237
+ })
238
+
239
+ /** The kinds a principal reference may name. */
240
+ export type PrincipalType = 'person' | 'agent' | 'api' | 'team' | 'org'
241
+
242
+ /**
243
+ * The stored value of a `principal`-typed attribute.
244
+ */
245
+ export interface PrincipalRef {
246
+ type: PrincipalType
247
+ id: string
248
+ }
249
+
250
+ export const PrincipalRefSchema = z.object({
251
+ type: z.enum(['person', 'agent', 'api', 'team', 'org']),
252
+ id: z.string(),
253
+ })
254
+
147
255
  /**
148
256
  * The stored value of a `currency`-typed attribute: an exact decimal `amount`
149
257
  * (a STRING, never a JS number — preserves financial-system precision and
@@ -236,6 +344,7 @@ export type AttributeMeta =
236
344
  | EnumAttributeMeta
237
345
  | RelationAttributeMeta
238
346
  | UserAttributeMeta
347
+ | PrincipalAttributeMeta
239
348
  | CurrencyAttributeMeta
240
349
  | KnowledgeTextAttributeMeta
241
350
  | FileAttributeMeta
@@ -259,6 +368,17 @@ export interface Attribute {
259
368
  * Mirrors `IsPlatformManaged` in the Go `metamodel.Attribute`.
260
369
  */
261
370
  is_platform_managed?: boolean
371
+ /**
372
+ * Attribute-level permissions. Absent means unrestricted (today's behaviour).
373
+ * Platform-managed attributes cannot carry restrictions.
374
+ */
375
+ restrictions?: AttributeRestrictions
376
+ /**
377
+ * Literal default, or — on a `user` / `principal` attribute only — the
378
+ * current-user sentinel `{ type: 'current_user' }` (see
379
+ * `CURRENT_USER_DEFAULT`), which data-service resolves to the writer at
380
+ * record-write time.
381
+ */
262
382
  default_value?: unknown
263
383
  /**
264
384
  * Type-specific metadata. The concrete shape is determined by `type`
@@ -365,6 +485,7 @@ export const AttributeSchema = z.object({
365
485
  is_nullable: z.boolean().optional(),
366
486
  is_unique: z.boolean(),
367
487
  is_read_only: z.boolean().optional(),
488
+ restrictions: AttributeRestrictionsSchema.optional(),
368
489
  default_value: z.unknown().optional(),
369
490
  meta: z.unknown().optional(),
370
491
  options: z.record(z.unknown()).optional(),
@@ -393,6 +514,18 @@ export function parseCurrencyMeta(attr: Attribute): CurrencyAttributeMeta | null
393
514
  return parsed.success ? parsed.data : null
394
515
  }
395
516
 
517
+ /**
518
+ * Returns the typed `PrincipalAttributeMeta` when `attr` is a principal
519
+ * attribute; null otherwise. Principal meta is optional, so an attribute with
520
+ * no meta resolves to an empty `{}` rather than null.
521
+ */
522
+ export function parsePrincipalMeta(attr: Attribute): PrincipalAttributeMeta | null {
523
+ if (attr.type !== 'principal') return null
524
+ if (attr.meta == null) return {}
525
+ const parsed = PrincipalAttributeMetaSchema.safeParse(attr.meta)
526
+ return parsed.success ? parsed.data : {}
527
+ }
528
+
396
529
  export function parseUserMeta(attr: Attribute): UserAttributeMeta | null {
397
530
  if (attr.type !== 'user') return null
398
531
  if (attr.meta == null) return {}
@@ -731,6 +864,19 @@ export interface UpdateComponentRequest {
731
864
 
732
865
  /**
733
866
  * List column definition.
867
+ *
868
+ * `attribute` is an attribute name or a dot path, told apart by the type of
869
+ * the first segment:
870
+ *
871
+ * - `name` — an attribute on the list's own entity.
872
+ * - `address.city` — a leaf inside one of its `object` attributes.
873
+ * - `company_id.name` — a field of the RELATED record, reached through a
874
+ * relation attribute (the first segment is the FK).
875
+ *
876
+ * A bare `object` attribute is not a valid column — it carries no value of
877
+ * its own, only leaves. Sorting follows the same grammar minus the relation
878
+ * hop: an attribute or an object path can be ordered by, a related field
879
+ * cannot (it would need a join).
734
880
  */
735
881
  export interface Column {
736
882
  attribute: string
@@ -744,7 +890,9 @@ export interface Column {
744
890
  export type SortDirection = 'asc' | 'desc'
745
891
 
746
892
  /**
747
- * Sort configuration.
893
+ * Sort configuration. `attribute` is an attribute name or an object path
894
+ * (`address.city`); relation paths are not sortable — ordering by a related
895
+ * field would need a join the records query doesn't do.
748
896
  */
749
897
  export interface SortConfig {
750
898
  attribute: string
@@ -771,6 +919,60 @@ export {
771
919
  type LogicalOperator,
772
920
  }
773
921
 
922
+ // ============================================================================
923
+ // Toolbar action buttons (shared by pages and lists)
924
+ // ============================================================================
925
+
926
+ /**
927
+ * What a page toolbar button invokes. Absent normalizes to `action` (pages
928
+ * persisted before `kind` existed).
929
+ */
930
+ export type PageActionKind = 'action' | 'workflow'
931
+
932
+ /**
933
+ * Page action definition — one toolbar button. `kind: action` invokes a
934
+ * function-service Action by slug (`action`) and may prefill its params;
935
+ * `kind: workflow` starts a manual run of a workflow by key (`workflow`) and
936
+ * may prefill its manual-trigger inputs. `params` / `inputs` map target field
937
+ * names to Liquid templates rendered against the page scope
938
+ * `{ record, entity, params, user }`; a resolved field is locked in the invoke
939
+ * dialog. `skip_confirmation` fires the target immediately when every required
940
+ * field resolved from the templates.
941
+ */
942
+ export interface PageAction {
943
+ label: string
944
+ icon: string
945
+ kind?: PageActionKind
946
+ action?: string
947
+ workflow?: string
948
+ params?: Record<string, string>
949
+ inputs?: Record<string, string>
950
+ skip_confirmation?: boolean
951
+ }
952
+
953
+ export const PageActionSchema = z.object({
954
+ label: z.string(),
955
+ icon: z.string(),
956
+ kind: z.enum(['action', 'workflow']).optional(),
957
+ action: z.string().optional(),
958
+ workflow: z.string().optional(),
959
+ params: z.record(z.string()).optional(),
960
+ inputs: z.record(z.string()).optional(),
961
+ skip_confirmation: z.boolean().optional(),
962
+ })
963
+
964
+ /**
965
+ * Whether a list's rows can be checked, and whether the checkboxes show from
966
+ * the start:
967
+ *
968
+ * - `on_demand` (default) — a Select toggle in the toolbar reveals them.
969
+ * - `always` — checkboxes are showing from the start.
970
+ * - `off` — rows can never be checked, even when the list carries actions.
971
+ */
972
+ export type SelectionMode = 'on_demand' | 'always' | 'off'
973
+
974
+ export const SelectionModeSchema = z.enum(['on_demand', 'always', 'off'])
975
+
774
976
  /**
775
977
  * List configuration.
776
978
  * Note: List uses `slug` as its primary identifier, not `id`.
@@ -782,6 +984,15 @@ export interface List extends AuditFields {
782
984
  name: string
783
985
  entity_slug: string
784
986
  columns: Column[]
987
+ /**
988
+ * Toolbar buttons on the list, same shape a page carries. They act on the
989
+ * rows SELECTED in the list, so an `action` button names an `entity_batch`
990
+ * action (invoked once with every selected record id) and prefill templates
991
+ * resolve against the list scope `{ selection, entity, user }`.
992
+ */
993
+ actions?: PageAction[]
994
+ /** Row-selection affordance; absent normalizes to `on_demand`. */
995
+ selection_mode?: SelectionMode
785
996
  /** Record page to open from this list; empty/absent = org default for the entity. */
786
997
  default_page_slug?: string
787
998
  sorting: SortConfig[]
@@ -805,6 +1016,8 @@ export const ListSchema = AuditFieldsSchema.extend({
805
1016
  name: z.string(),
806
1017
  entity_slug: z.string(),
807
1018
  columns: z.array(ColumnSchema),
1019
+ actions: z.array(PageActionSchema).optional(),
1020
+ selection_mode: SelectionModeSchema.optional(),
808
1021
  default_page_slug: z.string().optional(),
809
1022
  sorting: z.array(SortConfigSchema),
810
1023
  filters: z.array(FilterGroupSchema),
@@ -829,6 +1042,8 @@ export interface CreateListRequest {
829
1042
  entity_slug: string
830
1043
  name: string
831
1044
  columns: Column[]
1045
+ actions?: PageAction[]
1046
+ selection_mode?: SelectionMode
832
1047
  default_page_slug?: string
833
1048
  sorting: SortConfig[]
834
1049
  filters: FilterGroup[]
@@ -841,6 +1056,8 @@ export interface UpdateListRequest {
841
1056
  name?: string
842
1057
  module_slug?: string
843
1058
  columns?: Column[]
1059
+ actions?: PageAction[]
1060
+ selection_mode?: SelectionMode
844
1061
  /** Set to '' to clear back to the org default. */
845
1062
  default_page_slug?: string
846
1063
  sorting?: SortConfig[]
@@ -914,22 +1131,6 @@ export interface UpdateListViewRequest {
914
1131
  // Page Types
915
1132
  // ============================================================================
916
1133
 
917
- /**
918
- * Page action definition. Page-level toolbar item; addressed by permissions
919
- * and shortcuts systems.
920
- */
921
- export interface PageAction {
922
- label: string
923
- icon: string
924
- action: string
925
- }
926
-
927
- export const PageActionSchema = z.object({
928
- label: z.string(),
929
- icon: z.string(),
930
- action: z.string(),
931
- })
932
-
933
1134
  /**
934
1135
  * Page type — encodes what the page binds to and how it is served (chrome +
935
1136
  * auth posture both follow from it):
@@ -1252,3 +1453,30 @@ export interface UpdateDesignReferenceRequest {
1252
1453
  export interface DesignReferenceContent {
1253
1454
  content: string
1254
1455
  }
1456
+
1457
+ /* -------------------------------------------------------------------------
1458
+ Default-value sentinel
1459
+ ------------------------------------------------------------------------- */
1460
+
1461
+ /**
1462
+ * The one non-literal `default_value`: "whoever is writing the record".
1463
+ * Meaningful only on `user` and `principal` attributes, where data-service
1464
+ * resolves it to the caller's `{ type, id }` at write time — an owner field
1465
+ * granting `share`, an `assignee`, a `requested_by` fill themselves without a
1466
+ * hook. An object rather than a bare string because a bare string IS a valid
1467
+ * user value (clients send bare ids). Mirrors `metamodel.CurrentUserDefault`.
1468
+ */
1469
+ export const CURRENT_USER_DEFAULT = { type: 'current_user' } as const
1470
+ export type CurrentUserDefault = { type: 'current_user' }
1471
+
1472
+ /** True when a `default_value` is the current-user sentinel (and nothing else). */
1473
+ export function isCurrentUserDefault(value: unknown): value is CurrentUserDefault {
1474
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false
1475
+ const keys = Object.keys(value)
1476
+ return keys.length === 1 && (value as { type?: unknown }).type === 'current_user'
1477
+ }
1478
+
1479
+ /** Only the identity-valued attribute types can carry the sentinel. */
1480
+ export function acceptsCurrentUserDefault(type: AttributeType): boolean {
1481
+ return type === 'user' || type === 'principal'
1482
+ }
@@ -338,7 +338,14 @@ export interface CronTriggerParams {
338
338
  timezone: string
339
339
  }
340
340
 
341
- export type ManualTriggerParams = Record<string, never>
341
+ /**
342
+ * Manual trigger configuration. `input_schema` declares the typed inputs a
343
+ * manual run may provide (validated on run; they become the trigger item,
344
+ * addressable as `{{ $json.<name> }}`). Empty = the run takes no inputs.
345
+ */
346
+ export interface ManualTriggerParams {
347
+ input_schema?: Attribute[]
348
+ }
342
349
 
343
350
  export interface WebhookTriggerParams {
344
351
  token: string
@@ -474,6 +481,8 @@ export interface UpdateWorkflowRequest {
474
481
  */
475
482
  export interface RunWorkflowRequest {
476
483
  destination_node_id?: string
484
+ /** Values for the manual trigger's `input_schema`; seed the trigger item. */
485
+ inputs?: Record<string, unknown>
477
486
  }
478
487
 
479
488
  /** Where a standalone node test's input comes from. */
@@ -598,8 +607,9 @@ export interface ExecutionTriggerContext {
598
607
  kind: TriggerKind
599
608
  // schedule
600
609
  scheduled_at?: string
601
- // manual
610
+ // manual — the actor, and the partial-run bound when `destination_node_id` was passed
602
611
  actor?: UserRef
612
+ destination_node_id?: string
603
613
  // webhook
604
614
  received_at?: string
605
615
  // event
@@ -677,10 +687,17 @@ export interface ListExecutionsOptions extends ListOptions {
677
687
  // Execution API shapes
678
688
  // ---------------------------------------------------------------------------
679
689
 
680
- /** Execution detail: the header row plus its append-only node executions. */
690
+ /**
691
+ * Execution detail: the header row plus its append-only node executions.
692
+ * `nodes_total` is the number of nodes the pinned graph schedules for THIS run
693
+ * (reachable from the trigger, scoped to the destination path on a partial run;
694
+ * dead-branch and disabled nodes end as `skipped` rows) — the progress
695
+ * denominator.
696
+ */
681
697
  export interface GetExecutionDetailResponse {
682
698
  execution: WorkflowExecution
683
699
  node_executions: NodeExecution[]
700
+ nodes_total: number
684
701
  }
685
702
 
686
703
  /** Windows into one node run's stored items on one port. */