mindoodb 0.0.53 → 0.0.55

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 (99) hide show
  1. package/README-server.md +125 -69
  2. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.d.ts +17 -0
  3. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.d.ts.map +1 -1
  4. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js +22 -0
  5. package/dist/appendonlystores/network/ClientNetworkContentAddressedStore.js.map +1 -1
  6. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts +58 -0
  7. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.d.ts.map +1 -1
  8. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js +156 -3
  9. package/dist/appendonlystores/network/ServerNetworkContentAddressedStore.js.map +1 -1
  10. package/dist/browser/index.mjs +2 -0
  11. package/dist/core/BaseMindooDB.d.ts +73 -74
  12. package/dist/core/BaseMindooDB.d.ts.map +1 -1
  13. package/dist/core/BaseMindooDB.js +263 -509
  14. package/dist/core/BaseMindooDB.js.map +1 -1
  15. package/dist/core/MindooDBServerAdmin.d.ts +44 -22
  16. package/dist/core/MindooDBServerAdmin.d.ts.map +1 -1
  17. package/dist/core/MindooDBServerAdmin.js +45 -21
  18. package/dist/core/MindooDBServerAdmin.js.map +1 -1
  19. package/dist/core/appendonlystores/syncStores.d.ts +147 -0
  20. package/dist/core/appendonlystores/syncStores.d.ts.map +1 -0
  21. package/dist/core/appendonlystores/syncStores.js +612 -0
  22. package/dist/core/appendonlystores/syncStores.js.map +1 -0
  23. package/dist/core/builtinDbInvariants.d.ts +30 -0
  24. package/dist/core/builtinDbInvariants.d.ts.map +1 -1
  25. package/dist/core/builtinDbInvariants.js +97 -0
  26. package/dist/core/builtinDbInvariants.js.map +1 -1
  27. package/dist/core/index.d.ts +1 -1
  28. package/dist/core/index.d.ts.map +1 -1
  29. package/dist/core/index.js +7 -4
  30. package/dist/core/index.js.map +1 -1
  31. package/dist/core/types.d.ts +42 -0
  32. package/dist/core/types.d.ts.map +1 -1
  33. package/dist/node/server/CapabilityMatcher.d.ts +2 -2
  34. package/dist/node/server/CapabilityMatcher.js +2 -2
  35. package/dist/node/server/MindooDBServer.d.ts +14 -1
  36. package/dist/node/server/MindooDBServer.d.ts.map +1 -1
  37. package/dist/node/server/MindooDBServer.js +166 -159
  38. package/dist/node/server/MindooDBServer.js.map +1 -1
  39. package/dist/node/server/SyncEventBus.d.ts +10 -0
  40. package/dist/node/server/SyncEventBus.d.ts.map +1 -1
  41. package/dist/node/server/SyncEventBus.js.map +1 -1
  42. package/dist/node/server/TenantManager.d.ts +58 -6
  43. package/dist/node/server/TenantManager.d.ts.map +1 -1
  44. package/dist/node/server/TenantManager.js +90 -65
  45. package/dist/node/server/TenantManager.js.map +1 -1
  46. package/dist/node/server/add-to-network.d.ts.map +1 -1
  47. package/dist/node/server/add-to-network.js +33 -15
  48. package/dist/node/server/add-to-network.js.map +1 -1
  49. package/dist/node/server/canonicalSetupName.d.ts +22 -0
  50. package/dist/node/server/canonicalSetupName.d.ts.map +1 -0
  51. package/dist/node/server/canonicalSetupName.js +38 -0
  52. package/dist/node/server/canonicalSetupName.js.map +1 -0
  53. package/dist/node/server/config.d.ts.map +1 -1
  54. package/dist/node/server/config.js +33 -1
  55. package/dist/node/server/config.js.map +1 -1
  56. package/dist/node/server/peer/ClusterAuditLog.d.ts +64 -0
  57. package/dist/node/server/peer/ClusterAuditLog.d.ts.map +1 -0
  58. package/dist/node/server/peer/ClusterAuditLog.js +99 -0
  59. package/dist/node/server/peer/ClusterAuditLog.js.map +1 -0
  60. package/dist/node/server/peer/ClusterJobRunner.d.ts +43 -0
  61. package/dist/node/server/peer/ClusterJobRunner.d.ts.map +1 -0
  62. package/dist/node/server/peer/ClusterJobRunner.js +119 -0
  63. package/dist/node/server/peer/ClusterJobRunner.js.map +1 -0
  64. package/dist/node/server/peer/ClusterManager.d.ts +116 -0
  65. package/dist/node/server/peer/ClusterManager.d.ts.map +1 -0
  66. package/dist/node/server/peer/ClusterManager.js +274 -0
  67. package/dist/node/server/peer/ClusterManager.js.map +1 -0
  68. package/dist/node/server/peer/PeerAuthService.d.ts +69 -0
  69. package/dist/node/server/peer/PeerAuthService.d.ts.map +1 -0
  70. package/dist/node/server/peer/PeerAuthService.js +208 -0
  71. package/dist/node/server/peer/PeerAuthService.js.map +1 -0
  72. package/dist/node/server/peer/PeerReplicator.d.ts +232 -0
  73. package/dist/node/server/peer/PeerReplicator.d.ts.map +1 -0
  74. package/dist/node/server/peer/PeerReplicator.js +879 -0
  75. package/dist/node/server/peer/PeerReplicator.js.map +1 -0
  76. package/dist/node/server/peer/routes.d.ts +66 -0
  77. package/dist/node/server/peer/routes.d.ts.map +1 -0
  78. package/dist/node/server/peer/routes.js +322 -0
  79. package/dist/node/server/peer/routes.js.map +1 -0
  80. package/dist/node/server/peer/types.d.ts +244 -0
  81. package/dist/node/server/peer/types.d.ts.map +1 -0
  82. package/dist/node/server/peer/types.js +189 -0
  83. package/dist/node/server/peer/types.js.map +1 -0
  84. package/dist/node/server/server.d.ts +1 -1
  85. package/dist/node/server/server.js +18 -37
  86. package/dist/node/server/server.js.map +1 -1
  87. package/dist/node/server/serverinit.d.ts +2 -1
  88. package/dist/node/server/serverinit.d.ts.map +1 -1
  89. package/dist/node/server/serverinit.js +34 -12
  90. package/dist/node/server/serverinit.js.map +1 -1
  91. package/dist/node/server/types.d.ts +42 -30
  92. package/dist/node/server/types.d.ts.map +1 -1
  93. package/dist/node/server/types.js +1 -7
  94. package/dist/node/server/types.js.map +1 -1
  95. package/dist/node/server/validation.d.ts +0 -6
  96. package/dist/node/server/validation.d.ts.map +1 -1
  97. package/dist/node/server/validation.js +1 -7
  98. package/dist/node/server/validation.js.map +1 -1
  99. package/package.json +1 -1
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Types for server-to-server (peer) replication and the cluster admin surface.
3
+ *
4
+ * Two auth classes, two route prefixes — the split is load-bearing:
5
+ *
6
+ * - `/system/peer/*` is the **server-to-server protocol**. Callers authenticate
7
+ * with a server identity listed in `trusted-servers.json`. Only servers speak
8
+ * it.
9
+ * - `/system/cluster/*` is the **admin surface**. Callers authenticate with a
10
+ * system-admin JWT and pass the {@link CapabilityMatcher}. Only humans and
11
+ * UIs speak it.
12
+ *
13
+ * No endpoint accepts both, so a peer can never administer and an admin can
14
+ * never write as a peer.
15
+ */
16
+ /**
17
+ * Which way entries flow to a peer.
18
+ *
19
+ * Mirrors Haven's client-side `SyncDirectionPreference` so operators meet one
20
+ * vocabulary. `pull` is the backup/archive node (never writes to the peer),
21
+ * `push` the DMZ head (never reads back), `disabled` keeps the trust entry for
22
+ * inbound authentication but opens no outbound session.
23
+ */
24
+ export type PeerSyncDirection = "bidirectional" | "push" | "pull" | "disabled";
25
+ /**
26
+ * Mesh shape.
27
+ *
28
+ * A `spoke` opens sessions only to `hub` peers, never to another spoke, which
29
+ * turns the full mesh into a spanning tree. Because the entry set is a CRDT
30
+ * both converge; the tree just avoids the O(N^2) sessions of a large mesh.
31
+ * `peer` (the default) is fully meshed and is the right answer for two or three
32
+ * nodes — duplicate pushes are acknowledged idempotently by the receiver's
33
+ * duplicate path, so the redundancy is cheap.
34
+ */
35
+ export type PeerRole = "peer" | "hub" | "spoke";
36
+ /**
37
+ * How eagerly attachment blobs follow their documents.
38
+ *
39
+ * Attachments are usually the bulk of the bytes and live in a separate store,
40
+ * which makes this the biggest bandwidth lever. `lazy` still transfers them but
41
+ * only after every document store is done; `never` skips the attachment store
42
+ * entirely (an edge node that only needs text).
43
+ */
44
+ export type PeerAttachmentMode = "eager" | "lazy" | "never";
45
+ /** Peer settings resolved against their defaults. */
46
+ export interface PeerSettings {
47
+ direction: PeerSyncDirection;
48
+ role: PeerRole;
49
+ attachments: PeerAttachmentMode;
50
+ }
51
+ export declare const DEFAULT_PEER_SETTINGS: PeerSettings;
52
+ export declare function isPeerSyncDirection(value: unknown): value is PeerSyncDirection;
53
+ export declare function isPeerRole(value: unknown): value is PeerRole;
54
+ export declare function isPeerAttachmentMode(value: unknown): value is PeerAttachmentMode;
55
+ /** Fill in defaults for any peer field the operator left unset. */
56
+ export declare function normalizePeerSettings(raw: {
57
+ direction?: unknown;
58
+ role?: unknown;
59
+ attachments?: unknown;
60
+ }): PeerSettings;
61
+ /**
62
+ * Should this node open an outbound session to that peer?
63
+ *
64
+ * Spoke-to-spoke is the only pairing we suppress: both sides would otherwise
65
+ * dial each other even though the hub already carries their traffic.
66
+ */
67
+ export declare function shouldOpenSessionTo(local: PeerRole, remote: PeerRole): boolean;
68
+ /** May we send local entries to this peer? */
69
+ export declare function directionAllowsPush(direction: PeerSyncDirection): boolean;
70
+ /** May we take the peer's entries? */
71
+ export declare function directionAllowsPull(direction: PeerSyncDirection): boolean;
72
+ /**
73
+ * Order the databases of one tenant for replication.
74
+ *
75
+ * `directory` first, then `userdirectory`, then everything else alphabetically.
76
+ * This is not cosmetic. A peer validates every pushed entry against its own
77
+ * directory (`validatePublicSigningKey`), and an unknown author key is a
78
+ * **per-entry rejection**, not a batch failure. Push an application database
79
+ * before the peer has the author's grant and those entries are refused; with
80
+ * the client's cursor semantics they would then be skipped forever, leaving the
81
+ * two servers silently divergent.
82
+ *
83
+ * The same ordering also shrinks the transient window in which a purged
84
+ * document or a revoked `decryptionKeyId` makes the peer answer `ACCESS_DENIED`
85
+ * for a whole batch: both denylists are derived from the directory (purge
86
+ * requests live there and are executed by `executePendingPurges` after every
87
+ * directory push), so they converge as soon as the directory has arrived.
88
+ */
89
+ export declare function orderDatabasesForReplication(dbIds: Iterable<string>): string[];
90
+ /** True for the two system databases that must replicate before app data. */
91
+ export declare function isTrustBearingDatabase(dbId: string): boolean;
92
+ /** Live state of the outbound session to one peer. */
93
+ export type ClusterSessionState = "connected" | "connecting" | "backoff" | "disabled" | "paused" | "unreachable";
94
+ /**
95
+ * Health rollup, computed on the server so every console agrees on the
96
+ * thresholds instead of inventing its own.
97
+ */
98
+ export type ClusterHealth = "ok" | "degraded" | "stalled" | "down";
99
+ /**
100
+ * Why a peer is not `ok`. Typed so a UI can colour-code and explain without
101
+ * parsing prose.
102
+ *
103
+ * `entries-awaiting-directory-trust` is the one that matters most: it means the
104
+ * peer rejected entries because it does not yet trust their author, the cursor
105
+ * was held, and a retry is pending. Left unattended it is the visible precursor
106
+ * of two servers drifting apart.
107
+ */
108
+ export type ClusterHealthReason = "entries-awaiting-directory-trust" | "access-denied-backoff" | "events-disconnected" | "intersection-stale" | "lag-above-threshold" | "peer-auth-failed" | "peer-unreachable" | "no-url-configured" | "session-disabled" | "session-paused";
109
+ /** Typed error class beside the free-text `lastError`. */
110
+ export type ClusterErrorClass = "auth" | "network" | "access-denied" | "protocol" | "internal";
111
+ /**
112
+ * Bucket a replication failure so the console can react without parsing the
113
+ * message.
114
+ *
115
+ * The distinction that matters operationally is `access-denied` versus the
116
+ * rest: it is the peer *deliberately* refusing a batch (a purged document, a
117
+ * revoked key) and it resolves itself once the directory has replicated, so it
118
+ * warrants a backoff and not an alert. Everything else is either a
119
+ * misconfiguration (`auth`) or a genuine outage (`network`).
120
+ */
121
+ /**
122
+ * Strip document and entry identifiers out of a message before it reaches the
123
+ * cluster status read-model.
124
+ *
125
+ * Rejection messages name the offending entry, and an entry id starts with the
126
+ * document id. The cluster console is a system-admin surface, and a system
127
+ * admin is not supposed to learn which documents a tenant holds — that is the
128
+ * same admin-blindness the encryption enforces, and it would be odd to hand it
129
+ * back through an error string. The classified reason plus the counts are what
130
+ * an operator can act on anyway.
131
+ */
132
+ export declare function redactEntryIds(message: string): string;
133
+ export declare function classifyPeerError(error: unknown): ClusterErrorClass;
134
+ /** Per-tenant slice of a peer's replication state. */
135
+ export interface ClusterTenantStatus {
136
+ tenantId: string;
137
+ /** Databases mirrored with this peer, in replication order. */
138
+ databases: string[];
139
+ lastSyncAt: string | null;
140
+ /** Entries the peer still owes us or we owe the peer, by head comparison. */
141
+ lag: number;
142
+ /** Entries rejected and queued for retry (see `entries-awaiting-directory-trust`). */
143
+ retryQueueDepth: number;
144
+ rejectedEntries: number;
145
+ health: ClusterHealth;
146
+ reasons: ClusterHealthReason[];
147
+ }
148
+ /** One peer as this node sees it. */
149
+ export interface ClusterPeerStatus {
150
+ name: string;
151
+ url: string | null;
152
+ direction: PeerSyncDirection;
153
+ role: PeerRole;
154
+ attachments: PeerAttachmentMode;
155
+ state: ClusterSessionState;
156
+ health: ClusterHealth;
157
+ reasons: ClusterHealthReason[];
158
+ /** Tenants both sides hold, from the last Bloom intersection. */
159
+ sharedTenants: number;
160
+ lastIntersectionAt: string | null;
161
+ lastSyncAt: string | null;
162
+ eventsConnected: boolean;
163
+ lag: number;
164
+ retryQueueDepth: number;
165
+ rejectedEntries: number;
166
+ transferredEntries: number;
167
+ transferredBytes: number;
168
+ lastError: string | null;
169
+ lastErrorClass: ClusterErrorClass | null;
170
+ lastErrorAt: string | null;
171
+ }
172
+ /** Summary answer of `GET /system/cluster/status`. */
173
+ export interface ClusterStatusResponse {
174
+ server: string | null;
175
+ health: ClusterHealth;
176
+ reasons: ClusterHealthReason[];
177
+ autoSyncEnabled: boolean;
178
+ generatedAt: string;
179
+ peers: ClusterPeerStatus[];
180
+ }
181
+ /** Drill-down answer of `GET /system/cluster/status/tenants/:tenantId`. */
182
+ export interface ClusterTenantStatusResponse {
183
+ tenantId: string;
184
+ generatedAt: string;
185
+ peers: Array<{
186
+ name: string;
187
+ tenant: ClusterTenantStatus | null;
188
+ }>;
189
+ }
190
+ /** One entry of `GET /system/cluster/topology`. */
191
+ export interface ClusterTopologyPeer {
192
+ name: string;
193
+ url: string | null;
194
+ direction: PeerSyncDirection;
195
+ role: PeerRole;
196
+ attachments: PeerAttachmentMode;
197
+ sessionActive: boolean;
198
+ }
199
+ export interface ClusterTopologyResponse {
200
+ /**
201
+ * This node's own identity and role. The console starts here and then polls
202
+ * every peer directly — no node answers on behalf of another (fan-out).
203
+ */
204
+ server: {
205
+ name: string | null;
206
+ role: PeerRole;
207
+ };
208
+ peers: ClusterTopologyPeer[];
209
+ }
210
+ export type ClusterJobState = "queued" | "running" | "succeeded" | "failed";
211
+ export type ClusterJobKind = "sync" | "retry-rejected" | "refresh-intersection" | "pause" | "resume";
212
+ export interface ClusterJobScope {
213
+ peer?: string;
214
+ tenantId?: string;
215
+ dbId?: string;
216
+ }
217
+ export interface ClusterJob {
218
+ id: string;
219
+ kind: ClusterJobKind;
220
+ scope: ClusterJobScope;
221
+ state: ClusterJobState;
222
+ createdAt: string;
223
+ startedAt: string | null;
224
+ finishedAt: string | null;
225
+ /** Coarse progress counters; never carries document identity. */
226
+ progress: {
227
+ total: number;
228
+ completed: number;
229
+ };
230
+ result: ClusterJobResult | null;
231
+ error: string | null;
232
+ errorClass: ClusterErrorClass | null;
233
+ /** System-admin principal that requested the job. */
234
+ requestedBy: string;
235
+ }
236
+ export interface ClusterJobResult {
237
+ transferredEntries: number;
238
+ transferredBytes: number;
239
+ /** Count only — the entry ids would leak document identity to the console. */
240
+ rejectedEntries: number;
241
+ tenantsProcessed: number;
242
+ databasesProcessed: number;
243
+ }
244
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/node/server/peer/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAE/E;;;;;;;;;GASG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAE5D,qDAAqD;AACrD,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,iBAAiB,CAAC;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,EAAE,kBAAkB,CAAC;CACjC;AAED,eAAO,MAAM,qBAAqB,EAAE,YAInC,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAI9E;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,kBAAkB,CAEhF;AAED,mEAAmE;AACnE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,YAAY,CAUf;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAE9E;AAED,8CAA8C;AAC9C,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAEzE;AAED,sCAAsC;AACtC,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAEzE;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAoB9E;AAED,6EAA6E;AAC7E,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE5D;AAMD,sDAAsD;AACtD,MAAM,MAAM,mBAAmB,GAC3B,WAAW,GACX,YAAY,GACZ,SAAS,GACT,UAAU,GACV,QAAQ,GACR,aAAa,CAAC;AAElB;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAEnE;;;;;;;;GAQG;AACH,MAAM,MAAM,mBAAmB,GAC3B,kCAAkC,GAClC,uBAAuB,GACvB,qBAAqB,GACrB,oBAAoB,GACpB,qBAAqB,GACrB,kBAAkB,GAClB,kBAAkB,GAClB,mBAAmB,GACnB,kBAAkB,GAClB,gBAAgB,CAAC;AAErB,0DAA0D;AAC1D,MAAM,MAAM,iBAAiB,GACzB,MAAM,GACN,SAAS,GACT,eAAe,GACf,UAAU,GACV,UAAU,CAAC;AAEf;;;;;;;;;GASG;AACH;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,CAgDnE;AAED,sDAAsD;AACtD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAC;IACZ,sFAAsF;IACtF,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,mBAAmB,EAAE,CAAC;CAChC;AAED,qCAAqC;AACrC,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,EAAE,kBAAkB,CAAC;IAChC,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,iEAAiE;IACjE,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACzC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,sDAAsD;AACtD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,eAAe,EAAE,OAAO,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,iBAAiB,EAAE,CAAC;CAC5B;AAED,2EAA2E;AAC3E,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CACpE;AAED,mDAAmD;AACnD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,EAAE,kBAAkB,CAAC;IAChC,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC;IAChD,KAAK,EAAE,mBAAmB,EAAE,CAAC;CAC9B;AAMD,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE5E,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,gBAAgB,GAChB,sBAAsB,GACtB,OAAO,GACP,QAAQ,CAAC;AAEb,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,eAAe,CAAC;IACvB,KAAK,EAAE,eAAe,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iEAAiE;IACjE,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACrC,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,8EAA8E;IAC9E,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;CAC5B"}
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ /**
3
+ * Types for server-to-server (peer) replication and the cluster admin surface.
4
+ *
5
+ * Two auth classes, two route prefixes — the split is load-bearing:
6
+ *
7
+ * - `/system/peer/*` is the **server-to-server protocol**. Callers authenticate
8
+ * with a server identity listed in `trusted-servers.json`. Only servers speak
9
+ * it.
10
+ * - `/system/cluster/*` is the **admin surface**. Callers authenticate with a
11
+ * system-admin JWT and pass the {@link CapabilityMatcher}. Only humans and
12
+ * UIs speak it.
13
+ *
14
+ * No endpoint accepts both, so a peer can never administer and an admin can
15
+ * never write as a peer.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.DEFAULT_PEER_SETTINGS = void 0;
19
+ exports.isPeerSyncDirection = isPeerSyncDirection;
20
+ exports.isPeerRole = isPeerRole;
21
+ exports.isPeerAttachmentMode = isPeerAttachmentMode;
22
+ exports.normalizePeerSettings = normalizePeerSettings;
23
+ exports.shouldOpenSessionTo = shouldOpenSessionTo;
24
+ exports.directionAllowsPush = directionAllowsPush;
25
+ exports.directionAllowsPull = directionAllowsPull;
26
+ exports.orderDatabasesForReplication = orderDatabasesForReplication;
27
+ exports.isTrustBearingDatabase = isTrustBearingDatabase;
28
+ exports.redactEntryIds = redactEntryIds;
29
+ exports.classifyPeerError = classifyPeerError;
30
+ const types_1 = require("../../../core/types");
31
+ exports.DEFAULT_PEER_SETTINGS = {
32
+ direction: "bidirectional",
33
+ role: "peer",
34
+ attachments: "eager",
35
+ };
36
+ function isPeerSyncDirection(value) {
37
+ return (value === "bidirectional" || value === "push" || value === "pull" || value === "disabled");
38
+ }
39
+ function isPeerRole(value) {
40
+ return value === "peer" || value === "hub" || value === "spoke";
41
+ }
42
+ function isPeerAttachmentMode(value) {
43
+ return value === "eager" || value === "lazy" || value === "never";
44
+ }
45
+ /** Fill in defaults for any peer field the operator left unset. */
46
+ function normalizePeerSettings(raw) {
47
+ return {
48
+ direction: isPeerSyncDirection(raw.direction)
49
+ ? raw.direction
50
+ : exports.DEFAULT_PEER_SETTINGS.direction,
51
+ role: isPeerRole(raw.role) ? raw.role : exports.DEFAULT_PEER_SETTINGS.role,
52
+ attachments: isPeerAttachmentMode(raw.attachments)
53
+ ? raw.attachments
54
+ : exports.DEFAULT_PEER_SETTINGS.attachments,
55
+ };
56
+ }
57
+ /**
58
+ * Should this node open an outbound session to that peer?
59
+ *
60
+ * Spoke-to-spoke is the only pairing we suppress: both sides would otherwise
61
+ * dial each other even though the hub already carries their traffic.
62
+ */
63
+ function shouldOpenSessionTo(local, remote) {
64
+ return !(local === "spoke" && remote === "spoke");
65
+ }
66
+ /** May we send local entries to this peer? */
67
+ function directionAllowsPush(direction) {
68
+ return direction === "bidirectional" || direction === "push";
69
+ }
70
+ /** May we take the peer's entries? */
71
+ function directionAllowsPull(direction) {
72
+ return direction === "bidirectional" || direction === "pull";
73
+ }
74
+ // =========================================================================
75
+ // Replication ordering (convergence invariant 1)
76
+ // =========================================================================
77
+ /**
78
+ * Order the databases of one tenant for replication.
79
+ *
80
+ * `directory` first, then `userdirectory`, then everything else alphabetically.
81
+ * This is not cosmetic. A peer validates every pushed entry against its own
82
+ * directory (`validatePublicSigningKey`), and an unknown author key is a
83
+ * **per-entry rejection**, not a batch failure. Push an application database
84
+ * before the peer has the author's grant and those entries are refused; with
85
+ * the client's cursor semantics they would then be skipped forever, leaving the
86
+ * two servers silently divergent.
87
+ *
88
+ * The same ordering also shrinks the transient window in which a purged
89
+ * document or a revoked `decryptionKeyId` makes the peer answer `ACCESS_DENIED`
90
+ * for a whole batch: both denylists are derived from the directory (purge
91
+ * requests live there and are executed by `executePendingPurges` after every
92
+ * directory push), so they converge as soon as the directory has arrived.
93
+ */
94
+ function orderDatabasesForReplication(dbIds) {
95
+ const rest = [];
96
+ let hasDirectory = false;
97
+ let hasUserDirectory = false;
98
+ for (const dbId of dbIds) {
99
+ if (dbId === types_1.DIRECTORY_DB_ID) {
100
+ hasDirectory = true;
101
+ }
102
+ else if (dbId === types_1.USER_DIRECTORY_DB_ID) {
103
+ hasUserDirectory = true;
104
+ }
105
+ else {
106
+ rest.push(dbId);
107
+ }
108
+ }
109
+ rest.sort((left, right) => left.localeCompare(right));
110
+ const ordered = [];
111
+ if (hasDirectory)
112
+ ordered.push(types_1.DIRECTORY_DB_ID);
113
+ if (hasUserDirectory)
114
+ ordered.push(types_1.USER_DIRECTORY_DB_ID);
115
+ return ordered.concat(rest);
116
+ }
117
+ /** True for the two system databases that must replicate before app data. */
118
+ function isTrustBearingDatabase(dbId) {
119
+ return dbId === types_1.DIRECTORY_DB_ID || dbId === types_1.USER_DIRECTORY_DB_ID;
120
+ }
121
+ /**
122
+ * Bucket a replication failure so the console can react without parsing the
123
+ * message.
124
+ *
125
+ * The distinction that matters operationally is `access-denied` versus the
126
+ * rest: it is the peer *deliberately* refusing a batch (a purged document, a
127
+ * revoked key) and it resolves itself once the directory has replicated, so it
128
+ * warrants a backoff and not an alert. Everything else is either a
129
+ * misconfiguration (`auth`) or a genuine outage (`network`).
130
+ */
131
+ /**
132
+ * Strip document and entry identifiers out of a message before it reaches the
133
+ * cluster status read-model.
134
+ *
135
+ * Rejection messages name the offending entry, and an entry id starts with the
136
+ * document id. The cluster console is a system-admin surface, and a system
137
+ * admin is not supposed to learn which documents a tenant holds — that is the
138
+ * same admin-blindness the encryption enforces, and it would be odd to hand it
139
+ * back through an error string. The classified reason plus the counts are what
140
+ * an operator can act on anyway.
141
+ */
142
+ function redactEntryIds(message) {
143
+ return message.replace(/[0-9a-f]{16,}/gi, "<redacted>");
144
+ }
145
+ function classifyPeerError(error) {
146
+ const type = error?.type;
147
+ switch (type) {
148
+ case "ACCESS_DENIED":
149
+ // Every 403 reaches the client as USER_REVOKED, whatever the server meant
150
+ // by it. For a peer that is unambiguous: it holds no user identity, so a
151
+ // 403 can only mean the target refuses these particular entries — a purged
152
+ // document, a revoked decryption key. That is a backoff, not a
153
+ // misconfigured trust relationship.
154
+ case "USER_REVOKED":
155
+ return "access-denied";
156
+ case "INVALID_TOKEN":
157
+ case "INVALID_SIGNATURE":
158
+ case "CHALLENGE_EXPIRED":
159
+ return "auth";
160
+ case "NETWORK_ERROR":
161
+ case "RATE_LIMITED":
162
+ return "network";
163
+ case "PAYLOAD_TOO_LARGE":
164
+ case "SERVER_ERROR":
165
+ return "protocol";
166
+ default:
167
+ break;
168
+ }
169
+ const message = (error instanceof Error ? error.message : String(error)).toLowerCase();
170
+ if (message.includes("access_denied") || message.includes("access denied")) {
171
+ return "access-denied";
172
+ }
173
+ if (message.includes("401") ||
174
+ message.includes("403") ||
175
+ message.includes("authentication") ||
176
+ message.includes("token")) {
177
+ return "auth";
178
+ }
179
+ if (message.includes("fetch failed") ||
180
+ message.includes("econnrefused") ||
181
+ message.includes("enotfound") ||
182
+ message.includes("etimedout") ||
183
+ message.includes("socket") ||
184
+ message.includes("network")) {
185
+ return "network";
186
+ }
187
+ return "internal";
188
+ }
189
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/node/server/peer/types.ts"],"names":[],"mappings":"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"}
@@ -9,7 +9,7 @@
9
9
  * Options:
10
10
  * -d, --data-dir <path> Data directory path (default: ./data)
11
11
  * -p, --port <port> Server port (default: 1661)
12
- * -s, --auto-sync Enable automatic sync with remote servers
12
+ * -s, --auto-sync Replicate with the peers in trusted-servers.json
13
13
  * -w, --static-dir <path> Serve static files from this directory at /statics/
14
14
  * --tls-cert <path> Path to TLS certificate file (PEM)
15
15
  * --tls-key <path> Path to TLS private key file (PEM)
@@ -10,7 +10,7 @@
10
10
  * Options:
11
11
  * -d, --data-dir <path> Data directory path (default: ./data)
12
12
  * -p, --port <port> Server port (default: 1661)
13
- * -s, --auto-sync Enable automatic sync with remote servers
13
+ * -s, --auto-sync Replicate with the peers in trusted-servers.json
14
14
  * -w, --static-dir <path> Serve static files from this directory at /statics/
15
15
  * --tls-cert <path> Path to TLS certificate file (PEM)
16
16
  * --tls-key <path> Path to TLS private key file (PEM)
@@ -21,11 +21,9 @@
21
21
  */
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
23
  const MindooDBServer_1 = require("./MindooDBServer");
24
- const types_1 = require("../../core/types");
25
- const ServerSync_1 = require("./ServerSync");
26
24
  const config_1 = require("./config");
27
25
  const resolveServerPassword_1 = require("./resolveServerPassword");
28
- const types_2 = require("./types");
26
+ const types_1 = require("./types");
29
27
  function parseArgs(args) {
30
28
  const options = {
31
29
  dataDir: "./data",
@@ -111,7 +109,8 @@ Usage:
111
109
  Options:
112
110
  -d, --data-dir <path> Data directory path (default: ./data)
113
111
  -p, --port <port> Server port (default: 1661)
114
- -s, --auto-sync Enable automatic sync with remote servers
112
+ -s, --auto-sync Replicate with every peer in trusted-servers.json
113
+ that has a "url" (see README-server.md, Clustering)
115
114
  -w, --static-dir <path> Serve static files at /statics/ (e.g. bootstrap UI)
116
115
  --config <path> Path to config.json (default: <dataDir>/config.json)
117
116
  --tls-cert <path> Path to TLS certificate file (PEM format)
@@ -129,7 +128,7 @@ Examples:
129
128
  # Start server with custom data directory and port
130
129
  npm run server:dev -- -d /var/lib/mindoodb -p 8080
131
130
 
132
- # Start server with auto-sync enabled
131
+ # Start server as a cluster node, replicating with its trusted peers
133
132
  MINDOODB_SERVER_PASSWORD_FILE=./.server-password npm run server:dev -- -s
134
133
 
135
134
  # Start server with explicit config file
@@ -170,45 +169,27 @@ async function main() {
170
169
  const serverConfig = (0, config_1.loadServerConfig)(options.dataDir, options.configPath);
171
170
  // Create and start the server
172
171
  const server = new MindooDBServer_1.MindooDBServer(options.dataDir, serverPassword, options.staticDir, serverConfig, configPath);
173
- // If auto-sync is enabled and we have server identity, start periodic sync
174
- if (options.autoSync) {
172
+ // Peer replication is cluster-wide, not per tenant: one session per trusted
173
+ // server with a `url`, and every tenant both sides hold is mirrored over it.
174
+ if (options.autoSync || serverConfig.cluster?.autoSync) {
175
175
  const tenantManager = server.getTenantManager();
176
- const serverIdentity = tenantManager.getServerIdentity();
177
- if (!serverIdentity) {
176
+ if (!tenantManager.getServerIdentity()) {
178
177
  console.warn("[Main] Auto-sync enabled but no server.identity.json found. " +
179
178
  "Run 'npm run init' to create a server identity.");
180
179
  }
181
180
  else if (!serverPassword) {
182
181
  console.warn("[Main] Auto-sync enabled but no server password (set " +
183
- `${types_2.ENV_VARS.SERVER_PASSWORD} or ${types_2.ENV_VARS.SERVER_PASSWORD_FILE}). ` +
184
- "Server-to-server sync will not work.");
182
+ `${types_1.ENV_VARS.SERVER_PASSWORD} or ${types_1.ENV_VARS.SERVER_PASSWORD_FILE}). ` +
183
+ "Peer replication needs it to sign challenges and unwrap peer entries.");
185
184
  }
186
185
  else {
187
- const tenants = tenantManager.listTenants();
188
- for (const tenantId of tenants) {
189
- try {
190
- const tenant = await tenantManager.getTenant(tenantId);
191
- const config = tenant.context.config;
192
- if (config.remoteServers && config.remoteServers.length > 0) {
193
- const serverSync = new ServerSync_1.ServerSync(tenantManager.getCryptoAdapter(), tenantId, serverIdentity, serverPassword, async (dbId) => tenantManager.getStore(tenantId, dbId, types_1.StoreKind.docs));
194
- const stopSync = (0, ServerSync_1.startPeriodicSync)(serverSync, config.remoteServers);
195
- process.on("SIGINT", () => {
196
- console.log("\n[Main] Shutting down...");
197
- stopSync();
198
- process.exit(0);
199
- });
200
- process.on("SIGTERM", () => {
201
- console.log("\n[Main] Shutting down...");
202
- stopSync();
203
- process.exit(0);
204
- });
205
- console.log(`[Main] Started auto-sync for tenant ${tenantId}`);
206
- }
207
- }
208
- catch (error) {
209
- console.error(`[Main] Error setting up auto-sync for tenant ${tenantId}:`, error);
210
- }
211
- }
186
+ server.startCluster();
187
+ const shutdown = () => {
188
+ console.log("\n[Main] Shutting down...");
189
+ void server.stopCluster().finally(() => process.exit(0));
190
+ };
191
+ process.on("SIGINT", shutdown);
192
+ process.on("SIGTERM", shutdown);
212
193
  }
213
194
  }
214
195
  // Start listening
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/node/server/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/node/server/server.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,8 @@
7
7
  * npx ts-node src/serverinit.ts --name <serverName> [options]
8
8
  *
9
9
  * Options:
10
- * -n, --name <name> Server name (e.g., "server1") -- required
10
+ * -n, --name <name> Server name, canonical or abbreviated
11
+ * (e.g. "cn=server1/o=acme" or "server1/acme") -- required
11
12
  * -d, --data-dir <path> Data directory path (default: ./data)
12
13
  * -f, --force Overwrite existing server.identity.json
13
14
  * --skip-admin Skip system admin keypair generation
@@ -1 +1 @@
1
- {"version":3,"file":"serverinit.d.ts","sourceRoot":"","sources":["../../../src/node/server/serverinit.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;GAiBG"}
1
+ {"version":3,"file":"serverinit.d.ts","sourceRoot":"","sources":["../../../src/node/server/serverinit.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;GAkBG"}