crucix 2.39.0 → 2.39.2

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 (242) hide show
  1. package/.env.example +149 -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 +311 -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 +165 -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 +219 -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 +250 -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 +190 -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 +87 -87
  84. package/apis/utils/freshness.mjs +95 -95
  85. package/apis/utils/news-feeds.mjs +102 -102
  86. package/apis/utils/rss.mjs +56 -56
  87. package/apis/utils/xml.mjs +19 -19
  88. package/apis/utils/zip.mjs +42 -42
  89. package/crucix.config.mjs +209 -209
  90. package/dashboard/inject.mjs +923 -923
  91. package/dashboard/public/alert-rules.js +494 -494
  92. package/dashboard/public/alerts-core.js +48 -48
  93. package/dashboard/public/alerts.css +168 -168
  94. package/dashboard/public/alerts.js +475 -475
  95. package/dashboard/public/briefing.css +38 -38
  96. package/dashboard/public/briefing.js +171 -171
  97. package/dashboard/public/changes.css +45 -45
  98. package/dashboard/public/changes.js +331 -331
  99. package/dashboard/public/clock.js +14 -14
  100. package/dashboard/public/country.css +61 -61
  101. package/dashboard/public/country.js +259 -259
  102. package/dashboard/public/credits.js +56 -56
  103. package/dashboard/public/data/infrastructure.json +1 -1
  104. package/dashboard/public/domains.js +24 -24
  105. package/dashboard/public/embed.html +75 -75
  106. package/dashboard/public/health-matrix.css +75 -75
  107. package/dashboard/public/health-matrix.js +242 -242
  108. package/dashboard/public/infrastructure.js +186 -186
  109. package/dashboard/public/intelligence.css +63 -63
  110. package/dashboard/public/intelligence.js +341 -341
  111. package/dashboard/public/jarvis.html +3534 -3534
  112. package/dashboard/public/lens-core.js +37 -37
  113. package/dashboard/public/lens.css +13 -13
  114. package/dashboard/public/lens.js +101 -101
  115. package/dashboard/public/live-sources.css +36 -36
  116. package/dashboard/public/live-sources.js +115 -115
  117. package/dashboard/public/loading.html +169 -169
  118. package/dashboard/public/manifest.webmanifest +15 -15
  119. package/dashboard/public/palette-core.js +54 -54
  120. package/dashboard/public/palette.css +45 -45
  121. package/dashboard/public/palette.js +268 -268
  122. package/dashboard/public/pivots.js +61 -61
  123. package/dashboard/public/pwa.js +132 -132
  124. package/dashboard/public/record-core.js +153 -153
  125. package/dashboard/public/record-inspector.css +105 -105
  126. package/dashboard/public/record-inspector.js +350 -350
  127. package/dashboard/public/replay-core.js +72 -72
  128. package/dashboard/public/replay.css +33 -33
  129. package/dashboard/public/replay.js +251 -251
  130. package/dashboard/public/risk.css +35 -35
  131. package/dashboard/public/risk.js +292 -292
  132. package/dashboard/public/setup.html +1198 -1198
  133. package/dashboard/public/sw.js +52 -52
  134. package/data/world-rss/README.hu.md +324 -324
  135. package/data/world-rss/complete-world-feeds.js +6 -6
  136. package/data/world-rss/country-coverage.csv +251 -251
  137. package/data/world-rss/country-fallback-feeds.js +39 -39
  138. package/data/world-rss/country-search-feeds.js +594 -594
  139. package/data/world-rss/local-alternatives.js +610 -610
  140. package/data/world-rss/registry.json +48831 -48831
  141. package/data/world-rss/search-audit.json +241 -241
  142. package/data/world-rss/summary.json +15 -15
  143. package/data/world-rss/world-feeds.js +929 -929
  144. package/data/world-rss/world-feeds.opml +928 -928
  145. package/diag.mjs +94 -94
  146. package/lib/alerts/ask.mjs +216 -216
  147. package/lib/alerts/brief.mjs +85 -85
  148. package/lib/alerts/discord.mjs +661 -661
  149. package/lib/alerts/engine.mjs +614 -614
  150. package/lib/alerts/evaluators.mjs +417 -417
  151. package/lib/alerts/evidence.mjs +118 -118
  152. package/lib/alerts/levels.mjs +40 -40
  153. package/lib/alerts/lifecycle.mjs +185 -185
  154. package/lib/alerts/metrics.mjs +88 -88
  155. package/lib/alerts/notify.mjs +501 -501
  156. package/lib/alerts/routes.mjs +176 -176
  157. package/lib/alerts/rules.mjs +458 -458
  158. package/lib/alerts/store.mjs +383 -383
  159. package/lib/alerts/sweep.mjs +49 -49
  160. package/lib/alerts/telegram.mjs +828 -828
  161. package/lib/api-errors.mjs +24 -24
  162. package/lib/atomic-json.mjs +83 -83
  163. package/lib/basemap.mjs +48 -48
  164. package/lib/dashboard-path.mjs +80 -80
  165. package/lib/delta/engine.mjs +251 -251
  166. package/lib/delta/index.mjs +2 -2
  167. package/lib/delta/memory.mjs +247 -247
  168. package/lib/domains.mjs +32 -32
  169. package/lib/html.mjs +4 -4
  170. package/lib/http-security.mjs +142 -142
  171. package/lib/i18n.mjs +163 -163
  172. package/lib/install-mode.mjs +9 -9
  173. package/lib/intelligence/anomalies.mjs +63 -63
  174. package/lib/intelligence/countries.mjs +225 -225
  175. package/lib/intelligence/entities.mjs +269 -269
  176. package/lib/intelligence/events.mjs +423 -423
  177. package/lib/intelligence/export.mjs +90 -90
  178. package/lib/intelligence/exposure.mjs +61 -61
  179. package/lib/intelligence/geo.mjs +109 -109
  180. package/lib/intelligence/history.mjs +368 -368
  181. package/lib/intelligence/keywords.mjs +193 -193
  182. package/lib/intelligence/live-sources.mjs +80 -80
  183. package/lib/intelligence/military-sites.mjs +51 -51
  184. package/lib/intelligence/predictions.mjs +163 -163
  185. package/lib/intelligence/risk-routes.mjs +170 -170
  186. package/lib/intelligence/risk-step.mjs +145 -145
  187. package/lib/intelligence/risk.mjs +159 -159
  188. package/lib/intelligence/routes.mjs +46 -46
  189. package/lib/intelligence/thermal.mjs +194 -194
  190. package/lib/intelligence/timeline.mjs +34 -34
  191. package/lib/llm/alert-schema.mjs +22 -22
  192. package/lib/llm/anthropic.mjs +78 -78
  193. package/lib/llm/briefing.mjs +291 -291
  194. package/lib/llm/budgets.mjs +46 -46
  195. package/lib/llm/cadence.mjs +30 -30
  196. package/lib/llm/codex.mjs +160 -160
  197. package/lib/llm/cursor.mjs +78 -78
  198. package/lib/llm/gemini.mjs +57 -57
  199. package/lib/llm/grok.mjs +56 -56
  200. package/lib/llm/idea-schema.mjs +65 -65
  201. package/lib/llm/ideas.mjs +83 -83
  202. package/lib/llm/index.mjs +68 -68
  203. package/lib/llm/json-extract.mjs +129 -129
  204. package/lib/llm/minimax.mjs +53 -53
  205. package/lib/llm/mistral.mjs +53 -53
  206. package/lib/llm/ollama.mjs +54 -54
  207. package/lib/llm/openai-compatible.mjs +66 -66
  208. package/lib/llm/openai.mjs +52 -52
  209. package/lib/llm/openrouter.mjs +54 -54
  210. package/lib/llm/provider.mjs +26 -26
  211. package/lib/llm/rule-ideas.mjs +123 -123
  212. package/lib/markets/build.mjs +68 -68
  213. package/lib/markets/fx.mjs +136 -136
  214. package/lib/news/feed-store.mjs +332 -332
  215. package/lib/news/opml.mjs +69 -69
  216. package/lib/news/routes.mjs +75 -75
  217. package/lib/offline-shell.mjs +9 -9
  218. package/lib/open-browser.mjs +18 -18
  219. package/lib/profile-install.mjs +28 -28
  220. package/lib/setup-wizard.mjs +821 -821
  221. package/lib/snapshots.mjs +13 -13
  222. package/lib/sse.mjs +22 -22
  223. package/lib/sweeps/archive.mjs +463 -463
  224. package/lib/sweeps/changes.mjs +280 -280
  225. package/lib/sweeps/routes.mjs +122 -122
  226. package/lib/sweeps/step.mjs +22 -22
  227. package/lib/user-paths.mjs +38 -38
  228. package/lib/version.mjs +22 -0
  229. package/lib/world-rss-runner.mjs +213 -213
  230. package/locales/en.json +1724 -1724
  231. package/locales/fr.json +1724 -1724
  232. package/locales/hu.json +1724 -1724
  233. package/package.json +93 -93
  234. package/scripts/benchmark-world-rss.mjs +64 -64
  235. package/scripts/check.mjs +28 -28
  236. package/scripts/clean.mjs +18 -18
  237. package/scripts/cli.mjs +13 -0
  238. package/scripts/setup.mjs +8 -8
  239. package/scripts/status.mjs +113 -113
  240. package/scripts/sync-setup-html.mjs +47 -47
  241. package/scripts/verify-assets.mjs +16 -16
  242. package/scripts/watchlist.mjs +96 -96
package/.env.example CHANGED
@@ -1,149 +1,149 @@
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
+ # 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=