crucix 2.39.0 → 2.39.3

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 (244) hide show
  1. package/.env.example +151 -149
  2. package/LICENSE +661 -661
  3. package/README.md +238 -237
  4. package/apis/BRIEFING_PROMPT.md +220 -220
  5. package/apis/BRIEFING_TEMPLATE.md +106 -106
  6. package/apis/briefing.mjs +264 -264
  7. package/apis/save-briefing.mjs +27 -27
  8. package/apis/sources/acled.mjs +356 -311
  9. package/apis/sources/adsb-military.mjs +283 -283
  10. package/apis/sources/adsb-orbits.mjs +154 -154
  11. package/apis/sources/adsb.mjs +302 -302
  12. package/apis/sources/bls.mjs +199 -165
  13. package/apis/sources/bluesky.mjs +77 -77
  14. package/apis/sources/central-banks.mjs +144 -144
  15. package/apis/sources/cftc-cot.mjs +109 -109
  16. package/apis/sources/cisa-kev.mjs +144 -144
  17. package/apis/sources/cloudflare-radar.mjs +224 -224
  18. package/apis/sources/comtrade.mjs +303 -303
  19. package/apis/sources/copernicus-ems.mjs +117 -117
  20. package/apis/sources/ecb.mjs +62 -62
  21. package/apis/sources/ecdc-threats.mjs +99 -99
  22. package/apis/sources/eia.mjs +158 -158
  23. package/apis/sources/emsc.mjs +92 -92
  24. package/apis/sources/energy-charts.mjs +201 -201
  25. package/apis/sources/entsog.mjs +164 -164
  26. package/apis/sources/eonet.mjs +57 -57
  27. package/apis/sources/epa.mjs +266 -219
  28. package/apis/sources/epss.mjs +75 -75
  29. package/apis/sources/eurostat-hu.mjs +96 -96
  30. package/apis/sources/faa-airports.mjs +133 -133
  31. package/apis/sources/federal-register.mjs +148 -148
  32. package/apis/sources/finnhub.mjs +41 -41
  33. package/apis/sources/firms.mjs +157 -157
  34. package/apis/sources/fmp.mjs +109 -109
  35. package/apis/sources/fred.mjs +110 -110
  36. package/apis/sources/gdacs.mjs +75 -75
  37. package/apis/sources/gdelt.mjs +189 -189
  38. package/apis/sources/gpsjam.mjs +159 -159
  39. package/apis/sources/gscpi.mjs +165 -165
  40. package/apis/sources/hibp.mjs +105 -105
  41. package/apis/sources/inform.mjs +137 -137
  42. package/apis/sources/ioda.mjs +242 -242
  43. package/apis/sources/jma-typhoon.mjs +113 -113
  44. package/apis/sources/kiwisdr.mjs +305 -305
  45. package/apis/sources/launches.mjs +88 -88
  46. package/apis/sources/met-norway.mjs +129 -129
  47. package/apis/sources/meteoalarm.mjs +119 -119
  48. package/apis/sources/misp-galaxy.mjs +82 -82
  49. package/apis/sources/nhc.mjs +147 -147
  50. package/apis/sources/noaa.mjs +106 -106
  51. package/apis/sources/ofac.mjs +206 -206
  52. package/apis/sources/ooni.mjs +103 -103
  53. package/apis/sources/openmeteo-wind.mjs +83 -83
  54. package/apis/sources/opensanctions-index.mjs +155 -155
  55. package/apis/sources/opensanctions.mjs +112 -112
  56. package/apis/sources/opensky.mjs +271 -250
  57. package/apis/sources/patents.mjs +205 -205
  58. package/apis/sources/portwatch.mjs +183 -183
  59. package/apis/sources/prediction-markets.mjs +212 -212
  60. package/apis/sources/reddit.mjs +108 -108
  61. package/apis/sources/regulators.mjs +97 -97
  62. package/apis/sources/reliefweb.mjs +223 -223
  63. package/apis/sources/ripestat.mjs +99 -99
  64. package/apis/sources/safecast.mjs +164 -164
  65. package/apis/sources/sec-8k.mjs +152 -152
  66. package/apis/sources/ships.mjs +177 -177
  67. package/apis/sources/sigmet.mjs +189 -189
  68. package/apis/sources/space.mjs +222 -190
  69. package/apis/sources/swpc.mjs +47 -47
  70. package/apis/sources/telegram.mjs +309 -309
  71. package/apis/sources/threatfox.mjs +111 -111
  72. package/apis/sources/travel-advisories.mjs +100 -100
  73. package/apis/sources/treasury.mjs +81 -81
  74. package/apis/sources/unhcr-arrivals.mjs +131 -131
  75. package/apis/sources/usaspending.mjs +118 -118
  76. package/apis/sources/usgs.mjs +94 -94
  77. package/apis/sources/views.mjs +131 -131
  78. package/apis/sources/who.mjs +170 -170
  79. package/apis/sources/wmo-swic.mjs +119 -119
  80. package/apis/sources/yfinance.mjs +141 -141
  81. package/apis/utils/ais-collector.mjs +279 -279
  82. package/apis/utils/env.mjs +87 -87
  83. package/apis/utils/fetch.mjs +91 -87
  84. package/apis/utils/freshness.mjs +95 -95
  85. package/apis/utils/news-feeds.mjs +102 -102
  86. package/apis/utils/quota-cache.mjs +42 -0
  87. package/apis/utils/rss-pool.mjs +33 -0
  88. package/apis/utils/rss.mjs +56 -56
  89. package/apis/utils/xml.mjs +19 -19
  90. package/apis/utils/zip.mjs +42 -42
  91. package/crucix.config.mjs +209 -209
  92. package/dashboard/inject.mjs +944 -923
  93. package/dashboard/public/alert-rules.js +494 -494
  94. package/dashboard/public/alerts-core.js +48 -48
  95. package/dashboard/public/alerts.css +168 -168
  96. package/dashboard/public/alerts.js +475 -475
  97. package/dashboard/public/briefing.css +38 -38
  98. package/dashboard/public/briefing.js +171 -171
  99. package/dashboard/public/changes.css +45 -45
  100. package/dashboard/public/changes.js +331 -331
  101. package/dashboard/public/clock.js +14 -14
  102. package/dashboard/public/country.css +61 -61
  103. package/dashboard/public/country.js +259 -259
  104. package/dashboard/public/credits.js +56 -56
  105. package/dashboard/public/data/infrastructure.json +1 -1
  106. package/dashboard/public/domains.js +24 -24
  107. package/dashboard/public/embed.html +75 -75
  108. package/dashboard/public/health-matrix.css +75 -75
  109. package/dashboard/public/health-matrix.js +242 -242
  110. package/dashboard/public/infrastructure.js +186 -186
  111. package/dashboard/public/intelligence.css +63 -63
  112. package/dashboard/public/intelligence.js +341 -341
  113. package/dashboard/public/jarvis.html +3534 -3534
  114. package/dashboard/public/lens-core.js +37 -37
  115. package/dashboard/public/lens.css +13 -13
  116. package/dashboard/public/lens.js +101 -101
  117. package/dashboard/public/live-sources.css +36 -36
  118. package/dashboard/public/live-sources.js +115 -115
  119. package/dashboard/public/loading.html +169 -169
  120. package/dashboard/public/manifest.webmanifest +15 -15
  121. package/dashboard/public/palette-core.js +54 -54
  122. package/dashboard/public/palette.css +45 -45
  123. package/dashboard/public/palette.js +268 -268
  124. package/dashboard/public/pivots.js +61 -61
  125. package/dashboard/public/pwa.js +132 -132
  126. package/dashboard/public/record-core.js +153 -153
  127. package/dashboard/public/record-inspector.css +105 -105
  128. package/dashboard/public/record-inspector.js +350 -350
  129. package/dashboard/public/replay-core.js +72 -72
  130. package/dashboard/public/replay.css +33 -33
  131. package/dashboard/public/replay.js +251 -251
  132. package/dashboard/public/risk.css +35 -35
  133. package/dashboard/public/risk.js +292 -292
  134. package/dashboard/public/setup.html +1198 -1198
  135. package/dashboard/public/sw.js +52 -52
  136. package/data/world-rss/README.hu.md +324 -324
  137. package/data/world-rss/complete-world-feeds.js +6 -6
  138. package/data/world-rss/country-coverage.csv +251 -251
  139. package/data/world-rss/country-fallback-feeds.js +39 -39
  140. package/data/world-rss/country-search-feeds.js +594 -594
  141. package/data/world-rss/local-alternatives.js +610 -610
  142. package/data/world-rss/registry.json +48831 -48831
  143. package/data/world-rss/search-audit.json +241 -241
  144. package/data/world-rss/summary.json +15 -15
  145. package/data/world-rss/world-feeds.js +929 -929
  146. package/data/world-rss/world-feeds.opml +928 -928
  147. package/diag.mjs +94 -94
  148. package/lib/alerts/ask.mjs +216 -216
  149. package/lib/alerts/brief.mjs +85 -85
  150. package/lib/alerts/discord.mjs +661 -661
  151. package/lib/alerts/engine.mjs +614 -614
  152. package/lib/alerts/evaluators.mjs +417 -417
  153. package/lib/alerts/evidence.mjs +118 -118
  154. package/lib/alerts/levels.mjs +40 -40
  155. package/lib/alerts/lifecycle.mjs +185 -185
  156. package/lib/alerts/metrics.mjs +88 -88
  157. package/lib/alerts/notify.mjs +501 -501
  158. package/lib/alerts/routes.mjs +176 -176
  159. package/lib/alerts/rules.mjs +458 -458
  160. package/lib/alerts/store.mjs +383 -383
  161. package/lib/alerts/sweep.mjs +49 -49
  162. package/lib/alerts/telegram.mjs +828 -828
  163. package/lib/api-errors.mjs +24 -24
  164. package/lib/atomic-json.mjs +83 -83
  165. package/lib/basemap.mjs +48 -48
  166. package/lib/dashboard-path.mjs +80 -80
  167. package/lib/delta/engine.mjs +251 -251
  168. package/lib/delta/index.mjs +2 -2
  169. package/lib/delta/memory.mjs +247 -247
  170. package/lib/domains.mjs +32 -32
  171. package/lib/html.mjs +4 -4
  172. package/lib/http-security.mjs +142 -142
  173. package/lib/i18n.mjs +163 -163
  174. package/lib/install-mode.mjs +9 -9
  175. package/lib/intelligence/anomalies.mjs +63 -63
  176. package/lib/intelligence/countries.mjs +225 -225
  177. package/lib/intelligence/entities.mjs +269 -269
  178. package/lib/intelligence/events.mjs +423 -423
  179. package/lib/intelligence/export.mjs +90 -90
  180. package/lib/intelligence/exposure.mjs +61 -61
  181. package/lib/intelligence/geo.mjs +109 -109
  182. package/lib/intelligence/history.mjs +368 -368
  183. package/lib/intelligence/keywords.mjs +193 -193
  184. package/lib/intelligence/live-sources.mjs +80 -80
  185. package/lib/intelligence/military-sites.mjs +51 -51
  186. package/lib/intelligence/predictions.mjs +163 -163
  187. package/lib/intelligence/risk-routes.mjs +170 -170
  188. package/lib/intelligence/risk-step.mjs +145 -145
  189. package/lib/intelligence/risk.mjs +159 -159
  190. package/lib/intelligence/routes.mjs +46 -46
  191. package/lib/intelligence/thermal.mjs +194 -194
  192. package/lib/intelligence/timeline.mjs +34 -34
  193. package/lib/llm/alert-schema.mjs +22 -22
  194. package/lib/llm/anthropic.mjs +78 -78
  195. package/lib/llm/briefing.mjs +291 -291
  196. package/lib/llm/budgets.mjs +46 -46
  197. package/lib/llm/cadence.mjs +30 -30
  198. package/lib/llm/codex.mjs +160 -160
  199. package/lib/llm/cursor.mjs +88 -78
  200. package/lib/llm/gemini.mjs +57 -57
  201. package/lib/llm/grok.mjs +56 -56
  202. package/lib/llm/idea-schema.mjs +65 -65
  203. package/lib/llm/ideas.mjs +83 -83
  204. package/lib/llm/index.mjs +68 -68
  205. package/lib/llm/json-extract.mjs +129 -129
  206. package/lib/llm/minimax.mjs +53 -53
  207. package/lib/llm/mistral.mjs +53 -53
  208. package/lib/llm/ollama.mjs +54 -54
  209. package/lib/llm/openai-compatible.mjs +66 -66
  210. package/lib/llm/openai.mjs +52 -52
  211. package/lib/llm/openrouter.mjs +54 -54
  212. package/lib/llm/provider.mjs +26 -26
  213. package/lib/llm/rule-ideas.mjs +123 -123
  214. package/lib/markets/build.mjs +68 -68
  215. package/lib/markets/fx.mjs +136 -136
  216. package/lib/news/feed-store.mjs +332 -332
  217. package/lib/news/opml.mjs +69 -69
  218. package/lib/news/routes.mjs +75 -75
  219. package/lib/offline-shell.mjs +9 -9
  220. package/lib/open-browser.mjs +18 -18
  221. package/lib/profile-install.mjs +28 -28
  222. package/lib/setup-wizard.mjs +821 -821
  223. package/lib/snapshots.mjs +13 -13
  224. package/lib/sse.mjs +22 -22
  225. package/lib/sweeps/archive.mjs +463 -463
  226. package/lib/sweeps/changes.mjs +280 -280
  227. package/lib/sweeps/routes.mjs +122 -122
  228. package/lib/sweeps/step.mjs +22 -22
  229. package/lib/user-paths.mjs +38 -38
  230. package/lib/version.mjs +22 -0
  231. package/lib/world-rss-runner.mjs +225 -213
  232. package/locales/en.json +1724 -1724
  233. package/locales/fr.json +1724 -1724
  234. package/locales/hu.json +1724 -1724
  235. package/package.json +93 -93
  236. package/scripts/benchmark-world-rss.mjs +64 -64
  237. package/scripts/check.mjs +28 -28
  238. package/scripts/clean.mjs +18 -18
  239. package/scripts/cli.mjs +13 -0
  240. package/scripts/setup.mjs +8 -8
  241. package/scripts/status.mjs +113 -113
  242. package/scripts/sync-setup-html.mjs +47 -47
  243. package/scripts/verify-assets.mjs +16 -16
  244. package/scripts/watchlist.mjs +96 -96
package/.env.example CHANGED
@@ -1,149 +1,151 @@
1
- # ============================================
2
- # Crucix Intelligence Engine — Configuration
3
- # ============================================
4
- # Copy this file to .env and fill in your keys.
5
- # Keys are optional — sources without keys degrade gracefully.
6
- #
7
- # IMPORTANT: Do NOT put comments on the same line as values.
8
- # Docker env_file treats inline comments as part of the value.
9
-
10
- # === OSINT Source API Keys ===
11
-
12
- # Federal Reserve Economic Data (free: fred.stlouisfed.org/docs/api)
13
- FRED_API_KEY=
14
- # NASA FIRMS fire data (free: firms.modaps.eosdis.nasa.gov/api)
15
- FIRMS_MAP_KEY=
16
- # Energy Information Administration (free: api.eia.gov/register)
17
- EIA_API_KEY=
18
- # Financial Modeling Prep (free: site.financialmodelingprep.com/register, 250 calls/day): equities, indexes, forex in two
19
- # batch calls per sweep (192/day at the 15-minute sweep). FMP_DAILY_LIMIT caps the calls; without a key Yahoo covers it.
20
- FMP_API_KEY=
21
- FMP_DAILY_LIMIT=250
22
- # Finnhub (free: finnhub.io/register, 60 calls/minute): second quote source for the US-listed equities
23
- FINNHUB_API_KEY=
24
- # Base currency of the FX crosses: USD | EUR | GBP | HUF | JPY | CHF | CAD | AUD | CNY (each dashboard user can switch)
25
- CRUCIX_BASE_CURRENCY=USD
26
- # Maritime live AIS (free: aisstream.io/account, sign in with GitHub). With a key the dashboard server keeps one
27
- # aisstream.io WebSocket open and reports vessels seen at 11 chokepoints in the last hour; one-shot briefings do not.
28
- # A key allows 3 connections; the service has no SLA and no written licence or terms of use (aisstream issue #290).
29
- AISSTREAM_API_KEY=
30
- # Armed Conflict Location & Event Data (acleddata.com/user/register)
31
- ACLED_EMAIL=
32
- # OAuth2 password grant (API keys deprecated Sept 2025)
33
- ACLED_PASSWORD=
34
- # OpenSky Network API client (opensky-network.org/my-opensky/account -> Create a new API client -> credentials.json)
35
- # Optional: 4,000 instead of 400 credits/day and a refresh every 15 minutes instead of 2 hours; set both or neither
36
- OPENSKY_CLIENT_ID=
37
- OPENSKY_CLIENT_SECRET=
38
- # Cloudflare Radar internet outages & traffic anomalies (free: dash.cloudflare.com/profile/api-tokens, Account Analytics Read)
39
- CLOUDFLARE_API_TOKEN=
40
-
41
- # === Server Configuration ===
42
-
43
- # Dashboard server port
44
- PORT=3117
45
- # Auto-refresh interval (minutes)
46
- REFRESH_INTERVAL_MINUTES=15
47
-
48
- # === LLM Layer (optional) ===
49
- # Enables AI-enhanced trade ideas and breaking news Telegram alerts.
50
- # Provider options: anthropic | openai | gemini | codex | openrouter | minimax | mistral | ollama | grok | openai-compatible
51
- LLM_PROVIDER=
52
- # Not needed for codex (uses ~/.codex/auth.json) or ollama (local)
53
- LLM_API_KEY=
54
- # Optional override. Each provider has a sensible default:
55
- # anthropic: claude-sonnet-4-6 | openai: gpt-5.4 | gemini: gemini-3.1-pro | codex: first model in ~/.codex/models_cache.json (gpt-6.1-sol) | openrouter: openrouter/auto | minimax: MiniMax-M2.5 | ollama: llama3.1:8b | grok: grok-4-latest
56
- LLM_MODEL=
57
- # Ollama base URL (only needed if not using default http://localhost:11434)
58
- OLLAMA_BASE_URL=
59
- # Output language for the "Trade Ideas" LLM box. Supported: en | fr | hu
60
- # Falls back to CRUCIX_LANG, then to English if unset.
61
- TRADE_IDEAS_LANG=
62
-
63
- # === Telegram Alerts (optional; rules work without LLM) ===
64
- # Create a bot via @BotFather, get chat ID via @userinfobot
65
- TELEGRAM_BOT_TOKEN=
66
- TELEGRAM_CHAT_ID=
67
- # Alerts below this tier are not sent on their own but listed in /brief: FLASH | PRIORITY | ROUTINE (default PRIORITY)
68
- TELEGRAM_ALERT_MIN_TIER=PRIORITY
69
- # Group chats: only these Telegram user ids may run bot commands, /ask included (empty = anyone in TELEGRAM_CHAT_ID)
70
- TELEGRAM_ALLOWED_USER_IDS=
71
- # Local server access (HOST=0.0.0.0 enables LAN; Docker sets this internally)
72
- HOST=127.0.0.1
73
- AUTH_USER=
74
- AUTH_PASSWORD=
75
- PUBLIC_URL=
76
- MAX_SSE_CLIENTS=100
77
- NO_AUTO_OPEN=0
78
- # Opt-in browser access from other sites (comma lists of origins like https://example.com; empty = off, see docs/API.md and docs/EMBEDDING.md)
79
- # CORS_ORIGINS: pages from these origins may READ the GET /api routes (a lone * allows any site; only sensible with AUTH_USER/AUTH_PASSWORD)
80
- CORS_ORIGINS=
81
- # EMBED_ORIGINS: pages from these origins may show the dashboard (/) or the widget (/embed.html) in an iframe
82
- EMBED_ORIGINS=
83
- # Explicit opt-in to read public Telegram previews; never private bot updates
84
- TELEGRAM_OSINT_ENABLED=false
85
- # Optional user allowlist for Discord sweep/mute/unmute/ask (otherwise Manage Server required)
86
- DISCORD_ALLOWED_USER_IDS=
87
- DISCORD_ALERT_MIN_TIER=PRIORITY
88
- # === Bounded LLM requests / local OpenAI-compatible servers ===
89
- # LLM_PROVIDER=openai-compatible works with llama.cpp or LM Studio; key optional
90
- LLM_BASE_URL=
91
- # Independent from OLLAMA_BASE_URL; origin, /v1 or full chat/completions endpoint
92
- # LLM_PROVIDER=anthropic against a self-hosted Anthropic Messages API (gateway, router); origin, /v1 or full /v1/messages endpoint
93
- ANTHROPIC_BASE_URL=
94
- # Sent as Authorization: Bearer instead of x-api-key; use either this or LLM_API_KEY, not both
95
- ANTHROPIC_AUTH_TOKEN=
96
- LLM_IDEAS_MAX_TOKENS=4096
97
- LLM_IDEAS_TIMEOUT_MS=90000
98
- LLM_ALERT_MAX_TOKENS=800
99
- LLM_ALERT_TIMEOUT_MS=30000
100
- # Cited briefings (POST /api/briefing): tokens 128-8192, timeout 1000-360000 ms; a failure falls back to the rule-based briefing
101
- LLM_BRIEFING_MAX_TOKENS=1200
102
- LLM_BRIEFING_TIMEOUT_MS=60000
103
- # Bot /ask answers, from the latest sweep only: tokens 64-2048, timeout 1000-360000 ms
104
- LLM_ASK_MAX_TOKENS=500
105
- LLM_ASK_TIMEOUT_MS=45000
106
- # Optional only when your local model supports it: none|minimal|low|medium|high
107
- OLLAMA_REASONING_EFFORT=
108
- # 1=every sweep; 3=first sweep then sweeps 3,6,...; delta alerts still run every sweep
109
- LLM_IDEAS_EVERY_N_SWEEPS=1
110
-
111
- # === Sweep archive (replay, changes, source-health matrix) ===
112
- # Stored in RUNS_DIR/sweeps as one gzip file per sweep; the oldest go first when either limit is reached.
113
- # Sweeps kept, 2-672 (default 96 = 24 hours at a 15-minute refresh interval)
114
- SWEEP_ARCHIVE_COUNT=
115
- # Disk budget of the archive in MB, 4-512 (default 64); the newest sweep is always kept
116
- SWEEP_ARCHIVE_MAX_MB=
117
-
118
- # === Country risk, logged predictions and cited briefings ===
119
- # Stored in RUNS_DIR/intelligence (countries.json, predictions.json). The score is a heuristic 0-100 index, not a probability.
120
- # false skips the risk step: no files, no snapshot.risk, and /api/countries, /api/predictions and /api/briefing answer 404 (default true)
121
- RISK_ENABLED=
122
- # Days of event references and score history kept, 14-90 (default 35)
123
- RISK_RETENTION_DAYS=
124
-
125
- # === Alert engine notifications (optional) ===
126
- # Alerts always appear in the dashboard; these settings only control what is also sent out.
127
- # Telegram and Discord alerts use the TELEGRAM_* and DISCORD_* settings above; ntfy and the webhook are set here.
128
- # Send engine alerts to Telegram and/or Discord too: comma list of telegram, discord (default none; their /mute applies)
129
- ALERT_NOTIFY_CHANNELS=
130
- # Lowest severity that is sent: critical | high | watch | info (default high)
131
- ALERT_NOTIFY_MIN_SEVERITY=
132
- # Quiet hours in local time as HH:MM-HH:MM, for example 22:00-07:00; critical still goes through, the rest follows as one summary after the window
133
- ALERT_QUIET_HOURS=
134
- # Individual messages per sweep, 1-50 (default 5); further alerts are sent as one "+N more alerts" summary
135
- ALERT_MAX_NOTIFICATIONS_PER_SWEEP=
136
- # Dashboard address added as a link to every message and accepted as the page origin behind a reverse proxy, for example https://crucix.example.com (http or https, no user:password)
137
- ALERT_PUBLIC_URL=
138
- # Without AUTH_USER/AUTH_PASSWORD, alert changes are accepted only via localhost, an IP address, the ALERT_PUBLIC_URL host or these host names (comma list, e.g. crucix.lan)
139
- ALERT_ALLOWED_HOSTS=
140
- # ntfy topic URL, for example https://ntfy.sh/your-topic (http or https, no user:password)
141
- ALERT_NTFY_URL=
142
- # Optional ntfy access token sent as a Bearer header
143
- ALERT_NTFY_TOKEN=
144
- # Webhook URL that receives each alert as a JSON POST (http or https, no user:password)
145
- ALERT_WEBHOOK_URL=
146
- # Open alerts allowed per rule, 1-500 (default 50); more hits are counted but not opened
147
- ALERT_MAX_ACTIVE_PER_RULE=
148
- # Optional: the User-Agent sent to SEC EDGAR (SEC asks automated clients to declare contact details), for example "Example Org ops@example.org". Printable ASCII, at most 200 characters; empty uses the plain Crucix agent, which SEC accepts
149
- SEC_USER_AGENT=
1
+ # ============================================
2
+ # Crucix Intelligence Engine — Configuration
3
+ # ============================================
4
+ # Copy this file to .env and fill in your keys.
5
+ # Keys are optional — sources without keys degrade gracefully.
6
+ #
7
+ # IMPORTANT: Do NOT put comments on the same line as values.
8
+ # Docker env_file treats inline comments as part of the value.
9
+
10
+ # === OSINT Source API Keys ===
11
+
12
+ # Federal Reserve Economic Data (free: fred.stlouisfed.org/docs/api)
13
+ FRED_API_KEY=
14
+ # NASA FIRMS fire data (free: firms.modaps.eosdis.nasa.gov/api)
15
+ FIRMS_MAP_KEY=
16
+ # Energy Information Administration (free: api.eia.gov/register)
17
+ EIA_API_KEY=
18
+ # BLS Public Data (optional: data.bls.gov/registrationEngine). v1 is ~25/day; Crucix caches 12 hours. v2 is 500/day.
19
+ BLS_API_KEY=
20
+ # Financial Modeling Prep (free: site.financialmodelingprep.com/register, 250 calls/day): equities, indexes, forex in two
21
+ # batch calls per sweep (192/day at the 15-minute sweep). FMP_DAILY_LIMIT caps the calls; without a key Yahoo covers it.
22
+ FMP_API_KEY=
23
+ FMP_DAILY_LIMIT=250
24
+ # Finnhub (free: finnhub.io/register, 60 calls/minute): second quote source for the US-listed equities
25
+ FINNHUB_API_KEY=
26
+ # Base currency of the FX crosses: USD | EUR | GBP | HUF | JPY | CHF | CAD | AUD | CNY (each dashboard user can switch)
27
+ CRUCIX_BASE_CURRENCY=USD
28
+ # Maritime live AIS (free: aisstream.io/account, sign in with GitHub). With a key the dashboard server keeps one
29
+ # aisstream.io WebSocket open and reports vessels seen at 11 chokepoints in the last hour; one-shot briefings do not.
30
+ # A key allows 3 connections; the service has no SLA and no written licence or terms of use (aisstream issue #290).
31
+ AISSTREAM_API_KEY=
32
+ # Armed Conflict Location & Event Data (acleddata.com/user/register)
33
+ ACLED_EMAIL=
34
+ # OAuth2 password grant (API keys deprecated Sept 2025)
35
+ ACLED_PASSWORD=
36
+ # OpenSky Network API client (opensky-network.org/my-opensky/account -> Create a new API client -> credentials.json)
37
+ # Optional: 4,000 instead of 400 credits/day and a refresh every 15 minutes instead of 2 hours; set both or neither
38
+ OPENSKY_CLIENT_ID=
39
+ OPENSKY_CLIENT_SECRET=
40
+ # Cloudflare Radar internet outages & traffic anomalies (free: dash.cloudflare.com/profile/api-tokens, Account Analytics Read)
41
+ CLOUDFLARE_API_TOKEN=
42
+
43
+ # === Server Configuration ===
44
+
45
+ # Dashboard server port
46
+ PORT=3117
47
+ # Auto-refresh interval (minutes)
48
+ REFRESH_INTERVAL_MINUTES=15
49
+
50
+ # === LLM Layer (optional) ===
51
+ # Enables AI-enhanced trade ideas and breaking news Telegram alerts.
52
+ # Provider options: anthropic | openai | gemini | codex | openrouter | minimax | mistral | ollama | grok | openai-compatible
53
+ LLM_PROVIDER=
54
+ # Not needed for codex (uses ~/.codex/auth.json) or ollama (local)
55
+ LLM_API_KEY=
56
+ # Optional override. Each provider has a sensible default:
57
+ # anthropic: claude-sonnet-4-6 | openai: gpt-5.4 | gemini: gemini-3.1-pro | codex: first model in ~/.codex/models_cache.json (gpt-6.1-sol) | openrouter: openrouter/auto | minimax: MiniMax-M2.5 | ollama: llama3.1:8b | grok: grok-4-latest
58
+ LLM_MODEL=
59
+ # Ollama base URL (only needed if not using default http://localhost:11434)
60
+ OLLAMA_BASE_URL=
61
+ # Output language for the "Trade Ideas" LLM box. Supported: en | fr | hu
62
+ # Falls back to CRUCIX_LANG, then to English if unset.
63
+ TRADE_IDEAS_LANG=
64
+
65
+ # === Telegram Alerts (optional; rules work without LLM) ===
66
+ # Create a bot via @BotFather, get chat ID via @userinfobot
67
+ TELEGRAM_BOT_TOKEN=
68
+ TELEGRAM_CHAT_ID=
69
+ # Alerts below this tier are not sent on their own but listed in /brief: FLASH | PRIORITY | ROUTINE (default PRIORITY)
70
+ TELEGRAM_ALERT_MIN_TIER=PRIORITY
71
+ # Group chats: only these Telegram user ids may run bot commands, /ask included (empty = anyone in TELEGRAM_CHAT_ID)
72
+ TELEGRAM_ALLOWED_USER_IDS=
73
+ # Local server access (HOST=0.0.0.0 enables LAN; Docker sets this internally)
74
+ HOST=127.0.0.1
75
+ AUTH_USER=
76
+ AUTH_PASSWORD=
77
+ PUBLIC_URL=
78
+ MAX_SSE_CLIENTS=100
79
+ NO_AUTO_OPEN=0
80
+ # Opt-in browser access from other sites (comma lists of origins like https://example.com; empty = off, see docs/API.md and docs/EMBEDDING.md)
81
+ # CORS_ORIGINS: pages from these origins may READ the GET /api routes (a lone * allows any site; only sensible with AUTH_USER/AUTH_PASSWORD)
82
+ CORS_ORIGINS=
83
+ # EMBED_ORIGINS: pages from these origins may show the dashboard (/) or the widget (/embed.html) in an iframe
84
+ EMBED_ORIGINS=
85
+ # Explicit opt-in to read public Telegram previews; never private bot updates
86
+ TELEGRAM_OSINT_ENABLED=false
87
+ # Optional user allowlist for Discord sweep/mute/unmute/ask (otherwise Manage Server required)
88
+ DISCORD_ALLOWED_USER_IDS=
89
+ DISCORD_ALERT_MIN_TIER=PRIORITY
90
+ # === Bounded LLM requests / local OpenAI-compatible servers ===
91
+ # LLM_PROVIDER=openai-compatible works with llama.cpp or LM Studio; key optional
92
+ LLM_BASE_URL=
93
+ # Independent from OLLAMA_BASE_URL; origin, /v1 or full chat/completions endpoint
94
+ # LLM_PROVIDER=anthropic against a self-hosted Anthropic Messages API (gateway, router); origin, /v1 or full /v1/messages endpoint
95
+ ANTHROPIC_BASE_URL=
96
+ # Sent as Authorization: Bearer instead of x-api-key; use either this or LLM_API_KEY, not both
97
+ ANTHROPIC_AUTH_TOKEN=
98
+ LLM_IDEAS_MAX_TOKENS=4096
99
+ LLM_IDEAS_TIMEOUT_MS=180000
100
+ LLM_ALERT_MAX_TOKENS=800
101
+ LLM_ALERT_TIMEOUT_MS=30000
102
+ # Cited briefings (POST /api/briefing): tokens 128-8192, timeout 1000-360000 ms; a failure falls back to the rule-based briefing
103
+ LLM_BRIEFING_MAX_TOKENS=1200
104
+ LLM_BRIEFING_TIMEOUT_MS=60000
105
+ # Bot /ask answers, from the latest sweep only: tokens 64-2048, timeout 1000-360000 ms
106
+ LLM_ASK_MAX_TOKENS=500
107
+ LLM_ASK_TIMEOUT_MS=45000
108
+ # Optional only when your local model supports it: none|minimal|low|medium|high
109
+ OLLAMA_REASONING_EFFORT=
110
+ # 1=every sweep; 3=first sweep then sweeps 3,6,...; delta alerts still run every sweep
111
+ LLM_IDEAS_EVERY_N_SWEEPS=1
112
+
113
+ # === Sweep archive (replay, changes, source-health matrix) ===
114
+ # Stored in RUNS_DIR/sweeps as one gzip file per sweep; the oldest go first when either limit is reached.
115
+ # Sweeps kept, 2-672 (default 96 = 24 hours at a 15-minute refresh interval)
116
+ SWEEP_ARCHIVE_COUNT=
117
+ # Disk budget of the archive in MB, 4-512 (default 64); the newest sweep is always kept
118
+ SWEEP_ARCHIVE_MAX_MB=
119
+
120
+ # === Country risk, logged predictions and cited briefings ===
121
+ # Stored in RUNS_DIR/intelligence (countries.json, predictions.json). The score is a heuristic 0-100 index, not a probability.
122
+ # false skips the risk step: no files, no snapshot.risk, and /api/countries, /api/predictions and /api/briefing answer 404 (default true)
123
+ RISK_ENABLED=
124
+ # Days of event references and score history kept, 14-90 (default 35)
125
+ RISK_RETENTION_DAYS=
126
+
127
+ # === Alert engine notifications (optional) ===
128
+ # Alerts always appear in the dashboard; these settings only control what is also sent out.
129
+ # Telegram and Discord alerts use the TELEGRAM_* and DISCORD_* settings above; ntfy and the webhook are set here.
130
+ # Send engine alerts to Telegram and/or Discord too: comma list of telegram, discord (default none; their /mute applies)
131
+ ALERT_NOTIFY_CHANNELS=
132
+ # Lowest severity that is sent: critical | high | watch | info (default high)
133
+ ALERT_NOTIFY_MIN_SEVERITY=
134
+ # Quiet hours in local time as HH:MM-HH:MM, for example 22:00-07:00; critical still goes through, the rest follows as one summary after the window
135
+ ALERT_QUIET_HOURS=
136
+ # Individual messages per sweep, 1-50 (default 5); further alerts are sent as one "+N more alerts" summary
137
+ ALERT_MAX_NOTIFICATIONS_PER_SWEEP=
138
+ # Dashboard address added as a link to every message and accepted as the page origin behind a reverse proxy, for example https://crucix.example.com (http or https, no user:password)
139
+ ALERT_PUBLIC_URL=
140
+ # Without AUTH_USER/AUTH_PASSWORD, alert changes are accepted only via localhost, an IP address, the ALERT_PUBLIC_URL host or these host names (comma list, e.g. crucix.lan)
141
+ ALERT_ALLOWED_HOSTS=
142
+ # ntfy topic URL, for example https://ntfy.sh/your-topic (http or https, no user:password)
143
+ ALERT_NTFY_URL=
144
+ # Optional ntfy access token sent as a Bearer header
145
+ ALERT_NTFY_TOKEN=
146
+ # Webhook URL that receives each alert as a JSON POST (http or https, no user:password)
147
+ ALERT_WEBHOOK_URL=
148
+ # Open alerts allowed per rule, 1-500 (default 50); more hits are counted but not opened
149
+ ALERT_MAX_ACTIVE_PER_RULE=
150
+ # Optional: the User-Agent sent to SEC EDGAR (SEC asks automated clients to declare contact details), for example "Example Org ops@example.org". Printable ASCII, at most 200 characters; empty uses the plain Crucix agent, which SEC accepts
151
+ SEC_USER_AGENT=