v1.22 (versionCode 28): production hardening, flavor separation, CI - #7
Merged
Merged
Conversation
- Pin TLS certificates for mindpulse.ssc.wisc.edu (InCommon/USERTrust CAs, fail-open 2027-07-08) in network_security_config - Add SecureStore: enrollment token moves from plaintext SharedPreferences to AndroidKeyStore-backed AES-256-GCM, with legacy migration and tests - Sweep crash-orphaned plaintext temp files (Logger.sweepStaleTempFiles) - Expand DeviceStateCollector battery/runtime diagnostics - Make legacy Encryptor.encryptFile throw instead of silently no-op: callers delete the plaintext source on "success", so a no-op destroyed video recordings while logging success - Add 100k-file upload backlog stress-test scripts and runbook
…seDev Research features live only in the mindpulseDev flavor; the production standard flavor gets no-op stubs, no BLE permissions, and no native code. Flavor separation: - GlassBleService/GlassPhotoAssembler/VlmBridge/VlmBenchmark/OcrProcessor/ BehaviorContext moved to src/mindpulseDev; GlassesFeature facade + VlmBenchmark stub in src/standard - BLE permissions and service declaration in mindpulseDev manifest overlay - Native build gated by -DVLM_ENABLED=ON (dev flavor only); standard builds a placeholder excluded from packaging, restoring all-ABI production APKs with zero .so files; llama.cpp vendored as a pinned git submodule - Five-tap DevTools entry gated to debug builds / mindpulseDev Reliability and privacy fixes baked in: - GlassBleService: scan filter + balanced mode + exponential backoff (results now arrive with screen off), connect-fallback recovers from remembered-MAC changes, BT adapter state receiver, GATT status checks (a failed CCCD write no longer starts glasses capture), assembler reset on reconnect + 2MB cap (no cross-connection JPEG merging), stop-capture write grace before close, upload I/O off the BLE binder thread, removed the indefinite wake lock, fine-location gate on API 29-30 - VLM: OCR posted to worker thread (was silently returning "" on the accessibility path), native mutex + double-load guard (was leaking ~700MB per reload), n_batch follows n_ctx (prompts >512 tokens failed), UTF-8-safe JNI string returns, loadLibrary guard, -march i8mm removed (SIGILL on armv8.2 cores), DevTools listener leak fixed - Screen-derived text (VLM narrative/captions) and BLE MAC no longer written to logcat, which is uploaded as diagnostics
- Ignore model weights (models/, *.gguf), decrypted participant data (recentlog/, Screenshot_*.png), local dev prefs, and scratch notes - Stop tracking .claude/settings.local.json (machine-local, contains local paths) - Register llama.cpp submodule VCS root in IDE config
… alerts - Enrollment key moves from plaintext SharedPreferences to SecureStore (AndroidKeyStore AES-256-GCM) at every read/write site, with the same lazy migration + fail-open pattern already used for enrollment_token, so existing registered participants migrate transparently - Devicestate heartbeat now also runs from AutoUploadWorker (30-min throttle, deduped against LocationService's 10-min flush), so the server-side alive-vs-broken signal flows even for participants who declined location permission - HealthChecker gains a capture-stall alert (consecutive screenshot failures while unlocked — overnight non-use cannot trip it) and a participant-facing upload-backlog / low-storage alert - Daily warning into uploaded diagnostics starting a month before the TLS pin-set fail-open date (2027-07-08)
Lint (12 errors -> 0): - New A11yState holder: status flags and API-safe static helpers moved out of the @RequiresApi(R) AccessibilityCaptureService, clearing 10 spurious NewApi errors at API-29-reachable call sites - RegisterActivity: deprecated empty onBackPressed() override replaced with an OnBackPressedCallback (back stays disabled during registration) - standard fragment_mindpulse.xml: android:tint -> app:tint Tests (26 executions, 0 failures; Robolectric + JUnit): - GlassPhotoAssemblerTest: BLE frame-reassembly state machine (chunking, orientation framing, frame gaps, mid-stream joins, reset isolation, 2MB cap, JPEG validation) - EncryptorTest: full server-side round-trip of AES-GCM + RSA-OAEP wrap, per-file key/nonce uniqueness, legacy encryptFile throws - LoggerQueueTest: .enc/.meta pair contract, provenance fields, no plaintext temp left behind, refuses to queue without the server key
Runs on every push/PR. Skips the native llama.cpp build (dev-flavor Java compile doesn't trigger CMake; standard never needs the submodule), so a plain ubuntu runner with JDK 17 covers everything. Lint and test reports are uploaded as artifacts.
Windows checkouts commit gradlew with mode 100644; the Linux CI runner then fails with exit 126 (permission denied).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release candidate for Play v1.22 (versionCode 28). The standard (production) flavor contains NO research features.
PRODUCTION CHANGES
TLS certificate pinning for mindpulse.ssc.wisc.edu. Enrollment token and key now encrypted at rest (AndroidKeyStore AES-256-GCM) with transparent migration for existing installs. Devicestate heartbeat independent of location permission (WorkManager, 30-min throttle). New health alerts: capture-stall detection plus upload-backlog / low-storage participant notifications. Legacy Encryptor.encryptFile no longer silently destroys recordings. Five-tap DevTools entry gated out of production release builds. Java 17, zero lint errors, 26 unit tests, GitHub Actions CI on every push.
RESEARCH STACK (mindpulseDev flavor only, not in the Play APK)
OMI Glass BLE photo pipeline and on-device VLM/OCR (llama.cpp as pinned submodule). Native build gated by flavor; production APK ships zero native libraries (verified: 20MB, no .so).
RELEASE CHECKLIST