Files
Shadowbroker/desktop-shell
Shadowbroker 8dfa6a7199 release: v0.9.8 — Cumulative Fuel/CO2, AIS Resilience, Data-Layer Repair (#321)
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 <noreply@anthropic.com>
2026-05-23 16:24:20 -06:00
..
2026-05-01 22:56:50 -06:00
2026-05-01 22:56:50 -06:00
2026-05-01 22:56:50 -06:00

Desktop Shell

Native-side scaffold for the ShadowBroker desktop boundary.

Purpose

This package owns the accepted desktop track:

  • native privileged control routing through Rust
  • authoritative policy enforcement and audit
  • packaged managed local backend ownership
  • packaged desktop runtime with same-origin /api/*
  • tray/menu-bar lifecycle
  • optional reduced-trust browser companion mode
  • desktop packaging/release tooling

Browser mode remains intact; the desktop path layers on top of it.

Source of truth

The shared desktop control contract still lives in:

  • frontend/src/lib/desktopControlContract.ts
  • frontend/src/lib/desktopControlRouting.ts

The native side imports that contract instead of redefining it.

Layout

desktop-shell/
├── package.json
├── scripts/
│   └── run-desktop-build.cjs          # Cross-platform npm build wrapper
├── src/
│   ├── runtimeBridge.ts
│   ├── nativeControlRouter.ts
│   ├── nativeControlAudit.ts
│   └── handlers/
└── tauri-skeleton/
    ├── dev.sh
    ├── build.sh
    ├── build.ps1
    ├── RELEASE.md
    ├── scripts/
    │   ├── generate-icons.cjs
    │   └── write-release-manifest.cjs
    └── src-tauri/
        ├── Cargo.toml
        ├── tauri.conf.json
        ├── icons/                      # Generated branded bundle assets
        └── src/
            ├── main.rs
            ├── bridge.rs
            ├── policy.rs
            ├── tray.rs
            ├── companion.rs
            ├── companion_server.rs
            ├── handlers.rs
            └── http_client.rs

Desktop runtime model

Native privileged path

The accepted 27-command privileged path remains native-only:

  • frontend bridge detection builds window.__SHADOWBROKER_LOCAL_CONTROL__
  • privileged requests go through Tauri IPC
  • Rust policy enforces capability/profile rules before dispatch
  • Rust audit ring records all outcomes
  • the native admin key never reaches webview JavaScript

Packaged main window

Packaged builds now own a bundled local backend runtime by default, then use an app-level loopback server as the native window origin so ordinary non-privileged /api/* fetches resolve same-origin instead of dying on static asset serving.

Browser companion

Browser companion remains:

  • optional
  • loopback-only
  • explicitly enabled
  • reduced-trust

It never receives the native bridge injection, and it is not a drop-in replacement for standalone browser mode.

Packaging / release flow

Use any of these entrypoints:

./desktop-shell/tauri-skeleton/build.sh
./desktop-shell/tauri-skeleton/build.ps1
npm --prefix desktop-shell run build:desktop

Use --clean to remove the previous export, generated icons, and old installer artifacts before rebuilding.

The release flow now:

  1. generates branded desktop icons
  2. stages a desktop-only frontend export tree without Next server-only route handlers / middleware
  3. stages a managed backend runtime bundle from backend/
  4. builds the frontend export for Tauri packaging
  5. copies the export to companion-www
  6. runs cargo tauri build
  7. writes SHA256SUMS.txt and release-manifest.json next to the bundle output

If the Tauri CLI is missing, the build scripts now fail immediately with the correct cargo install tauri-cli@^2 instruction.

The repo also now has a no-secrets desktop matrix workflow at ../.github/workflows/desktop-release.yml that builds unsigned desktop artifacts on Windows, macOS, and Linux and turns v*.*.* tags into downloadable GitHub release assets.

See tauri-skeleton/RELEASE.md for release-path details and tauri-skeleton/RELEASE_INPUTS.md for the future inputs that only matter once public distribution trust becomes a goal.

Current status

This is a runnable desktop foundation with a repeatable packaging path.

What works:

  • native desktop window with full app UI
  • packaged desktop ownership of a bundled local backend runtime
  • packaged desktop auto-generates and persists its local backend admin/private-plane secrets on first run
  • packaged desktop-managed backend blocks legacy 16-hex node-ID compat and direct legacy_agent_id lookup by default
  • packaged same-origin /api/* path for non-privileged data
  • Rust-side policy enforcement and audit
  • tray/menu-bar background lifecycle
  • macOS dock reopen
  • optional reduced-trust browser companion opener
  • branded Tauri/Windows/macOS bundle icons
  • release manifest + checksum generation

What is still not done:

  • code signing / notarization
  • auto-update mechanism
  • final installer copy / splash polish
  • DM/data-plane native migration
  • standalone-browser-equivalent companion parity

Managed backend defaults

The packaged desktop-managed backend now defaults to the hardened posture for compatibility sunset work:

  • MESH_BLOCK_LEGACY_NODE_ID_COMPAT=true
  • MESH_ALLOW_LEGACY_NODE_ID_COMPAT_UNTIL= unless an operator sets a dated temporary migration override
  • MESH_BLOCK_LEGACY_AGENT_ID_LOOKUP=true

That default applies to the app-owned managed backend created under %LOCALAPPDATA%. Source/server deployments remain operator-controlled and can set those flags independently.

If a managed desktop operator leaves MESH_BLOCK_LEGACY_NODE_ID_COMPAT=false in the managed backend .env, bootstrap now normalizes it back to true. The only supported escape hatch for legacy 16-hex node IDs is a dated MESH_ALLOW_LEGACY_NODE_ID_COMPAT_UNTIL=YYYY-MM-DD override. MESH_BLOCK_LEGACY_AGENT_ID_LOOKUP=false is still preserved if an operator intentionally needs that separate migration path.