@deveye/types 0.15.2 → 0.16.1

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.
Files changed (73) hide show
  1. package/package.json +6 -6
  2. package/src/domain/device.ts +4 -29
  3. package/src/domain/featureRegistry.ts +40 -108
  4. package/src/domain/home.ts +40 -101
  5. package/src/domain/live.ts +36 -87
  6. package/src/domain/metrics.ts +10 -14
  7. package/src/domain/notifications.ts +39 -110
  8. package/src/domain/project.ts +3 -162
  9. package/src/domain/report.ts +54 -95
  10. package/src/domain/secrecy.ts +3 -5
  11. package/src/domain/sharing.ts +33 -70
  12. package/src/domain/syncProtocol.ts +5 -12
  13. package/src/domain/user.ts +8 -14
  14. package/src/domain/workspace.ts +0 -3
  15. package/src/domain/workspaceRole.ts +34 -82
  16. package/src/features/agent.ts +306 -0
  17. package/src/features/live.ts +17 -37
  18. package/src/features/notify.ts +19 -57
  19. package/src/features/registry.ts +7 -44
  20. package/src/features/secrecy.ts +4 -9
  21. package/src/features/sharing.ts +12 -26
  22. package/src/features/user.ts +6 -11
  23. package/src/features/workspace.ts +6 -11
  24. package/src/http/auth.ts +6 -13
  25. package/src/http/device.ts +13 -17
  26. package/src/http/status.ts +6 -10
  27. package/src/index.ts +29 -932
  28. package/src/protocol/agent.ts +40 -70
  29. package/src/protocol/envelope.ts +3 -10
  30. package/src/sdk/client-ambient.d.ts +228 -21
  31. package/src/sdk/client.ts +277 -17
  32. package/src/sdk/devb.ts +120 -0
  33. package/src/sdk/manifest.test.ts +0 -1
  34. package/src/sdk/manifest.ts +94 -25
  35. package/src/sdk/providers.ts +310 -5
  36. package/src/sdk/server.ts +483 -19
  37. package/src/sdk/testing.test.ts +2 -2
  38. package/src/sdk/testing.ts +302 -26
  39. package/src/utils/version.ts +5 -8
  40. package/src/domain/audience.ts +0 -549
  41. package/src/domain/backup.ts +0 -355
  42. package/src/domain/credential.ts +0 -55
  43. package/src/domain/database.ts +0 -467
  44. package/src/domain/deploy.ts +0 -231
  45. package/src/domain/finance.ts +0 -477
  46. package/src/domain/git.ts +0 -419
  47. package/src/domain/mail.ts +0 -394
  48. package/src/domain/note.ts +0 -202
  49. package/src/domain/password.ts +0 -36
  50. package/src/domain/projectBoard.ts +0 -130
  51. package/src/domain/projectChat.ts +0 -46
  52. package/src/domain/projectHistory.ts +0 -82
  53. package/src/domain/projectLink.ts +0 -87
  54. package/src/domain/projectPlan.ts +0 -68
  55. package/src/domain/sentinel.ts +0 -623
  56. package/src/domain/uptime.ts +0 -216
  57. package/src/features/audience.ts +0 -275
  58. package/src/features/backup.ts +0 -230
  59. package/src/features/database.ts +0 -461
  60. package/src/features/deploy.ts +0 -245
  61. package/src/features/device.ts +0 -292
  62. package/src/features/deviceFiles.ts +0 -83
  63. package/src/features/deviceLogs.ts +0 -36
  64. package/src/features/deviceTerminal.ts +0 -57
  65. package/src/features/finance.ts +0 -360
  66. package/src/features/git.ts +0 -368
  67. package/src/features/mail.ts +0 -374
  68. package/src/features/metrics.ts +0 -185
  69. package/src/features/note.ts +0 -189
  70. package/src/features/password.ts +0 -67
  71. package/src/features/project.ts +0 -709
  72. package/src/features/sentinel.ts +0 -233
  73. package/src/features/uptime.ts +0 -186
@@ -1,12 +1,14 @@
1
1
  /**
2
- * Provider contracts: the inversion for PUBLIC app code that needs a MODULE's
3
- * data.
2
+ * Provider contracts: the inversion for code that needs a MODULE's data,
3
+ * whether it is the app or another module.
4
4
  *
5
5
  * A module exposes named contracts on its service (`FeatureService.providers`);
6
6
  * the app looks them up at call time (`moduleProvider(key)` in its SDK
7
- * assembly) and degrades cleanly when the module is absent. The contract types
8
- * live here, in the published package, because both sides must agree on them
9
- * while neither may import the other.
7
+ * assembly, `ctx.providers.get(key)` from a module) and degrades cleanly when
8
+ * the module is absent. The contract types live here, in the published
9
+ * package, because both sides must agree on them while neither may import the
10
+ * other. Every provider is offered by a module's service: the app offers none
11
+ * itself.
10
12
  */
11
13
 
12
14
  /** Key under `FeatureService.providers` for the CloudSync backup source. */
@@ -46,3 +48,306 @@ export interface CloudSyncBackupProvider {
46
48
  /** Decrypted plaintext stream of one blob. */
47
49
  openBlob(shareId: number, hash: string): Promise<AsyncIterable<Uint8Array>>;
48
50
  }
51
+
52
+ /**
53
+ * Key of the database access the Backup module consumes: a logical dump goes
54
+ * through the SAME access as the monitoring (SSH tunnel or SOCKS proxy
55
+ * included), and only the Databases feature knows how to decrypt a connection.
56
+ */
57
+ export const DATABASE_BACKUP_PROVIDER = 'database.backup' as const;
58
+
59
+ /** A database of the workspace, as the source picker lists it. */
60
+ export interface DatabaseBackupCandidate {
61
+ id: number;
62
+ name: string;
63
+ engine: 'mysql' | 'postgres';
64
+ host: string;
65
+ database: string;
66
+ }
67
+
68
+ /**
69
+ * An OPEN access to a database: what a dump tool needs, reachable from the
70
+ * server (the tunnel's local listener when there is one). `close()` releases
71
+ * the tunnel; call it whatever happens, a forgotten tunnel keeps an SSH
72
+ * session and a listener alive.
73
+ */
74
+ export interface DatabaseBackupAccess {
75
+ engine: 'mysql' | 'postgres';
76
+ host: string;
77
+ port: number;
78
+ database: string;
79
+ username: string;
80
+ password: string | null;
81
+ close(): Promise<void>;
82
+ }
83
+
84
+ export interface DatabaseBackupProvider {
85
+ /** The databases of the workspace, its own only (a projection is not a source). */
86
+ listDatabases(workspaceId: number): Promise<readonly DatabaseBackupCandidate[]>;
87
+ findDatabase(databaseId: number, workspaceId: number): Promise<DatabaseBackupCandidate | null>;
88
+ /** null when the database is unknown to this workspace. */
89
+ openAccess(databaseId: number, workspaceId: number): Promise<DatabaseBackupAccess | null>;
90
+ }
91
+
92
+ /**
93
+ * Key under `FeatureService.providers` for the Databases items the Projects
94
+ * feature links to: same shape and reason as `UPTIME_ITEMS_PROVIDER`
95
+ * (`project_database_links` is Projects' table).
96
+ */
97
+ export const DATABASE_ITEMS_PROVIDER = 'database.items' as const;
98
+
99
+ export interface DatabaseItemsProvider {
100
+ /** Does this database live in this workspace? Its home only, never a projection. */
101
+ exists(databaseId: number, workspaceId: number): Promise<boolean>;
102
+ /**
103
+ * The item's display name under the OPEN cipher of `workspaceId`, its home;
104
+ * `null` when it is gone or unreadable. What a window onto a projected
105
+ * project shows for a link it cannot open: a name, never an id.
106
+ */
107
+ labelOf(databaseId: number, workspaceId: number): Promise<string | null>;
108
+ }
109
+
110
+ /**
111
+ * Key under `FeatureService.providers` for the workspace's outgoing mail: the
112
+ * transport the app's notification channels of kind `email` send through.
113
+ * Offered by the Mail module; absent, an email channel cannot be readied and
114
+ * the settings screen says so. Senders are the module's OPEN-tier, enabled
115
+ * accounts: a guarded mailbox needs a session unlock no background job has.
116
+ */
117
+ export const MAIL_TRANSPORT_PROVIDER = 'mail.transport' as const;
118
+
119
+ /** A mailbox able to send without anyone unlocking anything. */
120
+ export interface MailSender {
121
+ id: number;
122
+ label: string;
123
+ address: string;
124
+ }
125
+
126
+ export interface MailTransportProvider {
127
+ /** The workspace's ready senders (open tier, enabled). */
128
+ listSenders(workspaceId: number): Promise<readonly MailSender[]>;
129
+ /** Is this account a ready sender of this workspace right now? */
130
+ isReady(accountId: number, workspaceId: number): Promise<boolean>;
131
+ /**
132
+ * Sends one plain-text message from this account. Resolves `true` when the
133
+ * provider accepted it; `false` (never a throw) when the account is not a
134
+ * ready sender or the send failed, the failure logged by the module.
135
+ */
136
+ send(
137
+ accountId: number,
138
+ workspaceId: number,
139
+ message: { to: string; subject: string; text: string }
140
+ ): Promise<boolean>;
141
+ }
142
+
143
+ /**
144
+ * Key under `FeatureClient.providers` for the Mail pieces the app's settings
145
+ * shell composes: the ready senders an email channel picks from, and the
146
+ * feature's own account dialog (the "+" of the channel form). The contract
147
+ * types live in `@deveye/types/sdk/client`.
148
+ */
149
+ export const MAIL_CLIENT_PROVIDER = 'mail.client' as const;
150
+
151
+ /**
152
+ * Key under `FeatureService.providers` for the Audience sites the app's
153
+ * Projects feature links to: same shape and same reason as
154
+ * `UPTIME_ITEMS_PROVIDER` (`project_audience_links` is Projects' table).
155
+ */
156
+ export const AUDIENCE_ITEMS_PROVIDER = 'audience.items' as const;
157
+
158
+ export interface AudienceItemsProvider {
159
+ /** Does this site live in this workspace? Its home only, never a projection. */
160
+ exists(siteId: number, workspaceId: number): Promise<boolean>;
161
+ /**
162
+ * The item's display name under the OPEN cipher of `workspaceId`, its home;
163
+ * `null` when it is gone or unreadable. What a window onto a projected
164
+ * project shows for a link it cannot open: a name, never an id.
165
+ */
166
+ labelOf(siteId: number, workspaceId: number): Promise<string | null>;
167
+ }
168
+
169
+ /**
170
+ * Key under `FeatureClient.providers` for the Audience pieces the app's
171
+ * Projects screens compose: the list of the workspace's sites, a linked site
172
+ * shown in full inside a project's tab, and the feature's own site dialog.
173
+ * The contract types live in `@deveye/types/sdk/client`.
174
+ */
175
+ export const AUDIENCE_CLIENT_PROVIDER = 'audience.client' as const;
176
+
177
+ /**
178
+ * Key under `FeatureService.providers` for the Git repositories the app's
179
+ * Projects feature links to: same shape and same reason as
180
+ * `UPTIME_ITEMS_PROVIDER` (`project_repo_links` is Projects' table).
181
+ */
182
+ export const GIT_ITEMS_PROVIDER = 'git.items' as const;
183
+
184
+ export interface GitItemsProvider {
185
+ /** Does this repository live in this workspace? Its home only, never a projection. */
186
+ exists(repoId: number, workspaceId: number): Promise<boolean>;
187
+ /**
188
+ * The item's display name under the OPEN cipher of `workspaceId`, its home;
189
+ * `null` when it is gone or unreadable. What a window onto a projected
190
+ * project shows for a link it cannot open: a name, never an id.
191
+ */
192
+ labelOf(repoId: number, workspaceId: number): Promise<string | null>;
193
+ }
194
+
195
+ /**
196
+ * Key under `FeatureClient.providers` for the Git pieces the app's Projects
197
+ * screens compose: the list of the workspace's repositories, a linked
198
+ * repository shown in full inside a project's tab, and the feature's own
199
+ * repository dialog. The contract types live in `@deveye/types/sdk/client`.
200
+ */
201
+ export const GIT_CLIENT_PROVIDER = 'git.client' as const;
202
+
203
+ /**
204
+ * Key under `FeatureService.providers` for the Deploy targets the app's
205
+ * Projects feature links to: same shape and same reason as
206
+ * `UPTIME_ITEMS_PROVIDER` (`project_deploy_links` is Projects' table).
207
+ */
208
+ export const DEPLOY_ITEMS_PROVIDER = 'deploy.items' as const;
209
+
210
+ export interface DeployItemsProvider {
211
+ /** Does this target live in this workspace? Its home only, never a projection. */
212
+ exists(targetId: number, workspaceId: number): Promise<boolean>;
213
+ /**
214
+ * The item's display name under the OPEN cipher of `workspaceId`, its home;
215
+ * `null` when it is gone or unreadable. What a window onto a projected
216
+ * project shows for a link it cannot open: a name, never an id.
217
+ */
218
+ labelOf(targetId: number, workspaceId: number): Promise<string | null>;
219
+ }
220
+
221
+ /**
222
+ * Key under `FeatureClient.providers` for the Deploy pieces the app's
223
+ * Projects screens compose: the list of the workspace's targets, a linked
224
+ * target shown in full inside a project's tab, and the feature's own target
225
+ * dialog. The contract types live in `@deveye/types/sdk/client`.
226
+ */
227
+ export const DEPLOY_CLIENT_PROVIDER = 'deploy.client' as const;
228
+
229
+ /**
230
+ * Key under `FeatureClient.providers` for the Databases pieces the app's
231
+ * Projects screens compose: the list of the workspace's databases, a linked
232
+ * database shown in full inside a project's tab, and the feature's own
233
+ * database dialog (declaring a database from a project goes through the real
234
+ * form, never a reduced copy). The contract types live in
235
+ * `@deveye/types/sdk/client` (they are React components).
236
+ */
237
+ export const DATABASE_CLIENT_PROVIDER = 'database.client' as const;
238
+
239
+ /**
240
+ * Key of what Projects knows about the items of OTHER features: the projects
241
+ * of the workspace that link them (a module's list shows how many projects use
242
+ * each item, its detail lists them by title), without reading Projects'
243
+ * tables. Keyed by the linked feature's id so every linkable feature reads the
244
+ * same contract.
245
+ */
246
+ export const PROJECTS_USAGE_PROVIDER = 'projects.usage' as const;
247
+
248
+ /**
249
+ * A project that links an item. Open tier only: a guarded project cannot link
250
+ * a workspace item (its link row is plain, the item lives at the open tier),
251
+ * so every title here is readable without a session.
252
+ */
253
+ export interface ProjectUsage {
254
+ projectId: number;
255
+ title: string;
256
+ status: 'draft' | 'active' | 'paused' | 'done';
257
+ }
258
+
259
+ export interface ProjectsUsageProvider {
260
+ /** The workspace's projects linking this item of this feature, in Projects' display order. */
261
+ usageOf(feature: string, itemId: number, workspaceId: number): Promise<readonly ProjectUsage[]>;
262
+ /** How many projects of the workspace link each item of this feature (absent = zero). */
263
+ countByItem(feature: string, workspaceId: number): Promise<ReadonlyMap<number, number>>;
264
+ /**
265
+ * Writes one line in a project's timeline (a deployment triggered from a
266
+ * project's tab). Open tier only: an event aimed at a guarded project is
267
+ * dropped silently. Rejects when the write fails; a lost timeline line
268
+ * never turns a deployment into an error.
269
+ */
270
+ recordEvent(
271
+ projectId: number,
272
+ workspaceId: number,
273
+ event: { kind: string; label: string; actorUserId: number | null }
274
+ ): Promise<void>;
275
+ /**
276
+ * Reports a version on the projects linking this item that asked to
277
+ * follow it (Projects' `versionSource`, `'github_release'` for a git
278
+ * repository): the field then belongs to the item, and the project's
279
+ * screen shows it read-only. All linked projects of the workspace, open
280
+ * tier only; the others are left untouched.
281
+ */
282
+ applyVersion(
283
+ feature: string,
284
+ itemId: number,
285
+ workspaceId: number,
286
+ version: string
287
+ ): Promise<void>;
288
+ }
289
+
290
+ /**
291
+ * Key under `FeatureService.providers` for the Uptime items the app's Projects
292
+ * feature links to. Projects stores only identifiers; before linking one it
293
+ * asks the module whether the service exists in the workspace, so a foreign
294
+ * id can neither be linked nor leak its existence.
295
+ */
296
+ export const UPTIME_ITEMS_PROVIDER = 'uptime.items' as const;
297
+
298
+ export interface UptimeItemsProvider {
299
+ /** Does this service live in this workspace? Its home only, never a projection. */
300
+ exists(serviceId: number, workspaceId: number): Promise<boolean>;
301
+ /**
302
+ * The item's display name under the OPEN cipher of `workspaceId`, its home;
303
+ * `null` when it is gone or unreadable. What a window onto a projected
304
+ * project shows for a link it cannot open: a name, never an id.
305
+ */
306
+ labelOf(serviceId: number, workspaceId: number): Promise<string | null>;
307
+ }
308
+
309
+ /**
310
+ * Key under `FeatureClient.providers` for the Uptime pieces the app's Projects
311
+ * screens compose: the availability strip and ratios of a linked service, and
312
+ * the feature's own service dialog (declaring a service from a project goes
313
+ * through the real form, never a reduced copy). The contract types live in
314
+ * `@deveye/types/sdk/client` (they are React components).
315
+ */
316
+ export const UPTIME_CLIENT_PROVIDER = 'uptime.client' as const;
317
+
318
+ /**
319
+ * The client twin of the Devices module (`DevicesClientProvider`,
320
+ * `sdk/client.ts`): the workspace's devices as a store, one device's panel
321
+ * and tile. The app's home and topbar compose them; without the module they
322
+ * render nothing device-related.
323
+ */
324
+ export const DEVICES_CLIENT_PROVIDER = 'devices.client' as const;
325
+
326
+ /**
327
+ * Key under `FeatureService.providers` for what Sentinel contributes to the
328
+ * collection config the app pushes to an agent (`agent.config`): whether the
329
+ * security probes run, and at which cadence. Absent module: the app pushes the
330
+ * probes off.
331
+ */
332
+ export const SENTINEL_AGENT_CONFIG_PROVIDER = 'sentinel.agentConfig' as const;
333
+
334
+ /**
335
+ * Cadence du manifeste de persistance quand rien n'est réglé, en minutes.
336
+ * Vit ici et non dans le domaine du module parce que l'app l'applique
337
+ * elle-même : sans module installé, ou sans ligne de config pour l'appareil,
338
+ * la config poussée à l'agent porte ce défaut (sondes éteintes).
339
+ */
340
+ export const DEFAULT_SENTINEL_INTEGRITY_MINUTES = 360;
341
+
342
+ export interface SentinelAgentConfig {
343
+ enabled: boolean;
344
+ /** Cadence of the persistence manifest, in minutes. */
345
+ integrityMinutes: number;
346
+ /** Whether the agent reads the authentication journal. */
347
+ authEvents: boolean;
348
+ }
349
+
350
+ export interface SentinelAgentConfigProvider {
351
+ /** The device's contribution, or null when Sentinel knows nothing about it (probes off). */
352
+ configFor(deviceId: string): Promise<SentinelAgentConfig | null>;
353
+ }