@anzusystems/common-admin 1.47.0-beta.dev-1789897769 → 1.47.0-beta.dev-1790102667

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/labs.d.ts CHANGED
@@ -8,12 +8,17 @@ import { DefineComponent } from 'vue';
8
8
  import { InjectionKey } from 'vue';
9
9
  import { MaybeRefOrGetter } from 'vue';
10
10
  import { Method } from 'axios';
11
+ import { Promisify } from '@vueuse/shared';
11
12
  import { PublicProps } from 'vue';
12
13
  import { Ref } from 'vue';
13
14
  import { RouteLocationRaw } from 'vue-router';
15
+ import { SetupStoreDefinition } from 'pinia';
14
16
  import { ShallowRef } from 'vue';
15
17
  import { ShallowUnwrapRef } from 'vue';
16
18
  import { UseDebounceFnReturn } from '@vueuse/shared';
19
+ import { Validation } from '@vuelidate/core';
20
+ import { ValidationRuleWithoutParams } from '@vuelidate/core';
21
+ import { ValidationRuleWithParams } from '@vuelidate/core';
17
22
  import { VNode } from 'vue';
18
23
 
19
24
  declare const __VLS_base: DefineComponent<__VLS_PublicProps, {
@@ -23,12 +28,12 @@ declare const __VLS_base: DefineComponent<__VLS_PublicProps, {
23
28
  "update:datatableHiddenColumns": (value: string[] | undefined) => any;
24
29
  "update:showDetail": (value: boolean) => any;
25
30
  } & {
26
- reset: () => any;
27
31
  submit: () => any;
32
+ reset: () => any;
28
33
  bookmarkLoadAfter: () => any;
29
34
  }, string, PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
30
- onReset?: (() => any) | undefined;
31
35
  onSubmit?: (() => any) | undefined;
36
+ onReset?: (() => any) | undefined;
32
37
  "onUpdate:datatableHiddenColumns"?: ((value: string[] | undefined) => any) | undefined;
33
38
  onBookmarkLoadAfter?: (() => any) | undefined;
34
39
  "onUpdate:showDetail"?: ((value: boolean) => any) | undefined;
@@ -43,6 +48,52 @@ declare const __VLS_base: DefineComponent<__VLS_PublicProps, {
43
48
  hideMore: boolean;
44
49
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
45
50
 
51
+ declare const __VLS_base_10: DefineComponent<__VLS_PublicProps_9, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
52
+ "update:user": (value: AnzuUser) => any;
53
+ }, string, PublicProps, Readonly<__VLS_PublicProps_9> & Readonly<{
54
+ "onUpdate:user"?: ((value: AnzuUser) => any) | undefined;
55
+ }>, {
56
+ readonly: boolean;
57
+ isEdit: boolean;
58
+ randomColor: boolean;
59
+ permissionGroupEndPoint: string;
60
+ idInput: boolean;
61
+ requiredMetadata: boolean;
62
+ enabledNote: string;
63
+ metadataNote: string;
64
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
65
+
66
+ declare const __VLS_base_11: DefineComponent<__VLS_PublicProps_11, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
67
+ "update:user": (value: AnzuUser) => any;
68
+ }, string, PublicProps, Readonly<__VLS_PublicProps_11> & Readonly<{
69
+ "onUpdate:user"?: ((value: AnzuUser) => any) | undefined;
70
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
71
+
72
+ declare const __VLS_base_12: DefineComponent<__VLS_PublicProps_12, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
73
+ "update:modelValue": (value: boolean) => any;
74
+ }, string, PublicProps, Readonly<__VLS_PublicProps_12> & Readonly<{
75
+ "onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
76
+ }>, {
77
+ note: string;
78
+ readonly: boolean;
79
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
80
+
81
+ declare const __VLS_base_13: DefineComponent<__VLS_PublicProps_14, {
82
+ refresh: () => void;
83
+ }, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
84
+ "update:activeTab": (value: string) => any;
85
+ } & {
86
+ created: (descriptor: AnyUserSystemDescriptor) => any;
87
+ }, string, PublicProps, Readonly<__VLS_PublicProps_14> & Readonly<{
88
+ onCreated?: ((descriptor: AnyUserSystemDescriptor) => any) | undefined;
89
+ "onUpdate:activeTab"?: ((value: string) => any) | undefined;
90
+ }>, {
91
+ unsavedChanges: boolean;
92
+ readonly: boolean;
93
+ refreshHook: UserSystemRefreshHook;
94
+ tabQueryKey: string;
95
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
96
+
46
97
  declare const __VLS_base_2: DefineComponent<__VLS_Props_2, {
47
98
  resetFilter: () => void;
48
99
  }, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
@@ -59,12 +110,12 @@ declare const __VLS_base_3: DefineComponent<__VLS_PublicProps_2, {
59
110
  }, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
60
111
  "update:datatableHiddenColumns": (value: string[] | undefined) => any;
61
112
  } & {
62
- reset: () => any;
63
113
  submit: () => any;
114
+ reset: () => any;
64
115
  bookmarkLoadAfter: () => any;
65
116
  }, string, PublicProps, Readonly<__VLS_PublicProps_2> & Readonly<{
66
- onReset?: (() => any) | undefined;
67
117
  onSubmit?: (() => any) | undefined;
118
+ onReset?: (() => any) | undefined;
68
119
  "onUpdate:datatableHiddenColumns"?: ((value: string[] | undefined) => any) | undefined;
69
120
  onBookmarkLoadAfter?: (() => any) | undefined;
70
121
  }>, {
@@ -108,9 +159,9 @@ declare const __VLS_base_5: DefineComponent<__VLS_PublicProps_4, {}, {}, {}, {},
108
159
  "onUpdate:loadingLocal"?: ((value: boolean) => any) | undefined;
109
160
  "onUpdate:fetchedItemsMinimal"?: ((value: Map<string | number, any>) => any) | undefined;
110
161
  }>, {
111
- required: boolean;
112
- label: string;
113
162
  loading: boolean;
163
+ label: string;
164
+ required: boolean;
114
165
  clearable: boolean;
115
166
  errorMessage: string;
116
167
  v: any;
@@ -127,6 +178,62 @@ declare const __VLS_base_5: DefineComponent<__VLS_PublicProps_4, {}, {}, {}, {},
127
178
  minSearchText: string;
128
179
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
129
180
 
181
+ declare const __VLS_base_6: DefineComponent<__VLS_Props_18, {
182
+ refresh: UseDebounceFnReturn<() => Promise<void>>;
183
+ resetFilter: () => void;
184
+ submitFilter: () => void;
185
+ }, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
186
+ rowClick: (permissionGroup: PermissionGroup) => any;
187
+ }, string, PublicProps, Readonly<__VLS_Props_18> & Readonly<{
188
+ onRowClick?: ((permissionGroup: PermissionGroup) => any) | undefined;
189
+ }>, {
190
+ entity: string;
191
+ endPoint: string;
192
+ canUpdate: boolean;
193
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
194
+
195
+ declare const __VLS_base_7: DefineComponent<__VLS_Props_19, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_19> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
196
+
197
+ declare const __VLS_base_8: DefineComponent<__VLS_Props_22, {
198
+ refresh: UseDebounceFnReturn<() => Promise<void>>;
199
+ resetFilter: () => void;
200
+ submitFilter: () => void;
201
+ }, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
202
+ rowClick: (user: AnzuUser) => any;
203
+ }, string, PublicProps, Readonly<__VLS_Props_22> & Readonly<{
204
+ onRowClick?: ((user: AnzuUser) => any) | undefined;
205
+ }>, {
206
+ entity: string;
207
+ endPoint: string;
208
+ canUpdate: boolean;
209
+ permissionGroupEndPoint: string;
210
+ systemColumns: Array<string | {
211
+ key: string;
212
+ title: string;
213
+ }>;
214
+ impersonate: (user: AnzuUser) => void;
215
+ canImpersonate: boolean;
216
+ filterFields: readonly MakeFilterOption[];
217
+ filterClient: () => AxiosInstance;
218
+ filterUserId: IntegerIdNullable;
219
+ filterStore: FilterStoreIdentifier;
220
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
221
+
222
+ declare const __VLS_base_9: DefineComponent<__VLS_PublicProps_8, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
223
+ "update:datatableHiddenColumns": (value: string[] | undefined) => any;
224
+ } & {
225
+ submit: () => any;
226
+ reset: () => any;
227
+ }, string, PublicProps, Readonly<__VLS_PublicProps_8> & Readonly<{
228
+ onSubmit?: (() => any) | undefined;
229
+ onReset?: (() => any) | undefined;
230
+ "onUpdate:datatableHiddenColumns"?: ((value: string[] | undefined) => any) | undefined;
231
+ }>, {
232
+ userId: IntegerIdNullable;
233
+ client: () => AxiosInstance;
234
+ store: FilterStoreIdentifier;
235
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
236
+
130
237
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
131
238
 
132
239
  declare const __VLS_export_10: DefineComponent<__VLS_Props_8, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
@@ -458,10 +565,163 @@ declare const __VLS_export_22: DefineComponent<__VLS_Props_15, {}, {}, {}, {}, C
458
565
 
459
566
  declare const __VLS_export_23: DefineComponent<__VLS_Props_16, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_16> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
460
567
 
568
+ declare const __VLS_export_24: DefineComponent<__VLS_PublicProps_6, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
569
+ "update:modelValue": (value: Permissions_2) => any;
570
+ }, string, PublicProps, Readonly<__VLS_PublicProps_6> & Readonly<{
571
+ "onUpdate:modelValue"?: ((value: Permissions_2) => any) | undefined;
572
+ }>, {
573
+ roles: string[];
574
+ resolvedPermissions: Permissions_2;
575
+ entity: string;
576
+ readonly: boolean;
577
+ endPoint: string;
578
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
579
+
580
+ declare const __VLS_export_25: __VLS_WithSlots_6<typeof __VLS_base_6, __VLS_Slots_6>;
581
+
582
+ declare const __VLS_export_26: __VLS_WithSlots_7<typeof __VLS_base_7, __VLS_Slots_7>;
583
+
584
+ declare const __VLS_export_27: DefineComponent<{}, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
585
+ submit: () => any;
586
+ reset: () => any;
587
+ }, string, PublicProps, Readonly<{}> & Readonly<{
588
+ onSubmit?: (() => any) | undefined;
589
+ onReset?: (() => any) | undefined;
590
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
591
+
592
+ declare const __VLS_export_28: DefineComponent<__VLS_Props_20, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_20> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
593
+
594
+ declare const __VLS_export_29: DefineComponent<__VLS_PublicProps_7, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
595
+ "update:modelValue": (value: number | number[] | null) => any;
596
+ }, string, PublicProps, Readonly<__VLS_PublicProps_7> & Readonly<{
597
+ "onUpdate:modelValue"?: ((value: number | number[] | null) => any) | undefined;
598
+ }>, {
599
+ label: string;
600
+ required: boolean;
601
+ dataCy: string;
602
+ entity: string;
603
+ clearable: boolean;
604
+ readonly: boolean;
605
+ multiple: boolean;
606
+ endPoint: string;
607
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
608
+
461
609
  declare const __VLS_export_3: __VLS_WithSlots_3<typeof __VLS_base_3, __VLS_Slots_3>;
462
610
 
611
+ declare const __VLS_export_30: __VLS_WithSlots_8<typeof __VLS_base_8, __VLS_Slots_8>;
612
+
613
+ declare const __VLS_export_31: __VLS_WithSlots_9<typeof __VLS_base_9, __VLS_Slots_9>;
614
+
615
+ declare const __VLS_export_32: __VLS_WithSlots_10<typeof __VLS_base_10, __VLS_Slots_10>;
616
+
617
+ declare const __VLS_export_33: DefineComponent<__VLS_PublicProps_10, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
618
+ "update:modelValue": (value: string[]) => any;
619
+ }, string, PublicProps, Readonly<__VLS_PublicProps_10> & Readonly<{
620
+ "onUpdate:modelValue"?: ((value: string[]) => any) | undefined;
621
+ }>, {
622
+ entity: string;
623
+ readonly: boolean;
624
+ endPoint: string;
625
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
626
+
627
+ declare const __VLS_export_34: __VLS_WithSlots_11<typeof __VLS_base_11, __VLS_Slots_11>;
628
+
629
+ declare const __VLS_export_35: __VLS_WithSlots_12<typeof __VLS_base_12, __VLS_Slots_12>;
630
+
631
+ declare const __VLS_export_36: DefineComponent<__VLS_PublicProps_13, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
632
+ "update:user": (value: BaseUser) => any;
633
+ }, string, PublicProps, Readonly<__VLS_PublicProps_13> & Readonly<{
634
+ "onUpdate:user"?: ((value: BaseUser) => any) | undefined;
635
+ }>, {
636
+ note: string;
637
+ required: boolean;
638
+ readonly: boolean;
639
+ isEdit: boolean;
640
+ randomColor: boolean;
641
+ validationScope: string | false | symbol;
642
+ idInput: boolean;
643
+ scopeSystem: string;
644
+ scopeSubject: string;
645
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
646
+
647
+ declare const __VLS_export_37: DefineComponent<__VLS_Props_29, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_29> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
648
+
649
+ declare const __VLS_export_38: DefineComponent<__VLS_Props_30, {
650
+ refresh: () => Promise<void>;
651
+ }, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
652
+ create: (descriptor: AnyUserSystemDescriptor, user: BaseUser) => any;
653
+ }, string, PublicProps, Readonly<__VLS_Props_30> & Readonly<{
654
+ onCreate?: ((descriptor: AnyUserSystemDescriptor, user: BaseUser) => any) | undefined;
655
+ }>, {
656
+ source: BaseUser | null;
657
+ readonly: boolean;
658
+ createEnabled: boolean;
659
+ creating: boolean;
660
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
661
+
662
+ declare const __VLS_export_39: DefineComponent<__VLS_Props_31, {
663
+ refresh: () => void;
664
+ refreshSystem: (system: string) => void;
665
+ }, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
666
+ create: (descriptor: AnyUserSystemDescriptor, user: BaseUser) => any;
667
+ }, string, PublicProps, Readonly<__VLS_Props_31> & Readonly<{
668
+ onCreate?: ((descriptor: AnyUserSystemDescriptor, user: BaseUser) => any) | undefined;
669
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
670
+
463
671
  declare const __VLS_export_4: DefineComponent<{}, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
464
672
 
673
+ declare const __VLS_export_40: __VLS_WithSlots_13<typeof __VLS_base_13, __VLS_Slots_13>;
674
+
675
+ declare const __VLS_export_41: DefineComponent<__VLS_Props_33, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
676
+ confirm: (user: BaseUser) => any;
677
+ }, string, PublicProps, Readonly<__VLS_Props_33> & Readonly<{
678
+ onConfirm?: ((user: BaseUser) => any) | undefined;
679
+ }>, {
680
+ disabled: boolean;
681
+ userId: IntegerIdNullable;
682
+ willBeEnabled: boolean;
683
+ loading: boolean;
684
+ source: BaseUser | null;
685
+ requiredMetadata: boolean;
686
+ createNote: string;
687
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
688
+
689
+ declare const __VLS_export_42: DefineComponent<__VLS_Props_34, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_34> & Readonly<{}>, {
690
+ internalLabel: string;
691
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
692
+
693
+ declare const __VLS_export_43: DefineComponent<__VLS_Props_35, {
694
+ search: (value: string) => Promise<void>;
695
+ }, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
696
+ searched: (term: string) => any;
697
+ }, string, PublicProps, Readonly<__VLS_Props_35> & Readonly<{
698
+ onSearched?: ((term: string) => any) | undefined;
699
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
700
+
701
+ declare const __VLS_export_44: DefineComponent<__VLS_PublicProps_15, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
702
+ "update:open": (value: boolean) => any;
703
+ } & {
704
+ run: (systems: string[]) => any;
705
+ }, string, PublicProps, Readonly<__VLS_PublicProps_15> & Readonly<{
706
+ onRun?: ((systems: string[]) => any) | undefined;
707
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
708
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
709
+
710
+ declare const __VLS_export_45: DefineComponent<__VLS_PublicProps_16, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
711
+ "update:open": (value: boolean) => any;
712
+ } & {
713
+ confirm: (payload: {
714
+ target: BaseUser;
715
+ systems: string[];
716
+ }) => any;
717
+ }, string, PublicProps, Readonly<__VLS_PublicProps_16> & Readonly<{
718
+ onConfirm?: ((payload: {
719
+ target: BaseUser;
720
+ systems: string[];
721
+ }) => any) | undefined;
722
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
723
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
724
+
465
725
  declare const __VLS_export_5: DefineComponent<__VLS_Props_4, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
466
726
  change: () => any;
467
727
  }, string, PublicProps, Readonly<__VLS_Props_4> & Readonly<{
@@ -535,6 +795,34 @@ declare type __VLS_ModelProps = {
535
795
  'showDetail'?: boolean;
536
796
  };
537
797
 
798
+ declare type __VLS_ModelProps_10 = {
799
+ modelValue: string[];
800
+ };
801
+
802
+ declare type __VLS_ModelProps_11 = {
803
+ 'user': AnzuUser;
804
+ };
805
+
806
+ declare type __VLS_ModelProps_12 = {
807
+ modelValue: boolean;
808
+ };
809
+
810
+ declare type __VLS_ModelProps_13 = {
811
+ 'user': BaseUser;
812
+ };
813
+
814
+ declare type __VLS_ModelProps_14 = {
815
+ 'activeTab'?: string;
816
+ };
817
+
818
+ declare type __VLS_ModelProps_15 = {
819
+ 'open': boolean;
820
+ };
821
+
822
+ declare type __VLS_ModelProps_16 = {
823
+ 'open': boolean;
824
+ };
825
+
538
826
  declare type __VLS_ModelProps_2 = {
539
827
  'datatableHiddenColumns'?: string[] | undefined;
540
828
  };
@@ -553,6 +841,23 @@ declare type __VLS_ModelProps_5 = {
553
841
  modelValue: boolean;
554
842
  };
555
843
 
844
+ declare type __VLS_ModelProps_6 = {
845
+ modelValue: Permissions_2;
846
+ };
847
+
848
+ declare type __VLS_ModelProps_7 = {
849
+ modelValue: IntegerId | IntegerId[] | null;
850
+ };
851
+
852
+ declare type __VLS_ModelProps_8 = {
853
+ /** The column set a bookmark restores along with the filter values. */
854
+ 'datatableHiddenColumns'?: string[] | undefined;
855
+ };
856
+
857
+ declare type __VLS_ModelProps_9 = {
858
+ 'user': AnzuUser;
859
+ };
860
+
556
861
  declare type __VLS_PrettifyLocal<T> = (T extends any ? {
557
862
  [K in keyof T]: T[K];
558
863
  } : {
@@ -667,10 +972,235 @@ declare type __VLS_Props_16 = {
667
972
  logPaths: LogPaths;
668
973
  };
669
974
 
975
+ declare type __VLS_Props_17 = {
976
+ client: AxiosClientFn;
977
+ /** Which backend's permission vocabulary to draw. Never a global -- see `permissionConfigActions`. */
978
+ system: string;
979
+ entity?: string | undefined;
980
+ endPoint?: string | undefined;
981
+ /**
982
+ * The grants the subject already has from roles and groups. Undefined means "this model is a
983
+ * group, not a user": the origin column then reads every explicit grant as coming from the
984
+ * group itself rather than from the user.
985
+ */
986
+ resolvedPermissions?: Permissions_2 | undefined;
987
+ roles?: string[];
988
+ /** One component for detail and edit (decision 27). Readonly drops the grant column. */
989
+ readonly?: boolean;
990
+ };
991
+
992
+ declare type __VLS_Props_18 = {
993
+ client: AxiosClientFn;
994
+ /** Backend identity: keys the filter store and the cache, and reaches every api call. */
995
+ system: string;
996
+ entity?: string | undefined;
997
+ endPoint?: string | undefined;
998
+ /** Where a row and the detail button go. The library cannot know an app's typed route names. */
999
+ detailRoute: (permissionGroup: PermissionGroup) => RouteLocationRaw;
1000
+ editRoute: (permissionGroup: PermissionGroup) => RouteLocationRaw;
1001
+ /** Already-evaluated ACL. A boolean, not an `AclValue`: see 5.1 of the plan. */
1002
+ canUpdate?: boolean;
1003
+ };
1004
+
1005
+ declare type __VLS_Props_19 = {
1006
+ client: AxiosClientFn;
1007
+ system: string;
1008
+ entity?: string | undefined;
1009
+ endPoint?: string | undefined;
1010
+ };
1011
+
670
1012
  declare type __VLS_Props_2 = {
671
1013
  formName?: string;
672
1014
  };
673
1015
 
1016
+ declare type __VLS_Props_20 = {
1017
+ client: AxiosClientFn;
1018
+ /** Backend identity for the permission config fetch, not the i18n namespace below. */
1019
+ system: string;
1020
+ entity?: string | undefined;
1021
+ endPoint?: string | undefined;
1022
+ };
1023
+
1024
+ declare type __VLS_Props_21 = {
1025
+ client: AxiosClientFn;
1026
+ system: string;
1027
+ entity?: string | undefined;
1028
+ endPoint?: string | undefined;
1029
+ label?: string | undefined;
1030
+ required?: boolean | undefined;
1031
+ multiple?: boolean;
1032
+ clearable?: boolean;
1033
+ readonly?: boolean;
1034
+ dataCy?: string;
1035
+ };
1036
+
1037
+ declare type __VLS_Props_22 = {
1038
+ client: AxiosClientFn;
1039
+ system: string;
1040
+ entity?: string | undefined;
1041
+ endPoint?: string | undefined;
1042
+ detailRoute: (user: AnzuUser) => RouteLocationRaw;
1043
+ editRoute: (user: AnzuUser) => RouteLocationRaw;
1044
+ /** Already-evaluated ACL of the owning system. */
1045
+ canUpdate?: boolean;
1046
+ /** The permission-group endpoint, which is not the user one. */
1047
+ permissionGroupEndPoint?: string;
1048
+ /**
1049
+ * Extra columns the app draws through `#systemColumns`, appended after the shared ones.
1050
+ *
1051
+ * A bare key takes its header from the library's own `common.anzuUser.model.*`, which holds
1052
+ * eight keys and none of any system's -- so a system column passes its title already
1053
+ * translated, out of the namespace that has it.
1054
+ */
1055
+ systemColumns?: Array<string | {
1056
+ key: string;
1057
+ title: string;
1058
+ }>;
1059
+ /**
1060
+ * Signing in as somebody else, as a switchable feature.
1061
+ *
1062
+ * A callback rather than a path, because there is more than one mechanism: cms posts to
1063
+ * `/adm/users/{id}/impersonate` and gets a JWT with an impersonation claim, blog opens the
1064
+ * public site through `window.open`. Only the cms one reaches a shared component -- blog's
1065
+ * hangs off its product user, which is a different view -- so one prop is enough for now.
1066
+ * Left unset, nothing is drawn.
1067
+ */
1068
+ impersonate?: ((user: AnzuUser) => void) | undefined;
1069
+ canImpersonate?: boolean;
1070
+ /**
1071
+ * Filter fields this system adds to the shared three.
1072
+ *
1073
+ * A parameter and not part of the shared list, because the same filter is not the same query
1074
+ * everywhere: cms asks for permission groups with `memberOf`, dam with `custom`, and
1075
+ * `allowedSites` exists only in cms. A plain field needs nothing more -- the generic renderer
1076
+ * draws it -- while one that wants a remote autocomplete comes in through `#filter.<name>`.
1077
+ */
1078
+ filterFields?: readonly MakeFilterOption[];
1079
+ /**
1080
+ * Saved filters, which are stored per user, so both are needed for the button to appear. cms
1081
+ * and dam have them on the list this replaces; the other three admins do not.
1082
+ */
1083
+ filterClient?: (() => AxiosInstance) | undefined;
1084
+ filterUserId?: IntegerIdNullable | undefined;
1085
+ /** Where saved bookmarks are filed; see `AAnzuUserFilter`. */
1086
+ filterStore?: FilterStoreIdentifier | undefined;
1087
+ };
1088
+
1089
+ declare type __VLS_Props_23 = {
1090
+ /**
1091
+ * Both are what switches the bookmark UI on in `AFilterWrapper`, and both have to be there for
1092
+ * it to appear -- bookmarks are stored per user. Left unset, the filter is drawn without them,
1093
+ * which is what admin-inhouse, blog and forum have.
1094
+ */
1095
+ client?: (() => AxiosInstance) | undefined;
1096
+ userId?: IntegerIdNullable | undefined;
1097
+ /**
1098
+ * What the saved bookmarks are filed under on the server.
1099
+ *
1100
+ * Left unset it is the filter's own `common` / `anzuUser`. cms overrides it with the pair its
1101
+ * old list used, so the bookmarks operators already have keep showing up -- the field names are
1102
+ * the same, and a new key would simply orphan them.
1103
+ */
1104
+ store?: FilterStoreIdentifier | undefined;
1105
+ };
1106
+
1107
+ declare type __VLS_Props_24 = {
1108
+ client: AxiosClientFn;
1109
+ system: string;
1110
+ /**
1111
+ * The permission-group endpoint, which is not the user one.
1112
+ *
1113
+ * There is deliberately no `entity` prop here. `entity` names a *resource*, not a system, and
1114
+ * it is what a server validation failure is filed under -- so the group autocomplete, the role
1115
+ * list and the permission editor each use their own, and passing the user's down would file a
1116
+ * group's error under the user's labels.
1117
+ */
1118
+ permissionGroupEndPoint?: string;
1119
+ /**
1120
+ * One component for detail and edit (decision 27). Two parallel components drift: a field
1121
+ * added to the editable one and forgotten in the other is a silent divergence with nothing to
1122
+ * fail.
1123
+ */
1124
+ readonly?: boolean;
1125
+ isEdit?: boolean;
1126
+ /** From the system's descriptor. */
1127
+ requiredMetadata?: boolean;
1128
+ idInput?: boolean;
1129
+ randomColor?: boolean;
1130
+ enabledNote?: string | undefined;
1131
+ metadataNote?: string | undefined;
1132
+ };
1133
+
1134
+ declare type __VLS_Props_25 = {
1135
+ client: AxiosClientFn;
1136
+ /** Roles are per backend: they come from that system's `/adm/v1/permissions/config`. */
1137
+ system: string;
1138
+ entity?: string | undefined;
1139
+ endPoint?: string | undefined;
1140
+ readonly?: boolean;
1141
+ };
1142
+
1143
+ declare type __VLS_Props_26 = {
1144
+ /**
1145
+ * Reads the source account from the server. It is a prop because the shape of a user differs per
1146
+ * system -- cms answers `CmsUserDto`, dam `DamUserDto` -- and because the page already holds an
1147
+ * api instance pointed at the right backend.
1148
+ */
1149
+ fetchSourceUser: (id: number) => Promise<AnzuUser>;
1150
+ /**
1151
+ * Copies whatever the system keeps beyond roles, groups and grants. cms has nineteen such
1152
+ * fields; systems with none leave this out.
1153
+ */
1154
+ copySystemFields?: ((target: AnzuUser, source: AnzuUser) => void) | undefined;
1155
+ /** i18n keys listed in the dialog, so the operator sees exactly what will be overwritten. */
1156
+ copiedSettingKeys?: string[];
1157
+ };
1158
+
1159
+ declare type __VLS_Props_27 = {
1160
+ readonly?: boolean;
1161
+ /**
1162
+ * The system's `enabledNote`. A static string from the descriptor rather than a slot: a slot
1163
+ * would have to be filled by every admin separately, could drift from the wording in the bulk
1164
+ * dialog, and -- worst -- could be forgotten in admin-blog, which is the one place the sentence
1165
+ * matters most. The slot below stays as an escape hatch for more than a line of text.
1166
+ */
1167
+ note?: string | undefined;
1168
+ };
1169
+
1170
+ declare type __VLS_Props_28 = {
1171
+ /**
1172
+ * The system's validation profile (`requiredMetadata`). The cross-system repair form passes
1173
+ * `true` outright: it writes to nine places at once, and a loose form could put an empty name
1174
+ * into cms -- a record cms's own form would then refuse to save.
1175
+ */
1176
+ required?: boolean;
1177
+ /**
1178
+ * Whether the id is typed in at all. False only in cms, whose backend resolves it from SSO.
1179
+ * With `isEdit` this makes three states, which one `readonly` could not express: not drawn,
1180
+ * editable, or shown read-only.
1181
+ */
1182
+ idInput?: boolean;
1183
+ isEdit?: boolean;
1184
+ readonly?: boolean;
1185
+ /**
1186
+ * Random colour on an empty value, as all four admins do today. Deliberately not passed by the
1187
+ * cross-system repair form: it is always strict, so it would invent a colour on open and mark
1188
+ * it as a change in every system at once.
1189
+ */
1190
+ randomColor?: boolean;
1191
+ /** The system's `metadataNote` -- the same sentence the cross-system dialog shows. */
1192
+ note?: string | undefined;
1193
+ /** i18n namespace for the field labels; the backend identity does not belong here. */
1194
+ scopeSystem?: string;
1195
+ scopeSubject?: string;
1196
+ /** Vuelidate scope. Omitted means the page's own collector picks these rules up. */
1197
+ validationScope?: string | symbol | false | undefined;
1198
+ };
1199
+
1200
+ declare type __VLS_Props_29 = {
1201
+ axes: UserSystemAxes;
1202
+ };
1203
+
674
1204
  declare type __VLS_Props_3 = {
675
1205
  hideButtons?: boolean;
676
1206
  formName?: string;
@@ -680,6 +1210,125 @@ declare type __VLS_Props_3 = {
680
1210
  store?: FilterStoreIdentifier | boolean;
681
1211
  };
682
1212
 
1213
+ declare type __VLS_Props_30 = {
1214
+ descriptor: AnyUserSystemDescriptor;
1215
+ userId: IntegerId;
1216
+ /**
1217
+ * On a viewing page there is no Create. A write action on a read-only screen would be the first
1218
+ * in the fleet; Manage stays, because it only leads somewhere.
1219
+ */
1220
+ readonly?: boolean;
1221
+ /** Whether the account about to be created would be switched on. */
1222
+ createEnabled?: boolean;
1223
+ /** What the owning system holds, to prefill the create form. */
1224
+ source?: BaseUser | null;
1225
+ creating?: boolean;
1226
+ };
1227
+
1228
+ declare type __VLS_Props_31 = {
1229
+ descriptors: AnyUserSystemDescriptor[];
1230
+ userId: IntegerId;
1231
+ readonly?: boolean;
1232
+ /** Whether an account created from here would be switched on -- the dialog says so out loud. */
1233
+ createEnabled?: boolean;
1234
+ /** What the owning system holds, to prefill the create form. */
1235
+ source?: BaseUser | null;
1236
+ /** The system a create is currently running for. */
1237
+ creatingSystem?: string | null;
1238
+ };
1239
+
1240
+ declare type __VLS_Props_32 = {
1241
+ userId: IntegerId;
1242
+ /** Which tab carries the owning form, i.e. gets the slot. */
1243
+ owner: string;
1244
+ /**
1245
+ * The tabs, in the order they are drawn, plus "other systems" appended by this component.
1246
+ *
1247
+ * A prop and not something derived from the descriptor array, because the list depends on the
1248
+ * route rather than on what the admin owns: admin-inhouse owns four systems and has two tabs,
1249
+ * since the system is part of the path.
1250
+ */
1251
+ ownedTabs: string[];
1252
+ /** Every system this admin can reach. The "other systems" tab lists the ones not in a tab. */
1253
+ descriptors: AnyUserSystemDescriptor[];
1254
+ /**
1255
+ * "After a 401, refresh once and try again."
1256
+ *
1257
+ * The library cannot decide this for itself: the mechanism exists only in the apps, and each
1258
+ * one does it differently -- inhouse `refreshSession`, cms and contentHub their own
1259
+ * `refresh-token` call. Without it an expired token renders as "no account in this system",
1260
+ * which is the one confusion decision 16 forbids. Every panel this shell draws gets it.
1261
+ */
1262
+ refreshHook?: UserSystemRefreshHook | undefined;
1263
+ readonly?: boolean;
1264
+ /**
1265
+ * Whether the owning form holds edits that have not been saved.
1266
+ *
1267
+ * It drives two things. The dot on the owning tab, so the operator can see it from the other
1268
+ * tabs -- the Save button itself is visible everywhere, by decision, because a button that
1269
+ * disappeared would read as "this is read-only". And the guard below, which is the only thing
1270
+ * standing between unsaved work and the button in a panel that leaves the page: switching a tab
1271
+ * is not navigation, so nothing else ever asks.
1272
+ */
1273
+ unsavedChanges?: boolean;
1274
+ /** Query key for the deep link. */
1275
+ tabQueryKey?: string;
1276
+ };
1277
+
1278
+ declare type __VLS_Props_33 = {
1279
+ /** The system's name as the app translates it. */
1280
+ systemLabel: string;
1281
+ /** The system's `createNote` -- what is special about having an account there. */
1282
+ createNote?: string | undefined;
1283
+ /**
1284
+ * Whether the account about to be created will be switched on.
1285
+ *
1286
+ * The sentence about a working public account is composed here rather than carried by the
1287
+ * descriptor, because it depends on the value being sent: creating from a panel copies the
1288
+ * source account's `enabled` -- usually true -- while creating after a search that found
1289
+ * nobody sends false, since there is no source to copy from.
1290
+ */
1291
+ willBeEnabled?: boolean;
1292
+ loading?: boolean;
1293
+ disabled?: boolean;
1294
+ /** The target system's `requiredMetadata`: the profile the form validates against. */
1295
+ requiredMetadata?: boolean;
1296
+ /** The person's id. Always drawn and never editable here -- this path is about somebody who exists. */
1297
+ userId?: IntegerIdNullable;
1298
+ /**
1299
+ * What is already known about them, to prefill the form.
1300
+ *
1301
+ * Not the body that gets posted: the caller reads the source again immediately before the POST.
1302
+ * This is what the operator sees and completes, and completing it is the point -- a person known
1303
+ * only in blog usually has an empty `person`, while the target may require it, so a silent copy
1304
+ * would create a record the target's own form then refuses to save.
1305
+ */
1306
+ source?: BaseUser | null;
1307
+ };
1308
+
1309
+ declare type __VLS_Props_34 = {
1310
+ target: UserSystemManageTarget;
1311
+ /** The system's name as the app translates it. */
1312
+ systemLabel: string;
1313
+ /** "Edit" instead of "Manage in X" -- used where the operator is already in that admin. */
1314
+ internalLabel?: string | undefined;
1315
+ };
1316
+
1317
+ declare type __VLS_Props_35 = {
1318
+ /** Order matters twice: the order of the rows, and the priority when pre-filling. */
1319
+ descriptors: AnyUserSystemDescriptor[];
1320
+ refreshHook?: UserSystemRefreshHook | undefined;
1321
+ };
1322
+
1323
+ declare type __VLS_Props_36 = {
1324
+ action: BulkActionType;
1325
+ descriptors: AnyUserSystemDescriptor[];
1326
+ };
1327
+
1328
+ declare type __VLS_Props_37 = {
1329
+ descriptors: AnyUserSystemDescriptor[];
1330
+ };
1331
+
683
1332
  declare type __VLS_Props_4 = {
684
1333
  name: string;
685
1334
  allT?: string;
@@ -728,6 +1377,20 @@ declare type __VLS_Props_9 = {
728
1377
 
729
1378
  declare type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
730
1379
 
1380
+ declare type __VLS_PublicProps_10 = __VLS_Props_25 & __VLS_ModelProps_10;
1381
+
1382
+ declare type __VLS_PublicProps_11 = __VLS_Props_26 & __VLS_ModelProps_11;
1383
+
1384
+ declare type __VLS_PublicProps_12 = __VLS_Props_27 & __VLS_ModelProps_12;
1385
+
1386
+ declare type __VLS_PublicProps_13 = __VLS_Props_28 & __VLS_ModelProps_13;
1387
+
1388
+ declare type __VLS_PublicProps_14 = __VLS_Props_32 & __VLS_ModelProps_14;
1389
+
1390
+ declare type __VLS_PublicProps_15 = __VLS_Props_36 & __VLS_ModelProps_15;
1391
+
1392
+ declare type __VLS_PublicProps_16 = __VLS_Props_37 & __VLS_ModelProps_16;
1393
+
731
1394
  declare type __VLS_PublicProps_2 = __VLS_Props_3 & __VLS_ModelProps_2;
732
1395
 
733
1396
  declare type __VLS_PublicProps_3 = __VLS_Props_11 & __VLS_ModelProps_3;
@@ -736,6 +1399,14 @@ declare type __VLS_PublicProps_4 = __VLS_Props_13 & __VLS_ModelProps_4;
736
1399
 
737
1400
  declare type __VLS_PublicProps_5 = __VLS_Props_14 & __VLS_ModelProps_5;
738
1401
 
1402
+ declare type __VLS_PublicProps_6 = __VLS_Props_17 & __VLS_ModelProps_6;
1403
+
1404
+ declare type __VLS_PublicProps_7 = __VLS_Props_21 & __VLS_ModelProps_7;
1405
+
1406
+ declare type __VLS_PublicProps_8 = __VLS_Props_23 & __VLS_ModelProps_8;
1407
+
1408
+ declare type __VLS_PublicProps_9 = __VLS_Props_24 & __VLS_ModelProps_9;
1409
+
739
1410
  declare type __VLS_Slots = {} & {
740
1411
  [K in NonNullable<typeof __VLS_123>]?: (props: typeof __VLS_124) => any;
741
1412
  } & {
@@ -750,6 +1421,26 @@ declare type __VLS_Slots = {} & {
750
1421
  detail?: (props: typeof __VLS_108) => any;
751
1422
  };
752
1423
 
1424
+ declare type __VLS_Slots_10 = {} & {
1425
+ copyPermissions?: (props: typeof __VLS_42) => any;
1426
+ } & {
1427
+ systemFields?: (props: typeof __VLS_50) => any;
1428
+ } & {
1429
+ actions?: (props: typeof __VLS_80) => any;
1430
+ };
1431
+
1432
+ declare type __VLS_Slots_11 = {} & {
1433
+ sourcePicker?: (props: typeof __VLS_35) => any;
1434
+ };
1435
+
1436
+ declare type __VLS_Slots_12 = {} & {
1437
+ note?: (props: typeof __VLS_17) => any;
1438
+ };
1439
+
1440
+ declare type __VLS_Slots_13 = {} & {
1441
+ default?: (props: typeof __VLS_30) => any;
1442
+ };
1443
+
753
1444
  declare type __VLS_Slots_2 = {} & {
754
1445
  default?: (props: typeof __VLS_11) => any;
755
1446
  };
@@ -772,12 +1463,64 @@ declare type __VLS_Slots_5 = {} & {
772
1463
  'append-item'?: (props: typeof __VLS_14) => any;
773
1464
  };
774
1465
 
1466
+ declare type __VLS_Slots_6 = {} & {
1467
+ createdBy?: (props: typeof __VLS_47) => any;
1468
+ } & {
1469
+ modifiedBy?: (props: typeof __VLS_55) => any;
1470
+ };
1471
+
1472
+ declare type __VLS_Slots_7 = {} & {
1473
+ tracking?: (props: typeof __VLS_82) => any;
1474
+ };
1475
+
1476
+ declare type __VLS_Slots_8 = {} & {
1477
+ [K in NonNullable<typeof __VLS_12>]?: (props: typeof __VLS_13) => any;
1478
+ } & {
1479
+ permissionGroups?: (props: typeof __VLS_54) => any;
1480
+ } & {
1481
+ systemColumns?: (props: typeof __VLS_70) => any;
1482
+ } & {
1483
+ createdBy?: (props: typeof __VLS_78) => any;
1484
+ } & {
1485
+ modifiedBy?: (props: typeof __VLS_86) => any;
1486
+ } & {
1487
+ rowActions?: (props: typeof __VLS_111) => any;
1488
+ };
1489
+
1490
+ declare type __VLS_Slots_9 = {} & {
1491
+ [K in NonNullable<typeof __VLS_20>]?: (props: typeof __VLS_21) => any;
1492
+ };
1493
+
775
1494
  declare type __VLS_WithSlots<T, S> = T & {
776
1495
  new (): {
777
1496
  $slots: S;
778
1497
  };
779
1498
  };
780
1499
 
1500
+ declare type __VLS_WithSlots_10<T, S> = T & {
1501
+ new (): {
1502
+ $slots: S;
1503
+ };
1504
+ };
1505
+
1506
+ declare type __VLS_WithSlots_11<T, S> = T & {
1507
+ new (): {
1508
+ $slots: S;
1509
+ };
1510
+ };
1511
+
1512
+ declare type __VLS_WithSlots_12<T, S> = T & {
1513
+ new (): {
1514
+ $slots: S;
1515
+ };
1516
+ };
1517
+
1518
+ declare type __VLS_WithSlots_13<T, S> = T & {
1519
+ new (): {
1520
+ $slots: S;
1521
+ };
1522
+ };
1523
+
781
1524
  declare type __VLS_WithSlots_2<T, S> = T & {
782
1525
  new (): {
783
1526
  $slots: S;
@@ -802,6 +1545,40 @@ declare type __VLS_WithSlots_5<T, S> = T & {
802
1545
  };
803
1546
  };
804
1547
 
1548
+ declare type __VLS_WithSlots_6<T, S> = T & {
1549
+ new (): {
1550
+ $slots: S;
1551
+ };
1552
+ };
1553
+
1554
+ declare type __VLS_WithSlots_7<T, S> = T & {
1555
+ new (): {
1556
+ $slots: S;
1557
+ };
1558
+ };
1559
+
1560
+ declare type __VLS_WithSlots_8<T, S> = T & {
1561
+ new (): {
1562
+ $slots: S;
1563
+ };
1564
+ };
1565
+
1566
+ declare type __VLS_WithSlots_9<T, S> = T & {
1567
+ new (): {
1568
+ $slots: S;
1569
+ };
1570
+ };
1571
+
1572
+ export declare const AAnzuUserDatatable: typeof __VLS_export_30;
1573
+
1574
+ export declare const AAnzuUserFilter: typeof __VLS_export_31;
1575
+
1576
+ export declare const AAnzuUserForm: typeof __VLS_export_32;
1577
+
1578
+ export declare const AAnzuUserRoleAutocomplete: typeof __VLS_export_33;
1579
+
1580
+ declare type AclValue = `${string}_${string}_${string}`;
1581
+
805
1582
  export declare const ADatatableOrdering: typeof __VLS_export_13;
806
1583
 
807
1584
  export declare const ADatatablePagination: typeof __VLS_export_14;
@@ -839,6 +1616,8 @@ declare interface AddButtonSlotProps_3 {
839
1616
  };
840
1617
  }
841
1618
 
1619
+ declare type AddToCachedArgs<T extends DocId | IntegerId> = Array<T | null | undefined> | Array<Array<T | null | undefined> | T | null | undefined>;
1620
+
842
1621
  export declare const AFilterBooleanSelect: typeof __VLS_export_5;
843
1622
 
844
1623
  export declare const AFilterDatetimePicker: typeof __VLS_export_6;
@@ -875,16 +1654,123 @@ export declare const ALogListView: typeof __VLS_export_22;
875
1654
 
876
1655
  export declare const ANestedSortableListEditor: typeof __VLS_export_20;
877
1656
 
1657
+ /**
1658
+ * The erasure boundary for a heterogeneous array.
1659
+ *
1660
+ * Descriptors differ in `TUser` -- blog's `extraState` reaches for `status`, forum's for
1661
+ * `settings.banned` -- so an array of them cannot keep each one's type. Without a single place to
1662
+ * erase it, `strict: true` would demand a cast in every admin, at every call site. This does it
1663
+ * once, where the array is built.
1664
+ */
1665
+ export declare type AnyUserSystemDescriptor = UserSystemDescriptor<string, AnzuUser>;
1666
+
1667
+ export declare const ANZU_USER_ENDPOINT = "/adm/v1/anzu-user";
1668
+
1669
+ export declare const ANZU_USER_ENTITY = "anzuUser";
1670
+
1671
+ declare interface AnzuUser extends AnzuUserAndTimeTrackingAware, BaseUser {
1672
+ enabled: boolean;
1673
+ locale: LanguageCode | null;
1674
+ roles: string[];
1675
+ permissionGroups: IntegerId[];
1676
+ permissions: Permissions_2;
1677
+ resolvedPermissions: Permissions_2;
1678
+ _resourceName: string;
1679
+ _system: string;
1680
+ }
1681
+
1682
+ export declare interface AnzuUserActionsParams {
1683
+ client: AxiosClientFn;
1684
+ system: string;
1685
+ entity?: string;
1686
+ /**
1687
+ * i18n scope for a server-side validation failure, which is a different question from which
1688
+ * backend answered. `AnzuApiValidationError` builds `<system>.<entity>.model.<field>` keys, so
1689
+ * the pair has to name the namespace the *labels* live under. It defaults to `common` +
1690
+ * `anzuUser`, which is where the shared form's own fields are; an admin whose form carries
1691
+ * system fields as well passes its own pair, and keeps the base keys beside them.
1692
+ */
1693
+ validationSystem?: string;
1694
+ validationEntity?: string;
1695
+ endPoint?: string;
1696
+ /** Vuelidate scope, when the page collects its fields under one of its own. */
1697
+ validationScope?: string | symbol;
1698
+ }
1699
+
878
1700
  declare interface AnzuUserAndTimeTrackingAware extends CreatedByAware {
879
1701
  createdAt: DatetimeUTC;
880
1702
  modifiedAt: DatetimeUTC;
881
1703
  modifiedBy: IntegerIdNullable;
882
1704
  }
883
1705
 
1706
+ export declare interface AnzuUserApiParams {
1707
+ client: AxiosClientFn;
1708
+ /**
1709
+ * Both reach every `useApiRequest` built here. The admins' copies declared `system = 'common'`
1710
+ * and `entity = 'anzuUser'` as file constants, which is why a shared version has to take them:
1711
+ * the same file now serves nine backends, and the error context has to name the right one.
1712
+ */
1713
+ system: string;
1714
+ entity?: string;
1715
+ /**
1716
+ * i18n scope for a server-side validation failure, which is a different question from which
1717
+ * backend answered. `AnzuApiValidationError` builds `<system>.<entity>.model.<field>` keys, and
1718
+ * for a component shared by nine backends the labels are always the library's own `common.*` --
1719
+ * `weather.anzuUser.model.email` exists nowhere. Defaults to `common` plus the entity;
1720
+ * contentHub passes its own pair to keep the keys it already has.
1721
+ */
1722
+ validationSystem?: string;
1723
+ validationEntity?: string;
1724
+ endPoint?: string;
1725
+ }
1726
+
1727
+ /** `/adm/v1/anzu-user`. Absent in contentHub, which has only `/adm/users`. */
1728
+ export declare interface AnzuUserEndpointPair {
1729
+ get: string;
1730
+ put: string;
1731
+ post: string;
1732
+ }
1733
+
1734
+ export declare const anzuUserFilterStorageKey: (system: string) => string;
1735
+
1736
+ declare const anzuUserListFields: ({
1737
+ name: "id";
1738
+ default: null;
1739
+ type: "integer";
1740
+ variant?: undefined;
1741
+ render?: undefined;
1742
+ } | {
1743
+ name: "email";
1744
+ variant: "startsWith";
1745
+ default: null;
1746
+ type: "string";
1747
+ render: {
1748
+ skip: true;
1749
+ };
1750
+ } | {
1751
+ name: "enabled";
1752
+ default: null;
1753
+ type: "boolean";
1754
+ variant?: undefined;
1755
+ render?: undefined;
1756
+ })[];
1757
+
884
1758
  declare interface AnzuUserMinimal extends BaseUser {
885
1759
  id: IntegerId;
886
1760
  }
887
1761
 
1762
+ export declare const APermissionEditor: typeof __VLS_export_24;
1763
+
1764
+ export declare const APermissionGroupDatatable: typeof __VLS_export_25;
1765
+
1766
+ export declare const APermissionGroupDetail: typeof __VLS_export_26;
1767
+
1768
+ export declare const APermissionGroupFilter: typeof __VLS_export_27;
1769
+
1770
+ export declare const APermissionGroupManage: typeof __VLS_export_28;
1771
+
1772
+ export declare const APermissionGroupRemoteAutocomplete: typeof __VLS_export_29;
1773
+
888
1774
  export declare type ApiErrorContext = {
889
1775
  system: string;
890
1776
  entity: string;
@@ -905,6 +1791,18 @@ export declare type ApiErrorContext = {
905
1791
  * reaches the logger and is filtered here, on this field.
906
1792
  */
907
1793
  status?: number;
1794
+ /**
1795
+ * The i18n scope a field-level validation failure is reported under, when it is not the same as
1796
+ * the backend above.
1797
+ *
1798
+ * `AnzuApiValidationError` turns the server's field names into `<system>.<entity>.model.<field>`
1799
+ * translation keys. For a component shared by nine backends those two are different questions:
1800
+ * *which* backend failed -- which is what the report needs -- and *whose labels* name its fields,
1801
+ * which for a shared form is always the library's own `common.*`. Left unset, the two stay one
1802
+ * value, exactly as before.
1803
+ */
1804
+ validationSystem?: string;
1805
+ validationEntity?: string;
908
1806
  };
909
1807
 
910
1808
  export declare type ApiErrorLogger = (error: Error, context: ApiErrorContext) => void;
@@ -927,6 +1825,30 @@ export declare const ASubjectSelect: typeof __VLS_export_17;
927
1825
 
928
1826
  export declare const AUnsavedConfirmDialog: typeof __VLS_export_21;
929
1827
 
1828
+ export declare const AUserBulkActionDialog: typeof __VLS_export_44;
1829
+
1830
+ export declare const AUserCopyPermissionsDialog: typeof __VLS_export_34;
1831
+
1832
+ export declare const AUserCreateInSystemButton: typeof __VLS_export_41;
1833
+
1834
+ export declare const AUserEnabledSwitch: typeof __VLS_export_35;
1835
+
1836
+ export declare const AUserManageButton: typeof __VLS_export_42;
1837
+
1838
+ export declare const AUserMetadataForm: typeof __VLS_export_36;
1839
+
1840
+ export declare const AUserMetadataRepairDialog: typeof __VLS_export_45;
1841
+
1842
+ export declare const AUserOtherSystemsTable: typeof __VLS_export_39;
1843
+
1844
+ export declare const AUserSystemOverview: typeof __VLS_export_43;
1845
+
1846
+ export declare const AUserSystemPanel: typeof __VLS_export_38;
1847
+
1848
+ export declare const AUserSystemStatusChip: typeof __VLS_export_37;
1849
+
1850
+ export declare const AUserTabsShell: typeof __VLS_export_40;
1851
+
930
1852
  export declare type AxiosClientFn = () => AxiosInstance;
931
1853
 
932
1854
  declare interface BaseUser {
@@ -943,6 +1865,11 @@ declare interface BaseUser {
943
1865
  };
944
1866
  }
945
1867
 
1868
+ /** `/adm/users`. Only cms, dam and contentHub have it; it is the only path with a `PATCH`. */
1869
+ export declare interface BaseUserEndpointPair extends AnzuUserEndpointPair {
1870
+ patch: string;
1871
+ }
1872
+
946
1873
  /**
947
1874
  * Hash for a filter link, with values equal to their default left out.
948
1875
  *
@@ -954,6 +1881,44 @@ declare interface BaseUser {
954
1881
  */
955
1882
  export declare function buildFilterHash<F extends readonly MakeFilterOption<string>[]>(filterConfig: FilterConfig<F>, filters: Partial<Record<keyof FilterData<F> & string, AllowedFilterValues>>, sortBy?: DatatableSortBy): string;
956
1883
 
1884
+ export declare const BulkAction: {
1885
+ readonly Enable: "enable";
1886
+ readonly Disable: "disable";
1887
+ readonly Metadata: "metadata";
1888
+ };
1889
+
1890
+ export declare type BulkActionType = (typeof BulkAction)[keyof typeof BulkAction];
1891
+
1892
+ export declare interface BulkLogEntry {
1893
+ system: string;
1894
+ outcome: BulkOutcomeType;
1895
+ /**
1896
+ * Which run the line belongs to.
1897
+ *
1898
+ * The log survives a run so that a retry does not erase the systems that succeeded a minute ago,
1899
+ * and the retry button acts on whatever the log calls failed. Without these two fields a failed
1900
+ * metadata write would be retried as a disable, and a previous person's failures would be retried
1901
+ * against the id currently on screen -- neither `setEnabled` nor `writeMetadata` can tell it is
1902
+ * being asked about a different action or a different account.
1903
+ */
1904
+ action: BulkActionType;
1905
+ subjectId: IntegerIdNullable;
1906
+ detail?: string;
1907
+ }
1908
+
1909
+ export declare const BulkOutcome: {
1910
+ readonly Pending: "pending";
1911
+ readonly Running: "running";
1912
+ readonly Done: "done";
1913
+ readonly Forbidden: "forbidden";
1914
+ readonly Unauthenticated: "unauthenticated";
1915
+ readonly NotFound: "notFound";
1916
+ readonly Invalid: "invalid";
1917
+ readonly Unavailable: "unavailable";
1918
+ };
1919
+
1920
+ export declare type BulkOutcomeType = (typeof BulkOutcome)[keyof typeof BulkOutcome];
1921
+
957
1922
  /**
958
1923
  * `_unresolved` is terminal: the fetch settled without resolving the item, either because
959
1924
  * it failed or because the server did not return it.
@@ -963,6 +1928,37 @@ declare type CachedItem<T extends object> = T & {
963
1928
  _unresolved?: boolean;
964
1929
  };
965
1930
 
1931
+ export declare interface CachedPermissionGroupsParams {
1932
+ client: AxiosClientFn;
1933
+ system: string;
1934
+ entity?: string;
1935
+ endPoint?: string;
1936
+ }
1937
+
1938
+ /**
1939
+ * How a probe response becomes axes.
1940
+ *
1941
+ * 401 is its own case and it is not a detail. A first 401 is ambiguous -- an expired session looks
1942
+ * exactly like "no account here" -- and since the buttons are gated by this answer alone, showing
1943
+ * an expired token as "no account here" is the one confusion decision 16 forbids. The caller is
1944
+ * expected to have retried through its refresh hook before classifying; what arrives here is the
1945
+ * verdict after that retry.
1946
+ *
1947
+ * 422 deliberately has no case. A detail GET loads the record and returns it; it does not validate
1948
+ * a body. A 422 belongs to the log of writes.
1949
+ */
1950
+ export declare const classifyProbeStatus: (status: number | null) => Pick<UserSystemAxes, "presence" | "access">;
1951
+
1952
+ /**
1953
+ * What the operator is told about a failed write.
1954
+ *
1955
+ * 422 and 400 are their own line and not a generic failure: a PUT validates the whole body, and an
1956
+ * account carrying a colour or an e-mail that no longer passes validation will fail even on a plain
1957
+ * "disable". With legacy data that is an ordinary outcome, and "could not be saved" would send
1958
+ * somebody looking for a bug that is not there.
1959
+ */
1960
+ export declare const classifyWriteStatus: (status: number | null) => BulkOutcomeType;
1961
+
966
1962
  declare type CollabCachedUsersMap = Map<IntegerId, CachedItem<AnzuUserMinimal>>;
967
1963
 
968
1964
  declare type CollabComponentConfig = undefined | {
@@ -1014,6 +2010,22 @@ export declare function createFilterStore<F extends readonly MakeFilterOption<st
1014
2010
  */
1015
2011
  export declare function createListEditorStateScope(): ListEditorStateScope;
1016
2012
 
2013
+ export declare const CrossSystemPhase: {
2014
+ readonly Idle: "idle";
2015
+ /** First round of an e-mail search: find the person and their id. */
2016
+ readonly MatchingEmail: "matchingEmail";
2017
+ /** Second round: ask every system by that id, to catch the ones holding a different e-mail. */
2018
+ readonly VerifyingById: "verifyingById";
2019
+ readonly Done: "done";
2020
+ };
2021
+
2022
+ export declare type CrossSystemPhaseType = (typeof CrossSystemPhase)[keyof typeof CrossSystemPhase];
2023
+
2024
+ export declare interface CrossSystemSearchParams {
2025
+ descriptors: AnyUserSystemDescriptor[];
2026
+ refreshHook?: UserSystemRefreshHook | undefined;
2027
+ }
2028
+
1017
2029
  declare interface DatatableColumnsConfigMoreOptions {
1018
2030
  storeColumnsLocalStorage: string | boolean;
1019
2031
  disableActions: boolean;
@@ -1083,6 +2095,8 @@ export declare const DEFAULT_LOG_PATHS: LogPaths;
1083
2095
  /** What reporting does until an application says otherwise; exported so a test can put it back. */
1084
2096
  export declare const defaultApiErrorLogger: ApiErrorLogger;
1085
2097
 
2098
+ export declare const defineUserSystemDescriptor: <TSystem extends string, TUser extends AnzuUser>(descriptor: UserSystemDescriptor<TSystem, TUser>) => AnyUserSystemDescriptor;
2099
+
1086
2100
  /**
1087
2101
  * UUID v4 as string.
1088
2102
  */
@@ -1112,6 +2126,8 @@ declare interface EmptySlotProps_3 {
1112
2126
  };
1113
2127
  }
1114
2128
 
2129
+ export declare const emptyUserSystemAxes: () => UserSystemAxes;
2130
+
1115
2131
  export declare type ExecuteRequestParams<B> = {
1116
2132
  urlTemplate?: string;
1117
2133
  urlParams?: UrlParams;
@@ -1156,9 +2172,11 @@ declare type FetchItemsMinimalType = (pagination: Ref<Pagination>, filterData: F
1156
2172
 
1157
2173
  declare type FetchItemsMinimalType_2 = (pagination: Ref<Pagination>, filterData: FilterData, filterConfig: FilterConfig) => Promise<any[]>;
1158
2174
 
1159
- export declare type FetchItemsParams = {
2175
+ export declare type FetchItemsParams<B = never> = {
1160
2176
  urlTemplate?: string;
1161
2177
  urlParams?: UrlParams;
2178
+ /** `null` omits the body, as everywhere in this family. */
2179
+ body?: B;
1162
2180
  /** Stops this one call, leaving the instance's other calls alone. */
1163
2181
  signal?: AbortSignal;
1164
2182
  };
@@ -1241,7 +2259,7 @@ export declare type FilterStore<T extends readonly {
1241
2259
  [K in T[number]['name']]: AllowedFilterValues;
1242
2260
  };
1243
2261
 
1244
- declare type FilterStoreIdentifier = {
2262
+ export declare type FilterStoreIdentifier = {
1245
2263
  system: string;
1246
2264
  subject: string;
1247
2265
  };
@@ -1252,6 +2270,17 @@ declare type FilterVariant = 'search' | 'lt' | 'in' | 'notIn' | 'endsWith' | 'st
1252
2270
 
1253
2271
  declare type FilterVariant_2 = 'search' | 'lt' | 'in' | 'notIn' | 'endsWith' | 'startsWith' | 'memberOf' | 'contains' | 'neq' | 'gte' | 'gt' | 'eq' | 'lte' | 'custom';
1254
2272
 
2273
+ /**
2274
+ * Which of the six fields the systems disagree about.
2275
+ *
2276
+ * Blog is compared on `person.*` like everything else, and its own root `firstName`/`lastName`
2277
+ * columns are deliberately left out of this: those are the byline under an article, the blog's slug
2278
+ * and the public API, not back-office metadata. That blog's `person` is empty for most bloggers and
2279
+ * will therefore read as different is correct -- the back-office identity really is unset there,
2280
+ * and the first repair fills it in.
2281
+ */
2282
+ export declare const findMetadataDifferences: (records: Map<string, BaseUser>) => MetadataDifference[];
2283
+
1255
2284
  /**
1256
2285
  * Pretty-prints a JSON string, and hands back whatever it was given when that is not what it is.
1257
2286
  * Log context carries request and response bodies that are usually but not always JSON.
@@ -1269,6 +2298,14 @@ export declare const generateListQuery: (pagination: Ref<Pagination>, filterData
1269
2298
 
1270
2299
  export declare type GetKey<TItem> = keyof TItem | ((item: TItem) => ListEditorKey);
1271
2300
 
2301
+ declare const Grant: {
2302
+ readonly Deny: 0;
2303
+ readonly AllowOwner: 1;
2304
+ readonly Allow: 2;
2305
+ };
2306
+
2307
+ declare type GrantType = (typeof Grant)[keyof typeof Grant];
2308
+
1272
2309
  declare interface HeaderSlotProps {
1273
2310
  title: string | null;
1274
2311
  }
@@ -1291,11 +2328,28 @@ declare type IntegerId = number;
1291
2328
  */
1292
2329
  declare type IntegerIdNullable = number | null;
1293
2330
 
2331
+ /** A system a bulk action may act on: it answered, the account is there, and access was granted. */
2332
+ export declare const isActionable: (axes: UserSystemAxes) => boolean;
2333
+
2334
+ /**
2335
+ * Whether the probe answered authoritatively that nobody is there.
2336
+ *
2337
+ * Creating an account is offered only when every relevant system said so. A record that could not
2338
+ * be read is not a record that does not exist, and since no admin can delete an AnzuUser, a
2339
+ * duplicate identity created on a guess cannot be taken back.
2340
+ */
2341
+ export declare const isAuthoritativelyAbsent: (axes: UserSystemAxes) => boolean;
2342
+
2343
+ export declare const isEmailTerm: (term: string) => boolean;
2344
+
1294
2345
  export declare const isLogType: (value: unknown) => value is LogTypeType;
1295
2346
 
1296
2347
  /** Whether `router.push({ hash })` would leave the hash intact — see `buildFilterHash`. */
1297
2348
  export declare const isRouterSafeHash: (hash: string) => boolean;
1298
2349
 
2350
+ /** Which of the two shapes a list arrives in. */
2351
+ export declare type ItemsShape = 'envelope' | 'array';
2352
+
1299
2353
  declare const JOB_RESOURCE_USER_DATA_DELETE = "jobUserDataDelete";
1300
2354
 
1301
2355
  declare interface JobBase<T extends JobBaseResource = JobBaseResource> extends AnzuUserAndTimeTrackingAware {
@@ -1324,6 +2378,8 @@ declare const JobStatus: {
1324
2378
 
1325
2379
  declare type JobStatusType = (typeof JobStatus)[keyof typeof JobStatus];
1326
2380
 
2381
+ declare type LanguageCode = 'en' | 'sk' | 'cs' | 'xx';
2382
+
1327
2383
  export declare interface ListEditorApi<TItem> {
1328
2384
  viewItems: ComputedRef<ListViewItem<TItem>[]>;
1329
2385
  addItem: (data: TItem, positionHint?: PositionHint) => TItem[];
@@ -1451,6 +2507,10 @@ declare type ListEditorValidationScope = string | number | boolean | symbol;
1451
2507
 
1452
2508
  export declare type ListEditorValidationState = 'valid' | 'invalid' | 'warning' | null;
1453
2509
 
2510
+ declare type ListFields = typeof permissionGroupListFields;
2511
+
2512
+ declare type ListFields_2 = typeof anzuUserListFields;
2513
+
1454
2514
  export declare interface ListViewItem<TItem> {
1455
2515
  key: ListEditorKey;
1456
2516
  index: number;
@@ -1686,6 +2746,12 @@ export declare interface MakeFilterOption<TName extends string = string> {
1686
2746
  render?: Partial<FilerRenderOptions>;
1687
2747
  }
1688
2748
 
2749
+ export declare interface MetadataDifference {
2750
+ field: UserMetadataField;
2751
+ /** System to the value it holds, for every system that answered with a record. */
2752
+ values: Map<string, string>;
2753
+ }
2754
+
1689
2755
  export declare interface NestedListEditorApi<TItem extends Record<string, any>> {
1690
2756
  viewItems: ComputedRef<NestedViewItem<TItem>[]>;
1691
2757
  findNode: (id: ListEditorKey) => {
@@ -1841,6 +2907,14 @@ export declare interface NestedViewItem<TItem> extends ListViewItem<TItem> {
1841
2907
  */
1842
2908
  export declare const nextListEditorTempId: () => number;
1843
2909
 
2910
+ /**
2911
+ * The one tab that is not a system.
2912
+ *
2913
+ * A module of its own because `<script setup>` cannot export, and both the shell and the pages that
2914
+ * read `?tab=` need to name it.
2915
+ */
2916
+ export declare const OTHER_SYSTEMS_TAB = "__otherSystems";
2917
+
1844
2918
  export declare interface Pagination {
1845
2919
  sortBy: DatatableSortBy;
1846
2920
  page: number;
@@ -1855,6 +2929,181 @@ declare interface PaginationOptions {
1855
2929
  rowsPerPage: number;
1856
2930
  }
1857
2931
 
2932
+ export declare const PERMISSION_CONFIG_ENDPOINT = "/adm/v1/permissions/config";
2933
+
2934
+ export declare const PERMISSION_CONFIG_ENTITY = "permissionConfig";
2935
+
2936
+ export declare const PERMISSION_GROUP_ENDPOINT = "/adm/v1/permission-group";
2937
+
2938
+ export declare const PERMISSION_GROUP_ENTITY = "permissionGroup";
2939
+
2940
+ export declare interface PermissionActionsParams {
2941
+ client: AxiosClientFn;
2942
+ system: string;
2943
+ entity?: string;
2944
+ endPoint?: string;
2945
+ }
2946
+
2947
+ declare interface PermissionConfig {
2948
+ roles: string[];
2949
+ defaultGrants: GrantType[];
2950
+ config: {
2951
+ [subject: string]: {
2952
+ [action: string]: {
2953
+ grants?: GrantType[];
2954
+ };
2955
+ };
2956
+ };
2957
+ translation: {
2958
+ subjects: {
2959
+ [subject: string]: {
2960
+ [lang: string]: string;
2961
+ };
2962
+ };
2963
+ actions: {
2964
+ [action: string]: {
2965
+ [lang: string]: string;
2966
+ };
2967
+ };
2968
+ roles: {
2969
+ [role: string]: {
2970
+ [lang: string]: string;
2971
+ };
2972
+ };
2973
+ };
2974
+ }
2975
+
2976
+ export declare interface PermissionConfigActionsParams {
2977
+ client: AxiosClientFn;
2978
+ /**
2979
+ * The system this config belongs to. It is a parameter and not a global -- admin-inhouse used to
2980
+ * read it from a `curSystem` ref, which made the whole module impossible to use from a page that
2981
+ * shows two systems at once and impossible to move here at all.
2982
+ */
2983
+ system: string;
2984
+ entity?: string;
2985
+ endPoint?: string;
2986
+ /**
2987
+ * Fetch as soon as the composable is built, the way every admin does today. Turn it off where
2988
+ * the caller wants to decide when (a dialog that may never open, a test).
2989
+ */
2990
+ autoFetch?: boolean;
2991
+ }
2992
+
2993
+ export declare interface PermissionConfigApiParams {
2994
+ client: AxiosClientFn;
2995
+ /**
2996
+ * Which backend this instance talks to. It reaches `useApiRequest` for error context and is the
2997
+ * key everything downstream is stored under, so two systems can be loaded side by side.
2998
+ */
2999
+ system: string;
3000
+ /** Goes into every `useApiRequest` call; see the per-system entity note in `permissionGroupApi`. */
3001
+ entity?: string;
3002
+ endPoint?: string;
3003
+ }
3004
+
3005
+ /**
3006
+ * One entry per system. The admins this replaces kept `loading` and `initialized` as two module
3007
+ * booleans shared by every system they fetched, which is wrong the moment the fetches run in
3008
+ * parallel: the first one to finish cleared the flag for all of them, and the first one to fail
3009
+ * left it set forever because there was no `finally`.
3010
+ */
3011
+ export declare interface PermissionConfigEntry {
3012
+ config: PermissionConfig;
3013
+ loading: boolean;
3014
+ initialized: boolean;
3015
+ }
3016
+
3017
+ declare interface PermissionGroup extends PermissionGroupMinimal, AnzuUserAndTimeTrackingAware {
3018
+ description: string;
3019
+ _system: string;
3020
+ _resourceName: 'permissionGroup';
3021
+ }
3022
+
3023
+ export declare interface PermissionGroupActionsParams {
3024
+ client: AxiosClientFn;
3025
+ system: string;
3026
+ entity?: string;
3027
+ /**
3028
+ * i18n scope for a server-side validation failure, which is a different question from which
3029
+ * backend answered. `AnzuApiValidationError` builds `<system>.<entity>.model.<field>` keys, so
3030
+ * the pair has to name the namespace the *labels* live under. It defaults to `common` +
3031
+ * `permissionGroup`, which is where the shared form's own fields are; an admin whose form carries
3032
+ * system fields as well passes its own pair, and keeps the base keys beside them.
3033
+ */
3034
+ validationSystem?: string;
3035
+ validationEntity?: string;
3036
+ endPoint?: string;
3037
+ }
3038
+
3039
+ export declare interface PermissionGroupApiParams {
3040
+ client: AxiosClientFn;
3041
+ /**
3042
+ * Both of these reach every `useApiRequest` this builds, and both have to be taken rather than
3043
+ * assumed. admin-cms is the proof: its `permissionGroupApi.ts` declared `SYSTEM_COMMON` at the
3044
+ * top and then sent `SYSTEM_CMS` on one of its four calls, so the same file reported two
3045
+ * different systems for the same endpoint. A copy of that file per system multiplies the bug;
3046
+ * one file that is told which system it is cannot have it.
3047
+ */
3048
+ system: string;
3049
+ entity?: string;
3050
+ /**
3051
+ * i18n scope for a server-side validation failure, which is a different question from which
3052
+ * backend answered. `AnzuApiValidationError` builds `<system>.<entity>.model.<field>` keys, and
3053
+ * for a component shared by nine backends the labels are always the library's own `common.*` --
3054
+ * `weather.anzuUser.model.email` exists nowhere. Defaults to `common` plus the entity;
3055
+ * contentHub passes its own pair to keep the keys it already has.
3056
+ */
3057
+ validationSystem?: string;
3058
+ validationEntity?: string;
3059
+ endPoint?: string;
3060
+ }
3061
+
3062
+ /**
3063
+ * Local-storage key for the list filter. Named rather than derived so it cannot collide with the
3064
+ * per-admin views this replaces, which store under `tableFilter_common_permissionGroup`; while
3065
+ * both versions are on screen they must not share remembered filters (rule 8.0).
3066
+ */
3067
+ export declare const permissionGroupFilterStorageKey: (system: string) => string;
3068
+
3069
+ declare const permissionGroupListFields: ({
3070
+ name: "id";
3071
+ default: null;
3072
+ type: "integer";
3073
+ variant?: undefined;
3074
+ render?: undefined;
3075
+ } | {
3076
+ name: "title";
3077
+ variant: "startsWith";
3078
+ default: null;
3079
+ type: "string";
3080
+ render: {
3081
+ skip: true;
3082
+ };
3083
+ })[];
3084
+
3085
+ declare interface PermissionGroupMinimal {
3086
+ id: IntegerId;
3087
+ title: string;
3088
+ permissions: Permissions_2;
3089
+ }
3090
+
3091
+ declare type Permissions_2 = {
3092
+ [key in AclValue]?: GrantType;
3093
+ };
3094
+
3095
+ declare type PermissionTranslationGroup = 'subjects' | 'actions' | 'roles';
3096
+
3097
+ /**
3098
+ * Which record the repair form is pre-filled from: the first system in the configured order that
3099
+ * has one.
3100
+ *
3101
+ * Never "whichever answered first" -- the fan-out is parallel, so that would be a different answer
3102
+ * on every run. The order is a default rather than a hidden rule: the dialog names the source and
3103
+ * lets it be changed.
3104
+ */
3105
+ export declare const pickPrefillSource: (order: string[], records: Map<string, BaseUser>) => string | null;
3106
+
1858
3107
  /** Which mutation is asking for positions to be (re)assigned. */
1859
3108
  export declare type PositionAction = 'add' | 'update' | 'remove' | 'move' | 'payload';
1860
3109
 
@@ -1892,6 +3141,19 @@ export declare type PositionOption<TItem> = false | keyof TItem | {
1892
3141
  */
1893
3142
  export declare type PositionStrategy = 'renumber' | 'preserve-values';
1894
3143
 
3144
+ /**
3145
+ * The status the backend answered with, or null when nothing ever answered.
3146
+ *
3147
+ * Read off the axios failure the mapped error kept as its cause, not off the class. Going by class
3148
+ * alone misses exactly the answers that exist *because* the backend replied with a body: a
3149
+ * validation failure is `AnzuApiValidationError`, a dependency conflict is
3150
+ * `AnzuApiDependencyExistsError`, and both are 422s that have to be reported as such. Reported as
3151
+ * "the system did not answer" they would send the operator looking for an outage instead of at the
3152
+ * account whose stored data no longer validates -- which, with legacy rows, is the failure that
3153
+ * happens most.
3154
+ */
3155
+ export declare const probeStatusFromError: (error: unknown) => number | null;
3156
+
1895
3157
  declare interface Props<TItem extends Record<string, any>> {
1896
3158
  /**
1897
3159
  * New-row factory. Add / "add after" insert `factory()` through the controller
@@ -2251,6 +3513,8 @@ declare interface Props_4 {
2251
3513
  */
2252
3514
  export declare function provideListEditorStateScope(inherited: ListEditorStateScope | null): ListEditorStateScope;
2253
3515
 
3516
+ export declare const readMetadataField: (user: BaseUser, field: UserMetadataField) => string;
3517
+
2254
3518
  /**
2255
3519
  * Non-mutating renumber to sequential positions matching array order — the same
2256
3520
  * renumbering the editors apply on commit. Unchanged items stay reference-equal.
@@ -2290,6 +3554,48 @@ declare interface ReorderToggleSlotProps_2 {
2290
3554
  };
2291
3555
  }
2292
3556
 
3557
+ /** Creating an account goes the same way a write does. */
3558
+ export declare const resolveCreateEndpoint: (descriptor: AnyUserSystemDescriptor) => string;
3559
+
3560
+ /**
3561
+ * `enabled` has no `PATCH` anywhere: the only method that calls `setEnabled` is the full update.
3562
+ * So it goes GET + PUT, on the same path, with the whole DTO the GET returned.
3563
+ */
3564
+ export declare const resolveEnabledWrite: (descriptor: AnyUserSystemDescriptor) => {
3565
+ get: string;
3566
+ url: string;
3567
+ };
3568
+
3569
+ /**
3570
+ * Metadata is written through `PATCH /adm/users/{id}` wherever that path exists: the method behind
3571
+ * it can only write e-mail, locale, avatar and person -- it has no setter for roles, permissions,
3572
+ * groups or `enabled`. That is a stronger guarantee than being careful about what goes in the body.
3573
+ */
3574
+ export declare const resolveMetadataWrite: (descriptor: AnyUserSystemDescriptor) => {
3575
+ method: "PATCH";
3576
+ get: string;
3577
+ url: string;
3578
+ } | {
3579
+ method: "PUT";
3580
+ get: string;
3581
+ url: string;
3582
+ };
3583
+
3584
+ /**
3585
+ * The pair the probe reads through, with the one invariant the type cannot state: both branches of
3586
+ * `endpoints` are nullable, so nothing stops a descriptor naming `probe: 'base'` on a system that
3587
+ * has no `/adm/users`. Every admin's descriptor test asserts this resolves for each of its
3588
+ * systems.
3589
+ */
3590
+ export declare const resolveProbeEndpoint: (descriptor: AnyUserSystemDescriptor) => AnzuUserEndpointPair;
3591
+
3592
+ /**
3593
+ * The single closed function from axes to what is drawn. Order matters: a system switched off in
3594
+ * configuration is reported as such whatever else is known about it, and access is decided before
3595
+ * presence because a forbidden record is not an absent one.
3596
+ */
3597
+ export declare const resolveUserSystemState: (axes: UserSystemAxes) => UserSystemStateType;
3598
+
2293
3599
  declare interface RowActions<TItem> {
2294
3600
  edit: () => void;
2295
3601
  save: () => Promise<void> | void;
@@ -2498,6 +3804,9 @@ declare const SortOrder: {
2498
3804
 
2499
3805
  declare type SortOrderType = (typeof SortOrder)[keyof typeof SortOrder];
2500
3806
 
3807
+ /** Systems whose stored value differs from the one about to be written. Nothing else is touched. */
3808
+ export declare const systemsNeedingWrite: (target: BaseUser, records: Map<string, BaseUser>, fields?: readonly UserMetadataField[]) => string[];
3809
+
2501
3810
  export declare const TimeIntervalSpecialOptions: {
2502
3811
  readonly CurrentMonth: "cm";
2503
3812
  readonly LastMonth: "lm";
@@ -2533,26 +3842,261 @@ declare interface ToolbarSlotProps_2 {
2533
3842
  }
2534
3843
 
2535
3844
  /**
2536
- * One named, savable section the unsaved-changes confirm dialog can name back
2537
- * to the user. `dirty` is evaluated reactively inside the section's getter.
3845
+ * One named, savable section the unsaved-changes confirm dialog can name back
3846
+ * to the user. `dirty` is evaluated reactively inside the section's getter.
3847
+ */
3848
+ export declare interface UnsavedSectionDescriptor {
3849
+ label: string;
3850
+ dirty: boolean;
3851
+ }
3852
+
3853
+ /**
3854
+ * Getter returning a single descriptor, or an array of them for a component
3855
+ * that owns several sub-sections (e.g. page positions in one PageContentsManage).
3856
+ */
3857
+ export declare type UnsavedSectionSource = () => UnsavedSectionDescriptor | UnsavedSectionDescriptor[];
3858
+
3859
+ declare type UnsavedSource = Ref<boolean | Set<unknown> | unknown[] | null | undefined>;
3860
+
3861
+ declare type UrlParams = {
3862
+ [key: string]: number | string;
3863
+ };
3864
+
3865
+ /**
3866
+ * Per instance, like every other actions composable here. The admins' versions kept their loading
3867
+ * flags at module scope.
3868
+ */
3869
+ export declare const useAnzuUserActions: (params: AnzuUserActionsParams) => {
3870
+ isDirty: ComputedRef<boolean>;
3871
+ /** Takes the record as it stands as the new baseline; the page calls it after it seeds one. */
3872
+ markPristine: () => void;
3873
+ anzuUserList: Ref<{
3874
+ enabled: boolean;
3875
+ locale: LanguageCode | null;
3876
+ roles: string[];
3877
+ permissionGroups: IntegerId[];
3878
+ permissions: Permissions_2;
3879
+ resolvedPermissions: Permissions_2;
3880
+ _resourceName: string;
3881
+ _system: string;
3882
+ createdAt: DatetimeUTC;
3883
+ modifiedAt: DatetimeUTC;
3884
+ modifiedBy: IntegerIdNullable;
3885
+ createdBy: IntegerIdNullable;
3886
+ id?: IntegerIdNullable | undefined;
3887
+ email: string;
3888
+ person: {
3889
+ firstName: string;
3890
+ lastName: string;
3891
+ fullName: string;
3892
+ };
3893
+ avatar: {
3894
+ color: string;
3895
+ text: string;
3896
+ };
3897
+ }[], AnzuUser[] | {
3898
+ enabled: boolean;
3899
+ locale: LanguageCode | null;
3900
+ roles: string[];
3901
+ permissionGroups: IntegerId[];
3902
+ permissions: Permissions_2;
3903
+ resolvedPermissions: Permissions_2;
3904
+ _resourceName: string;
3905
+ _system: string;
3906
+ createdAt: DatetimeUTC;
3907
+ modifiedAt: DatetimeUTC;
3908
+ modifiedBy: IntegerIdNullable;
3909
+ createdBy: IntegerIdNullable;
3910
+ id?: IntegerIdNullable | undefined;
3911
+ email: string;
3912
+ person: {
3913
+ firstName: string;
3914
+ lastName: string;
3915
+ fullName: string;
3916
+ };
3917
+ avatar: {
3918
+ color: string;
3919
+ text: string;
3920
+ };
3921
+ }[]>;
3922
+ loadingAnzuUserList: Ref<boolean, boolean>;
3923
+ datatableHiddenColumns: Ref<string[], string[]>;
3924
+ fetchAnzuUserList: (pagination: Ref<Pagination>, filterData: FilterData<any>, filterConfig: FilterConfig<any>) => Promise<void>;
3925
+ cancelAnzuUserList: () => void;
3926
+ anzuUser: Ref<{
3927
+ enabled: boolean;
3928
+ locale: LanguageCode | null;
3929
+ roles: string[];
3930
+ permissionGroups: IntegerId[];
3931
+ permissions: Permissions_2;
3932
+ resolvedPermissions: Permissions_2;
3933
+ _resourceName: string;
3934
+ _system: string;
3935
+ createdAt: DatetimeUTC;
3936
+ modifiedAt: DatetimeUTC;
3937
+ modifiedBy: IntegerIdNullable;
3938
+ createdBy: IntegerIdNullable;
3939
+ id?: IntegerIdNullable | undefined;
3940
+ email: string;
3941
+ person: {
3942
+ firstName: string;
3943
+ lastName: string;
3944
+ fullName: string;
3945
+ };
3946
+ avatar: {
3947
+ color: string;
3948
+ text: string;
3949
+ };
3950
+ }, AnzuUser | {
3951
+ enabled: boolean;
3952
+ locale: LanguageCode | null;
3953
+ roles: string[];
3954
+ permissionGroups: IntegerId[];
3955
+ permissions: Permissions_2;
3956
+ resolvedPermissions: Permissions_2;
3957
+ _resourceName: string;
3958
+ _system: string;
3959
+ createdAt: DatetimeUTC;
3960
+ modifiedAt: DatetimeUTC;
3961
+ modifiedBy: IntegerIdNullable;
3962
+ createdBy: IntegerIdNullable;
3963
+ id?: IntegerIdNullable | undefined;
3964
+ email: string;
3965
+ person: {
3966
+ firstName: string;
3967
+ lastName: string;
3968
+ fullName: string;
3969
+ };
3970
+ avatar: {
3971
+ color: string;
3972
+ text: string;
3973
+ };
3974
+ }>;
3975
+ loadingAnzuUser: Ref<boolean, boolean>;
3976
+ fetchAnzuUser: (id: IntegerId) => Promise<void>;
3977
+ createAnzuUser: () => Promise<AnzuUser | null>;
3978
+ updateAnzuUser: () => Promise<boolean>;
3979
+ loadingCreateAnzuUser: Ref<boolean, boolean>;
3980
+ loadingUpdateAnzuUser: Ref<boolean, boolean>;
3981
+ resetAnzuUserStore: (system?: string, resourceName?: string) => void;
3982
+ };
3983
+
3984
+ /**
3985
+ * Generic in the user type, because the three systems that answer on `/adm/users` return a DTO of
3986
+ * their own -- `CmsUserDto`, `DamUserDto`, `ContentHubUserDto` -- each extending `UserDto` with
3987
+ * system fields. Losing those in the round trip is exactly what the write invariant forbids: the
3988
+ * body of a write is the whole object the preceding GET returned.
2538
3989
  */
2539
- export declare interface UnsavedSectionDescriptor {
2540
- label: string;
2541
- dirty: boolean;
2542
- }
3990
+ export declare const useAnzuUserApi: <T extends AnzuUser = AnzuUser>({ client, system, entity, validationSystem, validationEntity, endPoint, }: AnzuUserApiParams) => {
3991
+ useFetchAnzuUserListByIds: () => UseApiFetchByIdsReturnType<T>;
3992
+ useFetchAnzuUserList: () => UseApiFetchListReturnType<T>;
3993
+ useFetchAnzuUser: () => UseApiRequestReturnType<T, null>;
3994
+ useCreateAnzuUser: () => UseApiRequestReturnType<T, T>;
3995
+ useUpdateAnzuUser: () => UseApiRequestReturnType<T, T>;
3996
+ usePatchBaseUser: (patchEndPoint: string) => UseApiRequestReturnType<T, T>;
3997
+ };
2543
3998
 
2544
3999
  /**
2545
- * Getter returning a single descriptor, or an array of them for a component
2546
- * that owns several sub-sections (e.g. page positions in one PageContentsManage).
4000
+ * Exact match on e-mail, for the cross-system search.
4001
+ *
4002
+ * `startsWith` -- what the list filter uses and what admin-inhouse's search used -- cannot answer
4003
+ * the question that search asks. "Is this person here under this address" has to be `eq`, or
4004
+ * `jozko@sme.sk` matches `jozko.mrkvicka@sme.sk` and the fan-out reports the wrong identity.
2547
4005
  */
2548
- export declare type UnsavedSectionSource = () => UnsavedSectionDescriptor | UnsavedSectionDescriptor[];
2549
-
2550
- declare type UnsavedSource = Ref<boolean | Set<unknown> | unknown[] | null | undefined>;
4006
+ export declare function useAnzuUserEmailLookupFilter(): {
4007
+ filterConfig: FilterConfig<{
4008
+ name: "email";
4009
+ variant: "eq";
4010
+ default: null;
4011
+ type: "string";
4012
+ }[]>;
4013
+ filterData: FilterData<{
4014
+ name: "email";
4015
+ variant: "eq";
4016
+ default: null;
4017
+ type: "string";
4018
+ }[]>;
4019
+ };
2551
4020
 
2552
- declare type UrlParams = {
2553
- [key: string]: number | string;
4021
+ /**
4022
+ * The three fields every system has, plus whatever that system adds.
4023
+ *
4024
+ * The extras are a parameter rather than fields in the list above because the same filter is not
4025
+ * the same query everywhere: cms asks for permission groups with `memberOf` and dam with `custom`,
4026
+ * and cms has `allowedSites`, which exists nowhere else. Hard-coding either variant would send the
4027
+ * wrong query to the other backend, and leaving them out costs those two lists filters they have
4028
+ * today.
4029
+ *
4030
+ * `AFilterWrapper` draws any field that is not `render.skip` by itself, so a plain extra field
4031
+ * needs nothing else; one that wants its own widget -- a remote autocomplete -- is passed through
4032
+ * the matching slot.
4033
+ */
4034
+ export declare function useAnzuUserListFilter<E extends readonly MakeFilterOption[] = []>(system: string, extraFields?: E): {
4035
+ filterConfig: FilterConfig<readonly [...ListFields_2, ...E]>;
4036
+ filterData: FilterData<readonly [...ListFields_2, ...E]>;
2554
4037
  };
2555
4038
 
4039
+ /**
4040
+ * The one user the owning form is editing. Cross-system pages do not use this -- they hold a
4041
+ * result per system and never a single "current" user -- so it stays a single record, the way the
4042
+ * admins have it.
4043
+ */
4044
+ export declare const useAnzuUserOneStore: SetupStoreDefinition<"labsAnzuUserOneStore", {
4045
+ anzuUser: Ref<{
4046
+ enabled: boolean;
4047
+ locale: LanguageCode | null;
4048
+ roles: string[];
4049
+ permissionGroups: IntegerId[];
4050
+ permissions: Permissions_2;
4051
+ resolvedPermissions: Permissions_2;
4052
+ _resourceName: string;
4053
+ _system: string;
4054
+ createdAt: DatetimeUTC;
4055
+ modifiedAt: DatetimeUTC;
4056
+ modifiedBy: IntegerIdNullable;
4057
+ createdBy: IntegerIdNullable;
4058
+ id?: IntegerIdNullable | undefined;
4059
+ email: string;
4060
+ person: {
4061
+ firstName: string;
4062
+ lastName: string;
4063
+ fullName: string;
4064
+ };
4065
+ avatar: {
4066
+ color: string;
4067
+ text: string;
4068
+ };
4069
+ }, AnzuUser | {
4070
+ enabled: boolean;
4071
+ locale: LanguageCode | null;
4072
+ roles: string[];
4073
+ permissionGroups: IntegerId[];
4074
+ permissions: Permissions_2;
4075
+ resolvedPermissions: Permissions_2;
4076
+ _resourceName: string;
4077
+ _system: string;
4078
+ createdAt: DatetimeUTC;
4079
+ modifiedAt: DatetimeUTC;
4080
+ modifiedBy: IntegerIdNullable;
4081
+ createdBy: IntegerIdNullable;
4082
+ id?: IntegerIdNullable | undefined;
4083
+ email: string;
4084
+ person: {
4085
+ firstName: string;
4086
+ lastName: string;
4087
+ fullName: string;
4088
+ };
4089
+ avatar: {
4090
+ color: string;
4091
+ text: string;
4092
+ };
4093
+ }>;
4094
+ loadingAnzuUser: Ref<boolean, boolean>;
4095
+ setAnzuUser: (newAnzuUser: AnzuUser) => void;
4096
+ setLoadingAnzuUser: (loading: boolean) => void;
4097
+ reset: (system?: string, resourceName?: string) => void;
4098
+ }>;
4099
+
2556
4100
  /**
2557
4101
  * A request that asks the backend to do something and reads nothing back -- a delete, or a call that
2558
4102
  * only starts work and answers 202. Any successful status resolves; a body, if one arrives, is
@@ -2566,6 +4110,9 @@ export declare type UseApiFetchByIdsParams = {
2566
4110
  client: AxiosClientFn;
2567
4111
  system: string;
2568
4112
  entity: string;
4113
+ /** i18n scope for field-level validation failures; defaults to `system` / `entity`. */
4114
+ validationSystem?: string;
4115
+ validationEntity?: string;
2569
4116
  urlTemplate?: string;
2570
4117
  urlParams?: UrlParams;
2571
4118
  /** Anything axios takes except what this helper decides: the method, the url, the body and the signal. */
@@ -2581,16 +4128,28 @@ export declare type UseApiFetchByIdsReturnType<T> = {
2581
4128
  /**
2582
4129
  * True while this instance has a request in flight, false once the last one settles.
2583
4130
  *
2584
- * It is here so a caller does not have to keep its own: the hand-rolled version is a ref cleared
2585
- * in a `finally`, and that `finally` belongs to whichever call ended -- including one that
4131
+ * It is here so a caller does not have to keep its own: the hand-rolled version is a ref cleared in
4132
+ * a `finally`, and that `finally` belongs to whichever call ended -- including one that
2586
4133
  * `cancelPrevious` just superseded, which turns the spinner off while the call the user is waiting
2587
4134
  * for is still running. This one never dips between a superseded call and the one that replaced it.
4135
+ *
4136
+ * Two things to know before replacing a hand-rolled flag with it.
4137
+ *
4138
+ * It covers what this helper does and nothing the caller does afterwards. A flag that also spans a
4139
+ * follow-up cached fetch, a mapping pass or a second endpoint is not the same flag, and swapping it
4140
+ * for this one turns the spinner off too early. Keep your own where it means more than "this helper
4141
+ * is working".
4142
+ *
4143
+ * It belongs to the instance, so it is only reachable if you hold the instance. A factory that
4144
+ * builds one per call and hands back the promise alone -- `const { execute } = useX()` inside the
4145
+ * function that calls it -- cannot expose `loading`, `abort` or `cancelPrevious` at all. Hoist the
4146
+ * instance to where the caller lives first.
2588
4147
  */
2589
4148
  loading: Ref<boolean>;
2590
4149
  };
2591
4150
 
2592
4151
  /**
2593
- * A list read from an endpoint the caller has already written the query for, with no pagination.
4152
+ * A list from an endpoint the caller has already written the query for, with no pagination.
2594
4153
  *
2595
4154
  * It exists because the fleet kept doing this through `useApiRequest<ApiResponseList<T[]>>`: build a
2596
4155
  * query by hand -- an order, a limit, a fixed filter -- bake it into the url, and read `.data` off
@@ -2603,15 +4162,26 @@ export declare type UseApiFetchByIdsReturnType<T> = {
2603
4162
  * not the user's to change. So this is that helper with the pagination taken out: same core, same
2604
4163
  * error mapping, same list-body check, and it answers with the items rather than the envelope.
2605
4164
  *
4165
+ * Read is the usual case, not the only one: a filter too big for a url goes out as a POST, and a
4166
+ * mutation can answer with the list it just changed. The helper is about what comes back.
4167
+ *
4168
+ * Which shape it comes back in is declared, not guessed. `shape` picks the reader and the reader
4169
+ * refuses the other shape, the way `optionalBody` makes a caller declare a body instead of leaving
4170
+ * the helper to accept whatever turns up. A wrong declaration therefore fails loudly on the first
4171
+ * run, which is what makes having a default safe at all.
4172
+ *
2606
4173
  * It writes no metadata. An endpoint whose paging the user drives is `useApiFetchList`; a list read
2607
4174
  * page by page to the end is `useApiFetchListBatch`.
2608
4175
  */
2609
- export declare const useApiFetchItems: <T>(params: UseApiFetchItemsParams) => UseApiFetchItemsReturnType<T>;
4176
+ export declare const useApiFetchItems: <T, B = never>(params: UseApiFetchItemsParams) => UseApiFetchItemsReturnType<T, B>;
2610
4177
 
2611
4178
  export declare type UseApiFetchItemsParams = {
2612
4179
  client: AxiosClientFn;
2613
4180
  system: string;
2614
4181
  entity: string;
4182
+ /** i18n scope for field-level validation failures; defaults to `system` / `entity`. */
4183
+ validationSystem?: string;
4184
+ validationEntity?: string;
2615
4185
  /**
2616
4186
  * The url, query and all: whatever built the query has already run by the time it gets here.
2617
4187
  *
@@ -2625,18 +4195,45 @@ export declare type UseApiFetchItemsParams = {
2625
4195
  /** Anything axios takes except what this helper decides: the method, the url, the body and the signal. */
2626
4196
  options?: Omit<AxiosRequestConfig, 'method' | 'url' | 'data' | 'signal'>;
2627
4197
  cancelPrevious?: boolean;
4198
+ /**
4199
+ * Default `GET`, which is what 17 of the fleet's list reads and every existing caller here use.
4200
+ *
4201
+ * The others are here because a list is not only ever the answer to a read: a filter too big for a
4202
+ * url goes out as a POST, and a mutation can answer with the list it just changed -- a swap, a
4203
+ * shift, an upsert-all. What this helper is about is the answer, not the verb.
4204
+ */
4205
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH';
4206
+ /**
4207
+ * Default `'envelope'`, because that is the fleet's norm and the exception is what gets declared.
4208
+ *
4209
+ * Leaving it out cannot go wrong quietly: the reader refuses the shape that was not declared, so a
4210
+ * forgotten `'array'` fails on the first run rather than handing back something that is not a list.
4211
+ */
4212
+ shape?: ItemsShape;
2628
4213
  };
2629
4214
 
2630
- export declare type UseApiFetchItemsReturnType<T> = {
2631
- execute: (params?: FetchItemsParams) => Promise<T[]>;
4215
+ export declare type UseApiFetchItemsReturnType<T, B = never> = {
4216
+ execute: (params?: FetchItemsParams<B>) => Promise<T[]>;
2632
4217
  abort: () => void;
2633
4218
  /**
2634
4219
  * True while this instance has a request in flight, false once the last one settles.
2635
4220
  *
2636
- * It is here so a caller does not have to keep its own: the hand-rolled version is a ref cleared
2637
- * in a `finally`, and that `finally` belongs to whichever call ended -- including one that
4221
+ * It is here so a caller does not have to keep its own: the hand-rolled version is a ref cleared in
4222
+ * a `finally`, and that `finally` belongs to whichever call ended -- including one that
2638
4223
  * `cancelPrevious` just superseded, which turns the spinner off while the call the user is waiting
2639
4224
  * for is still running. This one never dips between a superseded call and the one that replaced it.
4225
+ *
4226
+ * Two things to know before replacing a hand-rolled flag with it.
4227
+ *
4228
+ * It covers what this helper does and nothing the caller does afterwards. A flag that also spans a
4229
+ * follow-up cached fetch, a mapping pass or a second endpoint is not the same flag, and swapping it
4230
+ * for this one turns the spinner off too early. Keep your own where it means more than "this helper
4231
+ * is working".
4232
+ *
4233
+ * It belongs to the instance, so it is only reachable if you hold the instance. A factory that
4234
+ * builds one per call and hands back the promise alone -- `const { execute } = useX()` inside the
4235
+ * function that calls it -- cannot expose `loading`, `abort` or `cancelPrevious` at all. Hoist the
4236
+ * instance to where the caller lives first.
2640
4237
  */
2641
4238
  loading: Ref<boolean>;
2642
4239
  };
@@ -2649,6 +4246,9 @@ export declare type UseApiFetchListBatchParams = {
2649
4246
  client: AxiosClientFn;
2650
4247
  system: string;
2651
4248
  entity: string;
4249
+ /** i18n scope for field-level validation failures; defaults to `system` / `entity`. */
4250
+ validationSystem?: string;
4251
+ validationEntity?: string;
2652
4252
  urlTemplate?: string;
2653
4253
  urlParams?: UrlParams;
2654
4254
  /** Anything axios takes except what this helper decides: the method, the url, the body and the signal. */
@@ -2660,12 +4260,27 @@ export declare type UseApiFetchListBatchReturnType<T> = {
2660
4260
  execute: (filterData: FilterData<any>, filterConfig: FilterConfig<any>, params?: FetchListBatchParams) => Promise<T[]>;
2661
4261
  abort: () => void;
2662
4262
  /**
2663
- * True while this instance has a request in flight, false once the last one settles.
4263
+ * True while this instance is working, false once it stops.
4264
+ *
4265
+ * Here that is the whole walk, not one request: a batch reads every page, and the flag stays up
4266
+ * across the gaps between them and across the reading of each answer.
2664
4267
  *
2665
- * It is here so a caller does not have to keep its own: the hand-rolled version is a ref cleared
2666
- * in a `finally`, and that `finally` belongs to whichever call ended -- including one that
4268
+ * It is here so a caller does not have to keep its own: the hand-rolled version is a ref cleared in
4269
+ * a `finally`, and that `finally` belongs to whichever call ended -- including one that
2667
4270
  * `cancelPrevious` just superseded, which turns the spinner off while the call the user is waiting
2668
4271
  * for is still running. This one never dips between a superseded call and the one that replaced it.
4272
+ *
4273
+ * Two things to know before replacing a hand-rolled flag with it.
4274
+ *
4275
+ * It covers what this helper does and nothing the caller does afterwards. A flag that also spans a
4276
+ * follow-up cached fetch, a mapping pass or a second endpoint is not the same flag, and swapping it
4277
+ * for this one turns the spinner off too early. Keep your own where it means more than "this helper
4278
+ * is working".
4279
+ *
4280
+ * It belongs to the instance, so it is only reachable if you hold the instance. A factory that
4281
+ * builds one per call and hands back the promise alone -- `const { execute } = useX()` inside the
4282
+ * function that calls it -- cannot expose `loading`, `abort` or `cancelPrevious` at all. Hoist the
4283
+ * instance to where the caller lives first.
2669
4284
  */
2670
4285
  loading: Ref<boolean>;
2671
4286
  };
@@ -2674,6 +4289,9 @@ export declare type UseApiFetchListParams = {
2674
4289
  client: AxiosClientFn;
2675
4290
  system: string;
2676
4291
  entity: string;
4292
+ /** i18n scope for field-level validation failures; defaults to `system` / `entity`. */
4293
+ validationSystem?: string;
4294
+ validationEntity?: string;
2677
4295
  urlTemplate?: string;
2678
4296
  urlParams?: UrlParams;
2679
4297
  /** Anything axios takes except what this helper decides: the method, the url, the body and the signal. */
@@ -2687,10 +4305,22 @@ export declare type UseApiFetchListReturnType<T> = {
2687
4305
  /**
2688
4306
  * True while this instance has a request in flight, false once the last one settles.
2689
4307
  *
2690
- * It is here so a caller does not have to keep its own: the hand-rolled version is a ref cleared
2691
- * in a `finally`, and that `finally` belongs to whichever call ended -- including one that
4308
+ * It is here so a caller does not have to keep its own: the hand-rolled version is a ref cleared in
4309
+ * a `finally`, and that `finally` belongs to whichever call ended -- including one that
2692
4310
  * `cancelPrevious` just superseded, which turns the spinner off while the call the user is waiting
2693
4311
  * for is still running. This one never dips between a superseded call and the one that replaced it.
4312
+ *
4313
+ * Two things to know before replacing a hand-rolled flag with it.
4314
+ *
4315
+ * It covers what this helper does and nothing the caller does afterwards. A flag that also spans a
4316
+ * follow-up cached fetch, a mapping pass or a second endpoint is not the same flag, and swapping it
4317
+ * for this one turns the spinner off too early. Keep your own where it means more than "this helper
4318
+ * is working".
4319
+ *
4320
+ * It belongs to the instance, so it is only reachable if you hold the instance. A factory that
4321
+ * builds one per call and hands back the promise alone -- `const { execute } = useX()` inside the
4322
+ * function that calls it -- cannot expose `loading`, `abort` or `cancelPrevious` at all. Hoist the
4323
+ * instance to where the caller lives first.
2694
4324
  */
2695
4325
  loading: Ref<boolean>;
2696
4326
  };
@@ -2741,6 +4371,9 @@ export declare type UseApiRequestParams = {
2741
4371
  method: Method;
2742
4372
  system: string;
2743
4373
  entity: string;
4374
+ /** i18n scope for field-level validation failures; defaults to `system` / `entity`. */
4375
+ validationSystem?: string;
4376
+ validationEntity?: string;
2744
4377
  urlTemplate?: string;
2745
4378
  urlParams?: UrlParams;
2746
4379
  /** Anything axios takes except what this helper decides: the method, the url, the body and the signal. */
@@ -2755,14 +4388,40 @@ export declare type UseApiRequestReturnType<R, B> = {
2755
4388
  /**
2756
4389
  * True while this instance has a request in flight, false once the last one settles.
2757
4390
  *
2758
- * It is here so a caller does not have to keep its own: the hand-rolled version is a ref cleared
2759
- * in a `finally`, and that `finally` belongs to whichever call ended -- including one that
4391
+ * It is here so a caller does not have to keep its own: the hand-rolled version is a ref cleared in
4392
+ * a `finally`, and that `finally` belongs to whichever call ended -- including one that
2760
4393
  * `cancelPrevious` just superseded, which turns the spinner off while the call the user is waiting
2761
4394
  * for is still running. This one never dips between a superseded call and the one that replaced it.
4395
+ *
4396
+ * Two things to know before replacing a hand-rolled flag with it.
4397
+ *
4398
+ * It covers what this helper does and nothing the caller does afterwards. A flag that also spans a
4399
+ * follow-up cached fetch, a mapping pass or a second endpoint is not the same flag, and swapping it
4400
+ * for this one turns the spinner off too early. Keep your own where it means more than "this helper
4401
+ * is working".
4402
+ *
4403
+ * It belongs to the instance, so it is only reachable if you hold the instance. A factory that
4404
+ * builds one per call and hands back the promise alone -- `const { execute } = useX()` inside the
4405
+ * function that calls it -- cannot expose `loading`, `abort` or `cancelPrevious` at all. Hoist the
4406
+ * instance to where the caller lives first.
2762
4407
  */
2763
4408
  loading: Ref<boolean>;
2764
4409
  };
2765
4410
 
4411
+ export declare const useCachedPermissionGroups: (params: CachedPermissionGroupsParams) => {
4412
+ cachedPermissionGroups: Ref<Map<number, CachedItem<PermissionGroupMinimal>>, Map<number, CachedItem<PermissionGroupMinimal>>>;
4413
+ toFetchCachedPermissionGroups: Ref<Set<number>, Set<number>>;
4414
+ fetchCachedPermissionGroups: () => Promisify<Promise<PermissionGroup[]>>;
4415
+ immediateFetchCachedPermissionGroups: () => Promise<PermissionGroup[]>;
4416
+ addToCachedPermissionGroups: (...args: AddToCachedArgs<number>) => void;
4417
+ addManualToCachedPermissionGroups: (data: PermissionGroup) => void;
4418
+ addManualMinimalToCachedPermissionGroups: (data: PermissionGroupMinimal) => void;
4419
+ hasCachedPermissionGroup: (id: number | null | undefined) => boolean;
4420
+ getCachedPermissionGroup: (id: number | null | undefined) => CachedItem<PermissionGroupMinimal> | undefined;
4421
+ isLoadedCachedPermissionGroup: (id: number | null | undefined) => boolean;
4422
+ clearCachedPermissionGroups: () => void;
4423
+ };
4424
+
2766
4425
  declare type UseCachedType = () => {
2767
4426
  fetch: any;
2768
4427
  add: any;
@@ -3137,6 +4796,306 @@ declare interface UsePaginationReturnType {
3137
4796
  incrementPage: () => number;
3138
4797
  }
3139
4798
 
4799
+ /**
4800
+ * Builds the grant map a user would end up with, for the editor's "resolved" column, out of what
4801
+ * the page already holds: the groups the user is in plus the grants set on the user directly.
4802
+ *
4803
+ * It is not the backend's `resolvedPermissions`. That one arrives with the record and includes
4804
+ * roles; this one is what the screen would send if saved now, so the editor can show the effect of
4805
+ * a group the operator has just ticked without a round trip.
4806
+ */
4807
+ export declare const usePermissionActions: (params: PermissionActionsParams) => {
4808
+ resolvePermissions: (user: AnzuUser) => Permissions_2;
4809
+ resolveGroupPermissions: (permissionGroupIds: IntegerId[]) => Permissions_2;
4810
+ };
4811
+
4812
+ export declare const usePermissionConfigActions: (params: PermissionConfigActionsParams) => {
4813
+ permissionConfig: ComputedRef<PermissionConfig>;
4814
+ loadingPermissionConfig: ComputedRef<boolean>;
4815
+ isPermissionConfigInitialized: ComputedRef<boolean>;
4816
+ fetchPermissionConfig: (force?: boolean) => Promise<void>;
4817
+ translatePermission: (group: PermissionTranslationGroup, key: string) => string;
4818
+ resetPermissionConfig: () => void;
4819
+ };
4820
+
4821
+ export declare const usePermissionConfigApi: ({ client, system, entity, endPoint, }: PermissionConfigApiParams) => {
4822
+ useFetchPermissionConfig: () => UseApiRequestReturnType<PermissionConfig, null>;
4823
+ };
4824
+
4825
+ export declare const usePermissionConfigStore: SetupStoreDefinition<"labsPermissionConfigStore", {
4826
+ entries: Ref<Map<string, {
4827
+ config: {
4828
+ roles: string[];
4829
+ defaultGrants: GrantType[];
4830
+ config: {
4831
+ [subject: string]: {
4832
+ [action: string]: {
4833
+ grants?: GrantType[];
4834
+ };
4835
+ };
4836
+ };
4837
+ translation: {
4838
+ subjects: {
4839
+ [subject: string]: {
4840
+ [lang: string]: string;
4841
+ };
4842
+ };
4843
+ actions: {
4844
+ [action: string]: {
4845
+ [lang: string]: string;
4846
+ };
4847
+ };
4848
+ roles: {
4849
+ [role: string]: {
4850
+ [lang: string]: string;
4851
+ };
4852
+ };
4853
+ };
4854
+ };
4855
+ loading: boolean;
4856
+ initialized: boolean;
4857
+ }> & Omit<Map<string, PermissionConfigEntry>, keyof Map<any, any>>, Map<string, PermissionConfigEntry> | (Map<string, {
4858
+ config: {
4859
+ roles: string[];
4860
+ defaultGrants: GrantType[];
4861
+ config: {
4862
+ [subject: string]: {
4863
+ [action: string]: {
4864
+ grants?: GrantType[];
4865
+ };
4866
+ };
4867
+ };
4868
+ translation: {
4869
+ subjects: {
4870
+ [subject: string]: {
4871
+ [lang: string]: string;
4872
+ };
4873
+ };
4874
+ actions: {
4875
+ [action: string]: {
4876
+ [lang: string]: string;
4877
+ };
4878
+ };
4879
+ roles: {
4880
+ [role: string]: {
4881
+ [lang: string]: string;
4882
+ };
4883
+ };
4884
+ };
4885
+ };
4886
+ loading: boolean;
4887
+ initialized: boolean;
4888
+ }> & Omit<Map<string, PermissionConfigEntry>, keyof Map<any, any>>)>;
4889
+ getEntry: (system: string) => PermissionConfigEntry;
4890
+ setLoading: (system: string, loading: boolean) => void;
4891
+ setConfig: (system: string, config: PermissionConfig) => void;
4892
+ resetSystem: (system: string) => void;
4893
+ reset: () => void;
4894
+ }>;
4895
+
4896
+ /**
4897
+ * Everything below is per instance. The admins kept `listLoading`, `detailLoading` and
4898
+ * `datatableHiddenColumns` at module scope, which is a single set of flags shared by every caller
4899
+ * -- fine for one list on one backend, wrong for a library a page may instantiate twice.
4900
+ */
4901
+ export declare const usePermissionGroupActions: (params: PermissionGroupActionsParams) => {
4902
+ datatableHiddenColumns: Ref<string[], string[]>;
4903
+ permissionGroupList: Ref<{
4904
+ description: string;
4905
+ _system: string;
4906
+ _resourceName: "permissionGroup";
4907
+ id: IntegerId;
4908
+ title: string;
4909
+ permissions: Permissions_2;
4910
+ createdAt: DatetimeUTC;
4911
+ modifiedAt: DatetimeUTC;
4912
+ modifiedBy: IntegerIdNullable;
4913
+ createdBy: IntegerIdNullable;
4914
+ }[], PermissionGroup[] | {
4915
+ description: string;
4916
+ _system: string;
4917
+ _resourceName: "permissionGroup";
4918
+ id: IntegerId;
4919
+ title: string;
4920
+ permissions: Permissions_2;
4921
+ createdAt: DatetimeUTC;
4922
+ modifiedAt: DatetimeUTC;
4923
+ modifiedBy: IntegerIdNullable;
4924
+ createdBy: IntegerIdNullable;
4925
+ }[]>;
4926
+ loadingPermissionGroupList: Ref<boolean, boolean>;
4927
+ fetchPermissionGroupList: (pagination: Ref<Pagination>, filterData: FilterData<any>, filterConfig: FilterConfig<any>) => Promise<void>;
4928
+ cancelPermissionGroupList: () => void;
4929
+ permissionGroup: Ref<{
4930
+ description: string;
4931
+ _system: string;
4932
+ _resourceName: "permissionGroup";
4933
+ id: IntegerId;
4934
+ title: string;
4935
+ permissions: Permissions_2;
4936
+ createdAt: DatetimeUTC;
4937
+ modifiedAt: DatetimeUTC;
4938
+ modifiedBy: IntegerIdNullable;
4939
+ createdBy: IntegerIdNullable;
4940
+ }, PermissionGroup | {
4941
+ description: string;
4942
+ _system: string;
4943
+ _resourceName: "permissionGroup";
4944
+ id: IntegerId;
4945
+ title: string;
4946
+ permissions: Permissions_2;
4947
+ createdAt: DatetimeUTC;
4948
+ modifiedAt: DatetimeUTC;
4949
+ modifiedBy: IntegerIdNullable;
4950
+ createdBy: IntegerIdNullable;
4951
+ }>;
4952
+ loadingPermissionGroup: Ref<boolean, boolean>;
4953
+ fetchPermissionGroup: (id: IntegerId) => Promise<void>;
4954
+ createPermissionGroup: () => Promise<PermissionGroup | null>;
4955
+ updatePermissionGroup: () => Promise<boolean>;
4956
+ deletePermissionGroup: (id: IntegerId) => Promise<boolean>;
4957
+ loadingCreatePermissionGroup: Ref<boolean, boolean>;
4958
+ loadingUpdatePermissionGroup: Ref<boolean, boolean>;
4959
+ loadingDeletePermissionGroup: Ref<boolean, boolean>;
4960
+ fetchPermissionGroupOptions: (pagination: Ref<Pagination>, filterData: FilterData<any>, filterConfig: FilterConfig<any>) => Promise<ValueObjectOption<IntegerId>[]>;
4961
+ fetchPermissionGroupOptionsByIds: (ids: IntegerId[]) => Promise<ValueObjectOption<IntegerId>[]>;
4962
+ resetPermissionGroupStore: () => void;
4963
+ };
4964
+
4965
+ export declare const usePermissionGroupApi: ({ client, system, entity, validationSystem, validationEntity, endPoint, }: PermissionGroupApiParams) => {
4966
+ useFetchPermissionGroupListByIds: () => UseApiFetchByIdsReturnType<PermissionGroup>;
4967
+ useFetchPermissionGroupList: () => UseApiFetchListReturnType<PermissionGroup>;
4968
+ useFetchPermissionGroup: () => UseApiRequestReturnType<PermissionGroup, null>;
4969
+ useCreatePermissionGroup: () => UseApiRequestReturnType<PermissionGroup, PermissionGroup>;
4970
+ useUpdatePermissionGroup: () => UseApiRequestReturnType<PermissionGroup, PermissionGroup>;
4971
+ useDeletePermissionGroup: () => UseApiRequestReturnType<void, null>;
4972
+ };
4973
+
4974
+ export declare function usePermissionGroupInnerFilter(): {
4975
+ filterConfig: FilterConfig<{
4976
+ name: "title";
4977
+ variant: "startsWith";
4978
+ default: null;
4979
+ type: "string";
4980
+ }[]>;
4981
+ filterData: FilterData<{
4982
+ name: "title";
4983
+ variant: "startsWith";
4984
+ default: null;
4985
+ type: "string";
4986
+ }[]>;
4987
+ };
4988
+
4989
+ export declare function usePermissionGroupListFilter(system: string): {
4990
+ filterConfig: FilterConfig<ListFields>;
4991
+ filterData: FilterData<ListFields>;
4992
+ };
4993
+
4994
+ /**
4995
+ * A single open group, not a map keyed by system.
4996
+ *
4997
+ * Decision 9 of the plan: one system is one route and one view, and there is no cross-system view
4998
+ * of permission groups at all. Only one group is ever open, so a per-system map would be state
4999
+ * nothing reads -- unlike the config store next door, which really is asked about several systems
5000
+ * at once by the cross-system user pages.
5001
+ */
5002
+ export declare const usePermissionGroupOneStore: SetupStoreDefinition<"labsPermissionGroupOneStore", {
5003
+ permissionGroup: Ref<{
5004
+ description: string;
5005
+ _system: string;
5006
+ _resourceName: "permissionGroup";
5007
+ id: IntegerId;
5008
+ title: string;
5009
+ permissions: Permissions_2;
5010
+ createdAt: DatetimeUTC;
5011
+ modifiedAt: DatetimeUTC;
5012
+ modifiedBy: IntegerIdNullable;
5013
+ createdBy: IntegerIdNullable;
5014
+ }, PermissionGroup | {
5015
+ description: string;
5016
+ _system: string;
5017
+ _resourceName: "permissionGroup";
5018
+ id: IntegerId;
5019
+ title: string;
5020
+ permissions: Permissions_2;
5021
+ createdAt: DatetimeUTC;
5022
+ modifiedAt: DatetimeUTC;
5023
+ modifiedBy: IntegerIdNullable;
5024
+ createdBy: IntegerIdNullable;
5025
+ }>;
5026
+ loadingPermissionGroup: Ref<boolean, boolean>;
5027
+ setPermissionGroup: (newPermissionGroup: PermissionGroup) => void;
5028
+ setLoadingPermissionGroup: (loading: boolean) => void;
5029
+ reset: () => void;
5030
+ }>;
5031
+
5032
+ /**
5033
+ * The same three rules all five admins carry today, verbatim. They are not derived from the
5034
+ * backend: `PermissionGroupDto` only requires a title, and the lengths here are the front-end's
5035
+ * own stricter profile.
5036
+ */
5037
+ export declare function usePermissionGroupValidation(permissionGroup: Ref<PermissionGroup>): {
5038
+ v$: Ref< Validation<{
5039
+ permissionGroup: {
5040
+ title: {
5041
+ required: ValidationRuleWithoutParams<any>;
5042
+ minLength: ValidationRuleWithParams<{
5043
+ min: number;
5044
+ }, any>;
5045
+ maxLength: ValidationRuleWithParams<{
5046
+ max: number;
5047
+ }, any>;
5048
+ };
5049
+ description: {
5050
+ maxLength: ValidationRuleWithParams<{
5051
+ max: number;
5052
+ }, any>;
5053
+ };
5054
+ };
5055
+ }, {
5056
+ permissionGroup: Ref<PermissionGroup, PermissionGroup>;
5057
+ }>, Validation<{
5058
+ permissionGroup: {
5059
+ title: {
5060
+ required: ValidationRuleWithoutParams<any>;
5061
+ minLength: ValidationRuleWithParams<{
5062
+ min: number;
5063
+ }, any>;
5064
+ maxLength: ValidationRuleWithParams<{
5065
+ max: number;
5066
+ }, any>;
5067
+ };
5068
+ description: {
5069
+ maxLength: ValidationRuleWithParams<{
5070
+ max: number;
5071
+ }, any>;
5072
+ };
5073
+ };
5074
+ }, {
5075
+ permissionGroup: Ref<PermissionGroup, PermissionGroup>;
5076
+ }>>;
5077
+ };
5078
+
5079
+ /**
5080
+ * The six fields the cross-system view compares.
5081
+ *
5082
+ * `email` is in the list and is also the reason the e-mail search runs twice: if a person is
5083
+ * `jozko@sme.sk` in weather and `j.mrkvicka@sme.sk` in blog, a search by e-mail finds weather and
5084
+ * blog answers nothing -- which looks exactly like "no account here". The second round, by the id
5085
+ * the first round found, is what turns that silence into the inconsistency it actually is.
5086
+ */
5087
+ export declare const USER_METADATA_FIELDS: readonly ["email", "person.firstName", "person.lastName", "person.fullName", "avatar.color", "avatar.text"];
5088
+
5089
+ /**
5090
+ * What the probe calls itself in the error context.
5091
+ *
5092
+ * A 404 here is an answer, not a failure -- it is how a system says "no account of yours". It still
5093
+ * reaches the api error logger like any other, so an app filters on this together with the status
5094
+ * rather than on the url, which would also silence a real detail read of the same path. The
5095
+ * validation scope stays the user's, so a field error would still name a real label.
5096
+ */
5097
+ export declare const USER_PROBE_ENTITY = "anzuUserProbe";
5098
+
3140
5099
  export declare interface UserAdminConfig<TData = UserAdminConfigDataFilterBookmark | UserAdminConfigDataPinnedWidgets> extends AnzuUserAndTimeTrackingAware, SortableItemDataAware {
3141
5100
  id: IntegerId;
3142
5101
  user: IntegerId;
@@ -3180,6 +5139,215 @@ export declare const UserAdminConfigTypeDefault: "pinnedWidgets";
3180
5139
 
3181
5140
  export declare type UserAdminConfigTypeType = (typeof UserAdminConfigType)[keyof typeof UserAdminConfigType];
3182
5141
 
5142
+ export declare type UserMetadataField = (typeof USER_METADATA_FIELDS)[number];
5143
+
5144
+ export declare interface UserMetadataValidationOptions {
5145
+ /**
5146
+ * The system's profile (`requiredMetadata` on its descriptor). `false` requires only the
5147
+ * e-mail; `true` also requires first name, last name, full name, avatar text and avatar colour.
5148
+ * It applies the same way to creating and to editing -- within a system it is one rule.
5149
+ */
5150
+ required: boolean;
5151
+ /** Whether the id is a field at all. When it is, and this is a create, it is required. */
5152
+ idInput: boolean;
5153
+ isEdit: boolean;
5154
+ /** Scope key, so an owning form can validate its own fields alongside the app's system fields. */
5155
+ scope?: string | symbol | false;
5156
+ }
5157
+
5158
+ export declare const UserSystemAccess: {
5159
+ readonly Ok: "ok";
5160
+ readonly Forbidden: "forbidden";
5161
+ readonly Unauthenticated: "unauthenticated";
5162
+ readonly Unavailable: "unavailable";
5163
+ readonly ConfigDisabled: "configDisabled";
5164
+ };
5165
+
5166
+ export declare type UserSystemAccessType = (typeof UserSystemAccess)[keyof typeof UserSystemAccess];
5167
+
5168
+ /**
5169
+ * `enabled` is one of the axes and not a detail: without it the two states the cross-system view
5170
+ * shows most often -- "the account is here and on" versus "here and off" -- cannot be told apart.
5171
+ *
5172
+ * Ownership is deliberately *not* an axis. None of the six visual states below distinguishes it;
5173
+ * it decides which button is drawn, and that is the descriptor's `manage` union.
5174
+ */
5175
+ export declare interface UserSystemAxes {
5176
+ load: UserSystemLoadType;
5177
+ presence: UserSystemPresenceType;
5178
+ access: UserSystemAccessType;
5179
+ enabled: boolean | 'unknown';
5180
+ }
5181
+
5182
+ export declare interface UserSystemDescriptor<TSystem extends string = string, TUser extends AnzuUser = AnzuUser> {
5183
+ system: TSystem;
5184
+ client: AxiosClientFn;
5185
+ /** Reaches every `useApiRequest` built for this system; see `permissionGroupApi`. */
5186
+ entity: string;
5187
+ /**
5188
+ * Whether the system is switched on in this admin's configuration. Mandatory, not optional: the
5189
+ * "disabled in configuration" state has to be *shown*, so leaving the system out of the array is
5190
+ * not the same thing. The value is app-specific (`envConfig[system].enabled`) and the library has
5191
+ * no way to read it.
5192
+ */
5193
+ isEnabled: () => boolean;
5194
+ /**
5195
+ * Which validation profile this system's form uses. `false` means only the e-mail is required;
5196
+ * `true` adds first name, last name, full name, avatar text and avatar colour. It is a property
5197
+ * of the system, and it is the same for creating and for editing.
5198
+ */
5199
+ requiredMetadata: boolean;
5200
+ /**
5201
+ * Whether the id is typed in. False only in cms, where the backend looks it up in SSO from the
5202
+ * e-mail. On an edit the field is read-only regardless.
5203
+ */
5204
+ idInput: boolean;
5205
+ extraState?: (user: TUser) => UserSystemExtraState | null;
5206
+ /** Above the `enabled` switch and in the row of a bulk action. */
5207
+ enabledNote?: string;
5208
+ /** In the metadata repair dialog and in the owning form. */
5209
+ metadataNote?: string;
5210
+ /** In the confirmation dialog when an account is created here. */
5211
+ createNote?: string;
5212
+ endpoints: UserSystemEndpoints;
5213
+ /** Added in task 2: the system's name as the app translates it. */
5214
+ label?: string;
5215
+ /** Added in task 2. */
5216
+ manage?: (user: TUser) => UserSystemManageTarget;
5217
+ }
5218
+
5219
+ /**
5220
+ * Paired GET + write paths, never loose urls.
5221
+ *
5222
+ * This is what makes the write invariant expressible: a write body is always the whole object the
5223
+ * preceding GET on the *same path* returned. The two paths return different DTOs -- `/adm/users`
5224
+ * in cms answers `CmsUserDto` and its PUT runs `updateRelations()` over seven scalars and twelve
5225
+ * collections -- so a GET from one path and a PUT to the other silently drops whatever the other
5226
+ * DTO carries.
5227
+ */
5228
+ export declare interface UserSystemEndpoints {
5229
+ anzuUser: AnzuUserEndpointPair | null;
5230
+ base: BaseUserEndpointPair | null;
5231
+ permissionGroup: string;
5232
+ /**
5233
+ * Per system, not one constant. contentHub's is `/adm/users/current`, and the admins had this
5234
+ * hard-coded as a single path shared by every backend.
5235
+ */
5236
+ currentUser: string;
5237
+ list: string;
5238
+ /**
5239
+ * Which pair the probe reads through. A field rather than something derived, because in dam the
5240
+ * choice is visible to the operator: `GET /adm/v1/anzu-user/{id}` has no gating at all while
5241
+ * `GET /adm/users/{id}` sits behind `DAM_USER_READ`, so only the second can ever render "you
5242
+ * have no access". The rule is "the probe goes the way the write goes".
5243
+ */
5244
+ probe: 'anzuUser' | 'base';
5245
+ }
5246
+
5247
+ /**
5248
+ * A state a system has on top of `enabled`, shown next to it. Today only two systems have one:
5249
+ * blog's `status` (guest / waiting_approval / active / ban / gdpr_deleted) and forum's
5250
+ * `settings.banned`. Both arrive with the record -- they are `#[Serialize]` on the entity -- so
5251
+ * rendering one costs no extra call.
5252
+ */
5253
+ export declare interface UserSystemExtraState {
5254
+ /** "blogger", "commenter" -- the app translates it; the library only prints it. */
5255
+ label: string;
5256
+ /** "active", "banned". */
5257
+ value: string;
5258
+ tone: 'ok' | 'warn' | 'error';
5259
+ }
5260
+
5261
+ /**
5262
+ * Four independent axes inside, one derived state outside.
5263
+ *
5264
+ * The axes are kept apart because they answer different questions and can move independently: a
5265
+ * system can be loaded and forbidden, or absent and still enabled in configuration. Collapsing
5266
+ * them into one enum early is what made the per-admin prototypes conflate "no access" with "no
5267
+ * account here" -- admin-cms's panel leaves `userExists` at null on any non-404 and offers
5268
+ * "Create" in a system the operator cannot even read.
5269
+ */
5270
+ export declare const UserSystemLoad: {
5271
+ readonly Idle: "idle";
5272
+ readonly Loading: "loading";
5273
+ readonly Loaded: "loaded";
5274
+ readonly Error: "error";
5275
+ };
5276
+
5277
+ export declare type UserSystemLoadType = (typeof UserSystemLoad)[keyof typeof UserSystemLoad];
5278
+
5279
+ /**
5280
+ * Where "manage in X" leads. A callback over the user rather than a static value: a global
5281
+ * descriptor does not know which row is being drawn.
5282
+ *
5283
+ * The return type is a discriminated union so the two cannot be confused in code either -- an
5284
+ * internal target is pushed through the router, an external one is an `<a href>` opened in a new
5285
+ * tab, and `href: null` is a configured-but-missing url, which renders disabled with a reason
5286
+ * rather than as a dead button.
5287
+ */
5288
+ export declare type UserSystemManageTarget = {
5289
+ kind: 'internal';
5290
+ to: RouteLocationRaw;
5291
+ } | {
5292
+ kind: 'external';
5293
+ href: string | null;
5294
+ };
5295
+
5296
+ export declare const UserSystemPresence: {
5297
+ readonly Present: "present";
5298
+ readonly Absent: "absent";
5299
+ readonly Unknown: "unknown";
5300
+ };
5301
+
5302
+ export declare type UserSystemPresenceType = (typeof UserSystemPresence)[keyof typeof UserSystemPresence];
5303
+
5304
+ export declare interface UserSystemProbeParams {
5305
+ descriptor: AnyUserSystemDescriptor;
5306
+ /** Usually injected once per page; passing it explicitly is for tests and one-off panels. */
5307
+ refreshHook?: UserSystemRefreshHook | undefined;
5308
+ }
5309
+
5310
+ export declare interface UserSystemProbeResult {
5311
+ axes: Ref<UserSystemAxes>;
5312
+ user: Ref<AnzuUser | null>;
5313
+ probe: (id: IntegerId) => Promise<void>;
5314
+ reset: () => void;
5315
+ cancel: () => void;
5316
+ }
5317
+
5318
+ /**
5319
+ * How an app refreshes a session for one system, and retries.
5320
+ *
5321
+ * The library cannot do this itself: a first 401 is ambiguous -- expired session or no account --
5322
+ * and the only way to tell them apart is to refresh and ask again. Every admin has its own
5323
+ * mechanism (`refreshSession.ts` in inhouse, an interceptor in cms, `requestRefreshToken.ts` in
5324
+ * blog) and none of them lives in `common-admin`. Without this hook a panel would show an expired
5325
+ * token as "no account here", which is exactly the confusion decision 16 forbids.
5326
+ *
5327
+ * Returns true when the refresh succeeded and the call is worth repeating.
5328
+ */
5329
+ export declare type UserSystemRefreshHook = (system: string) => Promise<boolean>;
5330
+
5331
+ export declare const UserSystemRefreshHookKey: InjectionKey<UserSystemRefreshHook>;
5332
+
5333
+ export declare interface UserSystemResult {
5334
+ axes: UserSystemAxes;
5335
+ user: AnzuUser | null;
5336
+ }
5337
+
5338
+ export declare const UserSystemState: {
5339
+ /** Nothing has been asked yet, or the answer is still on its way. */
5340
+ readonly Loading: "loading";
5341
+ readonly Enabled: "enabled";
5342
+ readonly Disabled: "disabled";
5343
+ readonly Absent: "absent";
5344
+ readonly Forbidden: "forbidden";
5345
+ readonly Unavailable: "unavailable";
5346
+ readonly ConfigDisabled: "configDisabled";
5347
+ };
5348
+
5349
+ export declare type UserSystemStateType = (typeof UserSystemState)[keyof typeof UserSystemState];
5350
+
3183
5351
  export declare function useSubjectSelect<TItem>(datatableConfig: any, datatableHiddenColumns: any, system: string, subject: string, execute: (pagination: Ref<Pagination>, filterData: FilterData<any>, filterConfig: FilterConfig<any>, params?: FetchListParams) => Promise<TItem[]>, filterData: FilterData<any>, filterConfig: FilterConfig<any>, filterSortBy?: DatatableSortBy | null, fetchParams?: FetchListParams | undefined, enableActions?: boolean): {
3184
5352
  items: Ref<TItem[], TItem[]>;
3185
5353
  selected: Ref<TItem[], TItem[]>;
@@ -3308,6 +5476,352 @@ export declare function useUserAdminConfigFactory(): {
3308
5476
  createDefaultUserAdminConfig: (system: string) => UserAdminConfig;
3309
5477
  };
3310
5478
 
5479
+ /**
5480
+ * The cross-system fan-out.
5481
+ *
5482
+ * No calls to the current-user endpoints go out at all: the buttons in a row are decided by the
5483
+ * probe's answer rather than by `<Acl>`, so there is nothing to load nine current users for. The
5484
+ * budget is nine calls when searching by id, eighteen when searching by e-mail.
5485
+ */
5486
+ export declare const useUserCrossSystemSearch: (params: CrossSystemSearchParams) => {
5487
+ search: (term: string) => Promise<boolean>;
5488
+ searchById: (id: IntegerId) => Promise<void>;
5489
+ searchByEmail: (email: string) => Promise<void>;
5490
+ refreshSystem: (system: string) => Promise<void>;
5491
+ resultFor: (system: string) => UserSystemResult | undefined;
5492
+ unresolvedSystems: ComputedRef<string[]>;
5493
+ cancel: () => void;
5494
+ };
5495
+
5496
+ /**
5497
+ * Search results and the bulk run live here, not inside the dialog's component.
5498
+ *
5499
+ * The dialog can be closed while the calls are still going -- one dead backend running into its
5500
+ * timeout must not lock the screen -- and state owned by the component would be thrown away with
5501
+ * it. The results stay on the page either way.
5502
+ */
5503
+ export declare const useUserCrossSystemStore: SetupStoreDefinition<"labsUserCrossSystemStore", {
5504
+ searchTerm: Ref<string, string>;
5505
+ resolvedId: Ref<IntegerIdNullable, IntegerIdNullable>;
5506
+ phase: Ref<CrossSystemPhaseType, CrossSystemPhaseType>;
5507
+ results: Ref<Map<string, {
5508
+ axes: {
5509
+ load: UserSystemLoadType;
5510
+ presence: UserSystemPresenceType;
5511
+ access: UserSystemAccessType;
5512
+ enabled: boolean | "unknown";
5513
+ };
5514
+ user: {
5515
+ enabled: boolean;
5516
+ locale: LanguageCode | null;
5517
+ roles: string[];
5518
+ permissionGroups: IntegerId[];
5519
+ permissions: Permissions_2;
5520
+ resolvedPermissions: Permissions_2;
5521
+ _resourceName: string;
5522
+ _system: string;
5523
+ createdAt: DatetimeUTC;
5524
+ modifiedAt: DatetimeUTC;
5525
+ modifiedBy: IntegerIdNullable;
5526
+ createdBy: IntegerIdNullable;
5527
+ id?: IntegerIdNullable | undefined;
5528
+ email: string;
5529
+ person: {
5530
+ firstName: string;
5531
+ lastName: string;
5532
+ fullName: string;
5533
+ };
5534
+ avatar: {
5535
+ color: string;
5536
+ text: string;
5537
+ };
5538
+ } | null;
5539
+ }> & Omit<Map<string, UserSystemResult>, keyof Map<any, any>>, Map<string, UserSystemResult> | (Map<string, {
5540
+ axes: {
5541
+ load: UserSystemLoadType;
5542
+ presence: UserSystemPresenceType;
5543
+ access: UserSystemAccessType;
5544
+ enabled: boolean | "unknown";
5545
+ };
5546
+ user: {
5547
+ enabled: boolean;
5548
+ locale: LanguageCode | null;
5549
+ roles: string[];
5550
+ permissionGroups: IntegerId[];
5551
+ permissions: Permissions_2;
5552
+ resolvedPermissions: Permissions_2;
5553
+ _resourceName: string;
5554
+ _system: string;
5555
+ createdAt: DatetimeUTC;
5556
+ modifiedAt: DatetimeUTC;
5557
+ modifiedBy: IntegerIdNullable;
5558
+ createdBy: IntegerIdNullable;
5559
+ id?: IntegerIdNullable | undefined;
5560
+ email: string;
5561
+ person: {
5562
+ firstName: string;
5563
+ lastName: string;
5564
+ fullName: string;
5565
+ };
5566
+ avatar: {
5567
+ color: string;
5568
+ text: string;
5569
+ };
5570
+ } | null;
5571
+ }> & Omit<Map<string, UserSystemResult>, keyof Map<any, any>>)>;
5572
+ identityConflict: Ref<(Map<string, number> & Omit<Map<string, number>, keyof Map<any, any>>) | null, Map<string, number> | (Map<string, number> & Omit<Map<string, number>, keyof Map<any, any>>) | null>;
5573
+ bulkRunning: Ref<boolean, boolean>;
5574
+ bulkAction: Ref<BulkActionType | null, BulkActionType | null>;
5575
+ bulkSubjectId: Ref<IntegerIdNullable, IntegerIdNullable>;
5576
+ bulkLog: Ref<{
5577
+ system: string;
5578
+ outcome: BulkOutcomeType;
5579
+ action: BulkActionType;
5580
+ subjectId: IntegerIdNullable;
5581
+ detail?: string | undefined;
5582
+ }[], BulkLogEntry[] | {
5583
+ system: string;
5584
+ outcome: BulkOutcomeType;
5585
+ action: BulkActionType;
5586
+ subjectId: IntegerIdNullable;
5587
+ detail?: string | undefined;
5588
+ }[]>;
5589
+ termRejected: Ref<boolean, boolean>;
5590
+ resetResults: () => void;
5591
+ setResult: (system: string, result: UserSystemResult) => void;
5592
+ patchAxes: (system: string, axes: UserSystemAxes) => void;
5593
+ setUser: (system: string, user: AnzuUser | null) => void;
5594
+ startBulk: (action: BulkActionType, systems: string[], subjectId: IntegerIdNullable) => void;
5595
+ setBulkEntry: (system: string, outcome: BulkOutcomeType, detail?: string) => void;
5596
+ finishBulk: () => void;
5597
+ reset: () => void;
5598
+ }>;
5599
+
5600
+ export declare const useUserCrossSystemWrites: () => {
5601
+ setEnabled: (descriptor: AnyUserSystemDescriptor, id: IntegerId, enabled: boolean) => Promise<WriteResult>;
5602
+ writeMetadata: (descriptor: AnyUserSystemDescriptor, id: IntegerId, target: BaseUser, fields?: readonly UserMetadataField[], seen?: BaseUser | null) => Promise<WriteResult & {
5603
+ changed: boolean;
5604
+ }>;
5605
+ createInSystem: (descriptor: AnyUserSystemDescriptor, body: AnzuUser) => Promise<WriteResult>;
5606
+ readSourceUser: (descriptor: AnyUserSystemDescriptor, id: IntegerId) => Promise<AnzuUser | null>;
5607
+ };
5608
+
5609
+ /**
5610
+ * The `BaseUserDto` rules, per profile.
5611
+ *
5612
+ * The lengths come from the backend constraints (`email` 256, first/last 120, full 242, avatar
5613
+ * text 2-3). The backend requires only the e-mail; the front end is deliberately stricter, and
5614
+ * `requiredMetadata` is what says by how much.
5615
+ */
5616
+ export declare function useUserMetadataValidation(user: Ref<BaseUser>, options: UserMetadataValidationOptions): {
5617
+ v$: Ref< Validation<{
5618
+ user: {
5619
+ id: {
5620
+ required: ValidationRuleWithoutParams<any>;
5621
+ } | {
5622
+ required?: undefined;
5623
+ };
5624
+ email: {
5625
+ required: ValidationRuleWithoutParams<any>;
5626
+ email: ValidationRuleWithoutParams<any>;
5627
+ maxLength: ValidationRuleWithParams<{
5628
+ max: number;
5629
+ }, any>;
5630
+ };
5631
+ person: {
5632
+ firstName: {
5633
+ minLength: ValidationRuleWithParams<{
5634
+ min: number;
5635
+ }, any>;
5636
+ maxLength: ValidationRuleWithParams<{
5637
+ max: number;
5638
+ }, any>;
5639
+ required: ValidationRuleWithoutParams<any>;
5640
+ } | {
5641
+ minLength: ValidationRuleWithParams<{
5642
+ min: number;
5643
+ }, any>;
5644
+ maxLength: ValidationRuleWithParams<{
5645
+ max: number;
5646
+ }, any>;
5647
+ required?: undefined;
5648
+ };
5649
+ lastName: {
5650
+ minLength: ValidationRuleWithParams<{
5651
+ min: number;
5652
+ }, any>;
5653
+ maxLength: ValidationRuleWithParams<{
5654
+ max: number;
5655
+ }, any>;
5656
+ required: ValidationRuleWithoutParams<any>;
5657
+ } | {
5658
+ minLength: ValidationRuleWithParams<{
5659
+ min: number;
5660
+ }, any>;
5661
+ maxLength: ValidationRuleWithParams<{
5662
+ max: number;
5663
+ }, any>;
5664
+ required?: undefined;
5665
+ };
5666
+ fullName: {
5667
+ minLength: ValidationRuleWithParams<{
5668
+ min: number;
5669
+ }, any>;
5670
+ maxLength: ValidationRuleWithParams<{
5671
+ max: number;
5672
+ }, any>;
5673
+ required: ValidationRuleWithoutParams<any>;
5674
+ } | {
5675
+ minLength: ValidationRuleWithParams<{
5676
+ min: number;
5677
+ }, any>;
5678
+ maxLength: ValidationRuleWithParams<{
5679
+ max: number;
5680
+ }, any>;
5681
+ required?: undefined;
5682
+ };
5683
+ };
5684
+ avatar: {
5685
+ color: {
5686
+ hexColor: any;
5687
+ required: ValidationRuleWithoutParams<any>;
5688
+ } | {
5689
+ hexColor: any;
5690
+ required?: undefined;
5691
+ };
5692
+ text: {
5693
+ minLength: ValidationRuleWithParams<{
5694
+ min: number;
5695
+ }, any>;
5696
+ maxLength: ValidationRuleWithParams<{
5697
+ max: number;
5698
+ }, any>;
5699
+ required: ValidationRuleWithoutParams<any>;
5700
+ } | {
5701
+ minLength: ValidationRuleWithParams<{
5702
+ min: number;
5703
+ }, any>;
5704
+ maxLength: ValidationRuleWithParams<{
5705
+ max: number;
5706
+ }, any>;
5707
+ required?: undefined;
5708
+ };
5709
+ };
5710
+ };
5711
+ }, {
5712
+ user: Ref<BaseUser, BaseUser>;
5713
+ }>, Validation<{
5714
+ user: {
5715
+ id: {
5716
+ required: ValidationRuleWithoutParams<any>;
5717
+ } | {
5718
+ required?: undefined;
5719
+ };
5720
+ email: {
5721
+ required: ValidationRuleWithoutParams<any>;
5722
+ email: ValidationRuleWithoutParams<any>;
5723
+ maxLength: ValidationRuleWithParams<{
5724
+ max: number;
5725
+ }, any>;
5726
+ };
5727
+ person: {
5728
+ firstName: {
5729
+ minLength: ValidationRuleWithParams<{
5730
+ min: number;
5731
+ }, any>;
5732
+ maxLength: ValidationRuleWithParams<{
5733
+ max: number;
5734
+ }, any>;
5735
+ required: ValidationRuleWithoutParams<any>;
5736
+ } | {
5737
+ minLength: ValidationRuleWithParams<{
5738
+ min: number;
5739
+ }, any>;
5740
+ maxLength: ValidationRuleWithParams<{
5741
+ max: number;
5742
+ }, any>;
5743
+ required?: undefined;
5744
+ };
5745
+ lastName: {
5746
+ minLength: ValidationRuleWithParams<{
5747
+ min: number;
5748
+ }, any>;
5749
+ maxLength: ValidationRuleWithParams<{
5750
+ max: number;
5751
+ }, any>;
5752
+ required: ValidationRuleWithoutParams<any>;
5753
+ } | {
5754
+ minLength: ValidationRuleWithParams<{
5755
+ min: number;
5756
+ }, any>;
5757
+ maxLength: ValidationRuleWithParams<{
5758
+ max: number;
5759
+ }, any>;
5760
+ required?: undefined;
5761
+ };
5762
+ fullName: {
5763
+ minLength: ValidationRuleWithParams<{
5764
+ min: number;
5765
+ }, any>;
5766
+ maxLength: ValidationRuleWithParams<{
5767
+ max: number;
5768
+ }, any>;
5769
+ required: ValidationRuleWithoutParams<any>;
5770
+ } | {
5771
+ minLength: ValidationRuleWithParams<{
5772
+ min: number;
5773
+ }, any>;
5774
+ maxLength: ValidationRuleWithParams<{
5775
+ max: number;
5776
+ }, any>;
5777
+ required?: undefined;
5778
+ };
5779
+ };
5780
+ avatar: {
5781
+ color: {
5782
+ hexColor: any;
5783
+ required: ValidationRuleWithoutParams<any>;
5784
+ } | {
5785
+ hexColor: any;
5786
+ required?: undefined;
5787
+ };
5788
+ text: {
5789
+ minLength: ValidationRuleWithParams<{
5790
+ min: number;
5791
+ }, any>;
5792
+ maxLength: ValidationRuleWithParams<{
5793
+ max: number;
5794
+ }, any>;
5795
+ required: ValidationRuleWithoutParams<any>;
5796
+ } | {
5797
+ minLength: ValidationRuleWithParams<{
5798
+ min: number;
5799
+ }, any>;
5800
+ maxLength: ValidationRuleWithParams<{
5801
+ max: number;
5802
+ }, any>;
5803
+ required?: undefined;
5804
+ };
5805
+ };
5806
+ };
5807
+ }, {
5808
+ user: Ref<BaseUser, BaseUser>;
5809
+ }>>;
5810
+ };
5811
+
5812
+ /**
5813
+ * One system's answer about one user.
5814
+ *
5815
+ * Reads through `endpoints[probe].get`, never a hard-coded path: in dam the choice is visible to
5816
+ * the operator, because `/adm/v1/anzu-user/{id}` has no gating there while `/adm/users/{id}` sits
5817
+ * behind `DAM_USER_READ` -- only the second can ever render "you have no access".
5818
+ *
5819
+ * Note for the app: a probe answering 404 is an expected result here, not a failure, but it still
5820
+ * reaches the api error logger. Filter on `status === 404 && entity === USER_PROBE_ENTITY`, or
5821
+ * every absent account writes a line into the log.
5822
+ */
5823
+ export declare const useUserSystemProbe: (params: UserSystemProbeParams) => UserSystemProbeResult;
5824
+
3311
5825
  declare interface ValueObjectOption<T> {
3312
5826
  value: T;
3313
5827
  title: string;
@@ -3324,6 +5838,22 @@ declare interface ViewBodySlotProps<TItem extends Record<string, any>> {
3324
5838
  };
3325
5839
  }
3326
5840
 
5841
+ export declare const writeMetadataField: (user: BaseUser, field: UserMetadataField, value: string) => void;
5842
+
5843
+ export declare interface WriteResult {
5844
+ outcome: BulkOutcomeType;
5845
+ /** What the server holds afterwards, when it answered with the record. */
5846
+ user?: AnzuUser;
5847
+ /**
5848
+ * Fields whose stored value had moved away from both the target and what the search saw.
5849
+ *
5850
+ * The write still goes through -- decision 24 says the operator's value wins -- but somebody
5851
+ * edited the record in between, and the log line says so rather than letting it pass unnoticed.
5852
+ */
5853
+ concurrentFields?: UserMetadataField[];
5854
+ detail?: string;
5855
+ }
5856
+
3327
5857
  export { }
3328
5858
 
3329
5859