yakmesh 1.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/README.md ADDED
@@ -0,0 +1,181 @@
1
+ <![CDATA[<div align="center">
2
+ <img src="https://yakmesh.dev/assets/yakmesh-logo2.png" alt="Yakmesh" width="200">
3
+
4
+ # 🏔️ YAKMESH: Sturdy & Secure
5
+
6
+ **Yielding Atomic Kernel Modular Encryption Secured Hub**
7
+
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+ [![Node.js](https://img.shields.io/badge/Node.js-18+-green.svg)](https://nodejs.org)
10
+ [![Post-Quantum](https://img.shields.io/badge/Crypto-Post--Quantum-blue.svg)](https://csrc.nist.gov/projects/post-quantum-cryptography)
11
+ [![npm version](https://img.shields.io/npm/v/yakmesh.svg)](https://www.npmjs.com/package/yakmesh)
12
+ </div>
13
+
14
+ ---
15
+
16
+ YAKMESH is a high-resiliency, decentralized networking layer designed for the 2026 threat landscape. Built with quantum-resistant cryptography at its core and anchored by PCIe atomic timing synchronization, YAKMESH provides a "sturdy" substrate for distributed systems that cannot afford to fail.
17
+
18
+ ## Why YAKMESH?
19
+
20
+ In an era where traditional ECDSA is increasingly vulnerable and network jitter can desynchronize global state, YAKMESH offers a three-pillar solution:
21
+
22
+ 🌿 **Yielding Resilience**: A self-healing mesh topology that adapts to node failure and adversarial interference without central authority.
23
+
24
+ ⚛️ **Atomic Precision**: Integrated support for PCIe atomic clock hardware, enabling nanosecond-level hardware timestamping for low-latency synchronization.
25
+
26
+ 🔐 **Quantum Hardened**: Fully compatible with Project Zond and the QRL (Quantum Resistant Ledger) ecosystem, utilizing stateless lattice-based signatures (ML-DSA) from Genesis.
27
+
28
+ ---
29
+
30
+ ## The Y.A.K.M.E.S.H. Philosophy
31
+
32
+ | Letter | Principle | Description |
33
+ |--------|-----------|-------------|
34
+ | **Y** | **Yielding** | Not brittle; flexible enough to absorb network shocks |
35
+ | **A** | **Atomic** | Grounded in the absolute truth of physical time |
36
+ | **K** | **Kernel** | The essential, innermost part of the secure stack |
37
+ | **M** | **Modular** | Swap out encryption primitives or transport layers as tech evolves |
38
+ | **E** | **Encryption** | Privacy and integrity by default |
39
+ | **S** | **Secured** | Hardened against both classical and quantum vectors |
40
+ | **H** | **Hub** | A nexus for decentralized data and peer-to-peer logic |
41
+
42
+ ---
43
+
44
+ ## Features
45
+
46
+ - 🔒 **Post-Quantum Secure** - ML-DSA-65 (NIST FIPS 204) signatures
47
+ - 🔮 **Self-Verifying Oracle** - Deterministic validation without external trust
48
+ - 🌐 **Mesh Networking** - P2P WebSocket communication with gossip protocol
49
+ - ⏱️ **Precision Timing** - Support for atomic clocks, GPS, PTP, NTP
50
+ - 🔌 **Plugin Architecture** - Adapters for any database or API
51
+ - 🛡️ **Phase Modulation** - Time-based anti-replay protection
52
+
53
+ ## Quick Start
54
+
55
+ ```bash
56
+ npm install yakmesh
57
+ ```
58
+
59
+ ```javascript
60
+ import { YakmeshNode } from 'yakmesh';
61
+
62
+ const node = new YakmeshNode({
63
+ node: { name: 'My Node' },
64
+ network: { httpPort: 3000, wsPort: 9001 },
65
+ });
66
+
67
+ await node.start();
68
+ ```
69
+
70
+ ## CLI
71
+
72
+ ```bash
73
+ # Initialize a new node
74
+ npx yakmesh init
75
+
76
+ # Start the node
77
+ npx yakmesh start
78
+
79
+ # Check status
80
+ npx yakmesh status
81
+ ```
82
+
83
+ ## Documentation
84
+
85
+ Full documentation available at **[yakmesh.dev](https://yakmesh.dev)**
86
+
87
+ ## Architecture
88
+
89
+ ```
90
+ yakmesh/
91
+ ├── oracle/ # Self-verifying validation engine
92
+ ├── mesh/ # WebSocket P2P networking
93
+ ├── gossip/ # Epidemic-style message propagation
94
+ ├── identity/ # Post-quantum key management
95
+ ├── database/ # SQLite replication engine
96
+ ├── adapters/ # Platform integration plugins
97
+ ├── security/ # Pro authentication & encryption
98
+ ├── webserver/ # Embedded Caddy web server
99
+ └── server/ # HTTP/WS server
100
+ ```
101
+
102
+ ## Network Identity
103
+
104
+ Each YAKMESH network has a unique identity derived from configurable salts:
105
+
106
+ ```javascript
107
+ import { setIdentityConfig } from 'yakmesh/oracle/network-identity.js';
108
+
109
+ setIdentityConfig({
110
+ networkPrefix: 'my', // Network ID prefix
111
+ identitySalt: 'my-app-v1', // Unique network salt
112
+ });
113
+
114
+ // Different salt = different network (cannot interoperate)
115
+ ```
116
+
117
+ ## Time Source Trust Levels
118
+
119
+ | Level | Source | Tolerance | Oracle Capable |
120
+ |-------|--------|-----------|----------------|
121
+ | ATOMIC | PCIe atomic clock | ±100ms | ✅ Yes |
122
+ | GPS | GPS with PPS | ±500ms | ✅ Yes |
123
+ | PTP | IEEE 1588 (Meinberg) | ±500ms | ⚠️ Partial |
124
+ | NTP | Standard NTP | ±5000ms | ❌ No |
125
+
126
+ ## Adapters
127
+
128
+ Create custom adapters by extending `BaseAdapter`:
129
+
130
+ ```javascript
131
+ import { BaseAdapter } from 'yakmesh/adapters/base-adapter.js';
132
+
133
+ class MyAdapter extends BaseAdapter {
134
+ async init() { /* Connect to your database */ }
135
+ getSchema() { return { tables: ['users', 'orders'] }; }
136
+ async fetchChanges(since) { /* Return changed records */ }
137
+ async applyChange(table, record, op) { /* Write to database */ }
138
+ }
139
+ ```
140
+
141
+ ### Official Adapters
142
+
143
+ - `@yakmesh/adapter-peerquanta` - PeerQuanta phpBB marketplace
144
+
145
+ ## API Endpoints
146
+
147
+ | Endpoint | Method | Description |
148
+ |----------|--------|-------------|
149
+ | `/health` | GET | Node health status |
150
+ | `/node` | GET | Node identity info |
151
+ | `/peers` | GET | Connected peers |
152
+ | `/oracle/status` | GET | Oracle integrity check |
153
+ | `/network/identity` | GET | Network identity (hash obfuscated) |
154
+ | `/time/status` | GET | Time source detection |
155
+ | `/time/capabilities` | GET | Time oracle eligibility |
156
+ | `/connect` | POST | Connect to a peer |
157
+
158
+ ## Pro Features
159
+
160
+ YAKMESH Pro includes additional security features:
161
+
162
+ - 🔐 **WebSocket Authentication** - Challenge-response auth with signatures
163
+ - 🔒 **Message Encryption** - XChaCha20-Poly1305 encrypted messages
164
+ - 📋 **Peer Allowlist/Blocklist** - Access control for private networks
165
+ - 🛡️ **Connection Rate Limiting** - DDoS protection
166
+
167
+ ## License
168
+
169
+ - **Community Edition**: MIT License
170
+ - **Pro Edition**: Proprietary License
171
+
172
+ ---
173
+
174
+ <div align="center">
175
+ <sub>Built with quantum principles. Secured by math.</sub>
176
+ <br><br>
177
+ <strong><a href="https://yakmesh.dev">yakmesh.dev</a></strong>
178
+ <br><br>
179
+ <sub>© 2026 YAKMESH Project. Sturdy & Secure.</sub>
180
+ </div>
181
+ ]]>
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Yakmesh - Base Adapter Interface
3
+ *
4
+ * All platform adapters must extend this class.
5
+ * Adapters bridge external data sources with the Yakmesh network.
6
+ *
7
+ * @module adapters/base-adapter
8
+ * @version 1.0.0
9
+ */
10
+
11
+ import { EventEmitter } from 'events';
12
+
13
+ /**
14
+ * Abstract base class for Yakmesh adapters
15
+ *
16
+ * Implement this to create integrations with:
17
+ * - phpBB forums (PeerQuanta)
18
+ * - WordPress/WooCommerce
19
+ * - Custom REST APIs
20
+ * - PostgreSQL databases
21
+ * - MongoDB collections
22
+ */
23
+ export class BaseAdapter extends EventEmitter {
24
+ constructor(YakmeshNode, config = {}) {
25
+ super();
26
+
27
+ if (new.target === BaseAdapter) {
28
+ throw new Error('BaseAdapter is abstract and cannot be instantiated directly');
29
+ }
30
+
31
+ this.node = YakmeshNode;
32
+ this.config = config;
33
+ this.syncInterval = null;
34
+ this.isInitialized = false;
35
+
36
+ // Statistics
37
+ this.stats = {
38
+ recordsProcessed: 0,
39
+ recordsValidated: 0,
40
+ recordsRejected: 0,
41
+ lastSyncTime: null,
42
+ errors: [],
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Initialize the adapter
48
+ * Must be implemented by subclasses
49
+ * @abstract
50
+ */
51
+ async init() {
52
+ throw new Error('init() must be implemented by subclass');
53
+ }
54
+
55
+ /**
56
+ * Get the schema definition for replicated tables
57
+ * Must be implemented by subclasses
58
+ * @abstract
59
+ * @returns {Object} Schema definition
60
+ */
61
+ getSchema() {
62
+ throw new Error('getSchema() must be implemented by subclass');
63
+ }
64
+
65
+ /**
66
+ * Fetch records that have changed since last sync
67
+ * Must be implemented by subclasses
68
+ * @abstract
69
+ * @param {Date} since - Timestamp of last sync
70
+ * @returns {Promise<Array>} Changed records
71
+ */
72
+ async fetchChanges(since) {
73
+ throw new Error('fetchChanges() must be implemented by subclass');
74
+ }
75
+
76
+ /**
77
+ * Apply a record change from the mesh to the local database
78
+ * Must be implemented by subclasses
79
+ * @abstract
80
+ * @param {string} table - Table name
81
+ * @param {Object} record - Record data
82
+ * @param {string} operation - 'INSERT', 'UPDATE', 'DELETE'
83
+ */
84
+ async applyChange(table, record, operation) {
85
+ throw new Error('applyChange() must be implemented by subclass');
86
+ }
87
+
88
+ /**
89
+ * Validate a record using custom rules
90
+ * Override to add platform-specific validation
91
+ * @param {string} type - Record type
92
+ * @param {Object} data - Record data
93
+ * @returns {Object} { valid: boolean, errors: string[] }
94
+ */
95
+ validate(type, data) {
96
+ return { valid: true, errors: [] };
97
+ }
98
+
99
+ /**
100
+ * Start periodic synchronization
101
+ * @param {number} intervalMs - Sync interval in milliseconds
102
+ */
103
+ startSync(intervalMs = 60000) {
104
+ if (this.syncInterval) {
105
+ this.stopSync();
106
+ }
107
+
108
+ console.log('Starting sync every ' + (intervalMs / 1000) + 's');
109
+ this.sync();
110
+
111
+ this.syncInterval = setInterval(() => {
112
+ this.sync();
113
+ }, intervalMs);
114
+ }
115
+
116
+ /**
117
+ * Stop periodic synchronization
118
+ */
119
+ stopSync() {
120
+ if (this.syncInterval) {
121
+ clearInterval(this.syncInterval);
122
+ this.syncInterval = null;
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Perform a sync cycle
128
+ */
129
+ async sync() {
130
+ try {
131
+ const changes = await this.fetchChanges(this.stats.lastSyncTime);
132
+
133
+ for (const change of changes) {
134
+ const validation = this.validate(change.type, change.data);
135
+
136
+ if (validation.valid) {
137
+ this.node.gossip.spreadRumor('adapter:' + change.type, {
138
+ table: change.table,
139
+ operation: change.operation,
140
+ data: change.data,
141
+ });
142
+ this.stats.recordsValidated++;
143
+ } else {
144
+ this.stats.recordsRejected++;
145
+ this.emit('validation-error', { change, errors: validation.errors });
146
+ }
147
+ this.stats.recordsProcessed++;
148
+ }
149
+
150
+ this.stats.lastSyncTime = new Date();
151
+ this.emit('sync-complete', { processed: changes.length });
152
+
153
+ } catch (error) {
154
+ this.stats.errors.push({ time: new Date(), error: error.message });
155
+ this.emit('sync-error', error);
156
+ }
157
+ }
158
+
159
+ getStats() {
160
+ return {
161
+ ...this.stats,
162
+ isRunning: this.syncInterval !== null,
163
+ adapterType: this.constructor.name,
164
+ };
165
+ }
166
+
167
+ async handleRumor(topic, data, origin) {
168
+ if (topic.startsWith('adapter:')) {
169
+ const { table, operation, data: recordData } = data;
170
+ await this.applyChange(table, recordData, operation);
171
+ }
172
+ }
173
+ }
174
+
175
+ export default BaseAdapter;
176
+
177
+
Binary file
Binary file
package/cli/index.js ADDED
@@ -0,0 +1,307 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Yakmesh CLI
5
+ * Command-line interface for managing Yakmesh nodes
6
+ */
7
+
8
+ import { Command } from 'commander';
9
+ import chalk from 'chalk';
10
+ import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
11
+ import { join, resolve } from 'path';
12
+ import { fileURLToPath } from 'url';
13
+
14
+ const __dirname = fileURLToPath(new URL('.', import.meta.url));
15
+ const VERSION = '0.1.0';
16
+
17
+ const program = new Command();
18
+
19
+ // Banner
20
+ function showBanner() {
21
+ console.log(chalk.cyan(`
22
+ 🦬 Yakmesh Network v${VERSION}
23
+ Post-Quantum Secure • Decentralized • Federated
24
+ `));
25
+ }
26
+
27
+ // ===== INIT COMMAND =====
28
+ program
29
+ .command('init')
30
+ .description('Initialize a new Yakmesh Node in the current directory')
31
+ .option('-n, --name <name>', 'Node name', 'My Yakmesh Node')
32
+ .option('-r, --region <region>', 'Geographic region', 'local')
33
+ .option('-p, --port <port>', 'HTTP port', '3000')
34
+ .option('-w, --ws-port <port>', 'WebSocket port', '9001')
35
+ .option('--bootstrap <urls>', 'Comma-separated bootstrap node URLs')
36
+ .action(async (options) => {
37
+ showBanner();
38
+ console.log(chalk.yellow('Initializing new Yakmesh Node...\n'));
39
+
40
+ const dataDir = resolve('./data');
41
+ const configPath = resolve('./yakmesh.config.js');
42
+
43
+ // Check if already initialized
44
+ if (existsSync(configPath)) {
45
+ console.log(chalk.red('✗ Error: yakmesh.config.js already exists'));
46
+ console.log(chalk.gray(' Use --force to reinitialize'));
47
+ process.exit(1);
48
+ }
49
+
50
+ // Create data directory
51
+ if (!existsSync(dataDir)) {
52
+ mkdirSync(dataDir, { recursive: true });
53
+ console.log(chalk.green('✓ Created data directory'));
54
+ }
55
+
56
+ // Parse bootstrap nodes
57
+ const bootstrapNodes = options.bootstrap
58
+ ? options.bootstrap.split(',').map(s => s.trim())
59
+ : ['wss://peerquanta.com:9001'];
60
+
61
+ // Generate config
62
+ const config = `/**
63
+ * Yakmesh Node Configuration
64
+ * Generated by: npx yakmesh init
65
+ */
66
+ export default {
67
+ // Node identity
68
+ node: {
69
+ name: '${options.name}',
70
+ region: '${options.region}',
71
+ capabilities: ['listings', 'chat', 'forum', 'qcoa'],
72
+ },
73
+
74
+ // Network settings
75
+ network: {
76
+ httpPort: ${options.port},
77
+ wsPort: ${options.wsPort},
78
+ publicHost: 'localhost',
79
+ },
80
+
81
+ // Bootstrap nodes (well-known entry points)
82
+ bootstrap: ${JSON.stringify(bootstrapNodes, null, 4).replace(/\n/g, '\n ')},
83
+
84
+ // Database
85
+ database: {
86
+ path: './data/peerquanta.db',
87
+ replication: {
88
+ enabled: true,
89
+ syncInterval: 30000, // 30 seconds
90
+ },
91
+ },
92
+
93
+ // Security
94
+ security: {
95
+ maxPeers: 50,
96
+ requireAuth: false,
97
+ },
98
+ };
99
+ `;
100
+
101
+ writeFileSync(configPath, config);
102
+ console.log(chalk.green('✓ Created yakmesh.config.js'));
103
+
104
+ console.log(chalk.cyan('\n📋 Node Configuration:'));
105
+ console.log(chalk.gray(` Name: ${options.name}`));
106
+ console.log(chalk.gray(` Region: ${options.region}`));
107
+ console.log(chalk.gray(` HTTP Port: ${options.port}`));
108
+ console.log(chalk.gray(` WS Port: ${options.wsPort}`));
109
+ console.log(chalk.gray(` Bootstrap: ${bootstrapNodes.length} node(s)`));
110
+
111
+ console.log(chalk.green('\n✓ Initialization complete!\n'));
112
+ console.log(chalk.white('Next steps:'));
113
+ console.log(chalk.gray(' 1. Edit yakmesh.config.js to customize settings'));
114
+ console.log(chalk.gray(' 2. Run: npx yakmesh start'));
115
+ console.log('');
116
+ });
117
+
118
+ // ===== START COMMAND =====
119
+ program
120
+ .command('start')
121
+ .description('Start the Yakmesh Node')
122
+ .option('-c, --config <path>', 'Path to config file', './yakmesh.config.js')
123
+ .option('-d, --daemon', 'Run as background daemon')
124
+ .action(async (options) => {
125
+ showBanner();
126
+
127
+ const configPath = resolve(options.config);
128
+
129
+ if (!existsSync(configPath)) {
130
+ console.log(chalk.red('✗ Error: yakmesh.config.js not found'));
131
+ console.log(chalk.gray(' Run: npx yakmesh init'));
132
+ process.exit(1);
133
+ }
134
+
135
+ console.log(chalk.yellow('Starting Yakmesh Node...\n'));
136
+
137
+ // Dynamic import of server - use the package's server module
138
+ const serverPath = join(__dirname, '..', 'server', 'index.js');
139
+ const serverURL = new URL(`file:///${serverPath.replace(/\\/g, '/')}`);
140
+ const { YakmeshNode } = await import(serverURL.href);
141
+
142
+ // Load config from current working directory
143
+ const configURL = new URL(`file:///${configPath.replace(/\\/g, '/')}`);
144
+ const { default: config } = await import(configURL.href);
145
+
146
+ const node = new YakmeshNode(config);
147
+
148
+ // Handle shutdown
149
+ process.on('SIGINT', async () => {
150
+ console.log(chalk.yellow('\n\nShutting down...'));
151
+ await node.stop();
152
+ process.exit(0);
153
+ });
154
+
155
+ process.on('SIGTERM', async () => {
156
+ await node.stop();
157
+ process.exit(0);
158
+ });
159
+
160
+ await node.start();
161
+ });
162
+
163
+ // ===== STATUS COMMAND =====
164
+ program
165
+ .command('status')
166
+ .description('Show node status')
167
+ .option('-p, --port <port>', 'HTTP port of local node', '3000')
168
+ .action(async (options) => {
169
+ try {
170
+ const response = await fetch(`http://localhost:${options.port}/health`);
171
+ const data = await response.json();
172
+
173
+ showBanner();
174
+ console.log(chalk.green('✓ Node is running\n'));
175
+ console.log(chalk.cyan('📊 Status:'));
176
+ console.log(chalk.gray(` Node ID: ${data.nodeId}`));
177
+ console.log(chalk.gray(` Peers: ${data.peers}`));
178
+ console.log(chalk.gray(` Algorithm: ${data.algorithm}`));
179
+ console.log('');
180
+ } catch (e) {
181
+ console.log(chalk.red('✗ Node is not running'));
182
+ console.log(chalk.gray(` Could not connect to http://localhost:${options.port}`));
183
+ process.exit(1);
184
+ }
185
+ });
186
+
187
+ // ===== PEERS COMMAND =====
188
+ program
189
+ .command('peers')
190
+ .description('List connected peers')
191
+ .option('-p, --port <port>', 'HTTP port of local node', '3000')
192
+ .action(async (options) => {
193
+ try {
194
+ const response = await fetch(`http://localhost:${options.port}/peers`);
195
+ const peers = await response.json();
196
+
197
+ showBanner();
198
+
199
+ if (peers.length === 0) {
200
+ console.log(chalk.yellow('No peers connected\n'));
201
+ return;
202
+ }
203
+
204
+ console.log(chalk.cyan(`📡 Connected Peers (${peers.length}):\n`));
205
+
206
+ for (const peer of peers) {
207
+ const ago = Math.floor((Date.now() - peer.lastSeen) / 1000);
208
+ console.log(chalk.white(` ${peer.name}`));
209
+ console.log(chalk.gray(` ID: ${peer.nodeId.slice(0, 24)}...`));
210
+ console.log(chalk.gray(` Endpoint: ${peer.endpoint || 'inbound'}`));
211
+ console.log(chalk.gray(` Last seen: ${ago}s ago`));
212
+ console.log('');
213
+ }
214
+ } catch (e) {
215
+ console.log(chalk.red('✗ Could not fetch peers'));
216
+ console.log(chalk.gray(` Is the node running on port ${options.port}?`));
217
+ process.exit(1);
218
+ }
219
+ });
220
+
221
+ // ===== INFO COMMAND =====
222
+ program
223
+ .command('info')
224
+ .description('Show detailed node information')
225
+ .option('-p, --port <port>', 'HTTP port of local node', '3000')
226
+ .action(async (options) => {
227
+ try {
228
+ const [nodeRes, replRes] = await Promise.all([
229
+ fetch(`http://localhost:${options.port}/node`),
230
+ fetch(`http://localhost:${options.port}/replication`),
231
+ ]);
232
+
233
+ const node = await nodeRes.json();
234
+ const repl = await replRes.json();
235
+
236
+ showBanner();
237
+ console.log(chalk.cyan('🦬 Node Information:\n'));
238
+
239
+ console.log(chalk.white(' Identity:'));
240
+ console.log(chalk.gray(` Node ID: ${node.nodeId}`));
241
+ console.log(chalk.gray(` Name: ${node.name}`));
242
+ console.log(chalk.gray(` Region: ${node.region}`));
243
+ console.log(chalk.gray(` Algorithm: ${node.algorithm} (NIST Level ${node.nistLevel})`));
244
+ console.log(chalk.gray(` Created: ${new Date(node.createdAt).toISOString()}`));
245
+
246
+ console.log(chalk.white('\n Capabilities:'));
247
+ for (const cap of node.capabilities) {
248
+ console.log(chalk.gray(` • ${cap}`));
249
+ }
250
+
251
+ console.log(chalk.white('\n Replication:'));
252
+ console.log(chalk.gray(` Log entries: ${repl.replicationLogSize}`));
253
+ console.log(chalk.gray(` Peer states: ${repl.peerStates.length}`));
254
+ console.log(chalk.gray(` Tables: ${repl.replicatedTables.join(', ')}`));
255
+
256
+ console.log(chalk.white('\n Public Key (ML-DSA-65):'));
257
+ console.log(chalk.gray(` ${node.publicKey.slice(0, 64)}...`));
258
+ console.log('');
259
+ } catch (e) {
260
+ console.log(chalk.red('✗ Could not fetch node info'));
261
+ process.exit(1);
262
+ }
263
+ });
264
+
265
+ // ===== JOIN COMMAND =====
266
+ program
267
+ .command('join <endpoint>')
268
+ .description('Connect to a peer node')
269
+ .option('-p, --port <port>', 'HTTP port of local node', '3000')
270
+ .action(async (endpoint, options) => {
271
+ try {
272
+ const response = await fetch(`http://localhost:${options.port}/connect`, {
273
+ method: 'POST',
274
+ headers: { 'Content-Type': 'application/json' },
275
+ body: JSON.stringify({ endpoint }),
276
+ });
277
+
278
+ const result = await response.json();
279
+
280
+ if (result.success) {
281
+ console.log(chalk.green(`✓ Connected to ${endpoint}`));
282
+ } else {
283
+ console.log(chalk.red(`✗ Failed to connect: ${result.error}`));
284
+ }
285
+ } catch (e) {
286
+ console.log(chalk.red('✗ Could not connect'));
287
+ console.log(chalk.gray(` ${e.message}`));
288
+ process.exit(1);
289
+ }
290
+ });
291
+
292
+ // ===== VERSION =====
293
+ program
294
+ .version(VERSION)
295
+ .description('Yakmesh Network - Post-Quantum Decentralized Node');
296
+
297
+ // Parse arguments
298
+ program.parse();
299
+
300
+ // Show help if no command
301
+ if (!process.argv.slice(2).length) {
302
+ showBanner();
303
+ program.outputHelp();
304
+ }
305
+
306
+
307
+