yakmesh 2.8.2 → 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/CONTRIBUTING.md +42 -0
- package/Caddyfile +77 -0
- package/README.md +119 -29
- package/adapters/adapter-mlv-bible/README.md +124 -0
- package/adapters/adapter-mlv-bible/index.js +400 -0
- package/adapters/chat-mod-adapter.js +532 -0
- package/adapters/content-adapter.js +273 -0
- package/content/api.js +50 -41
- package/content/index.js +2 -2
- package/content/store.js +355 -173
- 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 +334 -74
- 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 +113 -1
- package/mesh/darshan.js +1718 -0
- package/mesh/gumba.js +1567 -0
- package/mesh/jhilke.js +651 -0
- package/mesh/katha.js +1012 -0
- package/mesh/nakpak-routing.js +8 -5
- package/mesh/network.js +724 -34
- package/mesh/pulse-sync.js +4 -1
- package/mesh/rate-limiter.js +127 -15
- 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/vani.js +1364 -0
- package/mesh/yurt.js +1340 -0
- 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/network-identity.js +16 -0
- package/oracle/packet-checksum.js +201 -0
- package/oracle/sst.js +579 -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 +28 -13
- 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-nav.js +194 -0
- package/scripts/update-docs-sidebar.cjs +164 -0
- package/security/crypto-config.js +4 -3
- package/security/dharma-moderation.js +517 -0
- 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 +373 -5
- package/security/namche-gateway.js +298 -69
- package/security/sakshi.js +460 -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/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/mesh/sherpa-discovery.js
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import { sha3_256 } from '@noble/hashes/sha3.js';
|
|
23
23
|
import { bytesToHex, randomBytes, utf8ToBytes } from '@noble/hashes/utils.js';
|
|
24
24
|
import { EventEmitter } from 'events';
|
|
25
|
+
const peerTag = (id) => id?.split('-pq-').pop() || id?.slice?.(-8) || String(id);
|
|
25
26
|
|
|
26
27
|
// v2.7.0 Ternary Math Integration (TRIBHUJ)
|
|
27
28
|
import { Trit, TritState, calculatePathBalance, POSITIVE, NEUTRAL, NEGATIVE } from '../oracle/tribhuj.js';
|
|
@@ -257,6 +258,11 @@ class BeaconMessage {
|
|
|
257
258
|
this.timestamp = options.timestamp || Date.now();
|
|
258
259
|
this.ttl = options.ttl || 3600; // 1 hour default TTL
|
|
259
260
|
|
|
261
|
+
// Explicit reachable endpoints (override auto-constructed from ports)
|
|
262
|
+
// These let nodes behind firewalls/NAT advertise their actual connectable URLs
|
|
263
|
+
this.wsEndpoint = options.wsEndpoint || null; // e.g., "wss://mesh.yakmesh.dev"
|
|
264
|
+
this.relayEndpoint = options.relayEndpoint || null; // e.g., "https://yakmesh.dev/mesh/relay"
|
|
265
|
+
|
|
260
266
|
// Node capabilities
|
|
261
267
|
this.capabilities = {
|
|
262
268
|
wsPort: options.wsPort || null,
|
|
@@ -336,6 +342,7 @@ class BeaconMessage {
|
|
|
336
342
|
nodeId: peerInfo.nodeId,
|
|
337
343
|
endpoint: peerInfo.endpoint, // e.g., "https://example.com"
|
|
338
344
|
wsEndpoint: peerInfo.wsEndpoint, // e.g., "wss://example.com:9001"
|
|
345
|
+
relayEndpoint: peerInfo.relayEndpoint || null, // e.g., "https://example.com/mesh/relay"
|
|
339
346
|
lastSeen: peerInfo.lastSeen || Date.now(),
|
|
340
347
|
score: peerInfo.score || 1.0,
|
|
341
348
|
networkName: peerInfo.networkName,
|
|
@@ -363,7 +370,7 @@ class BeaconMessage {
|
|
|
363
370
|
* Serialize beacon for HTTP response
|
|
364
371
|
*/
|
|
365
372
|
serialize() {
|
|
366
|
-
|
|
373
|
+
const data = {
|
|
367
374
|
version: this.version,
|
|
368
375
|
nodeId: this.nodeId,
|
|
369
376
|
networkName: this.networkName,
|
|
@@ -376,6 +383,12 @@ class BeaconMessage {
|
|
|
376
383
|
publicKey: this.publicKey,
|
|
377
384
|
signature: this.signature,
|
|
378
385
|
};
|
|
386
|
+
|
|
387
|
+
// Include explicit endpoints if configured (firewall/NAT traversal)
|
|
388
|
+
if (this.wsEndpoint) data.wsEndpoint = this.wsEndpoint;
|
|
389
|
+
if (this.relayEndpoint) data.relayEndpoint = this.relayEndpoint;
|
|
390
|
+
|
|
391
|
+
return data;
|
|
379
392
|
}
|
|
380
393
|
|
|
381
394
|
/**
|
|
@@ -390,6 +403,9 @@ class BeaconMessage {
|
|
|
390
403
|
capabilities: this.capabilities,
|
|
391
404
|
geo: this.geo, // v2.5.0 include geo in signature
|
|
392
405
|
namche: this.namche, // Include NAMCHE in signature
|
|
406
|
+
// Include endpoints in signature to prevent tampering
|
|
407
|
+
wsEndpoint: this.wsEndpoint || undefined,
|
|
408
|
+
relayEndpoint: this.relayEndpoint || undefined,
|
|
393
409
|
});
|
|
394
410
|
}
|
|
395
411
|
|
|
@@ -402,6 +418,9 @@ class BeaconMessage {
|
|
|
402
418
|
networkName: data.networkName,
|
|
403
419
|
timestamp: data.timestamp,
|
|
404
420
|
ttl: data.ttl,
|
|
421
|
+
// Explicit reachable endpoints (must match what was signed)
|
|
422
|
+
wsEndpoint: data.wsEndpoint || null,
|
|
423
|
+
relayEndpoint: data.relayEndpoint || null,
|
|
405
424
|
wsPort: data.capabilities?.wsPort,
|
|
406
425
|
httpPort: data.capabilities?.httpPort,
|
|
407
426
|
supportsAnnex: data.capabilities?.supportsAnnex,
|
|
@@ -466,6 +485,8 @@ class PeerRegistry {
|
|
|
466
485
|
// Update existing peer
|
|
467
486
|
existing.endpoint = peerInfo.endpoint || existing.endpoint;
|
|
468
487
|
existing.wsEndpoint = peerInfo.wsEndpoint || existing.wsEndpoint;
|
|
488
|
+
existing.relayEndpoint = peerInfo.relayEndpoint || existing.relayEndpoint;
|
|
489
|
+
existing.publicKey = peerInfo.publicKey || existing.publicKey;
|
|
469
490
|
existing.lastSeen = Math.max(existing.lastSeen, peerInfo.lastSeen || Date.now());
|
|
470
491
|
existing.score = Math.min(1.0, existing.score + SHERPA_CONFIG.successBonus);
|
|
471
492
|
existing.capabilities = peerInfo.capabilities || existing.capabilities;
|
|
@@ -479,6 +500,8 @@ class PeerRegistry {
|
|
|
479
500
|
nodeId: peerInfo.nodeId,
|
|
480
501
|
endpoint: peerInfo.endpoint,
|
|
481
502
|
wsEndpoint: peerInfo.wsEndpoint,
|
|
503
|
+
relayEndpoint: peerInfo.relayEndpoint || null,
|
|
504
|
+
publicKey: peerInfo.publicKey || null,
|
|
482
505
|
lastSeen: peerInfo.lastSeen || Date.now(),
|
|
483
506
|
score: peerInfo.score || 1.0,
|
|
484
507
|
networkName: peerInfo.networkName,
|
|
@@ -595,6 +618,7 @@ class SherpaDiscovery extends EventEmitter {
|
|
|
595
618
|
// Our own endpoint info
|
|
596
619
|
this.selfEndpoint = options.selfEndpoint || null; // e.g., "https://mynode.com"
|
|
597
620
|
this.wsEndpoint = options.wsEndpoint || null;
|
|
621
|
+
this.relayEndpoint = options.relayEndpoint || null; // e.g., "https://mynode.com/mesh/relay"
|
|
598
622
|
this.capabilities = options.capabilities || {};
|
|
599
623
|
|
|
600
624
|
// v2.5.0 Geographic proof configuration
|
|
@@ -688,6 +712,9 @@ class SherpaDiscovery extends EventEmitter {
|
|
|
688
712
|
supportsNakpak: this.capabilities.supportsNakpak ?? true,
|
|
689
713
|
supportsGossip: this.capabilities.supportsGossip ?? true,
|
|
690
714
|
publicKey: this.publicKey,
|
|
715
|
+
// Explicit reachable endpoints (firewall/NAT traversal)
|
|
716
|
+
wsEndpoint: this.wsEndpoint,
|
|
717
|
+
relayEndpoint: this.relayEndpoint,
|
|
691
718
|
// v2.5.0 Geographic coordinates (if configured)
|
|
692
719
|
supportsGeoProof: this.geoConfig.enabled,
|
|
693
720
|
geoLat: this.geoConfig.lat,
|
|
@@ -745,12 +772,16 @@ class SherpaDiscovery extends EventEmitter {
|
|
|
745
772
|
|
|
746
773
|
// Add the beacon source as a peer
|
|
747
774
|
if (beacon.nodeId && beacon.nodeId !== this.nodeId) {
|
|
775
|
+
// Prefer explicit wsEndpoint from beacon (firewall/NAT aware)
|
|
776
|
+
// Fall back to auto-constructed from hostname:wsPort
|
|
777
|
+
const autoWsEndpoint = beacon.capabilities?.wsPort
|
|
778
|
+
? `wss://${new URL(endpoint).hostname}:${beacon.capabilities.wsPort}`
|
|
779
|
+
: null;
|
|
748
780
|
this.registry.upsert({
|
|
749
781
|
nodeId: beacon.nodeId,
|
|
750
782
|
endpoint: endpoint,
|
|
751
|
-
wsEndpoint: beacon.
|
|
752
|
-
|
|
753
|
-
: null,
|
|
783
|
+
wsEndpoint: beacon.wsEndpoint || autoWsEndpoint,
|
|
784
|
+
relayEndpoint: beacon.relayEndpoint || null,
|
|
754
785
|
networkName: beacon.networkName,
|
|
755
786
|
capabilities: beacon.capabilities,
|
|
756
787
|
});
|
|
@@ -769,6 +800,7 @@ class SherpaDiscovery extends EventEmitter {
|
|
|
769
800
|
nodeId: peer.nodeId,
|
|
770
801
|
endpoint: peer.endpoint,
|
|
771
802
|
wsEndpoint: peer.wsEndpoint,
|
|
803
|
+
relayEndpoint: peer.relayEndpoint,
|
|
772
804
|
networkName: peer.networkName,
|
|
773
805
|
lastSeen: peer.lastSeen,
|
|
774
806
|
});
|
|
@@ -807,7 +839,54 @@ class SherpaDiscovery extends EventEmitter {
|
|
|
807
839
|
* v2.5.0: Also measures RTT for geographic proof
|
|
808
840
|
*/
|
|
809
841
|
async _fetchBeacon(endpoint) {
|
|
810
|
-
|
|
842
|
+
// ── SSRF Protection: Validate endpoint URL before fetching ──
|
|
843
|
+
// Peer-supplied endpoints could target internal services, cloud metadata,
|
|
844
|
+
// or private networks. Block anything that isn't public HTTP(S).
|
|
845
|
+
let parsedUrl;
|
|
846
|
+
try {
|
|
847
|
+
parsedUrl = new URL(SHERPA_CONFIG.beaconPath, endpoint);
|
|
848
|
+
} catch {
|
|
849
|
+
throw new Error(`Invalid beacon endpoint URL: ${endpoint}`);
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// Only allow HTTP and HTTPS schemes
|
|
853
|
+
if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
|
|
854
|
+
throw new Error(`Blocked beacon fetch: disallowed scheme ${parsedUrl.protocol}`);
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// Block private/reserved IP ranges and cloud metadata endpoints
|
|
858
|
+
const hostname = parsedUrl.hostname.toLowerCase();
|
|
859
|
+
const BLOCKED_HOSTS = [
|
|
860
|
+
'localhost', '127.0.0.1', '::1', '[::1]', '0.0.0.0',
|
|
861
|
+
'169.254.169.254', // AWS/GCP/Azure metadata
|
|
862
|
+
'metadata.google.internal',
|
|
863
|
+
'metadata.google',
|
|
864
|
+
];
|
|
865
|
+
if (BLOCKED_HOSTS.includes(hostname)) {
|
|
866
|
+
throw new Error(`Blocked beacon fetch: reserved host ${hostname}`);
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
// Block private IP ranges: 10.x, 172.16-31.x, 192.168.x, fc00::/7, fe80::/10
|
|
870
|
+
const ipv4Match = hostname.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
|
|
871
|
+
if (ipv4Match) {
|
|
872
|
+
const [, a, b] = ipv4Match.map(Number);
|
|
873
|
+
if (a === 10 || // 10.0.0.0/8
|
|
874
|
+
(a === 172 && b >= 16 && b <= 31) || // 172.16.0.0/12
|
|
875
|
+
(a === 192 && b === 168) || // 192.168.0.0/16
|
|
876
|
+
a === 127 || // 127.0.0.0/8
|
|
877
|
+
a === 0 || // 0.0.0.0/8
|
|
878
|
+
(a === 169 && b === 254)) { // 169.254.0.0/16 (link-local)
|
|
879
|
+
throw new Error(`Blocked beacon fetch: private IP ${hostname}`);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
// Block IPv6 private: starts with fc, fd, or fe80
|
|
884
|
+
const bareV6 = hostname.replace(/^\[|\]$/g, '');
|
|
885
|
+
if (bareV6.startsWith('fc') || bareV6.startsWith('fd') || bareV6.startsWith('fe80')) {
|
|
886
|
+
throw new Error(`Blocked beacon fetch: private IPv6 ${hostname}`);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
const url = parsedUrl.toString();
|
|
811
890
|
|
|
812
891
|
const controller = new AbortController();
|
|
813
892
|
const timeout = setTimeout(() => controller.abort(), SHERPA_CONFIG.crawlTimeout);
|
|
@@ -877,14 +956,16 @@ class SherpaDiscovery extends EventEmitter {
|
|
|
877
956
|
}
|
|
878
957
|
|
|
879
958
|
/**
|
|
880
|
-
* Get connection candidates for mesh networking
|
|
959
|
+
* Get connection candidates for mesh networking.
|
|
960
|
+
* Returns peers that have either a wsEndpoint or relayEndpoint.
|
|
881
961
|
*/
|
|
882
962
|
getConnectionCandidates(count = 5) {
|
|
883
963
|
return this.registry.getBestPeers(count)
|
|
884
|
-
.filter(p => p.wsEndpoint)
|
|
964
|
+
.filter(p => p.wsEndpoint || p.relayEndpoint)
|
|
885
965
|
.map(p => ({
|
|
886
966
|
nodeId: p.nodeId,
|
|
887
967
|
wsEndpoint: p.wsEndpoint,
|
|
968
|
+
relayEndpoint: p.relayEndpoint || null,
|
|
888
969
|
score: p.score,
|
|
889
970
|
}));
|
|
890
971
|
}
|
|
@@ -979,7 +1060,7 @@ class SherpaDiscovery extends EventEmitter {
|
|
|
979
1060
|
beacon.geo.lat,
|
|
980
1061
|
beacon.geo.lon,
|
|
981
1062
|
{
|
|
982
|
-
name: beacon.geo.name || `SHERPA Beacon ${beacon.nodeId
|
|
1063
|
+
name: beacon.geo.name || `SHERPA Beacon ${peerTag(beacon.nodeId)}`,
|
|
983
1064
|
endpoint: beacon._endpoint,
|
|
984
1065
|
timeTier: beacon.geo.timeTier,
|
|
985
1066
|
accuracyKm: beacon.geo.accuracyKm,
|
package/mesh/sybil-defense.js
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Sybil Attack Protection Module
|
|
3
|
+
*
|
|
4
|
+
* Uses TRIBHUJ balanced ternary for connection evaluation:
|
|
5
|
+
* POSITIVE (+1): Accept — node is trusted or verified
|
|
6
|
+
* NEUTRAL ( 0): Challenge — node must prove itself (NAVR required)
|
|
7
|
+
* NEGATIVE (-1): Reject — node is banned or subnet saturated
|
|
8
|
+
*
|
|
3
9
|
* @module mesh/sybil-defense.js
|
|
4
10
|
*/
|
|
5
11
|
|
|
6
12
|
import { sha3_256 } from '@noble/hashes/sha3.js';
|
|
7
13
|
import { bytesToHex, utf8ToBytes } from '@noble/hashes/utils.js';
|
|
8
14
|
|
|
15
|
+
// ═══ TRIBHUJ — Balanced ternary for connection decisions ═══
|
|
16
|
+
import { POSITIVE, NEUTRAL, NEGATIVE } from '../oracle/tribhuj.js';
|
|
17
|
+
|
|
9
18
|
export class NAVR {
|
|
10
19
|
constructor(options = {}) {
|
|
11
20
|
this.difficulty = options.difficulty || 16;
|
|
@@ -125,16 +134,21 @@ export class SybilDefense {
|
|
|
125
134
|
this.diversity = new SubnetDiversity(options.diversity || {});
|
|
126
135
|
}
|
|
127
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Evaluate a connection request.
|
|
139
|
+
* Returns `allowed` boolean (backward compat) plus `verdict` trit:
|
|
140
|
+
* POSITIVE: accept, NEUTRAL: challenge required, NEGATIVE: reject
|
|
141
|
+
*/
|
|
128
142
|
evaluateConnection(ip, nodeId, NAVRSolution = null) {
|
|
129
143
|
const divCheck = this.diversity.allowConnection(ip);
|
|
130
|
-
if (!divCheck.allowed) return { allowed: false, reason: divCheck.reason };
|
|
144
|
+
if (!divCheck.allowed) return { allowed: false, verdict: NEGATIVE, reason: divCheck.reason };
|
|
131
145
|
let record = this.reputation.nodes.get(nodeId);
|
|
132
146
|
if (!record) record = this.reputation.registerNode(nodeId, NAVRSolution);
|
|
133
147
|
const trustLevel = this.reputation.getTrustLevel(nodeId);
|
|
134
|
-
if (trustLevel === 'banned') return { allowed: false, reason: 'Node is banned' };
|
|
135
|
-
if (trustLevel === 'unknown' && !NAVRSolution) return { allowed: false, reason: 'NAVR required', challenge: this.NAVR.createChallenge(nodeId) };
|
|
148
|
+
if (trustLevel === 'banned') return { allowed: false, verdict: NEGATIVE, reason: 'Node is banned' };
|
|
149
|
+
if (trustLevel === 'unknown' && !NAVRSolution) return { allowed: false, verdict: NEUTRAL, reason: 'NAVR required', challenge: this.NAVR.createChallenge(nodeId) };
|
|
136
150
|
this.diversity.addConnection(ip, nodeId);
|
|
137
|
-
return { allowed: true, trustLevel, reputation: record.reputation };
|
|
151
|
+
return { allowed: true, verdict: POSITIVE, trustLevel, reputation: record.reputation };
|
|
138
152
|
}
|
|
139
153
|
|
|
140
154
|
reportMessage(nodeId, valid) {
|
|
@@ -148,4 +162,4 @@ export class SybilDefense {
|
|
|
148
162
|
}
|
|
149
163
|
|
|
150
164
|
export default SybilDefense;
|
|
151
|
-
|
|
165
|
+
|
package/mesh/temporal-encoder.js
CHANGED
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
* @copyright 2026 YAKMESH™ Contributors
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
import {
|
|
23
|
+
import { createHash } from 'crypto';
|
|
24
|
+
import { ternaryId } from '../utils/ternary-id.js';
|
|
24
25
|
|
|
25
26
|
const TME_CONFIG = {
|
|
26
27
|
defaultSliceIntervalNs: 50_000_000,
|
|
@@ -112,7 +113,7 @@ class TemporalStream {
|
|
|
112
113
|
}
|
|
113
114
|
|
|
114
115
|
_generateStreamId() {
|
|
115
|
-
return
|
|
116
|
+
return ternaryId(16);
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
encode(message, meshPosition = [0, 0, 0]) {
|
|
@@ -287,7 +288,7 @@ class TemporalReconstructor {
|
|
|
287
288
|
|
|
288
289
|
class TemporalMeshEncoder {
|
|
289
290
|
constructor(options = {}) {
|
|
290
|
-
this.nodeId = options.nodeId ||
|
|
291
|
+
this.nodeId = options.nodeId || ternaryId(16);
|
|
291
292
|
this.meshPosition = options.meshPosition || [0, 0, 0];
|
|
292
293
|
this.reconstructor = new TemporalReconstructor();
|
|
293
294
|
this.outboundStreams = new Map();
|