borgmcp-server 0.1.1 → 0.1.5

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 (61) hide show
  1. package/README.md +70 -22
  2. package/THIRD_PARTY_NOTICES.md +1 -0
  3. package/dist/cli.js +62 -11
  4. package/dist/cli.js.map +1 -1
  5. package/dist/coordination-api.d.ts +3 -1
  6. package/dist/coordination-api.js +476 -78
  7. package/dist/coordination-api.js.map +1 -1
  8. package/dist/credentials.d.ts +13 -7
  9. package/dist/credentials.js +77 -15
  10. package/dist/credentials.js.map +1 -1
  11. package/dist/debug-log.d.ts +76 -0
  12. package/dist/debug-log.js +124 -0
  13. package/dist/debug-log.js.map +1 -0
  14. package/dist/enrollment.d.ts +3 -11
  15. package/dist/enrollment.js +21 -60
  16. package/dist/enrollment.js.map +1 -1
  17. package/dist/https-server.d.ts +5 -20
  18. package/dist/https-server.js +108 -50
  19. package/dist/https-server.js.map +1 -1
  20. package/dist/index.d.ts +1 -1
  21. package/dist/message-taxonomy.d.ts +38 -0
  22. package/dist/message-taxonomy.js +218 -0
  23. package/dist/message-taxonomy.js.map +1 -0
  24. package/dist/migrations.d.ts +4 -0
  25. package/dist/migrations.js +99 -0
  26. package/dist/migrations.js.map +1 -1
  27. package/dist/operator-error.d.ts +2 -1
  28. package/dist/operator-error.js +23 -5
  29. package/dist/operator-error.js.map +1 -1
  30. package/dist/role-section.d.ts +14 -0
  31. package/dist/role-section.js +87 -0
  32. package/dist/role-section.js.map +1 -0
  33. package/dist/service.d.ts +14 -4
  34. package/dist/service.js +243 -25
  35. package/dist/service.js.map +1 -1
  36. package/dist/start-options.d.ts +5 -1
  37. package/dist/start-options.js +17 -3
  38. package/dist/start-options.js.map +1 -1
  39. package/dist/store.d.ts +106 -8
  40. package/dist/store.js +772 -120
  41. package/dist/store.js.map +1 -1
  42. package/npm-shrinkwrap.json +6 -7
  43. package/package.json +2 -2
  44. package/src/cli.ts +61 -11
  45. package/src/coordination-api.ts +490 -72
  46. package/src/credentials.ts +103 -19
  47. package/src/debug-log.ts +165 -0
  48. package/src/enrollment.ts +32 -78
  49. package/src/https-server.ts +113 -78
  50. package/src/index.ts +1 -1
  51. package/src/message-taxonomy.ts +284 -0
  52. package/src/migrations.ts +102 -0
  53. package/src/operator-error.ts +40 -6
  54. package/src/role-section.ts +108 -0
  55. package/src/service.ts +268 -27
  56. package/src/start-options.ts +21 -4
  57. package/src/store.ts +887 -142
  58. package/dist/protocol-draft.d.ts +0 -2
  59. package/dist/protocol-draft.js +0 -31
  60. package/dist/protocol-draft.js.map +0 -1
  61. package/src/protocol-draft.ts +0 -32
package/dist/store.d.ts CHANGED
@@ -1,10 +1,13 @@
1
+ import type { MessageTaxonomy } from "borgmcp-shared/domain";
1
2
  import { type Principal } from "./principal.js";
3
+ import { type RoleSectionPatchOp } from "./role-section.js";
2
4
  export type CubeAccess = "read" | "write" | "manage";
3
5
  export interface CubeRecord {
4
6
  readonly id: string;
5
7
  readonly ownerId: string;
6
8
  readonly name: string;
7
9
  readonly directive: string;
10
+ readonly messageTaxonomy: MessageTaxonomy | null;
8
11
  readonly createdAt: string;
9
12
  readonly updatedAt: string;
10
13
  }
@@ -32,6 +35,19 @@ export interface EnrichedActivityRecord {
32
35
  readonly role_name: string | null;
33
36
  readonly recipient_drone_ids: string[];
34
37
  }
38
+ export type ActivityNotificationRecord = EnrichedActivityRecord & ({
39
+ readonly kind: "ack" | "claim";
40
+ readonly log_entry_id: string;
41
+ readonly ack_kind: "ack" | "claim";
42
+ readonly ack_at: string;
43
+ readonly entry_preview: string;
44
+ readonly author_drone_id?: string;
45
+ readonly claimant_drone_id?: string;
46
+ readonly claimant_role?: string | null;
47
+ } | {
48
+ readonly kind: "heartbeat_ping";
49
+ });
50
+ export type ActivityStreamRecord = EnrichedActivityRecord | ActivityNotificationRecord;
35
51
  export interface ClaimRecord {
36
52
  readonly log_entry_id: string;
37
53
  readonly claimant_drone_id: string;
@@ -63,8 +79,12 @@ export interface RoleRecord {
63
79
  readonly cube_id: string;
64
80
  readonly name: string;
65
81
  readonly short_description: string;
82
+ readonly detailed_description: string;
66
83
  readonly is_default: boolean;
84
+ readonly is_mandatory: boolean;
67
85
  readonly is_human_seat: boolean;
86
+ readonly can_broadcast: boolean;
87
+ readonly receives_all_direct: boolean;
68
88
  readonly role_class: "queen" | "worker";
69
89
  readonly created_at: string;
70
90
  }
@@ -75,7 +95,10 @@ export interface DroneRecord {
75
95
  readonly label: string;
76
96
  readonly last_seen: string;
77
97
  readonly hostname: string | null;
98
+ readonly posture: "observer" | "participant";
78
99
  readonly created_at: string;
100
+ readonly last_log_post_at?: string | null;
101
+ readonly seen_since?: boolean;
79
102
  }
80
103
  export interface StoreDiagnostics {
81
104
  readonly journalMode: string;
@@ -89,6 +112,7 @@ export interface OpenStoreOptions {
89
112
  readonly capacityProbe?: () => StorageCapacity;
90
113
  readonly cubeLimits?: CubeLimits;
91
114
  readonly mutationHook?: (phase: string) => void;
115
+ readonly migrationMode?: "apply" | "require-current";
92
116
  }
93
117
  export interface CubeLimits {
94
118
  readonly maxCubesPerClient: number;
@@ -109,9 +133,17 @@ export interface StoreRuntime {
109
133
  readonly forPrincipal: (principal: Principal) => ScopedStore;
110
134
  readonly maintenance: MaintenanceStore;
111
135
  readonly credentials: CredentialStore;
136
+ readonly liveness: LivenessStore;
112
137
  readonly diagnostics: () => StoreDiagnostics;
113
138
  readonly close: () => void;
114
139
  }
140
+ export interface LivenessStore {
141
+ readonly scan: (options?: {
142
+ readonly silentMs?: number;
143
+ readonly cooldownMs?: number;
144
+ readonly limit?: number;
145
+ }) => ActivityNotificationRecord[];
146
+ }
115
147
  export interface DigestPair {
116
148
  readonly lookup: Buffer;
117
149
  readonly verifier: Buffer;
@@ -126,6 +158,19 @@ export interface StoredSecretDigest extends DigestPair {
126
158
  export interface StoredInvitationDigest extends StoredSecretDigest {
127
159
  readonly purpose: "owner" | "client";
128
160
  readonly ownerEpoch: number | null;
161
+ readonly cubeId: string | null;
162
+ readonly access: CubeAccess | null;
163
+ }
164
+ export interface InvitationCubeScope {
165
+ readonly cubeId: string;
166
+ readonly cubeName: string;
167
+ readonly access: CubeAccess;
168
+ }
169
+ export declare class InvitationCubeNotFoundError extends Error {
170
+ }
171
+ export declare class InvitationCubeAmbiguousError extends Error {
172
+ readonly candidateIds: readonly string[];
173
+ constructor(candidateIds: readonly string[]);
129
174
  }
130
175
  export interface EnrollmentClaimResult {
131
176
  readonly purpose: "owner" | "client";
@@ -138,6 +183,7 @@ export interface StoredDroneSessionDigest extends StoredSecretDigest {
138
183
  readonly cubeId: string;
139
184
  readonly droneId: string;
140
185
  readonly expiresAt: string;
186
+ readonly evictedAt: string | null;
141
187
  }
142
188
  export interface CredentialStore {
143
189
  readonly createRecoveryCredential: (id: string, digest: DigestPair) => void;
@@ -147,7 +193,12 @@ export interface CredentialStore {
147
193
  readonly digest: DigestPair;
148
194
  readonly expiresAt: string;
149
195
  readonly purpose: "owner" | "client";
150
- }) => void;
196
+ readonly cubeSelector?: {
197
+ readonly kind: "id" | "name";
198
+ readonly value: string;
199
+ };
200
+ readonly access?: CubeAccess;
201
+ }) => InvitationCubeScope | null;
151
202
  readonly findInvitation: (lookup: Buffer) => StoredInvitationDigest | null;
152
203
  readonly claimInvitation: (input: {
153
204
  readonly invitationId: string;
@@ -161,6 +212,7 @@ export interface CredentialStore {
161
212
  readonly clientExists: (clientId: string) => boolean;
162
213
  readonly clientIsActive: (clientId: string) => boolean;
163
214
  readonly findDroneSessionCredential: (lookup: Buffer) => StoredDroneSessionDigest | null;
215
+ readonly findActiveDroneSessionExpiry: (sessionId: string) => string | null;
164
216
  readonly rotateClientCredential: (input: {
165
217
  readonly clientId: string;
166
218
  readonly credentialId: string;
@@ -172,11 +224,19 @@ export interface ScopedStore {
172
224
  readonly createCube: (input: CreateCubeInput) => CreateCubeRecord;
173
225
  readonly listCubes: () => CubeRecord[];
174
226
  readonly getCube: (cubeId: string) => CubeRecord | null;
227
+ readonly updateCube: (cubeId: string, input: UpdateCubeInput) => CubeRecord;
175
228
  readonly updateDirective: (cubeId: string, directive: string) => void;
176
229
  readonly appendActivity: (cubeId: string, message: string) => ActivityRecord;
177
230
  readonly readActivity: (cubeId: string, limit: number) => ActivityRecord[];
178
231
  readonly listRoles: (cubeId: string) => RoleRecord[];
232
+ readonly createRole: (cubeId: string, input: CreateRoleInput) => RoleRecord;
233
+ readonly updateRole: (cubeId: string, roleId: string, input: UpdateRoleInput) => RoleRecord;
234
+ readonly patchRoleSection: (cubeId: string, roleId: string, input: RoleSectionPatchOp) => RoleRecord;
179
235
  readonly listDrones: (cubeId: string) => DroneRecord[];
236
+ readonly listDronesSince: (cubeId: string, since: string) => {
237
+ readonly drones: DroneRecord[];
238
+ readonly since: string;
239
+ };
180
240
  readonly appendLog: (cubeId: string, input: {
181
241
  readonly message: string;
182
242
  readonly visibility?: "broadcast" | "direct";
@@ -190,9 +250,35 @@ export interface ScopedStore {
190
250
  readonly rationale?: string;
191
251
  }) => DecisionRecord;
192
252
  readonly listDecisions: (cubeId: string) => DecisionRecord[];
193
- readonly subscribeActivity: (cubeId: string, listener: (entry: EnrichedActivityRecord) => void) => (() => void);
253
+ readonly subscribeActivity: (cubeId: string, listener: (entry: ActivityStreamRecord) => void) => (() => void);
194
254
  readonly attachSeat: (input: SeatAttachInput) => SeatAttachRecord;
195
255
  }
256
+ export interface CreateRoleInput {
257
+ readonly name: string;
258
+ readonly shortDescription?: string;
259
+ readonly detailedDescription?: string;
260
+ readonly isDefault?: boolean;
261
+ readonly isMandatory?: boolean;
262
+ readonly isHumanSeat?: boolean;
263
+ readonly canBroadcast?: boolean;
264
+ readonly receivesAllDirect?: boolean;
265
+ readonly roleClass?: "queen" | "worker";
266
+ }
267
+ export interface UpdateRoleInput {
268
+ readonly name?: string;
269
+ readonly shortDescription?: string;
270
+ readonly detailedDescription?: string;
271
+ readonly isDefault?: boolean;
272
+ readonly isMandatory?: boolean;
273
+ readonly isHumanSeat?: boolean;
274
+ readonly canBroadcast?: boolean;
275
+ readonly receivesAllDirect?: boolean;
276
+ readonly roleClass?: "queen" | "worker";
277
+ }
278
+ export interface UpdateCubeInput {
279
+ readonly directive?: string;
280
+ readonly messageTaxonomy?: MessageTaxonomy | null;
281
+ }
196
282
  export interface CreateCubeInput {
197
283
  readonly retryKey: string;
198
284
  readonly name: string;
@@ -207,7 +293,6 @@ export interface CreateCubeRecord {
207
293
  export interface SeatAttachInput {
208
294
  readonly cubeId: string;
209
295
  readonly roleId: string;
210
- readonly retryKey: string;
211
296
  readonly priorDroneId?: string;
212
297
  readonly droneId: string;
213
298
  readonly sessionId: string;
@@ -232,9 +317,7 @@ export interface SeatAttachRecord {
232
317
  };
233
318
  readonly sessionId: string;
234
319
  readonly expiresAt: string;
235
- readonly generation: number;
236
- readonly reattached: boolean;
237
- readonly revokedSessionIds: readonly string[];
320
+ readonly result: "created" | "reused";
238
321
  }
239
322
  export interface MaintenanceStore {
240
323
  readonly createClient: (input: {
@@ -304,12 +387,24 @@ export declare class ScopedStoreError extends Error {
304
387
  readonly code = "NOT_FOUND";
305
388
  constructor();
306
389
  }
390
+ export declare class RoleConflictError extends Error {
391
+ readonly code = "ROLE_ALREADY_EXISTS";
392
+ constructor();
393
+ }
394
+ export declare class DefaultRoleRequiredError extends Error {
395
+ readonly code = "DEFAULT_ROLE_REQUIRED";
396
+ constructor();
397
+ }
398
+ export declare class RoleSectionConflictError extends Error {
399
+ readonly code = "ROLE_SECTION_CONFLICT";
400
+ constructor();
401
+ }
307
402
  export declare class CursorExpiredError extends Error {
308
403
  readonly code = "CURSOR_EXPIRED";
309
404
  constructor();
310
405
  }
311
- export declare class AttachConflictError extends Error {
312
- readonly code = "ATTACH_CONFLICT";
406
+ export declare class AttachSessionRejectedError extends Error {
407
+ readonly code = "SESSION_REJECTED";
313
408
  constructor();
314
409
  }
315
410
  export declare class StorageCapacityError extends Error {
@@ -325,3 +420,6 @@ export declare class CreateCubeConflictError extends Error {
325
420
  constructor();
326
421
  }
327
422
  export declare function openStore(options: OpenStoreOptions): Promise<StoreRuntime>;
423
+ export declare function preparePrivateDataDirectory(path: string): Promise<string>;
424
+ export declare const MAX_ROLE_DETAILED_DESCRIPTION_CHARS = 51200;
425
+ export declare function assertRoleTextWriteAllowed(value: string, previous?: string): void;