@deveye/types 0.15.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/LICENSE +21 -0
- package/README.md +23 -0
- package/package.json +68 -0
- package/src/domain/audience.ts +549 -0
- package/src/domain/backup.ts +355 -0
- package/src/domain/credential.ts +55 -0
- package/src/domain/database.ts +467 -0
- package/src/domain/deploy.ts +231 -0
- package/src/domain/device.ts +172 -0
- package/src/domain/deviceFiles.ts +84 -0
- package/src/domain/deviceLogs.ts +82 -0
- package/src/domain/featureRegistry.ts +392 -0
- package/src/domain/finance.ts +477 -0
- package/src/domain/git.ts +419 -0
- package/src/domain/home.ts +314 -0
- package/src/domain/live.ts +272 -0
- package/src/domain/logs.ts +117 -0
- package/src/domain/mail.ts +394 -0
- package/src/domain/metrics.ts +127 -0
- package/src/domain/note.ts +202 -0
- package/src/domain/notifications.ts +268 -0
- package/src/domain/packages.ts +35 -0
- package/src/domain/password.ts +36 -0
- package/src/domain/presence.ts +21 -0
- package/src/domain/project.ts +168 -0
- package/src/domain/projectBoard.ts +130 -0
- package/src/domain/projectChat.ts +46 -0
- package/src/domain/projectHistory.ts +82 -0
- package/src/domain/projectLink.ts +87 -0
- package/src/domain/projectPlan.ts +68 -0
- package/src/domain/report.ts +492 -0
- package/src/domain/role.ts +8 -0
- package/src/domain/secrecy.ts +66 -0
- package/src/domain/sentinel.ts +623 -0
- package/src/domain/sharing.ts +186 -0
- package/src/domain/syncProtocol.ts +116 -0
- package/src/domain/twoFactor.ts +40 -0
- package/src/domain/uptime.ts +216 -0
- package/src/domain/user.ts +141 -0
- package/src/domain/workspace.ts +56 -0
- package/src/domain/workspaceRole.ts +251 -0
- package/src/features/admin.ts +112 -0
- package/src/features/audience.ts +275 -0
- package/src/features/backup.ts +230 -0
- package/src/features/database.ts +461 -0
- package/src/features/deploy.ts +245 -0
- package/src/features/device.ts +292 -0
- package/src/features/deviceFiles.ts +83 -0
- package/src/features/deviceLogs.ts +36 -0
- package/src/features/deviceTerminal.ts +57 -0
- package/src/features/finance.ts +360 -0
- package/src/features/git.ts +368 -0
- package/src/features/home.ts +32 -0
- package/src/features/live.ts +113 -0
- package/src/features/logs.ts +86 -0
- package/src/features/mail.ts +374 -0
- package/src/features/metrics.ts +185 -0
- package/src/features/note.ts +189 -0
- package/src/features/notify.ts +164 -0
- package/src/features/password.ts +67 -0
- package/src/features/project.ts +709 -0
- package/src/features/registry.ts +103 -0
- package/src/features/secrecy.ts +120 -0
- package/src/features/sentinel.ts +233 -0
- package/src/features/sharing.ts +79 -0
- package/src/features/twoFactor.ts +47 -0
- package/src/features/uptime.ts +186 -0
- package/src/features/user.ts +91 -0
- package/src/features/workspace.ts +200 -0
- package/src/http/auth.ts +94 -0
- package/src/http/device.ts +222 -0
- package/src/http/status.ts +45 -0
- package/src/index.ts +1700 -0
- package/src/protocol/agent.ts +1171 -0
- package/src/protocol/envelope.ts +46 -0
- package/src/protocol/error.ts +27 -0
- package/src/protocol/result.ts +17 -0
- package/src/protocol/version.ts +6 -0
- package/src/sdk/client-ambient.d.ts +238 -0
- package/src/sdk/client.ts +66 -0
- package/src/sdk/ids.ts +25 -0
- package/src/sdk/index.ts +11 -0
- package/src/sdk/manifest.ts +326 -0
- package/src/sdk/providers.ts +48 -0
- package/src/sdk/server.ts +378 -0
- package/src/sdk/testing.ts +179 -0
- package/src/utils/version.ts +28 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { deviceSchema } from '../domain/device';
|
|
3
|
+
import { packageManagerIdSchema } from '../domain/packages';
|
|
4
|
+
import { agentLifecycleActionSchema, agentPowerActionSchema } from '../protocol/agent';
|
|
5
|
+
import { processCaptureSchema } from '../domain/report';
|
|
6
|
+
import { workspaceKindSchema } from '../domain/workspace';
|
|
7
|
+
|
|
8
|
+
const deviceId = z.uuid();
|
|
9
|
+
|
|
10
|
+
/** List devices visible to the caller (own devices; all devices for admins). */
|
|
11
|
+
export const deviceList = {
|
|
12
|
+
command: 'device.list' as const,
|
|
13
|
+
input: z.object({
|
|
14
|
+
/**
|
|
15
|
+
* `workspace` (défaut) : les appareils de l'espace actif — ce qu'affichent
|
|
16
|
+
* l'accueil, la topbar et Monitoring.
|
|
17
|
+
* `fleet` : toute la flotte, tous espaces confondus. Réservé aux
|
|
18
|
+
* administrateurs, pour la page Appareils.
|
|
19
|
+
*/
|
|
20
|
+
scope: z.enum(['workspace', 'fleet']).optional()
|
|
21
|
+
}),
|
|
22
|
+
output: z.object({ devices: z.array(deviceSchema) })
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/** Confirm a `pending` device, moving it to `active`. */
|
|
26
|
+
export const deviceConfirm = {
|
|
27
|
+
command: 'device.confirm' as const,
|
|
28
|
+
input: z.object({ deviceId }),
|
|
29
|
+
output: z.object({ device: deviceSchema })
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/** Revoke a device: its token is rejected and it can no longer push metrics. */
|
|
33
|
+
export const deviceRevoke = {
|
|
34
|
+
command: 'device.revoke' as const,
|
|
35
|
+
input: z.object({ deviceId }),
|
|
36
|
+
output: z.object({ device: deviceSchema })
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Lay out the workspace's devices: `ids` is the **complete** list in its final
|
|
41
|
+
* order (lower index first). New devices are appended, so the order is entirely
|
|
42
|
+
* the user's — as it is for monitored services, repositories and notes.
|
|
43
|
+
*
|
|
44
|
+
* Scoped to the active workspace, and gated on `devices: write` rather than on
|
|
45
|
+
* `admin: true` like the rest of this module: arranging a list one's own
|
|
46
|
+
* workspace displays is not fleet management. Touches no agent state.
|
|
47
|
+
*/
|
|
48
|
+
export const deviceReorder = {
|
|
49
|
+
command: 'device.reorder' as const,
|
|
50
|
+
input: z.object({ ids: z.array(deviceId).min(1) }),
|
|
51
|
+
output: z.object({ ids: z.array(deviceId) })
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const deviceRename = {
|
|
55
|
+
command: 'device.rename' as const,
|
|
56
|
+
input: z.object({ deviceId, name: z.string().min(1).max(128) }),
|
|
57
|
+
output: z.object({ device: deviceSchema })
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Update a device's collection config. Every field is optional; only the
|
|
62
|
+
* provided ones change. `null` resets a field to the server default. Interval
|
|
63
|
+
* or capture changes are pushed live to a connected agent.
|
|
64
|
+
*/
|
|
65
|
+
export const deviceSetConfig = {
|
|
66
|
+
command: 'device.setConfig' as const,
|
|
67
|
+
input: z
|
|
68
|
+
.object({
|
|
69
|
+
deviceId,
|
|
70
|
+
/** Collection interval in seconds — metrics *and* processes (5s–1h). */
|
|
71
|
+
metricIntervalSeconds: z.number().int().min(5).max(3600).nullable().optional(),
|
|
72
|
+
processCapture: processCaptureSchema.nullable().optional(),
|
|
73
|
+
/** Conservation de l'historique — métriques, présence et processus. */
|
|
74
|
+
retentionDays: z.number().int().positive().max(3650).nullable().optional()
|
|
75
|
+
})
|
|
76
|
+
.refine(
|
|
77
|
+
(v) =>
|
|
78
|
+
v.metricIntervalSeconds !== undefined ||
|
|
79
|
+
v.processCapture !== undefined ||
|
|
80
|
+
v.retentionDays !== undefined,
|
|
81
|
+
{ message: 'No config field provided' }
|
|
82
|
+
),
|
|
83
|
+
output: z.object({ device: deviceSchema })
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/** Un espace candidat au partage d'un appareil, tel que l'affiche la popup. */
|
|
87
|
+
export const deviceShareTargetSchema = z.object({
|
|
88
|
+
id: z.number().int().positive(),
|
|
89
|
+
name: z.string(),
|
|
90
|
+
kind: workspaceKindSchema,
|
|
91
|
+
/** L'espace a-t-il accès à cet appareil ? */
|
|
92
|
+
shared: z.boolean()
|
|
93
|
+
});
|
|
94
|
+
export type DeviceShareTarget = z.infer<typeof deviceShareTargetSchema>;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Les espaces avec lesquels un appareil peut être partagé, et lesquels le sont.
|
|
98
|
+
*
|
|
99
|
+
* Réservé aux administrateurs : c'est la seule commande qui énumère des espaces
|
|
100
|
+
* dont l'appelant n'est pas membre, et elle n'existe que pour la page Appareils.
|
|
101
|
+
*/
|
|
102
|
+
export const deviceWorkspaceList = {
|
|
103
|
+
command: 'device.workspaceList' as const,
|
|
104
|
+
input: z.object({ deviceId }),
|
|
105
|
+
output: z.object({
|
|
106
|
+
/**
|
|
107
|
+
* Espace d'appairage : toujours partagé, jamais retirable. `null` si cet
|
|
108
|
+
* espace a été supprimé depuis — l'appareil n'a alors plus d'origine et
|
|
109
|
+
* tous ses partages sont révocables.
|
|
110
|
+
*/
|
|
111
|
+
originWorkspaceId: z.number().int().positive().nullable(),
|
|
112
|
+
workspaces: z.array(deviceShareTargetSchema)
|
|
113
|
+
})
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Fixe l'ensemble des espaces ayant accès à un appareil. La liste est complète :
|
|
118
|
+
* un espace absent perd l'accès. L'espace d'appairage est réintégré d'office.
|
|
119
|
+
*/
|
|
120
|
+
export const deviceSetWorkspaces = {
|
|
121
|
+
command: 'device.setWorkspaces' as const,
|
|
122
|
+
input: z.object({
|
|
123
|
+
deviceId,
|
|
124
|
+
workspaceIds: z.array(z.number().int().positive())
|
|
125
|
+
}),
|
|
126
|
+
output: z.object({ device: deviceSchema })
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/** Reactivate a revoked device, moving it back to `active`. */
|
|
130
|
+
export const deviceReactivate = {
|
|
131
|
+
command: 'device.reactivate' as const,
|
|
132
|
+
input: z.object({ deviceId }),
|
|
133
|
+
output: z.object({ device: deviceSchema })
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Push a self-update to a connected device's agent: the server resolves the newer
|
|
138
|
+
* signed binary for the device's build target and sends `agent.update`. Admin-only
|
|
139
|
+
* (Appareils page). Fails if the agent is offline, has no known target, the binary
|
|
140
|
+
* is missing/unsigned, or it's already up to date.
|
|
141
|
+
*/
|
|
142
|
+
export const deviceUpdateAgent = {
|
|
143
|
+
command: 'device.updateAgent' as const,
|
|
144
|
+
input: z.object({ deviceId }),
|
|
145
|
+
output: z.object({ device: deviceSchema })
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Enable/disable the agent's per-user autostart (survives reboot, no privilege).
|
|
150
|
+
* Pushes `agent.service` to the connected agent (`install-user`/`uninstall-user`).
|
|
151
|
+
*/
|
|
152
|
+
export const deviceSetAutostart = {
|
|
153
|
+
command: 'device.setAutostart' as const,
|
|
154
|
+
input: z.object({ deviceId, enabled: z.boolean() }),
|
|
155
|
+
output: z.object({ device: deviceSchema })
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Ask the agent to become a root/system service. Hybrid: the agent pops an OS auth
|
|
160
|
+
* prompt if it has an interactive session, else replies `needsManualCommand` and the
|
|
161
|
+
* UI shows `manualCommand` (always returned, deterministic per platform) to run on
|
|
162
|
+
* the device. The new privilege/scope is observed on the agent's next report.
|
|
163
|
+
*/
|
|
164
|
+
export const deviceElevate = {
|
|
165
|
+
command: 'device.elevate' as const,
|
|
166
|
+
input: z.object({ deviceId }),
|
|
167
|
+
output: z.object({ device: deviceSchema, manualCommand: z.string() })
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
/** Ask a root/system agent to drop back to a per-user service. */
|
|
171
|
+
export const deviceDropPrivileges = {
|
|
172
|
+
command: 'device.dropPrivileges' as const,
|
|
173
|
+
input: z.object({ deviceId }),
|
|
174
|
+
output: z.object({ device: deviceSchema, manualCommand: z.string() })
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Ask the agent to enumerate its package managers + pending updates. The result
|
|
179
|
+
* arrives asynchronously as a `package.list` push event (the caller must be
|
|
180
|
+
* subscribed to the device). The command itself only acknowledges the request.
|
|
181
|
+
*/
|
|
182
|
+
export const deviceListPackages = {
|
|
183
|
+
command: 'device.listPackages' as const,
|
|
184
|
+
input: z.object({ deviceId }),
|
|
185
|
+
output: z.object({ ok: z.boolean() })
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Apply all pending updates of one manager. Progress streams as `package.progress`
|
|
190
|
+
* events, ending with `package.done`. Fails if the agent is offline or the manager
|
|
191
|
+
* needs root and the agent isn't privileged (elevate it first — see device.elevate).
|
|
192
|
+
*/
|
|
193
|
+
export const deviceUpgradePackages = {
|
|
194
|
+
command: 'device.upgradePackages' as const,
|
|
195
|
+
input: z.object({ deviceId, manager: packageManagerIdSchema }),
|
|
196
|
+
output: z.object({ ok: z.boolean() })
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Run a system power action on the device (shutdown / reboot / suspend / hibernate
|
|
201
|
+
* / lock). Owner-or-admin; the agent must be online. The command only acknowledges
|
|
202
|
+
* the request — the agent applies it best-effort and the outcome streams back as a
|
|
203
|
+
* `device.powerResult` push event (the caller must be subscribed to the device).
|
|
204
|
+
*/
|
|
205
|
+
export const devicePower = {
|
|
206
|
+
command: 'device.power' as const,
|
|
207
|
+
input: z.object({ deviceId, action: agentPowerActionSchema }),
|
|
208
|
+
output: z.object({ ok: z.boolean() })
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Stop or cleanly restart the agent *process* on the device (not the machine).
|
|
213
|
+
* - `stop`: the agent exits. With autostart (supervised service) the manager
|
|
214
|
+
* relaunches it within seconds; standalone, the device stays offline — and
|
|
215
|
+
* unmanageable remotely — until someone relaunches it on the machine.
|
|
216
|
+
* - `restart`: exit-and-relaunch (manager or self-respawn), e.g. to pick up a
|
|
217
|
+
* clean state.
|
|
218
|
+
* Owner-or-admin; the agent must be online. Fire-and-forget: the command only
|
|
219
|
+
* acknowledges the push — the outcome is observed through presence.
|
|
220
|
+
*/
|
|
221
|
+
export const deviceAgentLifecycle = {
|
|
222
|
+
command: 'device.agentLifecycle' as const,
|
|
223
|
+
input: z.object({ deviceId, action: agentLifecycleActionSchema }),
|
|
224
|
+
output: z.object({ ok: z.boolean() })
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Request a managed deletion (from the Appareils page). The device moves to
|
|
229
|
+
* `pending_deletion`: on its next connection the agent is told to self-destruct
|
|
230
|
+
* (wipe its local config + binary), after which the device is archived — its
|
|
231
|
+
* monitoring history is kept and stays browsable, but it's gone from management.
|
|
232
|
+
* If the agent is online the destroy signal is sent immediately.
|
|
233
|
+
*/
|
|
234
|
+
export const deviceRequestDelete = {
|
|
235
|
+
command: 'device.requestDelete' as const,
|
|
236
|
+
input: z.object({ deviceId }),
|
|
237
|
+
output: z.object({ device: deviceSchema })
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
/** Cancel a `pending_deletion` (only effective while the agent hasn't reconnected). */
|
|
241
|
+
export const deviceCancelDelete = {
|
|
242
|
+
command: 'device.cancelDelete' as const,
|
|
243
|
+
input: z.object({ deviceId }),
|
|
244
|
+
output: z.object({ device: deviceSchema })
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Finalise a deletion immediately: archive the device now without waiting for the
|
|
249
|
+
* agent to self-destruct (use when the agent is gone, or you don't care if it
|
|
250
|
+
* cleans itself up). A still-connected agent is told to self-destruct best-effort,
|
|
251
|
+
* but the device is archived regardless; if it ever reconnects it's refused.
|
|
252
|
+
*/
|
|
253
|
+
export const deviceForceDelete = {
|
|
254
|
+
command: 'device.forceDelete' as const,
|
|
255
|
+
input: z.object({ deviceId }),
|
|
256
|
+
output: z.object({ device: deviceSchema })
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Hard-purge a device and ALL its monitoring history (used by the Monitoring
|
|
261
|
+
* page to remove an archived — or any — device and reset its data). Works
|
|
262
|
+
* whether the agent is online or not; it does not self-destruct the agent.
|
|
263
|
+
*/
|
|
264
|
+
export const deviceDelete = {
|
|
265
|
+
command: 'device.delete' as const,
|
|
266
|
+
input: z.object({ deviceId }),
|
|
267
|
+
output: z.object({ deviceId })
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
export const deviceCommands = [
|
|
271
|
+
deviceList,
|
|
272
|
+
deviceConfirm,
|
|
273
|
+
deviceRevoke,
|
|
274
|
+
deviceReactivate,
|
|
275
|
+
deviceRename,
|
|
276
|
+
deviceReorder,
|
|
277
|
+
deviceSetConfig,
|
|
278
|
+
deviceWorkspaceList,
|
|
279
|
+
deviceSetWorkspaces,
|
|
280
|
+
deviceUpdateAgent,
|
|
281
|
+
deviceSetAutostart,
|
|
282
|
+
deviceElevate,
|
|
283
|
+
deviceDropPrivileges,
|
|
284
|
+
deviceListPackages,
|
|
285
|
+
deviceUpgradePackages,
|
|
286
|
+
devicePower,
|
|
287
|
+
deviceAgentLifecycle,
|
|
288
|
+
deviceRequestDelete,
|
|
289
|
+
deviceCancelDelete,
|
|
290
|
+
deviceForceDelete,
|
|
291
|
+
deviceDelete
|
|
292
|
+
] as const;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { fileMutateOpSchema, fileSearchFilterSchema } from '../domain/deviceFiles';
|
|
3
|
+
|
|
4
|
+
const deviceId = z.uuid();
|
|
5
|
+
/** Correlates a request to its streamed result (results carry no requestId). */
|
|
6
|
+
const opId = z.string().min(1).max(64);
|
|
7
|
+
const path = z.string().min(1).max(4096);
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* List a directory. Owner-or-admin + agent online. The listing arrives as a
|
|
11
|
+
* `device.filesListing` push event keyed by `opId` (the caller must be subscribed).
|
|
12
|
+
*/
|
|
13
|
+
export const deviceFilesList = {
|
|
14
|
+
command: 'device.filesList' as const,
|
|
15
|
+
input: z.object({ deviceId, opId, path }),
|
|
16
|
+
output: z.object({ ok: z.boolean() })
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Analyse a directory's recursive disk usage (ncdu-style): the total size of each
|
|
21
|
+
* immediate child. Result arrives as a `device.filesUsage` push event.
|
|
22
|
+
*/
|
|
23
|
+
export const deviceFilesAnalyze = {
|
|
24
|
+
command: 'device.filesAnalyze' as const,
|
|
25
|
+
input: z.object({ deviceId, opId, path }),
|
|
26
|
+
output: z.object({ ok: z.boolean() })
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Recursively search a directory with an advanced filter (name/extension/content,
|
|
31
|
+
* date & size windows). Matches arrive as a `device.filesMatches` push event.
|
|
32
|
+
*/
|
|
33
|
+
export const deviceFilesSearch = {
|
|
34
|
+
command: 'device.filesSearch' as const,
|
|
35
|
+
input: z.object({ deviceId, opId, path, filter: fileSearchFilterSchema }),
|
|
36
|
+
output: z.object({ ok: z.boolean() })
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Mutate the filesystem: `delete` (file or directory, recursive), `mkdir`, or
|
|
41
|
+
* `rename` (needs `dest`). The outcome arrives as a `device.filesOp` push event.
|
|
42
|
+
*/
|
|
43
|
+
export const deviceFilesMutate = {
|
|
44
|
+
command: 'device.filesMutate' as const,
|
|
45
|
+
input: z.object({ deviceId, opId, op: fileMutateOpSchema, path, dest: path.optional() }),
|
|
46
|
+
output: z.object({ ok: z.boolean() })
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Download a file. Bytes stream back as `device.filesChunk` push events keyed by
|
|
51
|
+
* `opId` (base64, the last with `done: true`); the client reassembles them.
|
|
52
|
+
*/
|
|
53
|
+
export const deviceFilesDownload = {
|
|
54
|
+
command: 'device.filesDownload' as const,
|
|
55
|
+
input: z.object({ deviceId, opId, path }),
|
|
56
|
+
output: z.object({ ok: z.boolean() })
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Upload one chunk of a file at `offset` (0 truncates/creates it). The completion
|
|
61
|
+
* (on `done`) arrives as a `device.filesOp` push event (op `upload`).
|
|
62
|
+
*/
|
|
63
|
+
export const deviceFilesUpload = {
|
|
64
|
+
command: 'device.filesUpload' as const,
|
|
65
|
+
input: z.object({
|
|
66
|
+
deviceId,
|
|
67
|
+
opId,
|
|
68
|
+
path,
|
|
69
|
+
offset: z.number().int().nonnegative(),
|
|
70
|
+
data: z.string().max(1_400_000),
|
|
71
|
+
done: z.boolean()
|
|
72
|
+
}),
|
|
73
|
+
output: z.object({ ok: z.boolean() })
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const deviceFilesCommands = [
|
|
77
|
+
deviceFilesList,
|
|
78
|
+
deviceFilesAnalyze,
|
|
79
|
+
deviceFilesSearch,
|
|
80
|
+
deviceFilesMutate,
|
|
81
|
+
deviceFilesDownload,
|
|
82
|
+
deviceFilesUpload
|
|
83
|
+
] as const;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { deviceLogFilterSchema, DEVICE_LOG_PAGE_MAX } from '../domain/deviceLogs';
|
|
3
|
+
|
|
4
|
+
const deviceId = z.uuid();
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Ask the agent to enumerate the log sources present on the device (system journal,
|
|
8
|
+
* Docker containers, log files…). Owner-or-admin + agent online. The command only
|
|
9
|
+
* acknowledges; the list arrives as a `device.logSources` push event (the caller
|
|
10
|
+
* must be subscribed to the device).
|
|
11
|
+
*/
|
|
12
|
+
export const deviceLogSources = {
|
|
13
|
+
command: 'device.logSources' as const,
|
|
14
|
+
input: z.object({ deviceId }),
|
|
15
|
+
output: z.object({ ok: z.boolean() })
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Query one source with an advanced filter. `queryId` correlates the streamed
|
|
20
|
+
* result back to this request (results have no requestId). Lines arrive as one or
|
|
21
|
+
* more `device.logLines` push events, the last carrying `done: true`.
|
|
22
|
+
*/
|
|
23
|
+
export const deviceLogQuery = {
|
|
24
|
+
command: 'device.logQuery' as const,
|
|
25
|
+
input: z.object({
|
|
26
|
+
deviceId,
|
|
27
|
+
sourceId: z.string().min(1).max(512),
|
|
28
|
+
/** Client-generated id echoed back on every `device.logLines` for this query. */
|
|
29
|
+
queryId: z.string().min(1).max(64),
|
|
30
|
+
filter: deviceLogFilterSchema.optional(),
|
|
31
|
+
limit: z.number().int().positive().max(DEVICE_LOG_PAGE_MAX).optional()
|
|
32
|
+
}),
|
|
33
|
+
output: z.object({ ok: z.boolean() })
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const deviceLogCommands = [deviceLogSources, deviceLogQuery] as const;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
const deviceId = z.uuid();
|
|
4
|
+
const sessionId = z.string().min(1).max(64);
|
|
5
|
+
const cols = z.number().int().min(1).max(2000);
|
|
6
|
+
const rows = z.number().int().min(1).max(2000);
|
|
7
|
+
/** Base64-encoded terminal bytes, capped per frame (~1.5 MB). */
|
|
8
|
+
const data = z.string().max(2_000_000);
|
|
9
|
+
/**
|
|
10
|
+
* Optional OS account to open the session under. Restricted to safe username
|
|
11
|
+
* characters (no shell metacharacters), since it reaches a `su` on the device.
|
|
12
|
+
*/
|
|
13
|
+
export const terminalUser = z
|
|
14
|
+
.string()
|
|
15
|
+
.regex(/^[A-Za-z0-9._-]+$/, 'Nom d’utilisateur invalide')
|
|
16
|
+
.max(32);
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Open an interactive terminal (PTY) on the device. Owner-or-admin + agent online.
|
|
20
|
+
* `sessionId` is client-generated and ties every later input/resize/close and the
|
|
21
|
+
* streamed `device.termOutput` / `device.termExit` push events together (the caller
|
|
22
|
+
* must be subscribed). `user` runs the shell under that account (`su -l`); omitted
|
|
23
|
+
* → the account the agent itself runs as.
|
|
24
|
+
*/
|
|
25
|
+
export const deviceTermOpen = {
|
|
26
|
+
command: 'device.termOpen' as const,
|
|
27
|
+
input: z.object({ deviceId, sessionId, cols, rows, user: terminalUser.optional() }),
|
|
28
|
+
output: z.object({ ok: z.boolean() })
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/** Send input (keystrokes / paste) to a terminal session. `data` is base64 bytes. */
|
|
32
|
+
export const deviceTermInput = {
|
|
33
|
+
command: 'device.termInput' as const,
|
|
34
|
+
input: z.object({ deviceId, sessionId, data }),
|
|
35
|
+
output: z.object({ ok: z.boolean() })
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/** Resize a terminal session's PTY to match the client viewport. */
|
|
39
|
+
export const deviceTermResize = {
|
|
40
|
+
command: 'device.termResize' as const,
|
|
41
|
+
input: z.object({ deviceId, sessionId, cols, rows }),
|
|
42
|
+
output: z.object({ ok: z.boolean() })
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/** Close a terminal session (kills the shell and frees the PTY). */
|
|
46
|
+
export const deviceTermClose = {
|
|
47
|
+
command: 'device.termClose' as const,
|
|
48
|
+
input: z.object({ deviceId, sessionId }),
|
|
49
|
+
output: z.object({ ok: z.boolean() })
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const deviceTerminalCommands = [
|
|
53
|
+
deviceTermOpen,
|
|
54
|
+
deviceTermInput,
|
|
55
|
+
deviceTermResize,
|
|
56
|
+
deviceTermClose
|
|
57
|
+
] as const;
|