@lossless.org/nosqldb 10.11.0 → 11.0.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/.smartconfig.json +117 -0
- package/dist_rust/rustdb_linux_amd64 +0 -0
- package/dist_rust/rustdb_linux_amd64.tsrust-build.json +5 -5
- package/dist_rust/rustdb_linux_amd64_musl +0 -0
- package/dist_rust/rustdb_linux_amd64_musl.tsrust-build.json +5 -5
- package/dist_rust/rustdb_linux_arm64 +0 -0
- package/dist_rust/rustdb_linux_arm64.tsrust-build.json +5 -5
- package/dist_rust/rustdb_linux_arm64_musl +0 -0
- package/dist_rust/rustdb_linux_arm64_musl.tsrust-build.json +5 -5
- package/dist_rust/rustdb_macos_amd64 +0 -0
- package/dist_rust/rustdb_macos_amd64.tsrust-build.json +5 -5
- package/dist_rust/rustdb_macos_arm64 +0 -0
- package/dist_rust/rustdb_macos_arm64.tsrust-build.json +5 -5
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/ts_local/classes.localnosqldb.d.ts +15 -4
- package/dist_ts/ts_local/classes.localnosqldb.js +31 -11
- package/dist_ts/ts_nosqldb/index.d.ts +3 -3
- package/dist_ts/ts_nosqldb/index.js +5 -4
- package/dist_ts/ts_nosqldb/rust-db-bridge.d.ts +125 -2
- package/dist_ts/ts_nosqldb/rust-db-bridge.js +261 -46
- package/dist_ts/ts_nosqldb/server/classes.nosqldbserver.d.ts +69 -3
- package/dist_ts/ts_nosqldb/server/classes.nosqldbserver.js +91 -12
- package/dist_ts/ts_nosqldb/server/index.d.ts +2 -2
- package/dist_ts/ts_nosqldb/server/index.js +2 -2
- package/dist_ts/ts_nosqldb/stopped-storage.d.ts +9 -1
- package/dist_ts/ts_nosqldb/stopped-storage.js +1 -1
- package/dist_ts/ts_nosqldb/storage-rehearsal.js +1 -1
- package/dist_ts/ts_nosqldb/storage-root-alignment.js +7 -3
- package/dist_ts/ts_nosqldb/storage-root-relocation.js +2 -2
- package/dist_ts_debugserver/bundled.js +6 -2
- package/package.json +28 -15
- package/readme.md +470 -730
- package/third-party-notices.md +40 -8
- package/third_party_licenses/inventory.json +6 -6
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/index.ts +85 -0
- package/ts/ts_local/classes.localnosqldb.ts +631 -0
- package/ts/ts_local/index.ts +19 -0
- package/ts/ts_local/plugins.ts +1 -0
- package/ts/ts_nosqldb/classes.storagerehearsal.ts +109 -0
- package/ts/ts_nosqldb/committed-writes.ts +38 -0
- package/ts/ts_nosqldb/file-storage-options.ts +33 -0
- package/ts/ts_nosqldb/file-storage-startup.ts +10 -0
- package/ts/ts_nosqldb/index.ts +132 -0
- package/ts/ts_nosqldb/offline-inspection.ts +375 -0
- package/ts/ts_nosqldb/plugins.ts +12 -0
- package/ts/ts_nosqldb/resource-fencing.ts +368 -0
- package/ts/ts_nosqldb/rust-db-bridge.ts +1309 -0
- package/ts/ts_nosqldb/server/classes.nosqldbserver.ts +874 -0
- package/ts/ts_nosqldb/server/index.ts +4 -0
- package/ts/ts_nosqldb/service-types.ts +499 -0
- package/ts/ts_nosqldb/stopped-storage.ts +116 -0
- package/ts/ts_nosqldb/storage-rehearsal.ts +215 -0
- package/ts/ts_nosqldb/storage-root-alignment.ts +180 -0
- package/ts/ts_nosqldb/storage-root-relocation.ts +279 -0
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Server module exports
|
|
2
|
+
export { NoSqlDbServer, noSqlDbServerStopGraceMs } from './classes.nosqldbserver.js';
|
|
3
|
+
export type { INoSqlDbServerOptions, INoSqlDbServerStopResult } from './classes.nosqldbserver.js';
|
|
4
|
+
export type { INoSqlDbQueryOptions, INoSqlDbInboundOptions } from '../rust-db-bridge.js';
|
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
export interface INoSqlDbHealth {
|
|
2
|
+
/** Present on engines supporting stopped root alignment. */
|
|
3
|
+
providerRootId?: string;
|
|
4
|
+
lsn?: string | null;
|
|
5
|
+
running: boolean;
|
|
6
|
+
storage?: 'memory' | 'file';
|
|
7
|
+
fileStorageEngine?: 'mvcc';
|
|
8
|
+
storagePurpose?: 'production' | 'rehearsal';
|
|
9
|
+
storageRehearsalId?: string | null;
|
|
10
|
+
storagePath?: string;
|
|
11
|
+
resourceFencingVersion?: 1;
|
|
12
|
+
resourceFencingSupported?: boolean;
|
|
13
|
+
resourceFencingRequiresDrain?: true;
|
|
14
|
+
allocationFencingVersion?: 1;
|
|
15
|
+
allocationFencingSupported?: boolean;
|
|
16
|
+
allocationFencingRequiresDrain?: true;
|
|
17
|
+
databaseAllocationReadAccessGrantVersion?: 1;
|
|
18
|
+
databaseAllocationReadAccessGrantSupported?: true;
|
|
19
|
+
publicationHoldVersion: 1;
|
|
20
|
+
publicationHoldSupported: boolean;
|
|
21
|
+
publicationHoldRequiresExternalDrain: boolean;
|
|
22
|
+
authEnabled?: boolean;
|
|
23
|
+
authUsers?: number;
|
|
24
|
+
usersPathConfigured?: boolean;
|
|
25
|
+
databaseCount: number;
|
|
26
|
+
collectionCount: number;
|
|
27
|
+
uptimeSeconds?: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Per-operation admission bounds for read-only stopped native storage inspection. */
|
|
31
|
+
export interface ILocalNoSqlDbOfflineInspectionLimits {
|
|
32
|
+
maximumEntries: number;
|
|
33
|
+
maximumTotalFileBytes: number;
|
|
34
|
+
maximumRecords: number;
|
|
35
|
+
maximumRecordBytes: number;
|
|
36
|
+
maximumResultBytes: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface ILocalNoSqlDbOfflineStringValueInspection {
|
|
40
|
+
folderPath: string;
|
|
41
|
+
databaseName: string;
|
|
42
|
+
collectionName: string;
|
|
43
|
+
match: {
|
|
44
|
+
field: string;
|
|
45
|
+
value: string;
|
|
46
|
+
};
|
|
47
|
+
valueField: string;
|
|
48
|
+
limits: ILocalNoSqlDbOfflineInspectionLimits;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type TLocalNoSqlDbOfflineStringValueInspectionResult =
|
|
52
|
+
| { status: 'not-found' }
|
|
53
|
+
| { status: 'found'; value: string };
|
|
54
|
+
|
|
55
|
+
export interface ILocalNoSqlDbOfflinePhysicalNamespaceInspectionLimits {
|
|
56
|
+
maximumEntries: number;
|
|
57
|
+
maximumDatabases: number;
|
|
58
|
+
maximumCollections: number;
|
|
59
|
+
maximumIndexes: number;
|
|
60
|
+
maximumTotalFileBytes: number;
|
|
61
|
+
maximumRecordsPerCollection: number;
|
|
62
|
+
maximumRecordBytes: number;
|
|
63
|
+
maximumResultBytes: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface ILocalNoSqlDbOfflinePhysicalNamespaceInspection {
|
|
67
|
+
folderPath: string;
|
|
68
|
+
limits: ILocalNoSqlDbOfflinePhysicalNamespaceInspectionLimits;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface ILocalNoSqlDbOfflinePhysicalNamespaceInspectionResult {
|
|
72
|
+
schemaVersion: 1;
|
|
73
|
+
databases: Array<{
|
|
74
|
+
name: string;
|
|
75
|
+
collections: string[];
|
|
76
|
+
}>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const noSqlDbResourceFenceErrorCodes = [
|
|
80
|
+
'EFENCE_REQUIRED',
|
|
81
|
+
'EFENCE_STALE',
|
|
82
|
+
'EFENCE_SCOPE_MISMATCH',
|
|
83
|
+
'EFENCE_UNSUPPORTED',
|
|
84
|
+
'EFENCE_MUTATION_MISMATCH',
|
|
85
|
+
'EFENCE_OWNERSHIP_MISMATCH',
|
|
86
|
+
'EFENCE_STATE_CORRUPT',
|
|
87
|
+
'EFENCE_RECEIPT_LIMIT',
|
|
88
|
+
'EFENCE_BUSY',
|
|
89
|
+
'EFENCE_PUBLICATION_HELD',
|
|
90
|
+
'EFENCE_CAPABILITY_MISMATCH',
|
|
91
|
+
'EFENCE_NOT_HELD',
|
|
92
|
+
'EALLOCATION_EXPECTED_ABSENT_CONFLICT',
|
|
93
|
+
'EALLOCATION_REQUIRED',
|
|
94
|
+
'EALLOCATION_MISMATCH',
|
|
95
|
+
'EALLOCATION_GENERATION_EXHAUSTED',
|
|
96
|
+
'EALLOCATION_DEPROVISIONED',
|
|
97
|
+
] as const;
|
|
98
|
+
|
|
99
|
+
export type TNoSqlDbResourceFenceErrorCode =
|
|
100
|
+
(typeof noSqlDbResourceFenceErrorCodes)[number];
|
|
101
|
+
|
|
102
|
+
export interface INoSqlDbResourceFence {
|
|
103
|
+
version: 1;
|
|
104
|
+
scopeId: string;
|
|
105
|
+
token: number;
|
|
106
|
+
mutationId: string;
|
|
107
|
+
payloadSha256: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface INoSqlDbResourceFenceReceipt
|
|
111
|
+
extends INoSqlDbResourceFence {
|
|
112
|
+
kind:
|
|
113
|
+
| 'smartdb.database.replace.v1'
|
|
114
|
+
| 'smartdb.database.delete.v1'
|
|
115
|
+
| 'smartdb.database.ensure.v1'
|
|
116
|
+
| 'smartdb.database.allocate.v1';
|
|
117
|
+
/** Digest of the canonical payload interpretation derived by NoSQLDB. */
|
|
118
|
+
effectivePayloadSha256: string;
|
|
119
|
+
provider?: 'smartdb';
|
|
120
|
+
resourceIdSha256?: string;
|
|
121
|
+
holdPublication?: true;
|
|
122
|
+
publicationState?: 'held' | 'released';
|
|
123
|
+
bindingSha256?: string;
|
|
124
|
+
resultSha256?: string;
|
|
125
|
+
receiptSha256?: string;
|
|
126
|
+
publicationCapabilitySha256?: string;
|
|
127
|
+
/** Present only while publication is held; never returned after release. */
|
|
128
|
+
publicationCapability?: string;
|
|
129
|
+
allocation?: INoSqlDbDatabaseAllocationIdentity;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface INoSqlDbDatabaseAllocationIdentity {
|
|
133
|
+
version: 1;
|
|
134
|
+
provider: 'smartdb';
|
|
135
|
+
state: 'active';
|
|
136
|
+
databaseName: string;
|
|
137
|
+
username: string;
|
|
138
|
+
allocationId: string;
|
|
139
|
+
generation: number;
|
|
140
|
+
principalId: string;
|
|
141
|
+
resourceIdSha256: string;
|
|
142
|
+
bindingSha256: string;
|
|
143
|
+
receiptSha256: string;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface INoSqlDbDatabaseAllocationLifecycle {
|
|
147
|
+
version: 1;
|
|
148
|
+
provider: 'smartdb';
|
|
149
|
+
state: 'allocating' | 'active' | 'deprovisioning' | 'deprovisioned';
|
|
150
|
+
databaseName: string;
|
|
151
|
+
username: string;
|
|
152
|
+
allocationId: string;
|
|
153
|
+
generation: number;
|
|
154
|
+
principalId: string;
|
|
155
|
+
resourceIdSha256: string;
|
|
156
|
+
bindingSha256: string;
|
|
157
|
+
receiptSha256: string;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface INoSqlDbDatabaseAllocationReadAccessGrantIdentity {
|
|
161
|
+
version: 1;
|
|
162
|
+
grantId: string;
|
|
163
|
+
principalId: string;
|
|
164
|
+
generation: number;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export interface INoSqlDbIssueDatabaseAllocationReadAccessGrantInput {
|
|
168
|
+
databaseName: string;
|
|
169
|
+
grantId: string;
|
|
170
|
+
username: string;
|
|
171
|
+
password: string;
|
|
172
|
+
allocation: INoSqlDbDatabaseAllocationIdentity;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export interface INoSqlDbIssueDatabaseAllocationReadAccessGrantResult {
|
|
176
|
+
databaseName: string;
|
|
177
|
+
username: string;
|
|
178
|
+
roles: ['read'];
|
|
179
|
+
authSource: string;
|
|
180
|
+
mongodbUri?: string;
|
|
181
|
+
allocation: INoSqlDbDatabaseAllocationIdentity;
|
|
182
|
+
grant: INoSqlDbDatabaseAllocationReadAccessGrantIdentity;
|
|
183
|
+
issuedAt: number;
|
|
184
|
+
expiresAt: number;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export interface INoSqlDbRevokeDatabaseAllocationReadAccessGrantInput {
|
|
188
|
+
databaseName: string;
|
|
189
|
+
grantId: string;
|
|
190
|
+
allocation: INoSqlDbDatabaseAllocationIdentity;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface INoSqlDbRevokeDatabaseAllocationReadAccessGrantResult {
|
|
194
|
+
databaseName: string;
|
|
195
|
+
grantId: string;
|
|
196
|
+
allocation: INoSqlDbDatabaseAllocationIdentity;
|
|
197
|
+
revoked: true;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export const noSqlDbAllocationReadAccessGrantErrorCodes = [
|
|
201
|
+
'EGRANT_INVALID_REQUEST',
|
|
202
|
+
'EGRANT_CREDENTIAL_MISMATCH',
|
|
203
|
+
'EGRANT_CONFLICT',
|
|
204
|
+
'EGRANT_REPLAY_CAPACITY',
|
|
205
|
+
'EGRANT_STATE_UNAVAILABLE',
|
|
206
|
+
] as const;
|
|
207
|
+
|
|
208
|
+
export type TNoSqlDbAllocationReadAccessGrantErrorCode =
|
|
209
|
+
(typeof noSqlDbAllocationReadAccessGrantErrorCodes)[number];
|
|
210
|
+
|
|
211
|
+
export class NoSqlDbAllocationReadAccessGrantError extends Error {
|
|
212
|
+
public readonly code: TNoSqlDbAllocationReadAccessGrantErrorCode;
|
|
213
|
+
|
|
214
|
+
public constructor(
|
|
215
|
+
codeArg: TNoSqlDbAllocationReadAccessGrantErrorCode,
|
|
216
|
+
messageArg: string,
|
|
217
|
+
causeArg?: unknown,
|
|
218
|
+
) {
|
|
219
|
+
super(`${codeArg}: ${messageArg}`, { cause: causeArg });
|
|
220
|
+
this.name = 'NoSqlDbAllocationReadAccessGrantError';
|
|
221
|
+
this.code = codeArg;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export const normalizeNoSqlDbAllocationReadAccessGrantError = (
|
|
226
|
+
errorArg: unknown,
|
|
227
|
+
codeArg?: unknown,
|
|
228
|
+
): Error => {
|
|
229
|
+
const error =
|
|
230
|
+
errorArg instanceof Error
|
|
231
|
+
? errorArg
|
|
232
|
+
: new Error(String(errorArg));
|
|
233
|
+
if (
|
|
234
|
+
typeof codeArg !== 'string'
|
|
235
|
+
|| !noSqlDbAllocationReadAccessGrantErrorCodes.includes(
|
|
236
|
+
codeArg as TNoSqlDbAllocationReadAccessGrantErrorCode,
|
|
237
|
+
)
|
|
238
|
+
) {
|
|
239
|
+
return error;
|
|
240
|
+
}
|
|
241
|
+
return new NoSqlDbAllocationReadAccessGrantError(
|
|
242
|
+
codeArg as TNoSqlDbAllocationReadAccessGrantErrorCode,
|
|
243
|
+
error.message,
|
|
244
|
+
error,
|
|
245
|
+
);
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
export interface INoSqlDbHeldPublicationReceipt
|
|
249
|
+
extends INoSqlDbResourceFenceReceipt {
|
|
250
|
+
provider: 'smartdb';
|
|
251
|
+
resourceIdSha256: string;
|
|
252
|
+
holdPublication: true;
|
|
253
|
+
publicationState: 'held';
|
|
254
|
+
bindingSha256: string;
|
|
255
|
+
resultSha256: string;
|
|
256
|
+
receiptSha256: string;
|
|
257
|
+
publicationCapabilitySha256: string;
|
|
258
|
+
publicationCapability: string;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export interface INoSqlDbCommitDatabasePublicationInput {
|
|
262
|
+
databaseName: string;
|
|
263
|
+
resourceFence: INoSqlDbHeldPublicationReceipt;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Cancellation and deadline ownership for one durable database-management
|
|
268
|
+
* operation. Aborting or timing out is fail-stop: NoSQLDB terminates the Rust
|
|
269
|
+
* engine so the operation cannot continue after the caller has released it.
|
|
270
|
+
*/
|
|
271
|
+
export interface INoSqlDbManagementOperationOptions {
|
|
272
|
+
signal?: AbortSignal;
|
|
273
|
+
timeoutMs?: number;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export interface INoSqlDbDatabaseResourceFenceState {
|
|
277
|
+
providerRootId?: string;
|
|
278
|
+
version: 1;
|
|
279
|
+
databaseName: string;
|
|
280
|
+
resourceIdSha256: string;
|
|
281
|
+
scopeId: string;
|
|
282
|
+
highestToken: number;
|
|
283
|
+
publicationState: 'requested' | 'publishing' | 'held' | 'released';
|
|
284
|
+
allocation?: INoSqlDbDatabaseAllocationLifecycle;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export class NoSqlDbResourceFenceError extends Error {
|
|
288
|
+
public readonly code: TNoSqlDbResourceFenceErrorCode;
|
|
289
|
+
|
|
290
|
+
public constructor(
|
|
291
|
+
codeArg: TNoSqlDbResourceFenceErrorCode,
|
|
292
|
+
messageArg: string,
|
|
293
|
+
causeArg?: unknown,
|
|
294
|
+
) {
|
|
295
|
+
super(`${codeArg}: ${messageArg}`, { cause: causeArg });
|
|
296
|
+
this.name = 'NoSqlDbResourceFenceError';
|
|
297
|
+
this.code = codeArg;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export const normalizeNoSqlDbResourceFenceError = (
|
|
302
|
+
errorArg: unknown,
|
|
303
|
+
): Error => {
|
|
304
|
+
const error =
|
|
305
|
+
errorArg instanceof Error
|
|
306
|
+
? errorArg
|
|
307
|
+
: new Error(String(errorArg));
|
|
308
|
+
const match = /^((?:EFENCE|EALLOCATION)_[A-Z_]+):\s*(.*)$/s.exec(error.message);
|
|
309
|
+
if (
|
|
310
|
+
!match ||
|
|
311
|
+
!noSqlDbResourceFenceErrorCodes.includes(
|
|
312
|
+
match[1] as TNoSqlDbResourceFenceErrorCode,
|
|
313
|
+
)
|
|
314
|
+
) {
|
|
315
|
+
return error;
|
|
316
|
+
}
|
|
317
|
+
return new NoSqlDbResourceFenceError(
|
|
318
|
+
match[1] as TNoSqlDbResourceFenceErrorCode,
|
|
319
|
+
match[2],
|
|
320
|
+
error,
|
|
321
|
+
);
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
export interface INoSqlDbDatabaseTenantInput {
|
|
325
|
+
databaseName: string;
|
|
326
|
+
username: string;
|
|
327
|
+
password: string;
|
|
328
|
+
roles?: string[];
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export interface INoSqlDbEnsureDatabaseTenantInput
|
|
332
|
+
extends INoSqlDbDatabaseTenantInput {
|
|
333
|
+
fence: INoSqlDbResourceFence;
|
|
334
|
+
allocation?: INoSqlDbDatabaseAllocationIdentity;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export interface INoSqlDbAttestDatabaseTenantInput {
|
|
338
|
+
databaseName: string;
|
|
339
|
+
username: string;
|
|
340
|
+
roles: string[];
|
|
341
|
+
password: string;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export interface INoSqlDbAttestDatabaseTenantResult {
|
|
345
|
+
matches: boolean;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export interface INoSqlDbAllocateDatabaseTenantInput
|
|
349
|
+
extends INoSqlDbDatabaseTenantInput {
|
|
350
|
+
expectedAbsent: true;
|
|
351
|
+
fence: INoSqlDbResourceFence;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export interface INoSqlDbDeleteDatabaseTenantInput {
|
|
355
|
+
databaseName: string;
|
|
356
|
+
/**
|
|
357
|
+
* Exact tenant user to revoke. For a fenced deletion this identity is
|
|
358
|
+
* included in the durable mutation and is removed idempotently after the
|
|
359
|
+
* database deletion is durable. Omitting it from a fenced deletion
|
|
360
|
+
* preserves auth users; an unfenced omission retains the legacy behavior
|
|
361
|
+
* of deleting every user for the database. If the database exists, a
|
|
362
|
+
* fenced deletion fails closed unless this exact user currently owns it.
|
|
363
|
+
*/
|
|
364
|
+
username?: string;
|
|
365
|
+
fence?: INoSqlDbResourceFence;
|
|
366
|
+
allocation?: INoSqlDbDatabaseAllocationIdentity;
|
|
367
|
+
/** Keep the database data plane closed until commitDatabasePublication. */
|
|
368
|
+
holdPublication?: boolean;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export interface INoSqlDbRotateDatabaseTenantPasswordInput {
|
|
372
|
+
username: string;
|
|
373
|
+
password: string;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export interface INoSqlDbDatabaseTenantDescriptor {
|
|
377
|
+
databaseName: string;
|
|
378
|
+
username: string;
|
|
379
|
+
roles: string[];
|
|
380
|
+
authSource: string;
|
|
381
|
+
mongodbUri?: string;
|
|
382
|
+
resourceFence?: INoSqlDbResourceFenceReceipt;
|
|
383
|
+
allocation?: INoSqlDbDatabaseAllocationIdentity;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export interface INoSqlDbEnsureDatabaseTenantResult
|
|
387
|
+
extends INoSqlDbDatabaseTenantDescriptor {
|
|
388
|
+
resourceFence: INoSqlDbResourceFenceReceipt;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
export interface INoSqlDbAllocateDatabaseTenantResult
|
|
392
|
+
extends INoSqlDbDatabaseTenantDescriptor {
|
|
393
|
+
resourceFence: INoSqlDbResourceFenceReceipt;
|
|
394
|
+
allocation: INoSqlDbDatabaseAllocationIdentity;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export interface INoSqlDbDeleteDatabaseTenantResult {
|
|
398
|
+
databaseName: string;
|
|
399
|
+
/**
|
|
400
|
+
* Users removed during the completing attempt. This can be zero after
|
|
401
|
+
* crash recovery when the exact user was durably removed by the prior
|
|
402
|
+
* attempt.
|
|
403
|
+
*/
|
|
404
|
+
deletedUsers: number;
|
|
405
|
+
databaseDropped: boolean;
|
|
406
|
+
/**
|
|
407
|
+
* Present for fenced calls. False means the bound exact username is now
|
|
408
|
+
* absent; true means no username was supplied and auth users were preserved.
|
|
409
|
+
*/
|
|
410
|
+
usersPreserved?: boolean;
|
|
411
|
+
resourceFence?: INoSqlDbResourceFenceReceipt;
|
|
412
|
+
allocation?: INoSqlDbDatabaseAllocationIdentity;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export interface INoSqlDbDatabaseExportCollection {
|
|
416
|
+
name: string;
|
|
417
|
+
/**
|
|
418
|
+
* Collection options exactly as `listCollections` reports them
|
|
419
|
+
* (`validator`, `validationLevel`, `validationAction`). Present only when
|
|
420
|
+
* the collection has options; engines up to 10.6.1 refuse such an export.
|
|
421
|
+
*/
|
|
422
|
+
options?: Record<string, any>;
|
|
423
|
+
documents: Record<string, any>[];
|
|
424
|
+
indexes: Record<string, any>[];
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
export interface INoSqlDbDatabaseExportLimits {
|
|
428
|
+
maxEncodedBytes?: number;
|
|
429
|
+
maxCollections?: number;
|
|
430
|
+
maxDocuments?: number;
|
|
431
|
+
maxIndexes?: number;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
export interface INoSqlDbExportDatabaseInput {
|
|
435
|
+
databaseName: string;
|
|
436
|
+
limits?: INoSqlDbDatabaseExportLimits;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/** Management-only read under an exact, still-held publication capability. */
|
|
440
|
+
export interface INoSqlDbExportHeldDatabaseInput extends INoSqlDbExportDatabaseInput {
|
|
441
|
+
resourceFence: INoSqlDbHeldPublicationReceipt;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export interface INoSqlDbDatabaseContentDigestLimits {
|
|
445
|
+
maxScannedBsonBytes?: number;
|
|
446
|
+
maxCollections?: number;
|
|
447
|
+
maxDocuments?: number;
|
|
448
|
+
maxIndexes?: number;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
export interface INoSqlDbGetDatabaseContentDigestInput {
|
|
452
|
+
databaseName: string;
|
|
453
|
+
limits?: INoSqlDbDatabaseContentDigestLimits;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
export interface INoSqlDbDatabaseContentDigest {
|
|
457
|
+
format: 'smartdb.database.content-digest.v1';
|
|
458
|
+
algorithm: 'sha256';
|
|
459
|
+
databaseName: string;
|
|
460
|
+
sha256: string;
|
|
461
|
+
scannedBsonBytes: number;
|
|
462
|
+
collections: number;
|
|
463
|
+
documents: number;
|
|
464
|
+
indexes: number;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
export interface INoSqlDbDatabaseExport {
|
|
468
|
+
format: 'smartdb.database.export.v1';
|
|
469
|
+
databaseName: string;
|
|
470
|
+
exportedAtMs: number;
|
|
471
|
+
collections: INoSqlDbDatabaseExportCollection[];
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
export interface INoSqlDbImportDatabaseInput {
|
|
475
|
+
databaseName: string;
|
|
476
|
+
source: INoSqlDbDatabaseExport;
|
|
477
|
+
/**
|
|
478
|
+
* Exact exclusive tenant owner required for this replacement. When used
|
|
479
|
+
* with a fence, the username is included in the provider-derived mutation
|
|
480
|
+
* identity. Omission preserves the original version 1 replacement profile.
|
|
481
|
+
*/
|
|
482
|
+
username?: string;
|
|
483
|
+
fence?: INoSqlDbResourceFence;
|
|
484
|
+
allocation?: INoSqlDbDatabaseAllocationIdentity;
|
|
485
|
+
/** Keep the database data plane closed until commitDatabasePublication. */
|
|
486
|
+
holdPublication?: boolean;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
export interface INoSqlDbImportDatabaseResult {
|
|
490
|
+
databaseName: string;
|
|
491
|
+
collections: number;
|
|
492
|
+
documents: number;
|
|
493
|
+
resourceFence?: INoSqlDbResourceFenceReceipt;
|
|
494
|
+
allocation?: INoSqlDbDatabaseAllocationIdentity;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
export type TNoSqlDbCommitDatabasePublicationResult =
|
|
498
|
+
| INoSqlDbImportDatabaseResult
|
|
499
|
+
| INoSqlDbDeleteDatabaseTenantResult;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { validateNoSqlDbManagementOperationOptions } from './offline-inspection.js';
|
|
3
|
+
import type { INoSqlDbManagementOperationOptions } from './service-types.js';
|
|
4
|
+
import type { TLocalNoSqlDbStorageRootRelocationErrorCode } from './storage-root-relocation.js';
|
|
5
|
+
|
|
6
|
+
export interface INoSqlDbStoppedOperationOptions extends INoSqlDbManagementOperationOptions {
|
|
7
|
+
/** Exact executable; invalid explicit paths never fall back to discovery. */
|
|
8
|
+
binaryPath?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ILocalNoSqlDbStoppedStorageRootInspectionInput { folderPath: string; }
|
|
12
|
+
export type TNoSqlDbStorageRootBindingChange = 'none' | 'path' | 'inode' | 'path+inode';
|
|
13
|
+
export interface INoSqlDbPhysicalAdmissionViolation {
|
|
14
|
+
relativePath: string;
|
|
15
|
+
rule: string;
|
|
16
|
+
observed: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ILocalNoSqlDbAuditedStorageRoot {
|
|
19
|
+
status: 'audited';
|
|
20
|
+
bindingState: 'matching' | 'foreign';
|
|
21
|
+
bindingChange: TNoSqlDbStorageRootBindingChange;
|
|
22
|
+
storagePurpose: 'production';
|
|
23
|
+
profileSchema: 1 | 4;
|
|
24
|
+
providerRootId: string;
|
|
25
|
+
/** Group/timeline describe shared lineage, not independent provider identity. */
|
|
26
|
+
groupId: string;
|
|
27
|
+
timelineId: string;
|
|
28
|
+
/** All counts and positions are canonical unsigned decimal strings. */
|
|
29
|
+
lsn: string;
|
|
30
|
+
records: string;
|
|
31
|
+
recordsSha256: string;
|
|
32
|
+
recordsWithoutFencingProfileSha256: string;
|
|
33
|
+
authUsers: string;
|
|
34
|
+
authority: {
|
|
35
|
+
resourceFences: string;
|
|
36
|
+
receipts: string;
|
|
37
|
+
publicationHolds: string;
|
|
38
|
+
activeAllocations: string;
|
|
39
|
+
retiredAllocations: string;
|
|
40
|
+
allocationReplays: string;
|
|
41
|
+
activeGrants: '0';
|
|
42
|
+
importStages: '0';
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* The generation inventory of a root that a 10.x release wrote, as this
|
|
46
|
+
* release's audit reports it and a 10.x engine's audit of its own root does.
|
|
47
|
+
* A root of this release keeps none: its report has no `generations` and
|
|
48
|
+
* says `storageFormat: 'format-3'`.
|
|
49
|
+
*/
|
|
50
|
+
generations?: { manifest: string; onDisk: string[] };
|
|
51
|
+
/** `'format-3'` for a root of this release; absent for a root that a 10.x release wrote. */
|
|
52
|
+
storageFormat?: 'format-3';
|
|
53
|
+
alignmentEligible: boolean;
|
|
54
|
+
reasons: string[];
|
|
55
|
+
physicalAdmissionViolations: [];
|
|
56
|
+
}
|
|
57
|
+
export interface ILocalNoSqlDbUnavailableStorageRoot {
|
|
58
|
+
status: 'unavailable';
|
|
59
|
+
stage: 'admission' | 'audit';
|
|
60
|
+
alignmentEligible: false;
|
|
61
|
+
reasons: string[];
|
|
62
|
+
/** Bounded advisory evidence. No logical identity or pin is trusted here. */
|
|
63
|
+
physicalAdmissionViolations: INoSqlDbPhysicalAdmissionViolation[];
|
|
64
|
+
}
|
|
65
|
+
export type TLocalNoSqlDbStoppedStorageRootInspection =
|
|
66
|
+
ILocalNoSqlDbAuditedStorageRoot | ILocalNoSqlDbUnavailableStorageRoot;
|
|
67
|
+
|
|
68
|
+
export class NoSqlDbStoppedOperationError extends Error {
|
|
69
|
+
public readonly responseErrorCode: TLocalNoSqlDbStorageRootRelocationErrorCode;
|
|
70
|
+
public constructor(public readonly code: TLocalNoSqlDbStorageRootRelocationErrorCode) {
|
|
71
|
+
super(`NoSQLDB stopped operation failed with code ${code}`);
|
|
72
|
+
this.name = 'NoSqlDbStoppedOperationError';
|
|
73
|
+
this.responseErrorCode = code;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const validateNoSqlDbStoppedOperationOptions = (options?: INoSqlDbStoppedOperationOptions): void => {
|
|
78
|
+
validateNoSqlDbManagementOperationOptions(options);
|
|
79
|
+
if (options?.binaryPath !== undefined && (typeof options.binaryPath !== 'string'
|
|
80
|
+
|| !options.binaryPath.length || options.binaryPath.includes('\0'))) {
|
|
81
|
+
throw new NoSqlDbStoppedOperationError('INVALID_REQUEST');
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const normalizeStoppedStorageRootInspectionInput = (
|
|
86
|
+
input: ILocalNoSqlDbStoppedStorageRootInspectionInput,
|
|
87
|
+
): ILocalNoSqlDbStoppedStorageRootInspectionInput => {
|
|
88
|
+
if (!input || Object.getPrototypeOf(input) !== Object.prototype
|
|
89
|
+
|| Reflect.ownKeys(input).length !== 1
|
|
90
|
+
|| !Object.getOwnPropertyDescriptor(input, 'folderPath')?.enumerable
|
|
91
|
+
|| !('value' in Object.getOwnPropertyDescriptor(input, 'folderPath')!)) {
|
|
92
|
+
throw new NoSqlDbStoppedOperationError('INVALID_REQUEST');
|
|
93
|
+
}
|
|
94
|
+
const folderPath = input.folderPath;
|
|
95
|
+
if (typeof folderPath !== 'string' || plugins.buffer.Buffer.byteLength(folderPath) > 4095
|
|
96
|
+
|| !plugins.path.isAbsolute(folderPath) || plugins.path.dirname(folderPath) === folderPath
|
|
97
|
+
|| folderPath.endsWith('/') || folderPath.includes('//') || /\p{Cc}/u.test(folderPath)
|
|
98
|
+
|| folderPath.split('/').some(part => part === '.' || part === '..' || part.startsWith('.smartdb-rehearsal-'))) {
|
|
99
|
+
throw new NoSqlDbStoppedOperationError('INVALID_REQUEST');
|
|
100
|
+
}
|
|
101
|
+
return { folderPath };
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/** Only a confirmed Rust response for this exact command proves non-dispatch.
|
|
105
|
+
* Transport errors with the same text remain ambiguous. */
|
|
106
|
+
export const isStoppedOperationUnknownMethod = (error: unknown, method: string): boolean =>
|
|
107
|
+
error instanceof Error && 'code' in error
|
|
108
|
+
&& error.code === 'ERR_RUST_BRIDGE_REQUEST_RUST_RESPONSE'
|
|
109
|
+
&& 'requestId' in error && typeof error.requestId === 'string' && error.requestId.length > 0
|
|
110
|
+
&& 'method' in error && error.method === method
|
|
111
|
+
&& (('responseErrorCode' in error && error.responseErrorCode === 'UNKNOWN_METHOD')
|
|
112
|
+
|| ((!('responseErrorCode' in error) || error.responseErrorCode === undefined)
|
|
113
|
+
&& error.message === `Unknown method: ${method}`));
|
|
114
|
+
|
|
115
|
+
export const normalizeStoppedOperationUnknownMethod = (error: unknown, method: string): unknown =>
|
|
116
|
+
isStoppedOperationUnknownMethod(error, method) ? new NoSqlDbStoppedOperationError('UNSUPPORTED') : error;
|