feat: jpa, messaging, notification, mongo, graphql 어댑터터 구현체 추가

This commit is contained in:
DongHyeonka
2026-08-15 13:01:58 +09:00
parent ac874e49e6
commit 2f5d2fc219
909 changed files with 62510 additions and 6354 deletions
@@ -30,8 +30,13 @@ design package's assumed module layout onto this leaf lives in
## Allowed
- No project dependency is required. The allowed-edge SSOT remains the
`adapter-outbound-persistence-mongo` entry in `src/config/architecture/modules.json`.
- No project dependency at all. The registry entry's `allowed_dependencies` is `[]`, matching what
the build actually uses; `application-core` and `shared-contract` were listed and unused, which is
a permission granted in advance for an adapter nobody has approved yet.
- `runtime_memberships` is `[]` and no composition root depends on this leaf. Property-only
activation switches on a module that is already on the classpath; it does not put one there. A
fork that wants it in a runtime adds the membership and the dependency in the same approved
change.
- External: `spring-boot-starter-data-mongodb` and `-reactive`, `spring-boot-autoconfigure`,
`micrometer-core`, `slf4j-api`, `spring-boot-configuration-processor` (annotation processor).
Versions come from the shared Spring Boot BOM; never pin the driver directly.
@@ -56,6 +61,57 @@ These reproduce the design's module dependency table. Breaking one fails the bui
- `imperative``reactive`, `query``aggregation`, `schema` ↛ execution packages,
`observation` ↛ execution packages, `migration``migration.flamingock`.
### Consistency-bound templates
`MongoConsistencyBinder` derives one `MongoTemplate` per consistency profile. Spring Data exposes
setters and no getters for a template's supporting contract, so the parts that must travel —
write-concern resolver, write-result checking, lifecycle events, and the `ApplicationContext` that
supplies entity callbacks and auditing — are passed explicitly as a `MongoTemplateSupportContract`.
Reflection over private fields is forbidden here. A template configured with callbacks registered
programmatically outside a context cannot be reproduced by the bound path; that configuration is
unsupported rather than silently dropped.
### Public surface
341 public top-level types live in one jar, so `public` means public to every adopter regardless of
which package it sits in. `verifyMongoApiSurface` (in `check`) compares the surface against
`docs/architecture/mongo-api-surface.txt`; growing it takes
`updateMongoApiSurface -PapproveMongoApiSurfaceChange`, which is a review decision.
The architecture rule catalogue (`…mongo.architecture`) is in the **testkit** source set, not
production: it is ArchUnit input, and shipping it put rule text on every consumer's runtime
classpath.
Still pending, and deliberately not done as part of a review sweep: moving implementation packages
under an `internal` root and lowering visibility inside them. That is a mechanical change over ~200
files and belongs in its own commit, after which the snapshot above is what proves the surface
actually shrank.
### Credentials and production profiles
A production `MongoProfileProperties` must declare TLS, authentication, strict Stable API, a
non-standalone topology and finite positive timeouts; `validate()` enforces all of them. The URI is a
`secret://` reference and `MongoCredentialResolver` is the only thing that turns one into a
connection string — it hands the value to a caller-supplied function and never returns it, so the
credential is a local for one call rather than a field, a bean property or a log line.
Not shipped: the resolver implementation (a fork wires its own secret store), and the TLS lane
(trusted CA, wrong CA, hostname mismatch, expired certificate) which needs a container with real
certificates. Rotation ordering — new generation ready, traffic switch, old lease drain, close — is
covered by `MongoClientGenerationConcurrencyTest`.
### Change-stream lifecycle
`MongoChangeStreamPipeline` owns ordering: it drives events through `MongoChangeStreamRunner` with
`concatMap` and refuses any event behind its cluster-time high-water mark, so a checkpoint write
always means "everything up to here is done". Callers must feed it a `Flux` in stream order rather
than calling `runOne` themselves.
The driver-side source — `watch`, `resumeAfter`/`startAfter`, cursor lifetime and reconnection — is
**not** shipped. A fork wires its `MongoChangeStreamSubscription` to the driver and feeds the
pipeline; the resume checkpoint it must pass back is `MongoResumeCheckpointStore`'s. Saying this
plainly is the point: the policy and value objects here do not add up to a running consumer.
### Platform invariants that are not stylistic
- Transaction body retry and commit retry are **separate loops**: a new session per body attempt, and
@@ -66,8 +122,16 @@ These reproduce the design's module dependency table. Breaking one fails the bui
(ADR-MONGO-002).
- Index and validator changes go through the manifest and the admin plane; ownership gates every drop
(ADR-MONGO-004).
- Every Advanced entry point refuses construction unless its `MongoAdvancedCapabilityFlags` capability
is enabled.
- Every concrete Advanced type is annotated `@MongoAdvancedEntryPoint(capability)` or
`@MongoAdvancedPolicy`, and an entry point takes a `MongoAdvancedCapabilityGuard` and calls
`require` before it exists. `MongoAdvancedRules` enforces both halves; the classification rule is
what keeps "we gate the executable ones" from meaning "the ones somebody remembered".
- The flags are bound from `ca-skeleton.persistence-mongo.advanced.<capability>.enabled` by
`MongoAdvancedProperties`. `MongoAdvancedConfiguration` is imported by name, never auto-loaded:
the Stable lane must reference nothing under `..advanced..`.
- `MongoSearchOperations`, `MongoVectorSearchOperations` and `MongoTimeSeriesOperations` are
**scaffold** — contracts with no implementation in this repository. A fork supplies the Atlas or
time-series deployment and the implementation.
- Observation tags are limited to `MongoObservationConvention`'s allowlist.
## Tests