mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-08-11 13:10:24 +02:00
Use USNI Fleet Tracker as the primary carrier source + small UI fixes (#293)
Background ========== PR #285 set up the seed -> cache -> GDELT model for the carrier tracker to address audit issues #244/#245/#246. The GDELT half of that pipeline hits api.gdeltproject.org's doc API for headline-region keyword matching -- low precision (false centroid positions per #245) AND unreliable (the host times out from some networks, including Docker Desktop on Windows). USNI publishes a weekly Fleet & Marine Tracker with explicit prose like: "The Gerald R. Ford Carrier Strike Group is operating in the Red Sea" "Aircraft carrier USS George Washington (CVN-73) is in port in Yokosuka, Japan" That is a strictly better source for U.S. Navy carrier positions: authoritative, deterministically parseable, weekly cadence. What this PR does ================= New module: backend/services/fetchers/usni_fleet_tracker.py - Pulls USNI's WordPress RSS feeds (site-wide + category, unioned). - Picks the most recent fleet-tracker post by parsed pubDate. - For each carrier in the registry, scans the article body for "is operating in / is in port in / returned to / transiting" near the carrier's name, hull code, or "<name> Carrier Strike Group" variant. Captures the region/port phrase that follows. - Maps the region phrase to coordinates via the existing REGION_COORDS table, with a USNI-phrase alias table for the specific wording USNI uses ("Yokosuka, Japan", "Norfolk, Va.", "Naval Station San Diego", "5th Fleet AOR", etc.). - Returns {hull: position_entry} with position_confidence="recent" and position_source_at = the article's actual publication timestamp (not now()). Politeness ---------- Uses outbound_user_agent("usni-fleet-tracker") so USNI sees a per-install Shadowbroker identifier (Round 7a / PR #292). The article body pages return 403 to non-browser UAs; the WordPress RSS feed serves the full <content:encoded> body and is the supported aggregator path. No browser UA spoofing. carrier_tracker.update_carrier_positions() now runs three phases: 1. Bootstrap from cache (or seed on first run). 2. USNI fleet tracker -- PRIMARY high-confidence source. 3. GDELT -- SECONDARY backfill; can NOT demote a "recent" USNI position to an "approximate" GDELT headline match. Verified live: 6 of 11 carriers picked up real May 18, 2026 positions on first refresh (Eisenhower, Ford, Bush, Roosevelt, Lincoln, Washington). The other 5 weren't mentioned in this week's article (they're in port at homeports with no deployment changes) and kept their cache entries -- which is the correct seed/cache contract from PR #285. Other small fixes bundled in ============================ docker-compose.yml: add the 6 third-party-fetcher opt-in env vars (PREDICTION_MARKETS_ENABLED, FINANCIAL_ENABLED, FIMI_ENABLED, NUFORC_ENABLED, NEWS_ENABLED, CROWDTHREAT_ENABLED). They were documented in .env.example but never wired through compose, so setting them in .env had no effect. frontend/src/components/TopRightControls.tsx: fix 6 broken i18n keys that were showing as raw "terminal.term1" / "terminal.cleanupDetail" / "node.soloReady" placeholders in the INFONET TERMINAL modal. The translation files have these strings under different key names; the component now calls the right ones. Full-file sweep confirmed every other t('...') key in the whole frontend resolves cleanly.
This commit is contained in:
@@ -859,7 +859,7 @@ export default function TopRightControls({
|
||||
}>
|
||||
{activatingPhase === 'done'
|
||||
? (syncOutcomeRaw === 'solo'
|
||||
? `${t('node.soloReady')} — ${nodeStatus?.total_events ?? 0} ${t('node.events')}`
|
||||
? `${t('node.soloNodeReady')} — ${nodeStatus?.total_events ?? 0} ${t('node.events')}`
|
||||
: `${t('node.synced')} — ${nodeStatus?.total_events ?? 0} ${t('node.events')}`)
|
||||
: activatingPhase === 'sync'
|
||||
? `${t('node.syncingChain')}${(nodeStatus?.total_events ?? 0) > 0 ? ` ${nodeStatus?.total_events} ${t('node.events')}` : ''}`
|
||||
@@ -1013,8 +1013,8 @@ export default function TopRightControls({
|
||||
: t('terminal.terminalDetail')}
|
||||
<div className="mt-2 text-[12px] text-cyan-200/70 normal-case tracking-normal">
|
||||
{terminalPrivateReady
|
||||
? t('terminal.enterTerminalDetail')
|
||||
: t('terminal.terminalDetailMore')}
|
||||
? t('terminal.identityReady')
|
||||
: t('terminal.identityNotReady')}
|
||||
</div>
|
||||
</div>
|
||||
{terminalLaunchError && (
|
||||
@@ -1025,15 +1025,15 @@ export default function TopRightControls({
|
||||
<div className="border border-cyan-500/20 bg-black/30 px-4 py-4 text-[12px] font-mono text-slate-200 leading-[1.85]">
|
||||
<div className="text-cyan-300 tracking-[0.18em]">{t('terminal.beforeYouEnter')}</div>
|
||||
<ul className="mt-3 space-y-2 list-disc pl-5">
|
||||
<li>{t('terminal.term1')}</li>
|
||||
<li>{t('terminal.term2')}</li>
|
||||
<li>{t('terminal.term3')}</li>
|
||||
<li>{t('terminal.termTerminal1')}</li>
|
||||
<li>{t('terminal.termTerminal2')}</li>
|
||||
<li>{t('terminal.termTerminal3')}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="border border-amber-500/20 bg-amber-950/10 px-4 py-3 text-[12px] font-mono text-amber-200/80 leading-[1.85]">
|
||||
<div className="text-amber-300 tracking-[0.18em]">{t('terminal.wormholeCleanup')}</div>
|
||||
<div className="mt-2">
|
||||
{t('terminal.wormholeCleanupDetail')}
|
||||
{t('terminal.cleanupDetail')}
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-3 sm:grid-cols-3">
|
||||
|
||||
Reference in New Issue
Block a user