@agenticmail/enterprise 0.5.291 → 0.5.293

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.
@@ -3,17 +3,232 @@ import { I } from '../components/icons.js';
3
3
  import { Modal } from '../components/modal.js';
4
4
  import { HelpButton } from '../components/help-button.js';
5
5
 
6
+ // ─── Permission Editor Component ───────────────────
7
+
8
+ function PermissionEditor({ userId, userName, currentPerms, pageRegistry, onSave, onClose }) {
9
+ // Deep clone perms
10
+ var [grants, setGrants] = useState(function() {
11
+ if (currentPerms === '*') {
12
+ // Start with all pages selected (all tabs)
13
+ var all = {};
14
+ Object.keys(pageRegistry).forEach(function(pid) { all[pid] = true; });
15
+ return all;
16
+ }
17
+ // Clone existing
18
+ var c = {};
19
+ Object.keys(currentPerms || {}).forEach(function(pid) {
20
+ var g = currentPerms[pid];
21
+ c[pid] = g === true ? true : (Array.isArray(g) ? g.slice() : true);
22
+ });
23
+ return c;
24
+ });
25
+ var [fullAccess, setFullAccess] = useState(currentPerms === '*');
26
+ var [saving, setSaving] = useState(false);
27
+ var [expandedPage, setExpandedPage] = useState(null);
28
+
29
+ var sections = { overview: [], management: [], administration: [] };
30
+ Object.keys(pageRegistry).forEach(function(pid) {
31
+ var page = pageRegistry[pid];
32
+ if (sections[page.section]) sections[page.section].push(pid);
33
+ });
34
+
35
+ var togglePage = function(pid) {
36
+ setGrants(function(g) {
37
+ var next = Object.assign({}, g);
38
+ if (next[pid]) {
39
+ delete next[pid];
40
+ if (expandedPage === pid) setExpandedPage(null);
41
+ } else {
42
+ next[pid] = true;
43
+ }
44
+ return next;
45
+ });
46
+ };
47
+
48
+ var toggleTab = function(pid, tabId) {
49
+ setGrants(function(g) {
50
+ var next = Object.assign({}, g);
51
+ var current = next[pid];
52
+ var allTabs = Object.keys(pageRegistry[pid].tabs || {});
53
+
54
+ if (current === true) {
55
+ // Was all tabs — remove this one
56
+ var remaining = allTabs.filter(function(t) { return t !== tabId; });
57
+ next[pid] = remaining.length > 0 ? remaining : true;
58
+ } else if (Array.isArray(current)) {
59
+ var idx = current.indexOf(tabId);
60
+ if (idx >= 0) {
61
+ var arr = current.filter(function(t) { return t !== tabId; });
62
+ if (arr.length === 0) delete next[pid]; // no tabs = remove page
63
+ else next[pid] = arr;
64
+ } else {
65
+ var newArr = current.concat([tabId]);
66
+ if (newArr.length === allTabs.length) next[pid] = true; // all tabs = page access
67
+ else next[pid] = newArr;
68
+ }
69
+ }
70
+ return next;
71
+ });
72
+ };
73
+
74
+ var isPageChecked = function(pid) { return !!grants[pid]; };
75
+ var isTabChecked = function(pid, tabId) {
76
+ var g = grants[pid];
77
+ if (!g) return false;
78
+ if (g === true) return true;
79
+ return Array.isArray(g) && g.indexOf(tabId) >= 0;
80
+ };
81
+
82
+ var toggleFullAccess = function() {
83
+ var newVal = !fullAccess;
84
+ setFullAccess(newVal);
85
+ if (newVal) {
86
+ var all = {};
87
+ Object.keys(pageRegistry).forEach(function(pid) { all[pid] = true; });
88
+ setGrants(all);
89
+ } else {
90
+ setGrants({});
91
+ }
92
+ };
93
+
94
+ var selectAll = function() {
95
+ var all = {};
96
+ Object.keys(pageRegistry).forEach(function(pid) { all[pid] = true; });
97
+ setGrants(all);
98
+ };
99
+ var selectNone = function() { setGrants({}); };
100
+
101
+ var doSave = async function() {
102
+ setSaving(true);
103
+ try {
104
+ var permsToSave = fullAccess ? '*' : grants;
105
+ await onSave(permsToSave);
106
+ } catch(e) { /* handled by parent */ }
107
+ setSaving(false);
108
+ };
109
+
110
+ var sectionLabels = { overview: 'Overview', management: 'Management', administration: 'Administration' };
111
+
112
+ var _cs = { display: 'flex', alignItems: 'center', gap: 8, padding: '8px 12px', borderRadius: 6, cursor: 'pointer', fontSize: 13, transition: 'background 0.15s' };
113
+ var _csHover = Object.assign({}, _cs, { background: 'var(--bg-tertiary)' });
114
+ var _tabRow = { display: 'flex', alignItems: 'center', gap: 8, padding: '4px 12px 4px 40px', fontSize: 12, color: 'var(--text-secondary)', cursor: 'pointer' };
115
+ var _checkbox = { width: 16, height: 16, accentColor: 'var(--primary)', cursor: 'pointer' };
116
+ var _sectionTitle = { fontSize: 11, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.05em', color: 'var(--text-muted)', padding: '16px 12px 4px', marginTop: 4 };
117
+
118
+ return h(Modal, {
119
+ title: 'Edit Permissions — ' + (userName || 'User'),
120
+ onClose: onClose,
121
+ width: 560,
122
+ footer: h(Fragment, null,
123
+ h('button', { className: 'btn btn-secondary', onClick: onClose }, 'Cancel'),
124
+ h('button', { className: 'btn btn-primary', onClick: doSave, disabled: saving }, saving ? 'Saving...' : 'Save Permissions')
125
+ )
126
+ },
127
+ // Full access toggle
128
+ h('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '8px 12px', marginBottom: 12, background: fullAccess ? 'var(--success-soft, rgba(21,128,61,0.1))' : 'var(--bg-tertiary)', borderRadius: 8, border: '1px solid ' + (fullAccess ? 'var(--success, #15803d)' : 'var(--border)') } },
129
+ h('div', null,
130
+ h('strong', { style: { fontSize: 13 } }, 'Full Access'),
131
+ h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginTop: 2 } }, 'Owner and Admin roles always have full access')
132
+ ),
133
+ h('input', { type: 'checkbox', checked: fullAccess, onChange: toggleFullAccess, style: Object.assign({}, _checkbox, { width: 20, height: 20 }) })
134
+ ),
135
+
136
+ // Quick actions
137
+ !fullAccess && h('div', { style: { display: 'flex', gap: 8, marginBottom: 12 } },
138
+ h('button', { className: 'btn btn-ghost btn-sm', onClick: selectAll, style: { fontSize: 11 } }, 'Select All'),
139
+ h('button', { className: 'btn btn-ghost btn-sm', onClick: selectNone, style: { fontSize: 11 } }, 'Select None')
140
+ ),
141
+
142
+ // Page/tab list grouped by section
143
+ !fullAccess && h('div', { style: { maxHeight: 400, overflowY: 'auto', border: '1px solid var(--border)', borderRadius: 8 } },
144
+ Object.keys(sections).map(function(sectionKey) {
145
+ var pageIds = sections[sectionKey];
146
+ if (pageIds.length === 0) return null;
147
+ return h(Fragment, { key: sectionKey },
148
+ h('div', { style: _sectionTitle }, sectionLabels[sectionKey]),
149
+ pageIds.map(function(pid) {
150
+ var page = pageRegistry[pid];
151
+ var hasTabs = page.tabs && Object.keys(page.tabs).length > 0;
152
+ var isExpanded = expandedPage === pid;
153
+ var checked = isPageChecked(pid);
154
+ var tabCount = hasTabs ? Object.keys(page.tabs).length : 0;
155
+ var checkedTabCount = 0;
156
+ if (hasTabs && checked) {
157
+ if (grants[pid] === true) checkedTabCount = tabCount;
158
+ else if (Array.isArray(grants[pid])) checkedTabCount = grants[pid].length;
159
+ }
160
+
161
+ return h(Fragment, { key: pid },
162
+ h('div', {
163
+ style: Object.assign({}, _cs, checked ? { background: 'var(--bg-tertiary)' } : {}),
164
+ onClick: function(e) {
165
+ // Don't toggle page when clicking the expand arrow
166
+ if (e.target.tagName === 'svg' || e.target.tagName === 'path' || e.target.closest?.('[data-expand]')) return;
167
+ togglePage(pid);
168
+ }
169
+ },
170
+ h('input', { type: 'checkbox', checked: checked, readOnly: true, style: _checkbox }),
171
+ h('div', { style: { flex: 1 } },
172
+ h('div', { style: { fontWeight: 500 } }, page.label),
173
+ page.description && h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginTop: 1 } }, page.description)
174
+ ),
175
+ hasTabs && h('div', { style: { display: 'flex', alignItems: 'center', gap: 6 } },
176
+ checked && h('span', { style: { fontSize: 10, color: 'var(--text-muted)', whiteSpace: 'nowrap' } },
177
+ checkedTabCount + '/' + tabCount + ' tabs'
178
+ ),
179
+ h('button', {
180
+ 'data-expand': true,
181
+ className: 'btn btn-ghost btn-sm',
182
+ style: { padding: '2px 4px', minWidth: 0 },
183
+ onClick: function(e) { e.stopPropagation(); setExpandedPage(isExpanded ? null : pid); }
184
+ }, isExpanded ? I.chevronDown() : I.chevronRight())
185
+ )
186
+ ),
187
+ // Expanded tabs
188
+ hasTabs && isExpanded && checked && Object.keys(page.tabs).map(function(tabId) {
189
+ return h('div', {
190
+ key: tabId,
191
+ style: _tabRow,
192
+ onClick: function() { toggleTab(pid, tabId); }
193
+ },
194
+ h('input', { type: 'checkbox', checked: isTabChecked(pid, tabId), readOnly: true, style: _checkbox }),
195
+ h('span', null, page.tabs[tabId])
196
+ );
197
+ })
198
+ );
199
+ })
200
+ );
201
+ })
202
+ ),
203
+
204
+ // Summary
205
+ h('div', { style: { marginTop: 12, padding: 8, background: 'var(--bg-tertiary)', borderRadius: 6, fontSize: 11, color: 'var(--text-muted)' } },
206
+ fullAccess
207
+ ? 'This user has full access to all pages and tabs.'
208
+ : 'Access to ' + Object.keys(grants).length + ' of ' + Object.keys(pageRegistry).length + ' pages.'
209
+ )
210
+ );
211
+ }
212
+
213
+ // ─── Users Page ────────────────────────────────────
214
+
6
215
  export function UsersPage() {
7
216
  var { toast } = useApp();
8
217
  var [users, setUsers] = useState([]);
9
218
  var [creating, setCreating] = useState(false);
10
219
  var [form, setForm] = useState({ email: '', password: '', name: '', role: 'viewer' });
11
- var [resetTarget, setResetTarget] = useState(null); // user object
220
+ var [resetTarget, setResetTarget] = useState(null);
12
221
  var [newPassword, setNewPassword] = useState('');
13
222
  var [resetting, setResetting] = useState(false);
223
+ var [permTarget, setPermTarget] = useState(null); // user object for permission editing
224
+ var [permGrants, setPermGrants] = useState('*'); // current permissions for target
225
+ var [pageRegistry, setPageRegistry] = useState(null); // page/tab registry from backend
14
226
 
15
227
  var load = function() { apiCall('/users').then(function(d) { setUsers(d.users || d || []); }).catch(function() {}); };
16
- useEffect(function() { load(); }, []);
228
+ useEffect(function() {
229
+ load();
230
+ apiCall('/page-registry').then(function(d) { setPageRegistry(d); }).catch(function() {});
231
+ }, []);
17
232
 
18
233
  var create = async function() {
19
234
  try {
@@ -50,6 +265,23 @@ export function UsersPage() {
50
265
  } catch (e) { toast(e.message, 'error'); }
51
266
  };
52
267
 
268
+ var openPermissions = async function(user) {
269
+ try {
270
+ var d = await apiCall('/users/' + user.id + '/permissions');
271
+ setPermGrants(d.permissions || '*');
272
+ setPermTarget(user);
273
+ } catch (e) { toast('Failed to load permissions', 'error'); }
274
+ };
275
+
276
+ var savePermissions = async function(newPerms) {
277
+ try {
278
+ await apiCall('/users/' + permTarget.id + '/permissions', { method: 'PUT', body: JSON.stringify({ permissions: newPerms }) });
279
+ toast('Permissions updated for ' + (permTarget.name || permTarget.email), 'success');
280
+ setPermTarget(null);
281
+ load();
282
+ } catch (e) { toast(e.message, 'error'); throw e; }
283
+ };
284
+
53
285
  var generatePassword = function() {
54
286
  var chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789!@#$%';
55
287
  var pw = '';
@@ -57,20 +289,36 @@ export function UsersPage() {
57
289
  setNewPassword(pw);
58
290
  };
59
291
 
292
+ // Permission badge for display
293
+ var permBadge = function(user) {
294
+ if (user.role === 'owner' || user.role === 'admin') {
295
+ return h('span', { className: 'badge badge-success', style: { fontSize: 10 } }, 'Full');
296
+ }
297
+ var p = user.permissions;
298
+ if (!p || p === '*' || p === '"*"') return h('span', { className: 'badge badge-success', style: { fontSize: 10 } }, 'Full');
299
+ try {
300
+ var parsed = typeof p === 'string' ? JSON.parse(p) : p;
301
+ if (parsed === '*') return h('span', { className: 'badge badge-success', style: { fontSize: 10 } }, 'Full');
302
+ var count = Object.keys(parsed).length;
303
+ var total = pageRegistry ? Object.keys(pageRegistry).length : '?';
304
+ return h('span', { className: 'badge badge-warning', style: { fontSize: 10 } }, count + '/' + total + ' pages');
305
+ } catch { return h('span', { className: 'badge badge-neutral', style: { fontSize: 10 } }, 'Custom'); }
306
+ };
307
+
60
308
  return h(Fragment, null,
61
309
  h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } },
62
310
  h('div', null, h('h1', { style: { fontSize: 20, fontWeight: 700, display: 'flex', alignItems: 'center' } }, 'Users', h(HelpButton, { label: 'Users' },
63
311
  h('p', null, 'Manage dashboard users who can access and administer the AgenticMail Enterprise console. Each user has a role that controls what they can see and do.'),
64
312
  h('h4', { style: { marginTop: 16, marginBottom: 8, fontSize: 14 } }, 'Roles'),
65
313
  h('ul', { style: { paddingLeft: 20, margin: '4px 0 8px' } },
66
- h('li', null, h('strong', null, 'Owner'), ' — Full access including billing, user management, and destructive actions.'),
67
- h('li', null, h('strong', null, 'Admin'), ' — Can manage agents, policies, and most settings. Cannot manage billing.'),
68
- h('li', null, h('strong', null, 'Member'), ' — Can view dashboards and interact with agents. Limited config access.'),
69
- h('li', null, h('strong', null, 'Viewer'), ' — Read-only access to dashboards and reports.')
314
+ h('li', null, h('strong', null, 'Owner'), ' — Full access to everything. Cannot be restricted.'),
315
+ h('li', null, h('strong', null, 'Admin'), ' — Full access to everything. Cannot be restricted.'),
316
+ h('li', null, h('strong', null, 'Member'), ' — Access based on page permissions. Set via the shield icon.'),
317
+ h('li', null, h('strong', null, 'Viewer'), ' — Read-only. Access based on page permissions.')
70
318
  ),
71
- h('h4', { style: { marginTop: 16, marginBottom: 8, fontSize: 14 } }, '2FA (Two-Factor Authentication)'),
72
- h('p', null, 'Users can enable TOTP-based 2FA for extra security. The 2FA column shows whether it\'s active.'),
73
- h('div', { style: { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 } }, h('strong', null, 'Tip: '), 'Use the lock icon to reset a user\'s password. The "Generate" button creates a secure random password.')
319
+ h('h4', { style: { marginTop: 16, marginBottom: 8, fontSize: 14 } }, 'Page Permissions'),
320
+ h('p', null, 'Click the shield icon on a Member or Viewer to control which pages and tabs they can see. Pages with tabs (like Agents) allow tab-level control.'),
321
+ h('div', { style: { marginTop: 12, padding: 12, background: 'var(--bg-secondary, #1e293b)', borderRadius: 'var(--radius, 8px)', fontSize: 13 } }, h('strong', null, 'Tip: '), 'Owner and Admin users always have full access permissions only apply to Member and Viewer roles.')
74
322
  )), h('p', { style: { color: 'var(--text-muted)', fontSize: 13 } }, 'Manage team members and their access')),
75
323
  h('button', { className: 'btn btn-primary', onClick: function() { setCreating(true); } }, I.plus(), ' Add User')
76
324
  ),
@@ -80,7 +328,10 @@ export function UsersPage() {
80
328
  h('div', { className: 'form-group' }, h('label', { className: 'form-label' }, 'Name'), h('input', { className: 'input', value: form.name, onChange: function(e) { setForm(function(f) { return Object.assign({}, f, { name: e.target.value }); }); } })),
81
329
  h('div', { className: 'form-group' }, h('label', { className: 'form-label' }, 'Email *'), h('input', { className: 'input', type: 'email', value: form.email, onChange: function(e) { setForm(function(f) { return Object.assign({}, f, { email: e.target.value }); }); } })),
82
330
  h('div', { className: 'form-group' }, h('label', { className: 'form-label' }, 'Password *'), h('input', { className: 'input', type: 'password', value: form.password, onChange: function(e) { setForm(function(f) { return Object.assign({}, f, { password: e.target.value }); }); } })),
83
- h('div', { className: 'form-group' }, h('label', { className: 'form-label' }, 'Role'), h('select', { className: 'input', value: form.role, onChange: function(e) { setForm(function(f) { return Object.assign({}, f, { role: e.target.value }); }); } }, h('option', { value: 'viewer' }, 'Viewer'), h('option', { value: 'member' }, 'Member'), h('option', { value: 'admin' }, 'Admin'), h('option', { value: 'owner' }, 'Owner')))
331
+ h('div', { className: 'form-group' }, h('label', { className: 'form-label' }, 'Role'), h('select', { className: 'input', value: form.role, onChange: function(e) { setForm(function(f) { return Object.assign({}, f, { role: e.target.value }); }); } }, h('option', { value: 'viewer' }, 'Viewer'), h('option', { value: 'member' }, 'Member'), h('option', { value: 'admin' }, 'Admin'), h('option', { value: 'owner' }, 'Owner'))),
332
+ (form.role === 'member' || form.role === 'viewer') && h('div', { style: { marginTop: 8, padding: 10, background: 'var(--info-soft)', borderRadius: 'var(--radius)', fontSize: 12, color: 'var(--info)' } },
333
+ 'After creating this user, click the shield icon to set their page permissions. By default, new Member/Viewer users have full access.'
334
+ )
84
335
  ),
85
336
 
86
337
  // Reset password modal
@@ -93,7 +344,7 @@ export function UsersPage() {
93
344
  )
94
345
  },
95
346
  h('div', { style: { marginBottom: 16 } },
96
- h('p', { style: { fontSize: 13, color: 'var(--text-secondary)' } }, 'Set a new password for ', h('strong', null, resetTarget.name || resetTarget.email), '. The user will need to use this password on their next login.'),
347
+ h('p', { style: { fontSize: 13, color: 'var(--text-secondary)' } }, 'Set a new password for ', h('strong', null, resetTarget.name || resetTarget.email), '.'),
97
348
  resetTarget.totpEnabled && h('div', { style: { marginTop: 8, padding: 8, background: 'var(--info-soft)', borderRadius: 'var(--radius)', fontSize: 12, color: 'var(--info)' } }, 'This user has 2FA enabled. Password reset will not affect their 2FA setup.')
98
349
  ),
99
350
  h('div', { className: 'form-group' },
@@ -104,25 +355,43 @@ export function UsersPage() {
104
355
  )
105
356
  ),
106
357
  newPassword && h('div', { style: { marginTop: 8, padding: 8, background: 'var(--bg-tertiary)', borderRadius: 'var(--radius)', fontSize: 12, color: 'var(--text-muted)' } },
107
- 'Make sure to share this password securely with the user. It will not be shown again.'
358
+ 'Make sure to share this password securely with the user.'
108
359
  )
109
360
  ),
110
361
 
362
+ // Permission editor modal
363
+ permTarget && pageRegistry && h(PermissionEditor, {
364
+ userId: permTarget.id,
365
+ userName: permTarget.name || permTarget.email,
366
+ currentPerms: permGrants,
367
+ pageRegistry: pageRegistry,
368
+ onSave: savePermissions,
369
+ onClose: function() { setPermTarget(null); }
370
+ }),
371
+
111
372
  // Users table
112
373
  h('div', { className: 'card' },
113
374
  h('div', { className: 'card-body-flush' },
114
375
  users.length === 0 ? h('div', { style: { padding: 24, textAlign: 'center', color: 'var(--text-muted)' } }, 'No users')
115
376
  : h('table', null,
116
- h('thead', null, h('tr', null, h('th', null, 'Name'), h('th', null, 'Email'), h('th', null, 'Role'), h('th', null, '2FA'), h('th', null, 'Created'), h('th', { style: { width: 160 } }, 'Actions'))),
377
+ h('thead', null, h('tr', null, h('th', null, 'Name'), h('th', null, 'Email'), h('th', null, 'Role'), h('th', null, 'Access'), h('th', null, '2FA'), h('th', null, 'Created'), h('th', { style: { width: 180 } }, 'Actions'))),
117
378
  h('tbody', null, users.map(function(u) {
379
+ var isRestricted = u.role === 'member' || u.role === 'viewer';
118
380
  return h('tr', { key: u.id },
119
381
  h('td', null, h('strong', null, u.name || '-')),
120
382
  h('td', null, h('span', { style: { fontFamily: 'var(--font-mono)', fontSize: 12 } }, u.email)),
121
383
  h('td', null, h('span', { className: 'badge badge-' + (u.role === 'owner' ? 'warning' : u.role === 'admin' ? 'primary' : 'neutral') }, u.role)),
384
+ h('td', null, permBadge(u)),
122
385
  h('td', null, u.totpEnabled ? h('span', { className: 'badge badge-success' }, 'On') : h('span', { className: 'badge badge-neutral' }, 'Off')),
123
386
  h('td', { style: { fontSize: 12, color: 'var(--text-muted)' } }, u.createdAt ? new Date(u.createdAt).toLocaleDateString() : '-'),
124
387
  h('td', null,
125
388
  h('div', { style: { display: 'flex', gap: 4 } },
389
+ h('button', {
390
+ className: 'btn btn-ghost btn-sm',
391
+ title: isRestricted ? 'Edit Permissions' : 'Permissions (Owner/Admin have full access)',
392
+ onClick: function() { openPermissions(u); },
393
+ style: !isRestricted ? { opacity: 0.4 } : {}
394
+ }, I.shield()),
126
395
  h('button', { className: 'btn btn-ghost btn-sm', title: 'Reset Password', onClick: function() { setResetTarget(u); setNewPassword(''); } }, I.lock()),
127
396
  h('button', { className: 'btn btn-ghost btn-sm', title: 'Delete User', onClick: function() { deleteUser(u); }, style: { color: 'var(--danger)' } }, I.trash())
128
397
  )
@@ -0,0 +1,9 @@
1
+ import {
2
+ createAdapter,
3
+ getSupportedDatabases
4
+ } from "./chunk-NPR5DIPX.js";
5
+ import "./chunk-KFQGP6VL.js";
6
+ export {
7
+ createAdapter,
8
+ getSupportedDatabases
9
+ };
package/dist/index.js CHANGED
@@ -1,3 +1,7 @@
1
+ import {
2
+ provision,
3
+ runSetupWizard
4
+ } from "./chunk-I3AODI5Z.js";
1
5
  import {
2
6
  AgenticMailManager,
3
7
  GoogleEmailProvider,
@@ -10,10 +14,6 @@ import {
10
14
  generateEnvFile,
11
15
  generateFlyToml
12
16
  } from "./chunk-CMJJLSUB.js";
13
- import {
14
- provision,
15
- runSetupWizard
16
- } from "./chunk-S3WOS4UN.js";
17
17
  import {
18
18
  AgentRuntime,
19
19
  EmailChannel,
@@ -28,7 +28,7 @@ import {
28
28
  executeTool,
29
29
  runAgentLoop,
30
30
  toolsToDefinitions
31
- } from "./chunk-2YOTK5B7.js";
31
+ } from "./chunk-67AD7SKP.js";
32
32
  import {
33
33
  ValidationError,
34
34
  auditLogger,
@@ -42,7 +42,7 @@ import {
42
42
  requireRole,
43
43
  securityHeaders,
44
44
  validate
45
- } from "./chunk-PG5CNF22.js";
45
+ } from "./chunk-64SXJMJI.js";
46
46
  import "./chunk-OF4MUWWS.js";
47
47
  import {
48
48
  PROVIDER_REGISTRY,
@@ -50,6 +50,16 @@ import {
50
50
  resolveApiKeyForProvider,
51
51
  resolveProvider
52
52
  } from "./chunk-UF3ZJMJO.js";
53
+ import {
54
+ ENGINE_TABLES,
55
+ ENGINE_TABLES_POSTGRES,
56
+ EngineDatabase,
57
+ MIGRATIONS,
58
+ MIGRATIONS_TABLE,
59
+ MIGRATIONS_TABLE_POSTGRES,
60
+ sqliteToMySQL,
61
+ sqliteToPostgres
62
+ } from "./chunk-KKTVGBSC.js";
53
63
  import {
54
64
  ActionJournal,
55
65
  ActivityTracker,
@@ -70,16 +80,6 @@ import {
70
80
  init_guardrails
71
81
  } from "./chunk-LOBBAW6U.js";
72
82
  import "./chunk-3OC6RH7W.js";
73
- import {
74
- ENGINE_TABLES,
75
- ENGINE_TABLES_POSTGRES,
76
- EngineDatabase,
77
- MIGRATIONS,
78
- MIGRATIONS_TABLE,
79
- MIGRATIONS_TABLE_POSTGRES,
80
- sqliteToMySQL,
81
- sqliteToPostgres
82
- } from "./chunk-KKTVGBSC.js";
83
83
  import {
84
84
  BUILTIN_SKILLS,
85
85
  PRESET_PROFILES,
@@ -113,7 +113,7 @@ import {
113
113
  import {
114
114
  createAdapter,
115
115
  getSupportedDatabases
116
- } from "./chunk-ULRBF2T7.js";
116
+ } from "./chunk-NPR5DIPX.js";
117
117
  import {
118
118
  AGENTICMAIL_TOOLS,
119
119
  ALL_TOOLS,
@@ -0,0 +1,178 @@
1
+ import "./chunk-KFQGP6VL.js";
2
+
3
+ // src/admin/page-registry.ts
4
+ var PAGE_REGISTRY = {
5
+ // ─── Overview ────────────────────────────────────
6
+ dashboard: {
7
+ label: "Dashboard",
8
+ section: "overview",
9
+ description: "Main dashboard with key metrics and activity feed"
10
+ },
11
+ // ─── Management ──────────────────────────────────
12
+ agents: {
13
+ label: "Agents",
14
+ section: "management",
15
+ description: "View and manage AI agents",
16
+ tabs: {
17
+ overview: "Overview",
18
+ personal: "Personal Details",
19
+ email: "Email",
20
+ whatsapp: "WhatsApp",
21
+ channels: "Channels",
22
+ configuration: "Configuration",
23
+ manager: "Manager",
24
+ tools: "Tools",
25
+ skills: "Skills",
26
+ permissions: "Permissions",
27
+ activity: "Activity",
28
+ communication: "Communication",
29
+ workforce: "Workforce",
30
+ memory: "Memory",
31
+ guardrails: "Guardrails",
32
+ autonomy: "Autonomy",
33
+ budget: "Budget",
34
+ security: "Security",
35
+ "tool-security": "Tool Security",
36
+ deployment: "Deployment"
37
+ }
38
+ },
39
+ skills: {
40
+ label: "Skills",
41
+ section: "management",
42
+ description: "Manage agent skill packs"
43
+ },
44
+ "community-skills": {
45
+ label: "Community Skills",
46
+ section: "management",
47
+ description: "Browse and install community skill marketplace"
48
+ },
49
+ "skill-connections": {
50
+ label: "Integrations & MCP",
51
+ section: "management",
52
+ description: "MCP servers, built-in integrations, and community skills"
53
+ },
54
+ "database-access": {
55
+ label: "Database Access",
56
+ section: "management",
57
+ description: "Manage database connections and agent access",
58
+ tabs: {
59
+ connections: "Connections",
60
+ access: "Agent Access",
61
+ audit: "Audit Log"
62
+ }
63
+ },
64
+ knowledge: {
65
+ label: "Knowledge Bases",
66
+ section: "management",
67
+ description: "Manage knowledge base documents and collections"
68
+ },
69
+ "knowledge-contributions": {
70
+ label: "Knowledge Hub",
71
+ section: "management",
72
+ description: "Agent contributions to shared knowledge"
73
+ },
74
+ approvals: {
75
+ label: "Approvals",
76
+ section: "management",
77
+ description: "Review and approve pending agent actions"
78
+ },
79
+ "org-chart": {
80
+ label: "Org Chart",
81
+ section: "management",
82
+ description: "Visual agent hierarchy and reporting structure"
83
+ },
84
+ "task-pipeline": {
85
+ label: "Task Pipeline",
86
+ section: "management",
87
+ description: "Track task lifecycle from creation to completion"
88
+ },
89
+ workforce: {
90
+ label: "Workforce",
91
+ section: "management",
92
+ description: "Agent scheduling, workload, and availability"
93
+ },
94
+ messages: {
95
+ label: "Messages",
96
+ section: "management",
97
+ description: "Inter-agent and external message logs"
98
+ },
99
+ guardrails: {
100
+ label: "Guardrails",
101
+ section: "management",
102
+ description: "Global safety policies and content filters"
103
+ },
104
+ journal: {
105
+ label: "Journal",
106
+ section: "management",
107
+ description: "System event journal and decision log"
108
+ },
109
+ // ─── Administration ──────────────────────────────
110
+ dlp: {
111
+ label: "DLP",
112
+ section: "administration",
113
+ description: "Data loss prevention policies and alerts"
114
+ },
115
+ compliance: {
116
+ label: "Compliance",
117
+ section: "administration",
118
+ description: "Regulatory compliance settings and reports"
119
+ },
120
+ "domain-status": {
121
+ label: "Domain",
122
+ section: "administration",
123
+ description: "Domain configuration and deployment status"
124
+ },
125
+ users: {
126
+ label: "Users",
127
+ section: "administration",
128
+ description: "Manage dashboard users, roles, and permissions"
129
+ },
130
+ vault: {
131
+ label: "Vault",
132
+ section: "administration",
133
+ description: "Encrypted credential storage"
134
+ },
135
+ audit: {
136
+ label: "Audit Log",
137
+ section: "administration",
138
+ description: "Full audit trail of all system actions"
139
+ },
140
+ settings: {
141
+ label: "Settings",
142
+ section: "administration",
143
+ description: "Global platform configuration and branding"
144
+ }
145
+ };
146
+ function getAllPageIds() {
147
+ return Object.keys(PAGE_REGISTRY);
148
+ }
149
+ function getPageTabs(pageId) {
150
+ const page = PAGE_REGISTRY[pageId];
151
+ return page?.tabs ? Object.keys(page.tabs) : [];
152
+ }
153
+ function hasPageAccess(grants, pageId) {
154
+ if (grants === "*") return true;
155
+ return pageId in grants;
156
+ }
157
+ function hasTabAccess(grants, pageId, tabId) {
158
+ if (grants === "*") return true;
159
+ const pageGrant = grants[pageId];
160
+ if (!pageGrant) return false;
161
+ if (pageGrant === true) return true;
162
+ return pageGrant.includes(tabId);
163
+ }
164
+ function getAccessibleTabs(grants, pageId) {
165
+ if (grants === "*") return "all";
166
+ const pageGrant = grants[pageId];
167
+ if (!pageGrant) return [];
168
+ if (pageGrant === true) return "all";
169
+ return pageGrant;
170
+ }
171
+ export {
172
+ PAGE_REGISTRY,
173
+ getAccessibleTabs,
174
+ getAllPageIds,
175
+ getPageTabs,
176
+ hasPageAccess,
177
+ hasTabAccess
178
+ };