feat(diag): dogfood log-shipping to logs.sulkta.com
Some checks failed
build-apk / build-and-publish (push) Successful in 14m24s
gitleaks / scan (push) Failing after 1s

Ship scrubbed device logs to our self-hosted ingest (logs.sulkta.com) so a
'green in every offline gate, broken on-device' regression (the visionOS
playback outage) can be caught end-to-end. LogShipper POSTs a scrubbed log
ring + crash stacktrace on (a) an uncaught exception (chained to the previous
handler) and (b) a 'Send logs to Kayos' Settings button. Everything runs
through LogDump.scrubLine first (URLs/video-ids/emails/tokens redacted); the
server re-scrubs. device_id = a random per-install UUID (no hardware id).
Compile-DISABLED unless the STRAW_LOGS_INGEST_TOKEN build secret is set, so
contributor forks never phone home. build.yml passes the secret to the debug
build.
This commit is contained in:
Cobb 2026-07-29 09:32:55 -07:00
parent 5021749975
commit b5ef1e1973
6 changed files with 429 additions and 9 deletions

View file

@ -10,6 +10,7 @@
*/
import com.android.build.api.dsl.ApplicationExtension
import java.util.Properties
plugins {
alias(libs.plugins.android.application)
@ -36,6 +37,30 @@ configure<ApplicationExtension> {
versionCode = STRAW_VERSION_CODE
versionName = STRAW_VERSION_NAME
resValue("string", "app_name", "Straw")
// Dogfood log-shipping token (feature/diag/LogShipper.kt). This repo
// is PUBLIC — the token must NEVER be committed, so it's injected at
// build time and defaults to "":
// 1. env var STRAW_LOGS_INGEST_TOKEN — CI: add a Forgejo Actions
// repo secret STRAW_LOGS_INGEST_TOKEN and pass it in the
// "Assemble debug APK" step's env block in
// .forgejo/workflows/build.yml.
// 2. `straw.logs.ingest.token=…` in local.properties (gitignored)
// for local dogfood builds.
// Empty token ⇒ LogShipper is fully disabled (no-op, zero network,
// no Settings row) — contributor builds neither break nor phone home.
val strawLogsToken: String = System.getenv("STRAW_LOGS_INGEST_TOKEN")
?: run {
val props = Properties()
val f = rootProject.file("local.properties")
if (f.exists()) f.inputStream().use { props.load(it) }
props.getProperty("straw.logs.ingest.token")
}
?: ""
// Escape so a pathological token can't break out of the generated
// String literal in BuildConfig.java.
val escapedToken = strawLogsToken.replace("\\", "\\\\").replace("\"", "\\\"")
buildConfigField("String", "STRAW_LOGS_TOKEN", "\"$escapedToken\"")
}
// Explicit signing so CI / release builds reuse ONE keystore instead of