@remit/backend 0.0.27 → 0.0.29

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/backend",
3
- "version": "0.0.27",
3
+ "version": "0.0.29",
4
4
  "description": "Remit Mail Inspector API backend",
5
5
  "license": "MIT",
6
6
  "author": "",
@@ -194,6 +194,68 @@ describe("GET /system/update", () => {
194
194
  assert.equal(result.check.status, "failed");
195
195
  assert.deepEqual(result.run, run);
196
196
  });
197
+
198
+ it("passes both schema-version fields through when the state file carries them", async () => {
199
+ writeState({
200
+ currentVersion: "v1.4.1",
201
+ currentSchemaVersion: 5,
202
+ check: { ...okState.check, schemaVersion: 6 },
203
+ run: null,
204
+ });
205
+
206
+ const result = (await getUpdate(buildEvent(OWNER))) as {
207
+ currentSchemaVersion?: number;
208
+ check: { schemaVersion?: number };
209
+ };
210
+
211
+ assert.equal(result.currentSchemaVersion, 5);
212
+ assert.equal(result.check.schemaVersion, 6);
213
+ });
214
+
215
+ it("omits both schema-version fields when the state file predates them", async () => {
216
+ writeState(okState);
217
+
218
+ const result = (await getUpdate(buildEvent(OWNER))) as {
219
+ currentSchemaVersion?: number;
220
+ check: { schemaVersion?: number };
221
+ };
222
+
223
+ assert.ok(!("currentSchemaVersion" in result));
224
+ assert.ok(!("schemaVersion" in result.check));
225
+ });
226
+
227
+ it("carries currentSchemaVersion alone when the check has no schema version", async () => {
228
+ writeState({
229
+ currentVersion: "v1.4.1",
230
+ currentSchemaVersion: 5,
231
+ check: okState.check,
232
+ run: null,
233
+ });
234
+
235
+ const result = (await getUpdate(buildEvent(OWNER))) as {
236
+ currentSchemaVersion?: number;
237
+ check: { schemaVersion?: number };
238
+ };
239
+
240
+ assert.equal(result.currentSchemaVersion, 5);
241
+ assert.ok(!("schemaVersion" in result.check));
242
+ });
243
+
244
+ it("carries check.schemaVersion alone when currentSchemaVersion is absent", async () => {
245
+ writeState({
246
+ currentVersion: "v1.4.1",
247
+ check: { ...okState.check, schemaVersion: 6 },
248
+ run: null,
249
+ });
250
+
251
+ const result = (await getUpdate(buildEvent(OWNER))) as {
252
+ currentSchemaVersion?: number;
253
+ check: { schemaVersion?: number };
254
+ };
255
+
256
+ assert.ok(!("currentSchemaVersion" in result));
257
+ assert.equal(result.check.schemaVersion, 6);
258
+ });
197
259
  });
198
260
 
199
261
  describe("POST /system/update", () => {
@@ -4,14 +4,23 @@ import { isSelfHostSqlBackend } from "../data-backend.js";
4
4
  /**
5
5
  * Semantic-search capability gate for the self-host compose profiles.
6
6
  *
7
- * The backend container image ships neither `@huggingface/transformers` (query
8
- * embedding) nor `sqlite-vec` (the vector store's loadable extension, glibc-only
9
- * on top of that see npm-scripts/docker-bundle.mjs and deploy/vps/README.md).
10
- * Both are reached lazily through `runtimeImport`, so the first semantic query —
11
- * not startup hits ERR_MODULE_NOT_FOUND. Without this gate every search the
12
- * web client issues fires a `/search/semantic` request that 500s (the client
13
- * fetches semantic hits alongside every literal search), retried by the client
14
- * on top.
7
+ * This gates the free-text `/search/semantic` path only. Answering that query
8
+ * means embedding it in-process, and the backend container image ships without
9
+ * `@huggingface/transformers` (the model plus its dependencies would roughly
10
+ * quadruple the image see npm-scripts/docker-bundle.mjs and
11
+ * deploy/vps/README.md). The embedder is reached lazily through `runtimeImport`,
12
+ * so the first semantic query not startup hits ERR_MODULE_NOT_FOUND. Without
13
+ * this gate every search the web client issues fires a `/search/semantic`
14
+ * request that 500s (the client fetches semantic hits alongside every literal
15
+ * search), retried by the client on top.
16
+ *
17
+ * The vector STORE is a separate capability and is NOT gated here. The Organize
18
+ * anchor widen (organize.ts matchSemantic) pools an anchor message's already
19
+ * stored chunk vectors and runs a KNN read over the vector store — no embedding
20
+ * model involved — so it needs only `sqlite-vec`, which the backend image now
21
+ * carries as a musl build (Dockerfile sqlite-vec-musl stage,
22
+ * SQLITE_VEC_EXTENSION_PATH). matchOrganize never consults the memoized flag
23
+ * below; a missing embedder therefore never disables the widen.
15
24
  *
16
25
  * The e2e-dev lane runs this backend from source rather than the container, so
17
26
  * `@huggingface/transformers` IS present and the local embedder instead tries to