|
All checks were successful
build-apk / build-and-publish (push) Successful in 8m2s
Pairs with strawcore's new extractor instrumentation to make "Send logs to Kayos" actually diagnosable. Today's bot-wall outage produced a log dump that was 90% framework noise, one mangled strawcore line, and zero failure signal. - LogDump: split the scrubber into a FULL profile (share-sheet export + on-screen error strings — unchanged, still over-redacts) and a lighter DOGFOOD profile (the logs.sulkta.com ingest path, our own infra) that KEEPS bare YouTube ids (video/channel/playlist/youtu.be — the triage signal) while still scrubbing every real credential: signed googlevideo URLs, bearer/cookie/token headers, sig/pot/n/cpn params, URL queries, emails, high-entropy tokens (visitorData), and IPs. LogShipper uses the dogfood profile. - Fixed the IPv6-compressed regex that mangled Rust module paths (`strawcore::stream` -> `strawcor<ip>stream`) and, as a bonus, a latent false-negative where `::1` was never scrubbed. - Always-log extraction + playback failures (strawLogI) so a user-visible failure always lands in the ring. - Wrapper (rust/strawcore): one catch-all WARN in run_extract that traces EVERY extraction failure system-wide, and raise android_logger Info->Debug so the extractor's DEBUG tier is live in the dogfood build. - Added a JVM unit test for the scrubber (not yet wired into CI — the repo has no test source set; follow-up). |
||
|---|---|---|
| .. | ||
| strawcore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
rust/ — strawcore: Rust YouTube core for Straw
Phase U- of the Straw build. Goal: replace the Java NewPipeExtractor dependency with a Rust core (rustypipe + tokio + reqwest), exposed to the Kotlin/Compose UI via UniFFI. Compose UI stays in Kotlin — only the YouTube/Innertube fetching layer moves to Rust.
Phases
| Phase | What |
|---|---|
| U-1 | Toolchain + UniFFI smoke test (hello_from_rust) round-tripping through JNA. No real APIs yet. |
| U-2 | rustypipe search. SearchViewModel calls the Rust core. |
| U-3 | rustypipe streamInfo + streams. VideoDetailViewModel + PlayerViewModel use it. |
| U-4 | rustypipe channel + tabs. ChannelViewModel + SubscriptionFeedViewModel. |
| U-5 | Rip NewPipeExtractor Java dep. Measure APK + cold-fetch latency before/after. |
| U-6 (stretch) | SponsorBlock + RYD HTTP through reqwest + tokio in the same lib. |
Build chain
Build container (Sulkta uses one; any toolchain matching this layout works)
├── rustup stable (target add: aarch64-linux-android, armv7-linux-androideabi,
│ x86_64-linux-android, i686-linux-android)
├── cargo-ndk (cross-compile helper)
├── android-sdk (ANDROID_HOME, sdkmanager, build-tools, platforms)
└── android-ndk (ANDROID_NDK_HOME, r27c LTS)
Gradle (strawApp/build.gradle.kts)
├── cargoBuild Exec task → cargo ndk -t <abi>... -o jniLibs/ build --release
├── uniffiBindgen Exec task → cargo run --bin uniffi-bindgen ... --library libstrawcore.so
└── source-set wiring generated Kotlin lands in strawApp/src/main/java/uniffi/strawcore/
Runtime (StrawApp.onCreate)
├── System.loadLibrary("strawcore")
└── uniffi.strawcore.initLogging()
Why UniFFI (and not raw JNI / JNA bindings)
- Hand-written JNI: tedious, error-prone, every type change is two files (Kotlin + Rust) that must stay in sync.
- Raw JNA: better, but you still hand-write the Kotlin side and worry about string ownership.
- UniFFI: write Rust, annotate with
#[uniffi::export], get a Kotlin shim generated. Strings, structs, enums, Result types,asyncfunctions all cross the boundary transparently. The runtime is JNA under the hood.
When in doubt
cargo check -p strawcore --target aarch64-linux-android— fast iteration.cargo run --bin uniffi-bindgen -- generate ...— regenerate Kotlin bindings.adb logcat -s strawcore— Rustlog::info!()lands here.aapt dump badging strawApp/build/outputs/apk/debug/strawApp-debug.apk— inspect what ABIs/native-libs the APK carries.