2727## 📑 Table of Contents
2828
2929* ⚡ [ Why this exists (practical impact)] ( #why-this-exists-practical-impact )
30- * 🆕 [ What’s new in 0.9.x ] ( #whats-new-in-09x )
30+ * 🆕 [ What’s new in 1.0.0 (GA) ] ( #whats-new-in-100-ga )
3131* ⚡ [ Real usage (what you actually do)] ( #real-usage-what-you-actually-do )
3232* ⚡ [ Quick start (2 minutes)] ( #quick-start-2-minutes )
3333* 🔁 [ Contract lifecycle model] ( #contract-lifecycle-model )
@@ -62,21 +62,112 @@ This project removes that entire class of problems.
6262
6363---
6464
65- ## What’s new in 0.9.x
65+ ## What’s new in 1.0.0 (GA)
6666
6767This is no longer a template-level customization.
6868
69- It is now a ** contract-aligned generation system with progressive adoption** .
69+ It is now a ** contract-aligned generation system with progressive adoption** — designed to adapt to existing architectures instead of forcing new ones .
7070
71- ### 1. Bring Your Own Contract (BYOC)
71+ ---
72+
73+ ### 1. Bring Your Own Envelope (BYOE)
74+
75+ Use your ** existing response envelope** without migrating to ` ServiceResponse ` .
76+
77+ ``` xml
78+ <additionalProperties >
79+ <additionalProperty >
80+ openapi-generics.envelope=io.example.contract.ApiResponse
81+ </additionalProperty >
82+ </additionalProperties >
83+ ```
84+
85+ Result:
86+
87+ * no forced migration to a new envelope type
88+ * your response model remains intact
89+ * existing contracts continue to work as-is
90+
91+ Behavior:
92+
93+ * If not configured → ` ServiceResponse<T> ` is used (default)
94+ * If configured → your envelope type becomes the base of generated wrappers
95+
96+ This removes the most common adoption blocker:
97+
98+ > "Do we need to change our response model to use this?"
99+
100+ Answer: ** No.**
101+
102+ ---
103+
104+ #### How it works
105+
106+ The platform does not generate your envelope.
107+
108+ It ** reuses it as a contract dependency** — both on the server and client side.
109+
110+ Two usage paths are supported:
111+
112+ ** 1. Springdoc-based (automatic)**
113+
114+ * Server starter detects your envelope
115+ * OpenAPI is enriched with required semantics automatically
116+ * No manual schema work is required
117+
118+ ** 2. Spec-first / manual OpenAPI**
119+
120+ * Teams can define wrapper schemas directly in OpenAPI
121+ * The wrapper expresses the relationship between the envelope and the payload
122+ * Minimal semantics are added to indicate that the schema represents a generic wrapper
123+ * Client generation reconstructs the correct generic structure from this definition
124+
125+ Example (simplified):
126+
127+ ``` yaml
128+ ApiResponseLicenseAccessResponse :
129+ type : object
130+ properties :
131+ data :
132+ $ref : " #/components/schemas/LicenseAccessResponse"
133+ x-api-wrapper : true
134+ x-api-wrapper-datatype : LicenseAccessResponse
135+ ` ` `
136+
137+ Optional: internal envelope-related models can be marked to avoid regeneration:
138+
139+ ` ` ` yaml
140+ ApiError :
141+ type : object
142+ properties :
143+ errorCode :
144+ type : string
145+ message :
146+ type : string
147+ x-ignore-model : true
148+ ` ` `
149+
150+ > Springdoc is the easiest path — not the only one.
151+
152+ In both approaches, the outcome is the same:
153+
154+ * the envelope remains your contract
155+ * OpenAPI acts as a projection
156+ * generated clients preserve the original type structure
157+
158+ > Note: BYOE currently supports flat generic envelopes (e.g. ` YourEnvelope<T>`).
159+ > More complex or nested generic shapes follow the platform’s default contract behavior.
160+
161+ ---
162+
163+ # ## 2. Bring Your Own Contract (BYOC)
72164
73165Reuse your own domain models instead of generating them :
74166
75167` ` ` xml
76- <!-- Map your DTOs to existing contract classes -->
77168<additionalProperties>
78169 <additionalProperty>
79- openapiGenerics.responseContract .CustomerDto=io.example.contract.CustomerDto
170+ openapi-generics.response-contract .CustomerDto=io.example.contract.CustomerDto
80171 </additionalProperty>
81172</additionalProperties>
82173` ` `
@@ -88,7 +179,7 @@ Result:
88179
89180---
90181
91- ### 2 . Progressive adoption (client-side only)
182+ # ## 3 . Progressive adoption (client-side only)
92183
93184Switch generation modes through the client build configuration :
94185
@@ -103,7 +194,7 @@ Switch generation modes through the client build configuration:
103194
104195---
105196
106- ### 3 . Deterministic build pipeline
197+ # ## 4 . Deterministic build pipeline
107198
108199Client generation is a **controlled execution system** :
109200
@@ -113,7 +204,7 @@ Client generation is a **controlled execution system**:
113204
114205---
115206
116- ### 4 . End-to-end samples (Spring Boot 3 & 4)
207+ # ## 5 . End-to-end samples (Spring Boot 3 & 4)
117208
118209Full pipelines are included :
119210
@@ -139,7 +230,7 @@ You only add two building blocks.
139230<dependency>
140231 <groupId>io.github.blueprintplatform</groupId>
141232 <artifactId>openapi-generics-server-starter</artifactId>
142- <version >0.9 .0</version >
233+ <version>1.0 .0</version>
143234</dependency>
144235` ` `
145236
@@ -149,7 +240,7 @@ You only add two building blocks.
149240<parent>
150241 <groupId>io.github.blueprintplatform</groupId>
151242 <artifactId>openapi-generics-java-codegen-parent</artifactId>
152- <version >0.9 .0</version >
243+ <version>1.0 .0</version>
153244</parent>
154245` ` `
155246
@@ -225,17 +316,97 @@ Client (contract-aligned)
225316The response envelope is a **shared contract**, not a generated model.
226317
227318` ` ` text
228- ServiceResponse <T>
319+ YourEnvelope <T>
229320` ` `
230321
231- Supported:
322+ > `ServiceResponse<T>` is the **default contract provided by the platform** — not a restriction.
323+
324+ The system is designed around a simple principle :
325+
326+ > Define your contract once. Preserve it end-to-end.
327+
328+ ---
329+
330+ # ## What this means in practice
331+
332+ * The response envelope is **not regenerated per endpoint**
333+ * The same contract is reused across:
334+
335+ * server responses
336+ * OpenAPI projection
337+ * generated clients
338+ * Client models **extend the contract**, instead of redefining it
339+
340+ Result :
341+
342+ * no envelope duplication
343+ * no drift between server and client
344+ * a stable, predictable type system
345+
346+ ---
347+
348+ # ## Supported shapes (deterministic scope)
232349
233350` ` ` text
234351ServiceResponse<T>
235352ServiceResponse<Page<T>>
353+ YourEnvelope<T>
236354` ` `
237355
238- Other cases follow standard OpenAPI behavior.
356+ These shapes are **explicitly supported and enforced** to guarantee :
357+
358+ * deterministic OpenAPI generation
359+ * predictable client reconstruction
360+ * zero ambiguity in generic resolution
361+
362+ > Note: Custom envelopes (BYOE) currently support a single direct generic payload (e.g. `YourEnvelope<T>`).
363+ > Nested generic payloads (e.g. `YourEnvelope<Page<T>>`) are intentionally out of scope.
364+
365+ ---
366+
367+ # ## Important: default ≠ mandatory
368+
369+ While `ServiceResponse<T>` is the canonical default, the platform does **not require you to use it**.
370+
371+ With BYOE (Bring Your Own Envelope) :
372+
373+ ` ` ` text
374+ YourEnvelope<T>
375+ ` ` `
376+
377+ can be used instead, without changing the overall model.
378+
379+ The behavior remains the same :
380+
381+ * OpenAPI is still a projection
382+ * Generics are still preserved
383+ * Clients still reconstruct the contract shape
384+
385+ ---
386+
387+ # ## Boundary of the system
388+
389+ Outside the supported shapes, the system intentionally falls back to standard OpenAPI behavior.
390+
391+ This is a **deliberate design decision** :
392+
393+ * keeps the model simple and predictable
394+ * avoids partial or misleading generics support
395+ * ensures long-term stability of generated clients
396+
397+ ---
398+
399+ # ## Mental model
400+
401+ ` ` ` text
402+ Contract (Java) → Projection (OpenAPI) → Reconstruction (Client)
403+ ` ` `
404+
405+ The envelope is the anchor of this flow.
406+
407+ It is not something the generator invents —
408+
409+ it is something the system preserves.
239410
240411---
241412
@@ -289,9 +460,10 @@ public class ServiceResponsePageCustomerDto
289460# # Design guarantees
290461
291462* ✔ Contract identity is preserved
463+ * ✔ Contract ownership is preserved (including the response envelope)
292464* ✔ Generics are preserved (within supported scope)
293465* ✔ Client generation is deterministic
294- * ✔ External models are reusable
466+ * ✔ No contract duplication (external models are reused, not regenerated)
295467* ✔ Upstream drift is detected early
296468
297469---
0 commit comments