feat: add GATRA SOC integration layer#293
Conversation
These CSS custom properties were used in 14 places but never defined, causing transparent backgrounds on playback panel, toggle button, header flash animation, select options, and offline retry button.
"here" and other basic English words (pronouns, prepositions, adverbs) were not in SUPPRESSED_TRENDING_TERMS, causing false keyword spike findings for common words.
"here" and other basic English words (pronouns, prepositions, adverbs) were not in SUPPRESSED_TRENDING_TERMS, causing false keyword spike findings for common words.
…ages Audit found missing keys in all non-EN locales (62-90 per file) and 25 stale keys in PT/NL/SV. Fixes gaps, removes stale keys, corrects FR infra key misplacement, and adds complete Russian (ru) translation with 1013/1013 keys matching the English reference.
When the NER model isn't loaded, isSignificantTerm was returning true for all terms, letting common words like "here" trigger keyword spike findings. Now falls back to a capitalization heuristic: single-word terms must appear capitalized (mid-sentence) in >50% of headlines to be treated as significant. Also added ~45 missing English stopwords.
When the NER model isn't loaded, isSignificantTerm was returning true for all terms, letting common words like "here" trigger keyword spike findings. Now falls back to a capitalization heuristic: single-word terms must appear capitalized (mid-sentence) in >50% of headlines to be treated as significant. Also added ~45 missing English stopwords.
Shows a compact pill badge (bottom-right) inviting users to the GitHub Discussions page. Includes pulsing dot indicator, CTA button, close button, and "Don't show again" option that persists to localStorage.
Floating pill badge (bottom-right) with pulsing dot, "Join the Discussion" text, and CTA linking to GitHub Discussions koala73#94. Shows 15s after initial data load. "Don't show again" persists dismissal to localStorage (wm-community-dismissed).
…case terms
P1: Start-of-headline matches (idx=0) no longer count against the
capitalization ratio. When all matches are headline-start only,
falls back to acronym check instead of returning false.
P2: Removed dead [A-Z]{2,} shortcut — terms are lowercased by
asDisplayTerm() before reaching isLikelyProperNoun.
…rrides These imports were accidentally committed from the i18n PR branch. The files don't exist on main, causing Vercel build errors.
- Add ar.json and zh.json translations (1013 keys each, full parity) - RTL support: dir="rtl" on <html>, targeted CSS overrides in rtl-overrides.css - Font fallbacks: system Arabic/CJK fonts via --font-body CSS variable - i18n.ts: RTL_LANGUAGES set, applyDocumentDirection(), isRTL(), getLocale() - story-renderer.ts: locale-aware date formatting via getLocale() - Type declarations for both new locales
…TC clock Replace hardcoded English text with t() calls across 12 source files: signal context descriptions, alert titles/summaries, intel topic names, map legend labels, asset/threat labels, UCDP panel headers, stablecoin/status panel sections. Add ~114 new keys to en.json and translate to all 11 locales (fr/de/es/it/pl/pt/nl/sv/ru/ar/zh). Remove dead #timeDisplay span that was never updated by JS. All 12 locales at 1127-key parity with 0 placeholder mismatches.
…AppImage, locale gaps, lang normalization
- Fix relative-time {{count}} placeholders in all 12 locales (5m ago, not m ago)
- Localize CommunityWidget: replace 3 hardcoded English strings with t() calls
- Add Linux AppImage to tech/finance Tauri configs, CI matrix (ubuntu-22.04), packaging scripts, and download-node.sh
- Fix language code normalization: add supportedLngs/nonExplicitSupportedLngs to i18next, normalize getCurrentLanguage()
- Translate ~240 untranslated English strings across 11 locale files (ru/ar/zh now 100% translated)
- Add components.community section to all 12 locales
- All 12 locales at 1130-key parity, 0 placeholder mismatches
applyDocumentDirection() now splits on '-' before checking RTL set, so ar-SA correctly triggers dir="rtl" on first detect.
- CommunityWidget: aria-label="Close" → t('common.close')
- App.ts: ' (current)' suffix → t('common.currentVariant')
- fr.json: "Cloud & Infrastructure" → "Cloud et infrastructure"
- sv.json: "24h Vol" → "24t volym"
- Added common.close + common.currentVariant to all 12 locales
New ja.json with full translation parity to en.json. Registered in i18n.ts: import, resources, supportedLngs, LANGUAGES, getLocale map.
t() always returns a string (key itself if missing), so || 'English' fallbacks were unreachable dead code.
t() always returns a string, so || 'English' fallbacks were unreachable. Removed all 15 instances.
Main variant: NHK World + Nikkei Asia in asia category. Finance variant: Nikkei Asia in markets category. Added asia.nikkei.com to RSS proxy allowlist.
Main variant: NHK World + Nikkei Asia in asia category. Finance variant: Nikkei Asia in markets category. Added asia.nikkei.com to RSS proxy allowlist.
…keys - CommunityWidget: add DOM check to prevent duplicate widgets on repeated loadNews() calls - RuntimeConfigPanel: compare t() result against key path to suppress missing help translations
* chore: apply cargo fmt formatting to main.rs Pure formatting normalization with no logic changes. Separated from the behavioral fix to keep git blame clean. https://claude.ai/code/session_01RPQ1PEqxTSEG6rB5XadzEz * fix: restrict settings-window re-focus to macOS to avoid Windows focus churn On Windows, the Focused(true) handler on the main window calls show()+set_focus() on the settings window, which steals focus back, retriggering the event in a tight loop and presenting as a UI hang. Gate the match arm with #[cfg(target_os = "macos")] (compile-time attribute) instead of cfg!() (runtime macro) to match the convention used by the adjacent macOS-only handlers and eliminate dead code on non-macOS builds entirely. https://claude.ai/code/session_01RPQ1PEqxTSEG6rB5XadzEz --------- Co-authored-by: Claude <noreply@anthropic.com>
…oala73#232) * fix(sentry): add noise filters for 5 non-actionable error patterns Filter dynamic import alt phrasing, script parse errors, maplibre style/WebGL crashes, and CustomEvent promise rejections. Also fix beforeSend to catch short Firefox null messages like "E is null". * fix: cache write race, settings stale key status, yahoo gate concurrency P1: Replace async background thread cache write with synchronous fs::write to prevent out-of-order writes and dirty flag cleared before persistence. P2: Add WorldMonitorTab.refresh() called after loadDesktopSecrets() so the API key badge reflects actual keychain state. P3: Replace timestamp-based Yahoo gate with promise queue to ensure sequential execution under concurrent callers. * feat: add Upstash Redis shared caching to all RPC handlers + fix cache key contamination - Add Redis L2 cache (getCachedJson/setCachedJson) to 28 RPC handlers across all service domains (market, conflict, cyber, economic, etc.) - Fix 10 P1 cache key contamination bugs where under-specified keys caused cross-request data pollution (e.g. filtered requests returning unfiltered cached data) - Restructure list-internet-outages to cache-then-filter pattern so country/timeRange filters always apply after cache read - Add write_lock mutex to PersistentCache in main.rs to prevent desktop cache write-race conditions - Document FMP (Financial Modeling Prep) as Yahoo Finance fallback TODO in market/v1/_shared.ts * fix: cache-key contamination and PizzINT/GDELT partial-failure regression - tech-events: fetch with limit=0 and cache full result, apply limit slice after cache read to prevent low-limit requests poisoning cache - pizzint: restore try-catch around PizzINT fetch so GDELT tension pairs are still returned when PizzINT API is down * fix: remove extra closing brace in pizzint try-catch * fix: recompute conferenceCount/mappableCount after limit slice * fix: bypass WM API key gate for registration endpoint /api/register-interest must reach cloud without a WorldMonitor API key, otherwise desktop users can never register (circular dependency).
…a73#243) * fix: resolve AppImage blank white screen and font crash on Linux (koala73#238) Disable WebKitGTK DMA-BUF renderer by default on Linux to prevent blank white screens caused by GPU buffer allocation failures (common with NVIDIA drivers and immutable distros like Bazzite). Add Linux-native monospace font fallbacks (DejaVu Sans Mono, Liberation Mono) to all font stacks so WebKitGTK font resolution doesn't hit out-of-bounds vector access when macOS-only fonts (SF Mono, Monaco) are unavailable. https://claude.ai/code/session_01TF2NPgSSjgenmLT2XuR5b9 * fix: consolidate monospace font stacks into --font-mono variable - Define --font-mono in :root (main.css) and .settings-shell (settings-window.css) - Align font stack: SF Mono, Monaco, Cascadia Code, Fira Code, DejaVu Sans Mono, Liberation Mono - Replace 3 hardcoded JetBrains Mono stacks with var(--font-mono) - Replace 4 hardcoded settings-window stacks with var(--font-mono) - Fix pre-existing bug: var(--font-mono) used in 4 places but never defined - Match index.html skeleton font stack to --font-mono --------- Co-authored-by: Claude <noreply@anthropic.com>
* feat: make intelligence alert popup opt-in via dropdown toggle Auto-popup was interrupting users every 10s refresh cycle. Badge still counts and pulses silently. New toggle in dropdown (default OFF) lets users explicitly opt in to auto-popup behavior. * chore: bump version to 2.5.5 ## Changelog ### Features - Intelligence alert popup is now opt-in (default OFF) — badge counts silently, toggle in dropdown to enable auto-popup ### Bug Fixes - Linux: disable DMA-BUF renderer on WebKitGTK to prevent blank white screen (NVIDIA/immutable distros) - Linux: add DejaVu Sans Mono + Liberation Mono font fallbacks for monospace rendering - Consolidate monospace font stacks into --font-mono CSS variable (fixes undefined var bug) - Reduce dedup coordinate rounding from 0.5° to 0.1° (~10km precision) - Vercel build: handle missing previous deploy SHA - Panel base class: add missing showRetrying method - Vercel ignoreCommand shortened to fit 256-char limit ### Infrastructure - Upstash Redis shared caching for all RPC handlers + cache key contamination fix - Format Rust code and fix Windows focus handling ### Docs - Community guidelines: contributing, code of conduct, security policy - Updated .env.example * chore: track Cargo.lock for reproducible Rust builds * fix: update layer help popup with all current map layers Added missing layers to the ? help popup across all 3 variants: - Full: UCDP Events, Displacement, Spaceports, Cyber Threats, Fires, Climate Anomalies, Critical Minerals; renamed Shipping→Ship Traffic - Tech: Tech Events, Cyber Threats, Fires - Finance: GCC Investments * docs: update README with crypto prices, analytics, typography, and dedup grid fix * fix: add /ingest to service worker NetworkOnly routes The SW was intercepting PostHog /ingest/* requests and returning no-response (404) because no cache match existed. Adding NetworkOnly ensures analytics requests pass through to Vercel's rewrite proxy. * chore: update Cargo.lock for v2.5.5 * fix: use explicit colors for findings toggle switch visibility
- Fix PostHog /ingest 404: Workbox registerRoute defaults to GET only, PostHog sends POST. Add POST routes for /api/ and /ingest/. - Fix fullscreen crash: optional chaining on exitFullscreen()?.catch() for browsers returning undefined instead of Promise. - Add 6 noise filters: __firefox__, ifameElement.contentDocument, Invalid video id, Fetch is aborted, Stylesheet append timeout, Cannot assign to read only property. - Widen Program failed to link filter (remove ": null" suffix).
The broad regex /^https?:\/\/.*\/api\/.*/i matched ANY URL with /api/ in the path, including external APIs like NASA EONET (eonet.gsfc.nasa.gov/api/v3/events). Workbox intercepted these cross-origin requests with NetworkOnly, causing no-response errors when CORS failed. Changed all /api/, /ingest/, and /rss/ SW route patterns to use sameOrigin callback check so only our Vercel routes get NetworkOnly handling. External APIs now pass through without SW interference.
koala73#251) * fix: restrict SW route patterns to same-origin only The broad regex /^https?:\/\/.*\/api\/.*/i matched ANY URL with /api/ in the path, including external APIs like NASA EONET (eonet.gsfc.nasa.gov/api/v3/events). Workbox intercepted these cross-origin requests with NetworkOnly, causing no-response errors when CORS failed. Changed all /api/, /ingest/, and /rss/ SW route patterns to use sameOrigin callback check so only our Vercel routes get NetworkOnly handling. External APIs now pass through without SW interference. * fix: whitelist social preview bots on OG image assets Slack-ImgProxy (distinct from Slackbot) was blocked from fetching /favico/og-image.png by both our bot filter and Vercel Attack Challenge. Extend middleware matcher to /favico/* and allow all social preview/image bots through on static asset paths.
Full translation of all 1,397 i18n keys to Greek. Registers 'el' in SUPPORTED_LANGUAGES, LANGUAGES display array, and getLocale() map.
…a73#262) On Windows, Tauri webviews send requests with origin `http://tauri.localhost` (HTTP), but the CORS allowlist only permitted `https://tauri.localhost` (HTTPS). This caused every sidecar API request to be blocked by CORS, making the app non-functional on Windows with a "sidecar not reachable" error. Change the regex from `^https:` to `^https?:` so both HTTP and HTTPS origins from tauri.localhost are accepted. https://claude.ai/code/session_016XMWtTPfE81bitu3QEoUwy Co-authored-by: Claude <noreply@anthropic.com>
…ching (koala73#266) * perf: optimize WebSocket relay to prevent Railway crashes under load Key fixes: - Fix crash: guard all res.writeHead() calls against "headers already sent" (the ais-relay.cjs:740 crash from error/timeout race conditions) - Pre-serialize + pre-gzip AIS snapshots — eliminates JSON.stringify and zlib.gzip on every HTTP request to /ais/snapshot - Add upstream WebSocket backpressure: pause/resume at 4MB/512KB watermarks to prevent unbounded buffer growth and OOM - Replace O(chokepoints × vessels) disruption detection with O(chokepoints) spatial bucket lookup populated at ingest time - Cap all Maps (vessels: 50K, history: 50K, density: 5K, candidates: 1.5K) to prevent unbounded memory growth between cleanup cycles - Reduce WS fanout from every 10th to every 50th message with per-client backpressure (skip clients with >1MB buffered) - Hoist all require('https'/'http'/'zlib') to top-level (6 inline calls removed from hot request paths) - Add memory monitoring: 60s interval logs RSS/heap, emergency cache flush at 400MB RSS threshold - Health endpoint now reports memory, droppedMessages, upstreamPaused state - Delete errored WS clients from Set immediately https://claude.ai/code/session_01WFQkHftPgni8oaWtznv1v5 * fix: harden AIS relay backpressure and chokepoint accuracy --------- Co-authored-by: Claude <noreply@anthropic.com>
…oala73#263) * fix: resolve AppImage crash on Ubuntu 25.10+ (GLib symbol mismatch) The AppImage bundles GLib from the build system, but host GIO modules (e.g. GVFS libgvfsdbus.so) compiled against a newer GLib reference symbols like g_task_set_static_name that don't exist in the older bundled copy, causing "undefined symbol" errors and WebKit crashes. Set GIO_MODULE_DIR="" when running as AppImage to prevent host GIO modules from loading against the incompatible bundled GLib. GVFS features (network mounts, trash, MTP) are unused by this app. Note: the CI should also be upgraded from ubuntu-22.04 to ubuntu-24.04 in .github/workflows/build-desktop.yml to ship GLib 2.80+ and extend forward-compatibility. This requires workflows permission to push. https://claude.ai/code/session_01J8HBrfb26GJm22MFCeGoAA * fix(appimage): keep bundled GIO modules for Ubuntu 25.10 --------- Co-authored-by: Claude <noreply@anthropic.com>
* Add Brasil Paralelo source One of the biggest independent media company in Brazil * Add Brasil Paralelo domain to rss-proxy.js * fix: add missing comma and https:// protocol for Brasil Paralelo feed --------- Co-authored-by: Elie Habib <elie.habib@gmail.com>
…la73#270) rsshub.app was returning non-2xx responses (likely 429 rate-limit) which were never cached, causing a thundering herd: 874 requests in 5 minutes to the same URL instead of 1. The in-flight dedup also cascaded — when waiters woke up and found no cache, they started their own fetches. - Cache all RSS responses (non-2xx with 60s TTL vs 5min for success) - Dedup waiters serve 502 on failure instead of cascading to new fetches - Log upstream error status codes for future diagnosis - Raise memory cleanup threshold to 450MB, only clear OpenSky cache
- Add 5 Nigeria news sources to Africa section (Premium Times, Vanguard, Channels TV, Daily Trust, ThisDay) - Add 5 Greek feeds with lang: 'el' for locale-aware filtering (Kathimerini, Naftemporiki, in.gr, iefimerida, Proto Thema) - Add source tiers for all new outlets - Allowlist 8 new domains in RSS proxy
…73#277) The existing scheduler skips fetches while the tab is hidden and reschedules with a 4x delay. When the user returns, they could wait up to interval x 4 (e.g. 20 min for a 5-min service) before seeing fresh data. Add flushStaleRefreshes() -- on visibilitychange, cancel pending timeouts for any service whose hidden duration exceeded its refresh interval and re-trigger them with 150ms stagger to avoid thundering herd. Services that are not stale yet keep their existing schedule. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: persist circuit breaker cache to IndexedDB across page reloads On page reload, all 28+ circuit breaker in-memory caches are lost, triggering 20-30 simultaneous POST requests to Vercel edge functions. Wire the existing persistent-cache.ts (IndexedDB + localStorage + Tauri fallback) into CircuitBreaker so every breaker automatically: - Hydrates from IndexedDB on first execute() call (~1-5ms read) - Writes to IndexedDB fire-and-forget on every recordSuccess() - Falls back to stale persistent data on network failure - Auto-disables for breakers with cacheTtlMs=0 (live pricing) Zero consumer code changes -- all 28+ breaker call sites untouched. Reloads within the cache TTL (default 10min) serve instantly from IndexedDB with zero network calls. Also adds deletePersistentCache() to persistent-cache.ts for clean cache invalidation via clearCache(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add Playwright e2e tests for circuit breaker persistent cache 7 tests covering: IndexedDB persistence on success, hydration on new instance, TTL expiry forcing fresh fetch, 24h stale ceiling rejection, clearCache cleanup, cacheTtlMs=0 auto-disable, and network failure fallback to stale persistent data. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: desktop cache deletion + clearCache race condition P1: deletePersistentCache sent empty string to write_cache_entry, which fails Rust's serde_json::from_str (not valid JSON). Add dedicated delete_cache_entry Tauri command that removes the key from the in-memory HashMap and flushes to disk. P2: clearCache() set persistentLoaded=false, allowing a concurrent execute() to re-hydrate stale data from IndexedDB before the async delete completed. Remove the reset — after explicit clear there is no reason to re-hydrate from persistent storage. * fix: default persistCache to false, fix falsy data guard P1b: 6 breakers store Date objects (weather, aviation, ACLED, military-flights, military-vessels, GDACS) which become strings after JSON round-trip. Callers like MapPopup.getTimeUntil() call date.getTime() on hydrated strings → TypeError. Change default to false (opt-in) so persistence requires explicit confirmation that the payload is JSON-safe. P2: `if (!entry?.data) return` drops valid falsy payloads (0, false, empty string). Use explicit null/undefined check instead. * fix: address blocking review issues on circuit breaker persistence - clearCache() nulls persistentLoadPromise to orphan in-flight hydration - delete_cache_entry defers disk flush to exit handler (avoids 14MB sync write) - hydratePersistentCache checks TTL before setting lastDataState to 'cached' - deletePersistentCache resets cacheDbPromise on IDB error + logs warning - hydration catch logs warning instead of silently swallowing - deletePersistentCache respects isStorageQuotaExceeded() for localStorage --------- Co-authored-by: Elias El Khoury <efk@anghami.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(live): custom channel management — add/remove/reorder, standalone window, i18n - Standalone channel management window (?live-channels=1) with list, add form, restore defaults - LIVE panel: gear icon opens channel management; channel tabs reorderable via DnD - Row click to edit; custom modal for delete confirmation (no window.confirm) - i18n for all locales (manage, addChannel, youtubeHandle, displayName, etc.) - UI: margin between channel list and add form in management window - settings-window: panel display settings comment in English Co-authored-by: Cursor <cursoragent@cursor.com> * feat(tauri): channel management in desktop app, dev base_url fix - Add live-channels.html and live-channels-main.ts for standalone window - Tauri: open_live_channels_window_command, close_live_channels_window, open live-channels window (WebviewUrl::App or External from base_url) - LiveNewsPanel: in desktop runtime invoke Tauri command with base_url (window.location.origin) so dev works when Vite runs on a different port than devUrl - Vite: add liveChannels entry to build input - capabilities: add live-channels window - tauri.conf: devUrl 3000 to match vite server.port - docs: PR_LIVE_CHANNEL_MANAGEMENT.md for PR koala73#276 Co-authored-by: Cursor <cursoragent@cursor.com> * fix: address review issues in live channel management PR - Revert settings button to open modal (not window.open popup) - Revert devUrl from localhost:3000 to localhost:5173 - Guard activeChannel against empty channels (fall back to defaults) - Escape i18n strings in innerHTML with escapeHtml() to prevent XSS - Only store displayNameOverrides for actually renamed channels - Use URL constructor for live-channels window URL - Add CSP meta tag to live-channels.html - Remove unused i18n keys (edit, editMode, done) from all locales - Remove unused CSS classes (live-news-manage-btn/panel/wrap) - Delete PR instruction doc (PR_LIVE_CHANNEL_MANAGEMENT.md) --------- Co-authored-by: Masaki <yukkurihakutaku@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…atching (koala73#283) * fix: add request coalescing to Redis cache layer Concurrent cache misses for the same key now share a single upstream fetch instead of each triggering redundant API calls. This eliminates duplicate work within Edge Function invocations under burst traffic. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: reduce AIS polling frequency from 10s to 30s Vessel positions do not change meaningfully in 10 seconds at sea. Reduces Railway relay requests by 66% with negligible UX impact. Stale threshold bumped to 45s to match the new interval. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: quantize military flights bbox cache keys to 1-degree grid Precise bounding box coordinates caused near-zero cache hit rate since every map pan/zoom produced a unique key. Snapping to a 1-degree grid lets nearby viewports share cache entries, dramatically reducing redundant OpenSky API calls. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: parallelize ETF chart fetches instead of sequential await loop The loop awaited each ETF chart fetch individually, blocking on every Yahoo gate delay. Using Promise.allSettled lets all 10 fetches queue concurrently through the Yahoo gate, cutting wall time from ~12s to ~6s. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add Redis pipeline batch GET to reduce round-trips Add getCachedJsonBatch() using the Upstash pipeline API to fetch multiple keys in a single HTTP call. Refactor aircraft details batch handler from 20 sequential GETs to 1 pipelined request. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add structural tests for Redis caching optimizations 18 tests covering: cachedFetchJson request coalescing (in-flight dedup, cache-before-fetch ordering, cleanup), getCachedJsonBatch pipeline API, aircraft batch handler pipeline usage, bbox grid quantization (1-degree step, expanded fetch bbox), and ETF parallel fetch. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: enforce military bbox contract and add behavioral cache tests --------- Co-authored-by: Elias El Khoury <efk@anghami.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…oala73#284) * fix: add request coalescing to Redis cache layer Concurrent cache misses for the same key now share a single upstream fetch instead of each triggering redundant API calls. This eliminates duplicate work within Edge Function invocations under burst traffic. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: reduce AIS polling frequency from 10s to 30s Vessel positions do not change meaningfully in 10 seconds at sea. Reduces Railway relay requests by 66% with negligible UX impact. Stale threshold bumped to 45s to match the new interval. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: quantize military flights bbox cache keys to 1-degree grid Precise bounding box coordinates caused near-zero cache hit rate since every map pan/zoom produced a unique key. Snapping to a 1-degree grid lets nearby viewports share cache entries, dramatically reducing redundant OpenSky API calls. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: parallelize ETF chart fetches instead of sequential await loop The loop awaited each ETF chart fetch individually, blocking on every Yahoo gate delay. Using Promise.allSettled lets all 10 fetches queue concurrently through the Yahoo gate, cutting wall time from ~12s to ~6s. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add Redis pipeline batch GET to reduce round-trips Add getCachedJsonBatch() using the Upstash pipeline API to fetch multiple keys in a single HTTP call. Refactor aircraft details batch handler from 20 sequential GETs to 1 pipelined request. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add structural tests for Redis caching optimizations 18 tests covering: cachedFetchJson request coalescing (in-flight dedup, cache-before-fetch ordering, cleanup), getCachedJsonBatch pipeline API, aircraft batch handler pipeline usage, bbox grid quantization (1-degree step, expanded fetch bbox), and ETF parallel fetch. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: enforce military bbox contract and add behavioral cache tests --------- Co-authored-by: Elias El Khoury <efk@anghami.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Introduces a unified GATRA SOC integration layer for the World Monitor cyber variant: - src/gatra/connector.ts: Centralized connector that fetches all GATRA data sources (ADA alerts, TAA analyses, CRA actions, agent health, correlations) in parallel with pub/sub notifications - src/panels/gatra-soc-panel.ts: Enhanced dashboard panel with 6 sections — agent status, incident stats, alert feed, TAA threat analysis (actor/campaign/kill-chain), CRA response actions, and dynamic World Monitor correlation insights - src/layers/gatra-alerts-layer.ts: Standalone deck.gl layer factory with severity-colored markers and pulsing rings for critical/high alerts - Extends src/services/gatra.ts with TAA analysis, correlation, and typed CRA action mock data using Indonesian locations and IOH infrastructure references - Wires createGatraAlertsLayers() in DeckGLMap.ts and adds gatraAlerts to all variant MapLayers definitions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@ghifiardi is attempting to deploy a commit to the Elie Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e782af66e4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| research: { name: 'Security Research', enabled: true, priority: 1 }, | ||
| policy: { name: 'Cyber Policy', enabled: true, priority: 2 }, | ||
| aiSecurity: { name: 'AI & Security', enabled: true, priority: 2 }, | ||
| 'gatra-soc': { name: 'GATRA SOC', enabled: true, priority: 1 }, |
There was a problem hiding this comment.
Instantiate the configured gatra-soc dashboard panel
This config enables a gatra-soc panel by default, but App.createPanels() never registers a panel instance for that key (and GatraSOCDashboardPanel has no usage sites), so the key is skipped when panel order is rendered and the SOC panel never appears in the cyber variant.
Useful? React with 👍 / 👎.
| public setGatraAlerts(alerts: GatraAlert[]): void { | ||
| this.gatraAlerts = alerts; | ||
| this.render(); |
There was a problem hiding this comment.
Wire GATRA alert data into the new map layer path
The new setGatraAlerts entry point is never called anywhere in src, so this.gatraAlerts remains empty and the added render guard (mapLayers.gatraAlerts && this.gatraAlerts.length > 0) keeps the GATRA layer from ever drawing markers even when the toggle is enabled.
Useful? React with 👍 / 👎.
| export const DEFAULT_PANELS = SITE_VARIANT === 'tech' ? TECH_PANELS : SITE_VARIANT === 'finance' ? FINANCE_PANELS : FULL_PANELS; | ||
| export const DEFAULT_MAP_LAYERS = SITE_VARIANT === 'tech' ? TECH_MAP_LAYERS : SITE_VARIANT === 'finance' ? FINANCE_MAP_LAYERS : FULL_MAP_LAYERS; | ||
| export const MOBILE_DEFAULT_MAP_LAYERS = SITE_VARIANT === 'tech' ? TECH_MOBILE_MAP_LAYERS : SITE_VARIANT === 'finance' ? FINANCE_MOBILE_MAP_LAYERS : FULL_MOBILE_MAP_LAYERS; | ||
| export const DEFAULT_PANELS = SITE_VARIANT === 'tech' ? TECH_PANELS : SITE_VARIANT === 'finance' ? FINANCE_PANELS : SITE_VARIANT === 'cyber' ? CYBER_PANELS : FULL_PANELS; |
There was a problem hiding this comment.
Align cyber panel defaults with actual feed loading
Switching SITE_VARIANT === 'cyber' to CYBER_PANELS exposes cyber-only news panels (for example indonesia, threats, malware), but news loading still iterates FEEDS from config/feeds.ts which has no cyber branch, so these default-enabled panels do not receive updates and stay empty/loading in cyber builds.
Useful? React with 👍 / 👎.
|
thank you @ghifiardi Currently this can't be merged P1 - HighBuild is currently broken. The gatra-soc panel is configured but never instantiated in the app.src/config/panels.ts:393 enables the panel, but src/App.ts:2092 creates no GATRA panel instance. GATRA map data path is incomplete, so the map layer cannot be populated.src/components/DeckGLMap.ts:3309 adds setGatraAlerts, but MapContainer has no corresponding setter around its data API (compare src/components/MapContainer.ts:320). Cyber variant is only partially wired into product flows.SITE_VARIANT persistence/recognition still only handles full|tech|finance in src/config/variant.ts:4. P2 - MediumDuplicate, unused panel implementations increase maintenance risk. Integration + Value Assessment
|
Instantiate GatraSOCDashboardPanel for cyber variant, add loadGatraData() method with 60s refresh cycle, wire gatraAlerts layer toggle, and add setGatraAlerts() proxy in MapContainer. Also adds cyber variant to the header switcher and enables local variant switching on localhost. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Feedback pls @ghifiardi |
Summary
src/gatra/connector.ts— Unified connector that fetches all GATRA 5-agent pipeline data (ADA alerts, TAA analyses, CRA actions, agent health, correlations) in parallel with pub/sub snapshot notificationssrc/panels/gatra-soc-panel.ts— Enhanced dashboard panel with agent status dots, incident stats, severity-colored alert feed, TAA threat analysis (actor/campaign/kill-chain), CRA response actions, and dynamic World Monitor correlation insightssrc/layers/gatra-alerts-layer.ts— Standalone deck.gl layer factory with severity-colored ScatterplotLayer markers and pulsing rings for critical/high alertssrc/services/gatra.tswith TAA analysis, correlation, and typed CRA action mock data using realistic Indonesian locations (Jakarta, Surabaya, Bandung, Medan, Makassar) and IOH infrastructure referencescreateGatraAlertsLayers()method in DeckGLMap.tsgatraAlertsfield to all variant MapLayers definitions (finance, full, tech, e2e harnesses)Test plan
npx tsc --noEmitpasses with zero errorscybervariant and confirm GATRA SOC panel renders with all 6 sections🤖 Generated with Claude Code