yakmesh 2.9.0 → 3.0.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 (225) hide show
  1. package/CHANGELOG.md +637 -0
  2. package/Caddyfile +77 -0
  3. package/README.md +119 -29
  4. package/content/api.js +50 -41
  5. package/content/index.js +1 -2
  6. package/content/store.js +323 -177
  7. package/dashboard/index.html +19 -3
  8. package/database/replication.js +117 -37
  9. package/docs/CRYPTO-AGILITY.md +204 -0
  10. package/docs/MTLS-RESEARCH.md +367 -0
  11. package/docs/NAMCHE-SPEC.md +681 -0
  12. package/docs/PEERQUANTA-YAKMESH-INTEGRATION.md +407 -0
  13. package/docs/PRECISION-DISCLOSURE.md +96 -0
  14. package/docs/README.md +76 -0
  15. package/docs/ROADMAP-2.4.0.md +447 -0
  16. package/docs/ROADMAP-2.5.0.md +244 -0
  17. package/docs/SECURITY-AUDIT-REPORT.md +306 -0
  18. package/docs/SST-INTEGRATION.md +712 -0
  19. package/docs/STEADYWATCH-IMPLEMENTATION.md +303 -0
  20. package/docs/TERNARY-AUDIT-REPORT.md +247 -0
  21. package/docs/TME-FAQ.md +221 -0
  22. package/docs/WHITEPAPER.md +623 -0
  23. package/docs/adapters.html +1001 -0
  24. package/docs/advanced-systems.html +1045 -0
  25. package/docs/annex.html +1046 -0
  26. package/docs/api.html +970 -0
  27. package/docs/business/response-templates.md +160 -0
  28. package/docs/c2c.html +1225 -0
  29. package/docs/cli.html +1332 -0
  30. package/docs/configuration.html +1248 -0
  31. package/docs/darshan.html +1085 -0
  32. package/docs/dharma.html +966 -0
  33. package/docs/docs-bundle.html +1075 -0
  34. package/docs/docs.css +3120 -0
  35. package/docs/docs.js +556 -0
  36. package/docs/doko.html +969 -0
  37. package/docs/geo-proof.html +858 -0
  38. package/docs/getting-started.html +840 -0
  39. package/docs/gumba-tutorial.html +1144 -0
  40. package/docs/gumba.html +1098 -0
  41. package/docs/index.html +914 -0
  42. package/docs/jhilke.html +1312 -0
  43. package/docs/karma.html +1100 -0
  44. package/docs/katha.html +1037 -0
  45. package/docs/lama.html +978 -0
  46. package/docs/mandala.html +1067 -0
  47. package/docs/mani.html +964 -0
  48. package/docs/mantra.html +967 -0
  49. package/docs/mesh.html +1409 -0
  50. package/docs/nakpak.html +869 -0
  51. package/docs/namche.html +928 -0
  52. package/docs/nav-order.json +53 -0
  53. package/docs/prahari.html +1043 -0
  54. package/docs/prism-bash.min.js +1 -0
  55. package/docs/prism-javascript.min.js +1 -0
  56. package/docs/prism-json.min.js +1 -0
  57. package/docs/prism-tomorrow.min.css +1 -0
  58. package/docs/prism.min.js +1 -0
  59. package/docs/privacy.html +699 -0
  60. package/docs/quick-reference.html +1181 -0
  61. package/docs/sakshi.html +1402 -0
  62. package/docs/sandboxing.md +386 -0
  63. package/docs/seva.html +911 -0
  64. package/docs/sherpa.html +871 -0
  65. package/docs/studio.html +860 -0
  66. package/docs/stupa.html +995 -0
  67. package/docs/tailwind.min.css +2 -0
  68. package/docs/tattva.html +1332 -0
  69. package/docs/terms.html +686 -0
  70. package/docs/time-server-deployment.md +166 -0
  71. package/docs/time-sources.html +1392 -0
  72. package/docs/tivra.html +1127 -0
  73. package/docs/trademark-policy.html +686 -0
  74. package/docs/tribhuj.html +1183 -0
  75. package/docs/trust-security.html +1029 -0
  76. package/docs/tutorials/backup-recovery.html +654 -0
  77. package/docs/tutorials/dashboard.html +604 -0
  78. package/docs/tutorials/domain-setup.html +605 -0
  79. package/docs/tutorials/host-website.html +456 -0
  80. package/docs/tutorials/mesh-network.html +505 -0
  81. package/docs/tutorials/mobile-access.html +445 -0
  82. package/docs/tutorials/privacy.html +467 -0
  83. package/docs/tutorials/raspberry-pi.html +600 -0
  84. package/docs/tutorials/security-basics.html +539 -0
  85. package/docs/tutorials/share-files.html +431 -0
  86. package/docs/tutorials/troubleshooting.html +637 -0
  87. package/docs/tutorials/trust-karma.html +419 -0
  88. package/docs/tutorials/yak-protocol.html +456 -0
  89. package/docs/tutorials.html +1034 -0
  90. package/docs/vani.html +1270 -0
  91. package/docs/webserver.html +809 -0
  92. package/docs/yak-protocol.html +940 -0
  93. package/docs/yak-timeserver-design.md +475 -0
  94. package/docs/yakapp.html +1015 -0
  95. package/docs/ypc27.html +1069 -0
  96. package/docs/yurt.html +1344 -0
  97. package/embedded-docs/bundle.js +274 -114
  98. package/gossip/protocol.js +247 -27
  99. package/identity/key-resolver.js +262 -0
  100. package/identity/machine-seed.js +632 -0
  101. package/identity/node-key.js +669 -368
  102. package/identity/tribhuj-ratchet.js +506 -0
  103. package/knowledge-base.js +37 -8
  104. package/launcher/yakmesh.bat +62 -0
  105. package/launcher/yakmesh.sh +70 -0
  106. package/mesh/annex.js +462 -108
  107. package/mesh/beacon-broadcast.js +4 -1
  108. package/mesh/darshan.js +17 -5
  109. package/mesh/gumba.js +47 -13
  110. package/mesh/jhilke.js +651 -0
  111. package/mesh/katha.js +5 -2
  112. package/mesh/nakpak-routing.js +8 -5
  113. package/mesh/network.js +724 -34
  114. package/mesh/pulse-sync.js +4 -1
  115. package/mesh/seva.js +526 -0
  116. package/mesh/sherpa-discovery.js +89 -8
  117. package/mesh/sybil-defense.js +19 -5
  118. package/mesh/temporal-encoder.js +4 -3
  119. package/mesh/yurt.js +72 -17
  120. package/models/entropy-sentinel.onnx +0 -0
  121. package/models/karma-trust.onnx +0 -0
  122. package/models/manifest.json +43 -0
  123. package/models/sakshi-anomaly.onnx +0 -0
  124. package/oracle/code-proof-protocol.js +7 -6
  125. package/oracle/codebase-lock.js +257 -28
  126. package/oracle/index.js +74 -15
  127. package/oracle/ma902-snmp.js +678 -0
  128. package/oracle/module-sealer.js +5 -3
  129. package/oracle/packet-checksum.js +201 -0
  130. package/oracle/ternary-144t.js +714 -0
  131. package/oracle/ternary-ml.js +481 -0
  132. package/oracle/time-api.js +239 -0
  133. package/oracle/time-source.js +137 -47
  134. package/oracle/validation-oracle-hardened.js +1111 -1071
  135. package/oracle/validation-oracle.js +4 -2
  136. package/oracle/ypc27.js +211 -0
  137. package/package.json +20 -3
  138. package/protocol/yak-handler.js +35 -9
  139. package/protocol/yak-protocol.js +6 -5
  140. package/reference/cpp/yakmesh_mceliece_shard.cpp +168 -0
  141. package/reference/cpp/yakmesh_ypc27.cpp +179 -0
  142. package/sbom.json +87 -0
  143. package/scripts/security-audit.mjs +264 -0
  144. package/scripts/update-docs-sidebar.cjs +164 -0
  145. package/security/crypto-config.js +4 -3
  146. package/security/dharma-moderation.js +4 -3
  147. package/security/doko-identity.js +193 -143
  148. package/security/domain-consensus.js +86 -85
  149. package/security/fs-hardening.js +620 -0
  150. package/security/hardware-attestation.js +5 -3
  151. package/security/hybrid-trust.js +227 -87
  152. package/security/karma-rate-limiter.js +692 -0
  153. package/security/khata-protocol.js +22 -21
  154. package/security/khata-trust-integration.js +277 -150
  155. package/security/memory-safety.js +635 -0
  156. package/security/mesh-auth.js +11 -10
  157. package/security/mesh-revocation.js +18 -5
  158. package/security/namche-gateway.js +298 -69
  159. package/security/sakshi.js +102 -3
  160. package/security/sangha.js +770 -0
  161. package/security/secure-config.js +473 -0
  162. package/security/silicon-parity.js +13 -10
  163. package/security/steadywatch.js +1142 -0
  164. package/security/strike-system.js +32 -3
  165. package/security/temporal-signing.js +488 -0
  166. package/security/trit-commitment.js +464 -0
  167. package/server/crypto/annex.js +247 -0
  168. package/server/darshan-api.js +343 -0
  169. package/server/index.js +3259 -362
  170. package/server/komm-api.js +668 -0
  171. package/utils/accel.js +2273 -0
  172. package/utils/ternary-id.js +79 -0
  173. package/utils/verify-worker.js +57 -0
  174. package/webserver/index.js +95 -5
  175. package/assets/yakmesh-logo.png +0 -0
  176. package/assets/yakmesh-logo.svg +0 -80
  177. package/assets/yakmesh-logo2.png +0 -0
  178. package/assets/yakmesh-logo2sm.png +0 -0
  179. package/assets/ymsm.png +0 -0
  180. package/scripts/update-docs-nav.cjs +0 -194
  181. package/update-docs-nav.cjs +0 -18
  182. package/update-nav.ps1 +0 -16
  183. package/website/assets/silhouettes/adapters.svg +0 -107
  184. package/website/assets/silhouettes/api-endpoints.svg +0 -115
  185. package/website/assets/silhouettes/atomic-clock.svg +0 -83
  186. package/website/assets/silhouettes/base-camp.svg +0 -81
  187. package/website/assets/silhouettes/bridge.svg +0 -69
  188. package/website/assets/silhouettes/docs-bundle.svg +0 -113
  189. package/website/assets/silhouettes/doko-basket.svg +0 -70
  190. package/website/assets/silhouettes/fortress.svg +0 -93
  191. package/website/assets/silhouettes/gateway.svg +0 -54
  192. package/website/assets/silhouettes/gears.svg +0 -93
  193. package/website/assets/silhouettes/globe-satellite.svg +0 -67
  194. package/website/assets/silhouettes/karma-wheel.svg +0 -137
  195. package/website/assets/silhouettes/lama-council.svg +0 -141
  196. package/website/assets/silhouettes/mandala-network.svg +0 -169
  197. package/website/assets/silhouettes/mani-stones.svg +0 -149
  198. package/website/assets/silhouettes/mantra-wheel.svg +0 -116
  199. package/website/assets/silhouettes/mesh-nodes.svg +0 -113
  200. package/website/assets/silhouettes/nakpak.svg +0 -56
  201. package/website/assets/silhouettes/peak-lightning.svg +0 -73
  202. package/website/assets/silhouettes/sherpa.svg +0 -69
  203. package/website/assets/silhouettes/stupa-tower.svg +0 -119
  204. package/website/assets/silhouettes/tattva-eye.svg +0 -78
  205. package/website/assets/silhouettes/terminal.svg +0 -74
  206. package/website/assets/silhouettes/webserver.svg +0 -145
  207. package/website/assets/silhouettes/yak.svg +0 -78
  208. package/website/assets/yakmesh-logo.png +0 -0
  209. package/website/assets/yakmesh-logo.webp +0 -0
  210. package/website/assets/yakmesh-logo128x140.webp +0 -0
  211. package/website/assets/yakmesh-logo2.png +0 -0
  212. package/website/assets/yakmesh-logo2.svg +0 -51
  213. package/website/assets/yakmesh-logo40x44.webp +0 -0
  214. package/website/assets/yakmesh.gif +0 -0
  215. package/website/assets/yakmesh.ico +0 -0
  216. package/website/assets/yakmesh.jpg +0 -0
  217. package/website/assets/yakmesh.pdf +0 -0
  218. package/website/assets/yakmesh.png +0 -0
  219. package/website/assets/yakmesh.svg +0 -70
  220. package/website/assets/yakmesh128.webp +0 -0
  221. package/website/assets/yakmesh32.png +0 -0
  222. package/website/assets/yakmesh32.svg +0 -65
  223. package/website/assets/yakmesh32o.ico +0 -2
  224. package/website/assets/yakmesh32o.svg +0 -65
  225. package/website/assets/yakmesh32o.svgz +0 -0
@@ -8,15 +8,22 @@
8
8
  * On Windows: Creates sharing violations for write access
9
9
  * On Unix: Removes write permissions during runtime
10
10
  *
11
+ * v1.3.0 ENHANCEMENTS:
12
+ * - File system watchdog for tampering detection
13
+ * - Tampering attempt logging and alerting
14
+ * - Identity key file protection (chmod 400)
15
+ * - Secure data directory permissions
16
+ *
11
17
  * @module CodebaseLock
12
- * @version 1.2.0
18
+ * @version 1.3.0
13
19
  */
14
20
 
15
- import { openSync, closeSync, readdirSync, statSync, chmodSync } from 'fs';
16
- import { join, extname } from 'path';
21
+ import { openSync, closeSync, readdirSync, statSync, chmodSync, watch, existsSync } from 'fs';
22
+ import { join, extname, basename } from 'path';
17
23
  import { fileURLToPath } from 'url';
18
24
  import { dirname } from 'path';
19
25
  import { createLogger } from '../utils/logger.js';
26
+ import { EventEmitter } from 'events';
20
27
 
21
28
  const log = createLogger('oracle:codebase-lock');
22
29
 
@@ -53,20 +60,51 @@ const EXCLUDE_FILES = new Set([
53
60
  '.env',
54
61
  ]);
55
62
 
63
+ // Identity/security files that need extra protection (chmod 400)
64
+ const CRITICAL_FILES = [
65
+ 'identity/node-key.json',
66
+ 'identity/private-key.pem',
67
+ 'data/node-identity.json',
68
+ ];
69
+
70
+ // Directories containing sensitive data
71
+ const SECURE_DIRS = [
72
+ 'identity',
73
+ 'data',
74
+ ];
75
+
76
+ /**
77
+ * TamperEvent - emitted when tampering is detected
78
+ */
79
+ export class TamperEvent {
80
+ constructor(type, path, details = {}) {
81
+ this.type = type; // 'modify' | 'delete' | 'create' | 'rename'
82
+ this.path = path;
83
+ this.details = details;
84
+ this.timestamp = Date.now();
85
+ this.isoTime = new Date().toISOString();
86
+ }
87
+ }
88
+
56
89
  /**
57
90
  * CodebaseLock - Runtime file locking for source code protection
91
+ * Now with tampering detection watchdog
58
92
  */
59
- export class CodebaseLock {
93
+ export class CodebaseLock extends EventEmitter {
60
94
  #handles = [];
61
95
  #locked = false;
62
96
  #rootDir = null;
63
97
  #isWindows = process.platform === 'win32';
64
98
  #originalPermissions = new Map();
65
-
99
+ #watchers = [];
100
+ #tamperEvents = [];
101
+ #watchdogActive = false;
102
+
66
103
  constructor() {
104
+ super();
67
105
  this.#rootDir = join(__dirname, '..');
68
106
  }
69
-
107
+
70
108
  /**
71
109
  * Lock all source files in the codebase
72
110
  * @returns {Object} Result with success status and file count
@@ -75,10 +113,10 @@ export class CodebaseLock {
75
113
  if (this.#locked) {
76
114
  return { success: true, fileCount: this.#handles.length, message: 'Already locked' };
77
115
  }
78
-
116
+
79
117
  try {
80
118
  const sourceFiles = this.#collectSourceFiles(this.#rootDir);
81
-
119
+
82
120
  for (const filePath of sourceFiles) {
83
121
  try {
84
122
  if (this.#isWindows) {
@@ -90,7 +128,7 @@ export class CodebaseLock {
90
128
  const stats = statSync(filePath);
91
129
  const originalMode = stats.mode;
92
130
  this.#originalPermissions.set(filePath, originalMode);
93
-
131
+
94
132
  // Remove write permissions (keep read/execute)
95
133
  const newMode = originalMode & ~0o222;
96
134
  chmodSync(filePath, newMode);
@@ -102,22 +140,30 @@ export class CodebaseLock {
102
140
  log.warn('Could not lock file', { path: filePath, error: e.message });
103
141
  }
104
142
  }
105
-
143
+
106
144
  this.#locked = true;
107
- return {
108
- success: true,
145
+
146
+ // Start watchdog for tampering detection
147
+ this.#startWatchdog();
148
+
149
+ // Protect critical identity files
150
+ this.#protectCriticalFiles();
151
+
152
+ return {
153
+ success: true,
109
154
  fileCount: this.#handles.length,
110
155
  message: `Locked ${this.#handles.length} source files`,
156
+ watchdogActive: this.#watchdogActive,
111
157
  };
112
158
  } catch (e) {
113
- return {
114
- success: false,
159
+ return {
160
+ success: false,
115
161
  error: e.message,
116
162
  fileCount: 0,
117
163
  };
118
164
  }
119
165
  }
120
-
166
+
121
167
  /**
122
168
  * Unlock all source files
123
169
  * @returns {Object} Result with success status
@@ -126,9 +172,9 @@ export class CodebaseLock {
126
172
  if (!this.#locked) {
127
173
  return { success: true, message: 'Not locked' };
128
174
  }
129
-
175
+
130
176
  let errors = [];
131
-
177
+
132
178
  for (const handle of this.#handles) {
133
179
  try {
134
180
  if (this.#isWindows && handle.fd !== undefined) {
@@ -142,18 +188,21 @@ export class CodebaseLock {
142
188
  errors.push(`${handle.path}: ${e.message}`);
143
189
  }
144
190
  }
145
-
191
+
146
192
  this.#handles = [];
147
193
  this.#originalPermissions.clear();
148
194
  this.#locked = false;
149
-
150
- return {
195
+
196
+ // Stop watchdog
197
+ this.#stopWatchdog();
198
+
199
+ return {
151
200
  success: errors.length === 0,
152
201
  errors: errors.length > 0 ? errors : undefined,
153
202
  message: 'Codebase unlocked',
154
203
  };
155
204
  }
156
-
205
+
157
206
  /**
158
207
  * Check if codebase is currently locked
159
208
  * @returns {boolean}
@@ -161,7 +210,30 @@ export class CodebaseLock {
161
210
  isLocked() {
162
211
  return this.#locked;
163
212
  }
164
-
213
+
214
+ /**
215
+ * Check if watchdog is active
216
+ * @returns {boolean}
217
+ */
218
+ isWatchdogActive() {
219
+ return this.#watchdogActive;
220
+ }
221
+
222
+ /**
223
+ * Get tampering events (if any)
224
+ * @returns {TamperEvent[]}
225
+ */
226
+ getTamperEvents() {
227
+ return [...this.#tamperEvents];
228
+ }
229
+
230
+ /**
231
+ * Clear tampering events after review
232
+ */
233
+ clearTamperEvents() {
234
+ this.#tamperEvents = [];
235
+ }
236
+
165
237
  /**
166
238
  * Get count of locked files
167
239
  * @returns {number}
@@ -169,7 +241,7 @@ export class CodebaseLock {
169
241
  getLockedFileCount() {
170
242
  return this.#handles.length;
171
243
  }
172
-
244
+
173
245
  /**
174
246
  * Collect all source files recursively
175
247
  * @private
@@ -177,10 +249,10 @@ export class CodebaseLock {
177
249
  #collectSourceFiles(dir, results = []) {
178
250
  try {
179
251
  const entries = readdirSync(dir, { withFileTypes: true });
180
-
252
+
181
253
  for (const entry of entries) {
182
254
  const fullPath = join(dir, entry.name);
183
-
255
+
184
256
  if (entry.isDirectory()) {
185
257
  // Skip excluded directories
186
258
  if (!EXCLUDE_DIRS.has(entry.name)) {
@@ -188,7 +260,7 @@ export class CodebaseLock {
188
260
  }
189
261
  } else if (entry.isFile()) {
190
262
  const ext = extname(entry.name).toLowerCase();
191
-
263
+
192
264
  // Include only source files, exclude specific files
193
265
  if (SOURCE_EXTENSIONS.has(ext) && !EXCLUDE_FILES.has(entry.name)) {
194
266
  results.push(fullPath);
@@ -198,9 +270,133 @@ export class CodebaseLock {
198
270
  } catch (e) {
199
271
  // Directory might not be readable
200
272
  }
201
-
273
+
202
274
  return results;
203
275
  }
276
+
277
+ /**
278
+ * Start file system watchdog for tampering detection
279
+ * @private
280
+ */
281
+ #startWatchdog() {
282
+ if (this.#watchdogActive) return;
283
+
284
+ try {
285
+ // Watch key directories for changes
286
+ const dirsToWatch = ['server', 'oracle', 'security', 'mesh', 'identity', 'gossip'];
287
+
288
+ for (const dirName of dirsToWatch) {
289
+ const dirPath = join(this.#rootDir, dirName);
290
+ if (!existsSync(dirPath)) continue;
291
+
292
+ try {
293
+ const watcher = watch(dirPath, { recursive: true }, (eventType, filename) => {
294
+ if (!filename) return;
295
+
296
+ // Only care about source files
297
+ const ext = extname(filename).toLowerCase();
298
+ if (!SOURCE_EXTENSIONS.has(ext)) return;
299
+
300
+ const event = new TamperEvent(eventType, join(dirPath, filename), {
301
+ directory: dirName,
302
+ filename,
303
+ });
304
+
305
+ this.#tamperEvents.push(event);
306
+
307
+ // Emit event for external handlers
308
+ this.emit('tamper', event);
309
+
310
+ // Log as critical security event
311
+ log.error('⚠️ TAMPERING DETECTED', {
312
+ type: eventType,
313
+ file: filename,
314
+ directory: dirName,
315
+ timestamp: event.isoTime,
316
+ });
317
+ });
318
+
319
+ this.#watchers.push(watcher);
320
+ } catch (e) {
321
+ log.warn('Could not watch directory', { dir: dirName, error: e.message });
322
+ }
323
+ }
324
+
325
+ this.#watchdogActive = this.#watchers.length > 0;
326
+
327
+ if (this.#watchdogActive) {
328
+ log.info('Watchdog active', { directories: this.#watchers.length });
329
+ }
330
+ } catch (e) {
331
+ log.warn('Watchdog failed to start', { error: e.message });
332
+ }
333
+ }
334
+
335
+ /**
336
+ * Stop file system watchdog
337
+ * @private
338
+ */
339
+ #stopWatchdog() {
340
+ for (const watcher of this.#watchers) {
341
+ try {
342
+ watcher.close();
343
+ } catch (e) {
344
+ // Ignore close errors
345
+ }
346
+ }
347
+ this.#watchers = [];
348
+ this.#watchdogActive = false;
349
+ }
350
+
351
+ /**
352
+ * Protect critical identity and security files
353
+ * Sets chmod 400 (read-only owner) on sensitive files
354
+ * @private
355
+ */
356
+ #protectCriticalFiles() {
357
+ if (this.#isWindows) {
358
+ // Windows doesn't support Unix permissions in the same way
359
+ // The file handle locking already provides protection
360
+ return;
361
+ }
362
+
363
+ for (const relPath of CRITICAL_FILES) {
364
+ const fullPath = join(this.#rootDir, relPath);
365
+
366
+ if (!existsSync(fullPath)) continue;
367
+
368
+ try {
369
+ const stats = statSync(fullPath);
370
+
371
+ // Store original permissions
372
+ if (!this.#originalPermissions.has(fullPath)) {
373
+ this.#originalPermissions.set(fullPath, stats.mode);
374
+ }
375
+
376
+ // Set to 0400 (read-only owner)
377
+ chmodSync(fullPath, 0o400);
378
+
379
+ log.info('Protected critical file', { path: relPath, mode: '0400' });
380
+ } catch (e) {
381
+ log.warn('Could not protect critical file', { path: relPath, error: e.message });
382
+ }
383
+ }
384
+
385
+ // Secure data directories
386
+ for (const dirName of SECURE_DIRS) {
387
+ const dirPath = join(this.#rootDir, dirName);
388
+
389
+ if (!existsSync(dirPath)) continue;
390
+
391
+ try {
392
+ // Set directory to 0700 (owner only)
393
+ chmodSync(dirPath, 0o700);
394
+ log.info('Secured directory', { path: dirName, mode: '0700' });
395
+ } catch (e) {
396
+ log.warn('Could not secure directory', { path: dirName, error: e.message });
397
+ }
398
+ }
399
+ }
204
400
  }
205
401
 
206
402
  // Singleton instance
@@ -244,16 +440,49 @@ export function setupUnlockOnExit() {
244
440
  lock.unlock();
245
441
  }
246
442
  };
247
-
443
+
248
444
  // Handle various exit signals
249
445
  process.on('exit', cleanup);
250
446
  process.on('SIGINT', () => { cleanup(); process.exit(0); });
251
447
  process.on('SIGTERM', () => { cleanup(); process.exit(0); });
448
+ // Transient network errors that are safe to ignore in a P2P mesh node.
449
+ // These bubble up as uncaught exceptions when TCP connections are reset
450
+ // by remote peers, timeouts occur, or connections are refused — all
451
+ // normal in a mesh network. Crashing on these kills the node needlessly.
452
+ const TRANSIENT_NETWORK_ERRORS = new Set([
453
+ 'ECONNRESET', 'EPIPE', 'ECONNREFUSED', 'ETIMEDOUT',
454
+ 'ECONNABORTED', 'EHOSTUNREACH', 'ENETUNREACH', 'EAI_AGAIN',
455
+ ]);
456
+
252
457
  process.on('uncaughtException', (err) => {
458
+ // Check if this is a transient network error
459
+ if (err.code && TRANSIENT_NETWORK_ERRORS.has(err.code)) {
460
+ log.warn('Transient network error (non-fatal)', { code: err.code, error: err.message });
461
+ return; // Do NOT exit — these are normal in P2P mesh operation
462
+ }
253
463
  log.error('Uncaught exception', { error: err.message, stack: err.stack });
254
464
  cleanup();
255
465
  process.exit(1);
256
466
  });
257
467
  }
258
468
 
469
+ /**
470
+ * Subscribe to tampering events
471
+ * @param {Function} handler - Called with TamperEvent on tampering
472
+ * @returns {Function} Unsubscribe function
473
+ */
474
+ export function onTamper(handler) {
475
+ const lock = getCodebaseLock();
476
+ lock.on('tamper', handler);
477
+ return () => lock.off('tamper', handler);
478
+ }
479
+
480
+ /**
481
+ * Get any tampering events that occurred
482
+ * @returns {TamperEvent[]}
483
+ */
484
+ export function getTamperEvents() {
485
+ return getCodebaseLock().getTamperEvents();
486
+ }
487
+
259
488
  export default CodebaseLock;
package/oracle/index.js CHANGED
@@ -41,27 +41,27 @@
41
41
  * @version 1.1.0
42
42
  */
43
43
 
44
- export {
45
- ValidationOracle,
44
+ export {
45
+ ValidationOracle,
46
46
  ValidationResult,
47
47
  getOracle,
48
48
  contentHash,
49
49
  deterministicStringify,
50
50
  } from './validation-oracle-hardened.js';
51
51
 
52
- export {
53
- CodeProofProtocol,
52
+ export {
53
+ CodeProofProtocol,
54
54
  ProofState,
55
55
  mutualVerification,
56
56
  } from './code-proof-protocol.js';
57
57
 
58
- export {
59
- ConsensusEngine,
58
+ export {
59
+ ConsensusEngine,
60
60
  ContentState,
61
61
  } from './consensus-engine.js';
62
62
 
63
- export {
64
- ModuleSealer,
63
+ export {
64
+ ModuleSealer,
65
65
  SealedModule,
66
66
  } from './module-sealer.js';
67
67
 
@@ -88,12 +88,71 @@ export {
88
88
  // Codebase lock - prevents source modification during runtime
89
89
  export {
90
90
  CodebaseLock,
91
+ TamperEvent,
91
92
  getCodebaseLock,
92
93
  lockCodebase,
93
94
  unlockCodebase,
94
95
  setupUnlockOnExit,
96
+ onTamper,
97
+ getTamperEvents,
95
98
  } from './codebase-lock.js';
96
99
 
100
+ // ═══════════════════════════════════════════════════════════════════════════════
101
+ // TRIBHUJ - Balanced Ternary Mathematics
102
+ // The foundational trit operations: {-1, 0, +1}
103
+ // ═══════════════════════════════════════════════════════════════════════════════
104
+ export {
105
+ POSITIVE, NEUTRAL, NEGATIVE,
106
+ TritState,
107
+ TritChars,
108
+ Trit,
109
+ TritArray,
110
+ hexToTrits,
111
+ hexCompare,
112
+ calculatePathBalance,
113
+ } from './tribhuj.js';
114
+
115
+ // ═══════════════════════════════════════════════════════════════════════════════
116
+ // SST - Synergy Sequence Theory
117
+ // The mathematical backbone: digital roots, family classification,
118
+ // Fibonacci 24-cycle, trust geometry, hexagonal tessellation
119
+ // ═══════════════════════════════════════════════════════════════════════════════
120
+ export {
121
+ // Constants
122
+ SSTFamily,
123
+ FIBONACCI_CYCLE_24,
124
+ FAMILY_TO_TRIT,
125
+ SynergyAngles,
126
+ TRUST_PROPAGATION,
127
+ HEX_CELL_SIZES,
128
+ // Digital root & family
129
+ digitalRoot,
130
+ getFamily,
131
+ getFamilyOf,
132
+ toFamilyTrit,
133
+ bytesToFamilyTrits,
134
+ analyzeBytesFamilies,
135
+ // Fibonacci analysis
136
+ fibonacciRoot,
137
+ fibonacciFamily,
138
+ fibonacciFamilyTrit,
139
+ analyzeFibonacciCycle,
140
+ generateFibonacciSequence,
141
+ // Synergy matrix
142
+ generateSynergyMatrix,
143
+ rowToFamilyPattern,
144
+ matrixToTritPatterns,
145
+ // Trust geometry (30-60-90 triangle)
146
+ propagateTrust,
147
+ trustHalfLife,
148
+ decayTrust,
149
+ // Hex grid
150
+ HexCoord,
151
+ hexRing,
152
+ hexDisk,
153
+ hexDiskSize,
154
+ } from './sst.js';
155
+
97
156
  /**
98
157
  * Create a fully configured oracle system for a Lantern node
99
158
  *
@@ -105,16 +164,16 @@ export function createOracleSystem(nodeIdentity, options = {}) {
105
164
  const { getOracle } = require('./validation-oracle-hardened.js');
106
165
  const { CodeProofProtocol } = require('./code-proof-protocol.js');
107
166
  const { ConsensusEngine } = require('./consensus-engine.js');
108
-
167
+
109
168
  const oracle = getOracle();
110
169
  const codeProof = new CodeProofProtocol(nodeIdentity);
111
170
  const consensus = new ConsensusEngine(nodeIdentity, options);
112
-
171
+
113
172
  return {
114
173
  oracle,
115
174
  codeProof,
116
175
  consensus,
117
-
176
+
118
177
  // Convenience methods
119
178
  validate: (type, content) => {
120
179
  switch (type) {
@@ -124,19 +183,19 @@ export function createOracleSystem(nodeIdentity, options = {}) {
124
183
  default: return { valid: false, reason: 'UNKNOWN_TYPE' };
125
184
  }
126
185
  },
127
-
186
+
128
187
  submit: (type, content, metadata) => {
129
188
  return consensus.submitContent(type, content, metadata);
130
189
  },
131
-
190
+
132
191
  generateChallenge: (peerId) => {
133
192
  return codeProof.generateChallenge(peerId);
134
193
  },
135
-
194
+
136
195
  verifyPeer: (proof) => {
137
196
  return oracle.verifyCodeProof(proof);
138
197
  },
139
-
198
+
140
199
  getStats: () => ({
141
200
  oracle: oracle.getModuleSeal(),
142
201
  consensus: consensus.getStats(),