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
@@ -323,7 +323,7 @@
323
323
  </div>
324
324
 
325
325
  <div class="connection-bar">
326
- <input type="text" id="node-url" value="http://localhost:3000" placeholder="Node HTTP URL">
326
+ <input type="text" id="node-url" placeholder="Node HTTP URL">
327
327
  <button onclick="connect()">Connect</button>
328
328
  <div class="status-indicator">
329
329
  <div class="status-dot" id="status-dot"></div>
@@ -518,10 +518,18 @@
518
518
  </div>
519
519
 
520
520
  <script>
521
- let nodeUrl = 'http://localhost:3000';
521
+ // Default to current origin (where dashboard was loaded from)
522
+ let nodeUrl = window.location.origin;
522
523
  let connected = false;
523
524
  let refreshInterval = null;
524
525
 
526
+ // Initialize input field with current origin on load
527
+ document.addEventListener('DOMContentLoaded', () => {
528
+ document.getElementById('node-url').value = nodeUrl;
529
+ // Auto-connect since we're served by the node
530
+ connect();
531
+ });
532
+
525
533
  // Helper function to format bytes
526
534
  function formatBytes(bytes) {
527
535
  if (bytes === 0) return '0 B';
@@ -617,6 +625,13 @@
617
625
  <div style="margin-top: 0.5rem;">
618
626
  Classical: ${crypto.classicalSecurity} | Quantum: ${crypto.quantumSecurity}
619
627
  </div>
628
+ ${crypto.routingSecurity ? `
629
+ <div style="margin-top: 0.5rem; padding-top: 0.5rem; border-top: 1px solid var(--border);">
630
+ <span style="color: var(--frost)">144T Routing:</span>
631
+ <span style="color: var(--mountain); font-weight: 600;">${crypto.routingSecurity}</span>
632
+ <div style="font-size: 0.75rem; color: var(--text-dim); margin-top: 0.25rem;">3^144 ≈ 10^68 address space • Grover-resistant</div>
633
+ </div>
634
+ ` : ''}
620
635
  <div style="margin-top: 0.5rem; font-size: 0.75rem;">
621
636
  ${crypto.nistStandards?.join(' • ') || ''}
622
637
  </div>
@@ -715,8 +730,9 @@
715
730
  <div style="width: 12px; height: 12px; border-radius: 50%; background: ${statusColor}; box-shadow: 0 0 8px ${statusColor};"></div>
716
731
  <span style="font-weight: 600; color: ${statusColor}">${website.status?.toUpperCase() || 'INACTIVE'}</span>
717
732
  </div>
718
- <div>Hosted Websites: <span style="color: var(--accent)">${website.websites || 0}</span></div>
733
+ <div>Published Manifests: <span style="color: var(--accent)">${website.websites || 0}</span></div>
719
734
  <div>.yak Domains: <span style="color: var(--frost)">${website.domains || 0}</span></div>
735
+ <div>Unique Sites: <span style="color: var(--text)">${website.uniqueSites || website.domains || 0}</span></div>
720
736
  <div>Files Served: <span style="color: var(--text)">${website.filesServed || 0}</span></div>
721
737
  <div>Bytes Served: <span style="color: var(--text)">${formatBytes(website.bytesServed || 0)}</span></div>
722
738
  ${website.status === 'active' ? `
@@ -44,6 +44,7 @@ export class ReplicationEngine {
44
44
  this.dbPath = dbPath;
45
45
  this.db = null;
46
46
  this.nodeId = mesh.identity.identity.nodeId;
47
+ this.identity = mesh.identity; // For ML-DSA-65 signing/verification
47
48
  this.syncInterval = null;
48
49
  }
49
50
 
@@ -98,6 +99,13 @@ export class ReplicationEngine {
98
99
  // Index already exists
99
100
  }
100
101
 
102
+ // Add signature column for ML-DSA-65 authenticated replication
103
+ try {
104
+ this.db.run(`ALTER TABLE _replication_log ADD COLUMN signature TEXT`);
105
+ } catch (e) {
106
+ // Column already exists
107
+ }
108
+
101
109
  this._saveDb();
102
110
  log.info('Database initialized', { path: this.dbPath });
103
111
 
@@ -143,12 +151,20 @@ export class ReplicationEngine {
143
151
  if (!REPLICATED_TABLES.includes(tableName)) return;
144
152
 
145
153
  const vectorClock = this._generateVectorClock();
154
+ const dataJson = JSON.stringify(data);
155
+
156
+ // Sign the change payload (ML-DSA-65) for authenticated replication
157
+ const sigPayload = JSON.stringify({
158
+ tableName, rowId: String(rowId), operation, data: dataJson,
159
+ nodeId: this.nodeId, vectorClock,
160
+ });
161
+ const signature = this.identity.sign(sigPayload);
146
162
 
147
163
  this.db.run(
148
164
  `INSERT INTO _replication_log
149
- (table_name, row_id, operation, data, node_id, vector_clock, created_at)
150
- VALUES (?, ?, ?, ?, ?, ?, ?)`,
151
- [tableName, String(rowId), operation, JSON.stringify(data), this.nodeId, vectorClock, Date.now()]
165
+ (table_name, row_id, operation, data, node_id, vector_clock, created_at, signature)
166
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
167
+ [tableName, String(rowId), operation, dataJson, this.nodeId, vectorClock, Date.now(), signature]
152
168
  );
153
169
 
154
170
  this._saveDb();
@@ -169,14 +185,20 @@ export class ReplicationEngine {
169
185
  * Sync with a specific peer
170
186
  */
171
187
  async syncWithPeer(peerNodeId) {
172
- // Get last sync state for this peer
173
- const result = this.db.exec(
174
- `SELECT last_sync_at FROM _replication_state WHERE peer_node_id = '${peerNodeId}'`
175
- );
176
-
177
- const lastSyncAt = result.length > 0 && result[0].values.length > 0
178
- ? result[0].values[0][0]
179
- : 0;
188
+ // Get last sync state for this peer (parameterized to prevent SQL injection)
189
+ let lastSyncAt = 0;
190
+ try {
191
+ const stmt = this.db.prepare(
192
+ 'SELECT last_sync_at FROM _replication_state WHERE peer_node_id = ?'
193
+ );
194
+ stmt.bind([peerNodeId]);
195
+ if (stmt.step()) {
196
+ lastSyncAt = stmt.get()[0] || 0;
197
+ }
198
+ stmt.free();
199
+ } catch (e) {
200
+ log.warn('Failed to query sync state', { peer: peerNodeId.slice(0, 12), error: e.message });
201
+ }
180
202
 
181
203
  // Request changes from peer since last sync
182
204
  try {
@@ -194,15 +216,41 @@ export class ReplicationEngine {
194
216
  * Apply a replicated change from another node
195
217
  */
196
218
  applyChange(change) {
197
- const { table_name, row_id, operation, data, node_id, vector_clock, created_at } = change;
219
+ const { table_name, row_id, operation, data, node_id, vector_clock, created_at, signature } = change;
198
220
 
199
- // Check if we already have this change
200
- const existing = this.db.exec(
201
- `SELECT id FROM _replication_log
202
- WHERE table_name = '${table_name}' AND row_id = '${row_id}' AND vector_clock = '${vector_clock}'`
203
- );
221
+ // Verify ML-DSA-65 signature before trusting remote change
222
+ if (!signature) {
223
+ log.warn('Rejecting unsigned replication change', { nodeId: node_id?.slice(0, 12), table: table_name });
224
+ return false;
225
+ }
226
+ const peerPubKey = this._getPeerPublicKey(node_id);
227
+ if (!peerPubKey) {
228
+ log.warn('Rejecting replication change from unknown node (no public key)', { nodeId: node_id?.slice(0, 12) });
229
+ return false;
230
+ }
231
+ const sigPayload = JSON.stringify({
232
+ tableName: table_name, rowId: row_id, operation, data,
233
+ nodeId: node_id, vectorClock: vector_clock,
234
+ });
235
+ if (!this.identity.verify(sigPayload, signature, peerPubKey)) {
236
+ log.warn('Rejecting replication change with invalid signature', { nodeId: node_id?.slice(0, 12), table: table_name });
237
+ return false;
238
+ }
239
+
240
+ // Check if we already have this change (parameterized)
241
+ let alreadyExists = false;
242
+ try {
243
+ const stmt = this.db.prepare(
244
+ 'SELECT id FROM _replication_log WHERE table_name = ? AND row_id = ? AND vector_clock = ?'
245
+ );
246
+ stmt.bind([table_name, row_id, vector_clock]);
247
+ alreadyExists = stmt.step();
248
+ stmt.free();
249
+ } catch (e) {
250
+ log.warn('Failed to check existing change', { error: e.message });
251
+ }
204
252
 
205
- if (existing.length > 0 && existing[0].values.length > 0) {
253
+ if (alreadyExists) {
206
254
  return false; // Already applied
207
255
  }
208
256
 
@@ -223,26 +271,31 @@ export class ReplicationEngine {
223
271
  * Get changes since a timestamp
224
272
  */
225
273
  getChangesSince(since, tables = REPLICATED_TABLES) {
226
- const tableList = tables.map(t => `'${t}'`).join(',');
274
+ const placeholders = tables.map(() => '?').join(',');
227
275
 
228
- const result = this.db.exec(
229
- `SELECT * FROM _replication_log
230
- WHERE created_at > ${since} AND table_name IN (${tableList})
231
- ORDER BY created_at ASC
232
- LIMIT 1000`
233
- );
234
-
235
- if (result.length === 0) return [];
236
-
237
- // Convert to objects
238
- const columns = result[0].columns;
239
- return result[0].values.map(row => {
240
- const obj = {};
241
- columns.forEach((col, i) => {
242
- obj[col] = row[i];
243
- });
244
- return obj;
245
- });
276
+ try {
277
+ const stmt = this.db.prepare(
278
+ `SELECT * FROM _replication_log
279
+ WHERE created_at > ? AND table_name IN (${placeholders})
280
+ ORDER BY created_at ASC
281
+ LIMIT 1000`
282
+ );
283
+ stmt.bind([since, ...tables]);
284
+
285
+ const columns = stmt.getColumnNames();
286
+ const results = [];
287
+ while (stmt.step()) {
288
+ const row = stmt.get();
289
+ const obj = {};
290
+ columns.forEach((col, i) => { obj[col] = row[i]; });
291
+ results.push(obj);
292
+ }
293
+ stmt.free();
294
+ return results;
295
+ } catch (e) {
296
+ log.warn('Failed to get changes', { error: e.message });
297
+ return [];
298
+ }
246
299
  }
247
300
 
248
301
  /**
@@ -264,6 +317,33 @@ export class ReplicationEngine {
264
317
 
265
318
  // ===== Private Methods =====
266
319
 
320
+ /**
321
+ * Resolve a peer's public key from mesh state.
322
+ * Checks WS peers, relay keys, SHERPA registry, and self.
323
+ */
324
+ _getPeerPublicKey(nodeId) {
325
+ // Self
326
+ if (nodeId === this.nodeId) {
327
+ return this.identity.identity.publicKey;
328
+ }
329
+ // WS peer info
330
+ if (this.mesh?.peers) {
331
+ const peer = this.mesh.peers.get(nodeId);
332
+ if (peer?.identity?.publicKey) return peer.identity.publicKey;
333
+ }
334
+ // Relay peer keys (stored during signed registration)
335
+ if (this.mesh?._relayPeerKeys) {
336
+ const key = this.mesh._relayPeerKeys.get(nodeId);
337
+ if (key) return key;
338
+ }
339
+ // SHERPA registry
340
+ if (this.mesh?.sherpa?.registry) {
341
+ const regPeer = this.mesh.sherpa.registry.get(nodeId);
342
+ if (regPeer?.publicKey) return regPeer.publicKey;
343
+ }
344
+ return null;
345
+ }
346
+
267
347
  _generateVectorClock() {
268
348
  const timestamp = Date.now();
269
349
  const random = Math.random().toString(36).slice(2, 8);
@@ -0,0 +1,204 @@
1
+ # Cryptographic Agility in Yakmesh
2
+
3
+ This document formalizes Yakmesh's approach to cryptographic agility—the ability to transition between cryptographic algorithms as standards evolve and new threats emerge.
4
+
5
+ ## Current Cryptographic Stack
6
+
7
+ | Purpose | Algorithm | Standard | Security Level |
8
+ |---------|-----------|----------|----------------|
9
+ | **Digital Signatures** | ML-DSA-65/87 | FIPS 204 | NIST Level 3/5 |
10
+ | **Key Encapsulation** | ML-KEM-768/1024 | FIPS 203 | NIST Level 3/5 |
11
+ | **Symmetric Encryption** | AES-256-GCM | FIPS 197 | 256-bit |
12
+ | **Hash Functions** | SHA3-256 | FIPS 202 | 256-bit |
13
+ | **Key Derivation** | HKDF-SHA3-256 | RFC 5869 | 256-bit |
14
+
15
+ ## Security Level Selection
16
+
17
+ Yakmesh supports two NIST security levels:
18
+
19
+ ### Level 3 (Default)
20
+ - **Signature**: ML-DSA-65 (Dilithium3)
21
+ - **KEM**: ML-KEM-768 (Kyber768)
22
+ - **Classical Security**: ~192 bits
23
+ - **Quantum Security**: ~128 bits
24
+ - **Use Case**: Standard operations, good performance
25
+
26
+ ### Level 5 (Paranoid Mode)
27
+ - **Signature**: ML-DSA-87 (Dilithium5)
28
+ - **KEM**: ML-KEM-1024 (Kyber1024)
29
+ - **Classical Security**: ~256 bits
30
+ - **Quantum Security**: ~192 bits
31
+ - **Use Case**: High-security environments, long-term secrets
32
+
33
+ ## Configuration
34
+
35
+ Set security level in `yakmesh.config.js`:
36
+
37
+ ```javascript
38
+ export default {
39
+ security: {
40
+ level: 5, // 3 = default, 5 = paranoid
41
+ },
42
+ // ... other config
43
+ };
44
+ ```
45
+
46
+ Or programmatically:
47
+
48
+ ```javascript
49
+ import { setSecurityLevel, SecurityLevel } from 'yakmesh/security/crypto-config';
50
+ setSecurityLevel(SecurityLevel.LEVEL_5);
51
+ ```
52
+
53
+ ## Algorithm Upgrade Path
54
+
55
+ ### When to Upgrade
56
+
57
+ 1. **NIST Recommendations Change**: If NIST deprecates an algorithm
58
+ 2. **New Attacks Published**: If cryptanalysis weakens security margins
59
+ 3. **Performance Improvements**: When newer algorithms offer better performance
60
+ 4. **Standard Updates**: When FIPS standards are revised
61
+
62
+ ### Upgrade Procedure
63
+
64
+ 1. **Announce Deprecation** (T-90 days)
65
+ - Publish security advisory
66
+ - Update documentation
67
+ - Begin dual-algorithm support period
68
+
69
+ 2. **Dual Support Period** (90 days)
70
+ - Accept both old and new algorithms
71
+ - Log deprecation warnings for old algorithm usage
72
+ - Allow nodes to upgrade at their own pace
73
+
74
+ 3. **Cutover** (T+0)
75
+ - Stop accepting old algorithms for new connections
76
+ - Existing sessions continue until natural expiry
77
+ - All new handshakes require new algorithm
78
+
79
+ 4. **Cleanup** (T+30)
80
+ - Remove old algorithm code
81
+ - Update minimum version requirements
82
+
83
+ ### Version Negotiation
84
+
85
+ During handshake, nodes exchange supported algorithms:
86
+
87
+ ```json
88
+ {
89
+ "supportedAlgorithms": {
90
+ "signature": ["ML-DSA-87", "ML-DSA-65"],
91
+ "kem": ["ML-KEM-1024", "ML-KEM-768"]
92
+ },
93
+ "preferredLevel": 5
94
+ }
95
+ ```
96
+
97
+ Nodes select the highest mutually-supported level.
98
+
99
+ ## Future Algorithm Candidates
100
+
101
+ ### Monitoring List
102
+
103
+ | Algorithm | Type | Status | Notes |
104
+ |-----------|------|--------|-------|
105
+ | **X-Wing** | Hybrid KEM | Draft | ML-KEM + X25519 hybrid |
106
+ | **SLH-DSA** | Signature | ✅ **Implemented** | Hash-based backup signatures (v1.7.0) |
107
+ | **HQC** | KEM | Round 4 | Code-based alternative to ML-KEM |
108
+ | **BIKE** | KEM | Round 4 | Code-based alternative |
109
+
110
+ > **Note (v1.7.0):** SLH-DSA is now implemented as backup signatures! Use `signDual()` and `verifyDual()` for defense-in-depth with both lattice-based (ML-DSA) and hash-based (SLH-DSA) algorithms.
111
+
112
+ ### Hybrid Approach (Future)
113
+
114
+ When NIST finalizes hybrid standards, Yakmesh will support:
115
+
116
+ ```
117
+ SharedSecret = KDF(ML-KEM-SharedSecret || X25519-SharedSecret)
118
+ ```
119
+
120
+ This provides defense-in-depth: both PQ and classical algorithms must be broken.
121
+
122
+ ## Hash Function Strategy
123
+
124
+ ### Current: SHA3-256 Everywhere
125
+
126
+ Yakmesh uses SHA3-256 (Keccak) for all hashing:
127
+ - Content addressing
128
+ - Oracle validation
129
+ - Key derivation context
130
+ - Bloom filter hashing
131
+
132
+ ### Rationale
133
+
134
+ 1. **SHA3 is Grover-resistant**: 256-bit hash provides 128-bit quantum security
135
+ 2. **Different construction**: SHA3 uses sponge construction vs SHA2's Merkle-Damgård
136
+ 3. **No length-extension**: SHA3 is immune to length-extension attacks
137
+ 4. **Future-proof**: Native 256-bit output without truncation
138
+
139
+ ## Backward Compatibility
140
+
141
+ ### Node Identity Continuity
142
+
143
+ When upgrading algorithms:
144
+ - Node IDs remain stable (derived from codebase hash)
145
+ - Public keys are regenerated with new algorithm
146
+ - Key rotation is transparent to peers
147
+
148
+ ### Message Format
149
+
150
+ Crypto parameters are included in message headers:
151
+
152
+ ```json
153
+ {
154
+ "cryptoVersion": "1.6.0",
155
+ "signatureAlgo": "ML-DSA-65",
156
+ "kemAlgo": "ML-KEM-768",
157
+ "hashAlgo": "SHA3-256"
158
+ }
159
+ ```
160
+
161
+ Receivers validate algorithm support before processing.
162
+
163
+ ## Security Considerations
164
+
165
+ ### Key Storage
166
+
167
+ - Private keys are stored locally in `data/node-key.json`
168
+ - Keys are never transmitted over the network
169
+ - Consider HSM integration for enterprise deployments
170
+
171
+ ### Algorithm Downgrades
172
+
173
+ - Yakmesh REJECTS algorithm downgrade attempts
174
+ - If peer offers only deprecated algorithms, connection fails
175
+ - Log all downgrade attempts for security monitoring
176
+
177
+ ### Side-Channel Resistance
178
+
179
+ The `@noble/post-quantum` library includes:
180
+ - Constant-time implementations
181
+ - Memory-hard operations where applicable
182
+ - No branching on secret data
183
+
184
+ ## Audit Trail
185
+
186
+ All cryptographic changes are logged:
187
+
188
+ | Version | Date | Change | Rationale |
189
+ |---------|------|--------|-----------|
190
+ | 1.0.0 | 2025-12 | Initial ML-DSA-65/ML-KEM-768 | FIPS 203/204 released |
191
+ | 1.4.0 | 2026-01 | Added ANNEX (ML-KEM-768) | P2P encryption |
192
+ | 1.6.0 | 2026-01 | Added Level 5 option | Paranoid mode |
193
+
194
+ ## References
195
+
196
+ - [NIST FIPS 203](https://csrc.nist.gov/publications/detail/fips/203/final) - ML-KEM
197
+ - [NIST FIPS 204](https://csrc.nist.gov/publications/detail/fips/204/final) - ML-DSA
198
+ - [NIST FIPS 205](https://csrc.nist.gov/publications/detail/fips/205/final) - SLH-DSA
199
+ - [@noble/post-quantum](https://github.com/paulmillr/noble-post-quantum) - Implementation
200
+
201
+ ---
202
+
203
+ *Last Updated: 2026-01-17*
204
+ *Document Version: 1.0*