@feltdb/core 0.11.3 → 0.11.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +8 -6
  2. package/dist/architecture-invariant.d.ts +407 -0
  3. package/dist/architecture-invariant.d.ts.map +1 -0
  4. package/dist/architecture-invariant.js +708 -0
  5. package/dist/collection.d.ts +11 -1
  6. package/dist/collection.d.ts.map +1 -1
  7. package/dist/collection.js +37 -6
  8. package/dist/create/package-versions.js +1 -1
  9. package/dist/create/server-source/crates/feltdb-server/src/main.rs +1 -1
  10. package/dist/db.d.ts +9 -5
  11. package/dist/db.d.ts.map +1 -1
  12. package/dist/db.js +24 -6
  13. package/dist/embedded-query.d.ts +43 -0
  14. package/dist/embedded-query.d.ts.map +1 -0
  15. package/dist/embedded-query.js +327 -0
  16. package/dist/feltdb-vision-invariants.d.ts +46 -0
  17. package/dist/feltdb-vision-invariants.d.ts.map +1 -0
  18. package/dist/feltdb-vision-invariants.js +213 -0
  19. package/dist/feltdb.d.ts +12 -1
  20. package/dist/feltdb.d.ts.map +1 -1
  21. package/dist/file-db.d.ts +8 -0
  22. package/dist/file-db.d.ts.map +1 -1
  23. package/dist/file-db.js +24 -0
  24. package/dist/http-db.d.ts +14 -0
  25. package/dist/http-db.d.ts.map +1 -1
  26. package/dist/http-db.js +1 -0
  27. package/dist/index-core.d.ts +3 -0
  28. package/dist/index-core.d.ts.map +1 -1
  29. package/dist/index-core.js +2 -0
  30. package/dist/index-types.d.ts +5 -1
  31. package/dist/index-types.d.ts.map +1 -1
  32. package/dist/indexeddb-db.d.ts +18 -0
  33. package/dist/indexeddb-db.d.ts.map +1 -1
  34. package/dist/indexeddb-db.js +28 -0
  35. package/dist/memory-db.d.ts +8 -0
  36. package/dist/memory-db.d.ts.map +1 -1
  37. package/dist/memory-db.js +19 -0
  38. package/dist/studio-app/assets/index-Cg6EWmLb.js +30 -0
  39. package/dist/studio-app/index.html +1 -1
  40. package/package.json +1 -1
  41. package/dist/studio-app/assets/index-CSLtbbtP.js +0 -30
@@ -0,0 +1,327 @@
1
+ const now = () => typeof performance !== 'undefined' ? performance.now() : Date.now();
2
+ function compareValue(left, right) {
3
+ if (left === right)
4
+ return 0;
5
+ if ((left === undefined || left === null) && (right === undefined || right === null))
6
+ return 0;
7
+ if (left === undefined || left === null)
8
+ return -1;
9
+ if (right === undefined || right === null)
10
+ return 1;
11
+ if (typeof left === 'number' && typeof right === 'number')
12
+ return left < right ? -1 : 1;
13
+ return String(left).localeCompare(String(right));
14
+ }
15
+ function fields(config) {
16
+ if (config.fields?.length)
17
+ return config.fields.map((field, index) => ({ field, direction: config.directions?.[index] ?? 'asc' }));
18
+ if (config.field)
19
+ return [{ field: config.field, direction: config.direction ?? 'asc' }];
20
+ return [];
21
+ }
22
+ function recordId(collection, key, _record) {
23
+ return key.slice(collection.length + 1);
24
+ }
25
+ function bucketKey(value) {
26
+ return `${typeof value}:${JSON.stringify(value)}`;
27
+ }
28
+ function compareBySpecs(collection, specs, left, right) {
29
+ for (const spec of specs) {
30
+ const compared = compareValue(left.record[spec.field], right.record[spec.field]);
31
+ if (compared)
32
+ return spec.direction === 'asc' ? compared : -compared;
33
+ }
34
+ return recordId(collection, left.key, left.record).localeCompare(recordId(collection, right.key, right.record));
35
+ }
36
+ function conditionMatches(record, condition) {
37
+ const actual = record[condition.field];
38
+ if ('eq' in condition && actual !== condition.eq)
39
+ return false;
40
+ if ('neq' in condition && actual === condition.neq)
41
+ return false;
42
+ if ('lt' in condition && compareValue(actual, condition.lt) >= 0)
43
+ return false;
44
+ if ('lte' in condition && compareValue(actual, condition.lte) > 0)
45
+ return false;
46
+ if ('gt' in condition && compareValue(actual, condition.gt) <= 0)
47
+ return false;
48
+ if ('gte' in condition && compareValue(actual, condition.gte) < 0)
49
+ return false;
50
+ return true;
51
+ }
52
+ function binding(query) {
53
+ const shape = JSON.stringify({ collection: query.collection, where: query.where ?? [], orderBy: query.orderBy ?? [], limit: query.limit });
54
+ let hash = 0xcbf29ce484222325n;
55
+ for (let index = 0; index < shape.length; index += 1) {
56
+ hash ^= BigInt(shape.charCodeAt(index));
57
+ hash = BigInt.asUintN(64, hash * 0x100000001b3n);
58
+ }
59
+ return hash.toString(16).padStart(16, '0');
60
+ }
61
+ function encode(value) {
62
+ const json = JSON.stringify(value);
63
+ if (typeof Buffer !== 'undefined')
64
+ return Buffer.from(json).toString('base64url');
65
+ return btoa(unescape(encodeURIComponent(json))).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
66
+ }
67
+ function decode(cursor, expectedBinding) {
68
+ try {
69
+ const json = typeof Buffer !== 'undefined'
70
+ ? Buffer.from(cursor, 'base64url').toString('utf8')
71
+ : (() => {
72
+ const base64 = cursor.replace(/-/g, '+').replace(/_/g, '/');
73
+ return decodeURIComponent(escape(atob(base64.padEnd(Math.ceil(base64.length / 4) * 4, '='))));
74
+ })();
75
+ const value = JSON.parse(json);
76
+ if (value.v !== 1 || value.binding !== expectedBinding || !Array.isArray(value.values) || typeof value.key !== 'string')
77
+ throw new Error();
78
+ return value;
79
+ }
80
+ catch {
81
+ throw new Error('INVALID_CURSOR: cursor is malformed or does not match this query');
82
+ }
83
+ }
84
+ /** Small deterministic planner/executor owned by an embedded storage boundary. */
85
+ export class EmbeddedQueryEngine {
86
+ allRows;
87
+ indexes = new Map();
88
+ constructor(allRows) {
89
+ this.allRows = allRows;
90
+ this.rebuild();
91
+ }
92
+ rebuild() {
93
+ this.indexes.clear();
94
+ const rows = [...this.allRows()];
95
+ for (const [key, value] of rows)
96
+ this.installDefinition(key, value, rows);
97
+ }
98
+ apply(key, value) {
99
+ if (key.startsWith('__indexes__:')) {
100
+ if (value === undefined)
101
+ this.indexes.delete(key);
102
+ else
103
+ this.installDefinition(key, value, [...this.allRows()]);
104
+ return;
105
+ }
106
+ const separator = key.indexOf(':');
107
+ if (separator < 1)
108
+ return;
109
+ const collection = key.slice(0, separator);
110
+ for (const index of this.indexes.values()) {
111
+ if (index.collection !== collection)
112
+ continue;
113
+ const old = index.byKey.get(key);
114
+ if (old) {
115
+ const oldBucket = index.buckets.get(bucketKey(old.record[index.fields[0].field]));
116
+ const position = oldBucket?.findIndex(entry => entry.key === key) ?? -1;
117
+ if (position >= 0)
118
+ oldBucket.splice(position, 1);
119
+ index.byKey.delete(key);
120
+ }
121
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
122
+ const entry = { key, record: value };
123
+ const keyForBucket = bucketKey(entry.record[index.fields[0].field]);
124
+ let bucket = index.buckets.get(keyForBucket);
125
+ if (!bucket) {
126
+ bucket = [];
127
+ index.buckets.set(keyForBucket, bucket);
128
+ }
129
+ let low = 0, high = bucket.length;
130
+ while (low < high) {
131
+ const middle = (low + high) >>> 1;
132
+ if (compareBySpecs(collection, index.fields, bucket[middle], entry) <= 0)
133
+ low = middle + 1;
134
+ else
135
+ high = middle;
136
+ }
137
+ bucket.splice(low, 0, entry);
138
+ index.byKey.set(key, entry);
139
+ }
140
+ index.globalDirty = true;
141
+ }
142
+ }
143
+ installDefinition(key, value, rows) {
144
+ const parts = key.split(':');
145
+ if (parts.length < 3 || parts[0] !== '__indexes__' || !value || typeof value !== 'object')
146
+ return;
147
+ const config = value.config;
148
+ if (!config?.name)
149
+ return;
150
+ const collection = parts[1];
151
+ const indexFields = fields(config);
152
+ if (!indexFields.length || config.type === 'text')
153
+ return;
154
+ const prefix = `${collection}:`;
155
+ const entries = rows
156
+ .filter(([rowKey, row]) => rowKey.startsWith(prefix) && row && typeof row === 'object' && !Array.isArray(row))
157
+ .map(([rowKey, row]) => ({ key: rowKey, record: row }));
158
+ entries.sort((left, right) => compareBySpecs(collection, indexFields, left, right));
159
+ const buckets = new Map();
160
+ for (const entry of entries) {
161
+ const keyForBucket = bucketKey(entry.record[indexFields[0].field]);
162
+ const bucket = buckets.get(keyForBucket) ?? [];
163
+ bucket.push(entry);
164
+ buckets.set(keyForBucket, bucket);
165
+ }
166
+ this.indexes.set(key, { collection, config, fields: indexFields, entries, byKey: new Map(entries.map(entry => [entry.key, entry])), buckets, globalDirty: false });
167
+ }
168
+ plan(query) {
169
+ const equality = new Map((query.where ?? []).filter(value => 'eq' in value).map(value => [value.field, value.eq]));
170
+ const requested = query.orderBy ?? [];
171
+ for (const index of this.indexes.values()) {
172
+ if (index.collection !== query.collection)
173
+ continue;
174
+ let prefix = 0;
175
+ while (prefix < index.fields.length && equality.has(index.fields[prefix].field))
176
+ prefix += 1;
177
+ if (prefix === 0 && (query.where?.length ?? 0) > 0)
178
+ continue;
179
+ const remaining = index.fields.slice(prefix);
180
+ const exact = requested.every((order, offset) => remaining[offset]?.field === order.field && remaining[offset]?.direction === order.direction);
181
+ const automaticIdTie = remaining.length === requested.length;
182
+ const declaredIdTie = remaining.length === requested.length + 1 && remaining.at(-1)?.field === 'id' && remaining.at(-1)?.direction === 'asc';
183
+ if (requested.length && (!exact || (!automaticIdTie && !declaredIdTie)))
184
+ continue;
185
+ return {
186
+ index,
187
+ explanation: { plan: requested.length ? 'index-range' : 'index-filter', index: index.config.name, order: this.orderDescription(query), limit: query.limit, cursor: Boolean(query.cursor) },
188
+ };
189
+ }
190
+ return { explanation: { plan: 'full-scan', reason: 'no compatible index', order: this.orderDescription(query), limit: query.limit, cursor: Boolean(query.cursor) } };
191
+ }
192
+ explain(query) {
193
+ this.validate(query);
194
+ return this.plan(query).explanation;
195
+ }
196
+ execute(query) {
197
+ this.validate(query);
198
+ const started = now();
199
+ const planned = this.plan(query);
200
+ const stats = { scanned: 0, decoded: 0, matched: 0, sorted: 0, materialized: 0, returned: 0, usedIndex: Boolean(planned.index), indexName: planned.index?.config.name, indexLookupMs: 0, executionMs: 0 };
201
+ const conditions = query.where ?? [];
202
+ const order = query.orderBy ?? [];
203
+ const outputSpecs = order.map(value => ({ field: value.field, direction: value.direction }));
204
+ const cursor = query.cursor ? decode(query.cursor, binding(query)) : undefined;
205
+ const range = planned.index
206
+ ? this.indexRange(planned.index, conditions)
207
+ : (() => {
208
+ const entries = [...this.allRows()].filter(([key]) => key.startsWith(`${query.collection}:`)).map(([key, value]) => ({ key, record: value }));
209
+ return { entries, start: 0, end: entries.length };
210
+ })();
211
+ const candidates = range.entries;
212
+ let candidateStart = range.start;
213
+ if (planned.index && cursor) {
214
+ let low = range.start;
215
+ let high = range.end;
216
+ while (low < high) {
217
+ const middle = (low + high) >>> 1;
218
+ if (this.compareEntryCursor(query.collection, outputSpecs, candidates[middle], cursor) <= 0)
219
+ low = middle + 1;
220
+ else
221
+ high = middle;
222
+ }
223
+ candidateStart = low;
224
+ }
225
+ let matching = [];
226
+ const lookupStarted = now();
227
+ for (let candidateIndex = candidateStart; candidateIndex < range.end; candidateIndex += 1) {
228
+ const entry = candidates[candidateIndex];
229
+ stats.scanned += 1;
230
+ if (!entry.record || typeof entry.record !== 'object' || !conditions.every(condition => conditionMatches(entry.record, condition)))
231
+ continue;
232
+ stats.matched += 1;
233
+ matching.push(entry);
234
+ if (planned.index && matching.length > query.limit)
235
+ break;
236
+ }
237
+ stats.indexLookupMs = planned.index ? now() - lookupStarted : 0;
238
+ const fullScanMaterialized = matching.length;
239
+ if (!planned.index) {
240
+ matching.sort((left, right) => compareBySpecs(query.collection, outputSpecs, left, right));
241
+ stats.sorted = matching.length;
242
+ if (cursor)
243
+ matching = matching.filter(entry => this.afterCursor(query.collection, outputSpecs, entry, cursor));
244
+ }
245
+ const hasMore = matching.length > query.limit;
246
+ const pageEntries = matching.slice(0, query.limit);
247
+ const records = pageEntries.map(entry => entry.record);
248
+ stats.materialized = planned.index ? records.length : fullScanMaterialized;
249
+ stats.returned = records.length;
250
+ stats.executionMs = now() - started;
251
+ const last = pageEntries.at(-1);
252
+ const nextCursor = hasMore && last ? encode({ v: 1, binding: binding(query), values: order.map(value => last.record[value.field]), key: recordId(query.collection, last.key, last.record) }) : undefined;
253
+ return {
254
+ records,
255
+ ...(nextCursor ? { nextCursor } : {}),
256
+ exhausted: !nextCursor,
257
+ stats,
258
+ plan: { access_method: planned.explanation.plan, actual_rows_scanned: stats.scanned, actual_rows_returned: stats.returned, matching_records: stats.matched, index: stats.indexName, scan_fallback: !stats.usedIndex },
259
+ };
260
+ }
261
+ afterCursor(collection, order, entry, cursor) {
262
+ return this.compareEntryCursor(collection, order, entry, cursor) > 0;
263
+ }
264
+ compareEntryCursor(collection, order, entry, cursor) {
265
+ for (let index = 0; index < order.length; index += 1) {
266
+ const compared = compareValue(entry.record[order[index].field], cursor.values[index]);
267
+ if (compared)
268
+ return order[index].direction === 'asc' ? compared : -compared;
269
+ }
270
+ return recordId(collection, entry.key, entry.record).localeCompare(cursor.key);
271
+ }
272
+ indexRange(index, conditions) {
273
+ const equality = new Map(conditions.filter(value => 'eq' in value).map(value => [value.field, value.eq]));
274
+ let count = 0;
275
+ while (count < index.fields.length && equality.has(index.fields[count].field))
276
+ count += 1;
277
+ if (count === 0) {
278
+ if (index.globalDirty) {
279
+ index.entries = [...index.byKey.values()].sort((left, right) => compareBySpecs(index.collection, index.fields, left, right));
280
+ index.globalDirty = false;
281
+ }
282
+ return { entries: index.entries, start: 0, end: index.entries.length };
283
+ }
284
+ const entries = index.buckets.get(bucketKey(equality.get(index.fields[0].field))) ?? [];
285
+ if (count === 1)
286
+ return { entries, start: 0, end: entries.length };
287
+ const comparePrefix = (entry) => {
288
+ for (let position = 0; position < count; position += 1) {
289
+ const spec = index.fields[position];
290
+ const compared = compareValue(entry.record[spec.field], equality.get(spec.field));
291
+ if (compared)
292
+ return spec.direction === 'asc' ? compared : -compared;
293
+ }
294
+ return 0;
295
+ };
296
+ let low = 0, high = entries.length;
297
+ while (low < high) {
298
+ const middle = (low + high) >>> 1;
299
+ if (comparePrefix(entries[middle]) < 0)
300
+ low = middle + 1;
301
+ else
302
+ high = middle;
303
+ }
304
+ const start = low;
305
+ high = entries.length;
306
+ while (low < high) {
307
+ const middle = (low + high) >>> 1;
308
+ if (comparePrefix(entries[middle]) <= 0)
309
+ low = middle + 1;
310
+ else
311
+ high = middle;
312
+ }
313
+ return { entries, start, end: low };
314
+ }
315
+ orderDescription(query) {
316
+ return [...(query.orderBy ?? []).map(value => `${value.field} ${value.direction.toUpperCase()}`), 'id ASC'].join(', ');
317
+ }
318
+ validate(query) {
319
+ if (!query.collection?.trim() || !Number.isInteger(query.limit) || query.limit < 1 || query.limit > 1_000)
320
+ throw new Error('INVALID_QUERY: collection and a limit between 1 and 1000 are required');
321
+ for (const condition of query.where ?? []) {
322
+ const operators = ['eq', 'neq', 'lt', 'lte', 'gt', 'gte'].filter(operator => operator in condition);
323
+ if (!condition.field || operators.length !== 1)
324
+ throw new Error('INVALID_QUERY: each condition requires one operator');
325
+ }
326
+ }
327
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * FeltDB's own architectural invariants, as durable declarations.
3
+ *
4
+ * `docs/history/reports/VISION_INVARIANTS.md` is the human-readable source.
5
+ * This module is the same statements in the durable model, carrying the stable
6
+ * ids `FELTDB-001` … `FELTDB-009` that appear in that document, so the two can
7
+ * be compared rather than silently diverging. `npm run check:vision-invariants`
8
+ * compares them on every change.
9
+ *
10
+ * FeltDB is the first consumer of its own invariant substrate. It declares
11
+ * what must remain true; an advisory evaluator says whether the evidence it
12
+ * collected looks consistent with that, and the evaluation is retained here.
13
+ * Nothing in this module evaluates anything.
14
+ */
15
+ import type { CreateArchitectureInvariantInput, FeltDBArchitectureInvariantService } from './architecture-invariant.js';
16
+ import type { ArchitectureInvariant } from './architecture-invariant.js';
17
+ /** Scope every FeltDB invariant is declared over. */
18
+ export declare const FELTDB_VISION_SCOPE = "feltdb";
19
+ /** Category grouping the invariants that come from the Vision Invariants document. */
20
+ export declare const FELTDB_VISION_CATEGORY = "vision";
21
+ /**
22
+ * The declarations, in document order.
23
+ *
24
+ * Each `description` is the statement as the Vision Invariants document words
25
+ * it. Each `verification` entry names something that exists in this repository
26
+ * — a test, a repository check, or the source that implements the invariant —
27
+ * so an evaluator has somewhere real to look, and `human-review` is used where
28
+ * the honest answer is that a person decides.
29
+ */
30
+ export declare const FELTDB_VISION_INVARIANTS: readonly CreateArchitectureInvariantInput[];
31
+ export interface SeedInvariantOutcome {
32
+ id: string;
33
+ /** `created` on first declaration, `versioned` when the wording changed. */
34
+ outcome: 'created' | 'versioned' | 'unchanged';
35
+ version: number;
36
+ invariant: ArchitectureInvariant;
37
+ }
38
+ /**
39
+ * Declare FeltDB's own invariants into a FeltDB database.
40
+ *
41
+ * Idempotent, and honest about what it did: an invariant that is already
42
+ * declared with the same wording is left alone, and one whose wording changed
43
+ * becomes a new version rather than a rewrite of the old one.
44
+ */
45
+ export declare function seedFeltDBVisionInvariants(service: FeltDBArchitectureInvariantService, declarations?: readonly CreateArchitectureInvariantInput[], reason?: string): Promise<SeedInvariantOutcome[]>;
46
+ //# sourceMappingURL=feltdb-vision-invariants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feltdb-vision-invariants.d.ts","sourceRoot":"","sources":["../src/feltdb-vision-invariants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,gCAAgC,EAAE,kCAAkC,EAAE,MAAM,6BAA6B,CAAC;AACxH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAEzE,qDAAqD;AACrD,eAAO,MAAM,mBAAmB,WAAW,CAAC;AAC5C,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,WAAW,CAAC;AAE/C;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,EAAE,SAAS,gCAAgC,EAqK/E,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,4EAA4E;IAC5E,OAAO,EAAE,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,qBAAqB,CAAC;CAClC;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,kCAAkC,EAC3C,YAAY,GAAE,SAAS,gCAAgC,EAA6B,EACpF,MAAM,SAA4D,GACjE,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAwBjC"}
@@ -0,0 +1,213 @@
1
+ /** Scope every FeltDB invariant is declared over. */
2
+ export const FELTDB_VISION_SCOPE = 'feltdb';
3
+ /** Category grouping the invariants that come from the Vision Invariants document. */
4
+ export const FELTDB_VISION_CATEGORY = 'vision';
5
+ /**
6
+ * The declarations, in document order.
7
+ *
8
+ * Each `description` is the statement as the Vision Invariants document words
9
+ * it. Each `verification` entry names something that exists in this repository
10
+ * — a test, a repository check, or the source that implements the invariant —
11
+ * so an evaluator has somewhere real to look, and `human-review` is used where
12
+ * the honest answer is that a person decides.
13
+ */
14
+ export const FELTDB_VISION_INVARIANTS = [
15
+ {
16
+ id: 'FELTDB-001',
17
+ name: 'Collections feel like native state',
18
+ description: 'Applications use collection.get, all, where, insert, update, delete, and subscribe; '
19
+ + 'storage and network topology stay behind that API.',
20
+ category: FELTDB_VISION_CATEGORY,
21
+ severity: 'critical',
22
+ scope: FELTDB_VISION_SCOPE,
23
+ verification: [
24
+ { method: 'automated-test', reference: 'test:e2e/acceptance.test.ts' },
25
+ { method: 'source-analysis', reference: 'file:packages/core/src/collection.ts' },
26
+ {
27
+ method: 'jev-advisory',
28
+ evaluator: 'jev',
29
+ predicate: 'the change keeps storage runtime and network topology behind the collection API',
30
+ },
31
+ ],
32
+ references: [],
33
+ },
34
+ {
35
+ id: 'FELTDB-002',
36
+ name: 'One canonical mutation path',
37
+ description: 'Embedded, HTTP, replicated, workflow, and agent changes become the same durable operation. '
38
+ + 'Adapters may transport operations but may not invent a second store.',
39
+ category: FELTDB_VISION_CATEGORY,
40
+ severity: 'critical',
41
+ scope: FELTDB_VISION_SCOPE,
42
+ verification: [
43
+ { method: 'contract-conformance', reference: 'command:check:public-contract' },
44
+ { method: 'automated-test', reference: 'test:e2e/conditional-write-runtime-parity.test.mjs' },
45
+ { method: 'jev-advisory', evaluator: 'jev',
46
+ predicate: 'the change keeps every durable mutation on the one canonical operation path and adds no second store' },
47
+ ],
48
+ references: [],
49
+ },
50
+ {
51
+ id: 'FELTDB-003',
52
+ name: 'Local-first operation',
53
+ description: 'Local reads and writes do not require a network round trip. Offline mutations retain '
54
+ + 'causal identity and converge when peers return.',
55
+ category: FELTDB_VISION_CATEGORY,
56
+ severity: 'critical',
57
+ scope: FELTDB_VISION_SCOPE,
58
+ verification: [
59
+ { method: 'automated-test', reference: 'test:e2e/file-runtime-authority.test.mjs' },
60
+ { method: 'runtime-observation', reference: 'test:e2e/pr30-partition-healing-convergence.test.mjs' },
61
+ { method: 'jev-advisory', evaluator: 'jev',
62
+ predicate: 'the change keeps local reads and writes free of a required network round trip' },
63
+ ],
64
+ references: [],
65
+ },
66
+ {
67
+ id: 'FELTDB-004',
68
+ name: 'Reactivity is a database guarantee',
69
+ description: 'A committed local or remote mutation reaches live collections without '
70
+ + 'application-managed refetch, invalidation, or cache synchronization.',
71
+ category: FELTDB_VISION_CATEGORY,
72
+ severity: 'critical',
73
+ scope: FELTDB_VISION_SCOPE,
74
+ verification: [
75
+ { method: 'automated-test', reference: 'test:e2e/pr25-subscription-lifecycle.test.mjs' },
76
+ { method: 'source-analysis', reference: 'file:packages/core/src/reactive-graph.ts' },
77
+ { method: 'jev-advisory', evaluator: 'jev',
78
+ predicate: 'the change keeps committed mutations reaching live collections without application-managed refetch or cache synchronization' },
79
+ ],
80
+ references: [],
81
+ },
82
+ {
83
+ id: 'FELTDB-005',
84
+ name: 'References describe identity, not location',
85
+ description: 'flow:// references survive movement between runtimes; acquisition and routing resolve '
86
+ + 'them without leaking topology into application code.',
87
+ category: FELTDB_VISION_CATEGORY,
88
+ severity: 'critical',
89
+ scope: FELTDB_VISION_SCOPE,
90
+ verification: [
91
+ { method: 'automated-test', reference: 'test:e2e/peer-acquisition.test.mjs' },
92
+ { method: 'source-analysis', reference: 'file:packages/core/src/sync-contract.ts' },
93
+ { method: 'jev-advisory', evaluator: 'jev',
94
+ predicate: 'the change keeps flow:// references identity-bearing and does not leak runtime topology into application code' },
95
+ ],
96
+ references: [],
97
+ },
98
+ {
99
+ id: 'FELTDB-006',
100
+ name: 'Distribution preserves causality',
101
+ description: 'Replication retains origin and sequence, verifies content, rejects gaps, deduplicates '
102
+ + 'delivery, and never translates remote writes into unrelated local ones.',
103
+ category: FELTDB_VISION_CATEGORY,
104
+ severity: 'critical',
105
+ scope: FELTDB_VISION_SCOPE,
106
+ verification: [
107
+ { method: 'contract-conformance', reference: 'command:check:causal-authority' },
108
+ { method: 'automated-test', reference: 'test:e2e/pr27-three-node-catchup-convergence.test.mjs' },
109
+ { method: 'jev-advisory', evaluator: 'jev',
110
+ predicate: 'the change preserves replication origin, sequence, content verification, gap rejection, and delivery deduplication' },
111
+ ],
112
+ references: [],
113
+ },
114
+ {
115
+ id: 'FELTDB-007',
116
+ name: 'Capabilities derive from state',
117
+ description: 'Search, vectors, workflows, and agents consume and produce canonical state transitions '
118
+ + 'rather than maintaining authoritative side databases.',
119
+ category: FELTDB_VISION_CATEGORY,
120
+ severity: 'critical',
121
+ scope: FELTDB_VISION_SCOPE,
122
+ verification: [
123
+ { method: 'automated-test', reference: 'test:e2e/state-trigger-workload.test.mjs' },
124
+ { method: 'source-analysis', reference: 'file:packages/core/src/capability.ts' },
125
+ { method: 'jev-advisory', evaluator: 'jev',
126
+ predicate: 'the change keeps capabilities deriving from canonical state and introduces no authoritative side database' },
127
+ ],
128
+ references: [{
129
+ authority: '.flow',
130
+ reference: 'feltdb.flow',
131
+ relationship: 'FeltDB must not introduce an independent authoritative representation of a .flow declaration; '
132
+ + 'it compiles the declaration that .flow owns.',
133
+ }],
134
+ },
135
+ {
136
+ id: 'FELTDB-008',
137
+ name: 'Unavailable means unavailable',
138
+ description: 'Runtime discovery and health must not advertise scaffolded or simulated functionality '
139
+ + 'as production-ready.',
140
+ category: FELTDB_VISION_CATEGORY,
141
+ severity: 'critical',
142
+ scope: FELTDB_VISION_SCOPE,
143
+ verification: [
144
+ { method: 'contract-conformance', reference: 'command:check:managed-no-fallback' },
145
+ { method: 'automated-test', reference: 'test:e2e/public-contract-authority-loss.test.mjs' },
146
+ {
147
+ method: 'human-review',
148
+ notes: 'Whether a newly declared capability is genuinely production-ready is a judgment, '
149
+ + 'not a measurement. The checks catch a silent fallback; they cannot catch an honest mistake.',
150
+ },
151
+ { method: 'jev-advisory', evaluator: 'jev',
152
+ predicate: 'the change does not advertise scaffolded or simulated functionality as production-ready' },
153
+ ],
154
+ references: [],
155
+ },
156
+ {
157
+ id: 'FELTDB-009',
158
+ name: 'Durable state has one authority',
159
+ description: 'Every durable fact has exactly one canonical owner inside FeltDB. Events, indexes, '
160
+ + 'caches, projections, and adapters are derived and rebuildable, never an independent source of '
161
+ + 'truth, and every durable operation carries explicit tenant and application scope and provenance.',
162
+ category: FELTDB_VISION_CATEGORY,
163
+ severity: 'critical',
164
+ scope: FELTDB_VISION_SCOPE,
165
+ verification: [
166
+ { method: 'contract-conformance', reference: 'command:check:public-contract' },
167
+ { method: 'contract-conformance', reference: 'command:check:managed-authority' },
168
+ { method: 'source-analysis', reference: 'file:packages/core/src/authority-scope.ts' },
169
+ { method: 'jev-advisory', evaluator: 'jev',
170
+ predicate: 'the change keeps one canonical authority for every durable fact, with derived projections rebuildable and durable operations explicitly scoped' },
171
+ ],
172
+ references: [{
173
+ authority: 'authboundry',
174
+ reference: 'authorization decisions',
175
+ relationship: 'FeltDB stores the authorization decision identity as provenance and does not re-decide it. '
176
+ + 'Who may act remains AuthBoundry\'s; where a durable fact lives remains FeltDB\'s.',
177
+ }],
178
+ },
179
+ ];
180
+ /**
181
+ * Declare FeltDB's own invariants into a FeltDB database.
182
+ *
183
+ * Idempotent, and honest about what it did: an invariant that is already
184
+ * declared with the same wording is left alone, and one whose wording changed
185
+ * becomes a new version rather than a rewrite of the old one.
186
+ */
187
+ export async function seedFeltDBVisionInvariants(service, declarations = FELTDB_VISION_INVARIANTS, reason = 'synchronized with the FeltDB Vision Invariants document') {
188
+ const outcomes = [];
189
+ for (const declaration of declarations) {
190
+ let existing;
191
+ try {
192
+ existing = await service.invariants.get(declaration.id);
193
+ }
194
+ catch (error) {
195
+ if (error.code !== 'NOT_FOUND')
196
+ throw error;
197
+ }
198
+ if (!existing) {
199
+ const invariant = await service.invariants.create(declaration);
200
+ outcomes.push({ id: declaration.id, outcome: 'created', version: invariant.version, invariant });
201
+ continue;
202
+ }
203
+ const { id: _id, ...changes } = declaration;
204
+ const invariant = await service.invariants.update(declaration.id, { ...changes, reason });
205
+ outcomes.push({
206
+ id: declaration.id,
207
+ outcome: invariant.version === existing.version ? 'unchanged' : 'versioned',
208
+ version: invariant.version,
209
+ invariant,
210
+ });
211
+ }
212
+ return outcomes;
213
+ }
package/dist/feltdb.d.ts CHANGED
@@ -40,8 +40,19 @@ export interface JsDb {
40
40
  * Query data
41
41
  */
42
42
  query(query: string): any | Promise<any>;
43
- /** Execute a bounded query inside a remote authority. Embedded runtimes omit it. */
43
+ /** Execute a bounded query at the runtime's storage boundary. */
44
44
  authority_query?(query: unknown): Promise<unknown>;
45
+ /**
46
+ * Plain `Collection.find(query)` should delegate to `authority_query`.
47
+ *
48
+ * Embedded runtimes may expose `authority_query` for bounded execution while
49
+ * still keeping the unbounded Collection API on the local cache/index path.
50
+ */
51
+ collection_queries_via_authority?: boolean;
52
+ /** Explain a bounded query without executing it. */
53
+ explain_query?(query: unknown): unknown | Promise<unknown>;
54
+ /** Rebuild derived embedded indexes from authoritative records. */
55
+ rebuild_indexes?(): void | Promise<void>;
45
56
  /**
46
57
  * Get a record
47
58
  */
@@ -1 +1 @@
1
- {"version":3,"file":"feltdb.d.ts","sourceRoot":"","sources":["../src/feltdb.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"feltdb.d.ts","sourceRoot":"","sources":["../src/feltdb.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAEpE;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB;;OAEG;IACH,UAAU,CAAC,SAAS,EAAE,GAAG,GAAG,GAAG,CAAC;IAEhC;;OAEG;IACH,SAAS,IAAI,GAAG,CAAC;IAEjB;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;IAE/B;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;IAEpC;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;IAEvC;;OAEG;IACH,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,GAAG,CAAC;IAEnE;;OAEG;IACH,2BAA2B,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC;IAEpE;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEzC,iEAAiE;IACjE,eAAe,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEnD;;;;;OAKG;IACH,gCAAgC,CAAC,EAAE,OAAO,CAAC;IAE3C,oDAAoD;IACpD,aAAa,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE3D,mEAAmE;IACnE,eAAe,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzC;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAErC;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEvD,6DAA6D;IAC7D,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAExD,qDAAqD;IACrD,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEzC,2EAA2E;IAC3E,iBAAiB,CAAC,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IAC5F,KAAK,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/B;;OAEG;IACH,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC;IAEhD;;OAEG;IACH,WAAW,IAAI,MAAM,CAAC;IAEtB;;;;;;;;;OASG;IACH,YAAY,IAAI,MAAM,CAAC;IAEvB;;;;;;;OAOG;IACH,SAAS,CAAC,IAAI,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAEjE;;;;;;;OAOG;IACH,QAAQ,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE/B,0EAA0E;IAC1E,YAAY,CAAC,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEpC,6DAA6D;IAC7D,iBAAiB,CAAC,CAAC,cAAc,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/D,uBAAuB,CAAC,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEhE;;;;;;OAMG;IACH,WAAW,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAExF;;;;;;OAMG;IACH,GAAG,CAAC,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;IAErQ,8EAA8E;IAC9E,cAAc,CAAC,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAE1C,kFAAkF;IAClF,mBAAmB,CAAC,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAE/C;;;;;;OAMG;IACH,kBAAkB,CAAC,CAAC,OAAO,EAAE;QAC3B,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,KAAK,CAAC;YAChB,UAAU,EAAE,MAAM,CAAC;YACnB,EAAE,EAAE,MAAM,CAAC;YACX,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAChC,aAAa,CAAC,EAAE,OAAO,CAAC;YACxB;;;eAGG;YACH,eAAe,CAAC,EAAE,MAAM,CAAC;YACzB,aAAa,CAAC,EAAE,MAAM,CAAC;YACvB,eAAe,CAAC,EAAE,MAAM,CAAC;SAC1B,CAAC,CAAC;QACH,4DAA4D;QAC5D,aAAa,CAAC,EAAE,KAAK,CAAC;YACpB,UAAU,EAAE,MAAM,CAAC;YACnB,EAAE,EAAE,MAAM,CAAC;YACX,aAAa,CAAC,EAAE,OAAO,CAAC;YACxB,eAAe,CAAC,EAAE,MAAM,CAAC;YACzB,aAAa,CAAC,EAAE,MAAM,CAAC;YACvB,eAAe,CAAC,EAAE,MAAM,CAAC;SAC1B,CAAC,CAAC;KACJ,GAAG,OAAO,CAAC;QACV,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,EAAE,CAAC;KACxB,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB"}
package/dist/file-db.d.ts CHANGED
@@ -2,6 +2,7 @@ import type { JsDb } from './feltdb.js';
2
2
  import type { FreshnessCapability } from './freshness.js';
3
3
  import type { OperationAdmissionInput, OperationAdmissionResult, OperationTransitionInput, OperationTransitionResult } from './operation-admission.js';
4
4
  import type { AtomicTransactionRequest, AtomicTransactionResult } from './transaction.js';
5
+ import type { AuthorityQueryRequest } from './http-db.js';
5
6
  interface JsResult {
6
7
  success: boolean;
7
8
  data?: string;
@@ -27,6 +28,8 @@ export declare class FileJsDb implements JsDb {
27
28
  private lockFd;
28
29
  private lockToken;
29
30
  private readonly applied;
31
+ private readonly queryEngine;
32
+ private indexedSequence;
30
33
  constructor(path: string);
31
34
  private loadState;
32
35
  private loadStateFromBackup;
@@ -59,6 +62,11 @@ export declare class FileJsDb implements JsDb {
59
62
  get(key: string): JsResult;
60
63
  delete(key: string): JsResult;
61
64
  query(capability: string): JsResult;
65
+ authority_query<T = Record<string, unknown>>(query: AuthorityQueryRequest): Promise<import("./http-db.js").AuthorityQueryPage<T> & {
66
+ stats: import("./embedded-query.js").EmbeddedQueryStats;
67
+ }>;
68
+ explain_query(query: AuthorityQueryRequest): import("./embedded-query.js").EmbeddedQueryExplanation;
69
+ rebuild_indexes(): void;
62
70
  get_capability_records(capability: string): JsResult;
63
71
  execute_op(): JsResult;
64
72
  sync_info(): JsResult;