The backend contract is Protocol Buffers. Generated gRPC/proto code is the foundation the whole service layer sits on (04 — Networking), so this doc explains where it comes from, how it's generated, and how to update it safely.
graph TD
Upstream["Upstream proto repos (Flipcash, OCP)"]
Protos[":definitions:*:protos — .proto sources (java-library)"]
Models[":definitions:*:models — generated Java/Kotlin + grpc stubs"]
Wrap[":services:* — hand-written Api/Service/Repository/Controller"]
Feat["features / shared"]
Upstream -->|/fetch-protos| Protos --> Models --> Wrap --> Feat
| Module | Plugin | Contents |
|---|---|---|
:definitions:flipcash:protos, :definitions:opencode:protos |
java-library |
The raw .proto source files under src/main/proto/. The java-library plugin packages them so the models module can compile them. |
:definitions:flipcash:models, :definitions:opencode:models |
flipcash.android.library + protobuf + protobuf.validate |
The generated Java/Kotlin message classes and gRPC stubs. |
The models build consumes the matching protos module via the protobuf(...)
configuration and runs protoc:
// definitions/<target>/models/build.gradle.kts
plugins {
alias(libs.plugins.flipcash.android.library)
alias(libs.plugins.protobuf)
alias(libs.plugins.protobuf.validate)
}
dependencies {
protobuf(project(":definitions:<target>:protos")) // source of .proto files
implementation(libs.grpc.protobuf.lite)
implementation(libs.protobuf.kotlin.lite)
}
protobuf {
protoc { artifact = "com.google.protobuf:protoc:$protobufVersion$archSuffix" }
plugins { /* protoc-gen-grpc-java */ }
}Generated output uses the lite runtime (protobuf-kotlin-lite,
grpc-protobuf-lite) suited to Android, and protobuf.validate wires up
protovalidate so requests can be validated at the Api boundary
(...orThrow() — see 04).
Never hand-edit anything under
:definitions:*:models. It is generated from the.protosources and will be overwritten. To change a model, change the.proto(upstream) and regenerate.
The hand-written code lives one layer up, in :services:* — the
Api/Service/Repository/Controller wrappers and the LocalToProtobuf /
ProtobufToLocal extensions that translate between protobuf and domain types.
Use the /fetch-protos skill rather than copying files by hand. It fetches the
latest .protos from the upstream repos, verifies they compile, summarizes the API
changes, and scaffolds missing service-layer stubs:
/fetch-protos # both targets at HEAD
/fetch-protos flipcash # flipcash only
/fetch-protos opencode <commit> # opencode at a specific commit
After fetching, run the proto-change-tracer agent to trace the impact through
generated models → Api → Service → Repository → Controller → features and get the
list of files that need updating.
/fetch-protos <target> [commit]— pull and regenerate.- Build
:definitions:<target>:modelsto confirm codegen succeeds. - Run
proto-change-tracerto find affected wrappers. - Update the hand-written
:services:*layer (new RPCs → new Api/Service methods; changed messages → mapper updates). - Add/adjust tests (12 — Testing) and build.
Keeping generated code isolated in :definitions:*:models and all
human-maintained code in :services:* means a proto bump is a mechanical
regenerate-plus-rewire, and the boundary (01) keeps
protobuf types from leaking past the service layer.