crbro-memory 1.3.0 → 1.5.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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +170 -121
  3. package/bin/{crbro.js → crbro.mjs} +119 -47
  4. package/dist/engine/brain.d.ts +3 -0
  5. package/dist/engine/brain.d.ts.map +1 -1
  6. package/dist/engine/brain.js +15 -2
  7. package/dist/engine/brain.js.map +1 -1
  8. package/dist/engine/cortex.d.ts +61 -7
  9. package/dist/engine/cortex.d.ts.map +1 -1
  10. package/dist/engine/cortex.js +168 -23
  11. package/dist/engine/cortex.js.map +1 -1
  12. package/dist/engine/maintenance.d.ts +6 -1
  13. package/dist/engine/maintenance.d.ts.map +1 -1
  14. package/dist/engine/maintenance.js +19 -5
  15. package/dist/engine/maintenance.js.map +1 -1
  16. package/dist/engine/prefrontal.d.ts +13 -2
  17. package/dist/engine/prefrontal.d.ts.map +1 -1
  18. package/dist/engine/prefrontal.js +47 -11
  19. package/dist/engine/prefrontal.js.map +1 -1
  20. package/dist/miner/index.d.ts.map +1 -1
  21. package/dist/miner/index.js +35 -30
  22. package/dist/miner/index.js.map +1 -1
  23. package/dist/search/index.d.ts +46 -6
  24. package/dist/search/index.d.ts.map +1 -1
  25. package/dist/search/index.js +335 -74
  26. package/dist/search/index.js.map +1 -1
  27. package/dist/search/tokenize.d.ts +23 -0
  28. package/dist/search/tokenize.d.ts.map +1 -0
  29. package/dist/search/tokenize.js +83 -0
  30. package/dist/search/tokenize.js.map +1 -0
  31. package/dist/server.d.ts.map +1 -1
  32. package/dist/server.js +132 -64
  33. package/dist/server.js.map +1 -1
  34. package/dist/types/index.d.ts +39 -8
  35. package/dist/types/index.d.ts.map +1 -1
  36. package/dist/utils/fs.d.ts +3 -1
  37. package/dist/utils/fs.d.ts.map +1 -1
  38. package/dist/utils/fs.js +6 -2
  39. package/dist/utils/fs.js.map +1 -1
  40. package/dist/utils/hash.d.ts +20 -0
  41. package/dist/utils/hash.d.ts.map +1 -0
  42. package/dist/utils/hash.js +45 -0
  43. package/dist/utils/hash.js.map +1 -0
  44. package/package.json +53 -52
  45. package/dist/engine/license.d.ts +0 -56
  46. package/dist/engine/license.d.ts.map +0 -1
  47. package/dist/engine/license.js +0 -332
  48. package/dist/engine/license.js.map +0 -1
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ // ─── CRBRO Content Hashing ───────────────────────────────────────
3
+ // Stable, content-derived IDs for facts and index chunks.
4
+ //
5
+ // Why content-derived and not random or positional:
6
+ // - Random (Math.random) collides. Measured on the reference brain: 59%
7
+ // collision inside a single 287-fact neuron with a 3-char suffix.
8
+ // - Positional (#f0, #f1) is only correct while facts are strictly
9
+ // append-only, and superseding breaks that premise.
10
+ // A content hash needs no backfill: the same text always yields the same id,
11
+ // so 1,183 existing neuron files stay untouched and still resolve.
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.contentHash = contentHash;
14
+ exports.chunkId = chunkId;
15
+ exports.factId = factId;
16
+ exports.pendingId = pendingId;
17
+ const node_crypto_1 = require("node:crypto");
18
+ /**
19
+ * Short, stable hash of a piece of content. 12 hex chars ≈ 48 bits,
20
+ * which is ample for per-neuron uniqueness.
21
+ */
22
+ function contentHash(text, length = 12) {
23
+ return (0, node_crypto_1.createHash)('sha1').update(text, 'utf8').digest('hex').slice(0, length);
24
+ }
25
+ /**
26
+ * ID for an indexed chunk: neuron id + hash of the chunk text.
27
+ * Editing a fact changes its id, which is what lets reindexing notice.
28
+ */
29
+ function chunkId(neuronId, text) {
30
+ return `${neuronId}#${contentHash(text)}`;
31
+ }
32
+ /**
33
+ * ID for a fact inside its neuron. Same hash, no prefix — facts are
34
+ * addressed relative to the neuron that holds them.
35
+ */
36
+ function factId(text) {
37
+ return contentHash(text);
38
+ }
39
+ /**
40
+ * Short id for a pending task. Prefixed so it reads as an id in a list.
41
+ */
42
+ function pendingId(text) {
43
+ return `p_${contentHash(text, 6)}`;
44
+ }
45
+ //# sourceMappingURL=hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/utils/hash.ts"],"names":[],"mappings":";AAAA,oEAAoE;AACpE,0DAA0D;AAC1D,EAAE;AACF,oDAAoD;AACpD,yEAAyE;AACzE,qEAAqE;AACrE,oEAAoE;AACpE,uDAAuD;AACvD,6EAA6E;AAC7E,mEAAmE;;AAQnE,kCAEC;AAMD,0BAEC;AAMD,wBAEC;AAKD,8BAEC;AA/BD,6CAAyC;AAEzC;;;GAGG;AACH,SAAgB,WAAW,CAAC,IAAY,EAAE,SAAiB,EAAE;IAC3D,OAAO,IAAA,wBAAU,EAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAChF,CAAC;AAED;;;GAGG;AACH,SAAgB,OAAO,CAAC,QAAgB,EAAE,IAAY;IACpD,OAAO,GAAG,QAAQ,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,SAAgB,MAAM,CAAC,IAAY;IACjC,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,SAAgB,SAAS,CAAC,IAAY;IACpC,OAAO,KAAK,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;AACrC,CAAC"}
package/package.json CHANGED
@@ -1,52 +1,53 @@
1
- {
2
- "name": "crbro-memory",
3
- "version": "1.3.0",
4
- "description": "CRBRO — Persistent neural memory for AI. A biological file-based MCP server that gives your AI long-term memory across sessions.",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "bin": {
8
- "crbro-memory": "./bin/crbro.js"
9
- },
10
- "scripts": {
11
- "build": "tsc",
12
- "dev": "tsc --watch",
13
- "start": "node dist/index.js",
14
- "test": "vitest run",
15
- "test:watch": "vitest",
16
- "prepublishOnly": "npm run build"
17
- },
18
- "keywords": [
19
- "mcp",
20
- "memory",
21
- "ai",
22
- "persistent-memory",
23
- "model-context-protocol",
24
- "llm",
25
- "synthetica"
26
- ],
27
- "author": "Synthetica Decks",
28
- "license": "MIT",
29
- "repository": {
30
- "type": "git",
31
- "url": "https://github.com/Octonove/crbro-memory"
32
- },
33
- "engines": {
34
- "node": ">=18.0.0"
35
- },
36
- "files": [
37
- "dist/",
38
- "bin/",
39
- "README.md",
40
- "LICENSE"
41
- ],
42
- "dependencies": {
43
- "@modelcontextprotocol/sdk": "^1.29.0",
44
- "@orama/orama": "^3.1.18",
45
- "zod": "^4.4.3"
46
- },
47
- "devDependencies": {
48
- "@types/node": "^25.6.0",
49
- "typescript": "^6.0.3",
50
- "vitest": "^4.1.5"
51
- }
52
- }
1
+ {
2
+ "name": "crbro-memory",
3
+ "version": "1.5.0",
4
+ "mcpName": "io.github.Octonove/crbro-memory",
5
+ "description": "CRBRO — Persistent neural memory for AI. A biological file-based MCP server that gives your AI long-term memory across sessions.",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "crbro-memory": "./bin/crbro.mjs"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "dev": "tsc --watch",
14
+ "start": "node dist/index.js",
15
+ "test": "vitest run",
16
+ "test:watch": "vitest",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "memory",
22
+ "ai",
23
+ "persistent-memory",
24
+ "model-context-protocol",
25
+ "llm",
26
+ "synthetica"
27
+ ],
28
+ "author": "Synthetica Decks",
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/Octonove/crbro-memory"
33
+ },
34
+ "engines": {
35
+ "node": ">=18.0.0"
36
+ },
37
+ "files": [
38
+ "dist/",
39
+ "bin/",
40
+ "README.md",
41
+ "LICENSE"
42
+ ],
43
+ "dependencies": {
44
+ "@modelcontextprotocol/sdk": "^1.29.0",
45
+ "@orama/orama": "^3.1.18",
46
+ "zod": "^4.4.3"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^25.6.0",
50
+ "typescript": "^6.0.3",
51
+ "vitest": "^4.1.5"
52
+ }
53
+ }
@@ -1,56 +0,0 @@
1
- import type { Brain } from './brain.js';
2
- import type { LicenseInfo } from '../types/index.js';
3
- export declare class LicenseEngine {
4
- private brain;
5
- private cacheFile;
6
- private deviceId;
7
- constructor(brain: Brain);
8
- /**
9
- * Check if the license is valid (server-verified + device limit).
10
- * Uses local cache if verified within 7 days.
11
- */
12
- isPremium(): Promise<boolean>;
13
- /**
14
- * Get the rejection reason (for error messages).
15
- */
16
- getRejectionReason(): Promise<string | null>;
17
- /**
18
- * Get current license info.
19
- */
20
- getLicenseInfo(): Promise<LicenseInfo>;
21
- /**
22
- * Legacy compatibility.
23
- */
24
- canUse(_toolName: string): Promise<boolean>;
25
- /**
26
- * Generate a unique device fingerprint.
27
- * Prefers a persistent UUID token stored on disk to withstand OS/hardware updates.
28
- * Falls back to a hardware-based fingerprint in case of filesystem restrictions.
29
- */
30
- private generateDeviceFingerprint;
31
- /**
32
- * Resolve the license key — env var takes priority over manifest.
33
- */
34
- private resolveKey;
35
- /**
36
- * Basic format validation — prefix + length + characters.
37
- */
38
- private validateFormat;
39
- /**
40
- * Verify license AND register this device.
41
- * Returns { valid, status } where status explains why if invalid.
42
- */
43
- private verifyAndRegisterDevice;
44
- /**
45
- * Fetch license document from Firestore REST API.
46
- */
47
- private fetchLicenseDoc;
48
- /**
49
- * Update the devices array in Firestore via REST API PATCH.
50
- */
51
- private updateDevices;
52
- private readCache;
53
- private writeCache;
54
- private getInfo;
55
- }
56
- //# sourceMappingURL=license.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../../src/engine/license.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAmCrD,qBAAa,aAAa;IAIZ,OAAO,CAAC,KAAK;IAHzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAS;gBAEL,KAAK,EAAE,KAAK;IAKhC;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IA+BnC;;OAEG;IACG,kBAAkB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAYlD;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAM5C;;OAEG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMjD;;;;OAIG;IACH,OAAO,CAAC,yBAAyB;IA0CjC;;OAEG;YACW,UAAU;IAYxB;;OAEG;IACH,OAAO,CAAC,cAAc;IAStB;;;OAGG;YACW,uBAAuB;IAsCrC;;OAEG;IACH,OAAO,CAAC,eAAe;IA0BvB;;OAEG;IACH,OAAO,CAAC,aAAa;YA6CP,SAAS;YAUT,UAAU;IAQxB,OAAO,CAAC,OAAO;CAUhB"}
@@ -1,332 +0,0 @@
1
- "use strict";
2
- // ─── CRBRO License Engine ────────────────────────────────────────
3
- // Server-side license validation against Firestore + device limit + local cache
4
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
- if (k2 === undefined) k2 = k;
6
- var desc = Object.getOwnPropertyDescriptor(m, k);
7
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
- desc = { enumerable: true, get: function() { return m[k]; } };
9
- }
10
- Object.defineProperty(o, k2, desc);
11
- }) : (function(o, m, k, k2) {
12
- if (k2 === undefined) k2 = k;
13
- o[k2] = m[k];
14
- }));
15
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
- Object.defineProperty(o, "default", { enumerable: true, value: v });
17
- }) : function(o, v) {
18
- o["default"] = v;
19
- });
20
- var __importStar = (this && this.__importStar) || (function () {
21
- var ownKeys = function(o) {
22
- ownKeys = Object.getOwnPropertyNames || function (o) {
23
- var ar = [];
24
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
25
- return ar;
26
- };
27
- return ownKeys(o);
28
- };
29
- return function (mod) {
30
- if (mod && mod.__esModule) return mod;
31
- var result = {};
32
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
33
- __setModuleDefault(result, mod);
34
- return result;
35
- };
36
- })();
37
- Object.defineProperty(exports, "__esModule", { value: true });
38
- exports.LicenseEngine = void 0;
39
- const https = __importStar(require("https"));
40
- const path = __importStar(require("path"));
41
- const fs = __importStar(require("fs"));
42
- const os = __importStar(require("os"));
43
- const crypto = __importStar(require("crypto"));
44
- // Firestore project for license validation
45
- const FIRESTORE_PROJECT = 'synthetica-decks';
46
- const COLLECTION = 'license-checks';
47
- const MAX_DEVICES = 3;
48
- // Cache duration: 7 days in milliseconds
49
- const CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
50
- // Valid license key prefix — Synthetica Zero Deck keys
51
- const LICENSE_PREFIX = 'SYNTH-ZERO-';
52
- class LicenseEngine {
53
- brain;
54
- cacheFile;
55
- deviceId;
56
- constructor(brain) {
57
- this.brain = brain;
58
- this.cacheFile = path.join(brain.paths.root, '.license-cache.json');
59
- this.deviceId = this.generateDeviceFingerprint();
60
- }
61
- /**
62
- * Check if the license is valid (server-verified + device limit).
63
- * Uses local cache if verified within 7 days.
64
- */
65
- async isPremium() {
66
- const key = await this.resolveKey();
67
- if (!key)
68
- return false;
69
- // Quick format check before wasting a network call
70
- if (!this.validateFormat(key))
71
- return false;
72
- // Check local cache first
73
- const cached = await this.readCache();
74
- if (cached && cached.key === key && cached.valid && cached.deviceId === this.deviceId) {
75
- const age = Date.now() - cached.verifiedAt;
76
- if (age < CACHE_TTL_MS) {
77
- return true;
78
- }
79
- }
80
- // Cache expired or missing — verify against Firestore
81
- const result = await this.verifyAndRegisterDevice(key);
82
- // Save result to cache
83
- await this.writeCache({
84
- key,
85
- valid: result.valid,
86
- verifiedAt: Date.now(),
87
- deviceId: this.deviceId,
88
- status: result.status,
89
- });
90
- return result.valid;
91
- }
92
- /**
93
- * Get the rejection reason (for error messages).
94
- */
95
- async getRejectionReason() {
96
- const key = await this.resolveKey();
97
- if (!key)
98
- return 'no_key';
99
- if (!this.validateFormat(key))
100
- return 'invalid_format';
101
- const cached = await this.readCache();
102
- if (cached && cached.key === key && !cached.valid) {
103
- return cached.status;
104
- }
105
- return null;
106
- }
107
- /**
108
- * Get current license info.
109
- */
110
- async getLicenseInfo() {
111
- const key = await this.resolveKey();
112
- const valid = await this.isPremium();
113
- return this.getInfo(valid ? key : null);
114
- }
115
- /**
116
- * Legacy compatibility.
117
- */
118
- async canUse(_toolName) {
119
- return this.isPremium();
120
- }
121
- // ─── Private ─────────────────────────────────────────────────
122
- /**
123
- * Generate a unique device fingerprint.
124
- * Prefers a persistent UUID token stored on disk to withstand OS/hardware updates.
125
- * Falls back to a hardware-based fingerprint in case of filesystem restrictions.
126
- */
127
- generateDeviceFingerprint() {
128
- const tokenFile = path.join(this.brain.paths.root, '.device-token');
129
- // 1. Try to read existing UUID token from local file
130
- try {
131
- if (fs.existsSync(tokenFile)) {
132
- const token = fs.readFileSync(tokenFile, 'utf-8').trim();
133
- if (token.length >= 10) {
134
- return token;
135
- }
136
- }
137
- }
138
- catch {
139
- // Fail silently and proceed to fallback/generation
140
- }
141
- // 2. Generate hardware fallback fingerprint in case of filesystem issues
142
- const raw = [
143
- os.hostname(),
144
- os.userInfo().username,
145
- os.platform(),
146
- os.arch(),
147
- os.cpus()[0]?.model || 'unknown',
148
- ].join('|');
149
- const hardwareFallback = crypto.createHash('sha256').update(raw).digest('hex').substring(0, 16);
150
- // 3. Try to generate a fresh persistent UUID token and save it to disk
151
- try {
152
- const uuid = crypto.randomUUID().replace(/-/g, '').substring(0, 16);
153
- // Ensure brain root directory exists before writing
154
- if (!fs.existsSync(this.brain.paths.root)) {
155
- fs.mkdirSync(this.brain.paths.root, { recursive: true });
156
- }
157
- fs.writeFileSync(tokenFile, uuid, 'utf-8');
158
- return uuid;
159
- }
160
- catch {
161
- // If writing to disk fails, gracefully fallback to the hardware fingerprint
162
- return hardwareFallback;
163
- }
164
- }
165
- /**
166
- * Resolve the license key — env var takes priority over manifest.
167
- */
168
- async resolveKey() {
169
- const envKey = process.env.CRBRO_LICENSE_KEY || null;
170
- if (envKey && this.validateFormat(envKey))
171
- return envKey;
172
- try {
173
- const manifest = await this.brain.getManifest();
174
- return manifest.license_key || null;
175
- }
176
- catch {
177
- return null;
178
- }
179
- }
180
- /**
181
- * Basic format validation — prefix + length + characters.
182
- */
183
- validateFormat(key) {
184
- if (!key)
185
- return false;
186
- if (!key.startsWith(LICENSE_PREFIX))
187
- return false;
188
- if (key.length < 20)
189
- return false;
190
- const payload = key.substring(LICENSE_PREFIX.length);
191
- if (!/^[A-Z0-9-]+$/.test(payload))
192
- return false;
193
- return true;
194
- }
195
- /**
196
- * Verify license AND register this device.
197
- * Returns { valid, status } where status explains why if invalid.
198
- */
199
- async verifyAndRegisterDevice(key) {
200
- // Step 1: Fetch the license document
201
- const doc = await this.fetchLicenseDoc(key);
202
- if (!doc) {
203
- return { valid: false, status: 'key_not_found' };
204
- }
205
- const status = doc.fields?.status?.stringValue;
206
- if (status !== 'active') {
207
- return { valid: false, status: 'license_revoked' };
208
- }
209
- // Step 2: Check device limit
210
- const devicesArray = doc.fields?.devices?.arrayValue?.values || [];
211
- const registeredDevices = devicesArray.map(v => v.stringValue || '');
212
- // This device is already registered — all good
213
- if (registeredDevices.includes(this.deviceId)) {
214
- return { valid: true, status: 'active' };
215
- }
216
- // Check if there's room for another device
217
- if (registeredDevices.length >= MAX_DEVICES) {
218
- return { valid: false, status: 'device_limit_exceeded' };
219
- }
220
- // Step 3: Register this device
221
- const newDevices = [...registeredDevices, this.deviceId];
222
- const registered = await this.updateDevices(key, newDevices);
223
- if (registered) {
224
- return { valid: true, status: 'active' };
225
- }
226
- else {
227
- // Registration failed (possibly race condition or rule violation)
228
- return { valid: false, status: 'device_registration_failed' };
229
- }
230
- }
231
- /**
232
- * Fetch license document from Firestore REST API.
233
- */
234
- fetchLicenseDoc(key) {
235
- return new Promise((resolve) => {
236
- const encodedKey = encodeURIComponent(key);
237
- const url = `https://firestore.googleapis.com/v1/projects/${FIRESTORE_PROJECT}/databases/(default)/documents/${COLLECTION}/${encodedKey}`;
238
- const req = https.get(url, { timeout: 10000 }, (res) => {
239
- let data = '';
240
- res.on('data', (chunk) => { data += chunk.toString(); });
241
- res.on('end', () => {
242
- try {
243
- if (res.statusCode === 200) {
244
- resolve(JSON.parse(data));
245
- }
246
- else {
247
- resolve(null);
248
- }
249
- }
250
- catch {
251
- resolve(null);
252
- }
253
- });
254
- });
255
- req.on('error', () => resolve(null));
256
- req.on('timeout', () => { req.destroy(); resolve(null); });
257
- });
258
- }
259
- /**
260
- * Update the devices array in Firestore via REST API PATCH.
261
- */
262
- updateDevices(key, devices) {
263
- return new Promise((resolve) => {
264
- const encodedKey = encodeURIComponent(key);
265
- const url = `https://firestore.googleapis.com/v1/projects/${FIRESTORE_PROJECT}/databases/(default)/documents/${COLLECTION}/${encodedKey}?updateMask.fieldPaths=devices`;
266
- const body = JSON.stringify({
267
- fields: {
268
- devices: {
269
- arrayValue: {
270
- values: devices.map(d => ({ stringValue: d })),
271
- },
272
- },
273
- },
274
- });
275
- const parsed = new URL(url);
276
- const options = {
277
- hostname: parsed.hostname,
278
- path: parsed.pathname + parsed.search,
279
- method: 'PATCH',
280
- timeout: 10000,
281
- headers: {
282
- 'Content-Type': 'application/json',
283
- 'Content-Length': Buffer.byteLength(body),
284
- },
285
- };
286
- const req = https.request(options, (res) => {
287
- let data = '';
288
- res.on('data', (chunk) => { data += chunk.toString(); });
289
- res.on('end', () => {
290
- // 200 = success, 403 = device limit exceeded (security rule violation)
291
- resolve(res.statusCode === 200);
292
- });
293
- });
294
- req.on('error', () => resolve(false));
295
- req.on('timeout', () => { req.destroy(); resolve(false); });
296
- req.write(body);
297
- req.end();
298
- });
299
- }
300
- // ─── Cache management ──────────────────────────────────────────
301
- async readCache() {
302
- try {
303
- if (!fs.existsSync(this.cacheFile))
304
- return null;
305
- const raw = fs.readFileSync(this.cacheFile, 'utf-8');
306
- return JSON.parse(raw);
307
- }
308
- catch {
309
- return null;
310
- }
311
- }
312
- async writeCache(cache) {
313
- try {
314
- fs.writeFileSync(this.cacheFile, JSON.stringify(cache, null, 2), 'utf-8');
315
- }
316
- catch {
317
- // Silent fail
318
- }
319
- }
320
- getInfo(key) {
321
- const valid = !!key;
322
- return {
323
- valid,
324
- tier: valid ? 'premium' : 'free',
325
- // Premium unlocks exactly the two license-gated tools — keep in sync
326
- // with server.ts gating and the README's Free/Premium tables.
327
- features: valid ? ['global_map', 'maintenance'] : [],
328
- };
329
- }
330
- }
331
- exports.LicenseEngine = LicenseEngine;
332
- //# sourceMappingURL=license.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"license.js","sourceRoot":"","sources":["../../src/engine/license.ts"],"names":[],"mappings":"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"}