feat: grpc 기능 deep 구현
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user