llm-entropy-filter 1.1.0 → 1.2.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.
@@ -1,73 +1,77 @@
1
- {
2
- "name": "default",
3
- "version": 1,
4
- "description": "Balanced preset: safe defaults for general apps.",
5
- "thresholds": { "warn": 0.45, "block": 0.65 },
6
- "normalization": {
7
- "lowercase": true,
8
- "trim": true,
9
- "collapse_whitespace": true,
10
- "unicode_nfkc": true
11
- },
12
- "hard_triggers": [
13
- {
14
- "id": "shouting",
15
- "type": "signal",
16
- "weight": 0.18,
17
- "notes": "Excess uppercase or repeated punctuation",
18
- "patterns": ["[A-ZÁÉÍÓÚÑ]{6,}", "!!+", "\\?\\?+", "¡¡+", "…{3,}"]
19
- },
20
- {
21
- "id": "urgency",
22
- "type": "topic_hint",
23
- "weight": 0.12,
24
- "patterns": ["\\bnow\\b", "\\btoday\\b", "\\burgent\\b", "\\bya\\b", "\\bahora\\b", "\\bhoy\\b", "\\búltim[oa]s?\\b", "\\bsolo\\s+hoy\\b"]
25
- },
26
- {
27
- "id": "money_signal",
28
- "type": "topic_hint",
29
- "weight": 0.12,
30
- "patterns": ["\\$\\d+", "\\bUSD\\b", "\\bMXN\\b", "\\b%\\b", "\\b90%\\b", "\\bfree\\b", "\\bgratis\\b", "\\bpromo\\b", "\\bdiscount\\b", "\\boffer\\b", "\\boferta\\b"]
31
- },
32
- {
33
- "id": "conspiracy_vague",
34
- "type": "topic_hint",
35
- "weight": 0.14,
36
- "patterns": ["\\ball\\s+hide\\b", "\\bthey\\s+hide\\b", "\\beveryone\\s+knows\\b", "\\btodos\\s+lo\\s+esconden\\b", "\\bla\\s+verdad\\s+oculta\\b", "\\bnadie\\s+quiere\\s+que\\s+sepas\\b"]
37
- }
38
- ],
39
- "topics": [
40
- {
41
- "id": "marketing_spam",
42
- "weight": 0.35,
43
- "signals": [
44
- { "id": "cta", "weight": 0.18, "patterns": ["\\bclick\\b", "\\bclaim\\b", "\\bbuy\\b", "\\bcompra\\b", "\\borden(a|e)\\b"] },
45
- { "id": "promo_terms", "weight": 0.15, "patterns": ["\\bfree\\b", "\\bgratis\\b", "\\bwin\\b", "\\bganaste\\b", "\\biphone\\b", "\\bpremio\\b"] },
46
- { "id": "links", "weight": 0.12, "patterns": ["https?://", "www\\.", "\\bbit\\.ly\\b"] }
47
- ]
48
- },
49
- {
50
- "id": "coercion",
51
- "weight": 0.25,
52
- "signals": [
53
- { "id": "threat", "weight": 0.18, "patterns": ["\\bor\\s+else\\b", "\\bsi\\s+no\\b", "\\bte\\s+voy\\s+a\\b", "\\bI\\s+will\\b"] },
54
- { "id": "forced_tone", "weight": 0.12, "patterns": ["\\bdo\\s+it\\b", "\\bhazlo\\b", "\\bahora\\b"] }
55
- ]
56
- },
57
- {
58
- "id": "conspiracy",
59
- "weight": 0.25,
60
- "signals": [
61
- { "id": "vague_all", "weight": 0.18, "patterns": ["\\btodos\\b", "\\beveryone\\b", "\\bthey\\b", "\\bel\\s+sistema\\b"] },
62
- { "id": "hidden_truth", "weight": 0.14, "patterns": ["\\bocult\\w+\\b", "\\bhidden\\b", "\\bsecret\\b", "\\bcover\\s*up\\b"] }
63
- ]
64
- },
65
- {
66
- "id": "broken_causality",
67
- "weight": 0.15,
68
- "signals": [
69
- { "id": "contradiction_markers", "weight": 0.12, "patterns": ["\\bpero\\s+entonces\\b", "\\btherefore\\b.*\\bnot\\b", "\\bsi\\s+A\\s+entonces\\s+no\\s+A\\b"] }
70
- ]
71
- }
72
- ]
73
- }
1
+ {
2
+ "name": "default",
3
+ "version": 1,
4
+ "description": "Balanced preset: safe defaults for general apps.",
5
+ "thresholds": { "warn": 0.45, "block": 0.65 },
6
+ "policy": { "strong_spam_block": false },
7
+
8
+ "normalization": {
9
+ "lowercase": true,
10
+ "trim": true,
11
+ "collapse_whitespace": true,
12
+ "unicode_nfkc": true
13
+ },
14
+ "hard_triggers": [
15
+ {
16
+ "id": "shouting",
17
+ "type": "signal",
18
+ "weight": 0.18,
19
+ "notes": "Excess uppercase or repeated punctuation",
20
+ "patterns": ["[A-ZÁÉÍÓÚÑ]{6,}", "!!+", "\\?\\?+", "¡¡+", "…{3,}"]
21
+ },
22
+ {
23
+ "id": "urgency",
24
+ "type": "topic_hint",
25
+ "weight": 0.12,
26
+ "patterns": ["\\bnow\\b", "\\btoday\\b", "\\burgent\\b", "\\bya\\b", "\\bahora\\b", "\\bhoy\\b", "\\búltim[oa]s?\\b", "\\bsolo\\s+hoy\\b"]
27
+ },
28
+ {
29
+ "id": "money_signal",
30
+ "type": "topic_hint",
31
+ "weight": 0.12,
32
+ "patterns": ["\\$\\d+", "\\bUSD\\b", "\\bMXN\\b", "\\b%\\b", "\\b90%\\b", "\\bfree\\b", "\\bgratis\\b", "\\bpromo\\b", "\\bdiscount\\b", "\\boffer\\b", "\\boferta\\b"]
33
+ },
34
+ {
35
+ "id": "conspiracy_vague",
36
+ "type": "topic_hint",
37
+ "weight": 0.14,
38
+ "patterns": ["\\ball\\s+hide\\b", "\\bthey\\s+hide\\b", "\\beveryone\\s+knows\\b", "\\btodos\\s+lo\\s+esconden\\b", "\\bla\\s+verdad\\s+oculta\\b", "\\bnadie\\s+quiere\\s+que\\s+sepas\\b"]
39
+ }
40
+ ],
41
+ "topics": [
42
+ {
43
+ "id": "marketing_spam",
44
+ "weight": 0.35,
45
+ "signals": [
46
+ { "id": "cta", "weight": 0.18, "patterns": ["\\bclick\\b", "\\bclaim\\b", "\\bbuy\\b", "\\bcompra\\b", "\\borden(a|e)\\b"] },
47
+ { "id": "promo_terms", "weight": 0.15, "patterns": ["\\bfree\\b", "\\bgratis\\b", "\\bwin\\b", "\\bganaste\\b", "\\biphone\\b", "\\bpremio\\b"] },
48
+ { "id": "links", "weight": 0.12, "patterns": ["https?://", "www\\.", "\\bbit\\.ly\\b"] }
49
+ ]
50
+ },
51
+ {
52
+ "id": "coercion",
53
+ "weight": 0.25,
54
+ "signals": [
55
+ { "id": "threat", "weight": 0.18, "patterns": ["\\bor\\s+else\\b", "\\bsi\\s+no\\b", "\\bte\\s+voy\\s+a\\b", "\\bI\\s+will\\b"] },
56
+ { "id": "forced_tone", "weight": 0.12, "patterns": ["\\bdo\\s+it\\b", "\\bhazlo\\b", "\\bahora\\b"] }
57
+ ]
58
+ },
59
+ {
60
+ "id": "conspiracy",
61
+ "weight": 0.25,
62
+ "signals": [
63
+ { "id": "vague_all", "weight": 0.18, "patterns": ["\\btodos\\b", "\\beveryone\\b", "\\bthey\\b", "\\bel\\s+sistema\\b"] },
64
+ { "id": "hidden_truth", "weight": 0.14, "patterns": ["\\bocult\\w+\\b", "\\bhidden\\b", "\\bsecret\\b", "\\bcover\\s*up\\b"] }
65
+ ]
66
+ },
67
+ {
68
+ "id": "broken_causality",
69
+ "weight": 0.15,
70
+ "signals": [
71
+ { "id": "contradiction_markers", "weight": 0.12, "patterns": ["\\bpero\\s+entonces\\b", "\\btherefore\\b.*\\bnot\\b", "\\bsi\\s+A\\s+entonces\\s+no\\s+A\\b"] }
72
+ ]
73
+ }
74
+ ]
75
+ }
76
+
77
+
@@ -0,0 +1,7 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+
4
+ const jsonPath = path.join(path.dirname(new URL(import.meta.url).pathname), "public-api.json");
5
+ const rules = JSON.parse(fs.readFileSync(jsonPath, "utf8"));
6
+
7
+ export default rules;
@@ -1,27 +1,179 @@
1
- {
2
- "name": "public-api",
3
- "version": 1,
4
- "description": "Hardened preset for open/public APIs: reduces abuse and quota burn.",
5
- "thresholds": { "warn": 0.40, "block": 0.60 },
6
- "normalization": { "lowercase": true, "trim": true, "collapse_whitespace": true, "unicode_nfkc": true },
7
- "hard_triggers": [
8
- { "id": "links", "type": "signal", "weight": 0.22, "patterns": ["https?://", "www\\.", "\\bbit\\.ly\\b", "\\bt\\.co\\b"] },
9
- { "id": "shouting", "type": "signal", "weight": 0.18, "patterns": ["[A-ZÁÉÍÓÚÑ]{5,}", "!!+", "\\?\\?+"] },
10
- { "id": "money_signal", "type": "topic_hint", "weight": 0.16, "patterns": ["\\$\\d+", "\\b%\\b", "\\bfree\\b", "\\bgratis\\b"] }
11
- ],
12
- "topics": [
13
- { "id": "marketing_spam", "weight": 0.40, "signals": [
14
- { "id": "cta", "weight": 0.20, "patterns": ["\\bclick\\b", "\\bclaim\\b", "\\bbuy\\b", "\\bcompra\\b"] },
15
- { "id": "promo", "weight": 0.18, "patterns": ["\\bfree\\b", "\\bgratis\\b", "\\bwin\\b", "\\bganaste\\b"] }
16
- ]},
17
- { "id": "coercion", "weight": 0.25, "signals": [
18
- { "id": "threat", "weight": 0.18, "patterns": ["\\bor\\s+else\\b", "\\bsi\\s+no\\b", "\\bI\\s+will\\b"] }
19
- ]},
20
- { "id": "conspiracy", "weight": 0.20, "signals": [
21
- { "id": "hidden", "weight": 0.14, "patterns": ["\\bocult\\w+\\b", "\\bhidden\\b", "\\bsecret\\b"] }
22
- ]},
23
- { "id": "incoherence", "weight": 0.15, "signals": [
24
- { "id": "noise_markers", "weight": 0.10, "patterns": ["\\bqwerty\\b", "\\basdf\\b", "([!?.])\\1{4,}"] }
25
- ]}
26
- ]
27
- }
1
+ {
2
+ "name": "public-api",
3
+ "version": 1,
4
+ "description": "Hardened preset for open/public APIs: reduces abuse and quota burn.",
5
+ "thresholds": { "warn": 0.40, "block": 0.60 },
6
+ "normalization": {
7
+ "lowercase": true,
8
+ "trim": true,
9
+ "collapse_whitespace": true,
10
+ "unicode_nfkc": true
11
+ },
12
+ "policy": {
13
+ "strong_spam_block": false,
14
+ "block_flags": ["phishing_verify_threat_en", "phishing_2fa_code"],
15
+ "warn_flags": ["fraud_payment_request", "scam_wfh"]
16
+ },
17
+ "hard_triggers": [
18
+ {
19
+ "id": "links",
20
+ "type": "signal",
21
+ "weight": 0.22,
22
+ "patterns": ["https?://", "www\\.", "\\bbit\\.ly\\b", "\\bt\\.co\\b"]
23
+ },
24
+ {
25
+ "id": "shouting",
26
+ "type": "signal",
27
+ "weight": 0.18,
28
+ "patterns": ["[A-ZÁÉÍÓÚÑ]{5,}", "!!+", "\\?\\?+"]
29
+ },
30
+ {
31
+ "id": "money_signal",
32
+ "type": "topic_hint",
33
+ "weight": 0.16,
34
+ "patterns": ["\\$\\d+", "\\b%\\b", "\\bfree\\b", "\\bgratis\\b"]
35
+ },
36
+ {
37
+ "id": "phishing_2fa_code_request_es",
38
+ "type": "topic_hint",
39
+ "weight": 0.60,
40
+ "notes": "ES: solicitud de código de verificación / 2FA (alto riesgo de phishing).",
41
+ "patterns": [
42
+ "\\bc[oó]digo\\s+de\\s+verificaci[oó]n\\b",
43
+ "\\bc[oó]digo\\s+de\\s+seguridad\\b",
44
+ "\\btoken\\s+de\\s+verificaci[oó]n\\b",
45
+ "\\bclave\\s+de\\s+verificaci[oó]n\\b",
46
+ "\\benv[ií]ame\\s+tu\\s+c[oó]digo\\b",
47
+ "\\bm[aá]ndame\\s+tu\\s+c[oó]digo\\b"
48
+ ]
49
+ },
50
+ {
51
+ "id": "fraud_card_request_es",
52
+ "type": "topic_hint",
53
+ "weight": 0.55,
54
+ "notes": "ES: solicitud de tarjeta/datos bancarios (alto riesgo de fraude).",
55
+ "patterns": [
56
+ "\\b(tarjeta|n[uú]mero\\s+de\\s+tarjeta)\\b",
57
+ "\\b(cv[vv]|cvc)\\b",
58
+ "\\bfecha\\s+de\\s+vencimiento\\b",
59
+ "\\bpor\\s+mensaje\\s+tu\\s+tarjeta\\b",
60
+ "\\bm[aá]ndame\\s+tu\\s+tarjeta\\b",
61
+ "\\benv[ií]ame\\s+tu\\s+tarjeta\\b"
62
+ ]
63
+ },
64
+ {
65
+ "id": "phish_account_threat_en",
66
+ "type": "topic_hint",
67
+ "weight": 0.35,
68
+ "notes": "EN: verify account + threat of closure (phishing-ish).",
69
+ "patterns": [
70
+ "\\bverify\\s+your\\s+account\\b.*\\b(closed|suspended|disabled)\\b",
71
+ "\\bor\\s+it\\s+will\\s+be\\s+(closed|suspended|disabled)\\b"
72
+ ]
73
+ },
74
+ {
75
+ "id": "scam_easy_money_es",
76
+ "type": "topic_hint",
77
+ "weight": 0.45,
78
+ "notes": "ES: estafa típica de dinero fácil / desde casa.",
79
+ "patterns": [
80
+ "gana\\s+dinero\\s+desde\\s+casa",
81
+ "sin\\s+esfuerzo",
82
+ "ingresos\\s+pasivos",
83
+ "dinero\\s+f[aá]cil"
84
+ ]
85
+ }
86
+ ],
87
+ "topics": [
88
+ {
89
+ "id": "marketing_spam",
90
+ "weight": 0.4,
91
+ "signals": [
92
+ {
93
+ "id": "cta",
94
+ "weight": 0.2,
95
+ "patterns": ["\\bclick\\b", "\\bclaim\\b", "\\bbuy\\b", "\\bcompra\\b"]
96
+ },
97
+ {
98
+ "id": "promo",
99
+ "weight": 0.18,
100
+ "patterns": ["\\bfree\\b", "\\bgratis\\b", "\\bwin\\b", "\\bganaste\\b"]
101
+ }
102
+ ]
103
+ },
104
+ {
105
+ "id": "coercion",
106
+ "weight": 0.25,
107
+ "signals": [
108
+ {
109
+ "id": "threat",
110
+ "weight": 0.18,
111
+ "patterns": ["\\bor\\s+else\\b", "\\bsi\\s+no\\b", "\\bI\\s+will\\b"]
112
+ }
113
+ ]
114
+ },
115
+ {
116
+ "id": "conspiracy",
117
+ "weight": 0.2,
118
+ "signals": [
119
+ {
120
+ "id": "hidden",
121
+ "weight": 0.14,
122
+ "patterns": ["\\bocult\\w+\\b", "\\bhidden\\b", "\\bsecret\\b"]
123
+ }
124
+ ]
125
+ },
126
+ {
127
+ "id": "incoherence",
128
+ "weight": 0.15,
129
+ "signals": [
130
+ {
131
+ "id": "noise_markers",
132
+ "weight": 0.1,
133
+ "patterns": ["\\bqwerty\\b", "\\basdf\\b", "([!?.])\\1{4,}"]
134
+ }
135
+ ]
136
+ },
137
+ {
138
+ "id": "phishing_fraud",
139
+ "weight": 0.45,
140
+ "signals": [
141
+ {
142
+ "id": "verify_account_request",
143
+ "weight": 0.3,
144
+ "patterns": [
145
+ "\\bverify\\s+your\\s+account\\b",
146
+ "\\bconfirm\\s+your\\s+account\\b",
147
+ "\\baccount\\s+will\\s+be\\s+closed\\b",
148
+ "\\bcódigo\\s+de\\s+verificación\\b",
149
+ "\\benvíame\\s+tu\\s+código\\b",
150
+ "\\bconfirma\\s+tu\\s+cuenta\\b"
151
+ ]
152
+ },
153
+ {
154
+ "id": "financial_data_request",
155
+ "weight": 0.35,
156
+ "patterns": [
157
+ "\\bmandas\\s+tu\\s+tarjeta\\b",
158
+ "\\benvía\\s+tu\\s+tarjeta\\b",
159
+ "\\bsend\\s+me\\s+your\\s+card\\b",
160
+ "\\btransferencia\\b",
161
+ "\\bwire\\b",
162
+ "\\bdeposito\\b",
163
+ "\\bdepósito\\b"
164
+ ]
165
+ },
166
+ {
167
+ "id": "easy_money_scam",
168
+ "weight": 0.25,
169
+ "patterns": [
170
+ "\\bgana\\s+dinero\\s+desde\\s+casa\\b",
171
+ "\\bearn\\s+money\\s+from\\s+home\\b",
172
+ "\\bsin\\s+esfuerzo\\b",
173
+ "\\bno\\s+experience\\s+needed\\b"
174
+ ]
175
+ }
176
+ ]
177
+ }
178
+ ]
179
+ }
package/rulesets/schema CHANGED
@@ -1,24 +1,24 @@
1
- {
2
- "name": "default",
3
- "version": 1,
4
- "description": "Balanced preset",
5
- "thresholds": { "warn": 0.45, "block": 0.65 },
6
- "hard_triggers": [
7
- { "id": "shouting", "type": "pattern", "weight": 0.20, "patterns": ["..."] }
8
- ],
9
- "topics": [
10
- {
11
- "id": "marketing_spam",
12
- "weight": 0.25,
13
- "signals": [
14
- { "id": "money_signal", "weight": 0.10, "patterns": ["..."] }
15
- ]
16
- }
17
- ],
18
- "normalization": {
19
- "lowercase": true,
20
- "trim": true,
21
- "collapse_whitespace": true,
22
- "unicode_nfkc": true
23
- }
24
- }
1
+ {
2
+ "name": "default",
3
+ "version": 1,
4
+ "description": "Balanced preset",
5
+ "thresholds": { "warn": 0.45, "block": 0.65 },
6
+ "hard_triggers": [
7
+ { "id": "shouting", "type": "pattern", "weight": 0.20, "patterns": ["..."] }
8
+ ],
9
+ "topics": [
10
+ {
11
+ "id": "marketing_spam",
12
+ "weight": 0.25,
13
+ "signals": [
14
+ { "id": "money_signal", "weight": 0.10, "patterns": ["..."] }
15
+ ]
16
+ }
17
+ ],
18
+ "normalization": {
19
+ "lowercase": true,
20
+ "trim": true,
21
+ "collapse_whitespace": true,
22
+ "unicode_nfkc": true
23
+ }
24
+ }
@@ -0,0 +1,7 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+
4
+ const jsonPath = path.join(path.dirname(new URL(import.meta.url).pathname), "strict.json");
5
+ const rules = JSON.parse(fs.readFileSync(jsonPath, "utf8"));
6
+
7
+ export default rules;
@@ -1,25 +1,173 @@
1
- {
2
- "name": "strict",
3
- "version": 1,
4
- "description": "Aggressive preset for public endpoints and high-abuse environments.",
5
- "thresholds": { "warn": 0.35, "block": 0.55 },
6
- "normalization": { "lowercase": true, "trim": true, "collapse_whitespace": true, "unicode_nfkc": true },
7
- "hard_triggers": [
8
- { "id": "shouting", "type": "signal", "weight": 0.22, "patterns": ["[A-ZÁÉÍÓÚÑ]{5,}", "!!+", "\\?\\?+", "¡¡+"] },
9
- { "id": "money_signal", "type": "topic_hint", "weight": 0.18, "patterns": ["\\$\\d+", "\\b%\\b", "\\bfree\\b", "\\bgratis\\b"] },
10
- { "id": "links", "type": "signal", "weight": 0.20, "patterns": ["https?://", "www\\.", "\\bbit\\.ly\\b"] },
11
- { "id": "conspiracy_vague", "type": "topic_hint", "weight": 0.18, "patterns": ["\\btodos\\s+lo\\s+esconden\\b", "\\btruth\\s+is\\s+hidden\\b"] }
12
- ],
13
- "topics": [
14
- { "id": "marketing_spam", "weight": 0.45, "signals": [
15
- { "id": "cta", "weight": 0.22, "patterns": ["\\bclick\\b", "\\bclaim\\b", "\\bbuy\\b", "\\bcompra\\b"] },
16
- { "id": "promo", "weight": 0.18, "patterns": ["\\bwin\\b", "\\bganaste\\b", "\\bgratis\\b", "\\bfree\\b"] }
17
- ]},
18
- { "id": "coercion", "weight": 0.30, "signals": [
19
- { "id": "threat", "weight": 0.22, "patterns": ["\\bor\\s+else\\b", "\\bsi\\s+no\\b", "\\bI\\s+will\\b", "\\bte\\s+voy\\s+a\\b"] }
20
- ]},
21
- { "id": "conspiracy", "weight": 0.25, "signals": [
22
- { "id": "hidden", "weight": 0.20, "patterns": ["\\bocult\\w+\\b", "\\bhidden\\b", "\\bsecret\\b"] }
23
- ]}
24
- ]
25
- }
1
+ {
2
+ "name": "strict",
3
+ "version": 1,
4
+ "description": "Aggressive preset for public endpoints and high-abuse environments.",
5
+ "thresholds": { "warn": 0.35, "block": 0.55 },
6
+ "normalization": {
7
+ "lowercase": true,
8
+ "trim": true,
9
+ "collapse_whitespace": true,
10
+ "unicode_nfkc": true
11
+ },
12
+ "policy": {
13
+ "strong_spam_block": false,
14
+ "block_flags": ["fraud_payment_request", "scam_wfh", "phishing_verify_threat_en", "phishing_2fa_code"]
15
+ },
16
+ "hard_triggers": [
17
+ {
18
+ "id": "shouting",
19
+ "type": "signal",
20
+ "weight": 0.22,
21
+ "patterns": ["[A-ZÁÉÍÓÚÑ]{5,}", "!!+", "\\?\\?+", "¡¡+"]
22
+ },
23
+ {
24
+ "id": "money_signal",
25
+ "type": "topic_hint",
26
+ "weight": 0.18,
27
+ "patterns": ["\\$\\d+", "\\b%\\b", "\\bfree\\b", "\\bgratis\\b"]
28
+ },
29
+ {
30
+ "id": "links",
31
+ "type": "signal",
32
+ "weight": 0.2,
33
+ "patterns": ["https?://", "www\\.", "\\bbit\\.ly\\b"]
34
+ },
35
+ {
36
+ "id": "conspiracy_vague",
37
+ "type": "topic_hint",
38
+ "weight": 0.18,
39
+ "patterns": ["\\btodos\\s+lo\\s+esconden\\b", "\\btruth\\s+is\\s+hidden\\b"]
40
+ },
41
+ {
42
+ "id": "phishing_2fa_code_request_es",
43
+ "type": "topic_hint",
44
+ "weight": 0.60,
45
+ "notes": "ES: solicitud de código de verificación / 2FA (alto riesgo de phishing).",
46
+ "patterns": [
47
+ "\\bc[oó]digo\\s+de\\s+verificaci[oó]n\\b",
48
+ "\\bc[oó]digo\\s+de\\s+seguridad\\b",
49
+ "\\btoken\\s+de\\s+verificaci[oó]n\\b",
50
+ "\\bclave\\s+de\\s+verificaci[oó]n\\b",
51
+ "\\benv[ií]ame\\s+tu\\s+c[oó]digo\\b",
52
+ "\\bm[aá]ndame\\s+tu\\s+c[oó]digo\\b"
53
+ ]
54
+ },
55
+ {
56
+ "id": "fraud_card_request_es",
57
+ "type": "topic_hint",
58
+ "weight": 0.55,
59
+ "notes": "ES: solicitud de tarjeta/datos bancarios (alto riesgo de fraude).",
60
+ "patterns": [
61
+ "\\b(tarjeta|n[uú]mero\\s+de\\s+tarjeta)\\b",
62
+ "\\b(cv[vv]|cvc)\\b",
63
+ "\\bfecha\\s+de\\s+vencimiento\\b",
64
+ "\\bpor\\s+mensaje\\s+tu\\s+tarjeta\\b",
65
+ "\\bm[aá]ndame\\s+tu\\s+tarjeta\\b",
66
+ "\\benv[ií]ame\\s+tu\\s+tarjeta\\b"
67
+ ]
68
+ },
69
+ {
70
+ "id": "phish_account_threat_en",
71
+ "type": "topic_hint",
72
+ "weight": 0.35,
73
+ "notes": "EN: verify account + threat of closure (phishing-ish).",
74
+ "patterns": [
75
+ "\\bverify\\s+your\\s+account\\b.*\\b(closed|suspended|disabled)\\b",
76
+ "\\bor\\s+it\\s+will\\s+be\\s+(closed|suspended|disabled)\\b"
77
+ ]
78
+ },
79
+ {
80
+ "id": "scam_easy_money_es",
81
+ "type": "topic_hint",
82
+ "weight": 0.45,
83
+ "notes": "ES: estafa típica de dinero fácil / desde casa.",
84
+ "patterns": [
85
+ "gana\\s+dinero\\s+desde\\s+casa",
86
+ "sin\\s+esfuerzo",
87
+ "ingresos\\s+pasivos",
88
+ "dinero\\s+f[aá]cil"
89
+ ]
90
+ }
91
+ ],
92
+ "topics": [
93
+ {
94
+ "id": "marketing_spam",
95
+ "weight": 0.45,
96
+ "signals": [
97
+ {
98
+ "id": "cta",
99
+ "weight": 0.22,
100
+ "patterns": ["\\bclick\\b", "\\bclaim\\b", "\\bbuy\\b", "\\bcompra\\b"]
101
+ },
102
+ {
103
+ "id": "promo",
104
+ "weight": 0.18,
105
+ "patterns": ["\\bwin\\b", "\\bganaste\\b", "\\bgratis\\b", "\\bfree\\b"]
106
+ }
107
+ ]
108
+ },
109
+ {
110
+ "id": "coercion",
111
+ "weight": 0.3,
112
+ "signals": [
113
+ {
114
+ "id": "threat",
115
+ "weight": 0.22,
116
+ "patterns": ["\\bor\\s+else\\b", "\\bsi\\s+no\\b", "\\bI\\s+will\\b", "\\bte\\s+voy\\s+a\\b"]
117
+ }
118
+ ]
119
+ },
120
+ {
121
+ "id": "conspiracy",
122
+ "weight": 0.25,
123
+ "signals": [
124
+ {
125
+ "id": "hidden",
126
+ "weight": 0.2,
127
+ "patterns": ["\\bocult\\w+\\b", "\\bhidden\\b", "\\bsecret\\b"]
128
+ }
129
+ ]
130
+ },
131
+ {
132
+ "id": "phishing_fraud",
133
+ "weight": 0.45,
134
+ "signals": [
135
+ {
136
+ "id": "verify_account_request",
137
+ "weight": 0.3,
138
+ "patterns": [
139
+ "\\bverify\\s+your\\s+account\\b",
140
+ "\\bconfirm\\s+your\\s+account\\b",
141
+ "\\baccount\\s+will\\s+be\\s+closed\\b",
142
+ "\\bcódigo\\s+de\\s+verificación\\b",
143
+ "\\benvíame\\s+tu\\s+código\\b",
144
+ "\\bconfirma\\s+tu\\s+cuenta\\b"
145
+ ]
146
+ },
147
+ {
148
+ "id": "financial_data_request",
149
+ "weight": 0.35,
150
+ "patterns": [
151
+ "\\bmandas\\s+tu\\s+tarjeta\\b",
152
+ "\\benvía\\s+tu\\s+tarjeta\\b",
153
+ "\\bsend\\s+me\\s+your\\s+card\\b",
154
+ "\\btransferencia\\b",
155
+ "\\bwire\\b",
156
+ "\\bdeposito\\b",
157
+ "\\bdepósito\\b"
158
+ ]
159
+ },
160
+ {
161
+ "id": "easy_money_scam",
162
+ "weight": 0.25,
163
+ "patterns": [
164
+ "\\bgana\\s+dinero\\s+desde\\s+casa\\b",
165
+ "\\bearn\\s+money\\s+from\\s+home\\b",
166
+ "\\bsin\\s+esfuerzo\\b",
167
+ "\\bno\\s+experience\\s+needed\\b"
168
+ ]
169
+ }
170
+ ]
171
+ }
172
+ ]
173
+ }
@@ -0,0 +1,7 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+
4
+ const jsonPath = path.join(path.dirname(new URL(import.meta.url).pathname), "support.json");
5
+ const rules = JSON.parse(fs.readFileSync(jsonPath, "utf8"));
6
+
7
+ export default rules;