ワンクリックで
protobuf-schema-evolution
Protobuf compatibility, reserved fields, diagnostics wire contracts, schema versions, and goldens.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Protobuf compatibility, reserved fields, diagnostics wire contracts, schema versions, and goldens.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Use this skill to generate well-branded interfaces and assets for RIPDPI (an Android-native, Compose-first VPN and DPI-bypass app), either for production or throwaway prototypes/mocks/etc. Contains essential design guidelines, colors, type, fonts, brand-ship icons, and an interactive UI kit of every public composable from the live ui/components tree.
Use when managing the Rust workspace, adding/removing crates, editing workspace dependencies, running cargo nextest/audit/deny, configuring Cargo profiles for Android cross-compilation, debugging Cargo.lock churn, migrating crate edition, or wiring Gradle to cargo via the ripdpi.android.rust-native plugin.
Use when modifying the diagnostics scan pipeline, ScanRequest/ScanReport types, ProbeTask families, ripdpi-monitor-engine / ripdpi-diagnostics-* crates, strategy-probe candidates, the diagnostics catalog (packs/profiles), wire-schema contracts between Rust and Kotlin, DIAGNOSTICS_ENGINE_SCHEMA_VERSION, golden contract tests, or adding a new probe type / profile. Triggers on diagnostics scans, strategy probes, automatic audit, dpi-detector profiles, or anything in core/diagnostics or native/rust/crates/ripdpi-monitor-*.
Android-specific Rust build, verification, and packaging — per-target 16 KiB page alignment, size-optimized release profile, ELF symbol allowlist, .so size budgets, NDK 29 specifics. Use when modifying .cargo/config.toml for Android targets, the workspace [profile.release] / [profile.android-jni] block, or when verifying a built .so before release.
Telemetry and observability discipline for the RIPDPI Android Rust stack — control-plane vs data-plane logging, bounded flume event queues, atomic counters, snapshot polling, readiness callbacks, and deterministic JSON contracts. Use when authoring or modifying telemetry emission code, the bounded event ring, the Kotlin-side telemetry consumer, or any per-packet logging.
Custom detekt rules, DI/privacy/suppression guardrails, detekt.yml configuration, and false-positive triage.
| name | protobuf-schema-evolution |
| description | Protobuf compatibility, reserved fields, diagnostics wire contracts, schema versions, and goldens. |
AppSettings is serialized as protobuf bytes and persisted on disk via Jetpack DataStore. When the app updates, new code must read bytes written by every older version. A field-number collision silently corrupts data -- the user loses their configuration with no error and no recovery path.
The diagnostics engine adds a second dimension: Kotlin and Rust exchange JSON wire messages whose schemas must stay in lockstep. A field mismatch causes silent data loss or deserialization failures at runtime.
Schema: core/data/model/src/main/proto/app_settings.proto
Reserved field numbers (never reuse): 15, 16, 17, 29, 30, 31, 32, 69, 71, 93, 94, 130
Reserved field names: desync_method, split_position, split_at_host,
tlsrec_enabled, tlsrec_position, tlsrec_at_sni, udp_fake_count,
split_marker, tlsrec_marker, dns_doh_url, dns_doh_bootstrap_ips,
settings_migration_level
Highest field number in use: 129 (freeze_detection_enabled).
Never reuse a field number. Proto3 identifies fields by number. If
field 15 was desync_method and you assign 15 to something new, existing
persisted bytes silently decode as the wrong field.
Reserve removed fields. Add both the number AND name to reserved.
This makes protoc reject future reuse at compile time.
Use the next available number. Do not fill gaps from past removals.
Set defaults in AppSettingsSerializer. Every new field needs a default
in AppSettingsSerializer.defaultValue (core/data/.../AppSettingsSerializer.kt).
Proto3 zero-values (0, false, "") are implicit; if the real default differs
(e.g., proxy_port = 1080), the serializer is the only place it gets set.
Validate string enums on read. Proto stores enum-like fields as plain strings ("vpn", "proxy"). Fall back to a safe default on unrecognized values.
Rust (ripdpi-diagnostics-contracts, re-exported by ripdpi-monitor-engine) and Kotlin exchange JSON wire messages. Schema version
is tracked by a constant that must be equal on both sides:
DIAGNOSTICS_ENGINE_SCHEMA_VERSION in native/rust/crates/ripdpi-diagnostics-contracts/src/wire.rsDiagnosticsEngineSchemaVersion in core/diagnostics/.../contract/engine/EngineContract.ktDiagnosticsContractGovernanceTest enforces equality by parsing the Rust
source with Regex("""DIAGNOSTICS_ENGINE_SCHEMA_VERSION:\s*u32\s*=\s*(\d+)""").
Wire types (all in wire.rs / EngineContract.kt):
| Rust | Kotlin | Direction |
|---|---|---|
EngineScanRequestWire | EngineScanRequestWire | Kotlin -> Rust |
EngineScanReportWire | EngineScanReportWire | Rust -> Kotlin |
EngineProgressWire | EngineProgressWire | Rust -> Kotlin |
Three test files enforce Kotlin/Rust wire compatibility using shared fixtures
in diagnostics-contract-fixtures/:
diagnostics_progress_fields.json, diagnostics_scan_report_fields.json)
match Kotlin wire classes.serde_json, asserts schema version, verifies outcome taxonomy covers all
emitted native outcome tokens.After a wire change: update structs in Rust/Kotlin, run Rust tests to
regenerate golden files (assert_contract_fixture writes on mismatch in
update mode), then run Kotlin tests. Commit updated fixtures with the code.
app_settings.proto.AppSettingsSerializer.defaultValue.toUiState(), toConfigDraft()).app_settings.proto.reserved numbers list.reserved names list.#[serde(default)] in Rust wire struct.@Serializable data class.DIAGNOSTICS_ENGINE_SCHEMA_VERSION in both Rust and Kotlin.app_settings.protoreserved lines (numbers AND names)AppSettingsSerializer.defaultValue#[serde(default)] / Kotlin defaultscargo test --locked -p ripdpi-monitor-engine) and Kotlin contract tests pass