@push.rocks/smartdb 5.5.1 → 5.6.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.
Binary file
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "format": "tsrust.build-provenance.v2",
3
- "binarySha256": "a4b1bb92556ac16600d9064d672acedebbada2ae471101aea54d3f81ca2aa14e",
3
+ "binarySha256": "55347a7396635075da1027b20e2bbccff00424f012d2001c087c73ea7e6c414d",
4
4
  "buildInfo": {
5
5
  "projectName": "@push.rocks/smartdb",
6
- "projectVersion": "5.5.1",
7
- "gitCommit": "6f369809b33f1a1e98ea51abf401e083dbd4818c",
6
+ "projectVersion": "5.6.0",
7
+ "gitCommit": "f0db2bc4f73ea31fd63f912dc61036c914946fce",
8
8
  "gitDirty": false,
9
- "builtAt": "2026-09-02T16:42:20.006Z",
9
+ "builtAt": "2026-09-05T12:44:09.182Z",
10
10
  "tsrustVersion": "1.10.4",
11
11
  "binary": "rustdb",
12
12
  "target": "linux_amd64"
Binary file
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "format": "tsrust.build-provenance.v2",
3
- "binarySha256": "bb68d54102556aff95978fa1e70bc38318ebb5508fdae4d1a0c1aac9903476a0",
3
+ "binarySha256": "14467960f6674176bc91a7237a471459a415b8e699c3202541e7850e389627f9",
4
4
  "buildInfo": {
5
5
  "projectName": "@push.rocks/smartdb",
6
- "projectVersion": "5.5.1",
7
- "gitCommit": "6f369809b33f1a1e98ea51abf401e083dbd4818c",
6
+ "projectVersion": "5.6.0",
7
+ "gitCommit": "f0db2bc4f73ea31fd63f912dc61036c914946fce",
8
8
  "gitDirty": false,
9
- "builtAt": "2026-09-02T16:42:58.586Z",
9
+ "builtAt": "2026-09-05T12:44:47.197Z",
10
10
  "tsrustVersion": "1.10.4",
11
11
  "binary": "rustdb",
12
12
  "target": "linux_arm64"
Binary file
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "format": "tsrust.build-provenance.v2",
3
- "binarySha256": "76c1670995d9a3d73aa27a2a071ac38483493683b0dbc0615c1570de96ed8dde",
3
+ "binarySha256": "255233b261d637b0ef65245ba123672b4fb89393127e92647bde47a9da4d07d7",
4
4
  "buildInfo": {
5
5
  "projectName": "@push.rocks/smartdb",
6
- "projectVersion": "5.5.1",
7
- "gitCommit": "6f369809b33f1a1e98ea51abf401e083dbd4818c",
6
+ "projectVersion": "5.6.0",
7
+ "gitCommit": "f0db2bc4f73ea31fd63f912dc61036c914946fce",
8
8
  "gitDirty": false,
9
- "builtAt": "2026-09-02T16:44:04.443Z",
9
+ "builtAt": "2026-09-05T12:45:49.186Z",
10
10
  "tsrustVersion": "1.10.4",
11
11
  "binary": "rustdb",
12
12
  "target": "macos_amd64"
Binary file
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "format": "tsrust.build-provenance.v2",
3
- "binarySha256": "49cb67fc38b85d8d50c86bd9fae504809b2439a3c174e707e688f61eada5870b",
3
+ "binarySha256": "c90862d452ac29941a98e94649cdf255cf93fdc895a2c0be61aa1c82bf146bbe",
4
4
  "buildInfo": {
5
5
  "projectName": "@push.rocks/smartdb",
6
- "projectVersion": "5.5.1",
7
- "gitCommit": "6f369809b33f1a1e98ea51abf401e083dbd4818c",
6
+ "projectVersion": "5.6.0",
7
+ "gitCommit": "f0db2bc4f73ea31fd63f912dc61036c914946fce",
8
8
  "gitDirty": false,
9
- "builtAt": "2026-09-02T16:44:48.396Z",
9
+ "builtAt": "2026-09-05T12:46:28.431Z",
10
10
  "tsrustVersion": "1.10.4",
11
11
  "binary": "rustdb",
12
12
  "target": "macos_arm64"
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartdb',
6
- version: '5.5.1',
6
+ version: '5.6.0',
7
7
  description: 'A MongoDB-compatible embedded database server with wire protocol support, backed by a high-performance Rust engine.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxxQkFBcUI7SUFDM0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHFIQUFxSDtDQUNuSSxDQUFBIn0=
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@push.rocks/smartdb",
3
- "version": "5.5.1",
3
+ "version": "5.6.0",
4
4
  "private": false,
5
5
  "description": "A MongoDB-compatible embedded database server with wire protocol support, backed by a high-performance Rust engine.",
6
6
  "exports": {
package/readme.md CHANGED
@@ -840,6 +840,13 @@ Mixed `localField`/`foreignField` plus `pipeline` lookups and other inner stages
840
840
  are rejected explicitly. Complete filter trees are validated before data is
841
841
  read, and query nesting plus aggregation work are bounded.
842
842
 
843
+ A leading `$match` narrows the pipeline's source load instead of filtering
844
+ after it: only matching documents are materialized, using an equality index when
845
+ one serves the filter and a bounded scan otherwise. Filter shapes the query
846
+ matcher cannot pre-compile fall back to the unnarrowed load, so results are
847
+ unchanged. The materialization limit therefore applies to the matched set, which
848
+ is what lets `countDocuments(filter)` run against collections larger than it.
849
+
843
850
  **Group accumulators:** `$sum`, `$avg`, `$min`, `$max`, `$first`, `$last`, `$push`, `$addToSet`, `$count`
844
851
 
845
852
  ### Indexes
@@ -862,6 +869,49 @@ validated no-op and index version `v: 2`. Unsupported options, including
862
869
  index in the request is created. TTL metadata is retained in the catalog;
863
870
  automatic TTL expiry is not implemented.
864
871
 
872
+ `find()` and collection `aggregate()` accept `hint` as an index name (including
873
+ `_id_`) or an exact ascending/descending key pattern. Key-pattern order matters;
874
+ if several indexes share a key pattern, use a name. The selected active scalar
875
+ index supplies every candidate, using safe full-key equality bounds or a full
876
+ scan of that index. The complete predicate still runs, and explicit sorting,
877
+ projection, skip, and limit retain their normal semantics. Index traversal uses
878
+ bounded pages under the namespace lock, so concurrent writes wait until the
879
+ hinted source read finishes. Unsorted results have no guaranteed BSON value order.
880
+
881
+ ```typescript
882
+ await collection.createIndex({ organizationId: 1, userId: 1 }, { name: 'organization_user' });
883
+ const page = await collection.find({ organizationId: 'org-1' }, {
884
+ hint: 'organization_user', sort: { userId: 1, _id: 1 }, skip: 20, limit: 10,
885
+ }).toArray();
886
+ const count = await collection.countDocuments({ organizationId: 'org-1' }, {
887
+ hint: 'organization_user',
888
+ });
889
+ ```
890
+
891
+ Unknown or quarantined indexes, malformed/ambiguous patterns, `$natural`, and
892
+ hints on missing collections or views fail explicitly. Forced multikey traversal
893
+ is unsupported and rejects; unhinted array queries keep their existing scan
894
+ behavior. Sparse hints intentionally exclude documents absent from that index,
895
+ including for empty filters and counts. A hint is never silently replaced by a
896
+ collection scan or another index.
897
+
898
+ Hinted transaction reads construct the selected index from the existing bounded
899
+ transaction snapshot plus buffered writes; they never fetch candidate documents
900
+ from live storage. Read-only aggregate source pipelines also use that transaction
901
+ view. Foreign-collection stages (`$lookup`, `$unionWith`) and writing stages
902
+ (`$out`, `$merge`), including stages inside `$facet`, reject within transactions.
903
+ Their existing nontransaction behavior is unchanged.
904
+
905
+ Finite count probes consisting of optional `$match`, optional `$skip`, positive
906
+ integer `$limit`, and `$count` (or the driver's equivalent constant-one `$group`)
907
+ stream candidates and stop when the limit is reached. They preserve hints,
908
+ deadlines, and empty-result shapes without materializing the matched set. Stage
909
+ dispatch, syntax, specifications, predicates, and streamed BSON processing consume
910
+ the same aggregation work budget as ordinary pipelines. This permits bounded namespace inspection of collections larger
911
+ than 10,000 documents or 32 MiB. Generic pipelines retain their existing
912
+ materialization limits. Transactions still require the existing bounded base
913
+ snapshot; finite counts do not bypass its 10,000-document / 32 MiB admission cap.
914
+
865
915
  ### Database & Admin
866
916
 
867
917
  ```typescript
package/readme.plan.md CHANGED
@@ -1,336 +1,9 @@
1
- # SmartDB advancement plan
1
+ # Query hints and finite counts
2
2
 
3
- Status: canonical direction, approved 2026-08-17. Reread before starting engine or
4
- managed-service work.
3
+ Find and aggregate select the requested active scalar index by name or exact numeric key pattern. Candidate pages have count and byte bounds; full predicates, explicit sorting, projection, skip, limit, deadlines, and cursor limits remain authoritative. Unknown, malformed, ambiguous, natural-order, and multikey hints reject explicitly. Sparse hints retain sparse membership semantics.
5
4
 
6
- Baseline: `@push.rocks/smartdb` 5.5.0. SmartDB is a Rust database engine with a
7
- TypeScript lifecycle facade, a MongoDB wire-protocol command surface, file and
8
- memory storage, authentication, transactions, resource fencing, and official
9
- MongoDB Node.js driver integration.
5
+ Transaction source reads use the owned snapshot plus buffered writes. Foreign-reading and writing aggregate stages reject inside transactions, including nested facets. Their nontransaction behavior is preserved.
10
6
 
11
- Current execution status:
7
+ Finite count pipelines support optional match, optional skip, positive integer limit, and count or the driver's constant-one count group. The query engine owns streaming accumulation and shares the normal aggregation work ceiling for stage dispatch, syntax, specifications, predicates, and BSON payload processing. Physical traversal preserves hints and deadlines. Generic materialization limits and the existing transaction snapshot admission cap of 10,000 documents / 32 MiB remain.
12
8
 
13
- - the legal and provenance gate passed on 2026-08-22
14
- - Phase 0 and the Phase 1 gate have not passed
15
- - 5.x maintenance now treats `data.rdb` as authoritative, ignores unverifiable
16
- legacy hint contents, streams CRC validation, and repairs only an incomplete
17
- final record-header prefix
18
- - strict latest-per-key runtime WAL recovery and post-publication point-write
19
- fencing were released in 5.3.2; crash-safe ordinary DDL, debug-server security,
20
- and general crash/soak qualification remain separate required 5.x slices
21
- - 5.4.0 released the non-serving, fixture-only A0 committed-log kernel with one
22
- static timeline, contiguous LSNs, exact retry receipts, bounded
23
- change-proportional appends, strict pair recovery, and ambiguity fencing; the
24
- follow-up A1/MVCC/rollover/checkpoint work is parked unreleased on the
25
- `storage-vnext-a1-wip` branch
26
- - A0 has no BSON document substrate, MVCC, checkpoint, segment rollover, OpenRaft
27
- integration, wire serving, migration, or availability claim; Phase 3B and the
28
- earlier Phase 0/1 gates have not passed
29
- - 5.5.0 serves the truthful single-node concern profile on the legacy engine:
30
- fsync-backed `w: 1`/`majority`/`j` acknowledgement, committed-state reads for
31
- `local`/`available`/`majority`/`linearizable`, database-wide transaction
32
- snapshots pinned by the namespace publication clock with fail-closed
33
- `SnapshotUnavailable` retries, cooperative `maxTimeMS` deadlines, and
34
- per-session idempotent commit/abort outcomes; unsatisfiable `w: N > 1`, tag
35
- sets, cluster-time read concerns, and journaled writes on the memory backend
36
- remain rejected
37
-
38
- ## Product objective
39
-
40
- Build SmartDB into a commercially operated, MongoDB-driver-compatible managed
41
- database service in this order:
42
-
43
- 1. truthful and provable single-node engine
44
- 2. certified compatibility profile
45
- 3. managed single-node service
46
- 4. replicated high-availability service
47
- 5. whole-database placement and migration
48
- 6. intra-database sharding only when customer scale requires it
49
-
50
- Reimplementing MongoDB-compatible server behavior and its persistence engine is the
51
- fixed strategy. SmartDB owns the wire, semantic, execution, storage, topology, and
52
- service contracts. Storage VNext does not embed SQLite, redb, Fjall, LMDB, RocksDB,
53
- or another database engine.
54
-
55
- ## Legal and provenance gate
56
-
57
- The official MongoDB wire-protocol documentation and specifications carry terms
58
- that expressly restrict commercial database and database-as-a-service adaptation.
59
- This plan does not interpret those terms. Before expanding compatibility work:
60
-
61
- - obtain written legal guidance for interoperability, clean-room implementation,
62
- product claims, and trademarks
63
- - audit the provenance of existing compatibility code and tests
64
- - classify disputed material for retention, independent rewrite, or quarantine
65
- - document which behavioral evidence and test sources implementation teams may use
66
- - market the service under an approved SmartDB identity and compatibility claim
67
-
68
- No compatibility feature enters a commercial release without passing this gate.
69
-
70
- ## Maintenance policy
71
-
72
- SmartDB 5.x is the maintenance lane for existing consumers:
73
-
74
- - accept security fixes, data-correctness fixes, explicit rejection of unsupported
75
- behavior, and bounded operability improvements
76
- - do not add broad MongoDB surface area or introduce a second durability model
77
- - keep persisted 5.x behavior supported until a tested offline conversion or
78
- snapshot/restore migration into Storage VNext exists
79
- - release small fixes independently when their invariants and compatibility impact
80
- can be verified in isolation
81
-
82
- Storage VNext is developed behind explicit format and capability boundaries. It
83
- must never dual-write through both the legacy and VNext commit paths.
84
-
85
- ## North-star architecture
86
-
87
- ### Wire gateway
88
-
89
- - parse and encode the declared wire profile exactly
90
- - validate complete command schemas before acquiring resources or mutating state
91
- - advertise only capabilities and limits proven by target-driver handshake tests
92
- - reject every unsupported command, concern, or option explicitly
93
-
94
- ### BSON semantic core
95
-
96
- - own one implementation of BSON equality, ordering, hashing, numeric promotion,
97
- null/missing behavior, array traversal, typed identifiers, projections,
98
- expressions, and updates
99
- - feed the same semantics into queries, indexes, transactions, aggregation,
100
- uniqueness checks, and change streams
101
-
102
- ### Planner and executor
103
-
104
- - use one planner for find, count, update, delete, aggregate, and explain
105
- - stream storage-backed cursors instead of materializing complete result sets
106
- - enforce deadlines, cancellation, admission, and work accounting at every loop
107
-
108
- ### Transactional storage kernel
109
-
110
- - own one authoritative, checksummed, monotonically ordered commit log
111
- - assign a stable timeline and LSN to every committed mutation
112
- - commit documents, DDL, catalogs, index definitions, users, retryable-write
113
- outcomes, and transaction outcomes through the same atomic boundary
114
- - serve database-wide MVCC snapshots and deterministic checkpoint-plus-log recovery
115
-
116
- ### Replication
117
-
118
- - replicate the committed Storage VNext log through a reviewed consensus design
119
- - use consensus terms to fence leaders; allocation fencing controls placement and
120
- publication but never substitutes for data-plane consensus
121
- - derive majority acknowledgement, failover, snapshot installation, causal times,
122
- and retry outcomes from the replicated commit history
123
-
124
- ### Administration and control plane
125
-
126
- - keep RBAC-protected database administration such as `currentOp`, `killOp`,
127
- `explain`, and user management available through the certified wire surface
128
- - keep service administration such as provisioning, placement, billing, backup,
129
- restore, upgrades, and incident actions on a separate privileged API
130
- - start with one process per tenant or isolated replica group; shared-process
131
- tenancy requires hard per-tenant admission and noisy-neighbor proof
132
-
133
- ## Phase 0: contract and measurement
134
-
135
- - complete the legal and provenance gate
136
- - select the first exact driver, ODM, topology, command, option, and error profile
137
- - maintain raw-wire and target-driver handshake tests
138
- - publish an out-of-band machine-readable compatibility manifest
139
- - version engine build, wire profile, storage format, and service API independently
140
- - establish baseline latency, memory, disk amplification, and restart benchmarks on
141
- Linux amd64 and arm64
142
-
143
- Gate: approved implementation sources and claims, an exact compatibility profile,
144
- and reproducible baseline measurements.
145
-
146
- ## Phase 1: truthful single-node behavior
147
-
148
- - stop over-advertising MongoDB version, wire behavior, and batch limits
149
- - serve the single-node concern profile truthfully and reject every concern,
150
- option, command, or administrative stub whose guarantee one node cannot
151
- provide (completed 2026-09-02: concerns, deadlines, database-wide transaction
152
- snapshots, idempotent transaction outcomes)
153
- - completed slice (2026-08-25): validate OP_MSG required flags, CRC-32C
154
- checksums, bounded framing, and exact no-response admission and execution
155
- - preserve complete BSON type and value identity for document and index keys
156
- - reconcile ambiguous point-write failures before returning control to callers
157
- - journal DDL and sync every required file and parent directory
158
- - distinguish incomplete final records from interior corruption and fail closed
159
- - isolate or secure all debug and privileged management surfaces
160
- - add an operation registry, deadlines, cancellation, real `currentOp`/`killOp`, and
161
- truthful metrics
162
- - write acknowledgement, recovery, corruption, and supported-filesystem contracts
163
-
164
- Gate: deterministic failpoints and randomized crashes produce no acknowledged-write
165
- loss, phantom documents, query/storage divergence, or unique-constraint violations
166
- within the declared single-node fault model.
167
-
168
- ## Phase 2: conformance foundation
169
-
170
- - build a legally approved behavioral comparison harness
171
- - fuzz raw wire framing, flags, malformed BSON, and command boundaries
172
- - validate commands into typed internal representations before execution
173
- - add exact response, error-code, error-label, and side-effect contracts
174
- - generate semantic corpora across BSON types, boundaries, arrays, null/missing,
175
- NaN, Decimal128, projections, paths, expressions, and identifiers
176
- - prevent any advertised capability from expanding without associated tests
177
-
178
- Gate: no known P0/P1 mismatch in the certified profile, and every unsupported path
179
- rejects before side effects.
180
-
181
- ## Phase 3A: storage-substrate decision
182
-
183
- Decision accepted 2026-08-28: implement a fully SmartDB-owned transactional storage
184
- kernel and persisted format. The legacy Bitcask engine remains only in the 5.x
185
- maintenance and offline-conversion lane; it is not the VNext durability boundary.
186
- Third-party database engines are excluded from the VNext runtime. Libraries for
187
- bounded primitives such as checksums, compression, or cryptography remain subject
188
- to ordinary evidence and license review without becoming an embedded database.
189
-
190
- The custom kernel and every candidate primitive are evaluated against:
191
-
192
- - crash and power-loss behavior
193
- - atomic batch and MVCC support
194
- - checkpoint, backup, and replication integration
195
- - memory, latency, write amplification, and restart behavior
196
- - format ownership, migration, licensing, and supply-chain risk
197
-
198
- Gate: one architecture decision selects exactly one authoritative durability
199
- boundary. Dual-WAL and dual-commit designs are prohibited.
200
-
201
- ## Phase 3B: Storage VNext
202
-
203
- - add a segmented, checksummed global commit log with stable timelines and LSNs
204
- - encode atomic data, DDL, catalog, index-metadata, and auth batches
205
- - persist request deduplication, retryable-write results, and transaction outcomes
206
- - add database-wide MVCC read timestamps and change-proportional transactions
207
- - replace full index-engine clones with incremental deltas
208
- - add immutable checkpoints, bounded replay, and a durable format manifest
209
- - move compaction to a rate-limited background service
210
- - add group commit and real batch publication
211
- - define an offline 5.x migration and N-1 compatibility contract
212
-
213
- Gates:
214
-
215
- - one-document transaction cost is independent of database size
216
- - repeated recovery is idempotent and produces the same content digest
217
- - ENOSPC, EIO, short writes, and failed fsyncs yield success, explicit ambiguity, or
218
- fail-closed state, never silent divergence
219
- - 24-hour nightly and 72-hour release-candidate soaks meet declared memory, disk,
220
- and restart ceilings on both Linux architectures
221
-
222
- ## Phase 4: query, index, and resource model
223
-
224
- - implement one streaming planner/executor
225
- - use canonical order-preserving BSON index keys
226
- - add range, compound-prefix, and index-ordered top-k scans
227
- - implement correct multikey expansion, uniqueness, and TTL execution
228
- - compile predicates and regular expressions once per operation
229
- - implement positional updates and array-filter semantics
230
- - add process-wide and per-tenant admission for memory, scans, connections, I/O,
231
- index builds, and maintenance
232
- - add configurable service classes and fair scheduling
233
- - add only features selected by the certified compatibility profile
234
-
235
- Semantic work may proceed after Phase 2. Crash-durable retryable outcomes,
236
- transaction publication, and durable index publication move onto Storage VNext.
237
- The single-node concern profile is served today: every acknowledged write is
238
- durable before the response, reads observe committed state, and transactions
239
- observe one database-wide snapshot. Multi-voter majority acknowledgement and
240
- cluster-time read concerns remain rejected until replication implements them.
241
-
242
- Gate: bounded-memory scans at maximum declared scale, published p99 latency and
243
- capacity curves, proven tenant isolation, and zero certified-profile mismatches.
244
-
245
- ## Phase 5: backup, PITR, and managed single-node service
246
-
247
- - create online immutable checkpoints at exact LSNs
248
- - archive subsequent commit-log segments continuously
249
- - encrypt, checksum, and sign backup manifests with timeline, format, LSN range,
250
- and key identity
251
- - restore into a new root, replay to an exact LSN or timestamp, verify its content
252
- digest, and promote atomically
253
- - retain logical export/import as migration tools rather than backup primitives
254
- - add versioned service classes, immutable node placement, node-bound grants,
255
- TLS/mTLS endpoints, credential rotation/revocation, quotas, metering, backup
256
- policy, maintenance windows, audit, and idempotent asynchronous operations
257
- - operate one process per tenant initially
258
- - qualify signed images, SBOM/provenance, canaries, rollback, alerts, runbooks, and
259
- security before any general-availability claim
260
-
261
- Launch order: internal alpha, private beta, then single-node GA with explicit
262
- availability, RPO, RTO, capacity, and compatibility limits.
263
-
264
- Gate: repeated maximum-size restore drills meet the published RPO/RTO; billing
265
- reconciles; upgrades and rollback/restore pass; cross-tenant network, auth, quota,
266
- backup, and restore isolation is proven; no plaintext secret reaches persisted or
267
- logged state.
268
-
269
- ## Phase 6: replication and high availability
270
-
271
- - replicate the Storage VNext log across three replicas in separate failure domains
272
- - add terms, quorum commit, snapshot installation, log catch-up, and membership
273
- changes
274
- - extend the single-node concern profile to multi-voter majority acknowledgement
275
- and cluster-time read concerns
276
- - publish accurate `hello` topology and election metadata
277
- - add causal times, retryable outcomes, idempotent transaction commits, and
278
- failover-safe session behavior
279
- - support mixed N/N-1 rolling upgrades
280
- - keep one database assigned to one replica group
281
-
282
- Majority RPO 0 means a majority-acknowledged write survives loss of any one replica
283
- within the declared replica-group fault model.
284
-
285
- Gate: no split-brain commits under partitions; accepted histories satisfy the
286
- declared consistency model; leader failure meets the published RTO; and retries
287
- return the original outcome exactly once.
288
-
289
- ## Phase 7: managed HA and compatibility expansion
290
-
291
- - place complete databases across replica groups
292
- - migrate a database through checkpoint transfer, log catch-up, and an atomic
293
- routing-epoch change
294
- - permanently fence stale owners
295
- - add automated replica replacement and maintenance-aware failover
296
- - derive durable change streams from the replicated commit log
297
- - certify additional drivers and ODMs
298
- - expand aggregation, views, indexes, and administrative behavior according to
299
- measured workload demand
300
- - publish machine-generated compatibility and SLO matrices
301
-
302
- Gate: no open P0/P1 defect in the certified surface, regional and maintenance
303
- exercises pass, and customer-visible incident/status processes are operational.
304
-
305
- ## Phase 8: horizontal scale
306
-
307
- Scale complete databases across replica groups first. Add intra-database sharding
308
- only after single-group limits become a measured customer constraint:
309
-
310
- - separate router and replicated placement catalog
311
- - range ownership and epochs
312
- - snapshot-plus-log range migration
313
- - stale-router rejection and permanent owner fencing
314
- - per-shard replica groups, balancing, and range cleanup
315
- - cross-shard transactions only as a separately justified program
316
-
317
- Gate: migration crashes cannot create gaps, duplicates, or dual writers; stale
318
- routing metadata cannot mutate old ownership; shard and region chaos meet the
319
- published SLOs.
320
-
321
- ## Release qualification
322
-
323
- Every applicable release must pass the narrowest relevant set of these gates:
324
-
325
- - raw-wire and target-driver handshake tests
326
- - generated semantic and certified compatibility suites
327
- - deterministic persistence failpoints and randomized process-kill tests
328
- - storage/index/content-digest reconciliation after recovery
329
- - 24-hour nightly and 72-hour release-candidate resource soaks
330
- - all published Linux and macOS architectures
331
- - automated backup/restore drills once backup exists
332
- - partition, failover, and history verification once replication exists
333
- - supply-chain, provenance, security, upgrade, and rollback checks for managed tiers
334
-
335
- No release may advertise a capability, durability level, topology, or operational
336
- limit that its release qualification did not exercise.
9
+ Regression coverage includes competing sparse/dense indexes, SCIM compound keys, candidate page count/byte boundaries, malformed hints, buffered transactions, foreign-stage rejection, 12,000-document finite probes, sources exceeding 32 MiB, retained resource caps, and shared aggregation work-budget enforcement.
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@push.rocks/smartdb',
6
- version: '5.5.1',
6
+ version: '5.6.0',
7
7
  description: 'A MongoDB-compatible embedded database server with wire protocol support, backed by a high-performance Rust engine.'
8
8
  }
package/readme.hints.md DELETED
@@ -1,77 +0,0 @@
1
- # smartdb hints
2
-
3
- ## Single-Node Concern Profile, Namespace Clock, and Deadlines (5.5.0)
4
-
5
- - `rustdb-commands/src/concerns.rs` is the sole owner of `readConcern`, `writeConcern`, and `maxTimeMS` validation. It runs in the router before authentication, sessions, permits, or gates. The profile is stated for one voting node: fsynced acknowledgement satisfies `w: 1`, `w: "majority"`, and `j: true`; `w: N > 1` is `UnsatisfiableWriteConcern` (100), tag sets are `UnknownReplWriteConcern` (79), cluster-time read concerns and misplaced fields are `InvalidOptions` (72), malformed deadlines are `BadValue` (2). `j: true` on `MemoryStorageAdapter` is `BadValue` through `StorageAdapter::journaled_writes()`. The driver sends a transaction's read concern on whichever statement starts the transaction, so a transaction-starting insert may carry one. Never accept a concern by widening an allowlist; every accepted value must map to a guarantee the engine actually provides.
6
- - `rustdb-commands/src/clock.rs` (`CommandContext::namespace_clock`) is the publication clock. Every in-process publication that changes visible namespace contents records `publish_namespace` while it still holds the namespace write lock (point writes, transaction commit completion, `create`, `drop`, `renameCollection`, `$out`, `$merge`, oplog revert) or `publish_database` (`dropDatabase`, in-process durable replacement through `invalidate_database_runtime`, and cross-process publication observed through `invalidate_database_runtime_for_epoch`). `$out` publishes right after it drops the old contents and again after the refill, so a failed refill still invalidates pinned snapshots. Index DDL does not change documents and does not publish. Adding a new mutation path without a publication is a snapshot-consistency bug.
7
- - Transactions pin `TransactionState::snapshot_sequence` when they materialize their first namespace. `transactions::load_transaction_docs_locked` requires the caller to hold the namespace write lock (insert/update/delete already do); `load_transaction_docs` acquires it for readers (`find`, `count`, `distinct`). A namespace whose `last_publication` exceeds the pinned sequence fails with `SnapshotUnavailable` (246); the router labels it `TransientTransactionError` so `withTransaction` restarts. This turns lazy per-namespace materialization into one database-wide snapshot without a second data copy; Storage VNext MVCC read timestamps replace the materialized copy itself.
8
- - Sessions retain `last_outcome` (`TransactionOutcome::Committed`/`Aborted` per transaction number) through `SessionEngine::finish_transaction_if_bound`. `commitTransaction`/`abortTransaction` without an active binding replay that outcome: repeated commit is `ok`, abort-after-commit is `TransactionCommitted` (256), commit-after-abort is `NoSuchTransaction` (251), and an older `txnNumber` on start is `TransactionTooOld` (225). Outcomes are process-local; after a crash the outcome of an in-flight commit is discoverable only from the data, which is why callers must journal their own attempts inside the transaction.
9
- - `rustdb-commands/src/deadline.rs` holds the `maxTimeMS` deadline in a tokio task-local set by `CommandRouter::route_with_response_policy`. Checks are cooperative: admission, `deadline::wait_bounded` inside `acquire_write_lock`/`acquire_maintenance_write_gate`, `wait_until_deadline` around the maintenance read lease, `check()` after materialization in readers, `check_every` in insert/delete loops, and one final `check()` before `apply_write_batch_with_completion` in commit. Handler futures are not cancellation-safe, so never wrap a handler in `tokio::time::timeout`; add a check at the next safe point instead. `SMARTDB_TEST_OPERATION_DELAY=<command>:<ms>` (test-support builds only) injects a pre-dispatch delay for deterministic expiry tests.
10
- - Error labels are derived from the response code in `attach_error_labels` so pre-dispatch rejections and handler errors label identically: transaction statements with 112/246/251 carry `TransientTransactionError`; `commitTransaction` with 50 or 64 carries `UnknownTransactionCommitResult`.
11
-
12
- ## Storage VNext A0 Committed Log
13
-
14
- - `rustdb-kernel` is a fixture-only, non-serving A0 durability slice. It is not linked into the released `rustdb` binary and provides no BSON, CRUD, MVCC, concern, deadline, migration, replication, or availability behavior.
15
- - The immutable `kernel-manifest.sdb` stores format, group, timeline, and fixed segment identity only. It never stores a mutable commit frontier. Complete prepared/commit-marker pairs in `commit-0000000000000001.sdb` are the sole A0 commit authority.
16
- - Each new command validates and prepares before append, receives the next contiguous nonzero LSN, and appends one `KPR1` prepared frame plus one `KCM1` marker binding the exact prepared bytes. Exact retries return the original LSN/response without appending; fingerprint conflicts, invalid commands, and segment exhaustion consume no LSN or state.
17
- - Any append or sync error after write admission is ambiguous and permanently fences that handle, including reads and exact retries. Reopen is the only reconciliation path. Reopen syncs every complete recovered segment before exposing state or receipts.
18
- - Recovery accepts only the declared timeline, contiguous LSNs, valid CRC frames, a matching marker position/hash, valid commands, and one durable record per receipt identity. It may truncate only an incomplete final frame of the expected kind or a complete valid prepared record without a complete marker. Complete corruption, wrong-kind tails, invalid prepared records, holes, duplicates, and marker mismatches fail without changing the segment.
19
- - The descriptor-safe root/framing primitives are shared by `rustdb-kernel` and `rustdb-replication`. Their common parent-slot/in-root lock namespace is intentional: kernel and Raft roots must be exclusive and are never interchangeable.
20
-
21
- ## Authoritative File Recovery
22
-
23
- - `data.rdb` is the sole runtime source for rebuilding KeyDir. The v1 `keydir.hint` format cannot prove completeness or data-generation identity, so existing regular hint files are tolerated for compatibility and diagnostics but their contents are never loaded as runtime state. New shutdowns, compactions, and v0-to-v1 migrations do not publish hints.
24
- - Runtime WAL scanning is bounded and strict: exact current headers, strictly increasing record sequences, operation shapes, lengths, CRCs, and nonduplicated commit references to preceding records must validate. Only an incomplete final record-header or commit-marker prefix with the expected magic is truncated. A complete header with a short payload and every checksum, sequence, magic, or interior failure stop startup without repairing either `data.rdb` or the WAL.
25
- - Recovery considers only the highest-sequence WAL record for each document key. If that final record is committed, no older markerless intent is replayed; if it is markerless, only that record is replayed. This prevents an older update or delete from overtaking a later acknowledged update or reinsert.
26
- - A point mutation whose data record reached `data.rdb` and fsynced before its WAL commit marker failed is successful so command indexes and OpLog publish the same mutation. The collection is then sticky-fenced: later document/index access and every write, batch publication, cache invalidation, rename, drop, and database replacement touching it fail until restart; maintenance may skip the collection but must never evict its fence. Pre-publication WAL/data append failures may continue only after both files are durably rolled back to their previously validated lengths; an unverified rollback fences instead.
27
- - `KeyDir::build_from_data_file()` streams every payload through CRC32 in fixed-size chunks before allocating its key and never allocates the declared value length. It may classify only a final prefix shorter than `RECORD_HEADER_SIZE` with matching record-magic bytes as an incomplete tail. A full header with a short payload and every checksum, magic, length, or UTF-8 key failure are corruption and must leave `data.rdb` unchanged.
28
- - Compaction durably removes any legacy hint and syncs the collection directory before replacing `data.rdb`. This ordering forces SmartDB 5.2.1 and earlier to rebuild after downgrade even when the compacted file happens to have the hint's old recorded size.
29
- - Startup maintenance may skip a publication-held database. Its first later storage access still performs the authoritative scan and fails unchanged on corruption; never infer validation of held data from listener startup alone.
30
- - Every cancellation-unsafe maintenance, fencing, auth, or storage worker must own a clone of the retained storage-root capability through its final file/lock cleanup. Provider installation is a finite joined startup sweep; periodic maintenance starts only after listener setup has no remaining fallible step. `close()` joins maintenance, `RustDb::drop()` requests cooperative shutdown, and Unix socket cleanup is bound to the exact device/inode created by `bind()`.
31
-
32
- ## Stopped Storage-Root Relocation
33
-
34
- - `LocalSmartDb.relocateStoppedStorageRoot()` is the only supported path-changing operation. It uses a dedicated serialized mutating sidecar runner; do not route it through the disposable offline-inspection helper. A bridge whose termination is unconfirmed remains in the static cleanup gate, and no later relocation may spawn until cleanup succeeds.
35
- - Rust owns the descriptor-relative operation in `rust/crates/rustdb/src/storage_root_relocation.rs`. It never constructs `RustDb`. The fixed journal phases are `preparing`, `prepared`, `exchanged`, `providerPublished`, `sentinelPublished`, and `cleaned`; retries reconcile the exact source-root/destination-absent-or-receipt topology or source-receipt/destination-root topology before continuing.
36
- - The destination receipt is published with an exclusive rename, then exchanged with the source root using an atomic swap (`RENAME_NOREPLACE`/`RENAME_EXCHANGE` on Linux and `RENAME_EXCL`/`RENAME_SWAP` on macOS). Provider and sentinel replacement also uses checked exchanges, retaining each previous object in the workspace until the replacement is durable and verified. The original root inode ends at the destination and the original receipt inode remains at the source indefinitely. Parent, root, internal, lock, provider, and sentinel identities are revalidated around publication.
37
- - Eligibility is intentionally narrow: Linux on the existing supported local-filesystem set or macOS on qualified local APFS, exact current owner/provider/sentinel metadata, no auth path digest, and no active resource receipt, allocation, database-mutation workspace, unrelated marker, symlink, unknown entry, or unsafe ownership/mode/link profile. A transaction workspace is eligible only when `rustdb-storage` validates its exact `cleaned` internal journal and matching database transaction marker; workspace debris, unfinished phases, mismatches, and allocation bindings remain unsupported. Empty retired legacy locks are eligible only with the canonical resource-digest/inode name parsed by `resource_fencing`, within its existing bound, and tied to one of those terminal transaction resources. macOS additionally rejects case, Unicode, mount, and ancestry aliases by retained physical identity. Missing metadata is rejected and never initialized by relocation.
38
- - Both TypeScript startup paths check for `.__rustdb_internal/storage-root-relocation` before `StorageMigrator`. Rust checks immediately after securely opening an existing root and repeats the descriptor-relative check after acquiring the owner lock, before storage initialization. This closes the interval where a relocation can create its workspace and release the lock after startup's first inspection. Occupancy or inspection ambiguity is a startup error; only an exact relocation retry performs recovery.
39
- - Completed roots retain the SmartDB 5.0.1 provider/sentinel JSON shape, changing only their storage-root path digest. Interrupted Linux state requires 5.1.0 or newer; interrupted macOS state requires a macOS-capable release. Exact replay lasts only while the destination remains current; a later relocation supersedes the old source/destination tuple.
40
-
41
- ## Restricted Deny-All Views
42
-
43
- - `rustdb-commands/src/views.rs` is the sole owner of `system.views` parsing, bounds, canonical `_id_` metadata validation, exact deny-all pipeline validation, and authoritative namespace classification. There is intentionally no mutable cross-command view cache; aggregate and transaction commit reuse one immutable authoritative catalog per database for that operation.
44
- - The only accepted definition is `viewOn: <same-db collection name>` plus exact pipeline `[{ $match: { $expr: { $eq: [1, 0] } } }]`. A logical view has no physical collection and never reads `viewOn`.
45
- - `system.views` is a physical reserved catalog. It is visible as a collection in wire `listCollections`, export, import, and content digest, but command-layer `IndexEngine` creation and direct wire access are forbidden. Internal view create/drop uses storage point insert/delete and preserves the storage adapter's canonical `_id` metadata.
46
- - Catalog loading is bounded to 1,024 view records and 1 MiB of encoded view documents and never enumerates all physical collections. Runtime validation checks each bounded logical name with `collection_exists`; snapshot/import validation uses its already-provided physical-name set without adding a runtime collection ceiling. Exact document shape is `_id`, `viewOn`, and `pipeline`; malformed records, noncanonical indexes, duplicate/reserved names, and physical/view collisions fail closed.
47
- - Publication permits validate once per newly observed publication state; databases without an epoch use an internal observed sentinel. Epoch refresh validates before recording the new observation. Startup validates databases whose publication lease can be acquired before listener bind; publication-held databases are validated on their first later permit. Snapshot/export explicitly revalidate. Import validates the source candidate, remaps only the exact source database prefix in catalog `_id` values, then validates the target candidate before mutation and clears its observed state after replacement.
48
- - Content digest hashes the physical catalog but removes its already-validated deterministic database prefix from `_id` first, preserving the database-name-independent digest contract across cross-name imports.
49
- - DDL and transaction commit take the maintenance write gate. View create/drop additionally lock the logical target and `${db}.system.views` in sorted order. View DDL validates the complete prospective catalog and performs cursor/index cleanup before its final point insert/delete, so cancellation cannot publish catalog state without cleanup. Commit locks every touched namespace in sorted order, loads one catalog per touched database, reclassifies each namespace, and transfers those guards into the storage completion closure.
50
- - Mutation handlers reclassify after acquiring their target namespace lock and before existence, auto-create, or lazy-index work. Logical-view data/index/output/rename mutations and direct `system.views` operations return `CommandNotSupportedOnView` code 166; `dropCollection` removes a logical view, while direct catalog drop remains forbidden. Ordinary create collision with a logical view returns `NamespaceExists`.
51
- - Find/count/distinct are empty outside a transaction, aggregate applies the client pipeline to an empty source, and lookup/union resolution is empty. A transaction first reading a current view snapshots an empty vector, while a populated snapshot captured before a rename-plus-view transition remains authoritative for find/count/distinct until commit revalidation. Do not infer view semantics from physical collection absence.
52
- - Successful create/drop/rename/dropDatabase publication removes affected namespace cursors before releasing DDL guards. A subsequent `getMore` cannot continue against stale namespace contents.
53
- - Management oplog revert rejects entries targeting `system.views` or a currently logical view. Logical-view `dropCollection` and whole-database drop are the catalog-removal exceptions; direct `system.views` drop is code 166. Database drop clears database indexes, cursors, oplog state, and observed publication state.
54
-
55
- ## Multikey Query Planning
56
-
57
- - SmartDB detects when an indexed path resolves through an array and keeps that state on the in-memory index until a complete rebuild.
58
- - Array-backed indexes are maintained for catalog and constraint compatibility but are not used to narrow queries; reads fall back to authoritative scans until full MongoDB multikey key expansion is implemented.
59
- - A scalar-to-multikey transition invalidates an in-progress paged index read with a write conflict; retrying starts with the authoritative scan path instead of returning a partial result.
60
- - Index data and multikey state are rebuilt from authoritative documents at startup, so this behavior requires no persisted-data migration.
61
-
62
- ## No-Op Write Detection (2.14.0)
63
-
64
- - `update`/`findAndModify` post-images that equal the stored document skip storage, WAL, index staging, and oplog entirely; volatile-only rewrites (top-level `_updatedAt` differs, everything else equal) are skipped the same way and keep the stored `_updatedAt`. Both report `matched=1, modified=0`.
65
- - Classification lives in `rustdb-commands/src/handlers/update_handler.rs` (`classify_document_rewrite`); the volatile field list is the `VOLATILE_METADATA_FIELDS` const. The comparison is key-order-insensitive (replacement paths re-append `_id`) and bails to "changed" on duplicate keys.
66
- - Counters: `serverStatus.writes.{updatesWritten, noopSkipped.identical, noopSkipped.volatileOnly}` backed by `WriteMetrics` on `CommandContext`. Wire-level coverage in `test/test.noop-writes.ts`.
67
- - Consequence for consumers: a save that changes nothing no longer bumps `_updatedAt` and emits no oplog event. To force a touch, change a non-volatile field.
68
-
69
- ## Static Rust Binaries
70
-
71
- - The Linux Rust binaries in `dist_rust/` are statically linked (static-pie) via `"static": true` in the `@git.zone/tsrust` block of `.smartconfig.json` (tsrust >= 1.4.1). They run on both glibc (Debian/Ubuntu) and musl (Alpine) systems. The macOS amd64 and arm64 binaries use the normal Apple platform linkage.
72
- - tsrust injects `RUSTFLAGS="-C target-feature=+crt-static"` only into its own per-target cargo invocations and verifies the result (no `PT_INTERP` ELF header). Keep `rust/.cargo/config.toml` free of `rustflags` entries: the injected env variable would replace them, and a repo-wide `rustflags` would also break plain `cargo test`/`cargo check` (proc-macros cannot build with `+crt-static` on linux-gnu without an explicit `--target`). The repo previously carried such `rustflags` lines; they were removed when the tsrust `static` option was adopted.
73
- - `pnpm run test:rust` runs the Rust unit tests; plain `cargo test` in `rust/` works as well.
74
- - Verify linkage manually with `ldd dist_rust/<binary>_linux_amd64` → "statically linked".
75
- - Do NOT verify feature presence in release binaries with `strings`/`grep`: on x86_64 release builds LLVM embeds short string literals (≤16 bytes, e.g. BSON doc keys like `volatileOnly`) as instruction immediates, so they are invisible to byte scans while the aarch64 binary shows them in `.rodata`. This produces false "stale binary" alarms. Verify behavior by running the binary (the wire tests spawn the host-arch binary from `dist_rust/`), or disassemble: `objdump -d <bin> | grep <hex-of-literal-LE>`.
76
- - Release builds use the tsrust 1.10 native matrix. The enabled gitzone test preflight checks the exact project-local tool, cross-execution, worker identities, toolchains, and remote root before versioning. The post-version build bundles TypeScript, transfers exact HEAD into isolated local and SSH workers, installs the frozen lockfile, executes all four target binaries, retrieves bounded artifact sets, and transactionally publishes the complete provenance matrix. Remote cleanup is limited to the unique owner-marked child below `SMARTDB_RELEASE_MACOS_TEMP_ROOT` and gates publication.
77
- - Workspace release-age exclusion arrays replace operator-global exclusions, and matrix workers use synthetic homes with a separate age policy. For immediate dependency-chain releases, enumerate every required exact audited package version across all install contexts; do not disable the age gate or widen an exception to a scope.