Kotlin/Native generates distinct Swift types for a class depending on
whether it's imported directly from its owning module or transitively
re-exported through another framework, so files consuming these DTOs
via FluxaShared's re-export of core no longer matched the FluxaCore
type Loader/ResourceLoader now return directly. Route Bootstrap and
HomeEffectHandler through FluxaCore consistently, and add an explicit
FluxaCore->FluxaShared stream conversion where DetailStartup crosses
back into FluxaApple.shared's Shared-typed API.
Xcode's embedAndSignAppleFrameworkForXcode task for :shared: is
intermittently disabled by the Kotlin Gradle Plugin's own IDE/index-build
detection (onlyIf 'Task is enabled' is false), silently skipping the
framework embed and leaving these types unavailable to Swift. core's
framework already embeds reliably for iOS (matching tvOS), so these plain
DTOs move there instead; the Compose-dependent DataSource wrappers stay in
shared, which already re-exports core.
FluxaAppleAddonStoreManager fetches manifests over URLSession and
persists the local addon list plus enabled/disabled state via
FluxaAppleAddonConfigurationStore. FluxaAppleAddonStoreStartup routes
AppleAddonStoreActionSnapshot actions from the shared UI to it and
pushes merged state back to Kotlin. FluxaIosApp constructs and
registers it, restoring/refreshing on launch. Users can now actually
add, toggle, reorder, and remove Stremio addons on iOS.
FluxaAppleAddonConfigurationStore gains a disabled-addon set and
enabledAddonUrls(); Home/Search/Discover/Detail now fetch from
enabledAddonUrls() instead of the raw configured list, so disabling an
addon in the store actually stops it from being queried.
Mirrors Android's PluginRepositoryManager: owns its own headless
runtime instance, dispatches repo/scraper actions, persists state via
UserDefaults, and exposes scraper settings layout and execution.
Implements the generated PluginHttpClient callback interface
synchronously via URLSession, with an SSRF guard (scheme allow-list
plus resolved-address blocklist) mirroring Android's PluginNetGuard.
Fixes AppleAuthDataSource: continueWithNuvio/continueWithStremio/
continueWithoutAccount were incorrectly routed through Swift
notifications - Android handles all three as pure local UI-state
transitions (no network), so this matches that instead of adding
unnecessary indirection.
submit() for the Credentials stage now posts a real request that
FluxaAppleAuthStartup.swift picks up: FluxaAppleStremioAuthClient
mirrors StremioService.kt's api.strem.io/api/login and /api/register
endpoints via URLSession, and the resulting session (id/email/authKey)
is persisted through FluxaAppleAuthStore using the Keychain generic-
password API (kSecClassGenericPassword, accessible-after-first-unlock),
not UserDefaults - this is the first credential-bearing data iOS
persists, unlike the existing UserDefaults-backed local stores.
Nuvio login/import is out of scope here: Android's version pulls
profile/addons/library/progress/history/collections through
NuvioAccountImportCoordinator, which needs library and addon-store
integration iOS doesn't have yet. The Nuvio stage transition works
(continueWithNuvio), but submitting Nuvio credentials currently has no
Swift listener - same "reachable but inert" scope already established
for AddonStore.
The error-state message on failed Stremio login is a hardcoded English
string rather than routed through AppStrings, since calling Kotlin's
AppStrings.t() from pure Swift needs framework-export verification I
can't perform without Xcode.
Caveat: this Swift code (Keychain access, URLSession networking) is
unverified - no Xcode/macOS toolchain available in this environment.
Only the Kotlin side (AppleAuthDataSource, all Gradle targets) is
compile-checked. Needs a real Xcode build and device/simulator test
before shipping.