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,517 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DHARMA Content Moderation Module
|
|
3
|
+
*
|
|
4
|
+
* Universal behavior-based content moderation for Yakmesh.
|
|
5
|
+
* Filters ACTIONS, not IDENTITIES.
|
|
6
|
+
*
|
|
7
|
+
* Philosophy:
|
|
8
|
+
* - No religious, ethnic, or identity-based discrimination
|
|
9
|
+
* - Focus on harmful BEHAVIORS: violence, exploitation, terrorism
|
|
10
|
+
* - Transparent criteria published openly
|
|
11
|
+
* - Host sovereignty: operators may extend locally
|
|
12
|
+
*
|
|
13
|
+
* @module security/dharma-moderation.js
|
|
14
|
+
* @version 3.0.0
|
|
15
|
+
* @license MIT
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { createHash } from 'crypto';
|
|
19
|
+
import { EventEmitter } from 'events';
|
|
20
|
+
|
|
21
|
+
// ============================================================
|
|
22
|
+
// PROHIBITED CONTENT CATEGORIES
|
|
23
|
+
// ============================================================
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Content categories that are universally prohibited.
|
|
27
|
+
* These target BEHAVIORS and ACTIONS, not identities.
|
|
28
|
+
*/
|
|
29
|
+
export const PROHIBITED_CATEGORIES = Object.freeze({
|
|
30
|
+
// Violence & Harm
|
|
31
|
+
VIOLENCE_INCITEMENT: {
|
|
32
|
+
id: 'violence-incitement',
|
|
33
|
+
severity: 'critical',
|
|
34
|
+
description: 'Content that directly incites violence against individuals or groups',
|
|
35
|
+
keywords: [
|
|
36
|
+
'kill them', 'murder them', 'exterminate', 'genocide', 'ethnic cleansing',
|
|
37
|
+
'mass shooting', 'bomb them', 'eradicate', 'purge them'
|
|
38
|
+
],
|
|
39
|
+
patterns: [
|
|
40
|
+
/\b(kill|murder|shoot|stab|bomb)\s+(all|every|the)\s+\w+s?\b/i,
|
|
41
|
+
/\bdeath\s+to\s+\w+\b/i,
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
TERRORISM_PROMOTION: {
|
|
46
|
+
id: 'terrorism-promotion',
|
|
47
|
+
severity: 'critical',
|
|
48
|
+
description: 'Content that promotes, glorifies or recruits for terrorism',
|
|
49
|
+
keywords: [
|
|
50
|
+
'join isis', 'join al-qaeda', 'jihad against', 'martyrdom operation',
|
|
51
|
+
'suicide bombing', 'terrorist attack', 'terror cell'
|
|
52
|
+
],
|
|
53
|
+
patterns: [
|
|
54
|
+
/\bterror(ist)?\s+(attack|cell|group|organization)\b/i,
|
|
55
|
+
/\brecruit.*for.*terror/i,
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
WEAPONS_INSTRUCTIONS: {
|
|
60
|
+
id: 'weapons-instructions',
|
|
61
|
+
severity: 'high',
|
|
62
|
+
description: 'Detailed instructions for creating weapons of mass harm',
|
|
63
|
+
keywords: [
|
|
64
|
+
'how to make bomb', 'pipe bomb instructions', 'ricin recipe',
|
|
65
|
+
'anthrax creation', 'sarin synthesis', 'nerve agent'
|
|
66
|
+
],
|
|
67
|
+
patterns: [
|
|
68
|
+
/\bhow\s+to\s+(make|build|create)\s+(a\s+)?(bomb|explosive|poison)/i,
|
|
69
|
+
/\b(detailed|step.by.step)\s+instructions?\s+for\s+(bomb|weapon)/i,
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
// Exploitation
|
|
74
|
+
CHILD_EXPLOITATION: {
|
|
75
|
+
id: 'child-exploitation',
|
|
76
|
+
severity: 'critical',
|
|
77
|
+
description: 'Any content that sexualizes or exploits minors',
|
|
78
|
+
keywords: [
|
|
79
|
+
'csam', 'child porn', 'pedo', 'minor explicit',
|
|
80
|
+
'underage sex', 'child abuse material'
|
|
81
|
+
],
|
|
82
|
+
patterns: [
|
|
83
|
+
/\b(child|minor|underage)\s+(porn|sex|explicit|nude)/i,
|
|
84
|
+
/\bcp\b.*\b(material|content|images)/i,
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
HUMAN_TRAFFICKING: {
|
|
89
|
+
id: 'human-trafficking',
|
|
90
|
+
severity: 'critical',
|
|
91
|
+
description: 'Content facilitating human trafficking or slavery',
|
|
92
|
+
keywords: [
|
|
93
|
+
'buy slaves', 'sell humans', 'traffick women', 'traffick children',
|
|
94
|
+
'sex slavery', 'forced labor market'
|
|
95
|
+
],
|
|
96
|
+
patterns: [
|
|
97
|
+
/\b(buy|sell|trade)\s+(slaves?|humans?|people)\b/i,
|
|
98
|
+
/\btraffick(ing)?\s+(women|children|people)\b/i,
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
// Harmful Instructions
|
|
103
|
+
SELF_HARM_PROMOTION: {
|
|
104
|
+
id: 'self-harm-promotion',
|
|
105
|
+
severity: 'high',
|
|
106
|
+
description: 'Content that promotes or provides methods for self-harm or suicide',
|
|
107
|
+
keywords: [
|
|
108
|
+
'how to kill yourself', 'suicide methods', 'best way to die',
|
|
109
|
+
'pro-ana', 'pro-mia', 'cutting tutorial'
|
|
110
|
+
],
|
|
111
|
+
patterns: [
|
|
112
|
+
/\bhow\s+to\s+(kill|end)\s+(yourself|your\s+life)/i,
|
|
113
|
+
/\b(best|easy|painless)\s+(way|method)\s+to\s+die\b/i,
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
DOXXING: {
|
|
118
|
+
id: 'doxxing',
|
|
119
|
+
severity: 'high',
|
|
120
|
+
description: 'Publishing private information to enable harassment',
|
|
121
|
+
keywords: [
|
|
122
|
+
'home address of', 'personal phone', 'doxx this person',
|
|
123
|
+
'leak their info', 'find where they live'
|
|
124
|
+
],
|
|
125
|
+
patterns: [
|
|
126
|
+
/\b(doxx|dox)\s+(this|them|him|her)\b/i,
|
|
127
|
+
/\bpost\s+(their|his|her)\s+(address|phone|ssn)\b/i,
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
// Fraud & Scams
|
|
132
|
+
FINANCIAL_FRAUD: {
|
|
133
|
+
id: 'financial-fraud',
|
|
134
|
+
severity: 'medium',
|
|
135
|
+
description: 'Content promoting financial scams or fraud schemes',
|
|
136
|
+
keywords: [
|
|
137
|
+
'steal credit cards', 'carding tutorial', 'phishing kit',
|
|
138
|
+
'identity theft', 'bank fraud', 'money laundering'
|
|
139
|
+
],
|
|
140
|
+
patterns: [
|
|
141
|
+
/\b(steal|hack)\s+(credit\s+cards?|bank\s+accounts?)\b/i,
|
|
142
|
+
/\b(carding|phishing)\s+(tutorial|guide|kit)\b/i,
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
// Specific Harmful Rituals
|
|
147
|
+
HUMAN_SACRIFICE: {
|
|
148
|
+
id: 'human-sacrifice',
|
|
149
|
+
severity: 'critical',
|
|
150
|
+
description: 'Content promoting or instructing human sacrifice rituals',
|
|
151
|
+
keywords: [
|
|
152
|
+
'human sacrifice ritual', 'blood sacrifice human', 'sacrificial killing',
|
|
153
|
+
'ritual murder', 'sacrifice a person'
|
|
154
|
+
],
|
|
155
|
+
patterns: [
|
|
156
|
+
/\bhuman\s+sacrifice\b/i,
|
|
157
|
+
/\bsacrifice\s+(a\s+)?(person|child|human|victim)\b/i,
|
|
158
|
+
/\britual\s+(murder|killing|sacrifice)\b/i,
|
|
159
|
+
]
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Severity levels for moderation actions
|
|
165
|
+
*/
|
|
166
|
+
export const SEVERITY_LEVELS = Object.freeze({
|
|
167
|
+
CRITICAL: 'critical', // Immediate block, report to authorities option
|
|
168
|
+
HIGH: 'high', // Block content, flag for review
|
|
169
|
+
MEDIUM: 'medium', // Flag for review, allow with warning
|
|
170
|
+
LOW: 'low', // Log only, allow
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Moderation actions
|
|
175
|
+
*/
|
|
176
|
+
export const MODERATION_ACTIONS = Object.freeze({
|
|
177
|
+
BLOCK: 'block', // Prevent content from being distributed
|
|
178
|
+
FLAG: 'flag', // Allow but mark for review
|
|
179
|
+
WARN: 'warn', // Allow with warning to user
|
|
180
|
+
LOG: 'log', // Silent logging only
|
|
181
|
+
ALLOW: 'allow', // No action
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// ============================================================
|
|
185
|
+
// DHARMA MODERATOR CLASS
|
|
186
|
+
// ============================================================
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* DharmaModerator - Universal behavior-based content moderation
|
|
190
|
+
*
|
|
191
|
+
* Named after the concept of righteous conduct across traditions.
|
|
192
|
+
* Enforces ethical behavior standards without religious discrimination.
|
|
193
|
+
*/
|
|
194
|
+
export class DharmaModerator extends EventEmitter {
|
|
195
|
+
/**
|
|
196
|
+
* Create a new DharmaModerator instance
|
|
197
|
+
* @param {Object} config - Configuration options
|
|
198
|
+
*/
|
|
199
|
+
constructor(config = {}) {
|
|
200
|
+
super();
|
|
201
|
+
|
|
202
|
+
this.config = {
|
|
203
|
+
// Default severity thresholds
|
|
204
|
+
blockThreshold: SEVERITY_LEVELS.HIGH,
|
|
205
|
+
flagThreshold: SEVERITY_LEVELS.MEDIUM,
|
|
206
|
+
|
|
207
|
+
// Enable/disable categories
|
|
208
|
+
enabledCategories: Object.keys(PROHIBITED_CATEGORIES),
|
|
209
|
+
|
|
210
|
+
// Custom patterns (host sovereignty)
|
|
211
|
+
customPatterns: [],
|
|
212
|
+
|
|
213
|
+
// Logging
|
|
214
|
+
logLevel: 'info',
|
|
215
|
+
|
|
216
|
+
// Rate limiting for moderation checks
|
|
217
|
+
maxChecksPerMinute: 1000,
|
|
218
|
+
|
|
219
|
+
...config,
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
this.checkCount = 0;
|
|
223
|
+
this.lastCheckReset = Date.now();
|
|
224
|
+
|
|
225
|
+
// Build pattern index for performance
|
|
226
|
+
this._buildPatternIndex();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Build optimized pattern index from categories
|
|
231
|
+
* @private
|
|
232
|
+
*/
|
|
233
|
+
_buildPatternIndex() {
|
|
234
|
+
this.patternIndex = new Map();
|
|
235
|
+
|
|
236
|
+
for (const [categoryKey, category] of Object.entries(PROHIBITED_CATEGORIES)) {
|
|
237
|
+
if (!this.config.enabledCategories.includes(categoryKey)) continue;
|
|
238
|
+
|
|
239
|
+
// Add keyword patterns (word boundary wrapped, metacharacters escaped)
|
|
240
|
+
for (const keyword of category.keywords) {
|
|
241
|
+
const escaped = keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
242
|
+
const pattern = new RegExp('\\b' + escaped.replace(/\s+/g, '\\s+') + '\\b', 'i');
|
|
243
|
+
this.patternIndex.set(pattern, { category, match: 'keyword', original: keyword });
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Add regex patterns
|
|
247
|
+
for (const pattern of category.patterns) {
|
|
248
|
+
this.patternIndex.set(pattern, { category, match: 'pattern' });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Add custom patterns
|
|
253
|
+
for (const custom of this.config.customPatterns) {
|
|
254
|
+
this.patternIndex.set(
|
|
255
|
+
custom.pattern,
|
|
256
|
+
{ category: custom, match: 'custom' }
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Check content against moderation rules
|
|
263
|
+
* @param {string} content - Content to check
|
|
264
|
+
* @param {Object} context - Optional context (adapterId, userId, etc.)
|
|
265
|
+
* @returns {Object} Moderation result
|
|
266
|
+
*/
|
|
267
|
+
async checkContent(content, context = {}) {
|
|
268
|
+
// Rate limiting
|
|
269
|
+
this._checkRateLimit();
|
|
270
|
+
|
|
271
|
+
if (!content || typeof content !== 'string') {
|
|
272
|
+
return this._createResult(MODERATION_ACTIONS.ALLOW, null, content);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const normalizedContent = this._normalizeContent(content);
|
|
276
|
+
const violations = [];
|
|
277
|
+
|
|
278
|
+
// Check against all patterns
|
|
279
|
+
for (const [pattern, info] of this.patternIndex) {
|
|
280
|
+
if (pattern.test(normalizedContent)) {
|
|
281
|
+
violations.push({
|
|
282
|
+
categoryId: info.category.id,
|
|
283
|
+
severity: info.category.severity,
|
|
284
|
+
matchType: info.match,
|
|
285
|
+
pattern: info.original || pattern.source,
|
|
286
|
+
description: info.category.description,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Determine action based on violations
|
|
292
|
+
const result = this._determineAction(violations, content, context);
|
|
293
|
+
|
|
294
|
+
// Emit events for logging/analysis
|
|
295
|
+
if (result.action !== MODERATION_ACTIONS.ALLOW) {
|
|
296
|
+
this.emit('violation', {
|
|
297
|
+
result,
|
|
298
|
+
context,
|
|
299
|
+
timestamp: Date.now(),
|
|
300
|
+
contentHash: this._hashContent(content),
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return result;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Batch check multiple content items
|
|
309
|
+
* @param {string[]} contents - Array of content strings
|
|
310
|
+
* @param {Object} context - Shared context
|
|
311
|
+
* @returns {Object[]} Array of moderation results
|
|
312
|
+
*/
|
|
313
|
+
async checkBatch(contents, context = {}) {
|
|
314
|
+
return Promise.all(
|
|
315
|
+
contents.map(content => this.checkContent(content, context))
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Normalize content for consistent matching
|
|
321
|
+
* @private
|
|
322
|
+
*/
|
|
323
|
+
_normalizeContent(content) {
|
|
324
|
+
return content
|
|
325
|
+
.toLowerCase()
|
|
326
|
+
// Remove excessive whitespace
|
|
327
|
+
.replace(/\s+/g, ' ')
|
|
328
|
+
// Remove common obfuscation
|
|
329
|
+
.replace(/[0-9@$!]/g, match => {
|
|
330
|
+
const map = { '0': 'o', '@': 'a', '$': 's', '!': 'i', '1': 'i', '3': 'e' };
|
|
331
|
+
return map[match] || match;
|
|
332
|
+
})
|
|
333
|
+
.trim();
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Create a moderation result object
|
|
338
|
+
* @private
|
|
339
|
+
*/
|
|
340
|
+
_createResult(action, violations, content) {
|
|
341
|
+
return {
|
|
342
|
+
action,
|
|
343
|
+
allowed: action !== MODERATION_ACTIONS.BLOCK,
|
|
344
|
+
violations: violations || [],
|
|
345
|
+
violationCount: violations ? violations.length : 0,
|
|
346
|
+
timestamp: Date.now(),
|
|
347
|
+
checksum: this._hashContent(content || ''),
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Determine appropriate action based on violations
|
|
353
|
+
* @private
|
|
354
|
+
*/
|
|
355
|
+
_determineAction(violations, content, context) {
|
|
356
|
+
if (violations.length === 0) {
|
|
357
|
+
return this._createResult(MODERATION_ACTIONS.ALLOW, [], content);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Find highest severity
|
|
361
|
+
const severityOrder = [
|
|
362
|
+
SEVERITY_LEVELS.CRITICAL,
|
|
363
|
+
SEVERITY_LEVELS.HIGH,
|
|
364
|
+
SEVERITY_LEVELS.MEDIUM,
|
|
365
|
+
SEVERITY_LEVELS.LOW,
|
|
366
|
+
];
|
|
367
|
+
|
|
368
|
+
let highestSeverity = SEVERITY_LEVELS.LOW;
|
|
369
|
+
for (const violation of violations) {
|
|
370
|
+
const currentIndex = severityOrder.indexOf(violation.severity);
|
|
371
|
+
const highestIndex = severityOrder.indexOf(highestSeverity);
|
|
372
|
+
if (currentIndex < highestIndex) {
|
|
373
|
+
highestSeverity = violation.severity;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Determine action based on severity
|
|
378
|
+
let action;
|
|
379
|
+
if (highestSeverity === SEVERITY_LEVELS.CRITICAL ||
|
|
380
|
+
highestSeverity === SEVERITY_LEVELS.HIGH) {
|
|
381
|
+
action = MODERATION_ACTIONS.BLOCK;
|
|
382
|
+
} else if (highestSeverity === SEVERITY_LEVELS.MEDIUM) {
|
|
383
|
+
action = MODERATION_ACTIONS.FLAG;
|
|
384
|
+
} else {
|
|
385
|
+
action = MODERATION_ACTIONS.WARN;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
return {
|
|
389
|
+
action,
|
|
390
|
+
allowed: action !== MODERATION_ACTIONS.BLOCK,
|
|
391
|
+
violations,
|
|
392
|
+
violationCount: violations.length,
|
|
393
|
+
highestSeverity,
|
|
394
|
+
timestamp: Date.now(),
|
|
395
|
+
checksum: this._hashContent(content),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Hash content for logging without storing actual content
|
|
401
|
+
* @private
|
|
402
|
+
*/
|
|
403
|
+
_hashContent(content) {
|
|
404
|
+
return createHash('sha256')
|
|
405
|
+
.update(content.substring(0, 1000))
|
|
406
|
+
.digest('hex')
|
|
407
|
+
.substring(0, 16);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Check and enforce rate limits
|
|
412
|
+
* @private
|
|
413
|
+
*/
|
|
414
|
+
_checkRateLimit() {
|
|
415
|
+
const now = Date.now();
|
|
416
|
+
if (now - this.lastCheckReset > 60000) {
|
|
417
|
+
this.checkCount = 0;
|
|
418
|
+
this.lastCheckReset = now;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
this.checkCount++;
|
|
422
|
+
if (this.checkCount > this.config.maxChecksPerMinute) {
|
|
423
|
+
throw new Error('Rate limit exceeded for moderation checks');
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Add a custom pattern (host sovereignty feature)
|
|
429
|
+
* @param {Object} pattern - Custom pattern definition
|
|
430
|
+
*/
|
|
431
|
+
addCustomPattern(pattern) {
|
|
432
|
+
if (!pattern.pattern || !pattern.severity || !pattern.id) {
|
|
433
|
+
throw new Error('Custom pattern requires pattern, severity, and id');
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
this.config.customPatterns.push(pattern);
|
|
437
|
+
this._buildPatternIndex();
|
|
438
|
+
|
|
439
|
+
this.emit('patternAdded', { pattern });
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Get current moderation configuration
|
|
444
|
+
* @returns {Object} Current configuration (sanitized)
|
|
445
|
+
*/
|
|
446
|
+
getConfiguration() {
|
|
447
|
+
return {
|
|
448
|
+
enabledCategories: this.config.enabledCategories,
|
|
449
|
+
blockThreshold: this.config.blockThreshold,
|
|
450
|
+
flagThreshold: this.config.flagThreshold,
|
|
451
|
+
customPatternCount: this.config.customPatterns.length,
|
|
452
|
+
totalPatterns: this.patternIndex.size,
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Get human-readable category descriptions
|
|
458
|
+
* @returns {Object} Category documentation
|
|
459
|
+
*/
|
|
460
|
+
static getCategoryDocumentation() {
|
|
461
|
+
const docs = {};
|
|
462
|
+
for (const [key, category] of Object.entries(PROHIBITED_CATEGORIES)) {
|
|
463
|
+
docs[key] = {
|
|
464
|
+
id: category.id,
|
|
465
|
+
severity: category.severity,
|
|
466
|
+
description: category.description,
|
|
467
|
+
// Don't expose actual patterns publicly
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
return docs;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// ============================================================
|
|
475
|
+
// INTEGRATION HELPERS
|
|
476
|
+
// ============================================================
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Create a moderation middleware for adapters
|
|
480
|
+
* @param {DharmaModerator} moderator - Moderator instance
|
|
481
|
+
* @returns {Function} Middleware function
|
|
482
|
+
*/
|
|
483
|
+
export function createModerationMiddleware(moderator) {
|
|
484
|
+
return async (content, context, next) => {
|
|
485
|
+
const result = await moderator.checkContent(content, context);
|
|
486
|
+
|
|
487
|
+
if (!result.allowed) {
|
|
488
|
+
return {
|
|
489
|
+
blocked: true,
|
|
490
|
+
reason: 'Content violates community standards',
|
|
491
|
+
violations: result.violations.map(v => ({
|
|
492
|
+
category: v.categoryId,
|
|
493
|
+
severity: v.severity,
|
|
494
|
+
})),
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Attach moderation result to context
|
|
499
|
+
context.moderationResult = result;
|
|
500
|
+
|
|
501
|
+
return next ? next(content, context) : { allowed: true };
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Create a default moderator instance
|
|
507
|
+
* @returns {DharmaModerator} Default moderator
|
|
508
|
+
*/
|
|
509
|
+
export function createDefaultModerator() {
|
|
510
|
+
return new DharmaModerator();
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// ============================================================
|
|
514
|
+
// EXPORTED CONSTANTS
|
|
515
|
+
// ============================================================
|
|
516
|
+
|
|
517
|
+
export default DharmaModerator;
|