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.
Files changed (232) hide show
  1. package/CHANGELOG.md +637 -0
  2. package/CONTRIBUTING.md +42 -0
  3. package/Caddyfile +77 -0
  4. package/README.md +119 -29
  5. package/adapters/adapter-mlv-bible/README.md +124 -0
  6. package/adapters/adapter-mlv-bible/index.js +400 -0
  7. package/adapters/chat-mod-adapter.js +532 -0
  8. package/adapters/content-adapter.js +273 -0
  9. package/content/api.js +50 -41
  10. package/content/index.js +2 -2
  11. package/content/store.js +355 -173
  12. package/dashboard/index.html +19 -3
  13. package/database/replication.js +117 -37
  14. package/docs/CRYPTO-AGILITY.md +204 -0
  15. package/docs/MTLS-RESEARCH.md +367 -0
  16. package/docs/NAMCHE-SPEC.md +681 -0
  17. package/docs/PEERQUANTA-YAKMESH-INTEGRATION.md +407 -0
  18. package/docs/PRECISION-DISCLOSURE.md +96 -0
  19. package/docs/README.md +76 -0
  20. package/docs/ROADMAP-2.4.0.md +447 -0
  21. package/docs/ROADMAP-2.5.0.md +244 -0
  22. package/docs/SECURITY-AUDIT-REPORT.md +306 -0
  23. package/docs/SST-INTEGRATION.md +712 -0
  24. package/docs/STEADYWATCH-IMPLEMENTATION.md +303 -0
  25. package/docs/TERNARY-AUDIT-REPORT.md +247 -0
  26. package/docs/TME-FAQ.md +221 -0
  27. package/docs/WHITEPAPER.md +623 -0
  28. package/docs/adapters.html +1001 -0
  29. package/docs/advanced-systems.html +1045 -0
  30. package/docs/annex.html +1046 -0
  31. package/docs/api.html +970 -0
  32. package/docs/business/response-templates.md +160 -0
  33. package/docs/c2c.html +1225 -0
  34. package/docs/cli.html +1332 -0
  35. package/docs/configuration.html +1248 -0
  36. package/docs/darshan.html +1085 -0
  37. package/docs/dharma.html +966 -0
  38. package/docs/docs-bundle.html +1075 -0
  39. package/docs/docs.css +3120 -0
  40. package/docs/docs.js +556 -0
  41. package/docs/doko.html +969 -0
  42. package/docs/geo-proof.html +858 -0
  43. package/docs/getting-started.html +840 -0
  44. package/docs/gumba-tutorial.html +1144 -0
  45. package/docs/gumba.html +1098 -0
  46. package/docs/index.html +914 -0
  47. package/docs/jhilke.html +1312 -0
  48. package/docs/karma.html +1100 -0
  49. package/docs/katha.html +1037 -0
  50. package/docs/lama.html +978 -0
  51. package/docs/mandala.html +1067 -0
  52. package/docs/mani.html +964 -0
  53. package/docs/mantra.html +967 -0
  54. package/docs/mesh.html +1409 -0
  55. package/docs/nakpak.html +869 -0
  56. package/docs/namche.html +928 -0
  57. package/docs/nav-order.json +53 -0
  58. package/docs/prahari.html +1043 -0
  59. package/docs/prism-bash.min.js +1 -0
  60. package/docs/prism-javascript.min.js +1 -0
  61. package/docs/prism-json.min.js +1 -0
  62. package/docs/prism-tomorrow.min.css +1 -0
  63. package/docs/prism.min.js +1 -0
  64. package/docs/privacy.html +699 -0
  65. package/docs/quick-reference.html +1181 -0
  66. package/docs/sakshi.html +1402 -0
  67. package/docs/sandboxing.md +386 -0
  68. package/docs/seva.html +911 -0
  69. package/docs/sherpa.html +871 -0
  70. package/docs/studio.html +860 -0
  71. package/docs/stupa.html +995 -0
  72. package/docs/tailwind.min.css +2 -0
  73. package/docs/tattva.html +1332 -0
  74. package/docs/terms.html +686 -0
  75. package/docs/time-server-deployment.md +166 -0
  76. package/docs/time-sources.html +1392 -0
  77. package/docs/tivra.html +1127 -0
  78. package/docs/trademark-policy.html +686 -0
  79. package/docs/tribhuj.html +1183 -0
  80. package/docs/trust-security.html +1029 -0
  81. package/docs/tutorials/backup-recovery.html +654 -0
  82. package/docs/tutorials/dashboard.html +604 -0
  83. package/docs/tutorials/domain-setup.html +605 -0
  84. package/docs/tutorials/host-website.html +456 -0
  85. package/docs/tutorials/mesh-network.html +505 -0
  86. package/docs/tutorials/mobile-access.html +445 -0
  87. package/docs/tutorials/privacy.html +467 -0
  88. package/docs/tutorials/raspberry-pi.html +600 -0
  89. package/docs/tutorials/security-basics.html +539 -0
  90. package/docs/tutorials/share-files.html +431 -0
  91. package/docs/tutorials/troubleshooting.html +637 -0
  92. package/docs/tutorials/trust-karma.html +419 -0
  93. package/docs/tutorials/yak-protocol.html +456 -0
  94. package/docs/tutorials.html +1034 -0
  95. package/docs/vani.html +1270 -0
  96. package/docs/webserver.html +809 -0
  97. package/docs/yak-protocol.html +940 -0
  98. package/docs/yak-timeserver-design.md +475 -0
  99. package/docs/yakapp.html +1015 -0
  100. package/docs/ypc27.html +1069 -0
  101. package/docs/yurt.html +1344 -0
  102. package/embedded-docs/bundle.js +334 -74
  103. package/gossip/protocol.js +247 -27
  104. package/identity/key-resolver.js +262 -0
  105. package/identity/machine-seed.js +632 -0
  106. package/identity/node-key.js +669 -368
  107. package/identity/tribhuj-ratchet.js +506 -0
  108. package/knowledge-base.js +37 -8
  109. package/launcher/yakmesh.bat +62 -0
  110. package/launcher/yakmesh.sh +70 -0
  111. package/mesh/annex.js +462 -108
  112. package/mesh/beacon-broadcast.js +113 -1
  113. package/mesh/darshan.js +1718 -0
  114. package/mesh/gumba.js +1567 -0
  115. package/mesh/jhilke.js +651 -0
  116. package/mesh/katha.js +1012 -0
  117. package/mesh/nakpak-routing.js +8 -5
  118. package/mesh/network.js +724 -34
  119. package/mesh/pulse-sync.js +4 -1
  120. package/mesh/rate-limiter.js +127 -15
  121. package/mesh/seva.js +526 -0
  122. package/mesh/sherpa-discovery.js +89 -8
  123. package/mesh/sybil-defense.js +19 -5
  124. package/mesh/temporal-encoder.js +4 -3
  125. package/mesh/vani.js +1364 -0
  126. package/mesh/yurt.js +1340 -0
  127. package/models/entropy-sentinel.onnx +0 -0
  128. package/models/karma-trust.onnx +0 -0
  129. package/models/manifest.json +43 -0
  130. package/models/sakshi-anomaly.onnx +0 -0
  131. package/oracle/code-proof-protocol.js +7 -6
  132. package/oracle/codebase-lock.js +257 -28
  133. package/oracle/index.js +74 -15
  134. package/oracle/ma902-snmp.js +678 -0
  135. package/oracle/module-sealer.js +5 -3
  136. package/oracle/network-identity.js +16 -0
  137. package/oracle/packet-checksum.js +201 -0
  138. package/oracle/sst.js +579 -0
  139. package/oracle/ternary-144t.js +714 -0
  140. package/oracle/ternary-ml.js +481 -0
  141. package/oracle/time-api.js +239 -0
  142. package/oracle/time-source.js +137 -47
  143. package/oracle/validation-oracle-hardened.js +1111 -1071
  144. package/oracle/validation-oracle.js +4 -2
  145. package/oracle/ypc27.js +211 -0
  146. package/package.json +20 -3
  147. package/protocol/yak-handler.js +35 -9
  148. package/protocol/yak-protocol.js +28 -13
  149. package/reference/cpp/yakmesh_mceliece_shard.cpp +168 -0
  150. package/reference/cpp/yakmesh_ypc27.cpp +179 -0
  151. package/sbom.json +87 -0
  152. package/scripts/security-audit.mjs +264 -0
  153. package/scripts/update-docs-nav.js +194 -0
  154. package/scripts/update-docs-sidebar.cjs +164 -0
  155. package/security/crypto-config.js +4 -3
  156. package/security/dharma-moderation.js +517 -0
  157. package/security/doko-identity.js +193 -143
  158. package/security/domain-consensus.js +86 -85
  159. package/security/fs-hardening.js +620 -0
  160. package/security/hardware-attestation.js +5 -3
  161. package/security/hybrid-trust.js +227 -87
  162. package/security/karma-rate-limiter.js +692 -0
  163. package/security/khata-protocol.js +22 -21
  164. package/security/khata-trust-integration.js +277 -150
  165. package/security/memory-safety.js +635 -0
  166. package/security/mesh-auth.js +11 -10
  167. package/security/mesh-revocation.js +373 -5
  168. package/security/namche-gateway.js +298 -69
  169. package/security/sakshi.js +460 -3
  170. package/security/sangha.js +770 -0
  171. package/security/secure-config.js +473 -0
  172. package/security/silicon-parity.js +13 -10
  173. package/security/steadywatch.js +1142 -0
  174. package/security/strike-system.js +32 -3
  175. package/security/temporal-signing.js +488 -0
  176. package/security/trit-commitment.js +464 -0
  177. package/server/crypto/annex.js +247 -0
  178. package/server/darshan-api.js +343 -0
  179. package/server/index.js +3259 -362
  180. package/server/komm-api.js +668 -0
  181. package/utils/accel.js +2273 -0
  182. package/utils/ternary-id.js +79 -0
  183. package/utils/verify-worker.js +57 -0
  184. package/webserver/index.js +95 -5
  185. package/assets/yakmesh-logo.png +0 -0
  186. package/assets/yakmesh-logo.svg +0 -80
  187. package/assets/yakmesh-logo2.png +0 -0
  188. package/assets/yakmesh-logo2sm.png +0 -0
  189. package/assets/ymsm.png +0 -0
  190. package/website/assets/silhouettes/adapters.svg +0 -107
  191. package/website/assets/silhouettes/api-endpoints.svg +0 -115
  192. package/website/assets/silhouettes/atomic-clock.svg +0 -83
  193. package/website/assets/silhouettes/base-camp.svg +0 -81
  194. package/website/assets/silhouettes/bridge.svg +0 -69
  195. package/website/assets/silhouettes/docs-bundle.svg +0 -113
  196. package/website/assets/silhouettes/doko-basket.svg +0 -70
  197. package/website/assets/silhouettes/fortress.svg +0 -93
  198. package/website/assets/silhouettes/gateway.svg +0 -54
  199. package/website/assets/silhouettes/gears.svg +0 -93
  200. package/website/assets/silhouettes/globe-satellite.svg +0 -67
  201. package/website/assets/silhouettes/karma-wheel.svg +0 -137
  202. package/website/assets/silhouettes/lama-council.svg +0 -141
  203. package/website/assets/silhouettes/mandala-network.svg +0 -169
  204. package/website/assets/silhouettes/mani-stones.svg +0 -149
  205. package/website/assets/silhouettes/mantra-wheel.svg +0 -116
  206. package/website/assets/silhouettes/mesh-nodes.svg +0 -113
  207. package/website/assets/silhouettes/nakpak.svg +0 -56
  208. package/website/assets/silhouettes/peak-lightning.svg +0 -73
  209. package/website/assets/silhouettes/sherpa.svg +0 -69
  210. package/website/assets/silhouettes/stupa-tower.svg +0 -119
  211. package/website/assets/silhouettes/tattva-eye.svg +0 -78
  212. package/website/assets/silhouettes/terminal.svg +0 -74
  213. package/website/assets/silhouettes/webserver.svg +0 -145
  214. package/website/assets/silhouettes/yak.svg +0 -78
  215. package/website/assets/yakmesh-logo.png +0 -0
  216. package/website/assets/yakmesh-logo.webp +0 -0
  217. package/website/assets/yakmesh-logo128x140.webp +0 -0
  218. package/website/assets/yakmesh-logo2.png +0 -0
  219. package/website/assets/yakmesh-logo2.svg +0 -51
  220. package/website/assets/yakmesh-logo40x44.webp +0 -0
  221. package/website/assets/yakmesh.gif +0 -0
  222. package/website/assets/yakmesh.ico +0 -0
  223. package/website/assets/yakmesh.jpg +0 -0
  224. package/website/assets/yakmesh.pdf +0 -0
  225. package/website/assets/yakmesh.png +0 -0
  226. package/website/assets/yakmesh.svg +0 -70
  227. package/website/assets/yakmesh128.webp +0 -0
  228. package/website/assets/yakmesh32.png +0 -0
  229. package/website/assets/yakmesh32.svg +0 -65
  230. package/website/assets/yakmesh32o.ico +0 -2
  231. package/website/assets/yakmesh32o.svg +0 -65
  232. package/website/assets/yakmesh32o.svgz +0 -0
@@ -0,0 +1,475 @@
1
+ # time.yakmesh.dev — Public Atomic Time Service
2
+
3
+ **Date**: 2026-02-21
4
+ **Status**: Design Draft
5
+ **Domain**: time.yakmesh.dev
6
+ **Hardware**: MA-902/S-C1 GPS Gigabit Time Server at 192.168.1.30
7
+
8
+ ---
9
+
10
+ ## Concept
11
+
12
+ Any device can gain atomic-grade time synchronization by pointing at a yakmesh node.
13
+ The MA-902 GPS time server already provides Stratum 1 NTP on the LAN — this design
14
+ exposes that precision publicly through three tiers:
15
+
16
+ | Tier | Protocol | URL / Address | Accuracy | Use Case |
17
+ |------|----------|---------------|----------|----------|
18
+ | **1. NTP** | NTPv4 (UDP 123) | `ntp.yakmesh.dev` | ±1ms | OS-level time sync (`w32tm`, `chrony`, `ntpd`) |
19
+ | **2. HTTP Time API** | HTTPS (Caddy) | `https://time.yakmesh.dev/api/time` | ±5ms | Web apps, IoT, scripts, cross-platform |
20
+ | **3. NTS** | NTS-KE + NTPv4 | `nts.yakmesh.dev` | ±1ms | Authenticated, tamper-proof time (RFC 8915) |
21
+
22
+ **Why better than OS standard:**
23
+ - Most machines sync to `time.windows.com` or `pool.ntp.org` — Stratum 2-3 servers
24
+ with ±10-50ms accuracy and no authentication
25
+ - time.yakmesh.dev is **Stratum 1** (direct GPS antenna), ±1ms, with satellite health
26
+ telemetry and optional NTS authentication
27
+ - MA-902 tracks GPS + BeiDou constellations with 8-12 satellites in fix solution
28
+
29
+ ---
30
+
31
+ ## Architecture
32
+
33
+ ```
34
+ Internet
35
+
36
+ ┌────────────┴────────────┐
37
+ │ yakmesh.dev VPS │
38
+ │ │
39
+ │ ┌───────────────────┐ │
40
+ │ │ Caddy (HTTPS) │ │
41
+ │ │ time.yakmesh. │ │
42
+ │ │ dev :443 │──┼──→ /api/time → time-api.js (Node)
43
+ │ │ │ │ /api/health → satellite status
44
+ │ │ │ │ / → landing page
45
+ │ └───────────────────┘ │
46
+ │ │
47
+ │ ┌───────────────────┐ │
48
+ │ │ NTP relay/proxy │ │
49
+ │ │ :123 UDP │──┼──→ Forwards to MA-902 192.168.1.30:123
50
+ │ │ (chrony or ntpd) │ │ via WireGuard tunnel
51
+ │ └───────────────────┘ │
52
+ │ │
53
+ └─────────┬───────────────┘
54
+ │ WireGuard tunnel
55
+
56
+ ┌─────────┴───────────────┐
57
+ │ LAN (192.168.1.x) │
58
+ │ │
59
+ │ ┌───────────────────┐ │
60
+ │ │ MA-902/S-C1 GPS │ │
61
+ │ │ 192.168.1.30 │ │
62
+ │ │ NTP Stratum 1 │ │
63
+ │ │ SNMP v2c │ │
64
+ │ │ GPS+BeiDou │ │
65
+ │ └───────────────────┘ │
66
+ │ │
67
+ │ ┌───────────────────┐ │
68
+ │ │ Yakmesh Node │ │
69
+ │ │ (this machine) │ │
70
+ │ │ ma902-snmp.js │──┼──→ SNMP telemetry
71
+ │ │ time-api.js │──┼──→ HTTP time endpoint (local)
72
+ │ └───────────────────┘ │
73
+ │ │
74
+ └─────────────────────────┘
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Tier 1: NTP Service (`ntp.yakmesh.dev`)
80
+
81
+ ### Option A: Direct NTP Relay (Preferred)
82
+
83
+ Run `chrony` on the VPS with the MA-902 as its upstream source via WireGuard.
84
+ The VPS becomes a **Stratum 2** NTP server that anyone can use.
85
+
86
+ ```ini
87
+ # /etc/chrony/chrony.conf on the VPS
88
+ server 10.0.0.30 iburst prefer # MA-902 via WireGuard
89
+ driftfile /var/lib/chrony/drift
90
+ makestep 1.0 3
91
+ rtcsync
92
+ allow 0.0.0.0/0 # Allow all clients
93
+ ```
94
+
95
+ DNS: `ntp.yakmesh.dev` → VPS public IP (A record)
96
+
97
+ **Usage by end users:**
98
+ ```bash
99
+ # Windows
100
+ w32tm /config /manualpeerlist:"ntp.yakmesh.dev" /syncfromflags:manual /update
101
+
102
+ # Linux (chrony)
103
+ echo "server ntp.yakmesh.dev iburst" >> /etc/chrony/chrony.conf
104
+
105
+ # Linux (systemd-timesyncd)
106
+ echo 'NTP=ntp.yakmesh.dev' >> /etc/systemd/timesyncd.conf
107
+ ```
108
+
109
+ ### Option B: LAN-Only NTP (Simpler)
110
+
111
+ If no VPS/tunnel, the MA-902 at 192.168.1.30 already serves NTP locally.
112
+ Yakmesh nodes on the LAN can use it directly. Remote nodes use the HTTP API.
113
+
114
+ ---
115
+
116
+ ## Tier 2: HTTP Time API (`time.yakmesh.dev`)
117
+
118
+ ### Caddy Configuration
119
+
120
+ ```caddyfile
121
+ time.yakmesh.dev {
122
+ # Time API — reverse proxy to local Node.js time service
123
+ handle /api/* {
124
+ reverse_proxy localhost:3099
125
+ }
126
+
127
+ # Landing page — static site
128
+ handle {
129
+ root * /var/www/yak-timeserver
130
+ file_server
131
+ }
132
+
133
+ # Security headers
134
+ header {
135
+ X-Content-Type-Options nosniff
136
+ X-Frame-Options DENY
137
+ Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
138
+ Access-Control-Allow-Origin "*"
139
+ Access-Control-Allow-Methods "GET, HEAD, OPTIONS"
140
+ }
141
+
142
+ # CORS preflight
143
+ @cors_preflight method OPTIONS
144
+ handle @cors_preflight {
145
+ header Access-Control-Max-Age "86400"
146
+ respond "" 204
147
+ }
148
+
149
+ # Rate limiting
150
+ rate_limit {
151
+ zone time_api {
152
+ key {remote_host}
153
+ events 60
154
+ window 1m
155
+ }
156
+ }
157
+ }
158
+ ```
159
+
160
+ ### Time API Endpoints
161
+
162
+ #### `GET /api/time`
163
+
164
+ Returns current atomic time with metadata.
165
+
166
+ ```json
167
+ {
168
+ "iso": "2026-02-21T14:30:00.123Z",
169
+ "unix": 1771598200.123,
170
+ "unix_ms": 1771598200123,
171
+ "stratum": 1,
172
+ "source": "MA-902/S-C1 GPS",
173
+ "accuracy_ms": 1,
174
+ "leap_indicator": 0,
175
+ "satellites": {
176
+ "visible": 12,
177
+ "used": 9,
178
+ "tracking": 11,
179
+ "constellations": ["GPS", "BeiDou"]
180
+ },
181
+ "lock": true,
182
+ "quality": "excellent",
183
+ "offset_ns": 0,
184
+ "reference_id": "GPS"
185
+ }
186
+ ```
187
+
188
+ **Headers returned:**
189
+ ```
190
+ X-Yakmesh-Time: 1771598200.123
191
+ X-Yakmesh-Stratum: 1
192
+ X-Yakmesh-Source: GPS
193
+ Date: Fri, 21 Feb 2026 14:30:00 GMT
194
+ ```
195
+
196
+ #### `GET /api/time/simple`
197
+
198
+ Minimal response for constrained clients:
199
+
200
+ ```json
201
+ {
202
+ "t": 1771598200123,
203
+ "s": 1,
204
+ "q": "excellent"
205
+ }
206
+ ```
207
+
208
+ #### `GET /api/health`
209
+
210
+ Satellite health and SNMP telemetry:
211
+
212
+ ```json
213
+ {
214
+ "status": "healthy",
215
+ "uptime_s": 864000,
216
+ "lock": true,
217
+ "satellites_visible": 12,
218
+ "satellites_used": 9,
219
+ "constellations": ["GPS", "BeiDou"],
220
+ "alarm": false,
221
+ "quality": 1,
222
+ "last_poll": "2026-02-21T14:29:55Z",
223
+ "drift_ns": 0,
224
+ "trust_level": "atomic"
225
+ }
226
+ ```
227
+
228
+ #### `HEAD /api/time`
229
+
230
+ Returns only headers — zero body. Fastest way to get time:
231
+
232
+ ```
233
+ X-Yakmesh-Time: 1771598200.123
234
+ X-Yakmesh-Stratum: 1
235
+ Content-Length: 0
236
+ ```
237
+
238
+ ### Node.js Time API Service (`oracle/time-api.js`)
239
+
240
+ New module that bridges MA-902 SNMP telemetry to an HTTP endpoint:
241
+
242
+ ```javascript
243
+ // oracle/time-api.js — HTTP Atomic Time API
244
+ //
245
+ // Reads GPS time from MA-902 via the existing MA902Monitor SNMP module
246
+ // and serves it as a lightweight HTTP endpoint.
247
+ //
248
+ // Runs on port 3099 (configurable via YAKMESH_TIME_API_PORT).
249
+ // Reverse-proxied by Caddy at time.yakmesh.dev.
250
+
251
+ import http from 'node:http';
252
+ import { MA902Monitor } from './ma902-snmp.js';
253
+
254
+ const PORT = parseInt(process.env.YAKMESH_TIME_API_PORT || '3099');
255
+
256
+ const monitor = new MA902Monitor({
257
+ host: process.env.MA902_HOST || '192.168.1.30',
258
+ community: process.env.MA902_COMMUNITY || 'public',
259
+ pollInterval: 5000,
260
+ });
261
+
262
+ // Cache last SNMP telemetry
263
+ let lastTelemetry = null;
264
+ monitor.on('telemetry', (data) => { lastTelemetry = data; });
265
+ monitor.start();
266
+
267
+ const server = http.createServer((req, res) => {
268
+ const url = new URL(req.url, `http://localhost:${PORT}`);
269
+
270
+ // CORS
271
+ res.setHeader('Access-Control-Allow-Origin', '*');
272
+ res.setHeader('Access-Control-Allow-Methods', 'GET, HEAD, OPTIONS');
273
+
274
+ if (req.method === 'OPTIONS') {
275
+ res.writeHead(204);
276
+ return res.end();
277
+ }
278
+
279
+ const now = Date.now();
280
+ const unixS = now / 1000;
281
+
282
+ // Common time headers
283
+ res.setHeader('X-Yakmesh-Time', unixS.toFixed(3));
284
+ res.setHeader('X-Yakmesh-Stratum', lastTelemetry?.lockStatus ? '1' : '2');
285
+ res.setHeader('X-Yakmesh-Source', lastTelemetry?.lockStatus ? 'GPS' : 'system');
286
+
287
+ if (url.pathname === '/api/time' && req.method === 'HEAD') {
288
+ res.writeHead(200);
289
+ return res.end();
290
+ }
291
+
292
+ if (url.pathname === '/api/time/simple') {
293
+ const body = JSON.stringify({
294
+ t: now,
295
+ s: lastTelemetry?.lockStatus ? 1 : 2,
296
+ q: getQuality(),
297
+ });
298
+ res.writeHead(200, { 'Content-Type': 'application/json' });
299
+ return res.end(body);
300
+ }
301
+
302
+ if (url.pathname === '/api/time') {
303
+ const body = JSON.stringify({
304
+ iso: new Date(now).toISOString(),
305
+ unix: unixS,
306
+ unix_ms: now,
307
+ stratum: lastTelemetry?.lockStatus ? 1 : 2,
308
+ source: 'MA-902/S-C1 GPS',
309
+ accuracy_ms: lastTelemetry?.lockStatus ? 1 : 50,
310
+ leap_indicator: 0,
311
+ satellites: {
312
+ visible: lastTelemetry?.satsVisible ?? 0,
313
+ used: lastTelemetry?.satsUsed ?? 0,
314
+ tracking: lastTelemetry?.satsTracking ?? 0,
315
+ constellations: lastTelemetry?.constellations ?? [],
316
+ },
317
+ lock: lastTelemetry?.lockStatus ?? false,
318
+ quality: getQuality(),
319
+ offset_ns: lastTelemetry?.offset ?? 0,
320
+ reference_id: lastTelemetry?.lockStatus ? 'GPS' : 'SYS',
321
+ });
322
+ res.writeHead(200, { 'Content-Type': 'application/json' });
323
+ return res.end(body);
324
+ }
325
+
326
+ if (url.pathname === '/api/health') {
327
+ const body = JSON.stringify({
328
+ status: lastTelemetry?.lockStatus ? 'healthy' : 'degraded',
329
+ lock: lastTelemetry?.lockStatus ?? false,
330
+ satellites_visible: lastTelemetry?.satsVisible ?? 0,
331
+ satellites_used: lastTelemetry?.satsUsed ?? 0,
332
+ constellations: lastTelemetry?.constellations ?? [],
333
+ alarm: lastTelemetry?.alarm ?? false,
334
+ quality: lastTelemetry?.quality ?? 0,
335
+ last_poll: lastTelemetry?.timestamp
336
+ ? new Date(lastTelemetry.timestamp).toISOString()
337
+ : null,
338
+ trust_level: lastTelemetry?.trustLevel ?? 'unknown',
339
+ });
340
+ res.writeHead(200, { 'Content-Type': 'application/json' });
341
+ return res.end(body);
342
+ }
343
+
344
+ res.writeHead(404, { 'Content-Type': 'application/json' });
345
+ res.end(JSON.stringify({ error: 'Not found' }));
346
+ });
347
+
348
+ function getQuality() {
349
+ if (!lastTelemetry) return 'unknown';
350
+ const sats = lastTelemetry.satsUsed || 0;
351
+ if (sats >= 8) return 'excellent';
352
+ if (sats >= 5) return 'good';
353
+ if (sats >= 3) return 'marginal';
354
+ return 'degraded';
355
+ }
356
+
357
+ server.listen(PORT, () => {
358
+ console.log(`Yakmesh Time API listening on :${PORT}`);
359
+ });
360
+ ```
361
+
362
+ ---
363
+
364
+ ## Tier 3: NTS — Network Time Security (Future)
365
+
366
+ NTS (RFC 8915) adds TLS-based authentication to NTP, preventing MITM time attacks.
367
+ This is a natural extension of yakmesh's post-quantum stance.
368
+
369
+ **Requirements:**
370
+ - NTS-KE (Key Establishment) server on port 4460
371
+ - TLS certificate (Let's Encrypt via Caddy)
372
+ - Compatible NTP server (chrony 4.0+ supports NTS natively)
373
+
374
+ **chrony NTS config:**
375
+ ```ini
376
+ ntsserverkey /etc/letsencrypt/live/nts.yakmesh.dev/privkey.pem
377
+ ntsservercert /etc/letsencrypt/live/nts.yakmesh.dev/fullchain.pem
378
+ ntsport 4460
379
+ ```
380
+
381
+ **Post-quantum consideration:** NTS currently uses TLS 1.3 with X25519/AES.
382
+ When PQ TLS (ML-KEM hybrid) ships in standard libraries, the NTS-KE handshake
383
+ becomes quantum-resistant. The NTP payload is already authenticated with AEAD.
384
+
385
+ **Client usage:**
386
+ ```bash
387
+ # chrony client
388
+ server nts.yakmesh.dev nts iburst
389
+ ```
390
+
391
+ ---
392
+
393
+ ## MANI Protocol Integration
394
+
395
+ The time API feeds directly into the existing MANI (prayer stone) time
396
+ synchronization protocol. Every yakmesh node can:
397
+
398
+ 1. Use `ntp.yakmesh.dev` as its NTP source (OS-level)
399
+ 2. Query `time.yakmesh.dev/api/time` for satellite health telemetry
400
+ 3. Feed responses into `ManiTimeDetector` for trust assessment
401
+ 4. Broadcast time trust level via MANI gossip to mesh peers
402
+
403
+ This means **any yakmesh node with internet access automatically gains
404
+ atomic-grade time** — even without a local GPS receiver.
405
+
406
+ ### Config Addition (yakmesh-node env vars)
407
+
408
+ ```bash
409
+ YAKMESH_TIME_API_PORT=3099 # Local time API port
410
+ YAKMESH_TIME_SOURCE=ma902 # 'ma902' | 'ntp' | 'system'
411
+ MA902_HOST=192.168.1.30 # MA-902 SNMP address
412
+ MA902_COMMUNITY=public # SNMP community string
413
+ ```
414
+
415
+ ---
416
+
417
+ ## DNS Setup
418
+
419
+ ```
420
+ time.yakmesh.dev A → VPS IP (Caddy serves HTTPS API + landing page)
421
+ ntp.yakmesh.dev A → VPS IP (chrony NTP relay on UDP 123)
422
+ nts.yakmesh.dev A → VPS IP (NTS-KE on TCP 4460 + NTP on UDP 123)
423
+ ```
424
+
425
+ All subdomains under `yakmesh.dev` — no additional domain purchase needed.
426
+
427
+ ---
428
+
429
+ ## Landing Page (`time.yakmesh.dev/`)
430
+
431
+ Static HTML page (served by Caddy) showing:
432
+
433
+ - **Live atomic clock** — JavaScript fetching `/api/time` every second
434
+ - **Satellite constellation map** — GPS/BeiDou satellite visualization from health data
435
+ - **Setup instructions** — How to configure your OS/device to use time.yakmesh.dev
436
+ - **About** — MA-902 hardware details, GPS antenna, accuracy specs
437
+ - **Status badge** — Green/yellow/red based on satellite lock
438
+ - **Integration with yakmesh** — Link to MANI docs, time-sources.html
439
+
440
+ Design: Match yakmesh.dev aesthetic (dark theme, system fonts, zero external deps).
441
+ Same domain family — consistent branding under `*.yakmesh.dev`.
442
+
443
+ ---
444
+
445
+ ## Implementation Order
446
+
447
+ | Step | Task | Effort | Depends On |
448
+ |------|------|--------|------------|
449
+ | 1 | Create `oracle/time-api.js` — HTTP time service | 2 hours | MA-902 SNMP module (done) |
450
+ | 2 | Add Caddy site block for `time.yakmesh.dev` to `generateCaddyfile()` | 1 hour | Step 1 |
451
+ | 3 | Create landing page (static HTML) | 3 hours | Step 1 |
452
+ | 4 | DNS setup (A/CNAME records) | 15 min | Domain registrar access |
453
+ | 5 | VPS chrony configuration (NTP relay) | 1 hour | WireGuard tunnel to LAN |
454
+ | 6 | Add `/api/time` docs section to `time-sources.html` | 1 hour | Step 1 |
455
+ | 7 | MANI integration — remote nodes query time.yakmesh.dev | 2 hours | Step 1, MANI module |
456
+ | 8 | NTS setup (optional, future) | 4 hours | Step 5, chrony 4.0+ |
457
+
458
+ **Total: ~10 hours for Tiers 1+2, ~14 hours with NTS**
459
+
460
+ ---
461
+
462
+ ## Security Considerations
463
+
464
+ - **Rate limiting**: 60 req/min per IP on the HTTP API (Caddy rate_limit plugin)
465
+ - **No auth required**: Time is a public good — unauthenticated, CORS-open
466
+ - **Read-only**: API is GET/HEAD only, no writes, no state mutation
467
+ - **SNMP isolation**: MA-902 SNMP is LAN-only (192.168.1.x), never exposed publicly
468
+ - **GPS spoofing**: MA-902 has quality indicators; if satellites degrade, the API
469
+ returns `"quality": "degraded"` and clients can fall back to system time
470
+ - **DDoS**: Caddy handles TLS termination; chrony handles NTP amplification protection
471
+ via `ratelimit` directive
472
+
473
+ ---
474
+
475
+ *Created: 2026-02-21 | Part of YAKMESH MANI Time Protocol Suite*