From 8dfa6a719986faceec598880476ba2ebbd4fc256 Mon Sep 17 00:00:00 2001 From: Shadowbroker <43977454+BigBodyCobain@users.noreply.github.com> Date: Sat, 23 May 2026 16:24:20 -0600 Subject: [PATCH] =?UTF-8?q?release:=20v0.9.8=20=E2=80=94=20Cumulative=20Fu?= =?UTF-8?q?el/CO2,=20AIS=20Resilience,=20Data-Layer=20Repair=20(#321)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps every hardcoded 0.9.79 → 0.9.8 across backend, frontend, desktop-shell, helm, lockfiles, test fixtures. Refreshes the in-app ChangelogModal HEADLINE_FEATURES, NEW_FEATURES, and BUG_FIXES with the v0.9.8 highlights. Release artifacts built locally and hashed into release_digests.json: ShadowBroker_v0.9.8.zip 6.06 MB d506f6b8462ccb12096f0cd9462233be58928094240416b65fb3127bdd1f3820 ShadowBroker_0.9.8_x64_en-US.msi 122.4 MB d4be4cb68c3e6409fff54c225acdcdd08e27d5d6d2b31616d78d2a4f6812991d ShadowBroker_0.9.8_x64-setup.exe 76.5 MB 1115d1f5cf37edd03ea2c21d821c7626e1bf3319c990402aaa0293bca46fea67 Sizes match the v0.9.79 reference shape (5.76 MB / 117 MB / 72.9 MB) within expected drift for new code. The .zip is a `git archive` of the v0.9.8 source tree (matching v0.9.79's approach). Audit confirms no .env, .key, .venv-dir, or cache files leaked into the backend-runtime bundle. Python 3.11.9 + 199 site-packages + privacy_core all staged correctly. Headline changes since v0.9.79: * Cumulative fuel/CO2 per flight (#317) — running totals since first observation, not just per-hour rate. * AIS maritime resilience (#314, #316) — outage banner + AISHub REST fallback when AISStream WebSocket primary is offline. * Data-layer repair (#311, #312) — UAP fallback respects the 60-day cutoff; GPS jamming threshold tuning + nac_p=0 inclusion so the layer actually fires. * Per-flight source attribution (#313) — source field on every record. * Cross-node DM mailbox replication (#309). * Infonet sync HTTP 429 honored (#310). Test fixtures updated: * test_per_operator_outbound_attribution.py — added v0.9.8 UA strings to the banned-aggregate-literals list (alongside v0.9.79). * updateRuntime.test.ts — bumped asset filename fixtures to v0.9.8. release_digests.json keeps the v0.9.79 block alongside v0.9.8 so operators still on 0.9.79 validate cleanly during the rollout. The accent narrowing fix in ChangelogModal (one feature uses 'purple', two use 'cyan' so the renderer's `accent === 'purple'` comparison still type-checks) is included. Co-authored-by: Claude Opus 4.7 --- backend/data/release_digests.json | 5 + backend/main.py | 2 +- backend/pyproject.toml | 4 +- backend/routers/ai_intel.py | 4 +- backend/routers/health.py | 2 +- .../test_per_operator_outbound_attribution.py | 2 + desktop-shell/package-lock.json | 4 +- desktop-shell/package.json | 2 +- .../tauri-skeleton/src-tauri/Cargo.lock | 2 +- .../tauri-skeleton/src-tauri/Cargo.toml | 2 +- .../tauri-skeleton/src-tauri/tauri.conf.json | 2 +- frontend/package-lock.json | 4 +- frontend/package.json | 2 +- .../__tests__/desktop/updateRuntime.test.ts | 10 +- frontend/src/components/ChangelogModal.tsx | 140 ++++++------------ frontend/src/components/OnboardingModal.tsx | 2 +- .../src/components/StartupWarmupModal.tsx | 2 +- helm/chart/Chart.yaml | 4 +- pyproject.toml | 2 +- uv.lock | 4 +- 20 files changed, 77 insertions(+), 124 deletions(-) diff --git a/backend/data/release_digests.json b/backend/data/release_digests.json index 8869c58..ab5dbd8 100644 --- a/backend/data/release_digests.json +++ b/backend/data/release_digests.json @@ -36,5 +36,10 @@ "ShadowBroker_v0.9.79.zip": "f6877c1d66614525315ea82636ce9f7b41178332c4dbf90d27431a1ea1d9cd47", "ShadowBroker_0.9.79_x64-setup.exe": "f7b676ada45cac7da05868b0a353678c9ee700e3abcf456a7c0c038c36da446f", "ShadowBroker_0.9.79_x64_en-US.msi": "e0713c3cdda184cfbea750bfac0d62a35678fec00847e6476f2cac8e7e42046e" + }, + "v0.9.8": { + "ShadowBroker_v0.9.8.zip": "d506f6b8462ccb12096f0cd9462233be58928094240416b65fb3127bdd1f3820", + "ShadowBroker_0.9.8_x64-setup.exe": "1115d1f5cf37edd03ea2c21d821c7626e1bf3319c990402aaa0293bca46fea67", + "ShadowBroker_0.9.8_x64_en-US.msi": "d4be4cb68c3e6409fff54c225acdcdd08e27d5d6d2b31616d78d2a4f6812991d" } } diff --git a/backend/main.py b/backend/main.py index 792bca3..4ad8542 100644 --- a/backend/main.py +++ b/backend/main.py @@ -14,7 +14,7 @@ from dataclasses import dataclass, field from typing import Any from json import JSONDecodeError -APP_VERSION = "0.9.79" +APP_VERSION = "0.9.8" logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 25617ea..6b734b9 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -7,7 +7,7 @@ py-modules = [] [project] name = "backend" -version = "0.9.79" +version = "0.9.8" requires-python = ">=3.10" dependencies = [ "apscheduler==3.10.3", @@ -43,7 +43,7 @@ dev = ["pytest>=8.3.4", "pytest-asyncio==0.25.0", "ruff>=0.9.0", "black>=24.0.0" [tool.ruff.lint] # The current backend carries historical style debt in large legacy modules. -# Keep CI focused on actionable correctness checks for the v0.9.79 release. +# Keep CI focused on actionable correctness checks for the v0.9.8 release. ignore = ["E401", "E402", "E701", "E731", "E741", "F401", "F402", "F541", "F811", "F841"] [tool.black] diff --git a/backend/routers/ai_intel.py b/backend/routers/ai_intel.py index 26faed7..320fb5a 100644 --- a/backend/routers/ai_intel.py +++ b/backend/routers/ai_intel.py @@ -1590,7 +1590,7 @@ async def agent_tool_manifest(request: Request): return { "ok": True, - "version": "0.9.79", + "version": "0.9.8", "access_tier": access_tier, "available_commands": available_commands, "transport": { @@ -2226,7 +2226,7 @@ async def api_capabilities(request: Request): access_tier = str(get_settings().OPENCLAW_ACCESS_TIER or "restricted").strip().lower() return { "ok": True, - "version": "0.9.79", + "version": "0.9.8", "auth": { "method": "HMAC-SHA256", "headers": ["X-SB-Timestamp", "X-SB-Nonce", "X-SB-Signature"], diff --git a/backend/routers/health.py b/backend/routers/health.py index 27aa7fc..2a20e56 100644 --- a/backend/routers/health.py +++ b/backend/routers/health.py @@ -8,7 +8,7 @@ from services.data_fetcher import get_latest_data from services.schemas import HealthResponse import os -APP_VERSION = os.environ.get("_HEALTH_APP_VERSION", "0.9.79") +APP_VERSION = os.environ.get("_HEALTH_APP_VERSION", "0.9.8") router = APIRouter() diff --git a/backend/tests/test_per_operator_outbound_attribution.py b/backend/tests/test_per_operator_outbound_attribution.py index e2aa643..813ccb2 100644 --- a/backend/tests/test_per_operator_outbound_attribution.py +++ b/backend/tests/test_per_operator_outbound_attribution.py @@ -238,6 +238,8 @@ class TestNoMonsterUserAgentRemains: "ShadowBroker-FeedIngester/1.0", "ShadowBroker/0.9.79 local Shodan connector", "ShadowBroker/0.9.79 Finnhub connector", + "ShadowBroker/0.9.8 local Shodan connector", + "ShadowBroker/0.9.8 Finnhub connector", "Mozilla/5.0 (compatible; ShadowBroker CCTV proxy)", ) diff --git a/desktop-shell/package-lock.json b/desktop-shell/package-lock.json index 4c6847f..d465ca7 100644 --- a/desktop-shell/package-lock.json +++ b/desktop-shell/package-lock.json @@ -1,12 +1,12 @@ { "name": "@shadowbroker/desktop-shell", - "version": "0.9.79", + "version": "0.9.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@shadowbroker/desktop-shell", - "version": "0.9.79", + "version": "0.9.8", "devDependencies": { "typescript": "^5.6.0" } diff --git a/desktop-shell/package.json b/desktop-shell/package.json index 305d083..4c80ce7 100644 --- a/desktop-shell/package.json +++ b/desktop-shell/package.json @@ -1,6 +1,6 @@ { "name": "@shadowbroker/desktop-shell", - "version": "0.9.79", + "version": "0.9.8", "private": true, "description": "ShadowBroker desktop shell packaging, runtime bridge, and release tooling", "scripts": { diff --git a/desktop-shell/tauri-skeleton/src-tauri/Cargo.lock b/desktop-shell/tauri-skeleton/src-tauri/Cargo.lock index d9d04a7..00985fd 100644 --- a/desktop-shell/tauri-skeleton/src-tauri/Cargo.lock +++ b/desktop-shell/tauri-skeleton/src-tauri/Cargo.lock @@ -4201,7 +4201,7 @@ dependencies = [ [[package]] name = "shadowbroker-tauri-shell" -version = "0.9.79" +version = "0.9.8" dependencies = [ "axum", "base64 0.22.1", diff --git a/desktop-shell/tauri-skeleton/src-tauri/Cargo.toml b/desktop-shell/tauri-skeleton/src-tauri/Cargo.toml index 88181db..c42ecb6 100644 --- a/desktop-shell/tauri-skeleton/src-tauri/Cargo.toml +++ b/desktop-shell/tauri-skeleton/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shadowbroker-tauri-shell" -version = "0.9.79" +version = "0.9.8" edition = "2021" [build-dependencies] diff --git a/desktop-shell/tauri-skeleton/src-tauri/tauri.conf.json b/desktop-shell/tauri-skeleton/src-tauri/tauri.conf.json index 194982d..f7c3211 100644 --- a/desktop-shell/tauri-skeleton/src-tauri/tauri.conf.json +++ b/desktop-shell/tauri-skeleton/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "ShadowBroker", - "version": "0.9.79", + "version": "0.9.8", "identifier": "com.shadowbroker.desktop", "build": { "frontendDist": "../../../frontend/out", diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5dba293..ea77654 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "frontend", - "version": "0.9.79", + "version": "0.9.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "frontend", - "version": "0.9.79", + "version": "0.9.8", "dependencies": { "@mapbox/point-geometry": "^1.1.0", "@tauri-apps/plugin-process": "^2.3.1", diff --git a/frontend/package.json b/frontend/package.json index cf96860..fb981ef 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "frontend", - "version": "0.9.79", + "version": "0.9.8", "private": true, "scripts": { "dev": "node scripts/dev-all.cjs", diff --git a/frontend/src/__tests__/desktop/updateRuntime.test.ts b/frontend/src/__tests__/desktop/updateRuntime.test.ts index 91cd8a7..9e04922 100644 --- a/frontend/src/__tests__/desktop/updateRuntime.test.ts +++ b/frontend/src/__tests__/desktop/updateRuntime.test.ts @@ -9,12 +9,12 @@ import { } from '@/lib/updateRuntime'; const RELEASE: GitHubLatestRelease = { - html_url: 'https://github.com/BigBodyCobain/Shadowbroker/releases/tag/v0.9.79', + html_url: 'https://github.com/BigBodyCobain/Shadowbroker/releases/tag/v0.9.8', assets: [ - { name: 'ShadowBroker_0.9.79_x64_en-US.msi', browser_download_url: 'https://example.test/windows.msi' }, - { name: 'ShadowBroker_0.9.79_x64-setup.exe', browser_download_url: 'https://example.test/windows-setup.exe' }, - { name: 'ShadowBroker_0.9.79_aarch64.dmg', browser_download_url: 'https://example.test/macos.dmg' }, - { name: 'ShadowBroker_0.9.79_amd64.AppImage', browser_download_url: 'https://example.test/linux.AppImage' }, + { name: 'ShadowBroker_0.9.8_x64_en-US.msi', browser_download_url: 'https://example.test/windows.msi' }, + { name: 'ShadowBroker_0.9.8_x64-setup.exe', browser_download_url: 'https://example.test/windows-setup.exe' }, + { name: 'ShadowBroker_0.9.8_aarch64.dmg', browser_download_url: 'https://example.test/macos.dmg' }, + { name: 'ShadowBroker_0.9.8_amd64.AppImage', browser_download_url: 'https://example.test/linux.AppImage' }, ], }; diff --git a/frontend/src/components/ChangelogModal.tsx b/frontend/src/components/ChangelogModal.tsx index a165bc2..af96f76 100644 --- a/frontend/src/components/ChangelogModal.tsx +++ b/frontend/src/components/ChangelogModal.tsx @@ -20,129 +20,75 @@ import { Heart, } from 'lucide-react'; -const CURRENT_VERSION = '0.9.79'; +const CURRENT_VERSION = '0.9.8'; const STORAGE_KEY = `shadowbroker_changelog_v${CURRENT_VERSION}`; -const RELEASE_TITLE = 'Onboarding, Live Feeds, Mesh, and Agent Hardening'; +const RELEASE_TITLE = 'Cumulative Fuel/CO2, AIS Resilience, and Data-Layer Repair'; const HEADLINE_FEATURES = [ { - icon: , + icon: , accent: 'purple' as const, - title: 'Agentic onboarding for OpenClaw-compatible agents', - subtitle: 'First-time setup now includes local/direct agent connection, access-tier selection, copyable HMAC setup, and optional Tor hidden-service prep.', + title: 'Cumulative Fuel & CO2 per Flight', + subtitle: 'The aircraft tooltip now shows how much fuel each plane has actually burned in the air, not just the per-hour rate.', details: [ - 'The onboarding flow can generate the local agent connection bundle through the existing HMAC API, point agents at /api/ai/tools, and let operators choose restricted read-only or full write access before connecting an agent.', - 'Remote mode is labeled honestly: .onion exposes the signed HTTP agent API over Tor. Wormhole/MLS is not claimed as the current agent command transport.', - 'The setup copy works for OpenClaw, Hermes, or any custom agent that implements the documented HMAC request contract.', + 'New flight_observations module tracks first-seen-at per ICAO24 hex. Multiplies the model-based rate by elapsed observation time to produce running totals — FUEL BURNED (gal) and CO2 EMITTED (kg) — in the EMISSIONS ESTIMATE block.', + '15-minute gap between sightings resets the session (treated as a new flight: landed and took off again, or transited a dead zone). The cumulative counter survives trail pruning so map-rendering lifecycle and emission tracking are independent.', + '24-hour clamp defends against clock-skew bugs; per-icao prune every 5 minutes keeps memory bounded. The per-hour rate is still shown as smaller context underneath each cumulative figure.', ], - callToAction: 'OPEN FIRST-TIME SETUP -> AI AGENT', + callToAction: 'OPEN A FLIGHT TOOLTIP → EMISSIONS ESTIMATE', }, { - icon: , - accent: 'purple' as const, - title: 'Agentic AI Channel — supports OpenClaw and any HMAC-signing agent', - subtitle: 'ShadowBroker now exposes a signed agent command channel. Bring your own agent (OpenClaw, Claude Code, GPT, LangChain, or a custom client) and drive the dashboard from any LLM that speaks the protocol.', - details: [ - 'A signed command channel (POST /api/ai/channel/command) plus a batched concurrent-execution endpoint (up to 20 tool calls per round-trip via /api/ai/channel/batch). Agents query flights, ships, SIGINT, news, and intel layers; reason over the live mesh; and run market or threat analyses without a human in the loop.', - 'HMAC-SHA256 request signing with timestamp + nonce replay protection. Tier-gated access (restricted vs full) governs which read and write commands the agent can invoke. Every call is auditable through the channel log.', - 'ShadowBroker does not bundle an LLM, an agent runtime, or model weights — it ships the protocol. Any agent that signs requests with the documented HMAC contract can connect. OpenClaw is the reference implementation.', - ], - callToAction: 'CONNECT YOUR AGENT \u2192 /API/AI/CHANNEL/COMMAND', - }, - { - icon: , + icon: , accent: 'cyan' as const, - title: 'InfoNet Testnet \u2014 Framework, Privacy, and a Path to Decentralized Intelligence', - subtitle: 'The testnet now ships its full governance economy and the runway for a privacy-preserving decentralized intelligence platform.', + title: 'AIS Maritime Resilience — Outage Banner + AISHub Fallback', + subtitle: 'When AISStream’s WebSocket goes offline (as happened upstream in May 2026), the ships layer no longer goes silently empty.', details: [ - 'Sovereign Shell views: petitions (governance DSL covers parameter updates and feature toggles), upgrade-hash voting (80% supermajority, 67% Heavy-Node activation), evidence submission, dispute markets, gate suspension and shutdown, and bootstrap eligible-node-one-vote. Every write action is a clickable form with verbatim diagnostics on rejection.', - 'Privacy primitive runway: locked Protocol contracts for ring signatures, stealth addresses, shielded balances, and DEX matching. The privacy-core Rust crate is the integration target. Function Keys (anonymous citizenship proof) ship 5 of 6 pieces; only blind-signature issuance waits on a primitive decision.', - 'Backbone: two-tier event state with epoch finality, identity rotation, progressive penalties, ramp milestones, and constitutional invariants enforced via MappingProxyType. Sprint 11+ wires the cryptographic primitives into the locked Protocols.', - 'Still an experimental testnet \u2014 no privacy guarantee yet. Treat all channels as public until E2E and the privacy primitives ship.', + 'AIS proxy health surfaces in /api/health: connected, last_msg_age_seconds, proxy_spawn_count. A dismissible amber banner explains the outage (“Ship data temporarily unavailable — AISStream upstream is offline”) instead of letting users assume their install is broken.', + 'AISHub REST fallback (free tier at aishub.net/api). Polls every 20 minutes when the primary is disconnected and merges vessels into the same store with source: “aishub” so existing tooling attributes the provider.', + 'Live data wins races: if the WebSocket reconnects mid-poll, fresh AISStream updates aren’t overwritten by stale REST records. Opt-in via AISHUB_USERNAME; cadence configurable via AISHUB_POLL_INTERVAL_MINUTES (clamped [1, 360]).', ], - callToAction: 'OPEN SOVEREIGN SHELL \u2192 PETITIONS \u2022 UPGRADES \u2022 GATES', + callToAction: 'SET AISHUB_USERNAME \u2192 RESTART BACKEND', + }, + { + icon: , + accent: 'cyan' as const, + title: 'Data-Layer Repair \u2014 UAP Cutoff + GPS Jamming Detection', + subtitle: 'Two long-broken layers fixed at the source. UFO sightings are actually recent now; GPS jamming zones actually fire.', + details: [ + 'UAP sightings: the Hugging Face NUFORC mirror fallback had no date cutoff, so when the live nuforc.org scrape failed the layer served 3-year-old reports as \u201crecent\u201d. Now drops rows older than 60 days and logs loudly when the mirror is fully stale. Scheduler moved daily \u2192 weekly (Mondays 12:00 UTC).', + 'GPS jamming: three stacked filters meant the layer almost never lit up. nac_p == 0 (\u201cGPS lock lost\u201d) was filtered out as if it were an old transponder \u2014 it\u2019s actually the strongest jamming signal. Now counted. MIN_AIRCRAFT lowered 5 \u2192 3 so sparser hotspots clear; MIN_RATIO lowered 0.30 \u2192 0.20.', + 'Both layers now surface their own outages via assert_canary so operators see broken vs empty, not silently stale.', + ], + callToAction: 'TOGGLE UAP \u2022 GPS JAMMING LAYERS', }, ]; const NEW_FEATURES = [ { - icon: , - title: 'Startup and Feed Responsiveness Pass', - desc: 'Map-critical feeds now lean on startup caches and priority preload behavior so the dashboard can paint before heavyweight synthesis jobs finish.', + icon: , + title: 'Per-Flight Source Attribution', + desc: 'Every aircraft record now carries a source field (adsb.lol, OpenSky, airplanes.live, adsb.fi) so consumers can attribute the data provider. Pre-fix, adsb.lol records were unmarked while OpenSky records were explicitly tagged, making it look like adsb.lol was unused even though it is the primary source.', }, { icon: , - title: 'MeshChat MQTT Settings', - desc: 'Public MeshChat stays opt-in and now has an in-panel settings lane for broker, port, username, password, and channel PSK while remaining separated from Wormhole/private mode.', + title: 'Cross-Node DM Mailbox Replication', + desc: 'Direct messages now replicate across mesh nodes when one party is offline. Per-(sender, recipient) anti-spam cap enforced as a network rule (not client-side) so source-code tampering cannot bypass it.', }, { - icon: , - title: 'Selected Entity Trails', - desc: 'Flight and vessel trails are drawn only for selected assets, reducing global clutter while still exposing movement history for unknown-route entities.', - }, - { - icon: , - title: 'Aircraft Detail Cards', - desc: 'Commercial aircraft stay airline-first, while private and general aviation aircraft can show model-focused Wiki context and imagery when available.', - }, - { - icon: , - title: 'AI Batch Command Channel', - desc: 'POST up to 20 tool calls in a single HTTP round-trip; the backend executes them concurrently and returns a fan-out result map. Cuts agent latency by an order of magnitude over sequential calls.', - }, - { - icon: , - title: 'Governance DSL — Petition-Driven Parameter Changes', - desc: 'Type-safe payload executor for UPDATE_PARAM, BATCH_UPDATE_PARAMS, ENABLE_FEATURE, and DISABLE_FEATURE petitions. Tunable knobs change on-chain via a vote — no code deploys required.', - }, - { - icon: , - title: 'Upgrade-Hash Governance', - desc: 'Protocol upgrades that need new logic (not just parameter changes) vote on a SHA-256 hash of the verified release. 80% supermajority, 40% quorum, 67% Heavy-Node activation. Lifecycle: signatures, voting, challenge window, awaiting readiness, activated.', - }, - { - icon: , - title: 'Function Keys — Anonymous Citizenship Proof', - desc: 'A citizen proves "I am an Infonet citizen" without revealing their Infonet identity. 5 of 6 pieces shipped: nullifiers, challenge-response, two-phase commit receipts, enumerated denial codes, batched settlement. Issuance via blind signatures waits on a primitive decision.', - }, - { - icon: , - title: 'Privacy Primitive Runway', - desc: 'Locked Protocol contracts in services/infonet/privacy/contracts.py for ring signatures, stealth addresses, Pedersen commitments, range proofs, and DEX matching. The privacy-core Rust crate is the integration target — no caller of the privacy module needs to know which scheme is active.', - }, - { - icon: , - title: 'Two-Tier State + Epoch Finality', - desc: 'Tier 1 events propagate CRDT-style for low latency; Tier 2 events require epoch finality before they can be acted on. Identity rotation, progressive penalties, ramp milestones, and constitutional invariants are enforced via MappingProxyType.', - }, - { - icon: , - title: 'Sovereign Shell Write Surface', - desc: 'PetitionsView, UpgradeView, ResolutionView, GateShutdownView, BootstrapView, and FunctionKeyView each expose every Sprint 4-8 + 10 write action as a clickable form. Adaptive polling tightens to 8 seconds during active voting/challenge phases.', - }, - { - icon: , - title: 'Time Machine — Snapshot Playback', - desc: 'Scrub backward through saved telemetry. Live polling pauses on entry to snapshot mode, the map redraws from the recorded snapshot, and moving entities interpolate between recorded frames. Hourly index lets you jump to any captured timestamp; pressing Live restores the current feed instantly.', - }, - { - icon: , - title: 'SAR Satellite Telemetry — ASF, OPERA, Copernicus', - desc: 'New SAR (Synthetic Aperture Radar) layer. Mode A (default-on) pulls free catalog metadata from the Alaska Satellite Facility — no account required. Mode B (two-step opt-in) ingests pre-processed ground-change anomalies from NASA OPERA, Copernicus EGMS, GFM, EMS, and UNOSAT — deformation, flood, and damage assessments. Integrates with OpenClaw so agents can read and act on SAR anomalies; broadcasts default to private-tier transport (Tor / RNS).', + icon: , + title: 'Infonet Sync — HTTP 429 Honored', + desc: 'When an upstream peer returns Retry-After, the node now waits exactly that long instead of retrying every 60 seconds and keeping the upstream rate-limit bucket permanently full. Exponential backoff on consecutive failures capped at 30 minutes.', }, ]; const BUG_FIXES = [ - 'Docker proxy and backend port handling hardened so changing the host backend port does not require changing the internal service contract.', - 'Global Threat Intercept and live-data startup paths no longer wait on slow-tier synthesis before cached data can paint the UI.', - 'MeshChat and Infonet statuses now separate public MQTT participation, private Wormhole mode, and local node bootstrap so the UI does not imply the wrong connection state.', - 'Commercial aircraft detail cards no longer show a confusing model image alongside the airline card.', - 'Sovereign Shell adaptive polling — voting and challenge windows refresh every 8 seconds while active, every 30 to 60 seconds when idle. Voting feels live without a websocket layer.', - 'Per-row write actions (petitions, upgrades, disputes) hold isolated submission state so concurrent forms no longer share a single in-flight slot.', - 'Verbatim diagnostic surfacing on every write button. The backend reason text is always shown on rejection — no opaque "denied" toasts.', - 'Evidence submission canonicalization matches Python repr() exactly, so client-side SHA-256 hashes round-trip cleanly through the chain.', - 'Function Keys copy is context-agnostic — citizenship proof is described abstractly, not tied to a specific use case.', - 'Post-cutover legacy mesh files (mesh_schema.py, mesh_signed_events.py, mesh_hashchain.py) hash-verified against the recorded baseline; the chain extension hook stays surgical.', + 'UAP layer no longer serves 3-year-old NUFORC sightings via the Hugging Face static-mirror fallback (60-day cutoff now applied to the fallback path too).', + 'GPS jamming detection now counts nac_p == 0 (the actual GPS-lost signal) instead of filtering it out as an old-transponder artifact.', + 'GPS jamming thresholds lowered (MIN_AIRCRAFT 5 → 3, MIN_RATIO 0.30 → 0.20) so sparser hotspots clear the bar without losing the 1-aircraft noise cushion.', + 'AIS layer surfaces an outage banner when the AISStream WebSocket upstream is offline, instead of silently showing an empty ocean.', + 'Flight emissions tooltip now shows cumulative fuel/CO2 since first observation, not just the per-hour rate.', + 'Per-aircraft observation tracker (15-min reopen gap, 24-hour clamp) survives trail-rendering cache pruning so cumulative counters do not reset mid-flight.', + 'UAP scheduler moved daily → weekly (Mondays 12:00 UTC) to match the layer’s rolling-window cadence and reduce upstream load.', ]; const CONTRIBUTORS = [ diff --git a/frontend/src/components/OnboardingModal.tsx b/frontend/src/components/OnboardingModal.tsx index 12defcb..ac86362 100644 --- a/frontend/src/components/OnboardingModal.tsx +++ b/frontend/src/components/OnboardingModal.tsx @@ -4,7 +4,7 @@ import React, { useState, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { X, ExternalLink, Key, Shield, Radar, Globe, Satellite, Ship, Radio, Bot, Copy, Check, Network } from 'lucide-react'; -const CURRENT_ONBOARDING_VERSION = '0.9.79-agentic-onboarding-1'; +const CURRENT_ONBOARDING_VERSION = '0.9.8-agentic-onboarding-1'; const STORAGE_KEY = `shadowbroker_onboarding_complete_v${CURRENT_ONBOARDING_VERSION}`; const LEGACY_STORAGE_KEY = 'shadowbroker_onboarding_complete'; diff --git a/frontend/src/components/StartupWarmupModal.tsx b/frontend/src/components/StartupWarmupModal.tsx index 19da333..99bf1d1 100644 --- a/frontend/src/components/StartupWarmupModal.tsx +++ b/frontend/src/components/StartupWarmupModal.tsx @@ -4,7 +4,7 @@ import React, { useEffect, useState } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Database, Clock, X } from 'lucide-react'; -const CURRENT_VERSION = '0.9.79'; +const CURRENT_VERSION = '0.9.8'; const STORAGE_KEY = `shadowbroker_startup_warmup_notice_v${CURRENT_VERSION}`; interface StartupWarmupModalProps { diff --git a/helm/chart/Chart.yaml b/helm/chart/Chart.yaml index 7b8103b..e5a42ec 100644 --- a/helm/chart/Chart.yaml +++ b/helm/chart/Chart.yaml @@ -1,8 +1,8 @@ --- apiVersion: v2 name: shadowbroker -version: 0.9.79 -appVersion: "0.9.79" +version: 0.9.8 +appVersion: "0.9.8" description: simple shadowbroker installation type: application diff --git a/pyproject.toml b/pyproject.toml index 30dcc52..73de004 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "shadowbroker" -version = "0.9.79" +version = "0.9.8" readme = "README.md" requires-python = ">=3.10" dependencies = [] diff --git a/uv.lock b/uv.lock index 6a28a8a..6af7c66 100644 --- a/uv.lock +++ b/uv.lock @@ -74,7 +74,7 @@ wheels = [ [[package]] name = "backend" -version = "0.9.79" +version = "0.9.8" source = { editable = "backend" } dependencies = [ { name = "apscheduler" }, @@ -2231,7 +2231,7 @@ wheels = [ [[package]] name = "shadowbroker" -version = "0.9.79" +version = "0.9.8" source = { virtual = "." } [package.metadata]