# ADR-GRPC-001: The gRPC platform ships as a registered family, not as one adapter leaf - Status: accepted - Date: 2026-08-30 - Scope: `:grpc:*`, `:grpc-advanced:*`, `src/config/architecture/modules.json` ## Context The two source plans describe a type-safe gRPC execution platform with its own API, SPI, adapters and composition root: fifteen Stable modules under `modules/grpc` and sixteen Advanced ones under `modules/grpc-advanced`, on Gradle Kotlin DSL, in package `io.backend.skeleton.grpc`, against Spring Boot 4.1. None of that layout exists here. This repository uses Groovy DSL, a fail-closed module registry that owns the leaf list, package root `dev.caskeleton`, and Spring Boot 4.0.8. The plans anticipate this: their last Global Constraint says that when the repository structure differs, file paths are remapped and the public contracts, invariants and test meanings are not changed. Two shapes were available. Fold the platform into the existing `:adapter:inbound:grpc` leaf as packages — which is what the JPA, GraphQL, WebSocket and HTTP platforms did here — or register it as a family the way `messaging:*` is registered. ## Decision Register it as a family: twelve Stable leaves under `src/grpc/` and six Advanced ones under `src/grpc-advanced/`. The deciding property is that this is not a layer of this application. Root `CLAUDE.md` already describes `messaging:*` as "a vendored messaging platform: a product with its own API, SPI, adapters and composition boundary, not a layer of this application", and the gRPC platform is the same shape for the same reason — the application is meant to reach it the way it reaches a library, through an application-owned port. The four platforms that became packages are all layers of this application; this one is not. The split between `src/grpc/` and `src/grpc-advanced/` is not organisational. The Stable plan requires that the Stable starter's build fail if it reaches an Advanced module, and separate Gradle path prefixes make that a `verifyCleanArchitectureDependencies` failure rather than a review note: `grpc-spring-boot-starter`'s registry entry names no advanced id, and it cannot acquire one silently. ## Consequences **The registry grew from 44 leaves to 62.** That is a large registry change, made deliberately and in one place. Every new leaf is `runtime_memberships: []`, so nothing ships until a second, explicit decision moves it. **The advanced boundary is checked twice.** Once by the registry at build time, and once by `GrpcStableBuildInvariant` at runtime, because a fat jar or a shaded artifact is assembled by something the registry never sees. **Four testkit modules became four test lanes.** The plan's split exists so in-process results cannot be mistaken for network results; this repository expresses that with `ca.strict-test-lane`, whose lanes fail when they discover nothing and never serve an up-to-date result. `GrpcEvidenceGrade` keeps the same rule inside the code, so a report cannot cite a contract run as transport evidence. **Codegen is not wired.** See ADR-GRPC-002.