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,273 @@
1
+ /**
2
+ * Yakmesh - Content Adapter Base Class
3
+ *
4
+ * Specialized adapter for content distribution via DARSHAN protocol.
5
+ * Designed for scripture, documents, educational materials, and other
6
+ * content that benefits from the view-not-copy paradigm.
7
+ *
8
+ * @module adapters/content-adapter
9
+ * @version 1.0.0
10
+ */
11
+
12
+ import { EventEmitter } from 'events';
13
+
14
+ /**
15
+ * Capability declarations for content adapters
16
+ * Adapters MUST declare their capabilities upfront
17
+ */
18
+ export const CONTENT_CAPABILITIES = {
19
+ // Content types this adapter can serve
20
+ SERVE_PDF: 'serve:pdf',
21
+ SERVE_TEXT: 'serve:text',
22
+ SERVE_AUDIO: 'serve:audio',
23
+ SERVE_VIDEO: 'serve:video',
24
+
25
+ // Search/lookup capabilities
26
+ SEARCH_FULLTEXT: 'search:fulltext',
27
+ SEARCH_REFERENCE: 'search:reference', // e.g., John 3:16
28
+
29
+ // Chat integration capabilities
30
+ CHAT_QUOTE: 'chat:quote', // Can generate quotes for KATHA
31
+ CHAT_EMBED: 'chat:embed', // Can embed previews in chat
32
+ CHAT_LOOKUP: 'chat:lookup', // Can respond to lookup commands
33
+
34
+ // Network capabilities
35
+ NET_STREAM: 'net:stream', // Can stream via DARSHAN
36
+ NET_DOWNLOAD: 'net:download', // Allows downloads (opt-in)
37
+ NET_CACHE: 'net:cache', // Can be cached by peers
38
+ };
39
+
40
+ /**
41
+ * Content metadata standard
42
+ */
43
+ export class ContentMetadata {
44
+ constructor({
45
+ id,
46
+ title,
47
+ author = null,
48
+ copyright = null,
49
+ license = null,
50
+ version = '1.0.0',
51
+ language = 'en',
52
+ contentType = 'application/pdf',
53
+ size = 0,
54
+ hash = null,
55
+ created = new Date(),
56
+ modified = new Date(),
57
+ tags = [],
58
+ references = {}, // e.g., { 'John 3:16': { page: 42, position: 0.3 } }
59
+ } = {}) {
60
+ this.id = id;
61
+ this.title = title;
62
+ this.author = author;
63
+ this.copyright = copyright;
64
+ this.license = license;
65
+ this.version = version;
66
+ this.language = language;
67
+ this.contentType = contentType;
68
+ this.size = size;
69
+ this.hash = hash;
70
+ this.created = created;
71
+ this.modified = modified;
72
+ this.tags = tags;
73
+ this.references = references;
74
+ }
75
+
76
+ toJSON() {
77
+ return { ...this };
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Abstract base class for content distribution adapters
83
+ */
84
+ export class ContentAdapter extends EventEmitter {
85
+ /**
86
+ * @param {Object} config - Adapter configuration
87
+ * @param {string} config.name - Human-readable adapter name
88
+ * @param {string} config.id - Unique adapter identifier
89
+ * @param {string[]} config.capabilities - Array of CONTENT_CAPABILITIES
90
+ * @param {Object} config.darshan - DARSHAN instance for streaming
91
+ */
92
+ constructor(config = {}) {
93
+ super();
94
+
95
+ if (new.target === ContentAdapter) {
96
+ throw new Error('ContentAdapter is abstract and cannot be instantiated directly');
97
+ }
98
+
99
+ this.name = config.name || 'UnnamedContentAdapter';
100
+ this.id = config.id || 'content-adapter-' + Date.now();
101
+ this.capabilities = new Set(config.capabilities || []);
102
+ this.darshan = config.darshan || null;
103
+
104
+ // Content catalog
105
+ this.catalog = new Map(); // id -> ContentMetadata
106
+
107
+ // Statistics
108
+ this.stats = {
109
+ contentServed: 0,
110
+ searchQueries: 0,
111
+ chatQuotes: 0,
112
+ errors: [],
113
+ };
114
+
115
+ // Security: Validate capabilities
116
+ this._validateCapabilities();
117
+ }
118
+
119
+ /**
120
+ * Initialize the adapter and build content catalog
121
+ * @abstract
122
+ */
123
+ async init() {
124
+ throw new Error('init() must be implemented by subclass');
125
+ }
126
+
127
+ /**
128
+ * Get list of available content
129
+ * @returns {ContentMetadata[]}
130
+ */
131
+ listContent() {
132
+ return Array.from(this.catalog.values());
133
+ }
134
+
135
+ /**
136
+ * Get content metadata by ID
137
+ * @param {string} id - Content ID
138
+ * @returns {ContentMetadata|null}
139
+ */
140
+ getContentMeta(id) {
141
+ return this.catalog.get(id) || null;
142
+ }
143
+
144
+ /**
145
+ * Search content by query
146
+ * @abstract
147
+ * @param {string} query - Search query
148
+ * @param {Object} options - Search options
149
+ * @returns {Promise<Object[]>} Search results
150
+ */
151
+ async search(query, options = {}) {
152
+ throw new Error('search() must be implemented by subclass');
153
+ }
154
+
155
+ /**
156
+ * Lookup content by reference (e.g., 'John 3:16')
157
+ * @abstract
158
+ * @param {string} reference - Reference string
159
+ * @returns {Promise<Object|null>} Lookup result
160
+ */
161
+ async lookupReference(reference) {
162
+ throw new Error('lookupReference() must be implemented by subclass');
163
+ }
164
+
165
+ /**
166
+ * Get content stream for DARSHAN
167
+ * @abstract
168
+ * @param {string} id - Content ID
169
+ * @param {Object} options - Stream options (range, quality, etc.)
170
+ * @returns {Promise<ReadableStream>}
171
+ */
172
+ async getContentStream(id, options = {}) {
173
+ throw new Error('getContentStream() must be implemented by subclass');
174
+ }
175
+
176
+ /**
177
+ * Generate a quotable snippet for KATHA chat
178
+ * @param {string} reference - Content reference
179
+ * @param {Object} options - Quote options
180
+ * @returns {Promise<Object>} Quote object for KATHA
181
+ */
182
+ async generateChatQuote(reference, options = {}) {
183
+ if (!this.capabilities.has(CONTENT_CAPABILITIES.CHAT_QUOTE)) {
184
+ throw new Error('Adapter does not support chat quotes');
185
+ }
186
+
187
+ const result = await this.lookupReference(reference);
188
+ if (!result) {
189
+ return null;
190
+ }
191
+
192
+ this.stats.chatQuotes++;
193
+
194
+ return {
195
+ type: 'content-quote',
196
+ adapter: this.id,
197
+ reference,
198
+ text: result.text,
199
+ metadata: {
200
+ source: this.name,
201
+ contentId: result.contentId,
202
+ position: result.position,
203
+ },
204
+ // Security: Sign the quote so it can be verified
205
+ verified: true,
206
+ };
207
+ }
208
+
209
+ /**
210
+ * Register content with DARSHAN for streaming
211
+ * @param {string} id - Content ID
212
+ * @param {Object} options - Registration options
213
+ */
214
+ async registerWithDarshan(id, options = {}) {
215
+ if (!this.darshan) {
216
+ throw new Error('DARSHAN instance not configured');
217
+ }
218
+
219
+ const meta = this.catalog.get(id);
220
+ if (!meta) {
221
+ throw new Error('Content not found: ' + id);
222
+ }
223
+
224
+ // Register as a DARSHAN content source
225
+ await this.darshan.registerContent(id, {
226
+ title: meta.title,
227
+ type: meta.contentType,
228
+ size: meta.size,
229
+ getStream: () => this.getContentStream(id),
230
+ allowDownload: options.allowDownload || false,
231
+ // DARSHAN handles view-not-copy enforcement
232
+ });
233
+
234
+ this.emit('content-registered', { id, meta });
235
+ }
236
+
237
+ /**
238
+ * Validate declared capabilities
239
+ * @private
240
+ */
241
+ _validateCapabilities() {
242
+ const validCaps = new Set(Object.values(CONTENT_CAPABILITIES));
243
+ for (const cap of this.capabilities) {
244
+ if (!validCaps.has(cap)) {
245
+ console.warn(\Unknown capability declared: \\);
246
+ }
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Check if adapter has a capability
252
+ * @param {string} capability - Capability to check
253
+ * @returns {boolean}
254
+ */
255
+ hasCapability(capability) {
256
+ return this.capabilities.has(capability);
257
+ }
258
+
259
+ /**
260
+ * Get adapter statistics
261
+ */
262
+ getStats() {
263
+ return {
264
+ ...this.stats,
265
+ name: this.name,
266
+ id: this.id,
267
+ capabilities: Array.from(this.capabilities),
268
+ catalogSize: this.catalog.size,
269
+ };
270
+ }
271
+ }
272
+
273
+ export default ContentAdapter;
package/content/api.js CHANGED
@@ -2,10 +2,14 @@
2
2
  * YAKMESH™ Public Content API
3
3
  * HTTP endpoints for public content delivery
4
4
  *
5
+ * Content integrity = SHA3-256 hash match.
6
+ * Content authorship = publisher ML-DSA-65 signature.
7
+ * No voting, no quorum, no consensus proofs.
8
+ *
5
9
  * Public (no auth required):
6
10
  * - GET /content/:hash - Fetch content by hash
7
11
  * - GET /content/:hash/meta - Fetch metadata only
8
- * - GET /content/:hash/proof - Fetch consensus proof
12
+ * - GET /content/:hash/integrity - Fetch integrity info (hash + publisher sig)
9
13
  * - GET /content/list - List available content
10
14
  *
11
15
  * Authenticated (rate limited):
@@ -18,18 +22,19 @@
18
22
  */
19
23
 
20
24
  import { Router } from 'express';
21
- import { ContentStore, ContentType, ContentStatus, computeContentHash } from './store.js';
25
+ import { ContentStore, ContentType, ContentStatus, computeContentHash, isTritAddress } from './store.js';
22
26
 
23
27
  /**
24
28
  * Create content API router
25
29
  */
26
30
  export function createContentAPI(contentStore, options = {}) {
27
31
  const router = Router();
28
-
32
+
29
33
  const {
30
34
  writeLimiter,
31
35
  readLimiter,
32
36
  validateString,
37
+ requirePeerAuth,
33
38
  } = options;
34
39
 
35
40
  // =========================================
@@ -38,22 +43,20 @@ export function createContentAPI(contentStore, options = {}) {
38
43
 
39
44
  /**
40
45
  * GET /content/:hash
41
- * Fetch content by hash with optional proof
46
+ * Fetch content by hash
42
47
  *
43
48
  * Query params:
44
- * - proof=1 : Include consensus proof in response headers
45
49
  * - download=1 : Force download (Content-Disposition)
46
50
  */
47
51
  router.get('/:hash', readLimiter, (req, res) => {
48
52
  const { hash } = req.params;
49
- const includeProof = req.query.proof === '1';
50
53
  const download = req.query.download === '1';
51
54
 
52
55
  // Get content with metadata
53
56
  const result = contentStore.getWithProof(hash);
54
-
57
+
55
58
  if (!result) {
56
- return res.status(404).json({
59
+ return res.status(404).json({
57
60
  error: 'Content not found',
58
61
  hash,
59
62
  hint: 'Content may not have synced yet. Try again later.',
@@ -64,19 +67,22 @@ export function createContentAPI(contentStore, options = {}) {
64
67
  res.setHeader('Content-Type', result.meta?.contentType || 'application/octet-stream');
65
68
  res.setHeader('Content-Length', result.meta?.size || result.content.length);
66
69
  res.setHeader('X-Content-Hash', result.hash);
70
+ res.setHeader('X-Content-Hash-144T', result.hash144t || result.meta?.hash144t || '');
67
71
  res.setHeader('X-Content-Status', result.meta?.status || 'unknown');
68
-
69
- // Cache headers (immutable content = cache forever)
72
+
73
+ // Cache headers (verified content = cache forever)
70
74
  if (result.verified) {
71
75
  res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
76
+ res.setHeader('X-Verified', 'true');
72
77
  } else {
73
78
  res.setHeader('Cache-Control', 'public, max-age=60');
79
+ res.setHeader('X-Verified', 'false');
74
80
  }
75
81
 
76
- // Include proof in headers if requested
77
- if (includeProof && result.proof) {
78
- res.setHeader('X-Consensus-Proof', JSON.stringify(result.proof));
79
- res.setHeader('X-Verified', result.verified ? 'true' : 'false');
82
+ // Publisher signature header
83
+ if (result.meta?.publisherSignature) {
84
+ res.setHeader('X-Publisher-Signature', result.meta.publisherSignature);
85
+ res.setHeader('X-Published-By', result.meta.publishedBy || 'unknown');
80
86
  }
81
87
 
82
88
  // Download disposition
@@ -95,7 +101,7 @@ export function createContentAPI(contentStore, options = {}) {
95
101
  router.get('/:hash/meta', readLimiter, (req, res) => {
96
102
  const { hash } = req.params;
97
103
  const meta = contentStore.getMeta(hash);
98
-
104
+
99
105
  if (!meta) {
100
106
  return res.status(404).json({ error: 'Content not found', hash });
101
107
  }
@@ -104,30 +110,31 @@ export function createContentAPI(contentStore, options = {}) {
104
110
  });
105
111
 
106
112
  /**
107
- * GET /content/:hash/proof
108
- * Fetch consensus proof for light client verification
113
+ * GET /content/:hash/integrity
114
+ * Fetch integrity info for content verification
115
+ * Returns hash, publisher identity, publisher signature, and verification status.
116
+ * Any client can independently verify: hash(content) === hash AND
117
+ * verify(hash, publisherSignature, publisherPubKey) === true.
109
118
  */
110
- router.get('/:hash/proof', readLimiter, (req, res) => {
119
+ router.get('/:hash/integrity', readLimiter, (req, res) => {
111
120
  const { hash } = req.params;
112
121
  const meta = contentStore.getMeta(hash);
113
-
122
+
114
123
  if (!meta) {
115
124
  return res.status(404).json({ error: 'Content not found', hash });
116
125
  }
117
126
 
118
- if (!meta.consensusProof) {
119
- return res.status(404).json({
120
- error: 'No consensus proof yet',
121
- hash,
122
- status: meta.status,
123
- hint: 'Content may still be pending consensus.',
124
- });
125
- }
126
-
127
127
  res.json({
128
- hash,
128
+ hash: meta.hash,
129
+ hash144t: meta.hash144t,
130
+ ioName: meta.ioName,
129
131
  verified: meta.status === ContentStatus.VERIFIED,
130
- proof: meta.consensusProof.toJSON ? meta.consensusProof.toJSON() : meta.consensusProof,
132
+ status: meta.status,
133
+ publishedBy: meta.publishedBy,
134
+ publisherSignature: meta.publisherSignature || null,
135
+ contentType: meta.contentType,
136
+ size: meta.size,
137
+ createdAt: meta.createdAt,
131
138
  });
132
139
  });
133
140
 
@@ -143,7 +150,7 @@ export function createContentAPI(contentStore, options = {}) {
143
150
  */
144
151
  router.get('/', readLimiter, (req, res) => {
145
152
  const { tag, status, limit = 100, offset = 0 } = req.query;
146
-
153
+
147
154
  const items = contentStore.list({
148
155
  tag,
149
156
  status,
@@ -164,7 +171,7 @@ export function createContentAPI(contentStore, options = {}) {
164
171
  */
165
172
  router.head('/:hash', readLimiter, (req, res) => {
166
173
  const { hash } = req.params;
167
-
174
+
168
175
  if (contentStore.has(hash)) {
169
176
  const meta = contentStore.getMeta(hash);
170
177
  res.setHeader('Content-Type', meta?.contentType || 'application/octet-stream');
@@ -199,7 +206,7 @@ export function createContentAPI(contentStore, options = {}) {
199
206
  * - name: optional name
200
207
  * - tags: comma-separated tags
201
208
  */
202
- router.post('/publish', writeLimiter, async (req, res) => {
209
+ router.post('/publish', writeLimiter, requirePeerAuth, async (req, res) => {
203
210
  try {
204
211
  let content;
205
212
  let options = {};
@@ -216,7 +223,7 @@ export function createContentAPI(contentStore, options = {}) {
216
223
  tags: req.body.tags || [],
217
224
  ttl: req.body.ttl || 0,
218
225
  };
219
- }
226
+ }
220
227
  // Handle raw body
221
228
  else if (req.body && Buffer.isBuffer(req.body)) {
222
229
  content = req.body;
@@ -245,9 +252,11 @@ export function createContentAPI(contentStore, options = {}) {
245
252
  res.status(201).json({
246
253
  success: true,
247
254
  hash: result.hash,
255
+ hash144t: result.hash144t,
256
+ ioName: result.ioName,
248
257
  status: result.status,
249
258
  meta: result.meta?.toJSON ? result.meta.toJSON() : result.meta,
250
- url: `/content/${result.hash}`,
259
+ url: `/content/${result.hash144t || result.hash}`,
251
260
  });
252
261
  } catch (error) {
253
262
  res.status(500).json({ error: error.message });
@@ -260,7 +269,7 @@ export function createContentAPI(contentStore, options = {}) {
260
269
  */
261
270
  router.post('/request', writeLimiter, async (req, res) => {
262
271
  const { hash } = req.body;
263
-
272
+
264
273
  if (!hash) {
265
274
  return res.status(400).json({ error: 'Hash required' });
266
275
  }
@@ -277,7 +286,7 @@ export function createContentAPI(contentStore, options = {}) {
277
286
 
278
287
  // Request from mesh
279
288
  const result = await contentStore.request(hash);
280
-
289
+
281
290
  res.json({
282
291
  found: true,
283
292
  local: false,
@@ -297,9 +306,9 @@ export function createContentAPI(contentStore, options = {}) {
297
306
  * DELETE /content/:hash
298
307
  * Remove content (local only - cannot remove from mesh)
299
308
  */
300
- router.delete('/:hash', writeLimiter, (req, res) => {
309
+ router.delete('/:hash', writeLimiter, requirePeerAuth, (req, res) => {
301
310
  const { hash } = req.params;
302
-
311
+
303
312
  if (!contentStore.has(hash)) {
304
313
  return res.status(404).json({ error: 'Content not found', hash });
305
314
  }
@@ -329,13 +338,13 @@ export function createContentAPI(contentStore, options = {}) {
329
338
  */
330
339
  router.post('/verify', readLimiter, (req, res) => {
331
340
  const content = req.body.content || req.body;
332
-
341
+
333
342
  if (!content) {
334
343
  return res.status(400).json({ error: 'Content required' });
335
344
  }
336
345
 
337
346
  const hash = computeContentHash(content);
338
-
347
+
339
348
  res.json({
340
349
  hash,
341
350
  exists: contentStore.has(hash),
package/content/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * YAKMESH™ Content Module
3
- * Content-addressed storage with public delivery
3
+ * Content-addressed storage with integrity verification
4
4
  *
5
5
  * @module content
6
6
  * @license MIT
@@ -12,8 +12,8 @@ export {
12
12
  ContentType,
13
13
  ContentStatus,
14
14
  ContentMetadata,
15
- ConsensusProof,
16
15
  computeContentHash,
16
+ deriveContentName,
17
17
  } from './store.js';
18
18
 
19
19
  export { createContentAPI } from './api.js';