Skip to content

Version the debug bundle, and move the system_server code into hook/ - #307

Merged
okhsunrog merged 2 commits into
mainfrom
chore/bundle-schema-versioning
Aug 24, 2026
Merged

Version the debug bundle, and move the system_server code into hook/#307
okhsunrog merged 2 commits into
mainfrom
chore/bundle-schema-versioning

Conversation

@okhsunrog

Copy link
Copy Markdown
Owner

state.json carried two schema numbers, both pinned at 1 since the format existed, next to a comment saying compatibility was not a concern. A number that never moves tells a triager nothing about the file in front of them, and nothing stopped the shape from drifting between releases. This makes it a real version and then uses that safety net for the first package move: hook/ is loaded by LSPosed into system_server, which is the one boundary in this module with a real failure mode, and the flat 96-file package hid it.

  • one version for the whole bundle (DiagnosticReport.schema is gone), bumped to 2, with a history table and bump rules in docs/debug-bundle.md §2.1
  • LsposedState and ProtectionCheck get explicit @SerialName values; without them kotlinx emits the fully-qualified class name as the kind discriminator, so those two blocks read dev.okhsunrog.vpnhide.LsposedState.Active while every other sealed type reads active — and the value would have changed silently the moment the class moved package
  • BundleSchemaGoldenTest pins the encoded shape against a checked-in golden file and asserts no fully-qualified name reaches the wire, so a shape change cannot ship unnoticed
  • hook/ package: HookEntry, PackageVisibilityHooks, SystemServerConfigCache, HookLog, HookReflectionProbe, ConnectivityAttachDiagnostics and the shared /data/system watcher. Pure move, 12 imports added, no logic touched; the shared vocabulary (HookRegistry, LsposedStats, canonical-config parsing, LogTags) stays at the root package
  • assets/xposed_init and the R8 keep rule name the new class — verified against the built APK, which carries dev/okhsunrog/vpnhide/hook/HookEntry after minification
  • HookPackageBoundaryTest enforces both directions: no Compose/Activity imports in hook/, no Xposed imports outside it, and xposed_init matching the real package

Note for whichever of this and #308 merges second: both touch the serialized report, so the golden file needs refreshing (UPDATE_GOLDEN=1 ./gradlew :app:testDebugUnitTest --tests '*BundleSchemaGoldenTest*'). Adding a field needs no schema bump.

`state.json` carried two schema numbers (one on the state, one on the
report), both pinned at 1 since the format existed, and a KDoc saying
compatibility was not a concern. A number that never moves tells a
triager nothing about the file in front of them, and nothing stopped the
shape from drifting between releases.

One version for the whole bundle, and a golden file so it cannot go
stale: the serialized shape is pinned in a test, which fails on any
change and points at the refresh command and the bump rule.

- give LsposedState and ProtectionCheck explicit @SerialName values.
  Without them kotlinx emits the fully-qualified class name as the `kind`
  discriminator, so those two blocks read
  "dev.okhsunrog.vpnhide.LsposedState.Active" while every other sealed
  type reads "active" — and the value would silently change if the class
  ever moved package
- drop DiagnosticReport.schema; the top-level one is the bundle's version
- bump it to 2 and document the history + bump rules in
  docs/debug-bundle.md §2.1, with the current schema in the triage list
- BundleSchemaGoldenTest pins the encoded shape (including the dashboard
  block, the only path those two sealed types reach) and asserts no
  fully-qualified name reaches the wire
96 files sat flat in one package, which hid the only boundary in this
module with a real failure mode: `hook/` is loaded by LSPosed into
system_server, everything else runs in the app process. Nothing enforced
it — `internal` is module-wide, so a hook file referencing a Compose
screen compiles fine and fails as a system_server crash on a device.

The seam was already clean (no Compose in any Xposed-importing file), so
this is a pure move: 7 files, no logic touched, 12 imports added.

- hook/: HookEntry, PackageVisibilityHooks, SystemServerConfigCache,
  HookLog, HookReflectionProbe, ConnectivityAttachDiagnostics and the
  shared /data/system watcher the three of them use
- shared vocabulary stays at the root package (HookRegistry, LsposedStats,
  canonical-config parsing, LogTags) — it is used by ~15 app-side files
  and belongs to neither process
- assets/xposed_init and the R8 keep rule now name the new class;
  verified against the built APK, which carries
  dev/okhsunrog/vpnhide/hook/HookEntry after minification
- HookPackageBoundaryTest enforces both directions: no UI in hook/, no
  Xposed imports outside it, and xposed_init matching the real package
@okhsunrog
okhsunrog merged commit b19660e into main Aug 24, 2026
35 checks passed
@okhsunrog
okhsunrog deleted the chore/bundle-schema-versioning branch August 24, 2026 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant