mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-05-28 10:01:31 +02:00
49621824b1
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.
116 lines
5.5 KiB
YAML
116 lines
5.5 KiB
YAML
## Default registry is GHCR because the GitHub release workflow publishes:
|
|
## ghcr.io/bigbodycobain/shadowbroker-backend:latest
|
|
## ghcr.io/bigbodycobain/shadowbroker-frontend:latest
|
|
##
|
|
## GitLab mirror images can still be used by swapping the image lines to:
|
|
## registry.gitlab.com/bigbodycobain/shadowbroker/backend:latest
|
|
## registry.gitlab.com/bigbodycobain/shadowbroker/frontend:latest
|
|
|
|
services:
|
|
backend:
|
|
image: ghcr.io/bigbodycobain/shadowbroker-backend:latest
|
|
container_name: shadowbroker-backend
|
|
ports:
|
|
- "${BIND:-127.0.0.1}:${BACKEND_PORT:-8000}:8000"
|
|
environment:
|
|
- AIS_API_KEY=${AIS_API_KEY:-}
|
|
- OPENSKY_CLIENT_ID=${OPENSKY_CLIENT_ID:-}
|
|
- OPENSKY_CLIENT_SECRET=${OPENSKY_CLIENT_SECRET:-}
|
|
- LTA_ACCOUNT_KEY=${LTA_ACCOUNT_KEY:-}
|
|
- ADMIN_KEY=${ADMIN_KEY:-}
|
|
- FINNHUB_API_KEY=${FINNHUB_API_KEY:-}
|
|
# Override allowed CORS origins (comma-separated). Auto-detects LAN IPs if empty.
|
|
- CORS_ORIGINS=${CORS_ORIGINS:-}
|
|
# Private Infonet bootstrap seeds. Seeds are discovery hints, not fixed roots.
|
|
- MESH_BOOTSTRAP_SEED_PEERS=${MESH_BOOTSTRAP_SEED_PEERS:-http://gqpbunqbgtkcqilvclm3xrkt3zowjyl3s62kkktvojgvxzizamvbrqid.onion:8000}
|
|
- MESH_DEFAULT_SYNC_PEERS=${MESH_DEFAULT_SYNC_PEERS:-}
|
|
# Operator-trusted sync/push peers. Leave empty unless you control the peer secret on both sides.
|
|
- MESH_RELAY_PEERS=${MESH_RELAY_PEERS:-}
|
|
# Shared transport auth for operator peer push. Must be set to a unique secret per deployment.
|
|
- MESH_PEER_PUSH_SECRET=${MESH_PEER_PUSH_SECRET:-}
|
|
# Issue #256: optional per-peer HMAC secrets. Comma-separated
|
|
# `url=secret` pairs (no spaces). When a peer URL appears here, only
|
|
# the listed per-peer secret is accepted for it — the global
|
|
# MESH_PEER_PUSH_SECRET above is ignored for that specific URL. This
|
|
# closes the cross-peer impersonation surface for multi-peer fleets.
|
|
# Single-peer installs leave this empty (default) for unchanged
|
|
# behavior. Both sides of a peering must agree on the per-peer
|
|
# secret for a given URL.
|
|
- MESH_PEER_SECRETS=${MESH_PEER_SECRETS:-}
|
|
# Meshtastic MQTT is opt-in to avoid passive load on the public broker.
|
|
# Set MESH_MQTT_ENABLED=true in .env only when this node should join live MQTT.
|
|
- MESH_MQTT_ENABLED=${MESH_MQTT_ENABLED:-false}
|
|
- MESH_MQTT_BROKER=${MESH_MQTT_BROKER:-mqtt.meshtastic.org}
|
|
- MESH_MQTT_PORT=${MESH_MQTT_PORT:-1883}
|
|
- MESH_MQTT_USER=${MESH_MQTT_USER:-meshdev}
|
|
- MESH_MQTT_PASS=${MESH_MQTT_PASS:-large4cats}
|
|
- MESH_MQTT_PSK=${MESH_MQTT_PSK:-}
|
|
- MESH_MQTT_INCLUDE_DEFAULT_ROOTS=${MESH_MQTT_INCLUDE_DEFAULT_ROOTS:-true}
|
|
- MESH_MQTT_EXTRA_ROOTS=${MESH_MQTT_EXTRA_ROOTS:-}
|
|
- MESH_MQTT_EXTRA_TOPICS=${MESH_MQTT_EXTRA_TOPICS:-}
|
|
- MESHTASTIC_OPERATOR_CALLSIGN=${MESHTASTIC_OPERATOR_CALLSIGN:-}
|
|
# The bundled Docker UI talks to the backend across Docker's private bridge.
|
|
# Treat that bridge as local operator access while ports remain bound to 127.0.0.1 by default.
|
|
- SHADOWBROKER_TRUST_DOCKER_BRIDGE_LOCAL_OPERATOR=${SHADOWBROKER_TRUST_DOCKER_BRIDGE_LOCAL_OPERATOR:-1}
|
|
# Issue #250: bridge trust is now bound to specific container hostnames
|
|
# (default: 'frontend' compose service + 'shadowbroker-frontend' container
|
|
# name). If you rename the frontend service or run with a different
|
|
# container_name, list the hostnames here (comma-separated, no spaces).
|
|
- SHADOWBROKER_TRUSTED_FRONTEND_HOSTS=${SHADOWBROKER_TRUSTED_FRONTEND_HOSTS:-frontend,shadowbroker-frontend}
|
|
# Third-party fetcher opt-ins. Default OFF — these phone home to
|
|
# politically/commercially sensitive upstreams (Polymarket, Kalshi,
|
|
# Yahoo Finance, EU disinfo trackers, NUFORC dataset host, etc.).
|
|
# Set to "true" in your .env only if you want the node's IP to
|
|
# contact each of these services. The dashboard panel for each
|
|
# feature reads as "no data" until the corresponding flag is on.
|
|
- PREDICTION_MARKETS_ENABLED=${PREDICTION_MARKETS_ENABLED:-false}
|
|
- FINANCIAL_ENABLED=${FINANCIAL_ENABLED:-false}
|
|
- CROWDTHREAT_ENABLED=${CROWDTHREAT_ENABLED:-false}
|
|
- FIMI_ENABLED=${FIMI_ENABLED:-false}
|
|
- NUFORC_ENABLED=${NUFORC_ENABLED:-false}
|
|
- NEWS_ENABLED=${NEWS_ENABLED:-true}
|
|
volumes:
|
|
- backend_data:/app/data
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8000/api/health"]
|
|
interval: 15s
|
|
timeout: 10s
|
|
retries: 5
|
|
start_period: 60s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: ${BACKEND_MEMORY_LIMIT:-4G}
|
|
cpus: '2'
|
|
|
|
frontend:
|
|
image: ghcr.io/bigbodycobain/shadowbroker-frontend:latest
|
|
container_name: shadowbroker-frontend
|
|
ports:
|
|
- "${BIND:-127.0.0.1}:${FRONTEND_PORT:-3000}:3000"
|
|
environment:
|
|
# Points the Next.js server-side proxy at the backend container via Docker networking.
|
|
# Change this if your backend runs on a different host or port.
|
|
- BACKEND_URL=http://backend:8000
|
|
# Lets the server-side proxy authenticate protected local-node API calls.
|
|
- ADMIN_KEY=${ADMIN_KEY:-}
|
|
depends_on:
|
|
backend:
|
|
condition: service_healthy
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:3000/"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 20s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 512M
|
|
cpus: '1'
|
|
|
|
volumes:
|
|
backend_data:
|