feat: GATRA Cyber SOC with CISA KEV live feed + Gulf Air Traffic#1156
feat: GATRA Cyber SOC with CISA KEV live feed + Gulf Air Traffic#1156ghifiardi wants to merge 1256 commits intokoala73:mainfrom
Conversation
Follow llmstxt.org standard so LLMs can understand the project. Concise version (~5KB) and extended version (~21KB) with full data layers, sources, and architecture details.
Add Turkish (tr) as the 14th supported language with full translation of all 1,134 locale keys, locale loader, tr-TR formatting, and flag mapping. Update documentation to reflect 14 languages.
Move pattern from beforeSend extension-only check to ignoreErrors array. All 16 events were iOS Safari with no stack trace — stale cached assets after deploys, not actionable bugs.
…ions - Add i18n keys for all 9 strategic posture theater names (Iran Theater, Baltic Theater, Taiwan Strait, etc.) across all 14 languages - Wire StrategicPosturePanel to use t() for theater display names with fallback to English if key is missing - Include webcam region button translations (ALL, MIDEAST, EUROPE, etc.) that were missing from deployed locale files Fixes koala73#121
- CIIPanel: use existing t('components.cii.noSignals') for empty state
- CountryBriefPage: localize level badge and trend indicator labels
- ETFFlowsPanel: localize summary labels, table headers, net direction
- LiveWebcamsPanel: localize region filter tab labels
- MacroSignalsPanel: localize verdict, signal names, and bullish count
- StrategicRiskPanel: localize score levels, trend label, and trend values
Add Ollama as the primary summarization provider for desktop builds, sitting before Groq/OpenRouter in the fallback chain. This enables fully local, unlimited LLM inference via Ollama's OpenAI-compatible endpoint (/v1/chat/completions). Changes across six layers: - runtime-config: OLLAMA_API_URL + OLLAMA_MODEL secret keys, aiOllama feature toggle (default on), URL validation - sidecar: allowlist + endpoint probe validation (tries /v1/models then /api/tags) - api/ollama-summarize.js: new handler mirroring Groq/OpenRouter with shared Redis cache keys - summarization.ts: tryOllama() + updated chain order in normal, beta, and translation paths (Ollama → Groq → OpenRouter → Browser T5) - RuntimeConfigPanel: signup URLs + i18n help text for new keys - desktop-readiness: aiOllama in key-backed features + readiness check https://claude.ai/code/session_01AGg9fG6LZ8Y6XhvLszdfeY
…ayers Three test files covering Ollama integration: api/ollama-summarize.test.mjs (9 tests): - Fallback signal when unconfigured, on API error, on empty response - Success path with correct provider label and response shape - Model selection via OLLAMA_MODEL env / default fallback - Network error handling (ECONNREFUSED) - Translate mode prompt verification tests/summarization-chain.test.mjs (7 tests): - Ollama success short-circuits chain (Groq never called) - Ollama fail → Groq success fallback - Full fallback when both unconfigured - Provider label correctness for Ollama and Groq - Uniform response shape across providers - Identical fallback signal shapes src-tauri/sidecar/local-api-server.test.mjs (8 new tests): - OLLAMA_API_URL and OLLAMA_MODEL accepted via env-update allowlist - Unknown keys rejected (403) - Validation via /v1/models probe (reachable mock) - Validation via /api/tags native fallback - OLLAMA_MODEL pass-through validation - Non-http protocol rejection (422) - Auth-required behavior preserved with token https://claude.ai/code/session_01AGg9fG6LZ8Y6XhvLszdfeY
Server-side: extract shared CORS, validation, caching, prompt building, and response shaping into api/_summarize-handler.js factory. Each endpoint (Groq, OpenRouter, Ollama) becomes a thin wrapper calling createSummarizeHandler() with a provider config: credentials, API URL, model, headers, and provider label. Client-side: replace three near-identical tryOllama/tryGroq/tryOpenRouter functions with a single tryApiProvider() driven by an API_PROVIDERS config array. Add runApiChain() helper that loops the chain with progress callbacks. Simplify translateText() from three copy-pasted blocks to a single loop over the same provider array. - groq-summarize.js: 297 → 30 lines - openrouter-summarize.js: 295 → 33 lines - ollama-summarize.js: 289 → 34 lines - summarization.ts: 336 → 239 lines - New _summarize-handler.js: 315 lines (shared) - Net: -566 lines of duplication removed Adding a new LLM provider now requires only a provider config object in the endpoint file + one entry in the API_PROVIDERS array. Tests: 13 new tests for the shared factory (cache key, dedup, handler creation, fallback, error casing, HTTP methods). All 42 existing tests pass unchanged. https://claude.ai/code/session_01AGg9fG6LZ8Y6XhvLszdfeY
- Use for...of entries() instead of index-based loops in summarization.ts to satisfy strict noUncheckedIndexedAccess (7 TS18048/TS2345 errors) - Replace fragile API_PROVIDERS[1] with .find(p => p.name === groq) - Add OLLAMA_API_URL and OLLAMA_MODEL to SUPPORTED_SECRET_KEYS in main.rs so keychain secrets are injected into sidecar on desktop startup
…and Ollama UX - Split settings window into 3 tabs: LLMs (Ollama/Groq/OpenRouter), API Keys (data feeds), and Debug & Logs - Add featureFilter option to RuntimeConfigPanel for rendering subsets - Consolidate keychain to single JSON vault entry (1 macOS prompt vs 20) - Add Ollama model discovery with /api/tags + /v1/models fallback - Strip <think> reasoning tokens from Ollama responses - Suppress thinking with think:false in Ollama request body - Parallel secret verification with 15s global timeout - Fix manual model input overlapping dropdown (CSS grid-area + hidden-input class) - Add loading spinners to settings tab panels - Suppress notification popups when settings window is open - Filter embed models from Ollama dropdown - Fix settings window black screen flash with inline dark background
Add local LLM support mentions across feature descriptions, talking points, screenshot suggestions, and changelog. New dedicated section for Ollama/LM Studio as feature koala73#11.
DeckGLMap: guard updateLayers/debounce/raf against null maplibreMap, null out references in destroy() to prevent post-destroy setProps crash. main.ts: filter contentWindow.postMessage (Facebook WebView), vertex shader compile (GPU driver), objectStoreNames (iOS background), Unexpected identifier https (Safari 16), _0x obfuscated vars (extensions), WKWebView deallocated (Tauri lifecycle).
…koala73#124) ## Summary Extracts shared summarization logic (CORS, validation, caching, prompt building) into a reusable `_summarize-handler.js` factory, then uses it to add Ollama as the first provider in the fallback chain. This reduces code duplication across Groq, OpenRouter, and the new Ollama endpoint while maintaining identical behavior. **Fallback chain is now:** Ollama → Groq → OpenRouter → Browser T5 ## Type of change - [x] New feature - [x] Refactor / code cleanup - [x] API endpoints (`/api/*`) ## Affected areas - [x] AI Insights / World Brief - [x] Desktop app (Tauri) - [x] API endpoints (`/api/*`) - [x] Config / Settings ## Changes ### New Files - **`api/_summarize-handler.js`** – Shared handler factory with: - `createSummarizeHandler(providerConfig)` – Creates edge handlers for any LLM provider - `getCacheKey()` – Stable cache key generation (extracted from per-provider code) - `deduplicateHeadlines()` – Headline deduplication logic (extracted from per-provider code) - Unified prompt building for brief/analysis/translate modes with tech/full variants - CORS, validation, caching, and error handling pipeline - **`api/ollama-summarize.js`** – New Ollama endpoint (34 lines): - Calls local/remote Ollama instance via OpenAI-compatible `/v1/chat/completions` - Reads `OLLAMA_API_URL` and `OLLAMA_MODEL` from environment - Shares Redis cache with Groq/OpenRouter (same cache key strategy) - Returns fallback signal when unconfigured or API fails - **`api/ollama-summarize.test.mjs`** – Unit tests for Ollama endpoint: - Fallback signal when `OLLAMA_API_URL` not configured - Success response with provider="ollama" - Error handling (API errors, empty responses) - Model selection via `OLLAMA_MODEL` env - **`api/_summarize-handler.test.mjs`** – Unit tests for shared factory: - Cache key stability and variation by mode/variant/lang/geoContext - Headline deduplication logic - Handler creation with missing credentials - API provider calls and response shaping - **`tests/summarization-chain.test.mjs`** – Integration tests for fallback chain: - Ollama success short-circuits (no downstream calls) - Ollama failure → Groq success - Both fail → fallback signals propagate ### Modified Files **`api/groq-summarize.js`** & **`api/openrouter-summarize.js`** - Replaced ~290 lines of duplicated logic with single call to `createSummarizeHandler()` - Now thin wrappers: 26 lines (Groq) and 28 lines (OpenRouter) - Identical behavior, zero functional changes **`src/services/summarization.ts`** - Updated fallback chain: `Ollama → Groq → OpenRouter → Browser T5` - Refactored `tryGroq()` and `tryOpenRouter()` into unified `tryApiProvider()` function - Added `API_PROVIDERS` config array for provider ordering - Updated `SummarizationProvider` type to include `'ollama'` **`src-tauri/sidecar/local-api-server.mjs`** - Added `OLLAMA_API_URL` and `OLLAMA_MODEL` to `ALLOWED_ENV_KEYS` - Added validation for `OLLAMA_API_URL` in `validateSecretAgainstProvider()`: - Probes `/v1/models` (OpenAI-compatible endpoint) - Falls back to `/api/tags` (native Ollama endpoint) - Returns "Ollama endpoint verified" or "Ollama endpoint verified (native API
…buffers Toggling cables/pipelines off then on caused deck.gl assertion failure because the cached PathLayer had its WebGL resources destroyed on removal.
…USNI News, Oryx OSINT, UK MOD)
…keychain vault - Ollama/LM Studio integration with auto model discovery and 4-tier fallback chain - Settings window split into LLMs, API Keys, and Debug tabs - Consolidated keychain vault (1 OS prompt instead of 20+) - README expanded with privacy architecture, summarization chain docs - CHANGELOG updated with full v2.5.0 release notes - 5 new defense/intel RSS feeds, Koeberg nuclear plant added
Removes circular dev→prod dependency. The new polymarketPlugin() mirrors the edge function logic locally: validates params, fetches from gamma-api.polymarket.com, and gracefully returns [] when Cloudflare JA3 blocks server-side TLS (expected behavior).
The Vite dev plugin was hardcoding `{ videoId: null }` with a TODO,
causing LiveNewsPanel to never resolve actual live streams during local
development. Replace the stub with the same fetch-and-scrape approach
used by the production edge function (api/youtube/live.js): fetch the
channel's /live page and extract videoId + isLive from the HTML.
https://claude.ai/code/session_01684qa7XvS7sf9CShqU8zNg
Store the interval ID returned by setInterval in a new clockIntervalId field and clear it in App.destroy(). Previously, the interval was never stored or cleared, causing DOM writes to double on each Vite HMR reload. https://claude.ai/code/session_0111CXxXM5qKR83UAdUTQDyL
npm install regenerated the lockfile to reflect the current version (2.5.0) and license field from package.json. https://claude.ai/code/session_01684qa7XvS7sf9CShqU8zNg
…eived load Inline a minimal HTML skeleton (header bar, map placeholder, panels grid) with critical CSS directly in index.html so the page shows a structured layout immediately instead of a blank screen while JavaScript boots. - Dark theme skeleton with hardcoded colors matching CSS variables - Light theme support via [data-theme="light"] selectors - Shimmer animation on placeholder lines for visual feedback - 6 skeleton panels in a responsive grid matching the real layout - Map section with radial gradient matching the map background - Skeleton is automatically replaced when App.renderLayout() sets innerHTML - Marked aria-hidden="true" for screen reader accessibility Expected gain: perceived load time drops to <0.5s. https://claude.ai/code/session_01Fxk8GMRn2cEUq3ThC2a8e5
Wires the real /a2a endpoint back into the A2A Security Monitor panel as an interactive control plane with three new sections: - ENDPOINT HEALTH: live status indicator that pings the real A2A endpoint every 30s, shows latency, A2A version, security headers - A2A CONSOLE: interactive message input with skill selector dropdown, sends real JSON-RPC to the live endpoint, displays structured responses with agent routing, task IDs, and timing - SECURITY TEST SUITE: one-click test cards for injection block, role impersonation, IOC lookup, bad method, parse error, and replay attack — each hits the real endpoint and shows pass/fail/warn The panel is now a fully functional live control plane for the A2A security middleware deployed in Phase 3. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
IOC Scanner now calls real VirusTotal + AbuseIPDB APIs: - IP lookup: AbuseIPDB check + VirusTotal IP report (parallel) - Hash lookup: VirusTotal file report with threat classification - Domain lookup: VirusTotal domain analysis with categorization - 5-minute in-memory cache, 6s fetch timeout, graceful fallback - Env vars: VIRUSTOTAL_API_KEY, ABUSEIPDB_API_KEY TAA now uses real MITRE ATT&CK enrichment: - 60-technique database with keywords, tactics, severity, detection - Keyword-to-technique matching with relevance scoring - Kill chain stage derivation from matched tactics - Per-technique detection guidance and tactical recommendations ADA also benefits from MITRE keyword matching for its ATT&CK line. CRA/CLA/RVA remain template-based (need SOAR/ML/BigQuery backends). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Detect HTTP 429 from VT and show clear rate limit message - Don't cache rate-limited results - Better fallback messages with diagnostic info - Add error logging for VT API failures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The differentiating feature of GATRA's A2A security: geopolitical trust adaptation based on real Country Instability Index scores derived from ACLED conflict data. New GATE 2.5 in the security pipeline (between auth and payload check): - Resolves agent country via Vercel geo, CF geo, TLD, or self-reported header - Looks up ACLED-derived CII score (30+ countries pre-seeded) - Maps to trust tier: STANDARD (CII 0-34), ELEVATED (35-60), CRITICAL (>60) - CRITICAL tier: rejects unless agent is in CII_ALLOWLIST env var - ELEVATED tier: applies tighter per-tier rate limiting - All tiers: CII metadata in audit logs and task security context Trust tier enforcement: - STANDARD: 100 req/hr, standard audit, no JWS required - ELEVATED: 30 req/hr, enhanced audit, JWS + deep injection scan - CRITICAL: 10 req/hr, forensic audit, admin allowlist required Real CII examples: Myanmar 72.8 (CRITICAL), Philippines 38.2 (ELEVATED), Indonesia 22.1 (STANDARD), Afghanistan 89.4 (CRITICAL). Error code: -32050 (CII policy rejection) with remediation guidance. Referenced in IEEE S&P Oakland 2027 paper Section 4.2. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Canonical TypeScript source at lib/cii-trust-policy.ts with full type definitions. Test suite validates tier classification, policy properties, country resolution, allowlist enforcement, and JSON-RPC rejection format. Results feed into IEEE S&P Oakland 2027 Table III. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rces
- Remove dead BSSN RSS feed (bssn.go.id/feed returns 404)
- Replace noisy English-only Google News queries with targeted Indonesian-
language searches ("keamanan siber", "serangan siber", "kebocoran data")
- Add CNN Indonesia Tekno RSS as direct Indonesian tech/security source
- Add Insiden Siber ID feed for ransomware/cyber incident coverage
- Add www.cnnindonesia.com to RSS proxy allowed domains
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
# Conflicts: # api/gatra-data.js # src/App.ts # src/config/feeds.ts # src/config/panels.ts # src/config/variants/cyber.ts # src/gatra/connector.ts # src/locales/en.json # src/panels/gatra-soc-panel.ts # src/services/cve-feed.ts
The rss() helper already calls encodeURIComponent, so feed URLs must use raw characters (quotes, colons) not pre-encoded %22/%3A sequences. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
15-section technical document covering all phases: security middleware, CII trust policy, threat intel integration, MITRE ATT&CK, test suite, and Indonesia Cyber panel overhaul. Both .md and .docx formats. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Client-side self-assessment (20 questions, 5 domains) with score ring, trend tracking, sector-aware recommendations, and delegated event handling. All data stored in localStorage only — nothing transmitted. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…r posture - New API endpoint (api/security-check.js) proxies HIBP Pwned Passwords (k-anonymity) and Cloudflare DNS-over-HTTPS for SPF/DMARC/MX checks - 6 client-side browser security checks (HTTPS, DNT, WebRTC leak, etc.) - Password never leaves device — only first 5 chars of SHA-1 hash sent - Email domain DNS checks use public records only - Results graded A–F with actionable per-check recommendations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Drill-down button flies to current center at zoom 14, pitch 60°, bearing 30° - 360° orbit auto-rotates bearing via requestAnimationFrame with 3 speeds (SLOW/MED/FAST) - Drill-down overlay shows zoom, pitch, bearing, lat/lon + reverse-geocoded location name - Overlay auto-shows when zoom > 8 or during drill/orbit mode - Exit drill restores previous view state - Proper cleanup in destroy() for orbit animation and geocode debounce Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Iran War Theater conflict zone (IRGC, Strait of Hormuz, Persian Gulf) - Add Iran Cyber Operations zone (APT33/35, MuddyWater, Shamoon) - Expand GATRA mock locations with Middle East targets (Tehran, Isfahan, Bushehr, Hormuz, Baghdad, Damascus, Riyadh) and global cyber targets (DC, London, Tel Aviv, Kyiv, Singapore) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add drill-down/orbit controls to Map.ts (SVG fallback map) so buttons appear in both DeckGL and SVG modes - Fix CSS selectors: add .map-controls alongside .deckgl-controls for drill-group, drill-btn, orbit-btn, orbit-speed-group - Implement SVG orbit as horizontal pan animation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix TAA agent regex to match named APT groups (Elfin, Charming Kitten, etc.) - Fix LFI/RFI substring collision that caused "APT Elfin" → File Inclusion - Add comprehensive APT knowledge base (10 groups: Iran, Russia, China, NK) - Add VirusTotal API proxy endpoint (api/ioc-lookup.js) - Wire client-side IOC lookup to query VT via server proxy - Configure VIRUSTOTAL_API_KEY in environment Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All cyber variant news panels showed "UNAVAILABLE" because their RSS feed domains (Bleeping Computer, SecurityWeek, The Record, CrowdStrike, Unit 42, Mandiant, etc.) were not in the rss-proxy ALLOWED_DOMAINS list, returning 403 "Domain not allowed" for every request. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Mandiant blog redirects to cloudblog.withgoogle.com — need both in allowlist. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add OpenSky Network proxy edge function and wire up live aircraft tracking for the Gulf region (Persian Gulf, Red Sea, CENTCOM AOR). Shows all flights (commercial as cyan dots, military as red) on the map with tooltips showing callsign, altitude, speed, and heading. - api/flights.js: Vercel edge proxy to OpenSky with 30s cache - fetchAllGulfFlights() service with circuit breaker + cache - GulfFlight type (military/commercial classification) - Gulf flights ScatterplotLayer in DeckGLMap - Enabled flights layer by default in cyber variant Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
OpenSky Network was timing out for the large CENTCOM 30°×30° bbox. Split into 4 smaller regional bboxes (Persian Gulf, Western Gulf, Red Sea/Yemen, Turkey/Syria/Iran) queried in parallel and deduped. Increased edge proxy timeout from 15s to 25s. Cache bumped to 60s. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Edge runtime was getting 'internal error' when connecting to OpenSky (likely IP blocking or TLS issues with Cloudflare edge). Node.js serverless function has better compatibility with slow upstream APIs. Added User-Agent header and 30s maxDuration config. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The fetch/undici API was failing with 'fetch failed' from Vercel serverless. Switch to native https.request for more reliable connectivity to OpenSky Network. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
OpenSky Network (Swiss) blocks/times out connections from US cloud providers. Deploy the serverless function to Frankfurt region for direct European connectivity. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
OpenSky blocks cloud provider IPs (Vercel/AWS). Switch to airplanes.live free ADS-B data which works reliably from edge. Proxy queries 6 coverage points (250nm radius each) covering Persian Gulf, Saudi, Iraq/Levant, Turkey, Iran, Yemen/Red Sea. Deduplicates by ICAO hex. Includes native military flag (dbFlags). Edge function with 45s cache. Client parser updated for new format. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bigger dots (radiusMinPixels 4, radius 6k-12k), opacity 0.9. Diagnostic logs at fetch, setGulfFlights, and buildLayers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
airplanes.live supports Access-Control-Allow-Origin: *, so we can call it directly from the browser without a proxy. This eliminates the edge function as a failure point. 6 coverage points queried in parallel, deduped by ICAO hex. Bigger dots (4-12px) for visibility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…owser calls Direct browser→airplanes.live requests (6 parallel) were getting rate-limited, returning empty arrays. The edge proxy makes one browser request and handles the 6 parallel queries server-side with dedup + caching. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lience - Add SITE_VARIANT === 'cyber' to loadIntelligenceSignals gate (initial + refresh) - Switch to sequential direct fetches with timeout to avoid connection exhaustion - Direct airplanes.live as primary source (CORS: *), proxy as fallback Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add api/cisa-kev.js edge function proxying CISA Known Exploited Vulnerabilities catalog (free, no API key, 5-min cache) - Update gatra/connector.ts cascade: GATRA API → CISA KEV → mock Maps real CVEs to GatraAlert type with severity from ransomware usage and due dates, CWE→MITRE ATT&CK mapping, geo-distributed map markers across global tech hubs - Disable /api/gatra-data fetch (BigQuery returning 500 errors) - Reduce GATRA refresh from 60s to 10min - Reduce A2A panel polling from 30s to 5min (saves ~83% serverless invocations per open tab) 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: 9a9ce100ad
ℹ️ 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".
| try { | ||
| const snap = await refreshGatraData(); | ||
| const gatraPanel = this.panels['gatra-soc'] as GatraSOCDashboardPanel | undefined; | ||
| gatraPanel?.refresh(); |
There was a problem hiding this comment.
Avoid triggering a second GATRA refresh
loadGatraData already awaits refreshGatraData(), but then immediately calls gatraPanel?.refresh(), and GatraSOCDashboardPanel.refresh() calls refreshGatraData() again. This means each scheduled GATRA update performs two full upstream fetch cascades back-to-back, doubling BigQuery/CISA traffic and latency on every cycle instead of reusing the snapshot that was just fetched.
Useful? React with 👍 / 👎.
| } | ||
| } | ||
|
|
||
| return aircraft; |
There was a problem hiding this comment.
Raise error when all flight point fetches fail
fetchAllGulfFlights() returns aircraft unconditionally, even when every Promise.allSettled result is rejected, so the handler can return HTTP 200 with total: 0 during complete airplanes.live outages. Because the client proxy path only checks HTTP status, this outage is treated as successful empty data and suppresses fallback/error handling, causing silent data loss in the Gulf flights layer.
Useful? React with 👍 / 👎.
Summary
api/cisa-kev.jsedge function with 5-min cacheapi/flights.jsedge function for Gulf/MENA aircraft coverageTest plan
/api/cisa-kevreturns 50 recent KEV entries🤖 Generated with Claude Code