fluxa-core/docs/overview.md
KhooLy 894ca2c81f feat: companion server, FFI cleanup, and pre-release hardening
- 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
2026-06-17 20:01:42 +03:00

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).