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
|
@@ -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
|
+
});
|