- Add fluxa-streaming-engine companion server (torrent start/stop, ffmpeg transcode/probe, OAuth token exchange) for the web build - Add SSRF guard restricting transcode/probe url param to http(s) loopback hosts, blocking file:// and remote-host abuse via ffmpeg - Add src/ffi.rs string-routed RPC dispatcher and wasm bindings - Add headless engine profile module and several FFI surface additions (scrobble plans, episode navigation, collections import/export) - Remove dead runtime::msg/update scaffolding and addon_transport trait - Remove fluxa_play.rs dev scratch binary (hardcoded scraper, not part of the product) - Reorder dv_rewrite.rs so implementation precedes its test module; strip decorative section dividers - Add docs/, fuzz/ targets, and a rewritten README - Fix .gitignore to cover fluxa-streaming-engine/target
4.7 KiB
fluxa-core overview
fluxa-core is the platform-agnostic Rust brain for the Fluxa media-streaming app. It holds all domain logic — content discovery, stream selection, playback state, profiles, library, calendar, external sync — and never does I/O itself. Instead, it emits typed effects that the host platform executes (network calls, storage reads, player commands, etc.) and reports back via completeEffect.
The result is a single Rust codebase that runs on Android, desktop (Linux/macOS/Windows), iOS, and webOS, with each platform providing a thin shell that drives the effect loop.
Architecture
Host → dispatch(action_json)
← { state, effects: [{ id, type, payload }] }
Host → executes each effect (HTTP / storage / player / ...)
→ completeEffect({ effectId, result })
← { state, effects: [...] }
The core never initiates anything. Every state transition begins with the platform dispatching an action.
Two state engines
headless_engine/ is the primary, actively-developed engine. State is held in a typed EngineState struct composed of per-feature sub-structs (HomeState, DetailState, PlayerState, etc.). Cross-module mutation goes through pub(super) setters — never reaching across module boundaries directly.
app_state.rs is a lighter, independently-maintained engine for overlapping concerns (home/discover/calendar/library/player). It is used by Android via UniFFI (createAppCoreStateJson / appCoreDispatchJson). The two engines are intentionally separate — don't try to merge them.
Three exposure mechanisms
| Mechanism | Used by | File |
|---|---|---|
FluxaCore struct |
Desktop (Tauri) | src/core_api.rs |
core_invoke(method, args_json) |
Desktop + Swift | src/ffi.rs |
| JNI externs | Android | src/bindings/jni.rs |
FluxaCore is intentionally minimal — exactly 8 methods that fluxa-desktop calls directly. Everything else goes through core_invoke (for desktop/Swift) or raw JNI bindings (for Android). There is no shared registration table: wiring a new capability to a platform means adding it to the right file for that platform.
Module map
| Module | Responsibility |
|---|---|
headless_engine |
Primary state machine — typed EngineState, action dispatch, effect emission |
app_state |
Secondary state engine, Android/UniFFI only |
core_api |
FluxaCore struct, 8 methods, desktop only |
ffi |
core_invoke string-routed dispatcher (~115 methods) |
runtime |
EffectKind / EffectEnvelope types |
bindings/jni |
~157 JNI externs for Android |
bindings/uniffi |
UniFFI exports (headless engine lifecycle, coreCapabilities, version) |
bindings/wasm |
WASM exports for webOS |
addon_protocol |
Manifest URL normalisation, resource URL construction, manifest merging |
addon_store |
Addon search policy, CloudStream/plugin repo URL normalisation |
addon_resource |
Addon HTTP response classification (success / empty / error) |
stream_policy |
Stream selection, magnet building, audio/subtitle preference matching |
player_policy |
Backend selection, track state, Dolby Vision fallback policy |
player_flow |
Self-contained typed playback sub-engine (load → select → play) |
player_scrobble |
Trakt/Simkl scrobble body construction |
content_identity |
ID parsing/normalisation (IMDB, TMDB, Kitsu, episode locators) |
home_ranking |
Billboard/shelf ordering, continue-watching dedup, personalization scoring |
library_state |
Continue-watching badge computation, next-episode resolution |
profile_contract |
Profile activation, auth token merging, settings migration |
profile_prefs |
Typed read of user preferences from raw profile JSON |
search_plan / discovery_plan |
Search/discover query planning, result grouping, sort |
calendar_plan |
Calendar item filtering, widget rows, release notifications |
external_sync |
Trakt and Simkl API response parsing and history mapping |
intro_segments |
introdb.app and AniSkip segment parsing, deduplication |
dolby_vision_rpu |
Dolby Vision RPU metadata extraction (native feature, JNI-only) |
platform_plan |
Season/episode navigation planning |
tmdb_plan |
TMDB ID resolution hints, trailer mapping |
watchlist_plan |
Watchlist toggle, offline grouping, progress merging |
offline_download |
Offline download plan construction |
data_policy |
Cache/data-failure policy |
Companion crate
fluxa-streaming-engine/ lives in the same repo. It handles the runtime streaming side — torrent via librqbit, HTTP proxying via axum, Dolby Vision bitstream rewriting. It exposes its own JNI bindings (bindings/jni.rs) and three CLI tools (torrent_bench, torrent_serve, companion_server).