@openmdm/core 0.2.0 → 0.4.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.
package/src/types.ts CHANGED
@@ -28,6 +28,7 @@ export interface Device {
28
28
 
29
29
  // MDM State
30
30
  policyId?: string | null;
31
+ agentVersion?: string | null; // MDM agent version installed on device
31
32
  lastHeartbeat?: Date | null;
32
33
  lastSync?: Date | null;
33
34
 
@@ -80,6 +81,7 @@ export interface UpdateDeviceInput {
80
81
  externalId?: string | null;
81
82
  status?: DeviceStatus;
82
83
  policyId?: string | null;
84
+ agentVersion?: string | null;
83
85
  model?: string;
84
86
  manufacturer?: string;
85
87
  osVersion?: string;
@@ -374,6 +376,7 @@ export type CommandType =
374
376
  | 'setTimeZone' // Set device timezone
375
377
  | 'enableAdb' // Enable/disable ADB debugging
376
378
  | 'rollbackApp' // Rollback to previous app version
379
+ | 'updateAgent' // Update MDM agent to a new version
377
380
  | 'custom';
378
381
 
379
382
  export type CommandStatus =
@@ -660,6 +663,37 @@ export interface MDMConfig {
660
663
  onHeartbeat?: (device: Device, heartbeat: Heartbeat) => Promise<void>;
661
664
  onCommand?: (command: Command) => Promise<void>;
662
665
  onEvent?: (event: MDMEvent) => Promise<void>;
666
+
667
+ // Enterprise features
668
+ /** Multi-tenancy configuration */
669
+ multiTenancy?: {
670
+ enabled: boolean;
671
+ defaultTenantId?: string;
672
+ tenantResolver?: (context: unknown) => Promise<string | null>;
673
+ };
674
+
675
+ /** Authorization (RBAC) configuration */
676
+ authorization?: {
677
+ enabled: boolean;
678
+ defaultRole?: string;
679
+ };
680
+
681
+ /** Audit logging configuration */
682
+ audit?: {
683
+ enabled: boolean;
684
+ retentionDays?: number;
685
+ };
686
+
687
+ /** Scheduling configuration */
688
+ scheduling?: {
689
+ enabled: boolean;
690
+ timezone?: string;
691
+ };
692
+
693
+ /** Plugin storage configuration */
694
+ pluginStorage?: {
695
+ adapter: 'database' | 'memory';
696
+ };
663
697
  }
664
698
 
665
699
  export interface StorageConfig {
@@ -834,6 +868,82 @@ export interface DatabaseAdapter {
834
868
  updateRollback?(id: string, data: Partial<AppRollback>): Promise<AppRollback>;
835
869
  listRollbacks?(filter?: { deviceId?: string; packageName?: string }): Promise<AppRollback[]>;
836
870
 
871
+ // Group Hierarchy (optional)
872
+ getGroupChildren?(parentId: string | null): Promise<Group[]>;
873
+ getGroupAncestors?(groupId: string): Promise<Group[]>;
874
+ getGroupDescendants?(groupId: string): Promise<Group[]>;
875
+ getGroupTree?(rootId?: string): Promise<GroupTreeNode[]>;
876
+ getGroupEffectivePolicy?(groupId: string): Promise<Policy | null>;
877
+ moveGroup?(groupId: string, newParentId: string | null): Promise<Group>;
878
+ getGroupHierarchyStats?(): Promise<GroupHierarchyStats>;
879
+
880
+ // Tenants (optional - for multi-tenancy)
881
+ findTenant?(id: string): Promise<Tenant | null>;
882
+ findTenantBySlug?(slug: string): Promise<Tenant | null>;
883
+ listTenants?(filter?: TenantFilter): Promise<TenantListResult>;
884
+ createTenant?(data: CreateTenantInput): Promise<Tenant>;
885
+ updateTenant?(id: string, data: UpdateTenantInput): Promise<Tenant>;
886
+ deleteTenant?(id: string): Promise<void>;
887
+ getTenantStats?(tenantId: string): Promise<TenantStats>;
888
+
889
+ // Users (optional - for RBAC)
890
+ findUser?(id: string): Promise<User | null>;
891
+ findUserByEmail?(email: string, tenantId?: string): Promise<User | null>;
892
+ listUsers?(filter?: UserFilter): Promise<UserListResult>;
893
+ createUser?(data: CreateUserInput): Promise<User>;
894
+ updateUser?(id: string, data: UpdateUserInput): Promise<User>;
895
+ deleteUser?(id: string): Promise<void>;
896
+
897
+ // Roles (optional - for RBAC)
898
+ findRole?(id: string): Promise<Role | null>;
899
+ listRoles?(tenantId?: string): Promise<Role[]>;
900
+ createRole?(data: CreateRoleInput): Promise<Role>;
901
+ updateRole?(id: string, data: UpdateRoleInput): Promise<Role>;
902
+ deleteRole?(id: string): Promise<void>;
903
+ assignRoleToUser?(userId: string, roleId: string): Promise<void>;
904
+ removeRoleFromUser?(userId: string, roleId: string): Promise<void>;
905
+ getUserRoles?(userId: string): Promise<Role[]>;
906
+
907
+ // Audit Logs (optional - for compliance)
908
+ createAuditLog?(data: CreateAuditLogInput): Promise<AuditLog>;
909
+ listAuditLogs?(filter?: AuditLogFilter): Promise<AuditLogListResult>;
910
+ deleteAuditLogs?(filter: { olderThan?: Date; tenantId?: string }): Promise<number>;
911
+
912
+ // Scheduled Tasks (optional - for scheduling)
913
+ findScheduledTask?(id: string): Promise<ScheduledTask | null>;
914
+ listScheduledTasks?(filter?: ScheduledTaskFilter): Promise<ScheduledTaskListResult>;
915
+ createScheduledTask?(data: CreateScheduledTaskInput): Promise<ScheduledTask>;
916
+ updateScheduledTask?(id: string, data: UpdateScheduledTaskInput): Promise<ScheduledTask>;
917
+ deleteScheduledTask?(id: string): Promise<void>;
918
+ getUpcomingTasks?(hours: number): Promise<ScheduledTask[]>;
919
+ createTaskExecution?(data: { taskId: string }): Promise<TaskExecution>;
920
+ updateTaskExecution?(id: string, data: Partial<TaskExecution>): Promise<TaskExecution>;
921
+ listTaskExecutions?(taskId: string, limit?: number): Promise<TaskExecution[]>;
922
+
923
+ // Message Queue (optional - for persistent messaging)
924
+ enqueueMessage?(data: EnqueueMessageInput): Promise<QueuedMessage>;
925
+ dequeueMessages?(deviceId: string, limit?: number): Promise<QueuedMessage[]>;
926
+ peekMessages?(deviceId: string, limit?: number): Promise<QueuedMessage[]>;
927
+ acknowledgeMessage?(messageId: string): Promise<void>;
928
+ failMessage?(messageId: string, error: string): Promise<void>;
929
+ retryFailedMessages?(maxAttempts?: number): Promise<number>;
930
+ purgeExpiredMessages?(): Promise<number>;
931
+ getQueueStats?(tenantId?: string): Promise<QueueStats>;
932
+
933
+ // Plugin Storage (optional)
934
+ getPluginValue?(pluginName: string, key: string): Promise<unknown | null>;
935
+ setPluginValue?(pluginName: string, key: string, value: unknown): Promise<void>;
936
+ deletePluginValue?(pluginName: string, key: string): Promise<void>;
937
+ listPluginKeys?(pluginName: string, prefix?: string): Promise<string[]>;
938
+ clearPluginData?(pluginName: string): Promise<void>;
939
+
940
+ // Dashboard (optional - for analytics)
941
+ getDashboardStats?(tenantId?: string): Promise<DashboardStats>;
942
+ getDeviceStatusBreakdown?(tenantId?: string): Promise<DeviceStatusBreakdown>;
943
+ getEnrollmentTrend?(days: number, tenantId?: string): Promise<EnrollmentTrendPoint[]>;
944
+ getCommandSuccessRates?(tenantId?: string): Promise<CommandSuccessRates>;
945
+ getAppInstallationSummary?(tenantId?: string): Promise<AppInstallationSummary>;
946
+
837
947
  // Transactions (optional)
838
948
  transaction?<T>(fn: () => Promise<T>): Promise<T>;
839
949
  }
@@ -966,6 +1076,21 @@ export interface MDMInstance {
966
1076
  /** Group management */
967
1077
  groups: GroupManager;
968
1078
 
1079
+ /** Tenant management (if multi-tenancy enabled) */
1080
+ tenants?: TenantManager;
1081
+ /** Authorization management (RBAC) */
1082
+ authorization?: AuthorizationManager;
1083
+ /** Audit logging */
1084
+ audit?: AuditManager;
1085
+ /** Scheduled task management */
1086
+ schedules?: ScheduleManager;
1087
+ /** Persistent message queue */
1088
+ messageQueue?: MessageQueueManager;
1089
+ /** Dashboard analytics */
1090
+ dashboard?: DashboardManager;
1091
+ /** Plugin storage */
1092
+ pluginStorage?: PluginStorageAdapter;
1093
+
969
1094
  /** Push notification service */
970
1095
  push: PushAdapter;
971
1096
 
@@ -1056,15 +1181,577 @@ export interface CommandManager {
1056
1181
  }
1057
1182
 
1058
1183
  export interface GroupManager {
1184
+ // Basic CRUD operations
1059
1185
  get(id: string): Promise<Group | null>;
1060
1186
  list(): Promise<Group[]>;
1061
1187
  create(data: CreateGroupInput): Promise<Group>;
1062
1188
  update(id: string, data: UpdateGroupInput): Promise<Group>;
1063
1189
  delete(id: string): Promise<void>;
1190
+
1191
+ // Device management
1064
1192
  getDevices(groupId: string): Promise<Device[]>;
1065
1193
  addDevice(groupId: string, deviceId: string): Promise<void>;
1066
1194
  removeDevice(groupId: string, deviceId: string): Promise<void>;
1195
+
1196
+ // Hierarchy operations
1067
1197
  getChildren(groupId: string): Promise<Group[]>;
1198
+ getTree(rootId?: string): Promise<GroupTreeNode[]>;
1199
+ getAncestors(groupId: string): Promise<Group[]>;
1200
+ getDescendants(groupId: string): Promise<Group[]>;
1201
+ move(groupId: string, newParentId: string | null): Promise<Group>;
1202
+ getEffectivePolicy(groupId: string): Promise<Policy | null>;
1203
+ getHierarchyStats(): Promise<GroupHierarchyStats>;
1204
+ }
1205
+
1206
+ // ============================================
1207
+ // Group Hierarchy Types
1208
+ // ============================================
1209
+
1210
+ export interface GroupTreeNode extends Group {
1211
+ children: GroupTreeNode[];
1212
+ depth: number;
1213
+ path: string[];
1214
+ effectivePolicyId?: string | null;
1215
+ }
1216
+
1217
+ export interface GroupHierarchyStats {
1218
+ totalGroups: number;
1219
+ maxDepth: number;
1220
+ groupsWithDevices: number;
1221
+ groupsWithPolicies: number;
1222
+ }
1223
+
1224
+ // ============================================
1225
+ // Tenant Types (Multi-tenancy)
1226
+ // ============================================
1227
+
1228
+ export type TenantStatus = 'active' | 'suspended' | 'pending';
1229
+
1230
+ export interface Tenant {
1231
+ id: string;
1232
+ name: string;
1233
+ slug: string;
1234
+ status: TenantStatus;
1235
+ settings?: TenantSettings | null;
1236
+ metadata?: Record<string, unknown> | null;
1237
+ createdAt: Date;
1238
+ updatedAt: Date;
1239
+ }
1240
+
1241
+ export interface TenantSettings {
1242
+ maxDevices?: number;
1243
+ maxUsers?: number;
1244
+ features?: string[];
1245
+ branding?: {
1246
+ logo?: string;
1247
+ primaryColor?: string;
1248
+ };
1249
+ }
1250
+
1251
+ export interface CreateTenantInput {
1252
+ name: string;
1253
+ slug: string;
1254
+ settings?: TenantSettings;
1255
+ metadata?: Record<string, unknown>;
1256
+ }
1257
+
1258
+ export interface UpdateTenantInput {
1259
+ name?: string;
1260
+ slug?: string;
1261
+ status?: TenantStatus;
1262
+ settings?: TenantSettings;
1263
+ metadata?: Record<string, unknown>;
1264
+ }
1265
+
1266
+ export interface TenantFilter {
1267
+ status?: TenantStatus;
1268
+ search?: string;
1269
+ limit?: number;
1270
+ offset?: number;
1271
+ }
1272
+
1273
+ export interface TenantListResult {
1274
+ tenants: Tenant[];
1275
+ total: number;
1276
+ limit: number;
1277
+ offset: number;
1278
+ }
1279
+
1280
+ export interface TenantStats {
1281
+ deviceCount: number;
1282
+ userCount: number;
1283
+ policyCount: number;
1284
+ appCount: number;
1285
+ }
1286
+
1287
+ // ============================================
1288
+ // RBAC Types (Role-Based Access Control)
1289
+ // ============================================
1290
+
1291
+ export type PermissionAction = 'create' | 'read' | 'update' | 'delete' | 'manage' | '*';
1292
+ export type PermissionResource = 'devices' | 'policies' | 'apps' | 'groups' | 'commands' | 'users' | 'roles' | 'tenants' | 'audit' | '*';
1293
+
1294
+ export interface Permission {
1295
+ action: PermissionAction;
1296
+ resource: PermissionResource;
1297
+ resourceId?: string;
1298
+ }
1299
+
1300
+ export interface Role {
1301
+ id: string;
1302
+ tenantId?: string | null;
1303
+ name: string;
1304
+ description?: string | null;
1305
+ permissions: Permission[];
1306
+ isSystem: boolean;
1307
+ createdAt: Date;
1308
+ updatedAt: Date;
1309
+ }
1310
+
1311
+ export interface CreateRoleInput {
1312
+ tenantId?: string;
1313
+ name: string;
1314
+ description?: string;
1315
+ permissions: Permission[];
1316
+ }
1317
+
1318
+ export interface UpdateRoleInput {
1319
+ name?: string;
1320
+ description?: string;
1321
+ permissions?: Permission[];
1322
+ }
1323
+
1324
+ export interface User {
1325
+ id: string;
1326
+ tenantId?: string | null;
1327
+ email: string;
1328
+ name?: string | null;
1329
+ status: 'active' | 'inactive' | 'pending';
1330
+ metadata?: Record<string, unknown> | null;
1331
+ lastLoginAt?: Date | null;
1332
+ createdAt: Date;
1333
+ updatedAt: Date;
1334
+ }
1335
+
1336
+ export interface UserWithRoles extends User {
1337
+ roles: Role[];
1338
+ }
1339
+
1340
+ export interface CreateUserInput {
1341
+ tenantId?: string;
1342
+ email: string;
1343
+ name?: string;
1344
+ status?: 'active' | 'inactive' | 'pending';
1345
+ metadata?: Record<string, unknown>;
1346
+ }
1347
+
1348
+ export interface UpdateUserInput {
1349
+ email?: string;
1350
+ name?: string;
1351
+ status?: 'active' | 'inactive' | 'pending';
1352
+ metadata?: Record<string, unknown>;
1353
+ }
1354
+
1355
+ export interface UserFilter {
1356
+ tenantId?: string;
1357
+ status?: 'active' | 'inactive' | 'pending';
1358
+ search?: string;
1359
+ limit?: number;
1360
+ offset?: number;
1361
+ }
1362
+
1363
+ export interface UserListResult {
1364
+ users: User[];
1365
+ total: number;
1366
+ limit: number;
1367
+ offset: number;
1368
+ }
1369
+
1370
+ // ============================================
1371
+ // Audit Types
1372
+ // ============================================
1373
+
1374
+ export type AuditAction = 'create' | 'read' | 'update' | 'delete' | 'login' | 'logout' | 'enroll' | 'unenroll' | 'command' | 'export' | 'import' | 'custom';
1375
+
1376
+ export interface AuditLog {
1377
+ id: string;
1378
+ tenantId?: string | null;
1379
+ userId?: string | null;
1380
+ action: AuditAction;
1381
+ resource: string;
1382
+ resourceId?: string | null;
1383
+ status: 'success' | 'failure';
1384
+ error?: string | null;
1385
+ details?: Record<string, unknown> | null;
1386
+ ipAddress?: string | null;
1387
+ userAgent?: string | null;
1388
+ createdAt: Date;
1389
+ }
1390
+
1391
+ export interface CreateAuditLogInput {
1392
+ tenantId?: string;
1393
+ userId?: string;
1394
+ action: AuditAction;
1395
+ resource: string;
1396
+ resourceId?: string;
1397
+ status?: 'success' | 'failure';
1398
+ error?: string;
1399
+ details?: Record<string, unknown>;
1400
+ ipAddress?: string;
1401
+ userAgent?: string;
1402
+ }
1403
+
1404
+ export interface AuditConfig {
1405
+ enabled: boolean;
1406
+ retentionDays?: number;
1407
+ skipReadOperations?: boolean;
1408
+ logActions?: AuditAction[];
1409
+ logResources?: string[];
1410
+ }
1411
+
1412
+ export interface AuditSummary {
1413
+ totalLogs: number;
1414
+ byAction: Record<AuditAction, number>;
1415
+ byResource: Record<string, number>;
1416
+ byStatus: { success: number; failure: number };
1417
+ topUsers: Array<{ userId: string; count: number }>;
1418
+ recentFailures: AuditLog[];
1419
+ }
1420
+
1421
+ export interface AuditLogFilter {
1422
+ tenantId?: string;
1423
+ userId?: string;
1424
+ action?: string;
1425
+ resource?: string;
1426
+ resourceId?: string;
1427
+ startDate?: Date;
1428
+ endDate?: Date;
1429
+ limit?: number;
1430
+ offset?: number;
1431
+ }
1432
+
1433
+ export interface AuditLogListResult {
1434
+ logs: AuditLog[];
1435
+ total: number;
1436
+ limit: number;
1437
+ offset: number;
1438
+ }
1439
+
1440
+ // ============================================
1441
+ // Schedule Types
1442
+ // ============================================
1443
+
1444
+ export type TaskType = 'command' | 'policy_update' | 'app_install' | 'maintenance' | 'custom';
1445
+ export type ScheduledTaskStatus = 'active' | 'paused' | 'completed' | 'failed';
1446
+
1447
+ export interface MaintenanceWindow {
1448
+ daysOfWeek: number[];
1449
+ startTime: string;
1450
+ endTime: string;
1451
+ timezone: string;
1452
+ }
1453
+
1454
+ export interface TaskSchedule {
1455
+ type: 'once' | 'recurring' | 'window';
1456
+ executeAt?: Date;
1457
+ cron?: string;
1458
+ window?: MaintenanceWindow;
1459
+ }
1460
+
1461
+ export interface ScheduledTask {
1462
+ id: string;
1463
+ tenantId?: string | null;
1464
+ name: string;
1465
+ description?: string | null;
1466
+ taskType: TaskType;
1467
+ schedule: TaskSchedule;
1468
+ target?: DeployTarget;
1469
+ payload?: Record<string, unknown> | null;
1470
+ status: ScheduledTaskStatus;
1471
+ nextRunAt?: Date | null;
1472
+ lastRunAt?: Date | null;
1473
+ maxRetries: number;
1474
+ retryCount: number;
1475
+ createdAt: Date;
1476
+ updatedAt: Date;
1477
+ }
1478
+
1479
+ export interface CreateScheduledTaskInput {
1480
+ tenantId?: string;
1481
+ name: string;
1482
+ description?: string;
1483
+ taskType: TaskType;
1484
+ schedule: TaskSchedule;
1485
+ target?: DeployTarget;
1486
+ payload?: Record<string, unknown>;
1487
+ maxRetries?: number;
1488
+ }
1489
+
1490
+ export interface UpdateScheduledTaskInput {
1491
+ name?: string;
1492
+ description?: string;
1493
+ schedule?: TaskSchedule;
1494
+ target?: DeployTarget;
1495
+ payload?: Record<string, unknown>;
1496
+ status?: ScheduledTaskStatus;
1497
+ maxRetries?: number;
1498
+ }
1499
+
1500
+ export interface ScheduledTaskFilter {
1501
+ tenantId?: string;
1502
+ taskType?: TaskType | TaskType[];
1503
+ status?: ScheduledTaskStatus | ScheduledTaskStatus[];
1504
+ limit?: number;
1505
+ offset?: number;
1506
+ }
1507
+
1508
+ export interface ScheduledTaskListResult {
1509
+ tasks: ScheduledTask[];
1510
+ total: number;
1511
+ limit: number;
1512
+ offset: number;
1513
+ }
1514
+
1515
+ export interface TaskExecution {
1516
+ id: string;
1517
+ taskId: string;
1518
+ status: 'running' | 'completed' | 'failed';
1519
+ startedAt: Date;
1520
+ completedAt?: Date | null;
1521
+ devicesProcessed: number;
1522
+ devicesSucceeded: number;
1523
+ devicesFailed: number;
1524
+ error?: string | null;
1525
+ details?: Record<string, unknown> | null;
1526
+ }
1527
+
1528
+ // ============================================
1529
+ // Message Queue Types
1530
+ // ============================================
1531
+
1532
+ export type QueueMessageStatus = 'pending' | 'processing' | 'delivered' | 'failed' | 'expired';
1533
+
1534
+ export interface QueuedMessage {
1535
+ id: string;
1536
+ tenantId?: string | null;
1537
+ deviceId: string;
1538
+ messageType: string;
1539
+ payload: Record<string, unknown>;
1540
+ priority: 'high' | 'normal' | 'low';
1541
+ status: QueueMessageStatus;
1542
+ attempts: number;
1543
+ maxAttempts: number;
1544
+ lastAttemptAt?: Date | null;
1545
+ lastError?: string | null;
1546
+ expiresAt?: Date | null;
1547
+ createdAt: Date;
1548
+ updatedAt: Date;
1549
+ }
1550
+
1551
+ export interface EnqueueMessageInput {
1552
+ tenantId?: string;
1553
+ deviceId: string;
1554
+ messageType: string;
1555
+ payload: Record<string, unknown>;
1556
+ priority?: 'high' | 'normal' | 'low';
1557
+ maxAttempts?: number;
1558
+ ttlSeconds?: number;
1559
+ }
1560
+
1561
+ export interface QueueStats {
1562
+ pending: number;
1563
+ processing: number;
1564
+ delivered: number;
1565
+ failed: number;
1566
+ expired: number;
1567
+ byDevice: Record<string, number>;
1568
+ oldestPending?: Date;
1569
+ }
1570
+
1571
+ // ============================================
1572
+ // Dashboard Types
1573
+ // ============================================
1574
+
1575
+ export interface DashboardStats {
1576
+ devices: {
1577
+ total: number;
1578
+ enrolled: number;
1579
+ active: number;
1580
+ blocked: number;
1581
+ pending: number;
1582
+ };
1583
+ policies: {
1584
+ total: number;
1585
+ deployed: number;
1586
+ };
1587
+ applications: {
1588
+ total: number;
1589
+ deployed: number;
1590
+ };
1591
+ commands: {
1592
+ pendingCount: number;
1593
+ last24hTotal: number;
1594
+ last24hSuccess: number;
1595
+ last24hFailed: number;
1596
+ };
1597
+ groups: {
1598
+ total: number;
1599
+ withDevices: number;
1600
+ };
1601
+ }
1602
+
1603
+ export interface DeviceStatusBreakdown {
1604
+ byStatus: Record<DeviceStatus, number>;
1605
+ byOs: Record<string, number>;
1606
+ byManufacturer: Record<string, number>;
1607
+ byModel: Record<string, number>;
1608
+ }
1609
+
1610
+ export interface EnrollmentTrendPoint {
1611
+ date: Date;
1612
+ enrolled: number;
1613
+ unenrolled: number;
1614
+ netChange: number;
1615
+ totalDevices: number;
1616
+ }
1617
+
1618
+ export interface CommandSuccessRates {
1619
+ overall: {
1620
+ total: number;
1621
+ completed: number;
1622
+ failed: number;
1623
+ successRate: number;
1624
+ };
1625
+ byType: Record<string, {
1626
+ total: number;
1627
+ completed: number;
1628
+ failed: number;
1629
+ successRate: number;
1630
+ avgExecutionTimeMs?: number;
1631
+ }>;
1632
+ last24h: {
1633
+ total: number;
1634
+ completed: number;
1635
+ failed: number;
1636
+ pending: number;
1637
+ };
1638
+ }
1639
+
1640
+ export interface AppInstallationSummary {
1641
+ total: number;
1642
+ byStatus: Record<string, number>;
1643
+ recentFailures: Array<{
1644
+ packageName: string;
1645
+ deviceId: string;
1646
+ error: string;
1647
+ timestamp: Date;
1648
+ }>;
1649
+ topInstalled: Array<{
1650
+ packageName: string;
1651
+ name: string;
1652
+ installedCount: number;
1653
+ }>;
1654
+ }
1655
+
1656
+ // ============================================
1657
+ // Plugin Storage Types
1658
+ // ============================================
1659
+
1660
+ export interface PluginStorageAdapter {
1661
+ get<T>(pluginName: string, key: string): Promise<T | null>;
1662
+ set<T>(pluginName: string, key: string, value: T): Promise<void>;
1663
+ delete(pluginName: string, key: string): Promise<void>;
1664
+ list(pluginName: string, prefix?: string): Promise<string[]>;
1665
+ clear(pluginName: string): Promise<void>;
1666
+ }
1667
+
1668
+ export interface PluginStorageEntry {
1669
+ pluginName: string;
1670
+ key: string;
1671
+ value: unknown;
1672
+ createdAt: Date;
1673
+ updatedAt: Date;
1674
+ }
1675
+
1676
+ // ============================================
1677
+ // Enterprise Manager Interfaces
1678
+ // ============================================
1679
+
1680
+ export interface TenantManager {
1681
+ get(id: string): Promise<Tenant | null>;
1682
+ getBySlug(slug: string): Promise<Tenant | null>;
1683
+ list(filter?: TenantFilter): Promise<TenantListResult>;
1684
+ create(data: CreateTenantInput): Promise<Tenant>;
1685
+ update(id: string, data: UpdateTenantInput): Promise<Tenant>;
1686
+ delete(id: string, cascade?: boolean): Promise<void>;
1687
+ getStats(tenantId: string): Promise<TenantStats>;
1688
+ activate(id: string): Promise<Tenant>;
1689
+ deactivate(id: string): Promise<Tenant>;
1690
+ }
1691
+
1692
+ export interface AuthorizationManager {
1693
+ createRole(data: CreateRoleInput): Promise<Role>;
1694
+ getRole(id: string): Promise<Role | null>;
1695
+ listRoles(tenantId?: string): Promise<Role[]>;
1696
+ updateRole(id: string, data: UpdateRoleInput): Promise<Role>;
1697
+ deleteRole(id: string): Promise<void>;
1698
+ createUser(data: CreateUserInput): Promise<User>;
1699
+ getUser(id: string): Promise<UserWithRoles | null>;
1700
+ getUserByEmail(email: string, tenantId?: string): Promise<UserWithRoles | null>;
1701
+ listUsers(filter?: UserFilter): Promise<UserListResult>;
1702
+ updateUser(id: string, data: UpdateUserInput): Promise<User>;
1703
+ deleteUser(id: string): Promise<void>;
1704
+ assignRole(userId: string, roleId: string): Promise<void>;
1705
+ removeRole(userId: string, roleId: string): Promise<void>;
1706
+ getUserRoles(userId: string): Promise<Role[]>;
1707
+ can(userId: string, action: PermissionAction, resource: PermissionResource, resourceId?: string): Promise<boolean>;
1708
+ canAny(userId: string, permissions: Array<{ action: PermissionAction; resource: PermissionResource }>): Promise<boolean>;
1709
+ requirePermission(userId: string, action: PermissionAction, resource: PermissionResource, resourceId?: string): Promise<void>;
1710
+ isAdmin(userId: string): Promise<boolean>;
1711
+ }
1712
+
1713
+ export interface AuditManager {
1714
+ log(entry: CreateAuditLogInput): Promise<AuditLog>;
1715
+ list(filter?: AuditLogFilter): Promise<AuditLogListResult>;
1716
+ getByResource(resource: string, resourceId: string): Promise<AuditLog[]>;
1717
+ getByUser(userId: string, filter?: AuditLogFilter): Promise<AuditLogListResult>;
1718
+ export(filter: AuditLogFilter, format: 'json' | 'csv'): Promise<string>;
1719
+ purge(olderThanDays?: number): Promise<number>;
1720
+ getSummary(tenantId?: string, days?: number): Promise<AuditSummary>;
1721
+ }
1722
+
1723
+ export interface ScheduleManager {
1724
+ get(id: string): Promise<ScheduledTask | null>;
1725
+ list(filter?: ScheduledTaskFilter): Promise<ScheduledTaskListResult>;
1726
+ create(data: CreateScheduledTaskInput): Promise<ScheduledTask>;
1727
+ update(id: string, data: UpdateScheduledTaskInput): Promise<ScheduledTask>;
1728
+ delete(id: string): Promise<void>;
1729
+ pause(id: string): Promise<ScheduledTask>;
1730
+ resume(id: string): Promise<ScheduledTask>;
1731
+ runNow(id: string): Promise<TaskExecution>;
1732
+ getUpcoming(hours: number): Promise<ScheduledTask[]>;
1733
+ getExecutions(taskId: string, limit?: number): Promise<TaskExecution[]>;
1734
+ calculateNextRun(schedule: TaskSchedule): Date | null;
1735
+ }
1736
+
1737
+ export interface MessageQueueManager {
1738
+ enqueue(message: EnqueueMessageInput): Promise<QueuedMessage>;
1739
+ enqueueBatch(messages: EnqueueMessageInput[]): Promise<QueuedMessage[]>;
1740
+ dequeue(deviceId: string, limit?: number): Promise<QueuedMessage[]>;
1741
+ acknowledge(messageId: string): Promise<void>;
1742
+ fail(messageId: string, error: string): Promise<void>;
1743
+ retryFailed(maxAttempts?: number): Promise<number>;
1744
+ purgeExpired(): Promise<number>;
1745
+ getStats(tenantId?: string): Promise<QueueStats>;
1746
+ peek(deviceId: string, limit?: number): Promise<QueuedMessage[]>;
1747
+ }
1748
+
1749
+ export interface DashboardManager {
1750
+ getStats(tenantId?: string): Promise<DashboardStats>;
1751
+ getDeviceStatusBreakdown(tenantId?: string): Promise<DeviceStatusBreakdown>;
1752
+ getEnrollmentTrend(days: number, tenantId?: string): Promise<EnrollmentTrendPoint[]>;
1753
+ getCommandSuccessRates(tenantId?: string): Promise<CommandSuccessRates>;
1754
+ getAppInstallationSummary(tenantId?: string): Promise<AppInstallationSummary>;
1068
1755
  }
1069
1756
 
1070
1757
  // ============================================
@@ -1136,6 +1823,30 @@ export class ApplicationNotFoundError extends MDMError {
1136
1823
  }
1137
1824
  }
1138
1825
 
1826
+ export class TenantNotFoundError extends MDMError {
1827
+ constructor(identifier: string) {
1828
+ super(`Tenant not found: ${identifier}`, 'TENANT_NOT_FOUND', 404);
1829
+ }
1830
+ }
1831
+
1832
+ export class RoleNotFoundError extends MDMError {
1833
+ constructor(identifier: string) {
1834
+ super(`Role not found: ${identifier}`, 'ROLE_NOT_FOUND', 404);
1835
+ }
1836
+ }
1837
+
1838
+ export class GroupNotFoundError extends MDMError {
1839
+ constructor(identifier: string) {
1840
+ super(`Group not found: ${identifier}`, 'GROUP_NOT_FOUND', 404);
1841
+ }
1842
+ }
1843
+
1844
+ export class UserNotFoundError extends MDMError {
1845
+ constructor(identifier: string) {
1846
+ super(`User not found: ${identifier}`, 'USER_NOT_FOUND', 404);
1847
+ }
1848
+ }
1849
+
1139
1850
  export class EnrollmentError extends MDMError {
1140
1851
  constructor(message: string, details?: unknown) {
1141
1852
  super(message, 'ENROLLMENT_ERROR', 400, details);