@openmdm/core 0.4.1 → 0.6.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/dist/index.d.ts CHANGED
@@ -2,6 +2,119 @@ import { WebhookConfig, MDMEvent, WebhookEndpoint, EventType, DatabaseAdapter, T
2
2
  export { AppInstallationSummary, AppRollback, AppVersion, Application, ApplicationManager, ApplicationNotFoundError, AuditAction, AuditLog, AuditLogFilter, AuditLogListResult, AuditSummary, AuthConfig, AuthenticationError, AuthorizationError, Command, CommandFilter, CommandManager, CommandNotFoundError, CommandResult, CommandStatus, CommandSuccessRates, CommandType, CreateAppRollbackInput, CreateApplicationInput, CreateAuditLogInput, CreateDeviceInput, CreateGroupInput, CreatePolicyInput, CreateRoleInput, CreateScheduledTaskInput, CreateTenantInput, CreateUserInput, DashboardStats, DeployTarget, Device, DeviceFilter, DeviceListResult, DeviceLocation, DeviceManager, DeviceNotFoundError, DeviceStatus, DeviceStatusBreakdown, EnqueueMessageInput, EnrollmentConfig, EnrollmentError, EnrollmentMethod, EnrollmentRequest, EnrollmentResponse, EnrollmentTrendPoint, EventFilter, EventHandler, EventPayloadMap, Group, GroupHierarchyStats, GroupManager, GroupNotFoundError, GroupTreeNode, HardwareControl, Heartbeat, InstalledApp, MDMError, MDMPlugin, MaintenanceWindow, PasswordPolicy, Permission, PermissionAction, PermissionResource, PluginMiddleware, PluginRoute, PluginStorageEntry, Policy, PolicyApplication, PolicyManager, PolicyNotFoundError, PolicySettings, PushAdapter, PushBatchResult, PushConfig, PushMessage, PushProviderConfig, PushResult, PushToken, QueueMessageStatus, QueueStats, QueuedMessage, RegisterPushTokenInput, Role, RoleNotFoundError, ScheduledTask, ScheduledTaskFilter, ScheduledTaskListResult, ScheduledTaskStatus, SendCommandInput, StorageConfig, SystemUpdatePolicy, TaskExecution, TaskSchedule, TaskType, Tenant, TenantFilter, TenantListResult, TenantNotFoundError, TenantSettings, TenantStats, TenantStatus, TimeWindow, UpdateApplicationInput, UpdateDeviceInput, UpdateGroupInput, UpdatePolicyInput, UpdateRoleInput, UpdateScheduledTaskInput, UpdateTenantInput, UpdateUserInput, User, UserFilter, UserListResult, UserNotFoundError, UserWithRoles, ValidationError, VpnConfig, WebhookDeliveryResult, WebhookManager, WifiConfig } from './types.js';
3
3
  export { ColumnDefinition, ColumnType, IndexDefinition, SchemaDefinition, TableDefinition, camelToSnake, getColumnNames, getPrimaryKey, getTableNames, mdmSchema, snakeToCamel, transformToCamelCase, transformToSnakeCase } from './schema.js';
4
4
 
5
+ /**
6
+ * OpenMDM Agent Wire Protocol v2.
7
+ *
8
+ * A unified response envelope for every `/agent/*` endpoint, plus the
9
+ * version-selection rules that let the server serve v1 and v2 clients
10
+ * simultaneously during a fleet rollout.
11
+ *
12
+ * ## Background
13
+ *
14
+ * Until now, agent-facing handlers returned either a bare JSON body
15
+ * on success or raised an `HTTPException(401|404|5xx)` on failure.
16
+ * The agent had to interpret five different HTTP status codes and
17
+ * infer what to do about each — which in practice meant "on auth
18
+ * error, wipe local enrollment state and re-enroll". That single
19
+ * ambiguity produced the auto-unenroll behavior we saw in production:
20
+ * a transient 401 or 404 was indistinguishable from "you are really
21
+ * unenrolled", so the agent self-destructed.
22
+ *
23
+ * ## Protocol v2
24
+ *
25
+ * Every agent-facing endpoint replies with HTTP 200 and a body of
26
+ * shape {@link AgentResponse}:
27
+ *
28
+ * ```json
29
+ * { "ok": true, "action": "none", "data": { ... } }
30
+ * { "ok": false, "action": "retry", "message": "..." }
31
+ * { "ok": false, "action": "reauth", "message": "..." }
32
+ * { "ok": false, "action": "unenroll", "message": "..." }
33
+ * ```
34
+ *
35
+ * - `ok` is the boolean the agent checks first.
36
+ * - `action` is the *only* field the agent reads to decide what to do
37
+ * next. There is exactly one handler per action on the client, so
38
+ * adding a new server response path is a matter of picking an
39
+ * existing action.
40
+ * - `data` carries the handler-specific payload (heartbeat response,
41
+ * policy update, etc.) on success.
42
+ * - `message` is a human-readable hint, for logs.
43
+ *
44
+ * HTTP 5xx is still used for real infrastructure failures (the Lambda
45
+ * timed out, the database connection dropped, etc.). v2 envelopes are
46
+ * reserved for *application-level* failures the agent can reason about.
47
+ *
48
+ * ## Versioning and rollout
49
+ *
50
+ * The agent opts into v2 by sending the header
51
+ * `X-Openmdm-Protocol: 2` on every request. When absent, the server
52
+ * falls back to the legacy v1 behavior — bare JSON on success,
53
+ * `HTTPException(401|404|…)` on failure — so a fleet still running
54
+ * older APKs keeps working during rollout.
55
+ *
56
+ * After the fleet has been upgraded, v1 can be dropped in a future
57
+ * major release by ignoring the header and always emitting v2.
58
+ */
59
+ /**
60
+ * Instruction the server gives the agent on how to react to this
61
+ * response. This is the entire client-side decision space.
62
+ *
63
+ * - `none`: happy path. The agent consumes `data` and continues.
64
+ * - `retry`: transient problem. The agent re-tries later without
65
+ * touching local state.
66
+ * - `reauth`: the agent's access token is no longer valid. It should
67
+ * call the refresh flow. It must NOT wipe enrollment state.
68
+ * - `unenroll`: the server-side record for this device is gone or
69
+ * blocked and the agent's credentials will never work again. The
70
+ * agent should stop making requests and surface this to the user.
71
+ * In Phase 2b this will be further softened: the agent will attempt
72
+ * a hardware-identity-based rebind before treating this as terminal.
73
+ */
74
+ type AgentAction = 'none' | 'retry' | 'reauth' | 'unenroll';
75
+ /**
76
+ * Unified response envelope for every `/agent/*` endpoint under
77
+ * protocol v2.
78
+ *
79
+ * Successful responses carry `data`; failure responses carry
80
+ * `message`. The envelope never carries both the happy-path payload
81
+ * and an error hint at the same time.
82
+ */
83
+ type AgentResponse<T = unknown> = {
84
+ ok: true;
85
+ action: 'none';
86
+ data: T;
87
+ } | {
88
+ ok: false;
89
+ action: Exclude<AgentAction, 'none'>;
90
+ message?: string;
91
+ };
92
+ /**
93
+ * HTTP header an agent sends to opt into protocol v2. Case-insensitive
94
+ * on the wire; use the constant to avoid typos.
95
+ */
96
+ declare const AGENT_PROTOCOL_HEADER = "X-Openmdm-Protocol";
97
+ /**
98
+ * Current wire-protocol version. Agents that send
99
+ * `X-Openmdm-Protocol: 2` get envelope responses. Absent or older
100
+ * values are served with the legacy flat shape.
101
+ */
102
+ declare const AGENT_PROTOCOL_V2 = "2";
103
+ /**
104
+ * Helper: build a success envelope.
105
+ */
106
+ declare function agentOk<T>(data: T): AgentResponse<T>;
107
+ /**
108
+ * Helper: build a failure envelope.
109
+ */
110
+ declare function agentFail(action: Exclude<AgentAction, 'none'>, message?: string): AgentResponse<never>;
111
+ /**
112
+ * Returns `true` iff the caller should be served protocol v2. The
113
+ * input is the value of the {@link AGENT_PROTOCOL_HEADER} header,
114
+ * which may be undefined.
115
+ */
116
+ declare function wantsAgentProtocolV2(headerValue: string | undefined | null): boolean;
117
+
5
118
  /**
6
119
  * OpenMDM Webhook Delivery System
7
120
  *
@@ -189,4 +302,4 @@ declare function parsePluginKey(key: string): {
189
302
  */
190
303
  declare function createMDM(config: MDMConfig): MDMInstance;
191
304
 
192
- export { AuditConfig, AuditManager, AuthorizationManager, DashboardManager, DatabaseAdapter, EventType, MDMConfig, MDMEvent, MDMInstance, MessageQueueManager, PluginStorageAdapter, ScheduleManager, TenantManager, WebhookConfig, WebhookEndpoint, type WebhookPayload, createAuditManager, createAuthorizationManager, createDashboardManager, createMDM, createMemoryPluginStorageAdapter, createMessageQueueManager, createPluginKey, createPluginStorageAdapter, createScheduleManager, createTenantManager, createWebhookManager, parsePluginKey, verifyWebhookSignature };
305
+ export { AGENT_PROTOCOL_HEADER, AGENT_PROTOCOL_V2, type AgentAction, type AgentResponse, AuditConfig, AuditManager, AuthorizationManager, DashboardManager, DatabaseAdapter, EventType, MDMConfig, MDMEvent, MDMInstance, MessageQueueManager, PluginStorageAdapter, ScheduleManager, TenantManager, WebhookConfig, WebhookEndpoint, type WebhookPayload, agentFail, agentOk, createAuditManager, createAuthorizationManager, createDashboardManager, createMDM, createMemoryPluginStorageAdapter, createMessageQueueManager, createPluginKey, createPluginStorageAdapter, createScheduleManager, createTenantManager, createWebhookManager, parsePluginKey, verifyWebhookSignature, wantsAgentProtocolV2 };
package/dist/index.js CHANGED
@@ -2026,6 +2026,19 @@ function transformToSnakeCase(obj) {
2026
2026
  return result;
2027
2027
  }
2028
2028
 
2029
+ // src/agent-protocol.ts
2030
+ var AGENT_PROTOCOL_HEADER = "X-Openmdm-Protocol";
2031
+ var AGENT_PROTOCOL_V2 = "2";
2032
+ function agentOk(data) {
2033
+ return { ok: true, action: "none", data };
2034
+ }
2035
+ function agentFail(action, message) {
2036
+ return { ok: false, action, message };
2037
+ }
2038
+ function wantsAgentProtocolV2(headerValue) {
2039
+ return headerValue === AGENT_PROTOCOL_V2;
2040
+ }
2041
+
2029
2042
  // src/index.ts
2030
2043
  function createMDM(config) {
2031
2044
  const { database, push, enrollment, webhooks: webhooksConfig, plugins = [] } = config;
@@ -2895,6 +2908,6 @@ function generateDeviceToken(deviceId, secret, expirationSeconds) {
2895
2908
  return `${header}.${payload}.${signature}`;
2896
2909
  }
2897
2910
 
2898
- export { ApplicationNotFoundError, AuthenticationError, AuthorizationError, CommandNotFoundError, DeviceNotFoundError, EnrollmentError, GroupNotFoundError, MDMError, PolicyNotFoundError, RoleNotFoundError, TenantNotFoundError, UserNotFoundError, ValidationError, camelToSnake, createAuditManager, createAuthorizationManager, createDashboardManager, createMDM, createMemoryPluginStorageAdapter, createMessageQueueManager, createPluginKey, createPluginStorageAdapter, createScheduleManager, createTenantManager, createWebhookManager, getColumnNames, getPrimaryKey, getTableNames, mdmSchema, parsePluginKey, snakeToCamel, transformToCamelCase, transformToSnakeCase, verifyWebhookSignature };
2911
+ export { AGENT_PROTOCOL_HEADER, AGENT_PROTOCOL_V2, ApplicationNotFoundError, AuthenticationError, AuthorizationError, CommandNotFoundError, DeviceNotFoundError, EnrollmentError, GroupNotFoundError, MDMError, PolicyNotFoundError, RoleNotFoundError, TenantNotFoundError, UserNotFoundError, ValidationError, agentFail, agentOk, camelToSnake, createAuditManager, createAuthorizationManager, createDashboardManager, createMDM, createMemoryPluginStorageAdapter, createMessageQueueManager, createPluginKey, createPluginStorageAdapter, createScheduleManager, createTenantManager, createWebhookManager, getColumnNames, getPrimaryKey, getTableNames, mdmSchema, parsePluginKey, snakeToCamel, transformToCamelCase, transformToSnakeCase, verifyWebhookSignature, wantsAgentProtocolV2 };
2899
2912
  //# sourceMappingURL=index.js.map
2900
2913
  //# sourceMappingURL=index.js.map