@raviolelabs/engram-mcp 0.5.3 → 0.5.4

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 (168) hide show
  1. package/dist/cloud/pairing.d.ts.map +1 -1
  2. package/dist/cloud/pairing.js +45 -4
  3. package/dist/cloud/pairing.js.map +1 -1
  4. package/package.json +1 -2
  5. package/dist/mcp-server/tests/mcp-e2e.test.d.ts +0 -2
  6. package/dist/mcp-server/tests/mcp-e2e.test.d.ts.map +0 -1
  7. package/dist/mcp-server/tests/mcp-e2e.test.js +0 -157
  8. package/dist/mcp-server/tests/mcp-e2e.test.js.map +0 -1
  9. package/dist/memory/modules/_custom/tests/custom-types.test.d.ts +0 -2
  10. package/dist/memory/modules/_custom/tests/custom-types.test.d.ts.map +0 -1
  11. package/dist/memory/modules/_custom/tests/custom-types.test.js +0 -96
  12. package/dist/memory/modules/_custom/tests/custom-types.test.js.map +0 -1
  13. package/dist/memory/modules/audio/tests/audio.test.d.ts +0 -2
  14. package/dist/memory/modules/audio/tests/audio.test.d.ts.map +0 -1
  15. package/dist/memory/modules/audio/tests/audio.test.js +0 -66
  16. package/dist/memory/modules/audio/tests/audio.test.js.map +0 -1
  17. package/dist/memory/modules/audio/tests/transcriber.test.d.ts +0 -2
  18. package/dist/memory/modules/audio/tests/transcriber.test.d.ts.map +0 -1
  19. package/dist/memory/modules/audio/tests/transcriber.test.js +0 -27
  20. package/dist/memory/modules/audio/tests/transcriber.test.js.map +0 -1
  21. package/dist/memory/modules/conversations/tests/conversations.test.d.ts +0 -2
  22. package/dist/memory/modules/conversations/tests/conversations.test.d.ts.map +0 -1
  23. package/dist/memory/modules/conversations/tests/conversations.test.js +0 -75
  24. package/dist/memory/modules/conversations/tests/conversations.test.js.map +0 -1
  25. package/dist/memory/modules/drive/tests/drive.test.d.ts +0 -2
  26. package/dist/memory/modules/drive/tests/drive.test.d.ts.map +0 -1
  27. package/dist/memory/modules/drive/tests/drive.test.js +0 -66
  28. package/dist/memory/modules/drive/tests/drive.test.js.map +0 -1
  29. package/dist/memory/modules/notes/tests/notes.test.d.ts +0 -2
  30. package/dist/memory/modules/notes/tests/notes.test.d.ts.map +0 -1
  31. package/dist/memory/modules/notes/tests/notes.test.js +0 -64
  32. package/dist/memory/modules/notes/tests/notes.test.js.map +0 -1
  33. package/dist/memory/modules/notion/tests/notion.test.d.ts +0 -2
  34. package/dist/memory/modules/notion/tests/notion.test.d.ts.map +0 -1
  35. package/dist/memory/modules/notion/tests/notion.test.js +0 -53
  36. package/dist/memory/modules/notion/tests/notion.test.js.map +0 -1
  37. package/dist/memory/modules/obsidian/tests/obsidian.test.d.ts +0 -2
  38. package/dist/memory/modules/obsidian/tests/obsidian.test.d.ts.map +0 -1
  39. package/dist/memory/modules/obsidian/tests/obsidian.test.js +0 -72
  40. package/dist/memory/modules/obsidian/tests/obsidian.test.js.map +0 -1
  41. package/dist/memory/modules/obsidian/tests/vault-reader.test.d.ts +0 -2
  42. package/dist/memory/modules/obsidian/tests/vault-reader.test.d.ts.map +0 -1
  43. package/dist/memory/modules/obsidian/tests/vault-reader.test.js +0 -37
  44. package/dist/memory/modules/obsidian/tests/vault-reader.test.js.map +0 -1
  45. package/dist/memory/modules/youtube/tests/channel.test.d.ts +0 -2
  46. package/dist/memory/modules/youtube/tests/channel.test.d.ts.map +0 -1
  47. package/dist/memory/modules/youtube/tests/channel.test.js +0 -61
  48. package/dist/memory/modules/youtube/tests/channel.test.js.map +0 -1
  49. package/dist/memory/modules/youtube/tests/transcript-fetcher.test.d.ts +0 -2
  50. package/dist/memory/modules/youtube/tests/transcript-fetcher.test.d.ts.map +0 -1
  51. package/dist/memory/modules/youtube/tests/transcript-fetcher.test.js +0 -23
  52. package/dist/memory/modules/youtube/tests/transcript-fetcher.test.js.map +0 -1
  53. package/dist/memory/modules/youtube/tests/youtube.test.d.ts +0 -2
  54. package/dist/memory/modules/youtube/tests/youtube.test.d.ts.map +0 -1
  55. package/dist/memory/modules/youtube/tests/youtube.test.js +0 -61
  56. package/dist/memory/modules/youtube/tests/youtube.test.js.map +0 -1
  57. package/dist/sync/tests/apply.test.d.ts +0 -4
  58. package/dist/sync/tests/apply.test.d.ts.map +0 -1
  59. package/dist/sync/tests/apply.test.js +0 -117
  60. package/dist/sync/tests/apply.test.js.map +0 -1
  61. package/dist/sync/tests/ops-log.test.d.ts +0 -2
  62. package/dist/sync/tests/ops-log.test.d.ts.map +0 -1
  63. package/dist/sync/tests/ops-log.test.js +0 -105
  64. package/dist/sync/tests/ops-log.test.js.map +0 -1
  65. package/dist/sync/tests/two-device-sync.test.d.ts +0 -2
  66. package/dist/sync/tests/two-device-sync.test.d.ts.map +0 -1
  67. package/dist/sync/tests/two-device-sync.test.js +0 -250
  68. package/dist/sync/tests/two-device-sync.test.js.map +0 -1
  69. package/dist/tests/chunker.test.d.ts +0 -2
  70. package/dist/tests/chunker.test.d.ts.map +0 -1
  71. package/dist/tests/chunker.test.js +0 -24
  72. package/dist/tests/chunker.test.js.map +0 -1
  73. package/dist/tests/cloud-auth.test.d.ts +0 -2
  74. package/dist/tests/cloud-auth.test.d.ts.map +0 -1
  75. package/dist/tests/cloud-auth.test.js +0 -75
  76. package/dist/tests/cloud-auth.test.js.map +0 -1
  77. package/dist/tests/cloud-crypto.test.d.ts +0 -2
  78. package/dist/tests/cloud-crypto.test.d.ts.map +0 -1
  79. package/dist/tests/cloud-crypto.test.js +0 -58
  80. package/dist/tests/cloud-crypto.test.js.map +0 -1
  81. package/dist/tests/cloud-integration.test.d.ts +0 -2
  82. package/dist/tests/cloud-integration.test.d.ts.map +0 -1
  83. package/dist/tests/cloud-integration.test.js +0 -193
  84. package/dist/tests/cloud-integration.test.js.map +0 -1
  85. package/dist/tests/cloud-pairing.test.d.ts +0 -2
  86. package/dist/tests/cloud-pairing.test.d.ts.map +0 -1
  87. package/dist/tests/cloud-pairing.test.js +0 -86
  88. package/dist/tests/cloud-pairing.test.js.map +0 -1
  89. package/dist/tests/cloud-saves-integration.test.d.ts +0 -2
  90. package/dist/tests/cloud-saves-integration.test.d.ts.map +0 -1
  91. package/dist/tests/cloud-saves-integration.test.js +0 -92
  92. package/dist/tests/cloud-saves-integration.test.js.map +0 -1
  93. package/dist/tests/cloud-transit.test.d.ts +0 -2
  94. package/dist/tests/cloud-transit.test.d.ts.map +0 -1
  95. package/dist/tests/cloud-transit.test.js +0 -263
  96. package/dist/tests/cloud-transit.test.js.map +0 -1
  97. package/dist/tests/config.test.d.ts +0 -2
  98. package/dist/tests/config.test.d.ts.map +0 -1
  99. package/dist/tests/config.test.js +0 -25
  100. package/dist/tests/config.test.js.map +0 -1
  101. package/dist/tests/db.test.d.ts +0 -2
  102. package/dist/tests/db.test.d.ts.map +0 -1
  103. package/dist/tests/db.test.js +0 -73
  104. package/dist/tests/db.test.js.map +0 -1
  105. package/dist/tests/embeddings-providers.test.d.ts +0 -2
  106. package/dist/tests/embeddings-providers.test.d.ts.map +0 -1
  107. package/dist/tests/embeddings-providers.test.js +0 -62
  108. package/dist/tests/embeddings-providers.test.js.map +0 -1
  109. package/dist/tests/embeddings.test.d.ts +0 -2
  110. package/dist/tests/embeddings.test.d.ts.map +0 -1
  111. package/dist/tests/embeddings.test.js +0 -22
  112. package/dist/tests/embeddings.test.js.map +0 -1
  113. package/dist/tests/integrations-api.test.d.ts +0 -2
  114. package/dist/tests/integrations-api.test.d.ts.map +0 -1
  115. package/dist/tests/integrations-api.test.js +0 -129
  116. package/dist/tests/integrations-api.test.js.map +0 -1
  117. package/dist/tests/memory-store.test.d.ts +0 -2
  118. package/dist/tests/memory-store.test.d.ts.map +0 -1
  119. package/dist/tests/memory-store.test.js +0 -129
  120. package/dist/tests/memory-store.test.js.map +0 -1
  121. package/dist/tests/module-registry.test.d.ts +0 -2
  122. package/dist/tests/module-registry.test.d.ts.map +0 -1
  123. package/dist/tests/module-registry.test.js +0 -44
  124. package/dist/tests/module-registry.test.js.map +0 -1
  125. package/dist/tests/property-extractor.test.d.ts +0 -2
  126. package/dist/tests/property-extractor.test.d.ts.map +0 -1
  127. package/dist/tests/property-extractor.test.js +0 -24
  128. package/dist/tests/property-extractor.test.js.map +0 -1
  129. package/dist/tests/public-tools.test.d.ts +0 -2
  130. package/dist/tests/public-tools.test.d.ts.map +0 -1
  131. package/dist/tests/public-tools.test.js +0 -286
  132. package/dist/tests/public-tools.test.js.map +0 -1
  133. package/dist/tests/reindex.test.d.ts +0 -2
  134. package/dist/tests/reindex.test.d.ts.map +0 -1
  135. package/dist/tests/reindex.test.js +0 -58
  136. package/dist/tests/reindex.test.js.map +0 -1
  137. package/dist/tests/scope-encryption.test.d.ts +0 -2
  138. package/dist/tests/scope-encryption.test.d.ts.map +0 -1
  139. package/dist/tests/scope-encryption.test.js +0 -71
  140. package/dist/tests/scope-encryption.test.js.map +0 -1
  141. package/dist/tests/shamir.test.d.ts +0 -2
  142. package/dist/tests/shamir.test.d.ts.map +0 -1
  143. package/dist/tests/shamir.test.js +0 -57
  144. package/dist/tests/shamir.test.js.map +0 -1
  145. package/dist/tests/source-registry.test.d.ts +0 -2
  146. package/dist/tests/source-registry.test.d.ts.map +0 -1
  147. package/dist/tests/source-registry.test.js +0 -58
  148. package/dist/tests/source-registry.test.js.map +0 -1
  149. package/dist/tests/types.test.d.ts +0 -2
  150. package/dist/tests/types.test.d.ts.map +0 -1
  151. package/dist/tests/types.test.js +0 -26
  152. package/dist/tests/types.test.js.map +0 -1
  153. package/dist/tests/vector.test.d.ts +0 -2
  154. package/dist/tests/vector.test.d.ts.map +0 -1
  155. package/dist/tests/vector.test.js +0 -61
  156. package/dist/tests/vector.test.js.map +0 -1
  157. package/dist/tests/wikilinks.test.d.ts +0 -2
  158. package/dist/tests/wikilinks.test.d.ts.map +0 -1
  159. package/dist/tests/wikilinks.test.js +0 -20
  160. package/dist/tests/wikilinks.test.js.map +0 -1
  161. package/dist/webapp/tests/api.test.d.ts +0 -2
  162. package/dist/webapp/tests/api.test.d.ts.map +0 -1
  163. package/dist/webapp/tests/api.test.js +0 -125
  164. package/dist/webapp/tests/api.test.js.map +0 -1
  165. package/dist/webapp/tests/mcp-http.test.d.ts +0 -2
  166. package/dist/webapp/tests/mcp-http.test.d.ts.map +0 -1
  167. package/dist/webapp/tests/mcp-http.test.js +0 -47
  168. package/dist/webapp/tests/mcp-http.test.js.map +0 -1
@@ -1,75 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import fs from 'fs';
3
- import os from 'os';
4
- import path from 'path';
5
- import { initDb, closeDb } from '../db/index.js';
6
- import { saveTokens, loadTokens, clearTokens, isPaired, parseJwtExpiry, getApiKey, } from '../cloud/auth.js';
7
- // Minimal JWT with exp claim — not a real signed JWT but parseJwtExpiry only
8
- // reads the payload, so this is fine for unit tests.
9
- function makeTestJwt(expUnix) {
10
- const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64url');
11
- const payload = Buffer.from(JSON.stringify({ sub: 'user_test', exp: expUnix })).toString('base64url');
12
- return `${header}.${payload}.fakesig`;
13
- }
14
- describe('cloud/auth', () => {
15
- let tmpDir;
16
- beforeEach(() => {
17
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'engram-auth-'));
18
- initDb(tmpDir);
19
- });
20
- afterEach(() => {
21
- closeDb();
22
- fs.rmSync(tmpDir, { recursive: true, force: true });
23
- });
24
- it('isPaired() returns false before any save', () => {
25
- expect(isPaired()).toBe(false);
26
- });
27
- it('saveTokens + loadTokens round-trips all fields', () => {
28
- const expMs = Date.now() + 3600_000;
29
- const jwt = makeTestJwt(Math.floor(expMs / 1000));
30
- saveTokens({ jwt, refreshToken: 'rt-abc', apiKey: 'ak-xyz', expiresAt: expMs });
31
- expect(isPaired()).toBe(true);
32
- const loaded = loadTokens();
33
- expect(loaded).not.toBeNull();
34
- expect(loaded.jwt).toBe(jwt);
35
- expect(loaded.refreshToken).toBe('rt-abc');
36
- expect(loaded.apiKey).toBe('ak-xyz');
37
- expect(loaded.expiresAt).toBe(expMs);
38
- });
39
- it('saveTokens is idempotent — overwrites on second call', () => {
40
- const exp1 = Date.now() + 1000;
41
- const exp2 = Date.now() + 9999;
42
- saveTokens({ jwt: 'jwt1', refreshToken: 'rt1', apiKey: 'ak1', expiresAt: exp1 });
43
- saveTokens({ jwt: 'jwt2', refreshToken: 'rt2', apiKey: 'ak2', expiresAt: exp2 });
44
- const t = loadTokens();
45
- expect(t.jwt).toBe('jwt2');
46
- expect(t.apiKey).toBe('ak2');
47
- });
48
- it('clearTokens removes the row', () => {
49
- saveTokens({ jwt: 'j', refreshToken: 'r', apiKey: 'a', expiresAt: 1 });
50
- clearTokens();
51
- expect(isPaired()).toBe(false);
52
- expect(loadTokens()).toBeNull();
53
- });
54
- it('parseJwtExpiry extracts exp in ms', () => {
55
- const expSec = Math.floor(Date.now() / 1000) + 3600;
56
- const jwt = makeTestJwt(expSec);
57
- expect(parseJwtExpiry(jwt)).toBe(expSec * 1000);
58
- });
59
- it('parseJwtExpiry throws on malformed JWT', () => {
60
- expect(() => parseJwtExpiry('notajwt')).toThrow(/Malformed/);
61
- });
62
- it('getApiKey throws when not paired', () => {
63
- expect(() => getApiKey()).toThrow(/Not paired/);
64
- });
65
- it('getApiKey returns stored key when paired', () => {
66
- saveTokens({
67
- jwt: makeTestJwt(Math.floor(Date.now() / 1000) + 3600),
68
- refreshToken: 'rt',
69
- apiKey: 'my-api-key',
70
- expiresAt: Date.now() + 3600_000,
71
- });
72
- expect(getApiKey()).toBe('my-api-key');
73
- });
74
- });
75
- //# sourceMappingURL=cloud-auth.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cloud-auth.test.js","sourceRoot":"","sources":["../../src/tests/cloud-auth.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=cloud-crypto.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cloud-crypto.test.d.ts","sourceRoot":"","sources":["../../src/tests/cloud-crypto.test.ts"],"names":[],"mappings":""}
@@ -1,58 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { generateMasterKeySalt, deriveMasterKey, encryptBlob, decryptBlob, generateEphemeralKeypair, deriveSessionKey, } from '../cloud/crypto.js';
3
- describe('cloud/crypto', () => {
4
- it('generateMasterKeySalt returns 64-char hex string (32 bytes)', async () => {
5
- const salt = await generateMasterKeySalt();
6
- expect(typeof salt).toBe('string');
7
- expect(salt).toHaveLength(64);
8
- expect(/^[0-9a-f]+$/i.test(salt)).toBe(true);
9
- });
10
- it('deriveMasterKey produces 32-byte key deterministically', async () => {
11
- const salt = await generateMasterKeySalt();
12
- const key1 = await deriveMasterKey('correct horse battery staple', salt);
13
- const key2 = await deriveMasterKey('correct horse battery staple', salt);
14
- expect(key1.length).toBe(32);
15
- expect(Buffer.from(key1).toString('hex')).toBe(Buffer.from(key2).toString('hex'));
16
- });
17
- it('deriveMasterKey differs for different passphrases', async () => {
18
- const salt = await generateMasterKeySalt();
19
- const k1 = await deriveMasterKey('passA', salt);
20
- const k2 = await deriveMasterKey('passB', salt);
21
- expect(Buffer.from(k1).toString('hex')).not.toBe(Buffer.from(k2).toString('hex'));
22
- });
23
- it('encryptBlob + decryptBlob round-trips cleanly', async () => {
24
- const salt = await generateMasterKeySalt();
25
- const key = await deriveMasterKey('test passphrase', salt);
26
- const plaintext = new TextEncoder().encode('Hello, Engram transit!');
27
- const wire = await encryptBlob(plaintext, key);
28
- // wire length = 24 (nonce) + plaintext + 16 (Poly1305 MAC)
29
- expect(wire.length).toBe(24 + plaintext.length + 16);
30
- const recovered = await decryptBlob(wire, key);
31
- expect(new TextDecoder().decode(recovered)).toBe('Hello, Engram transit!');
32
- });
33
- it('decryptBlob throws on wrong key', async () => {
34
- const salt = await generateMasterKeySalt();
35
- const keyGood = await deriveMasterKey('right', salt);
36
- const keyBad = await deriveMasterKey('wrong', salt);
37
- const wire = await encryptBlob(new TextEncoder().encode('secret'), keyGood);
38
- await expect(decryptBlob(wire, keyBad)).rejects.toThrow(/[Dd]ecryption failed/);
39
- });
40
- it('decryptBlob throws on truncated input', async () => {
41
- const salt = await generateMasterKeySalt();
42
- const key = await deriveMasterKey('pass', salt);
43
- await expect(decryptBlob(new Uint8Array(10), key)).rejects.toThrow(/too short/);
44
- });
45
- it('generateEphemeralKeypair returns valid 32-byte keys', async () => {
46
- const { publicKey, privateKey } = await generateEphemeralKeypair();
47
- expect(publicKey.length).toBe(32);
48
- expect(privateKey.length).toBe(32);
49
- });
50
- it('deriveSessionKey is commutative (DH)', async () => {
51
- const alice = await generateEphemeralKeypair();
52
- const bob = await generateEphemeralKeypair();
53
- const s1 = await deriveSessionKey(alice.privateKey, bob.publicKey);
54
- const s2 = await deriveSessionKey(bob.privateKey, alice.publicKey);
55
- expect(Buffer.from(s1).toString('hex')).toBe(Buffer.from(s2).toString('hex'));
56
- });
57
- });
58
- //# sourceMappingURL=cloud-crypto.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cloud-crypto.test.js","sourceRoot":"","sources":["../../src/tests/cloud-crypto.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=cloud-integration.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cloud-integration.test.d.ts","sourceRoot":"","sources":["../../src/tests/cloud-integration.test.ts"],"names":[],"mappings":""}
@@ -1,193 +0,0 @@
1
- /**
2
- * src/tests/cloud-integration.test.ts
3
- *
4
- * End-to-end integration test for Plan K:
5
- * - Pairing flow (simulated callback)
6
- * - Crypto key derivation
7
- * - Transit poll → decrypt → ingest → ack
8
- *
9
- * Uses real SQLite + real LanceDB + real Ollama embeddings.
10
- * Uses mock HTTP servers for Plan I/J endpoints.
11
- * No real cloud needed.
12
- */
13
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
14
- import fs from 'fs';
15
- import os from 'os';
16
- import path from 'path';
17
- import http from 'http';
18
- import { ulid } from 'ulid';
19
- import { initDb, closeDb, getDb } from '../db/index.js';
20
- import { initVectorStore } from '../vector/store.js';
21
- import { MemoryStore } from '../memory/core/store.js';
22
- import { saveTokens, loadTokens, isPaired } from '../cloud/auth.js';
23
- import { generateMasterKeySalt, deriveMasterKey, encryptBlob } from '../cloud/crypto.js';
24
- import { pollOnce } from '../cloud/transit-poller.js';
25
- function buildMockServer(state) {
26
- return new Promise((res) => {
27
- const server = http.createServer((req, resp) => {
28
- const u = new URL(req.url, 'http://localhost');
29
- if (req.method === 'GET' && u.pathname === '/transit/inbox') {
30
- const since = u.searchParams.get('since') ?? '';
31
- resp.writeHead(200, { 'Content-Type': 'application/json' });
32
- resp.end(JSON.stringify({ items: state.inbox.filter((i) => i.createdAt > since) }));
33
- return;
34
- }
35
- if (req.method === 'GET' && u.pathname.startsWith('/blob/')) {
36
- const id = u.pathname.slice(6);
37
- const blob = state.blobs.get(id);
38
- if (!blob) {
39
- resp.writeHead(404);
40
- resp.end();
41
- return;
42
- }
43
- resp.writeHead(200);
44
- resp.end(Buffer.from(blob));
45
- return;
46
- }
47
- if (req.method === 'POST' && u.pathname === '/transit/ack') {
48
- let body = '';
49
- req.on('data', (d) => (body += d));
50
- req.on('end', () => {
51
- const { id } = JSON.parse(body);
52
- state.ackedIds.push(id);
53
- state.inbox = state.inbox.filter((i) => i.id !== id);
54
- resp.writeHead(200);
55
- resp.end(JSON.stringify({ ok: true }));
56
- });
57
- return;
58
- }
59
- resp.writeHead(404);
60
- resp.end();
61
- });
62
- server.listen(0, '127.0.0.1', () => {
63
- const addr = server.address();
64
- res({ server, url: `http://127.0.0.1:${addr.port}` });
65
- });
66
- });
67
- }
68
- function fakeJwt(expSec) {
69
- const h = Buffer.from(JSON.stringify({ alg: 'HS256' })).toString('base64url');
70
- const p = Buffer.from(JSON.stringify({ sub: 'u', exp: expSec })).toString('base64url');
71
- return `${h}.${p}.sig`;
72
- }
73
- // ---------------------------------------------------------------------------
74
- // Tests
75
- // ---------------------------------------------------------------------------
76
- describe('Plan K integration — pairing + transit cycle', () => {
77
- let tmpDir;
78
- let store;
79
- let state;
80
- let server;
81
- let baseUrl;
82
- const passphrase = 'integration-test-passphrase-secure-enough';
83
- beforeEach(async () => {
84
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'engram-k-integ-'));
85
- initDb(tmpDir);
86
- initVectorStore(tmpDir);
87
- store = new MemoryStore({
88
- embeddings: {
89
- provider: 'ollama',
90
- baseUrl: 'http://localhost:11434',
91
- model: 'nomic-embed-text',
92
- dimensions: 768,
93
- },
94
- });
95
- state = { inbox: [], ackedIds: [], blobs: new Map() };
96
- const started = await buildMockServer(state);
97
- server = started.server;
98
- baseUrl = started.url;
99
- });
100
- afterEach(() => {
101
- closeDb();
102
- server.close();
103
- fs.rmSync(tmpDir, { recursive: true, force: true });
104
- });
105
- it('simulated pairing stores tokens in oauth_tokens', () => {
106
- // Simulate what startPairing() + saveTokens() does after receiving callback
107
- expect(isPaired()).toBe(false);
108
- const expSec = Math.floor(Date.now() / 1000) + 3600;
109
- saveTokens({
110
- jwt: fakeJwt(expSec),
111
- refreshToken: 'refresh-abc',
112
- apiKey: 'api-key-xyz',
113
- expiresAt: expSec * 1000,
114
- });
115
- expect(isPaired()).toBe(true);
116
- const tokens = loadTokens();
117
- expect(tokens.apiKey).toBe('api-key-xyz');
118
- expect(tokens.refreshToken).toBe('refresh-abc');
119
- });
120
- it('full cycle: pair → derive key → encrypt on mobile → poll → decrypt → ingest → ack', async () => {
121
- // --- Simulate pairing ---
122
- const saltHex = await generateMasterKeySalt();
123
- const expSec = Math.floor(Date.now() / 1000) + 3600;
124
- saveTokens({
125
- jwt: fakeJwt(expSec),
126
- refreshToken: 'rt',
127
- apiKey: 'ak',
128
- expiresAt: expSec * 1000,
129
- });
130
- // --- Simulate mobile: derive same key and encrypt a note ---
131
- const masterKey = await deriveMasterKey(passphrase, saltHex);
132
- const plaintext = new TextEncoder().encode('Met with the team today. Key decision: ship Plan K by end of sprint.');
133
- const encrypted = await encryptBlob(plaintext, masterKey);
134
- // --- Populate mock transit inbox ---
135
- const itemId = ulid();
136
- state.blobs.set(itemId, encrypted);
137
- state.inbox.push({
138
- id: itemId,
139
- type: 'text',
140
- downloadUrl: `${baseUrl}/blob/${itemId}`,
141
- createdAt: new Date().toISOString(),
142
- mimeType: 'text/plain',
143
- filename: 'meeting-note.txt',
144
- sizeBytes: encrypted.length,
145
- });
146
- // --- PC polls ---
147
- const config = {
148
- dataDir: tmpDir,
149
- embeddings: {
150
- provider: 'ollama',
151
- baseUrl: 'http://localhost:11434',
152
- model: 'nomic-embed-text',
153
- dimensions: 768,
154
- },
155
- propertyExtraction: {
156
- enabled: false,
157
- baseUrl: '',
158
- model: '',
159
- maxTokens: 300,
160
- },
161
- whisper: { enabled: true, model: 'small.en', language: 'auto' },
162
- youtube: { enabled: true, preferLanguage: 'en', fallbackToYtdlp: true },
163
- modules: {},
164
- mcp: { stdio: false, httpPort: 7777 },
165
- engramAccount: {
166
- jwt: fakeJwt(expSec),
167
- refreshToken: 'rt',
168
- apiKey: 'ak',
169
- masterKeySalt: saltHex,
170
- baseUrl,
171
- pairedAt: new Date().toISOString(),
172
- },
173
- };
174
- const result = await pollOnce({ store, config, masterKey });
175
- // --- Assert ---
176
- expect(result.processed).toBe(1);
177
- expect(result.errors).toBe(0);
178
- // Item was acknowledged (removed from inbox)
179
- expect(state.ackedIds).toContain(itemId);
180
- expect(state.inbox).toHaveLength(0);
181
- // Memory was stored in SQLite
182
- const rows = getDb()
183
- .prepare("SELECT content, properties_json FROM memories WHERE type = 'notes'")
184
- .all();
185
- expect(rows).toHaveLength(1);
186
- expect(rows[0].content).toContain('ship Plan K');
187
- // Vector store can find it via semantic search
188
- const hits = await store.search('notes', 'team meeting decision sprint', 5);
189
- expect(hits.length).toBeGreaterThan(0);
190
- expect(hits[0].memory.content).toContain('ship Plan K');
191
- }, 60_000);
192
- });
193
- //# sourceMappingURL=cloud-integration.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cloud-integration.test.js","sourceRoot":"","sources":["../../src/tests/cloud-integration.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=cloud-pairing.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cloud-pairing.test.d.ts","sourceRoot":"","sources":["../../src/tests/cloud-pairing.test.ts"],"names":[],"mappings":""}
@@ -1,86 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import fs from 'fs';
3
- import os from 'os';
4
- import path from 'path';
5
- import http from 'http';
6
- import { URL } from 'url';
7
- import { initDb, closeDb } from '../db/index.js';
8
- import { isPaired, loadTokens, saveTokens, parseJwtExpiry } from '../cloud/auth.js';
9
- // Helper: make a GET request to the local callback server
10
- function getCallback(port, params) {
11
- return new Promise((resolve, reject) => {
12
- const qs = new URLSearchParams(params).toString();
13
- const options = {
14
- hostname: '127.0.0.1',
15
- port,
16
- path: `/auth/callback?${qs}`,
17
- method: 'GET',
18
- };
19
- const req = http.request(options, (res) => {
20
- let body = '';
21
- res.on('data', (d) => (body += d));
22
- res.on('end', () => resolve({ status: res.statusCode ?? 0, body }));
23
- });
24
- req.on('error', reject);
25
- req.end();
26
- });
27
- }
28
- // Build a fake JWT with the given exp (Unix seconds)
29
- function fakeJwt(expSec) {
30
- const h = Buffer.from(JSON.stringify({ alg: 'HS256' })).toString('base64url');
31
- const p = Buffer.from(JSON.stringify({ sub: 'u', exp: expSec })).toString('base64url');
32
- return `${h}.${p}.sig`;
33
- }
34
- describe('cloud/pairing callback server', () => {
35
- let tmpDir;
36
- beforeEach(() => {
37
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'engram-pairing-'));
38
- initDb(tmpDir);
39
- });
40
- afterEach(() => {
41
- closeDb();
42
- fs.rmSync(tmpDir, { recursive: true, force: true });
43
- });
44
- it('accepts valid callback params, saves tokens, returns success HTML', async () => {
45
- const CALLBACK_PORT = 7778;
46
- const jwt = fakeJwt(Math.floor(Date.now() / 1000) + 3600);
47
- // Build a minimal callback server (mirrors the one in pairing.ts)
48
- let resolveCallback;
49
- const callbackDone = new Promise((res) => (resolveCallback = res));
50
- const server = http.createServer((req, res) => {
51
- const parsed = new URL(req.url, `http://localhost:${CALLBACK_PORT}`);
52
- const j = parsed.searchParams.get('jwt') ?? '';
53
- const rt = parsed.searchParams.get('refreshToken') ?? '';
54
- const ak = parsed.searchParams.get('apiKey') ?? '';
55
- res.writeHead(200);
56
- res.end('ok');
57
- server.close();
58
- resolveCallback({ jwt: j, refreshToken: rt, apiKey: ak });
59
- });
60
- await new Promise((res) => server.listen(CALLBACK_PORT, '127.0.0.1', res));
61
- // Fire the callback
62
- await getCallback(CALLBACK_PORT, {
63
- jwt,
64
- refreshToken: 'rt-test',
65
- apiKey: 'ak-test',
66
- });
67
- const result = await callbackDone;
68
- expect(result.jwt).toBe(jwt);
69
- expect(result.refreshToken).toBe('rt-test');
70
- expect(result.apiKey).toBe('ak-test');
71
- // Simulate saveTokens (what startPairing does after callback)
72
- saveTokens({
73
- jwt: result.jwt,
74
- refreshToken: result.refreshToken,
75
- apiKey: result.apiKey,
76
- expiresAt: parseJwtExpiry(result.jwt),
77
- });
78
- expect(isPaired()).toBe(true);
79
- const tokens = loadTokens();
80
- expect(tokens.apiKey).toBe('ak-test');
81
- }, 10_000);
82
- it('isPaired() is false before pairing', () => {
83
- expect(isPaired()).toBe(false);
84
- });
85
- });
86
- //# sourceMappingURL=cloud-pairing.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cloud-pairing.test.js","sourceRoot":"","sources":["../../src/tests/cloud-pairing.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=cloud-saves-integration.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cloud-saves-integration.test.d.ts","sourceRoot":"","sources":["../../src/tests/cloud-saves-integration.test.ts"],"names":[],"mappings":""}
@@ -1,92 +0,0 @@
1
- // src/tests/cloud-saves-integration.test.ts
2
- /**
3
- * Integration test: simulates PC1 taking a snapshot and PC2 bootstrapping from it.
4
- *
5
- * Requires:
6
- * - Local wrangler dev running at ENGRAM_CLOUD_URL (default: http://localhost:8787)
7
- * - A valid test JWT in env: ENGRAM_TEST_JWT
8
- * - The D1 migration 003-cloud-saves.sql applied: wrangler d1 execute --local --file=schema/003-cloud-saves.sql
9
- *
10
- * Run:
11
- * ENGRAM_TEST_JWT=<token> npx vitest run src/tests/cloud-saves-integration.test.ts
12
- *
13
- * Skip (no JWT provided): tests are automatically skipped.
14
- */
15
- import { describe, it, expect, afterEach } from 'vitest';
16
- import fs from 'fs';
17
- import os from 'os';
18
- import path from 'path';
19
- import { initDb, closeDb, getDb } from '../db/index.js';
20
- import { initCloudSaves, takeSnapshot, bootstrapFromSnapshot, encryptBuffer, decryptBuffer, } from '../sync/cloud-saves.js';
21
- const CLOUD_URL = process.env.ENGRAM_CLOUD_URL ?? 'http://localhost:8787';
22
- const JWT = process.env.ENGRAM_TEST_JWT ?? '';
23
- const MASTER_KEY = Buffer.alloc(32, 0xab); // test key — never use in production
24
- const skip = !JWT;
25
- describe('Encrypt/Decrypt round-trip (libsodium secretstream)', () => {
26
- it('encrypts and decrypts a buffer correctly', async () => {
27
- const plain = Buffer.from('Hello Engram snapshot world! This is a test of the secretstream.');
28
- const key = Buffer.alloc(32, 0xcd); // test key
29
- const encrypted = await encryptBuffer(plain, key);
30
- const decrypted = await decryptBuffer(encrypted, key);
31
- expect(decrypted).toStrictEqual(plain);
32
- });
33
- it('fails to decrypt with wrong key', async () => {
34
- const plain = Buffer.from('Secret data');
35
- const key = Buffer.alloc(32, 0xaa);
36
- const wrongKey = Buffer.alloc(32, 0xbb);
37
- const encrypted = await encryptBuffer(plain, key);
38
- await expect(decryptBuffer(encrypted, wrongKey)).rejects.toThrow(/decryption failed/);
39
- });
40
- });
41
- describe.skipIf(skip)('Cloud Saves integration (PC1 → snapshot → PC2 bootstrap)', () => {
42
- let pc1Dir;
43
- let pc2Dir;
44
- afterEach(() => {
45
- try {
46
- closeDb();
47
- }
48
- catch {
49
- // May already be closed
50
- }
51
- if (pc1Dir)
52
- fs.rmSync(pc1Dir, { recursive: true, force: true });
53
- if (pc2Dir)
54
- fs.rmSync(pc2Dir, { recursive: true, force: true });
55
- });
56
- it('PC1 snapshot is downloadable and restores DB on PC2', async () => {
57
- // PC1 setup
58
- pc1Dir = fs.mkdtempSync(path.join(os.tmpdir(), 'engram-pc1-'));
59
- pc2Dir = fs.mkdtempSync(path.join(os.tmpdir(), 'engram-pc2-'));
60
- process.env.DATA_DIR = pc1Dir;
61
- initDb(pc1Dir);
62
- const db = getDb();
63
- // Insert some test memories
64
- const now = Date.now();
65
- db.prepare(`INSERT INTO memories (id, type, source_id, content, content_hash, properties_json, wikilinks_json, related_ids_json, embedding_model, created_at)
66
- VALUES (?, 'notes', 's1', 'Hello from PC1', 'hash1', '{}', '[]', '[]', 'test', ?)`).run('mem_001', now);
67
- // PC1 takes a snapshot
68
- initCloudSaves({ masterKey: MASTER_KEY, jwt: JWT, cloudBaseUrl: CLOUD_URL });
69
- const { id: snapshotId, sizeBytes } = await takeSnapshot();
70
- expect(snapshotId).toBeTruthy();
71
- expect(sizeBytes).toBeGreaterThan(0);
72
- closeDb();
73
- // PC2 bootstrap
74
- const result = await bootstrapFromSnapshot({
75
- masterKey: MASTER_KEY,
76
- jwt: JWT,
77
- dataDir: pc2Dir,
78
- cloudBaseUrl: CLOUD_URL,
79
- });
80
- expect(result).not.toBeNull();
81
- expect(result.sizeBytes).toBeGreaterThan(0);
82
- // PC2 opens the restored DB and finds PC1's memory
83
- process.env.DATA_DIR = pc2Dir;
84
- initDb(pc2Dir);
85
- const pc2Db = getDb();
86
- const row = pc2Db.prepare(`SELECT content FROM memories WHERE id = ?`).get('mem_001');
87
- expect(row).toBeDefined();
88
- expect(row.content).toBe('Hello from PC1');
89
- closeDb();
90
- }, 60_000);
91
- });
92
- //# sourceMappingURL=cloud-saves-integration.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cloud-saves-integration.test.js","sourceRoot":"","sources":["../../src/tests/cloud-saves-integration.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=cloud-transit.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cloud-transit.test.d.ts","sourceRoot":"","sources":["../../src/tests/cloud-transit.test.ts"],"names":[],"mappings":""}