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
@@ -0,0 +1,179 @@
1
+ #include <iostream>
2
+ #include <vector>
3
+ #include <array>
4
+ #include <cstdint>
5
+ #include <numeric>
6
+ #include <iomanip>
7
+
8
+ // ============================================================================
9
+ // YAKMESH CORE: YPC-27 (27-Trit Polynomial Checksum)
10
+ // Ring: R = Z[x] / (x^27 - 1) mod 3
11
+ // Coefficients: Balanced Ternary {-1, 0, 1}
12
+ // ============================================================================
13
+
14
+ namespace yakmesh {
15
+
16
+ constexpr int N = 27;
17
+
18
+ // Balanced Ternary Trit: Can be -1, 0, or 1
19
+ using Trit = int8_t;
20
+
21
+ struct Poly27 {
22
+ std::array<Trit, N> coeffs;
23
+
24
+ Poly27() { coeffs.fill(0); }
25
+
26
+ // Print representation (e.g., + - 0 + ...)
27
+ void print() const {
28
+ std::cout << "[ ";
29
+ for (int i = 0; i < N; ++i) {
30
+ if (coeffs[i] == 1) std::cout << "+";
31
+ else if (coeffs[i] == -1) std::cout << "-";
32
+ else std::cout << "0";
33
+ }
34
+ std::cout << " ]" << std::endl;
35
+ }
36
+ };
37
+
38
+ // ------------------------------------------------------------------------
39
+ // MATH HELPERS (Mod 3)
40
+ // ------------------------------------------------------------------------
41
+
42
+ // Canonical reduction to balanced ternary {-1, 0, 1}
43
+ // (val % 3) -> {0, 1, 2} -> {-1, 0, 1}
44
+ constexpr Trit reduce3(int val) {
45
+ int r = val % 3;
46
+ if (r < 0) r += 3; // Handle C++ negative modulo behavior
47
+ // Map {0, 1, 2} => {0, 1, -1}
48
+ return (r == 2) ? -1 : static_cast<Trit>(r);
49
+ }
50
+
51
+ // Polynomial Addition: A + B mod 3
52
+ Poly27 add(const Poly27& a, const Poly27& b) {
53
+ Poly27 res;
54
+ for (int i = 0; i < N; ++i) {
55
+ res.coeffs[i] = reduce3(a.coeffs[i] + b.coeffs[i]);
56
+ }
57
+ return res;
58
+ }
59
+
60
+ // Polynomial Multiplication: A * B mod (x^27 - 1) mod 3
61
+ // Since N=27 is small, we use direct convolution O(N^2).
62
+ // For x^N - 1, index wraps simply: (i + j) % N
63
+ Poly27 multiply(const Poly27& a, const Poly27& b) {
64
+ Poly27 res;
65
+ for (int i = 0; i < N; ++i) {
66
+ for (int j = 0; j < N; ++j) {
67
+ int idx = (i + j) % N; // Cyclic convolution
68
+ int prod = a.coeffs[i] * b.coeffs[j];
69
+ // Accumulate without immediate reduction for speed (optional)
70
+ // But doing it step-wise keeps ints small.
71
+ int current = res.coeffs[idx] + prod;
72
+ res.coeffs[idx] = reduce3(current);
73
+ }
74
+ }
75
+ return res;
76
+ }
77
+
78
+ // ------------------------------------------------------------------------
79
+ // DATA CONVERSION
80
+ // ------------------------------------------------------------------------
81
+
82
+ // Convert raw Bytes to Trits (5 Trits per Byte)
83
+ // 3^5 = 243, so we can map 0-242 exactly.
84
+ // Values 243-255 are wrapped (mod 243) to avoid bias, or just simple mod 3 loop.
85
+ std::vector<Trit> bytesToTrits(const std::vector<uint8_t>& data) {
86
+ std::vector<Trit> trits;
87
+ trits.reserve(data.size() * 5);
88
+
89
+ for (uint8_t b : data) {
90
+ int val = static_cast<int>(b);
91
+ // Extract 5 trits (Little Endian)
92
+ for (int k = 0; k < 5; ++k) {
93
+ trits.push_back(reduce3(val % 3));
94
+ val /= 3;
95
+ }
96
+ }
97
+ return trits;
98
+ }
99
+
100
+ // ------------------------------------------------------------------------
101
+ // CHECKSUM ENGINE
102
+ // ------------------------------------------------------------------------
103
+
104
+ class YPC27Checksum {
105
+ Poly27 state;
106
+ Poly27 seed; // The "Challenge" or "Key" polynomial
107
+
108
+ public:
109
+ // Initialize with a "Seed" (e.g., derived from PeerID or Network Key)
110
+ YPC27Checksum(const Poly27& network_seed) : seed(network_seed) {
111
+ state.coeffs.fill(0);
112
+ }
113
+
114
+ // Rolling Update: State = (State + Input_Poly) * Seed
115
+ // This makes order significant and diffuses the bits across the lattice.
116
+ void update(const std::vector<uint8_t>& data) {
117
+ std::vector<Trit> raw_trits = bytesToTrits(data);
118
+
119
+ // Process in chunks of N (27) trits
120
+ size_t num_chunks = (raw_trits.size() + N - 1) / N;
121
+
122
+ for (size_t k = 0; k < num_chunks; ++k) {
123
+ Poly27 chunk_poly;
124
+ for (int i = 0; i < N; ++i) {
125
+ size_t src_idx = k * N + i;
126
+ if (src_idx < raw_trits.size()) {
127
+ chunk_poly.coeffs[i] = raw_trits[src_idx];
128
+ } else {
129
+ chunk_poly.coeffs[i] = 0; // Padding
130
+ }
131
+ }
132
+
133
+ // The Core "Lattice" Mix: S_new = (S_old + M) * G
134
+ Poly27 sum = add(state, chunk_poly);
135
+ state = multiply(sum, seed);
136
+ }
137
+ }
138
+
139
+ Poly27 digest() const {
140
+ return state;
141
+ }
142
+ };
143
+ }
144
+
145
+ // ----------------------------------------------------------------------------
146
+ // TEST HARNESS
147
+ // ----------------------------------------------------------------------------
148
+ int main() {
149
+ using namespace yakmesh;
150
+
151
+ // 1. Define a Network Seed (e.g., The "Yakmesh Gen 1" constant)
152
+ // In production, this would be hardcoded or derived from the PeerID.
153
+ Poly27 seed;
154
+ for(int i=0; i<N; ++i) seed.coeffs[i] = (i % 3 == 0) ? 1 : (i % 3 == 1) ? -1 : 0;
155
+
156
+ std::cout << "Yakmesh YPC-27 Initialization..." << std::endl;
157
+ std::cout << "Seed Poly: "; seed.print();
158
+
159
+ // 2. Create the Checksum Engine
160
+ YPC27Checksum hasher(seed);
161
+
162
+ // 3. Simulate a Packet (Hello World)
163
+ std::string msg = "Yakmesh_Packet_v1:Keep_It_Ternary";
164
+ std::vector<uint8_t> packet(msg.begin(), msg.end());
165
+
166
+ // 4. Update
167
+ hasher.update(packet);
168
+
169
+ // 5. Final Digest
170
+ Poly27 checksum = hasher.digest();
171
+
172
+ std::cout << "\nInput Data: \"" << msg << "\"" << std::endl;
173
+ std::cout << "YPC-27 Checksum: ";
174
+ checksum.print();
175
+
176
+ // Verification Logic:
177
+ // A receiver does the same. If (Checksum_Calc - Checksum_Header) != 0, drop packet.
178
+ return 0;
179
+ }
package/sbom.json ADDED
@@ -0,0 +1,87 @@
1
+ {
2
+ "bomFormat": "CycloneDX",
3
+ "specVersion": "1.4",
4
+ "version": 1,
5
+ "metadata": {
6
+ "timestamp": "2026-02-24T21:17:21.964Z",
7
+ "component": {
8
+ "type": "application",
9
+ "name": "yakmesh",
10
+ "version": "3.0.0"
11
+ }
12
+ },
13
+ "components": [
14
+ {
15
+ "type": "library",
16
+ "name": "@noble/hashes",
17
+ "version": "2.0.0",
18
+ "scope": "required"
19
+ },
20
+ {
21
+ "type": "library",
22
+ "name": "@noble/post-quantum",
23
+ "version": "0.5.4",
24
+ "scope": "required"
25
+ },
26
+ {
27
+ "type": "library",
28
+ "name": "chalk",
29
+ "version": "5.3.0",
30
+ "scope": "required"
31
+ },
32
+ {
33
+ "type": "library",
34
+ "name": "commander",
35
+ "version": "12.0.0",
36
+ "scope": "required"
37
+ },
38
+ {
39
+ "type": "library",
40
+ "name": "express",
41
+ "version": "4.18.2",
42
+ "scope": "required"
43
+ },
44
+ {
45
+ "type": "library",
46
+ "name": "express-rate-limit",
47
+ "version": "8.2.1",
48
+ "scope": "required"
49
+ },
50
+ {
51
+ "type": "library",
52
+ "name": "node-forge",
53
+ "version": "1.3.3",
54
+ "scope": "required"
55
+ },
56
+ {
57
+ "type": "library",
58
+ "name": "onnxruntime-node",
59
+ "version": "1.24.2",
60
+ "scope": "required"
61
+ },
62
+ {
63
+ "type": "library",
64
+ "name": "sql.js",
65
+ "version": "1.10.0",
66
+ "scope": "required"
67
+ },
68
+ {
69
+ "type": "library",
70
+ "name": "ws",
71
+ "version": "8.16.0",
72
+ "scope": "required"
73
+ },
74
+ {
75
+ "type": "library",
76
+ "name": "nodemon",
77
+ "version": "3.0.0",
78
+ "scope": "optional"
79
+ },
80
+ {
81
+ "type": "library",
82
+ "name": "vitest",
83
+ "version": "4.0.17",
84
+ "scope": "optional"
85
+ }
86
+ ]
87
+ }
@@ -0,0 +1,264 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Security Audit Script
4
+ *
5
+ * Runs dependency security checks and generates SBOM.
6
+ * Run before deployment or as part of CI/CD.
7
+ *
8
+ * Usage:
9
+ * node scripts/security-audit.mjs
10
+ * node scripts/security-audit.mjs --fix # Auto-fix where possible
11
+ * node scripts/security-audit.mjs --sbom # Generate SBOM only
12
+ * node scripts/security-audit.mjs --json # JSON output for CI
13
+ *
14
+ * @module scripts/security-audit
15
+ * @version 1.0.0
16
+ */
17
+
18
+ import { spawnSync } from 'child_process';
19
+ import { readFileSync, writeFileSync, existsSync } from 'fs';
20
+ import { join, dirname } from 'path';
21
+ import { fileURLToPath } from 'url';
22
+ import { createHash } from 'crypto';
23
+
24
+ const __filename = fileURLToPath(import.meta.url);
25
+ const __dirname = dirname(__filename);
26
+ const ROOT_DIR = join(__dirname, '..');
27
+
28
+ const args = process.argv.slice(2);
29
+ const FIX_MODE = args.includes('--fix');
30
+ const SBOM_ONLY = args.includes('--sbom');
31
+ const JSON_OUTPUT = args.includes('--json');
32
+
33
+ const results = {
34
+ timestamp: new Date().toISOString(),
35
+ audit: null,
36
+ lockfileIntegrity: null,
37
+ sbom: null,
38
+ recommendations: [],
39
+ };
40
+
41
+ /**
42
+ * Run npm audit
43
+ */
44
+ function runAudit() {
45
+ console.log('\n📦 Running npm audit...\n');
46
+
47
+ try {
48
+ const cmdArgs = FIX_MODE
49
+ ? ['audit', 'fix', '--audit-level=moderate']
50
+ : ['audit', '--json'];
51
+
52
+ const result = spawnSync('npm', cmdArgs, {
53
+ cwd: ROOT_DIR,
54
+ encoding: 'utf-8',
55
+ shell: true,
56
+ });
57
+
58
+ if (JSON_OUTPUT || !FIX_MODE) {
59
+ try {
60
+ const auditData = JSON.parse(result.stdout);
61
+ results.audit = {
62
+ vulnerabilities: auditData.metadata?.vulnerabilities || {},
63
+ totalDependencies: auditData.metadata?.dependencies?.total || 0,
64
+ advisories: Object.keys(auditData.advisories || {}).length,
65
+ };
66
+
67
+ const vulns = results.audit.vulnerabilities;
68
+ const total = (vulns.critical || 0) + (vulns.high || 0) + (vulns.moderate || 0) + (vulns.low || 0);
69
+
70
+ if (vulns.critical > 0) {
71
+ results.recommendations.push(`🔴 CRITICAL: ${vulns.critical} critical vulnerabilities found!`);
72
+ }
73
+ if (vulns.high > 0) {
74
+ results.recommendations.push(`🟠 HIGH: ${vulns.high} high severity vulnerabilities`);
75
+ }
76
+
77
+ console.log(` Total dependencies: ${results.audit.totalDependencies}`);
78
+ console.log(` Vulnerabilities: ${total} (${vulns.critical || 0} critical, ${vulns.high || 0} high)`);
79
+
80
+ return total === 0;
81
+ } catch (e) {
82
+ // npm audit returns non-zero on vulnerabilities, output may not be valid JSON
83
+ if (result.stderr) {
84
+ console.log(' Audit stderr:', result.stderr.slice(0, 200));
85
+ }
86
+ results.audit = { raw: result.stdout?.slice(0, 500) };
87
+ return false;
88
+ }
89
+ } else {
90
+ console.log(result.stdout);
91
+ return result.status === 0;
92
+ }
93
+ } catch (e) {
94
+ console.error(' Audit failed:', e.message);
95
+ results.audit = { error: e.message };
96
+ return false;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Verify package-lock.json integrity
102
+ */
103
+ function verifyLockfile() {
104
+ console.log('\n🔒 Verifying lockfile integrity...\n');
105
+
106
+ const lockPath = join(ROOT_DIR, 'package-lock.json');
107
+
108
+ if (!existsSync(lockPath)) {
109
+ console.log(' ⚠️ No package-lock.json found');
110
+ results.lockfileIntegrity = { exists: false };
111
+ results.recommendations.push('Generate package-lock.json with npm install');
112
+ return false;
113
+ }
114
+
115
+ try {
116
+ const lockContent = readFileSync(lockPath, 'utf-8');
117
+ const lockData = JSON.parse(lockContent);
118
+
119
+ // Calculate hash of lockfile
120
+ const hash = createHash('sha256').update(lockContent).digest('hex');
121
+
122
+ results.lockfileIntegrity = {
123
+ exists: true,
124
+ hash: hash.slice(0, 16),
125
+ lockfileVersion: lockData.lockfileVersion,
126
+ packageCount: Object.keys(lockData.packages || {}).length,
127
+ };
128
+
129
+ console.log(` Lockfile version: ${lockData.lockfileVersion}`);
130
+ console.log(` Packages locked: ${results.lockfileIntegrity.packageCount}`);
131
+ console.log(` Lockfile hash: ${hash.slice(0, 16)}...`);
132
+
133
+ // Verify with npm ci (dry run)
134
+ const verifyResult = spawnSync('npm', ['ci', '--dry-run'], {
135
+ cwd: ROOT_DIR,
136
+ encoding: 'utf-8',
137
+ shell: true,
138
+ });
139
+
140
+ if (verifyResult.status === 0) {
141
+ console.log(' ✓ Lockfile is valid and consistent');
142
+ return true;
143
+ } else {
144
+ console.log(' ⚠️ Lockfile may be out of sync with package.json');
145
+ results.recommendations.push('Run npm install to regenerate lockfile');
146
+ return false;
147
+ }
148
+ } catch (e) {
149
+ console.error(' Lockfile verification failed:', e.message);
150
+ results.lockfileIntegrity = { error: e.message };
151
+ return false;
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Generate Software Bill of Materials (SBOM)
157
+ */
158
+ function generateSBOM() {
159
+ console.log('\n📋 Generating SBOM...\n');
160
+
161
+ const packagePath = join(ROOT_DIR, 'package.json');
162
+ const lockPath = join(ROOT_DIR, 'package-lock.json');
163
+
164
+ try {
165
+ const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));
166
+ const lock = existsSync(lockPath) ? JSON.parse(readFileSync(lockPath, 'utf-8')) : null;
167
+
168
+ const sbom = {
169
+ bomFormat: 'CycloneDX',
170
+ specVersion: '1.4',
171
+ version: 1,
172
+ metadata: {
173
+ timestamp: new Date().toISOString(),
174
+ component: {
175
+ type: 'application',
176
+ name: pkg.name,
177
+ version: pkg.version,
178
+ },
179
+ },
180
+ components: [],
181
+ };
182
+
183
+ // Add direct dependencies
184
+ for (const [name, version] of Object.entries(pkg.dependencies || {})) {
185
+ sbom.components.push({
186
+ type: 'library',
187
+ name,
188
+ version: version.replace(/^[\^~]/, ''),
189
+ scope: 'required',
190
+ });
191
+ }
192
+
193
+ // Add dev dependencies
194
+ for (const [name, version] of Object.entries(pkg.devDependencies || {})) {
195
+ sbom.components.push({
196
+ type: 'library',
197
+ name,
198
+ version: version.replace(/^[\^~]/, ''),
199
+ scope: 'optional',
200
+ });
201
+ }
202
+
203
+ const sbomPath = join(ROOT_DIR, 'sbom.json');
204
+ writeFileSync(sbomPath, JSON.stringify(sbom, null, 2));
205
+
206
+ results.sbom = {
207
+ generated: true,
208
+ path: 'sbom.json',
209
+ componentCount: sbom.components.length,
210
+ };
211
+
212
+ console.log(` Generated sbom.json with ${sbom.components.length} components`);
213
+ console.log(` Direct deps: ${Object.keys(pkg.dependencies || {}).length}`);
214
+ console.log(` Dev deps: ${Object.keys(pkg.devDependencies || {}).length}`);
215
+
216
+ return true;
217
+ } catch (e) {
218
+ console.error(' SBOM generation failed:', e.message);
219
+ results.sbom = { error: e.message };
220
+ return false;
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Main
226
+ */
227
+ async function main() {
228
+ console.log('╔════════════════════════════════════════════════════════════╗');
229
+ console.log('║ YAKMESH SECURITY AUDIT ║');
230
+ console.log('╚════════════════════════════════════════════════════════════╝');
231
+
232
+ let allPassed = true;
233
+
234
+ if (SBOM_ONLY) {
235
+ generateSBOM();
236
+ } else {
237
+ allPassed = runAudit() && allPassed;
238
+ allPassed = verifyLockfile() && allPassed;
239
+ generateSBOM();
240
+ }
241
+
242
+ console.log('\n═══════════════════════════════════════════════════════════════');
243
+
244
+ if (results.recommendations.length > 0) {
245
+ console.log('\n📝 Recommendations:\n');
246
+ for (const rec of results.recommendations) {
247
+ console.log(` ${rec}`);
248
+ }
249
+ }
250
+
251
+ if (JSON_OUTPUT) {
252
+ console.log('\n📊 JSON Results:\n');
253
+ console.log(JSON.stringify(results, null, 2));
254
+ }
255
+
256
+ console.log('\n' + (allPassed ? '✅ Security audit passed' : '⚠️ Security issues detected'));
257
+
258
+ process.exit(allPassed ? 0 : 1);
259
+ }
260
+
261
+ main().catch(e => {
262
+ console.error('Audit failed:', e);
263
+ process.exit(1);
264
+ });
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * update-docs-sidebar.cjs - Update sidebar navigation in all doc pages
4
+ *
5
+ * Reads docs/nav-order.json and updates the <ul class="sidebar-nav"> section
6
+ * in all HTML files to match the canonical navigation order.
7
+ *
8
+ * Usage: node scripts/update-docs-sidebar.cjs [--dry-run] [--verbose]
9
+ *
10
+ * This ensures all pages have consistent sidebar navigation without manual updates.
11
+ */
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+
16
+ // Support both /docs and /website/docs
17
+ const SCRIPTS_DIR = __dirname;
18
+ const ROOT_DIR = path.join(SCRIPTS_DIR, '..');
19
+ const NAV_ORDER_FILE = path.join(ROOT_DIR, 'docs', 'nav-order.json');
20
+
21
+ // Target directories to scan
22
+ const DOCS_DIRS = [
23
+ path.join(ROOT_DIR, 'docs'),
24
+ path.join(ROOT_DIR, 'website', 'docs'),
25
+ path.join(ROOT_DIR, 'website', 'docs', 'tutorials')
26
+ ];
27
+
28
+ // Parse args
29
+ const args = process.argv.slice(2);
30
+ const DRY_RUN = args.includes('--dry-run');
31
+ const VERBOSE = args.includes('--verbose');
32
+
33
+ function log(...msg) {
34
+ if (VERBOSE) console.log(...msg);
35
+ }
36
+
37
+ function loadNavOrder() {
38
+ const content = fs.readFileSync(NAV_ORDER_FILE, 'utf8');
39
+ return JSON.parse(content).pages;
40
+ }
41
+
42
+ /**
43
+ * Generate sidebar nav list items from nav-order.json
44
+ * @param {string} currentFile - The current file name (for "active" class)
45
+ * @param {string} prefix - Path prefix (e.g., "../" for subdirectory pages)
46
+ */
47
+ function generateSidebarNavItems(currentFile, prefix = '') {
48
+ const pages = loadNavOrder();
49
+
50
+ const items = pages.map(page => {
51
+ const isActive = page.file === currentFile;
52
+ const activeClass = isActive ? ' class="active"' : '';
53
+ const href = prefix + page.file;
54
+
55
+ // Icon handling - some use classes like yak-icon
56
+ let iconHtml;
57
+ if (page.title === 'YAK://') {
58
+ iconHtml = '<span class="yak-icon"></span>';
59
+ } else {
60
+ iconHtml = `<span>${page.icon}</span>`;
61
+ }
62
+
63
+ return ` <li><a href="${href}"${activeClass}>${iconHtml} <span>${page.title}</span></a></li>`;
64
+ });
65
+
66
+ return items.join('\n');
67
+ }
68
+
69
+ /**
70
+ * Update sidebar in a single file
71
+ */
72
+ function updateFileSidebar(filePath) {
73
+ let content = fs.readFileSync(filePath, 'utf8');
74
+ const fileName = path.basename(filePath);
75
+
76
+ // Determine prefix for subdirectory pages (tutorials/)
77
+ const inSubdir = filePath.includes(path.sep + 'tutorials' + path.sep);
78
+ const prefix = inSubdir ? '../' : '';
79
+
80
+ // Match the sidebar-nav ul section
81
+ const sidebarPattern = /<ul class="sidebar-nav">\s*(?:<li>.*?<\/li>\s*)+<\/ul>/s;
82
+
83
+ if (!sidebarPattern.test(content)) {
84
+ log(' No sidebar-nav found in', fileName);
85
+ return false;
86
+ }
87
+
88
+ const newNavItems = generateSidebarNavItems(fileName, prefix);
89
+ const newSidebar = `<ul class="sidebar-nav">\n${newNavItems}\n </ul>`;
90
+
91
+ const newContent = content.replace(sidebarPattern, newSidebar);
92
+
93
+ if (newContent === content) {
94
+ log(' No changes needed in', fileName);
95
+ return false;
96
+ }
97
+
98
+ if (!DRY_RUN) {
99
+ fs.writeFileSync(filePath, newContent, 'utf8');
100
+ }
101
+
102
+ return true;
103
+ }
104
+
105
+ /**
106
+ * Get all HTML files in a directory
107
+ */
108
+ function getHtmlFiles(dir) {
109
+ if (!fs.existsSync(dir)) return [];
110
+
111
+ return fs.readdirSync(dir)
112
+ .filter(f => f.endsWith('.html'))
113
+ .map(f => path.join(dir, f));
114
+ }
115
+
116
+ /**
117
+ * Main update function
118
+ */
119
+ function updateAllSidebars() {
120
+ console.log('🧭 Updating documentation sidebars...');
121
+ if (DRY_RUN) console.log(' (DRY RUN - no files will be modified)');
122
+ console.log('');
123
+
124
+ const pages = loadNavOrder();
125
+ console.log(`Loaded ${pages.length} pages from nav-order.json`);
126
+ console.log('');
127
+
128
+ let updated = 0;
129
+ let skipped = 0;
130
+
131
+ // Collect all HTML files from all directories
132
+ const allFiles = [];
133
+ for (const dir of DOCS_DIRS) {
134
+ allFiles.push(...getHtmlFiles(dir));
135
+ }
136
+
137
+ console.log(`Found ${allFiles.length} HTML files to process`);
138
+ console.log('');
139
+
140
+ for (const filePath of allFiles) {
141
+ const relativePath = path.relative(ROOT_DIR, filePath);
142
+
143
+ if (updateFileSidebar(filePath)) {
144
+ console.log('✅', relativePath);
145
+ updated++;
146
+ } else {
147
+ log('⏭️ ', relativePath);
148
+ skipped++;
149
+ }
150
+ }
151
+
152
+ console.log('');
153
+ console.log('Summary:');
154
+ console.log(' Updated:', updated);
155
+ console.log(' Skipped:', skipped);
156
+
157
+ if (DRY_RUN) {
158
+ console.log('');
159
+ console.log('Run without --dry-run to apply changes.');
160
+ }
161
+ }
162
+
163
+ // Run
164
+ updateAllSidebars();