mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
58e42aadf951d8ea35403cbb60a6cb1792713d61
26 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
58e42aadf9 |
chore(api): enforce sebuf contract + migrate drifting endpoints (#3207) (#3242)
* chore(api): enforce sebuf contract via exceptions manifest (#3207) Adds api/api-route-exceptions.json as the single source of truth for non-proto /api/ endpoints, with scripts/enforce-sebuf-api-contract.mjs gating every PR via npm run lint:api-contract. Fixes the root-only blind spot in the prior allowlist (tests/edge-functions.test.mjs), which only scanned top-level *.js files and missed nested paths and .ts endpoints — the gap that let api/supply-chain/v1/country-products.ts and friends drift under proto domain URL prefixes unchallenged. Checks both directions: every api/<domain>/v<N>/[rpc].ts must pair with a generated service_server.ts (so a deleted proto fails CI), and every generated service must have an HTTP gateway (no orphaned generated code). Manifest entries require category + reason + owner, with removal_issue mandatory for temporary categories (deferred, migration-pending) and forbidden for permanent ones. .github/CODEOWNERS pins the manifest to @SebastienMelki so new exceptions don't slip through review. The manifest only shrinks: migration-pending entries (19 today) will be removed as subsequent commits in this PR land each migration. * refactor(maritime): migrate /api/ais-snapshot → maritime/v1.GetVesselSnapshot (#3207) The proto VesselSnapshot was carrying density + disruptions but the frontend also needed sequence, relay status, and candidate_reports to drive the position-callback system. Those only lived on the raw relay passthrough, so the client had to keep hitting /api/ais-snapshot whenever callbacks were registered and fall back to the proto RPC only when the relay URL was gone. This commit pushes all three missing fields through the proto contract and collapses the dual-fetch-path into one proto client call. Proto changes (proto/worldmonitor/maritime/v1/): - VesselSnapshot gains sequence, status, candidate_reports. - GetVesselSnapshotRequest gains include_candidates (query: include_candidates). Handler (server/worldmonitor/maritime/v1/get-vessel-snapshot.ts): - Forwards include_candidates to ?candidates=... on the relay. - Separate 5-min in-memory caches for the candidates=on and candidates=off variants; they have very different payload sizes and should not share a slot. - Per-request in-flight dedup preserved per-variant. Frontend (src/services/maritime/index.ts): - fetchSnapshotPayload now calls MaritimeServiceClient.getVesselSnapshot directly with includeCandidates threaded through. The raw-relay path, SNAPSHOT_PROXY_URL, DIRECT_RAILWAY_SNAPSHOT_URL and LOCAL_SNAPSHOT_FALLBACK are gone — production already routed via Vercel, the "direct" branch only ever fired on localhost, and the proto gateway covers both. - New toLegacyCandidateReport helper mirrors toDensityZone/toDisruptionEvent. api/ais-snapshot.js deleted; manifest entry removed. Only reduced the codegen scope to worldmonitor.maritime.v1 (buf generate --path) — regenerating the full tree drops // @ts-nocheck from every client/server file and surfaces pre-existing type errors across 30+ unrelated services, which is not in scope for this PR. Shape-diff vs legacy payload: - disruptions / density: proto carries the same fields, just with the GeoCoordinates wrapper and enum strings (remapped client-side via existing toDisruptionEvent / toDensityZone helpers). - sequence, status.{connected,vessels,messages}: now populated from the proto response — was hardcoded to 0/false in the prior proto fallback. - candidateReports: same shape; optional numeric fields come through as 0 instead of undefined, which the legacy consumer already handled. * refactor(sanctions): migrate /api/sanctions-entity-search → LookupSanctionEntity (#3207) The proto docstring already claimed "OFAC + OpenSanctions" coverage but the handler only fuzzy-matched a local OFAC Redis index — narrower than the legacy /api/sanctions-entity-search, which proxied OpenSanctions live (the source advertised in docs/api-proxies.mdx). Deleting the legacy without expanding the handler would have been a silent coverage regression for external consumers. Handler changes (server/worldmonitor/sanctions/v1/lookup-entity.ts): - Primary path: live search against api.opensanctions.org/search/default with an 8s timeout and the same User-Agent the legacy edge fn used. - Fallback path: the existing OFAC local fuzzy match, kept intact for when OpenSanctions is unreachable / rate-limiting. - Response source field flips between 'opensanctions' (happy path) and 'ofac' (fallback) so clients can tell which index answered. - Query validation tightened: rejects q > 200 chars (matches legacy cap). Rate limiting: - Added /api/sanctions/v1/lookup-entity to ENDPOINT_RATE_POLICIES at 30/min per IP — matches the legacy createIpRateLimiter budget. The gateway already enforces per-endpoint policies via checkEndpointRateLimit. Docs: - docs/api-proxies.mdx — dropped the /api/sanctions-entity-search row (plus the orphaned /api/ais-snapshot row left over from the previous commit in this PR). - docs/panels/sanctions-pressure.mdx — points at the new RPC URL and describes the OpenSanctions-primary / OFAC-fallback semantics. api/sanctions-entity-search.js deleted; manifest entry removed. * refactor(military): migrate /api/military-flights → ListMilitaryFlights (#3207) Legacy /api/military-flights read a pre-baked Redis blob written by the seed-military-flights cron and returned flights in a flat app-friendly shape (lat/lon, lowercase enums, lastSeenMs). The proto RPC takes a bbox, fetches OpenSky live, classifies server-side, and returns nested GeoCoordinates + MILITARY_*_TYPE_* enum strings + lastSeenAt — same data, different contract. fetchFromRedis in src/services/military-flights.ts was doing nothing sebuf-aware. Renamed it to fetchViaProto and rewrote to: - Instantiate MilitaryServiceClient against getRpcBaseUrl(). - Iterate MILITARY_QUERY_REGIONS (PACIFIC + WESTERN) in parallel — same regions the desktop OpenSky path and the seed cron already use, so dashboard coverage tracks the analytic pipeline. - Dedup by hexCode across regions. - Map proto → app shape via new mapProtoFlight helper plus three reverse enum maps (AIRCRAFT_TYPE_REVERSE, OPERATOR_REVERSE, CONFIDENCE_REVERSE). The seed cron (scripts/seed-military-flights.mjs) stays put: it feeds regional-snapshot mobility, cross-source signals, correlation, and the health freshness check (api/health.js: 'military:flights:v1'). None of those read the legacy HTTP endpoint; they read the Redis key directly. The proto handler uses its own per-bbox cache keys under the same prefix, so dashboard traffic no longer races the seed cron's blob — the two paths diverge by a small refresh lag, which is acceptable. Docs: dropped the /api/military-flights row from docs/api-proxies.mdx. api/military-flights.js deleted; manifest entry removed. Shape-diff vs legacy: - f.location.{latitude,longitude} → f.lat, f.lon - f.aircraftType: MILITARY_AIRCRAFT_TYPE_TANKER → 'tanker' via reverse map - f.operator: MILITARY_OPERATOR_USAF → 'usaf' via reverse map - f.confidence: MILITARY_CONFIDENCE_LOW → 'low' via reverse map - f.lastSeenAt (number) → f.lastSeen (Date) - f.enrichment → f.enriched (with field renames) - Extra fields registration / aircraftModel / origin / destination / firstSeenAt now flow through where proto populates them. * fix(supply-chain): thread includeCandidates through chokepoint status (#3207) Caught by tsconfig.api.json typecheck in the pre-push hook (not covered by the plain tsc --noEmit run that ran before I pushed the ais-snapshot commit). The chokepoint status handler calls getVesselSnapshot internally with a static no-auth request — now required to include the new includeCandidates bool from the proto extension. Passing false: server-internal callers don't need per-vessel reports. * test(maritime): update getVesselSnapshot cache assertions (#3207) The ais-snapshot migration replaced the single cachedSnapshot/cacheTimestamp pair with a per-variant cache so candidates-on and candidates-off payloads don't evict each other. Pre-push hook surfaced that tests/server-handlers still asserted the old variable names. Rewriting the assertions to match the new shape while preserving the invariants they actually guard: - Freshness check against slot TTL. - Cache read before relay call. - Per-slot in-flight dedup. - Stale-serve on relay failure (result ?? slot.snapshot). * chore(proto): restore // @ts-nocheck on regenerated maritime files (#3207) I ran 'buf generate --path worldmonitor/maritime/v1' to scope the proto regen to the one service I was changing (to avoid the toolchain drift that drops @ts-nocheck from 60+ unrelated files — separate issue). But the repo convention is the 'make generate' target, which runs buf and then sed-prepends '// @ts-nocheck' to every generated .ts file. My scoped command skipped the sed step. The proto-check CI enforces the sed output, so the two maritime files need the directive restored. * refactor(enrichment): decomm /api/enrichment/{company,signals} legacy edge fns (#3207) Both endpoints were already ported to IntelligenceService: - getCompanyEnrichment (/api/intelligence/v1/get-company-enrichment) - listCompanySignals (/api/intelligence/v1/list-company-signals) No frontend callers of the legacy /api/enrichment/* paths exist. Removes: - api/enrichment/company.js, signals.js, _domain.js - api-route-exceptions.json migration-pending entries (58 remain) - docs/api-proxies.mdx rows for /api/enrichment/{company,signals} - docs/architecture.mdx reference updated to the IntelligenceService RPCs Verified: typecheck, typecheck:api, lint:api-contract (89 files / 58 entries), lint:boundaries, tests/edge-functions.test.mjs (136 pass), tests/enrichment-caching.test.mjs (14 pass — still guards the intelligence/v1 handlers), make generate is zero-diff. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(leads): migrate /api/{contact,register-interest} → LeadsService (#3207) New leads/v1 sebuf service with two POST RPCs: - SubmitContact → /api/leads/v1/submit-contact - RegisterInterest → /api/leads/v1/register-interest Handler logic ported 1:1 from api/contact.js + api/register-interest.js: - Turnstile verification (desktop sources bypass, preserved) - Honeypot (website field) silently accepts without upstream calls - Free-email-domain gate on SubmitContact (422 ApiError) - validateEmail (disposable/offensive/typo-TLD/MX) on RegisterInterest - Convex writes via ConvexHttpClient (contactMessages:submit, registerInterest:register) - Resend notification + confirmation emails (HTML templates unchanged) Shared helpers moved to server/_shared/: - turnstile.ts (getClientIp + verifyTurnstile) - email-validation.ts (disposable/offensive/MX checks) Rate limits preserved via ENDPOINT_RATE_POLICIES: - submit-contact: 3/hour per IP (was in-memory 3/hr) - register-interest: 5/hour per IP (was in-memory 5/hr; desktop sources previously capped at 2/hr via shared in-memory map — now 5/hr like everyone else, accepting the small regression in exchange for Upstash-backed global limiting) Callers updated: - pro-test/src/App.tsx contact form → new submit-contact path - src-tauri/sidecar/local-api-server.mjs cloud-fallback rewrites /api/register-interest → /api/leads/v1/register-interest when proxying; keeps local path for older desktop builds - src/services/runtime.ts isKeyFreeApiTarget allows both old and new paths through the WORLDMONITOR_API_KEY-optional gate Tests: - tests/contact-handler.test.mjs rewritten to call submitContact handler directly; asserts on ValidationError / ApiError - tests/email-validation.test.mjs + tests/turnstile.test.mjs point at the new server/_shared/ modules Deleted: api/contact.js, api/register-interest.js, api/_ip-rate-limit.js, api/_turnstile.js, api/_email-validation.js, api/_turnstile.test.mjs. Manifest entries removed (58 → 56). Docs updated (api-platform, api-commerce, usage-rate-limits). Verified: npm run typecheck + typecheck:api + lint:api-contract (88 files / 56 entries) + lint:boundaries pass; full test:data (5852 tests) passes; make generate is zero-diff. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(pro-test): rebuild bundle for leads/v1 contact form (#3207) Updates the enterprise contact form to POST to /api/leads/v1/submit-contact (old path /api/contact removed in the previous commit). Bundle is rebuilt from pro-test/src/App.tsx source change in |
||
|
|
c081556121 |
feat(route-explorer): Sprint 6 — free-tier blur + analytics + docs (#3000)
* feat(route-explorer): Sprint 6 — free-tier blur + analytics + docs
Free-tier treatment:
- Non-PRO users see a public route highlight on the map using only
TRADE_ROUTES + COUNTRY_PORT_CLUSTERS (no PRO RPC calls)
- Left rail blurred with filter:blur(6px) + pointer-events:none
- Tab content replaced with upgrade CTA (startCheckout wired)
- Zero requests to get-route-explorer-lane or get-route-impact for
free users (network-verifiable)
Analytics (8 events, type-safe via UmamiEvent):
- route-explorer:opened (tier, source)
- route-explorer:query (from, to, hs2, cargo, tier)
- route-explorer:tab-switch (tab, tier)
- route-explorer:alternative-selected (corridorId, tier)
- route-explorer:impact-viewed (toIso2, hs2, tier)
- route-explorer:share-copied (tier)
- route-explorer:free-cta-click (from, to, hs2)
- route-explorer:closed (durationSec, queryCount, tier)
- trackGateHit('route-explorer') on first free-tier open per session
Documentation:
- docs/maritime-intelligence.mdx: Route Explorer section with feature list
- CHANGELOG.md + docs/changelog.mdx dual-updated with feature entry
Plan status updated to completed.
E2E Playwright specs deferred: need running dev server + authenticated
PRO session. Manual verification recommended via the test plan in PR.
Plan: docs/plans/2026-04-11-001-feat-worldwide-route-explorer-plan.md
* fix(route-explorer): free-tier highlight matches server logic
1. No-shared-route pairs no longer highlight a fallback route. When
fromIso2 and toIso2 clusters share no routes, applyPublicRouteHighlight
returns early without highlighting, matching the server's noModeledLane
behavior that clears primaryRouteId and geometry.
2. Shared routes are now ranked by cargo-category compatibility before
picking the primary route, matching the server's rankSharedRoutesByCargo
logic. Uses the same CARGO_TO_ROUTE_CATEGORY mapping (tanker→energy,
container→container, bulk→bulk, roro→container) and TRADE_ROUTES
category lookup so free and PRO users see the same primary route for
the same query.
* fix(route-explorer): address PR #3000 review comments
P2: removed redundant trackGateHit from CTA click handler (already
fired once on modal open via gateHitTracked guard; route-explorer:free-
cta-click is the dedicated CTA event).
P2: open() now accepts a source parameter ('cmdk'|'url'|'icon') so
route-explorer:opened events distinguish entry points in Umami.
P2: blurred left rail now sets aria-hidden="true" so screen readers
cannot read gated content. Removed on PRO data load alongside the
blur class.
P2: removed duplicate CSS declarations for .re-content__gate h3,
.re-content__gate ul, and .re-content__upgrade from the earlier
section; Sprint 6 section is now the single source of truth.
|
||
|
|
f482c13d6b |
fix(gateway): gate CDN-Cache-Control on trusted origin (#2496)
* fix(gateway): gate CDN-Cache-Control on trusted origin to close cache bypass No-origin server-side requests (external scrapers) no longer receive a CDN-Cache-Control header, so Vercel CDN never caches their responses. Every request without a trusted origin must reach the edge function, ensuring validateApiKey() always runs and returns 401 for unauthenticated callers. Trusted origins (worldmonitor.app, Vercel previews, Tauri) are unchanged — CDN caching behaviour and hit rates for the app itself are unaffected. * docs: external API usage learnings from aeris-AgentR and HOPEFX * docs: fix markdown lint (blanks around lists) * docs: move external-learnings to separate PR |
||
|
|
e5db9a0700 |
docs: update Mintlify docs for recent features (#1693)
- finance-data.mdx: Add US Treasury customs revenue to Trade Policy section (Revenue tab, free API, FYTD comparison, desktop support) - features.mdx: Expand CMD+K section from 5 categories to full 55 panel coverage with organized subcategories - data-sources.mdx: Update advisory section for gold standard migration (Railway seed, 265-entry country map, relay proxy) - architecture.mdx: Add 12 missing seed scripts to Railway pipeline table (forecasts, conflict-intel, economy, supply-chain-trade, security-advisories, usni-fleet, gdelt-intel, research, etc.) - changelog.mdx + CHANGELOG.md: Add unreleased entries for customs revenue, advisory migration, CMD+K coverage, R2 traces, and 6 fixes |
||
|
|
14bc59e543 |
fix(supply-chain): correct PortWatch ArcGIS URL and field mappings (#1572)
* fix(supply-chain): correct PortWatch ArcGIS URL, field names, and chokepoint mappings The PortWatch seed was failing silently because: 1. Wrong service name: portal_chokepoint_daily -> Daily_Chokepoints_Data 2. Wrong query fields: chokepoint/observation_date -> portname/date (epoch) 3. Wrong data model: expected one row per vessel type, actual schema has all counts as columns (n_tanker, n_cargo, n_total) per row 4. Wrong chokepoint names: e.g. "Strait of Malacca" -> "Malacca Strait", "Bab el-Mandeb" -> "Bab el-Mandeb Strait", "Bosphorus" -> "Bosporus Strait" 5. Removed Dardanelles (not in PortWatch dataset) Discovered via IMF PortWatch ArcGIS service directory and returnDistinctValues query on the portname field. * feat(supply-chain): add Korea, Dover, Kerch, Lombok chokepoints Extend from 10 to 14 monitored chokepoints using PortWatch data availability. All 4 new straits have IMF PortWatch coverage. - Korea Strait: Japan-Korea trade, busiest East Asia corridor - Dover Strait: world's busiest shipping lane - Kerch Strait: war_zone (Russia controls, Ukraine grain restricted) - Lombok Strait: Malacca bypass for VLCCs Added to: handler config, canonical ID map, PortWatch seed names, AIS relay transit counter, tests. * docs: update maritime docs and changelog for 14 chokepoints + transit intelligence - maritime-intelligence.mdx: 9 -> 14 chokepoints, add data source descriptions, add chart rendering note - changelog.mdx + CHANGELOG.md: add [Unreleased] section for #1560 and #1572 * fix(tests): update portwatch test for pre-aggregated column model pwClassifyVesselType was removed when switching to pre-aggregated n_tanker/n_cargo/n_total columns. Update test to verify the new field names instead. * fix(supply-chain): sync canonical PortWatch names with actual ArcGIS feed P1: Dardanelles has no PortWatch data (0 rows). Set portwatchName to empty string so it won't attempt fetch or show phantom zero history. P2: portwatchNameToId() returned undefined for Malacca Strait, Bab el-Mandeb Strait, Gibraltar Strait, Bosporus Strait because canonical map used old names instead of actual ArcGIS portname values. Fixed mappings: Strait of Malacca -> Malacca Strait Bab el-Mandeb -> Bab el-Mandeb Strait Strait of Gibraltar -> Gibraltar Strait Bosphorus -> Bosporus Strait Dardanelles -> '' (not in PortWatch) * refactor(supply-chain): merge Dardanelles into Turkish Straits IMF PortWatch tracks Bosphorus+Dardanelles as a single corridor (Bosporus Strait). Keeping them separate caused double-counting in AIS transit data and left Dardanelles with permanently empty history. - Merge into single "Turkish Straits" entry (id stays 'bosphorus') - Absorb all Dardanelles keywords (canakkale, gallipoli, aegean) - Single wider AIS geofence (lat 40.70, lon 28.0, radius 1.5) - 14 -> 13 chokepoints - Update docs, changelog, tests * fix: rename Turkish Straits to Bosporus Strait (match PortWatch naming) |
||
|
|
f26c1b3016 |
chore: bump version to 2.6.1 with changelog (#1410)
Release 2.6.1 covering blog platform, country intelligence, satellite imagery overhaul, and numerous fixes since 2.6.0. |
||
|
|
c63c9c6281 |
docs: add v2.6.0 changelog (#1298)
Covers ~160 commits since v2.5.25 including orbital surveillance, premium finance suite, self-hosted PMTiles basemap, GPS jamming v2, military flights overhaul, Pro waitlist/landing page, commodity variant, and comprehensive health check system. |
||
|
|
c2f17dec45 |
fix(supply-chain): resolve P1 threat zeroing and P2 geo-first misclassification (#964)
* enhance supply chain panel * fix(supply-chain): resolve P1 threat zeroing and P2 geo-first misclassification P1: threat baseline is now always applied regardless of config staleness — stale config only adds a review-recommended note, never zeros the score. P2: resolveChokepointId now checks text evidence first and only falls back to proximity when text has no confident match. Adds regression test: text "Bab el-Mandeb" with location near Suez correctly resolves to bab_el_mandeb. --------- Co-authored-by: fayez bast <fayezbast15@gmail.com> |
||
|
|
6f06373423 | docs: add v2.5.24 changelog (76 commits since v2.5.23) (#862) | ||
|
|
566552fc01 |
docs(changelog): add v2.5.21 entry covering 86 merged PRs (#616)
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. |
||
|
|
9613d05815 | fix(docs): add blank lines after CHANGELOG headings for markdownlint (#608) | ||
|
|
b4638b281e |
chore: bump version to 2.5.20 + changelog
Covers PRs #452–#484: Cloudflare edge caching, commodities SWR fix, security advisories panel, settings redesign, 52 POST→GET migrations. |
||
|
|
012907ae84 |
chore: bump v2.5.10 and update README for recent fixes (#408)
* chore: bump v2.5.10 and update README for recent fixes Version 2.5.9 → 2.5.10. Roadmap entries for: - Yahoo Finance rate-limit UX across all market panels - Sidecar auth resilience (401-retry, settings diagFetch) - Verbose toggle persistence to writable data directory - Finnhub-to-Yahoo fallback routing * chore: add v2.5.10 changelog entry |
||
|
|
eafc4cb955 | chore: bump version to 2.5.6 with changelog (#272) | ||
|
|
48f8e24353 | release: v2.5.2 — quota guard, map race fixes, Vercel build skip fix | ||
|
|
7440281d71 | release: v2.5.1 — batch FRED, parallel UCDP, partial cache TTL, bot middleware | ||
|
|
fce6c52970 |
release: v2.5.0 — Ollama/LM Studio local LLM support, settings tabs, 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 |
||
|
|
572f380856 |
release: v2.4.0 — live webcams, mobile detection fix, sentry triage
- Live Webcams Panel with region filters and grid/single view (#111) - Mobile detection: width-only, touch notebooks get desktop layout (#113) - Le Monde RSS URL fix, workbox precache HTML, panel ordering migration - Sentry: ML timeout catch, YT player guards, maplibre noise filters - Changelog for v2.4.0 |
||
|
|
922092c653 | docs: add v2.3.9 changelog | ||
|
|
9a31eeba09 | chore(release): finalize 2.3.8 changelog and version | ||
|
|
a524ab3ad7 |
merge(main): integrate finance variant and resilience hardening
Merge branch 'feature/finance-variant' into main. Changelog (2.3.8): - add dedicated finance variant with finance/trading focused feeds, panels, and desktop profile - stage feed category loading with bounded concurrency to reduce startup pressure - add AI classification admission control and tighter non-finance budgets - harden external source behavior (Polymarket fallback probing, FRED graceful empty payloads) - replace brittle MarketWatch direct RSS usage with resilient Google News fallbacks across variants - keep finance data-rich panels while adding news panels, and ensure first-class desktop Deck.GL behavior |
||
|
|
88ad25cb93 |
release: v2.3.7
Full light mode theme, header dark/light toggle, desktop update checker, bundled Node.js in installer, CORS fixes, and panel defaults update. |
||
|
|
8f8d07c3a1 |
docs: fix stale documentation across project
- CHANGELOG: add missing v2.3.5 and v2.3.6 entries - README: update API edge function count (45+ → 60+), port count (84 → 83), desktop secret key count (15 → 17) - DOCUMENTATION: fix version badge (2.1.4 → 2.3.6), CII monitored countries (20 → 22, add Brazil/UAE), add CNBC to live streams, fix vessel database count (50+ → 25+), fix port count (61 → 83), update news source count (80+ → 100+) - DESKTOP_CONFIGURATION: update secret keys list from 13 to 17, add FINNHUB, URLHAUS, OTX, ABUSEIPDB, NASA_FIRMS keys - Remove obsolete ROADMAP.md (all 5 proposed features are already implemented: geographic convergence, CII, temporal anomaly detection, trade route risk, infrastructure cascade) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
7d3b600364 |
fix: strip UNC path prefix for Windows sidecar, set explicit CWD & bump v2.3.4
Tauri resource_dir() on Windows returns \\?\ extended-length paths that Node.js module resolution cannot handle, causing EISDIR: lstat 'C:'. Strip the prefix before passing to Node.js, set current_dir to the sidecar directory, and add package.json with "type": "module" to prevent ESM scope walk-up to drive root. |
||
|
|
f3581a5f9b |
fix: enable macOS Keychain backend for keyring crate & bump v2.3.3
keyring v3 ships with NO default platform backends — API keys were stored in-memory only, lost on every app restart. Add apple-native and windows-native features to use real OS credential stores. |
||
|
|
723279eedc |
chore: bump v2.3.0 — security hardening release with changelog
Major security hardening: CORS enforcement on all API endpoints, sidecar auth bypass fix, postMessage origin validation, CSP tightening, and service worker stale cache fix. |