@swiss-ai-hub/web 0.303.0 → 0.304.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,67 @@
1
+ <template>
2
+ <div class="flex flex-col gap-1 rounded-lg border border-surface-200 p-6 dark:border-surface-700">
3
+ <div class="flex items-center gap-2">
4
+ <span class="text-xl font-bold">
5
+ {{ readonly ? t('role.capabilities_readonly_title') : t('role.capabilities_title') }}
6
+ </span>
7
+ <ProgressSpinner
8
+ v-if="capabilitiesAreLoading"
9
+ style="width: 1rem; height: 1rem"
10
+ stroke-width="6"
11
+ />
12
+ </div>
13
+ <p class="text-xs text-surface-500 dark:text-surface-400">
14
+ {{ readonly ? t('role.capabilities_readonly_subtitle') : t('role.capabilities_subtitle') }}
15
+ </p>
16
+
17
+ <div class="mt-5 flex flex-col gap-10">
18
+ <AccessCapabilityGroup
19
+ v-for="group in capabilities?.groups ?? []"
20
+ :key="group.key"
21
+ :group="group"
22
+ :depth="0"
23
+ :readonly="readonly"
24
+ @add="(rule) => emit('add', rule)"
25
+ @remove="(rule) => emit('remove', rule)"
26
+ />
27
+ </div>
28
+ <p
29
+ v-if="!capabilitiesAreLoading && !(capabilities?.groups?.length)"
30
+ class="text-sm italic text-surface-500 dark:text-surface-400"
31
+ >
32
+ {{ t('role.capabilities_empty') }}
33
+ </p>
34
+ </div>
35
+ </template>
36
+
37
+ <script setup lang="ts">
38
+ import { useI18n } from 'vue-i18n'
39
+
40
+ import AccessCapabilityGroup from './AccessCapabilityGroup.vue'
41
+
42
+ import { useAccessCapabilities } from '@/composables/access/useAccessCapabilities'
43
+
44
+ const { t } = useI18n()
45
+
46
+ const props = withDefaults(defineProps<{
47
+ rules: string[]
48
+ restrictToTenant?: boolean
49
+ isSysAdmin?: boolean
50
+ readonly?: boolean
51
+ }>(), {
52
+ restrictToTenant: true,
53
+ isSysAdmin: false,
54
+ readonly: false,
55
+ })
56
+
57
+ const emit = defineEmits<{
58
+ add: [rule: string]
59
+ remove: [rule: string]
60
+ }>()
61
+
62
+ const { capabilities, capabilitiesAreLoading } = useAccessCapabilities(
63
+ () => props.rules,
64
+ () => props.restrictToTenant,
65
+ () => props.isSysAdmin,
66
+ )
67
+ </script>
@@ -0,0 +1,130 @@
1
+ <template>
2
+ <div class="flex flex-col">
3
+ <!-- Service header: icon + name + hairline rule -->
4
+ <div
5
+ v-if="depth === 0"
6
+ class="flex items-center gap-2.5 border-b border-surface-200 pb-2.5 dark:border-surface-800"
7
+ >
8
+ <Icon
9
+ v-if="group.icon"
10
+ :name="group.icon"
11
+ size="1.4em"
12
+ class="text-surface-500 dark:text-surface-400"
13
+ />
14
+ <span class="text-lg font-bold">{{ group.label }}</span>
15
+ </div>
16
+
17
+ <!-- Class subtitle -->
18
+ <div
19
+ v-else-if="depth === 1"
20
+ class="flex items-center gap-2"
21
+ >
22
+ <Icon
23
+ v-if="group.icon"
24
+ :name="group.icon"
25
+ size="1.2em"
26
+ class="text-surface-500 dark:text-surface-400"
27
+ />
28
+ <span class="text-base font-semibold text-surface-700 dark:text-surface-200">
29
+ {{ group.label }}
30
+ </span>
31
+ </div>
32
+
33
+ <!-- Instance subtitle -->
34
+ <div
35
+ v-else
36
+ class="flex items-center gap-2 text-sm font-medium text-surface-600 dark:text-surface-300"
37
+ >
38
+ <span class="size-1.5 rounded-full bg-surface-300 dark:bg-surface-600" />
39
+ {{ group.label }}
40
+ </div>
41
+
42
+ <!-- Capabilities -->
43
+ <div
44
+ class="flex flex-col gap-1"
45
+ :class="depth === 0 ? 'mt-3' : 'mt-2'"
46
+ >
47
+ <label
48
+ v-for="cap in group.capabilities ?? []"
49
+ :key="cap.key"
50
+ class="group/cap flex items-start gap-3 rounded-md py-1 pr-1"
51
+ :class="readonly || !cap.toggleable || cap.locked ? 'cursor-default' : 'cursor-pointer'"
52
+ >
53
+ <Checkbox
54
+ :model-value="cap.granted"
55
+ binary
56
+ :disabled="readonly || !cap.toggleable || cap.locked"
57
+ size="small"
58
+ class="mt-0.5"
59
+ @update:model-value="(value) => onToggle(cap, value)"
60
+ />
61
+ <span class="flex min-w-0 flex-1 flex-col">
62
+ <span class="flex items-center gap-1.5 text-sm leading-tight">
63
+ {{ cap.label }}
64
+ <template v-if="!readonly">
65
+ <i
66
+ v-if="cap.locked"
67
+ v-tooltip.top="t('role.capability_locked')"
68
+ class="pi pi-lock text-[10px] text-surface-400"
69
+ />
70
+ <i
71
+ v-else-if="!cap.toggleable"
72
+ v-tooltip.top="t('role.capability_readonly')"
73
+ class="pi pi-eye text-[10px] text-surface-400"
74
+ />
75
+ </template>
76
+ </span>
77
+ <span class="mt-0.5 text-xs leading-snug text-surface-500 dark:text-surface-400">{{ cap.description }}</span>
78
+ </span>
79
+ <code
80
+ v-if="cap.rule"
81
+ class="mt-0.5 shrink-0 font-mono text-[11px] text-surface-300 transition-colors group-hover/cap:text-surface-500 dark:text-surface-600 dark:group-hover/cap:text-surface-400"
82
+ >{{ cap.rule }}</code>
83
+ </label>
84
+ </div>
85
+
86
+ <!-- Nested groups (classes, then instances) -->
87
+ <div
88
+ v-if="group.groups?.length"
89
+ class="mt-4 flex flex-col gap-6"
90
+ :class="depth === 0 ? 'pl-1' : 'pl-4'"
91
+ >
92
+ <AccessCapabilityGroup
93
+ v-for="sub in group.groups ?? []"
94
+ :key="sub.key"
95
+ :group="sub"
96
+ :depth="depth + 1"
97
+ :readonly="readonly"
98
+ @add="(rule) => emit('add', rule)"
99
+ @remove="(rule) => emit('remove', rule)"
100
+ />
101
+ </div>
102
+ </div>
103
+ </template>
104
+
105
+ <script setup lang="ts">
106
+ import { useI18n } from 'vue-i18n'
107
+
108
+ import type { Capability, CapabilityGroup } from '@core/sdk/client'
109
+
110
+ const { t } = useI18n()
111
+
112
+ const props = withDefaults(defineProps<{
113
+ group: CapabilityGroup
114
+ depth?: number
115
+ readonly?: boolean
116
+ }>(), {
117
+ depth: 0,
118
+ readonly: false,
119
+ })
120
+
121
+ const emit = defineEmits<{
122
+ add: [rule: string]
123
+ remove: [rule: string]
124
+ }>()
125
+
126
+ const onToggle = (cap: Capability, value: boolean) => {
127
+ if (props.readonly || !cap.rule) return
128
+ emit(value ? 'add' : 'remove', cap.rule)
129
+ }
130
+ </script>
@@ -1,116 +1,193 @@
1
1
  <template>
2
- <div class="flex flex-col gap-2 rounded-lg border border-surface-200 p-4 dark:border-surface-700">
3
- <span class="flex items-center gap-1 font-semibold">
4
- {{ t('role.access_rules') }}
5
- <i
6
- class="pi pi-question-circle text-surface-400"
7
- @mouseenter="(e: Event) => accessRulesHelp?.show(e)"
8
- @mouseleave="() => accessRulesHelp?.hide()"
9
- />
10
- <Popover ref="accessRulesHelp">
11
- <div class="text-sm font-normal">
12
- <p class="mb-2">
13
- {{ t('role.access_rules_help_intro') }}
14
- </p>
15
- <ul class="flex flex-col gap-1">
16
- <li class="whitespace-nowrap"><Badge
17
- value="aihub.user.agent.>"
2
+ <div class="flex flex-col gap-4">
3
+ <div class="flex flex-col gap-2 rounded-lg border border-surface-200 p-4 dark:border-surface-700">
4
+ <span class="flex items-center gap-1 font-semibold">
5
+ {{ t('role.access_rules') }}
6
+ <i
7
+ class="pi pi-question-circle text-surface-400"
8
+ @mouseenter="(e: Event) => accessRulesHelp?.show(e)"
9
+ @mouseleave="() => accessRulesHelp?.hide()"
10
+ />
11
+ <Popover ref="accessRulesHelp">
12
+ <div class="text-sm font-normal">
13
+ <p class="mb-2">
14
+ {{ t('role.access_rules_help_intro') }}
15
+ </p>
16
+ <ul class="flex flex-col gap-1">
17
+ <li class="whitespace-nowrap"><Badge
18
+ value="aihub.user.agent.>"
19
+ severity="secondary"
20
+ size="small"
21
+ /> — {{ t('role.access_rules_help_all_agents') }}</li>
22
+ <li class="whitespace-nowrap"><Badge
23
+ value="aihub.user.agent.MyAgent.*"
24
+ severity="secondary"
25
+ size="small"
26
+ /> — {{ t('role.access_rules_help_agent_instances') }}</li>
27
+ <li class="whitespace-nowrap"><Badge
28
+ value="aihub.user.service.knowledge"
29
+ severity="secondary"
30
+ size="small"
31
+ /> — {{ t('role.access_rules_help_service') }}</li>
32
+ <li class="whitespace-nowrap"><Badge
33
+ value="aihub.admin.>"
34
+ severity="secondary"
35
+ size="small"
36
+ /> — {{ t('role.access_rules_help_admin') }}</li>
37
+ </ul>
38
+ </div>
39
+ </Popover>
40
+ </span>
41
+ <DataTable
42
+ v-if="rules.length"
43
+ :value="tableRows"
44
+ data-key="id"
45
+ size="small"
46
+ >
47
+ <Column field="accessRule">
48
+ <template #body="{ data }">
49
+ <Badge
50
+ :value="data.accessRule"
18
51
  severity="secondary"
19
- size="small"
20
- /> — {{ t('role.access_rules_help_all_agents') }}</li>
21
- <li class="whitespace-nowrap"><Badge
22
- value="aihub.user.agent.MyAgent.*"
52
+ class="border border-gray-400/30"
53
+ />
54
+ </template>
55
+ </Column>
56
+ <Column class="w-24 !text-end">
57
+ <template #body="{ data }">
58
+ <Tag
59
+ v-if="isNew(data.accessRule)"
60
+ :value="t('role.is_new')"
61
+ severity="success"
62
+ />
63
+ </template>
64
+ </Column>
65
+ <Column class="w-12">
66
+ <template #body="{ data }">
67
+ <Button
68
+ icon="pi pi-times"
23
69
  severity="secondary"
70
+ variant="text"
71
+ rounded
24
72
  size="small"
25
- /> — {{ t('role.access_rules_help_agent_instances') }}</li>
26
- <li class="whitespace-nowrap"><Badge
27
- value="aihub.user.service.knowledge"
28
- severity="secondary"
29
- size="small"
30
- /> — {{ t('role.access_rules_help_service') }}</li>
31
- <li class="whitespace-nowrap"><Badge
32
- value="aihub.admin.>"
33
- severity="secondary"
34
- size="small"
35
- /> — {{ t('role.access_rules_help_admin') }}</li>
36
- </ul>
73
+ @click="remove(data.accessRule)"
74
+ />
75
+ </template>
76
+ </Column>
77
+ </DataTable>
78
+ <span
79
+ v-else
80
+ class="text-sm italic text-muted-color"
81
+ >
82
+ {{ t('role.no_access_rules') }}
83
+ </span>
84
+ <div class="flex items-center gap-2">
85
+ <Button
86
+ type="button"
87
+ icon="pi pi-th-large"
88
+ :label="t('role.presets_button')"
89
+ severity="secondary"
90
+ outlined
91
+ size="small"
92
+ @click="(e: Event) => presetsPopover?.toggle(e)"
93
+ />
94
+ <InputText
95
+ v-model="newRule"
96
+ :placeholder="t('role.add_access_role')"
97
+ size="small"
98
+ class="flex-1"
99
+ @keyup.enter="add"
100
+ />
101
+ <Button
102
+ type="button"
103
+ icon="pi pi-plus"
104
+ :label="t('role.add_button')"
105
+ size="small"
106
+ :disabled="!newRule"
107
+ @click="add"
108
+ />
109
+ </div>
110
+
111
+ <Popover ref="presetsPopover">
112
+ <div class="flex max-h-96 w-80 flex-col gap-3 overflow-y-auto">
113
+ <span class="font-semibold">{{ t('role.presets_title') }}</span>
114
+ <div
115
+ v-for="group in presetGroups"
116
+ :key="group.category"
117
+ class="flex flex-col gap-1"
118
+ >
119
+ <span class="text-xs font-medium uppercase text-muted-color">{{ group.label }}</span>
120
+ <button
121
+ v-for="preset in group.presets"
122
+ :key="preset.rule"
123
+ type="button"
124
+ class="flex flex-col items-start gap-1 rounded-md p-2 text-left hover:bg-surface-100 disabled:opacity-40 dark:hover:bg-surface-800"
125
+ :disabled="rules.includes(preset.rule)"
126
+ @click="addPreset(preset.rule)"
127
+ >
128
+ <span class="flex items-center gap-2 text-sm font-medium">
129
+ {{ preset.name }}
130
+ <i
131
+ v-if="rules.includes(preset.rule)"
132
+ class="pi pi-check text-green-500"
133
+ />
134
+ </span>
135
+ <span class="text-xs text-muted-color">{{ preset.description }}</span>
136
+ <Badge
137
+ :value="preset.rule"
138
+ severity="secondary"
139
+ size="small"
140
+ />
141
+ </button>
142
+ </div>
37
143
  </div>
38
144
  </Popover>
39
- </span>
40
- <DataTable
41
- v-if="rules.length"
42
- :value="tableRows"
43
- data-key="id"
44
- size="small"
45
- >
46
- <Column field="accessRule">
47
- <template #body="{ data }">
48
- <Badge
49
- :value="data.accessRule"
50
- severity="secondary"
51
- class="border border-gray-400/30"
52
- />
53
- </template>
54
- </Column>
55
- <Column class="w-24 !text-end">
56
- <template #body="{ data }">
57
- <Tag
58
- v-if="isNew(data.accessRule)"
59
- :value="t('role.is_new')"
60
- severity="success"
61
- />
62
- </template>
63
- </Column>
64
- <Column class="w-12">
65
- <template #body="{ data }">
66
- <Button
67
- icon="pi pi-times"
68
- severity="secondary"
69
- variant="text"
70
- rounded
71
- size="small"
72
- @click="remove(data.accessRule)"
73
- />
74
- </template>
75
- </Column>
76
- </DataTable>
77
- <span
78
- v-else
79
- class="text-sm italic text-muted-color"
80
- >
81
- {{ t('role.no_access_rules') }}
82
- </span>
83
- <div class="flex items-center gap-2">
84
- <InputText
85
- v-model="newRule"
86
- :placeholder="t('role.add_access_role')"
87
- size="small"
88
- class="flex-1"
89
- @keyup.enter="add"
90
- />
91
- <Button
92
- type="button"
93
- icon="pi pi-plus"
94
- :label="t('role.add_button')"
95
- size="small"
96
- :disabled="!newRule"
97
- @click="add"
98
- />
99
145
  </div>
146
+
147
+ <AccessCapabilities
148
+ :rules="rules"
149
+ :restrict-to-tenant="restrictToTenant"
150
+ @add="addPreset"
151
+ @remove="remove"
152
+ />
100
153
  </div>
101
154
  </template>
102
155
 
103
156
  <script setup lang="ts">
104
157
  import { useI18n } from 'vue-i18n'
105
158
 
159
+ import AccessCapabilities from './AccessCapabilities.vue'
160
+
161
+ import type { AccessPresetDto } from '@core/sdk/client'
162
+
163
+ import useAccessPresets from '@/composables/access/useAccessPresets'
164
+
106
165
  const { t } = useI18n()
107
166
 
108
167
  const accessRulesHelp = ref()
168
+ const presetsPopover = ref()
109
169
  const rules = defineModel<string[]>('rules', { required: true })
110
170
 
111
- const props = defineProps<{
171
+ const props = withDefaults(defineProps<{
112
172
  initialRules: string[]
113
- }>()
173
+ restrictToTenant?: boolean
174
+ }>(), {
175
+ restrictToTenant: true,
176
+ })
177
+
178
+ const { presets } = useAccessPresets()
179
+
180
+ const presetGroups = computed<{ category: string, label: string, presets: AccessPresetDto[] }[]>(() => {
181
+ const order = ['everything', 'agents', 'processes', 'knowledge']
182
+ const byCategory = new Map<string, AccessPresetDto[]>()
183
+ for (const preset of presets.value ?? []) {
184
+ if (!byCategory.has(preset.category)) byCategory.set(preset.category, [])
185
+ byCategory.get(preset.category)!.push(preset)
186
+ }
187
+ return [...byCategory.keys()]
188
+ .sort((a, b) => order.indexOf(a) - order.indexOf(b))
189
+ .map(category => ({ category, label: t(`role.preset_category_${category}`), presets: byCategory.get(category)! }))
190
+ })
114
191
 
115
192
  const tableRows = computed(() =>
116
193
  rules.value.map(accessRule => ({ accessRule, id: accessRule })),
@@ -122,10 +199,14 @@ const isNew = (rule: string) => !props.initialRules.includes(rule)
122
199
 
123
200
  const add = () => {
124
201
  if (!newRule.value) return
125
- rules.value.push(newRule.value)
202
+ if (!rules.value.includes(newRule.value)) rules.value.push(newRule.value)
126
203
  newRule.value = ''
127
204
  }
128
205
 
206
+ const addPreset = (rule: string) => {
207
+ if (!rules.value.includes(rule)) rules.value.push(rule)
208
+ }
209
+
129
210
  const remove = (rule: string) => {
130
211
  rules.value = rules.value.filter(r => r !== rule)
131
212
  }
@@ -0,0 +1,49 @@
1
+ import { type AccessCapabilitiesResponse, getAccessCapabilities } from '@core/sdk/client'
2
+
3
+ import type { MaybeRefOrGetter } from 'vue'
4
+
5
+ /**
6
+ * Evaluates the capability catalog (services / agents / processes) against a draft rule set.
7
+ *
8
+ * Keyed on the rules so it refetches whenever they change — ticking a capability adds its exact rule,
9
+ * which re-evaluates the whole catalog (e.g. a broad rule then locks the capabilities it covers).
10
+ */
11
+ export function useAccessCapabilities(
12
+ rules: MaybeRefOrGetter<string[]>,
13
+ restrictToTenant: MaybeRefOrGetter<boolean> = true,
14
+ // The read-only user view passes the viewed user's AIHubSysAdmin flag: a sysadmin holds admin on
15
+ // everything via the short-circuit, not via rules, so the catalog must be evaluated with it set.
16
+ isSysAdmin: MaybeRefOrGetter<boolean> = false,
17
+ ) {
18
+ const { tenantId } = useTenant()
19
+ // The tenant-ceiling editor (configure-new-tenant) runs on a route with no tenant param. With
20
+ // restrict_to_tenant=false the catalog is tenant-independent, so 'active' is a safe path fallback.
21
+ const targetTenantId = computed(() => tenantId.value ?? 'active')
22
+
23
+ const {
24
+ data: capabilities,
25
+ isPending: capabilitiesAreLoading,
26
+ } = useQuery<AccessCapabilitiesResponse>({
27
+ key: () => [
28
+ 'tenant', targetTenantId.value, 'access-capabilities',
29
+ toValue(restrictToTenant), toValue(isSysAdmin), JSON.stringify(toValue(rules)),
30
+ ],
31
+ staleTime: 0,
32
+ query: async () => {
33
+ return await getAccessCapabilities({
34
+ composable: '$fetch',
35
+ path: { tenant_id: targetTenantId.value },
36
+ body: {
37
+ access_rules: toValue(rules),
38
+ restrict_to_tenant: toValue(restrictToTenant),
39
+ is_sys_admin: toValue(isSysAdmin),
40
+ },
41
+ })
42
+ },
43
+ })
44
+
45
+ return {
46
+ capabilities,
47
+ capabilitiesAreLoading,
48
+ }
49
+ }
@@ -0,0 +1,28 @@
1
+ import { type AccessPresetDto, getAccessPresets } from '@core/sdk/client'
2
+ import { minutesToMilliseconds } from 'date-fns'
3
+
4
+ export default defineQuery(() => {
5
+ const { tenantId } = useTenant()
6
+ // Presets are tenant-independent; fall back to 'active' so the editor works on the
7
+ // configure-new-tenant route (which has no tenant param). See useAccessCapabilities.
8
+ const targetTenantId = computed(() => tenantId.value ?? 'active')
9
+
10
+ const {
11
+ data: presets,
12
+ isPending: presetsAreLoading,
13
+ } = useQuery<AccessPresetDto[]>({
14
+ key: () => ['tenant', targetTenantId.value, 'access-presets'],
15
+ staleTime: minutesToMilliseconds(30),
16
+ query: async () => {
17
+ return await getAccessPresets({
18
+ composable: '$fetch',
19
+ path: { tenant_id: targetTenantId.value },
20
+ })
21
+ },
22
+ })
23
+
24
+ return {
25
+ presets,
26
+ presetsAreLoading,
27
+ }
28
+ })
@@ -631,6 +631,23 @@ role:
631
631
  access_rules_help_agent_instances: Alle Instanzen von MyAgent
632
632
  access_rules_help_service: Knowledge-Service
633
633
  access_rules_help_admin: Admin-Zugriff auf alles
634
+ presets_button: Vorlagen
635
+ presets_title: Zugriffsvorlagen
636
+ preset_category_everything: Alles
637
+ preset_category_agents: Agenten
638
+ preset_category_processes: Prozesse
639
+ preset_category_knowledge: Wissen
640
+ capabilities_title: Was diese Regeln gewähren
641
+ capabilities_subtitle: Aktiviere eine Fähigkeit, um sie zu gewähren. Gesperrte Einträge
642
+ sind durch eine breitere Regel abgedeckt.
643
+ capabilities_readonly_title: Effektiver Zugriff
644
+ capabilities_readonly_subtitle: Was dieser Benutzer tun kann, basierend auf seinen
645
+ Rollen und innerhalb der Grenzen des Tenants.
646
+ capabilities_empty: Dieser Benutzer hat keinen Zugriff.
647
+ capability_locked: Durch eine breitere Regel gewährt — entferne diese Regel, um
648
+ dies zu ändern.
649
+ capability_readonly: Keine einzelne Regel gewährt dies allein — nutze eine Vorlage
650
+ oder eine breitere Regel.
634
651
  pattern_help_intro: 'Muster verwenden Platzhalter für Agenten:'
635
652
  pattern_help_all: Alle Agenten
636
653
  pattern_help_wildcard: Alle Instanzen von MyAgent
@@ -621,6 +621,22 @@ role:
621
621
  access_rules_help_agent_instances: All instances of MyAgent
622
622
  access_rules_help_service: Knowledge service
623
623
  access_rules_help_admin: Admin access to everything
624
+ presets_button: Presets
625
+ presets_title: Access presets
626
+ preset_category_everything: Everything
627
+ preset_category_agents: Agents
628
+ preset_category_processes: Processes
629
+ preset_category_knowledge: Knowledge
630
+ capabilities_title: What these rules grant
631
+ capabilities_subtitle: Tick a capability to grant it. Locked items are covered by
632
+ a broader rule.
633
+ capabilities_readonly_title: Effective access
634
+ capabilities_readonly_subtitle: What this user can do, based on their roles and
635
+ within the tenant's limits.
636
+ capabilities_empty: This user has no access.
637
+ capability_locked: Granted by a broader rule — remove that rule to change this.
638
+ capability_readonly: No single rule grants this on its own — use a preset or a broader
639
+ rule.
624
640
  pattern_help_intro: 'Patterns use wildcards to match agents:'
625
641
  pattern_help_all: All agents
626
642
  pattern_help_wildcard: All instances of MyAgent
@@ -629,6 +629,23 @@ role:
629
629
  access_rules_help_agent_instances: Toutes les instances de MyAgent
630
630
  access_rules_help_service: Service Knowledge
631
631
  access_rules_help_admin: Accès admin à tout
632
+ presets_button: Modèles
633
+ presets_title: Modèles d'accès
634
+ preset_category_everything: Tout
635
+ preset_category_agents: Agents
636
+ preset_category_processes: Processus
637
+ preset_category_knowledge: Connaissances
638
+ capabilities_title: Ce que ces règles accordent
639
+ capabilities_subtitle: Cochez une capacité pour l'accorder. Les éléments verrouillés
640
+ sont couverts par une règle plus large.
641
+ capabilities_readonly_title: Accès effectif
642
+ capabilities_readonly_subtitle: Ce que cet utilisateur peut faire, selon ses rôles
643
+ et dans les limites du tenant.
644
+ capabilities_empty: Cet utilisateur n'a aucun accès.
645
+ capability_locked: Accordé par une règle plus large — supprimez cette règle pour
646
+ changer ceci.
647
+ capability_readonly: Aucune règle unique ne l'accorde — utilisez un modèle ou une
648
+ règle plus large.
632
649
  pattern_help_intro: 'Les modèles utilisent des jokers pour les agents :'
633
650
  pattern_help_all: Tous les agents
634
651
  pattern_help_wildcard: Toutes les instances de MyAgent
@@ -626,6 +626,23 @@ role:
626
626
  access_rules_help_agent_instances: Tutte le istanze di MyAgent
627
627
  access_rules_help_service: Servizio Knowledge
628
628
  access_rules_help_admin: Accesso admin a tutto
629
+ presets_button: Modelli
630
+ presets_title: Modelli di accesso
631
+ preset_category_everything: Tutto
632
+ preset_category_agents: Agenti
633
+ preset_category_processes: Processi
634
+ preset_category_knowledge: Conoscenza
635
+ capabilities_title: Cosa concedono queste regole
636
+ capabilities_subtitle: Seleziona una capacità per concederla. Gli elementi bloccati
637
+ sono coperti da una regola più ampia.
638
+ capabilities_readonly_title: Accesso effettivo
639
+ capabilities_readonly_subtitle: Cosa può fare questo utente, in base ai suoi ruoli
640
+ e nei limiti del tenant.
641
+ capabilities_empty: Questo utente non ha accesso.
642
+ capability_locked: Concesso da una regola più ampia — rimuovi quella regola per
643
+ cambiare questo.
644
+ capability_readonly: Nessuna singola regola lo concede — usa un modello o una regola
645
+ più ampia.
629
646
  pattern_help_intro: 'I modelli usano caratteri jolly per gli agenti:'
630
647
  pattern_help_all: Tutti gli agenti
631
648
  pattern_help_wildcard: Tutte le istanze di MyAgent