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.
- package/CHANGELOG.md +637 -0
- package/Caddyfile +77 -0
- package/README.md +119 -29
- package/content/api.js +50 -41
- package/content/index.js +1 -2
- package/content/store.js +323 -177
- package/dashboard/index.html +19 -3
- package/database/replication.js +117 -37
- package/docs/CRYPTO-AGILITY.md +204 -0
- package/docs/MTLS-RESEARCH.md +367 -0
- package/docs/NAMCHE-SPEC.md +681 -0
- package/docs/PEERQUANTA-YAKMESH-INTEGRATION.md +407 -0
- package/docs/PRECISION-DISCLOSURE.md +96 -0
- package/docs/README.md +76 -0
- package/docs/ROADMAP-2.4.0.md +447 -0
- package/docs/ROADMAP-2.5.0.md +244 -0
- package/docs/SECURITY-AUDIT-REPORT.md +306 -0
- package/docs/SST-INTEGRATION.md +712 -0
- package/docs/STEADYWATCH-IMPLEMENTATION.md +303 -0
- package/docs/TERNARY-AUDIT-REPORT.md +247 -0
- package/docs/TME-FAQ.md +221 -0
- package/docs/WHITEPAPER.md +623 -0
- package/docs/adapters.html +1001 -0
- package/docs/advanced-systems.html +1045 -0
- package/docs/annex.html +1046 -0
- package/docs/api.html +970 -0
- package/docs/business/response-templates.md +160 -0
- package/docs/c2c.html +1225 -0
- package/docs/cli.html +1332 -0
- package/docs/configuration.html +1248 -0
- package/docs/darshan.html +1085 -0
- package/docs/dharma.html +966 -0
- package/docs/docs-bundle.html +1075 -0
- package/docs/docs.css +3120 -0
- package/docs/docs.js +556 -0
- package/docs/doko.html +969 -0
- package/docs/geo-proof.html +858 -0
- package/docs/getting-started.html +840 -0
- package/docs/gumba-tutorial.html +1144 -0
- package/docs/gumba.html +1098 -0
- package/docs/index.html +914 -0
- package/docs/jhilke.html +1312 -0
- package/docs/karma.html +1100 -0
- package/docs/katha.html +1037 -0
- package/docs/lama.html +978 -0
- package/docs/mandala.html +1067 -0
- package/docs/mani.html +964 -0
- package/docs/mantra.html +967 -0
- package/docs/mesh.html +1409 -0
- package/docs/nakpak.html +869 -0
- package/docs/namche.html +928 -0
- package/docs/nav-order.json +53 -0
- package/docs/prahari.html +1043 -0
- package/docs/prism-bash.min.js +1 -0
- package/docs/prism-javascript.min.js +1 -0
- package/docs/prism-json.min.js +1 -0
- package/docs/prism-tomorrow.min.css +1 -0
- package/docs/prism.min.js +1 -0
- package/docs/privacy.html +699 -0
- package/docs/quick-reference.html +1181 -0
- package/docs/sakshi.html +1402 -0
- package/docs/sandboxing.md +386 -0
- package/docs/seva.html +911 -0
- package/docs/sherpa.html +871 -0
- package/docs/studio.html +860 -0
- package/docs/stupa.html +995 -0
- package/docs/tailwind.min.css +2 -0
- package/docs/tattva.html +1332 -0
- package/docs/terms.html +686 -0
- package/docs/time-server-deployment.md +166 -0
- package/docs/time-sources.html +1392 -0
- package/docs/tivra.html +1127 -0
- package/docs/trademark-policy.html +686 -0
- package/docs/tribhuj.html +1183 -0
- package/docs/trust-security.html +1029 -0
- package/docs/tutorials/backup-recovery.html +654 -0
- package/docs/tutorials/dashboard.html +604 -0
- package/docs/tutorials/domain-setup.html +605 -0
- package/docs/tutorials/host-website.html +456 -0
- package/docs/tutorials/mesh-network.html +505 -0
- package/docs/tutorials/mobile-access.html +445 -0
- package/docs/tutorials/privacy.html +467 -0
- package/docs/tutorials/raspberry-pi.html +600 -0
- package/docs/tutorials/security-basics.html +539 -0
- package/docs/tutorials/share-files.html +431 -0
- package/docs/tutorials/troubleshooting.html +637 -0
- package/docs/tutorials/trust-karma.html +419 -0
- package/docs/tutorials/yak-protocol.html +456 -0
- package/docs/tutorials.html +1034 -0
- package/docs/vani.html +1270 -0
- package/docs/webserver.html +809 -0
- package/docs/yak-protocol.html +940 -0
- package/docs/yak-timeserver-design.md +475 -0
- package/docs/yakapp.html +1015 -0
- package/docs/ypc27.html +1069 -0
- package/docs/yurt.html +1344 -0
- package/embedded-docs/bundle.js +274 -114
- package/gossip/protocol.js +247 -27
- package/identity/key-resolver.js +262 -0
- package/identity/machine-seed.js +632 -0
- package/identity/node-key.js +669 -368
- package/identity/tribhuj-ratchet.js +506 -0
- package/knowledge-base.js +37 -8
- package/launcher/yakmesh.bat +62 -0
- package/launcher/yakmesh.sh +70 -0
- package/mesh/annex.js +462 -108
- package/mesh/beacon-broadcast.js +4 -1
- package/mesh/darshan.js +17 -5
- package/mesh/gumba.js +47 -13
- package/mesh/jhilke.js +651 -0
- package/mesh/katha.js +5 -2
- package/mesh/nakpak-routing.js +8 -5
- package/mesh/network.js +724 -34
- package/mesh/pulse-sync.js +4 -1
- package/mesh/seva.js +526 -0
- package/mesh/sherpa-discovery.js +89 -8
- package/mesh/sybil-defense.js +19 -5
- package/mesh/temporal-encoder.js +4 -3
- package/mesh/yurt.js +72 -17
- package/models/entropy-sentinel.onnx +0 -0
- package/models/karma-trust.onnx +0 -0
- package/models/manifest.json +43 -0
- package/models/sakshi-anomaly.onnx +0 -0
- package/oracle/code-proof-protocol.js +7 -6
- package/oracle/codebase-lock.js +257 -28
- package/oracle/index.js +74 -15
- package/oracle/ma902-snmp.js +678 -0
- package/oracle/module-sealer.js +5 -3
- package/oracle/packet-checksum.js +201 -0
- package/oracle/ternary-144t.js +714 -0
- package/oracle/ternary-ml.js +481 -0
- package/oracle/time-api.js +239 -0
- package/oracle/time-source.js +137 -47
- package/oracle/validation-oracle-hardened.js +1111 -1071
- package/oracle/validation-oracle.js +4 -2
- package/oracle/ypc27.js +211 -0
- package/package.json +20 -3
- package/protocol/yak-handler.js +35 -9
- package/protocol/yak-protocol.js +6 -5
- package/reference/cpp/yakmesh_mceliece_shard.cpp +168 -0
- package/reference/cpp/yakmesh_ypc27.cpp +179 -0
- package/sbom.json +87 -0
- package/scripts/security-audit.mjs +264 -0
- package/scripts/update-docs-sidebar.cjs +164 -0
- package/security/crypto-config.js +4 -3
- package/security/dharma-moderation.js +4 -3
- package/security/doko-identity.js +193 -143
- package/security/domain-consensus.js +86 -85
- package/security/fs-hardening.js +620 -0
- package/security/hardware-attestation.js +5 -3
- package/security/hybrid-trust.js +227 -87
- package/security/karma-rate-limiter.js +692 -0
- package/security/khata-protocol.js +22 -21
- package/security/khata-trust-integration.js +277 -150
- package/security/memory-safety.js +635 -0
- package/security/mesh-auth.js +11 -10
- package/security/mesh-revocation.js +18 -5
- package/security/namche-gateway.js +298 -69
- package/security/sakshi.js +102 -3
- package/security/sangha.js +770 -0
- package/security/secure-config.js +473 -0
- package/security/silicon-parity.js +13 -10
- package/security/steadywatch.js +1142 -0
- package/security/strike-system.js +32 -3
- package/security/temporal-signing.js +488 -0
- package/security/trit-commitment.js +464 -0
- package/server/crypto/annex.js +247 -0
- package/server/darshan-api.js +343 -0
- package/server/index.js +3259 -362
- package/server/komm-api.js +668 -0
- package/utils/accel.js +2273 -0
- package/utils/ternary-id.js +79 -0
- package/utils/verify-worker.js +57 -0
- package/webserver/index.js +95 -5
- package/assets/yakmesh-logo.png +0 -0
- package/assets/yakmesh-logo.svg +0 -80
- package/assets/yakmesh-logo2.png +0 -0
- package/assets/yakmesh-logo2sm.png +0 -0
- package/assets/ymsm.png +0 -0
- package/scripts/update-docs-nav.cjs +0 -194
- package/update-docs-nav.cjs +0 -18
- package/update-nav.ps1 +0 -16
- package/website/assets/silhouettes/adapters.svg +0 -107
- package/website/assets/silhouettes/api-endpoints.svg +0 -115
- package/website/assets/silhouettes/atomic-clock.svg +0 -83
- package/website/assets/silhouettes/base-camp.svg +0 -81
- package/website/assets/silhouettes/bridge.svg +0 -69
- package/website/assets/silhouettes/docs-bundle.svg +0 -113
- package/website/assets/silhouettes/doko-basket.svg +0 -70
- package/website/assets/silhouettes/fortress.svg +0 -93
- package/website/assets/silhouettes/gateway.svg +0 -54
- package/website/assets/silhouettes/gears.svg +0 -93
- package/website/assets/silhouettes/globe-satellite.svg +0 -67
- package/website/assets/silhouettes/karma-wheel.svg +0 -137
- package/website/assets/silhouettes/lama-council.svg +0 -141
- package/website/assets/silhouettes/mandala-network.svg +0 -169
- package/website/assets/silhouettes/mani-stones.svg +0 -149
- package/website/assets/silhouettes/mantra-wheel.svg +0 -116
- package/website/assets/silhouettes/mesh-nodes.svg +0 -113
- package/website/assets/silhouettes/nakpak.svg +0 -56
- package/website/assets/silhouettes/peak-lightning.svg +0 -73
- package/website/assets/silhouettes/sherpa.svg +0 -69
- package/website/assets/silhouettes/stupa-tower.svg +0 -119
- package/website/assets/silhouettes/tattva-eye.svg +0 -78
- package/website/assets/silhouettes/terminal.svg +0 -74
- package/website/assets/silhouettes/webserver.svg +0 -145
- package/website/assets/silhouettes/yak.svg +0 -78
- package/website/assets/yakmesh-logo.png +0 -0
- package/website/assets/yakmesh-logo.webp +0 -0
- package/website/assets/yakmesh-logo128x140.webp +0 -0
- package/website/assets/yakmesh-logo2.png +0 -0
- package/website/assets/yakmesh-logo2.svg +0 -51
- package/website/assets/yakmesh-logo40x44.webp +0 -0
- package/website/assets/yakmesh.gif +0 -0
- package/website/assets/yakmesh.ico +0 -0
- package/website/assets/yakmesh.jpg +0 -0
- package/website/assets/yakmesh.pdf +0 -0
- package/website/assets/yakmesh.png +0 -0
- package/website/assets/yakmesh.svg +0 -70
- package/website/assets/yakmesh128.webp +0 -0
- package/website/assets/yakmesh32.png +0 -0
- package/website/assets/yakmesh32.svg +0 -65
- package/website/assets/yakmesh32o.ico +0 -2
- package/website/assets/yakmesh32o.svg +0 -65
- package/website/assets/yakmesh32o.svgz +0 -0
package/oracle/codebase-lock.js
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
108
|
-
|
|
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
|
-
|
|
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(),
|