feat: implement deduct situation feature (#636)#642
Merged
koala73 merged 157 commits intokoala73:mainfrom Mar 1, 2026
Merged
Conversation
) * feat: add Security Advisories panel with government travel advisory feeds Adds a new panel aggregating travel/security advisories from official government foreign affairs agencies (US State Dept, AU DFAT Smartraveller, UK FCDO, NZ MFAT). Advisories are categorized by severity level (Do Not Travel, Reconsider, Caution, Normal) with filter tabs by source country. Includes summary counts, auto-refresh, and persistent caching via the existing data-freshness system. * chore: update package-lock.json * fix: event delegation, localization, and cleanup for SecurityAdvisories panel P1 fixes: - Use event delegation on this.content (bound once in constructor) instead of direct addEventListener after each innerHTML replacement — prevents memory leaks and stale listener issues on re-render - Use setContent() consistently instead of mixing with this.content.innerHTML - Add securityAdvisories translations to all 16 non-English locale files (panels name, component strings, common.all key) - Revert unrelated package-lock.json version bump P2 fixes: - Deduplicate loadSecurityAdvisories — loadIntelligenceData now calls the shared method instead of inlining duplicate fetch+set logic - Add Accept header to fetch calls for better content negotiation * feat(advisories): add US embassy alerts, CDC, ECDC, and WHO health feeds Adds 21 new advisory RSS feeds: - 13 US Embassy per-country security alerts (TH, AE, DE, UA, MX, IN, PK, CO, PL, BD, IT, DO, MM) - CDC Travel Notices - 5 ECDC feeds (epidemiological, threats, risk assessments, avian flu, publications) - 2 WHO feeds (global news, Africa emergencies) Panel gains a Health filter tab for CDC/ECDC/WHO sources. All new domains added to RSS proxy allowlist. i18n "health" key added across all 17 locales.
) When upstream APIs return errors (HTTP 403, 429, timeout), fetchers return null. Previously null results were not cached, causing repeated request storms against broken APIs every refresh cycle. Now caches a sentinel value ('__WM_NEG__') with a short 2-minute TTL on null results. Subsequent requests within that window get null immediately without hitting upstream. Thrown errors (transient) skip sentinel caching and retry immediately. Also filters sentinels from getCachedJsonBatch pipeline reads and fixes theater posture coalescing test (expected 2 OpenSky fetches for 2 theater query regions, not 1).
…la73#468) * feat: convert 52 API endpoints from POST to GET for edge caching Convert all cacheable sebuf RPC endpoints to HTTP GET with query/path parameters, enabling CDN edge caching to reduce costs. Flatten nested request types (TimeRange, PaginationRequest, BoundingBox) into scalar query params. Add path params for resource lookups (GetFredSeries, GetHumanitarianSummary, GetCountryStockIndex, GetCountryIntelBrief, GetAircraftDetails). Rewrite router with hybrid static/dynamic matching for path param support. Kept as POST: SummarizeArticle, ClassifyEvent, RecordBaselineSnapshot, GetAircraftDetailsBatch, RegisterInterest. Generated with sebuf v0.9.0 (protoc-gen-ts-client, protoc-gen-ts-server). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add rate_limited field to market response protos The rateLimited field was hand-patched into generated files on main but never declared in the proto definitions. Regenerating wiped it out, breaking the build. Now properly defined in both ListEtfFlowsResponse and ListMarketQuotesResponse protos. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: remove accidentally committed .planning files Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
….app (koala73#471) Route web production RPC traffic through api.worldmonitor.app via fetch interceptor (installWebApiRedirect). Add default Cache-Control headers (s-maxage=300, stale-while-revalidate=60) on GET 200 responses, with no-store override for real-time endpoints (vessel snapshot). Update CORS to allow GET method. Skip Vercel bot middleware for API subdomain using hostname check (non-spoofable, replacing CF-Ray header approach). Update desktop cloud fallback to route through api.worldmonitor.app.
BETA_MODE now couples the badge AND model loading — the summarization-beta model starts loading on startup instead of waiting for the first summarization call.
…oala73#472) Vercel's `api/[domain]/v1/[rpc].ts` captures one dynamic segment. Path params like `/get-humanitarian-summary/SA` add an extra segment that has no matching route file, causing 404 on both OPTIONS preflight and direct requests. These endpoints were broken in production. Changes: - Remove `{param}` from 5 service.proto HTTP paths - Add `(sebuf.http.query)` annotations to request message fields - Update generated client/server code to use URLSearchParams - Update OpenAPI specs (YAML + JSON) to declare query params - Add early-return guards in 4 handlers for missing required params - Add happy.worldmonitor.app to runtime.ts redirect hosts Affected endpoints: - GET /api/conflict/v1/get-humanitarian-summary?country_code=SA - GET /api/economic/v1/get-fred-series?series_id=T10Y2Y&limit=120 - GET /api/market/v1/get-country-stock-index?country_code=US - GET /api/intelligence/v1/get-country-intel-brief?country_code=US - GET /api/military/v1/get-aircraft-details?icao24=a12345
… blocks (koala73#473) - Advisory feeds were fetched directly from the browser, hitting CORS on all 21 feeds (US State Dept, AU Smartraveller, US Embassies, ECDC, CDC, WHO). Route through /api/rss-proxy on web, keep proxyUrl for desktop. - Fix double slash in ECDC Avian Influenza URL (323//feed → 323/feed) - Add feeds.news24.com to RSS proxy allowlist (was returning 403)
…a73#474) * fix: move 5 path-param endpoints to query params for Vercel routing Vercel's `api/[domain]/v1/[rpc].ts` captures one dynamic segment. Path params like `/get-humanitarian-summary/SA` add an extra segment that has no matching route file, causing 404 on both OPTIONS preflight and direct requests. These endpoints were broken in production. Changes: - Remove `{param}` from 5 service.proto HTTP paths - Add `(sebuf.http.query)` annotations to request message fields - Update generated client/server code to use URLSearchParams - Update OpenAPI specs (YAML + JSON) to declare query params - Add early-return guards in 4 handlers for missing required params - Add happy.worldmonitor.app to runtime.ts redirect hosts Affected endpoints: - GET /api/conflict/v1/get-humanitarian-summary?country_code=SA - GET /api/economic/v1/get-fred-series?series_id=T10Y2Y&limit=120 - GET /api/market/v1/get-country-stock-index?country_code=US - GET /api/intelligence/v1/get-country-intel-brief?country_code=US - GET /api/military/v1/get-aircraft-details?icao24=a12345 * feat(cache): add tiered edge Cache-Control aligned to upstream TTLs Replace flat s-maxage=300 with 5 tiers (fast/medium/slow/static/no-store) mapped per-endpoint to respect upstream Redis TTLs. Adds stale-if-error resilience headers and X-No-Cache plumbing for future degraded responses. X-Cache-Tier debug header gated behind ?_debug query param.
…ala73#475) - CISA Advisories used dead rss.worldmonitor.app domain (404), switch to rss() helper - Remove Vite build from pre-push hook (tsc already catches errors)
…oala73#476) * fix(tech): use rss() for CISA feed, drop build from pre-push hook - CISA Advisories used dead rss.worldmonitor.app domain (404), switch to rss() helper - Remove Vite build from pre-push hook (tsc already catches errors) * fix(desktop): enable click-to-play for YouTube embeds in WKWebView WKWebView blocks programmatic autoplay in cross-origin iframes regardless of allow attributes, Permissions-Policy, mute-first retries, or secure context. Documented all 10 approaches tested in docs/internal/. Changes: - Switch sidecar embed origin from 127.0.0.1 to localhost (secure context) - Add MutationObserver + retry chain as best-effort autoplay attempts - Use postMessage('*') to fix tauri://localhost cross-origin messaging - Make sidecar play overlay non-interactive (pointer-events:none) - Fix .webcam-iframe pointer-events:none blocking clicks in grid view - Add expand button to grid cells for switching to single view on desktop - Add http://localhost:* to CSP frame-src in index.html and tauri.conf.json
…koala73#477) Stale cached client bundles still send POST to endpoints converted to GET in PR koala73#468, causing 404s. The gateway now parses the POST JSON body into query params and retries the match as GET.
…oala73#478) Add CDN-Cache-Control headers to all proxy endpoints so Cloudflare can cache responses at the edge independently of browser Cache-Control: - RSS: 600s edge + stale-while-revalidate=300 (browser: 300s) - UCDP: 3600s edge (matches browser) - OpenSky: 15s edge (browser: 30s) for fresher flight data - WorldBank: 1800s/86400s edge (matches browser) - Polymarket: 120s edge (matches browser) - Telegram: 10s edge (matches browser) - AIS snapshot: 2s edge (matches browser) Also fixes: - Vary header merging: sendCompressed/sendPreGzipped now merge existing Vary: Origin instead of overwriting, preventing cross-origin cache poisoning at the edge - Stale fallback responses (OpenSky, WorldBank, Polymarket, RSS) now set Cache-Control: no-store + CDN-Cache-Control: no-store to prevent edge caching of degraded responses - All no-cache branches get CDN-Cache-Control: no-store - /opensky-reset gets no-store (state-changing endpoint)
- Tighten AbortError filter to match "AbortError: The operation was aborted" - Filter "The user aborted a request" (normal navigation cancellation) - Filter UltraViewer service worker injection errors (/uv/service/) - Filter Huawei WebView __isInQueue__ injection
* fix(gateway): harden POST→GET shim with scalar guard and size limit - Only convert string/number/boolean values to query params (skip objects, nested arrays, __proto__ etc.) to prevent prototype pollution vectors - Skip body parsing for Content-Length > 1MB to avoid memory pressure * feat: make API base URL configurable via VITE_WS_API_URL Replace hardcoded api.worldmonitor.app with VITE_WS_API_URL env var. When empty, installWebApiRedirect() is skipped entirely — relative /api/* calls stay on the same domain (local installs). When set, browser fetch is redirected to that URL. Also adds VITE_WS_API_URL and VITE_WS_RELAY_URL hostnames to APP_HOSTS allowlist dynamically.
) Vercel's :path* wildcard doesn't match trailing slashes that PostHog SDK appends (e.g. /ingest/s/?compression=...), causing 404s. Switch to :path(.*) which matches all path segments including trailing slashes. Ref: PostHog/posthog#17596
With 20k requests/30min (60% of proxy traffic) and per-PoP caching, a 2s edge TTL expires before the next request from the same PoP arrives, resulting in near-zero cache hits. 10s allows same-PoP dedup while keeping browser TTL at 2s for fresh vessel positions.
…koala73#483) The shared circuit breaker (cacheTtlMs: 0) cached the stocks response, then the stale-while-revalidate path returned that cached stocks data for the subsequent commodities fetch. Skip SWR when caching is disabled.
…policy (koala73#484) - Add 11 missing GET routes to RPC_CACHE_TIER map (8 slow, 3 medium) - Add response-headers side-channel (WeakMap) so handlers can signal X-No-Cache without codegen changes; wire into military-flights and positive-geo-events handlers on upstream failure - Add env-controlled per-endpoint tier override (CACHE_TIER_OVERRIDE_*) for incident response rollback - Add VITE_WS_API_URL hostname allowlist (*.worldmonitor.app + localhost) - Fix fetch.bind(globalThis) in positive-events-geo.ts (deferred lambda) - Add CI test asserting every generated GET route has an explicit cache tier entry (prevents silent default-tier drift)
Covers PRs koala73#452–koala73#484: Cloudflare edge caching, commodities SWR fix, security advisories panel, settings redesign, 52 POST→GET migrations.
…la73#486) Feed has no <pubDate> fields and latest content is from April 2022. Not referenced in any feed config — only in the proxy domain allowlist.
- Add ko.json with all 1606 translation keys matching en.json structure - Register 'ko' in SUPPORTED_LANGUAGES, LANGUAGES display array, and locale map - Korean appears as 🇰🇷 한국어 in the language dropdown
* perf: bootstrap endpoint + polling optimization (phases 3-4)
Replace 15+ individual RPC calls on startup with a single /api/bootstrap
batch call that fetches pre-cached data from Redis. Consolidate 6 panel
setInterval timers into the central RefreshScheduler for hidden-tab
awareness (10x multiplier) and adaptive backoff (up to 4x for unchanged
data). Convert IntelligenceGapBadge from 10s polling to event-driven
updates with 60s safety fallback.
* fix(bootstrap): inline Redis + cache keys in edge function
Vercel Edge Functions cannot resolve cross-directory TypeScript imports
from server/_shared/. Inline getCachedJsonBatch and BOOTSTRAP_CACHE_KEYS
directly in api/bootstrap.js. Add sync test to ensure inlined keys stay
in sync with the canonical server/_shared/cache-keys.ts registry.
* test: add Edge Function module isolation guard for all api/*.js files
Prevents any Edge Function from importing from ../server/ or ../src/
which breaks Vercel builds. Scans all 12 non-helper Edge Functions.
* fix(bootstrap): read unprefixed cache keys on all environments
Preview deploys set VERCEL_ENV=preview which caused getKeyPrefix() to
prefix Redis keys with preview:<sha>:, but handlers only write to
unprefixed keys on production. Bootstrap is a read-only consumer of
production cache — always read unprefixed keys.
* fix(bootstrap): wire sectors hydration + add coverage guard
- Wire getHydratedData('sectors') in data-loader to skip Yahoo Finance
fetch when bootstrap provides sector data
- Add test ensuring every bootstrap key has a getHydratedData consumer
— prevents adding keys without wiring them
* fix(server): resolve 25 TypeScript errors + add server typecheck to CI
- _shared.ts: remove unused `delay` variable
- list-etf-flows.ts: add missing `rateLimited` field to 3 return literals
- list-market-quotes.ts: add missing `rateLimited` field to 4 return literals
- get-cable-health.ts: add non-null assertions for regex groups and array access
- list-positive-geo-events.ts: add non-null assertion for array index
- get-chokepoint-status.ts: add required fields to request objects
- CI: run `typecheck:api` (tsconfig.api.json) alongside `typecheck` to catch
server/ TS errors before merge
…a73#496) * feat(military): server-side military bases with 125K entries + rate limiting (koala73#485) Migrate military bases from 224 static client-side entries to 125,380 server-side entries stored in Redis GEO sorted sets, served via bbox-filtered GEOSEARCH endpoint with server-side clustering. Data pipeline: - Pizzint/Polyglobe: 79,156 entries (Supabase extraction) - OpenStreetMap: 45,185 entries - MIRTA: 821 entries - Curated strategic: 218 entries - 277 proximity duplicates removed Server: - ListMilitaryBases RPC with GEOSEARCH + HMGET + tier/filter/clustering - Antimeridian handling (split bbox queries) - Blue-green Redis deployment with atomic version pointer switch - geoSearchByBox() + getHashFieldsBatch() helpers in redis.ts Security: - @upstash/ratelimit: 60 req/min sliding window per IP - IP spoofing fix: prioritize x-real-ip (Vercel-injected) over x-forwarded-for - Require API key for non-browser requests (blocks unauthenticated curl/scripts) - Input validation: allowlisted types/kinds, regex country, clamped bbox/zoom Frontend: - Viewport-driven loading with bbox quantization + debounce - Server-side grid clustering at low zoom levels - Enriched popup with kind, category badges (airforce/naval/nuclear/space) - Static 224 bases kept as search fallback + initial render * fix(military): fallback to production Redis keys in preview deployments Preview deployments prefix Redis keys with `preview:{sha}:` but military bases data is seeded to unprefixed (production) keys. When the prefixed `military:bases:active` key is missing, fall back to the unprefixed key and use raw (unprefixed) keys for geo/meta lookups. * fix: remove unused 'remaining' destructure in rate-limit (TS6133) * ci: add typecheck:api to pre-push hook to catch server-side TS errors * debug(military): add X-Bases-Debug response header for preview diagnostics * fix(bases): trigger initial server fetch on map load fetchServerBases() was only called on moveend — if the user never panned/zoomed, the API was never called and only the 224 static fallback bases showed.
…tier (koala73#497) - Add 300ms debounce on moveend to prevent rapid pan flooding - Fixes stale-bbox bug where pendingFetch returns old viewport data - Upgrade edge cache tier from medium (5min) to static (1hr) — bases are static infrastructure, aligned with server-side cachedFetchJson TTL - Keep error logging in catch blocks for production diagnostics
…3#498) Replace Math.random() jitter with DJB2 hash seeded by the threat indicator (IP/URL), so the same threat always maps to the same coordinates across requests while different threats from the same country still spread out. Closes koala73#203 Co-authored-by: Chris Chen <fuleinist@users.noreply.github.com>
Replace direct `VAR=value command` syntax with cross-env/cross-env-shell so dev, build, test, and desktop scripts work on Windows PowerShell/CMD. Co-authored-by: facusturla <facusturla@users.noreply.github.com>
…3#504) - Filter null/undefined values before storing in hydration cache to prevent future consumers using !== undefined from misinterpreting null as valid data - Debounce wm:intelligence-updated event handler via requestAnimationFrame to coalesce rapid alert generation into a single render pass - Include alert IDs in StrategicRiskPanel change fingerprint so content changes are detected even when alert count stays the same - Replace JSON.stringify change detection in ServiceStatusPanel with lightweight name:status fingerprint - Document max effective refresh interval (40x base) in scheduler
…oala73#610) - Remove useFallbackOnly from RT channel — RT is HLS-only (banned from YouTube), so the flag was causing undefined videoId on HLS failure instead of graceful offline state - Add response-headers shim to redis-caching test so military flights bbox tests can import list-military-flights.ts - Restore LiveNOW from FOX fallbackVideoId (removed in channel audit)
koala73#612) Reduces upstream RSS polling frequency and extends client-side cache lifetime to lower API load and bandwidth usage.
Comprehensive changelog for 2026-03-01 release including Iran Attacks layer, Telegram Intel panel, OREF sirens, GPS jamming, AviationStack, breaking news alerts, and strategic risk score.
…oala73#618) - Fetch and display alert history waves in OrefSirensPanel (cap 50 most recent) - Last-hour waves highlighted with amber border and RECENT badge - Translate Hebrew history alerts via existing translateAlerts pipeline - Guard formatAlertTime/formatWaveTime against NaN from unparseable OREF dates - Cap relay history bootstrap to 500 records - Add 3-minute TTL to prevent re-fetching history on every 10s poll - Remove dead .oref-footer/.oref-history CSS; add i18n key for history summary
…ull feature parity (koala73#619) - Fix URL restore: lat/lon now override view center when explicitly provided - Fix touch scroll: 8px threshold before drag activation, preventDefault once active - Add location bootstrap: timezone-first detection, optional geolocation upgrade - Enable DeckGL on mobile with deviceMemory capability guard - Add DeckGL state sync on moveend/zoomend for URL param updates - Fix breakpoint off-by-one: JS now uses <= to match CSS max-width: 768px - Add country-click on SVG fallback with CSS transform inversion - Add fitCountry() to both map engines (DeckGL uses fitBounds, SVG uses projection) - Add SVG inertial touch animation with exponential velocity decay - Add mobile map e2e tests for timezone, URL restore, touch, and breakpoint
…koala73#624) - Fix: `this.player.pauseVideo()` → `this.player.pauseVideo?.()` at LiveNewsPanel line 1301 (6 Sentry issues, 33 events) - Noise: Chrome extension "Could not establish connection" - Noise: Safari "webkitCurrentPlaybackTargetIsWireless" internal - Noise: Sentry SDK crash on iOS "a.theme" - Noise: Broaden Can't find variable to include EmptyRanges - Noise: Catch stale cached builds with /this.player.\w+ is not a function/
- Replace manual getCachedJson/setCachedJson with cachedFetchJson for intl delays — prevents thundering herd (concurrent misses each firing 93 API calls independently) - Bump Redis cache TTL from 30min to 2h - Bump frontend polling from 10min to 2h to match server cache - Bump circuit breaker browser cache from 5min to 2h - Bump CDN edge tier from medium (5min) to static (1h) - Bump cache key to v3 to force fresh entry with new TTL
…y ~95% (koala73#622) Phase 1: Force CDN caching on rss-proxy (s-maxage=300 for 2xx, short TTL for errors) — fixes bug where upstream no-cache headers were passed through verbatim, defeating Vercel CDN. Phase 2: Add ListFeedDigest RPC that aggregates all feeds server-side into a single Redis-cached response. Client makes 1 request instead of ~90 per cycle. Includes circuit breaker with persistent cache fallback, per-feed AI reclassification, and headline ingestion parity. Phase 3: Increase polling interval from 5min to 7min to offset CDN cache alignment. New files: - proto/worldmonitor/news/v1/list_feed_digest.proto - server/worldmonitor/news/v1/{_feeds,_classifier,list-feed-digest}.ts - src/services/ai-classify-queue.ts (extracted from rss.ts)
…lay (koala73#625) When RSS cache expires, send If-None-Match/If-Modified-Since headers on revalidation. Upstream 304 responses refresh the cache timestamp and serve cached body with zero bandwidth, cutting egress ~80-95% for feeds that support conditional GET.
…koala73#621) Layer toggles were not updating the browser URL, so shared links would not carry the user's current layer state. Extracted the debounced URL sync to a reusable class method and call it on every layer change.
…la73#626) Audit and raise every cache/poll under 5 min to reduce upstream API pressure and Vercel function invocations across 31 files: Frontend polling: markets 4→8min, crypto 4→8min, predictions 5→10min, natural 5→1hr, cableHealth 5→2hr, oref 10s→2min, maritime 30s→5min, IntelligenceGapBadge 1→3min. Circuit breakers: PizzINT 2→30min, aviation 5→20min, seismology/weather/ outages/statuses/wildfires 5→30min, military-vessels/flights/GDACS/ maritime/polymarket/GDELT 5→10min, chokepoint 5→20min. Server Redis: market-quotes 2→8min, stablecoins 2→8min/5→10min, vessel-snapshot 10s→5min, earthquakes 5→30min, sector 5→10min, predictions/crypto/commodities 5→10min, outages/statuses 5→30min, macro-signals/chokepoints 5→15min, aviation-sim 5→15min. CDN edge: market RPCs fast→medium, infra/seismology fast→slow.
koala73#627) * fix(military): narrow hex ranges and callsign regex to stop civilian false positives (koala73#462) MILITARY_HEX_RANGES used entire country ICAO allocations instead of military-specific sub-ranges (sourced from tar1090-db/ranges.json). This flagged ALL commercial aircraft from Italy, Spain, Japan, India, South Korea, etc. as military activity. Key changes: - Remove A00000-A3FFFF (US civilian N-numbers) — military starts at ADF7C8 - Italy 300000-33FFFF → 33FF00-33FFFF (top 256 codes only) - Spain 340000-37FFFF → 350000-37FFFF (upper 3/4 confirmed military) - Japan 840000-87FFFF removed (no confirmed JASDF sub-range) - France narrowed to 3AA000-3AFFFF + 3B7000-3BFFFF - Germany narrowed to 3EA000-3EBFFF + 3F4000-3FBFFF - India 800000-83FFFF → 800200-8002FF (256 codes) - Canada C00000-C0FFFF → C20000-C3FFFF (upper half) - Remove unconfirmed: South Korea, Sweden, Singapore, Pakistan - Add confirmed: Austria, Belgium, Switzerland, Brazil - Drop overly broad /^[A-Z]{4,}\d{1,3}$/ callsign regex from server * fix(military): constrain short prefixes + add classification tests Move ambiguous 2-letter prefixes (AE, RF, TF, PAT, SAM, OPS, CTF, IRG, TAF) to SHORT_MILITARY_PREFIXES — these now only match when followed by a digit (e.g. AE1234=military, AEE123=Aegean Airlines). Add 97-case test suite covering: - Military callsign detection (19 known patterns) - Short prefix digit gating (6 cases) - Civilian airline non-detection (26 airlines) - Short prefix letter rejection (6 cases) - Military hex range boundaries (7 confirmed ranges) - Civilian hex non-detection (19 codes) - Boundary precision (ADF7C8 start, 33FF00 start, etc.) - No-full-allocation guard (10 countries) * fix: use charAt() instead of bracket indexing for strict TS
…koala73#632) Both keys were added to Rust SUPPORTED_SECRET_KEYS and runtime-config.ts but the sidecar's own ALLOWED_ENV_KEYS was never updated. This caused "key not in allowlist" 403 when saving/verifying these keys from the desktop settings UI. Also adds AviationStack API validation in validateSecretAgainstProvider.
…indow (koala73#633) Three bugs combine to burn 130% CPU when sidecar auth fails: 1. RefreshScheduler resets backoff multiplier to 1 (fastest) on error, causing failed endpoints to poll at base interval instead of backing off. Fix: exponential backoff on errors, same as unchanged-data path. 2. classify-event batch system ignores 401 (auth failure) — only pauses on 429/5xx. Hundreds of classify calls fire every 2s, each wasted. Fix: pause 120s on 401, matching the 429/5xx pattern. 3. Fetch patch retries every 401 (refresh token + retry), doubling all requests to the sidecar even when token refresh consistently fails. Fix: 60s cooldown after a retry-401 still returns 401. Also shrinks settings window from 760→600px (min 620→480) to reduce the empty whitespace below content on all tabs.
|
@fuleinist is attempting to deploy a commit to the Elie Team on Vercel. A member of the Team first needs to authorize it. |
…posture, and tech events with associated backend services and E2E tests.
- Gate DeductionPanel creation behind isDesktopApp check - Gate deduce buttons in StrategicPosturePanel and TechEventsPanel behind isDesktopRuntime() - Remove deduction from FULL_PANELS (runtime-only on desktop) - Add DOMPurify to sanitize marked.parse() output before innerHTML - Revert shared _shared.ts: restore UPSTREAM_TIMEOUT_MS=30_000, hardcoded GROQ_API_URL/MODEL - Define local DEDUCT_TIMEOUT_MS=120_000, DEDUCT_API_URL, DEDUCT_MODEL in handler - Fix dead API key guard: remove 'ollama-local' fallback, skip if no key - Strip all console.log from deduct-situation handler (keep console.error) - Bump max_tokens 500→1500 for meaningful analysis - Fix cache key: deduct:sebuf→deduct:situation - Add 5s client-side rate limit cooldown on submit button - Move @types/marked to devDependencies, add dompurify + @types/dompurify - Add DeductContextDetail shared interface in types/index.ts - Extract buildNewsContext helper to src/utils/news-context.ts - Pass getLatestNews to StrategicPosturePanel constructor - Fix E2E test: .deduction-markdown-content→.deduction-result - Revert emoji escapes in commands.ts to unicode format - Revert variant-switcher whitespace in panel-layout.ts
Generated IranEvent.timestamp is string but consumers expected number. - Coerce timestamps via Number() in data-loader before passing to aggregators - Accept string|number in MapPopup IranEventPopupData interface - Fix scrapedAt fallback type in conflict/index.ts - Coerce timestamp in country-intel.ts and DeckGLMap.ts sort
…ion RPC Reverts all src/generated/ files to origin/main except the intelligence service client/server which retains the new deductSituation RPC added by this PR. Fixes scrapedAt type to match generated number type.
The Gulf Economies panel (PR koala73#667) added this RPC after the feature branch was forked. Bring handler and registration from main.
- P1: Fix event listener leak — store handler ref, remove in destroy()
- P1: Prevent cooldown bypass via requestSubmit when button disabled
- P2: Read process.env inside function body for runtime secret updates
- P3: Use \u{1F9E0} unicode escape in StrategicPosturePanel (consistency)
Merge origin/main into feature/deduct-situation, resolving all conflicts. Re-applied PR-specific changes: DeductionPanel desktop gating, DOMPurify, deductSituation RPC client method, IranEvent timestamp coercion, and missing markNoCacheResponse import.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves #636.
Summary of Changes
DeductSituationRPC endpoint to process timeline and impact deductions, includingqueryandgeo_contextfields.DeductionPanelcomponent into theFULLlayout containing a text area for queries and Markdown-rendering for AI predictions. Available via the command palette (CMD+K-> "deduction").