[
https://issues.apache.org/jira/browse/UNOMI-963?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Serge Huber updated UNOMI-963:
------------------------------
Description:
h2. Summary
Enrich Apache Unomi's *live* OpenAPI document (CXF {{OpenApiFeature}} / {{GET
/cxs/openapi.json}} + Swagger UI) so developers get usable statuses, examples,
and *wire-accurate* schemas—without changing REST behavior.
*Approach (decided):* treat *Javadoc* as the source of truth. At build time,
the external toolkit
*[https://repo1.maven.org/maven2/dev/inoyu/openapi/|dev.inoyu.openapi]
openapi-enrich {{0.1.0}}* (Maven Central) scans sources into enrichment packs;
at runtime CXF merges them. Optional thin machine tags {{@api.status}} /
{{@api.example}} where inference needs help.
*Toolkit provenance:* *openapi-enrich* was *designed and developed for this
Unomi need* (Javadoc-driven enrichment of a CXF/OSGi live OpenAPI, without mass
Swagger annotations) and *open-sourced by [https://inoyu.dev|Inoyu]* under
Apache-2.0 on Maven Central under the {{dev.inoyu.openapi}} coordinates. Unomi
depends on the published artifacts as a normal third-party library—it does
*not* vendor the toolkit sources.
*Toolkit links:*
* GitHub: [https://github.com/inoyu-dev/openapi-enrich]
* README (usage, {{@api.status}} / {{@api.example}} grammar, pack format):
[https://github.com/inoyu-dev/openapi-enrich/blob/main/README.md]
* Maven Central: [https://repo1.maven.org/maven2/dev/inoyu/openapi/]
*Explicitly not used:* Swagger/OpenAPI annotations such as {{@Operation}},
{{@ApiResponse}}, {{@Schema(description=...)}}. Those would *duplicate*
existing Javadoc, drift from code, and fight Unomi's OSGi/dynamic surface. (The
issue *summary* previously mentioned Swagger annotations; that path was
rejected.)
*Primary consumers:* integration engineers (Swagger UI, curl/Postman), OpenAPI
codegen / typed clients, {{unomi-ui}} / tooling, AI agents that need a real
contract (not empty {{application/json: {}}}/{{default}} responses).
*Related (not a duplicate):* [UNOMI-899] (replace jaxrs-analyzer / CXF OpenAPI
*generation*). That covers *how* the live spec is produced; this ticket covers
*documentation completeness* of that generation.
*PR:* [https://github.com/apache/unomi/pull/826|#826] — branch
{{UNOMI-963-openapi-javadoc-enrichment}}
----
h2. Problem
The live spec was path-complete but documentation-poor:
* Methods returning {{javax.ws.rs.core.Response}} often showed empty bodies
even when the wire JSON is a typed DTO.
* Responses were overwhelmingly a single {{default}} entry; named
{{200}}/{{204}}/{{400}}/{{403}}/{{404}}… were missing.
* Schemas often lacked field descriptions, and sometimes leaked Java/transient
names instead of *wire* JSON (e.g. Condition {{type}} + {{parameterValues}} vs
internal ids).
* Stock CXF {{JavaDocProvider}} scrapes *generated Javadoc HTML*—brittle across
JDKs.
* Mass Swagger annotations would duplicate Javadoc and drift.
----
h2. Goals
# Live OpenAPI remains *deployment-accurate* (CXF reflects OSGi-registered
resources only).
# Enrichment packs generated at *build time* from Java + Javadoc (+ JAX-RS
annotations)—*no HTML scrape*, *no Swagger annotation dual-maint*.
# Prose stays in Javadoc; thin {{@api.*}} tags only where status/example/schema
binding needs an explicit signal.
# OpenAPI useful for humans *and* agents: summaries, params, named statuses,
examples, {{$ref}} schemas, stable operation keys, wire names.
# Per-bundle packs so optional extensions contribute docs only when installed.
----
h2. Non-goals
* Mass {{@Schema(description=...)}} / {{@Operation(summary=...)}} /
{{@ApiResponse}} copying Javadoc (*rejected*).
* Using CXF {{JavaDocProvider}} HTML scraping in production.
* Replacing CXF {{OpenApiFeature}} with a build-time-only OpenAPI as the sole
live API.
* Breaking HTTP wire contracts (paths, methods, status semantics, JSON shapes).
* Enriching {{GET /api-docs/{resource}}} (Swagger helper, not a product API).
----
h2. Architecture (as implemented)
{code}
Maven (rest + extension REST modules)
→ openapi-enrich-maven-plugin (dev.inoyu.openapi:0.1.0)
→ META-INF/openapi-enrich/openapi-doc.json (pack)
packaged in OSGi bundle
Runtime
→ BundleContextDocPackLoader discovers packs from *installed* bundles
→ EnrichingOpenApiCustomizer merges ops/schemas/examples into CXF OpenAPI
→ OpenApiFeature serves complete /cxs/openapi.json
{code}
Unomi *wires* the toolkit and supplies Javadoc content; correctness (aliases,
{{@XmlTransient}} suppress, inherited JAX-RS methods, path-param regex
normalize, subclass override docs) lives in the Central library maintained by
Inoyu.
Servlet surface in scope: {{GET /health/check}} via servlet pack merge
(healthcheck module).
----
----
h2. Gold coverage (what it means + how much work)
h3. What "gold" means
We score each HTTP operation in the live {{/cxs/openapi.json}} as:
|| Tier || Criteria ||
| *Gold* | Has a *named* success/error status (e.g. {{200}}/{{204}}/{{400}})
whose description is *not* empty/{{default response}}, *and* the operation
carries at least one response *example* |
| *Partial* | Has statuses *or* an example, but not both to gold standard |
| *Weak* | Neither usable statuses nor examples |
That bar is what makes Swagger UI and codegen useful: developers see *what can
happen* and *what a valid body looks like*, not a CXF skeleton.
h3. Result on this branch
* *179 / 179* operations *gold* (excluding {{GET /api-docs/{resource}}},
intentionally skipped — Swagger helper, not a product API).
* *0* partial, *0* weak on the product surface after the final example pass.
* Critical schemas verified: Condition/Action expose wire {{type}} +
{{parameterValues}}; Event exposes {{profileId}}/{{sessionId}} (not leaked
nested/transient fields).
h3. Work that got us there
Not a thin status pass — end-to-end enrichment of the JAX-RS inventory (~180
ops) plus schema quality:
# *Toolkit (Inoyu, open-sourced):* openapi-enrich {{0.1.0}} — scan/Javadoc
tags, schema inheritance, wire aliases, {{@XmlTransient}} suppress, HTTP
overloads, inherited JAX-RS methods, path-param regex normalize, subclass
override docs, servlet merge — published to Maven Central so Unomi (and CI)
resolve a release, not a SNAPSHOT.
# *Exemplar content:* Tenant + Health to prove the pipeline and tag grammar.
# *Hot paths:* context, eventcollector, profiles (36 ops), rules, segments,
privacy — statuses, examples, shared models (Query, PartialList,
Condition/Action, …).
# *Mid + thin REST + extensions:* definitions, campaigns, scoring, goals,
events, tasks, scopes, query, cluster, client, patch, userList, test/ping, plus
json-schema, lists, geonames, router import/export, groovy, SFDC, healthcheck.
# *Gold completion pass:* every remaining partial (void DELETE/OPTIONS/thin
GETs, geonames regex-path ops, query metrics) got *context-specific*
{{@api.example}} values (entity illustrations, JS for {{context.js}}, CSV for
export, {{true}}/maps where appropriate)—so "examples everywhere" is
intentional and domain-relevant, not filler.
*Effort order of magnitude (tracker planning bands):* toolkit MVP roughly *4–8*
person-days; Unomi hot-path content roughly *4–7* person-days; full
Tenant-quality inventory across mid/thin/extensions a further multi-day content
push on top—plus the final gold example sweep after live scorecards.
----
h2. Delivery status (2026-07-15)
|| Area || Status ||
| Toolkit published Central {{0.1.0}} | Done |
| Unomi pin {{${openapi.enrich.version}=0.1.0}} | Done (PR #826) |
| Hot paths (context, events, profiles, rules, segments, privacy) | Done |
| Mid / thin REST + extensions (incl. geonames, lists, json-schema, router,
groovy, SFDC, health) | Done |
| Live verify | *179/179* **gold** excl. {{/api-docs}} — see *Gold coverage*
above for definition + work scope |
| ASF review | PR [https://github.com/apache/unomi/pull/826|#826] open |
----
h2. Acceptance criteria
h3. Pipeline
* [x] Maven Mojo extracts JAX-RS + Javadoc into versioned JSON packs (format
{{1.1}}).
* [x] Packs at {{META-INF/openapi-enrich/openapi-doc.json}} in REST OSGi
bundles.
* [x] Runtime discovery loads packs only from *installed* bundles.
* [x] {{OpenApiCustomizer}} merge for statuses, examples, schema property docs,
response {{$ref}}s.
* [x] Wired from {{RestServer}}; dependency on Central {{0.1.0}} (not SNAPSHOT).
h3. Coverage / quality
* [x] Core + common/optional extension REST inventory enriched (excl.
{{/api-docs}}).
* [x] {{Response}}/multi-status methods have named statuses where realistic.
* [x] Key DTOs (Profile, Event, Condition/Action, Query, PartialList, Tenant,
…) documented; wire aliases / transient suppress.
* [x] {{GET /health/check}} documented when health bundle installed.
* [x] No Swagger annotation dual-maint; Javadoc + {{@api.status}} /
{{@api.example}} only.
h3. Compatibility
* [x] Documentation-only (no intentional wire/behavior change).
* [ ] CI green on PR #826; REST ITs unchanged aside from build resolving
Central artifacts.
----
h2. References
* PR: [https://github.com/apache/unomi/pull/826]
* Toolkit:
[https://repo1.maven.org/maven2/dev/inoyu/openapi/cxf-openapi-enricher/0.1.0/]
* {{RestServer.java}} — OpenApiFeature / EnrichingOpenApiCustomizer
* Exemplars: {{TenantEndpoint}}, {{ContextJsonEndpoint}},
{{RulesServiceEndPoint}}, {{HealthCheckServlet}}
* Related: [UNOMI-899]
* Toolkit GitHub: [https://github.com/inoyu-dev/openapi-enrich]
* Toolkit README:
[https://github.com/inoyu-dev/openapi-enrich/blob/main/README.md]
* Toolkit on Central:
[https://repo1.maven.org/maven2/dev/inoyu/openapi/cxf-openapi-enricher/0.1.0/]
* Toolkit author/publisher: [https://inoyu.dev|Inoyu] (Apache-2.0)
was:
h2. Summary
Enrich Apache Unomi's *live* OpenAPI document (CXF {{OpenApiFeature}} / {{GET
/cxs/openapi.json}} + Swagger UI) so developers get usable statuses, examples,
and *wire-accurate* schemas—without changing REST behavior.
*Approach (decided):* treat *Javadoc* as the source of truth. At build time,
the external toolkit
*[https://repo1.maven.org/maven2/dev/inoyu/openapi/|dev.inoyu.openapi]
openapi-enrich {{0.1.0}}* (Maven Central) scans sources into enrichment packs;
at runtime CXF merges them. Optional thin machine tags {{@api.status}} /
{{@api.example}} where inference needs help.
*Toolkit provenance:* *openapi-enrich* was *designed and developed for this
Unomi need* (Javadoc-driven enrichment of a CXF/OSGi live OpenAPI, without mass
Swagger annotations) and *open-sourced by [https://inoyu.dev|Inoyu]* under
Apache-2.0 on Maven Central under the {{dev.inoyu.openapi}} coordinates. Unomi
depends on the published artifacts as a normal third-party library—it does
*not* vendor the toolkit sources.
*Toolkit links:*
* GitHub: [https://github.com/inoyu-dev/openapi-enrich]
* README (usage, {{@api.status}} / {{@api.example}} grammar, pack format):
[https://github.com/inoyu-dev/openapi-enrich/blob/main/README.md]
* Maven Central: [https://repo1.maven.org/maven2/dev/inoyu/openapi/]
*Explicitly not used:* Swagger/OpenAPI annotations such as {{@Operation}},
{{@ApiResponse}}, {{@Schema(description=...)}}. Those would *duplicate*
existing Javadoc, drift from code, and fight Unomi's OSGi/dynamic surface. (The
issue *summary* previously mentioned Swagger annotations; that path was
rejected.)
*Primary consumers:* integration engineers (Swagger UI, curl/Postman), OpenAPI
codegen / typed clients, {{unomi-ui}} / tooling, AI agents that need a real
contract (not empty {{application/json: {}}}/{{default}} responses).
*Related (not a duplicate):* [UNOMI-899] (replace jaxrs-analyzer / CXF OpenAPI
*generation*). That covers *how* the live spec is produced; this ticket covers
*documentation completeness* of that generation.
*PR:* [https://github.com/apache/unomi/pull/826|#826] — branch
{{UNOMI-963-openapi-javadoc-enrichment}}
----
h2. Problem
The live spec was path-complete but documentation-poor:
* Methods returning {{javax.ws.rs.core.Response}} often showed empty bodies
even when the wire JSON is a typed DTO.
* Responses were overwhelmingly a single {{default}} entry; named
{{200}}/{{204}}/{{400}}/{{403}}/{{404}}… were missing.
* Schemas often lacked field descriptions, and sometimes leaked Java/transient
names instead of *wire* JSON (e.g. Condition {{type}} + {{parameterValues}} vs
internal ids).
* Stock CXF {{JavaDocProvider}} scrapes *generated Javadoc HTML*—brittle across
JDKs.
* Mass Swagger annotations would duplicate Javadoc and drift.
----
h2. Goals
# Live OpenAPI remains *deployment-accurate* (CXF reflects OSGi-registered
resources only).
# Enrichment packs generated at *build time* from Java + Javadoc (+ JAX-RS
annotations)—*no HTML scrape*, *no Swagger annotation dual-maint*.
# Prose stays in Javadoc; thin {{@api.*}} tags only where status/example/schema
binding needs an explicit signal.
# OpenAPI useful for humans *and* agents: summaries, params, named statuses,
examples, {{$ref}} schemas, stable operation keys, wire names.
# Per-bundle packs so optional extensions contribute docs only when installed.
----
h2. Non-goals
* Mass {{@Schema(description=...)}} / {{@Operation(summary=...)}} /
{{@ApiResponse}} copying Javadoc (*rejected*).
* Using CXF {{JavaDocProvider}} HTML scraping in production.
* Replacing CXF {{OpenApiFeature}} with a build-time-only OpenAPI as the sole
live API.
* Breaking HTTP wire contracts (paths, methods, status semantics, JSON shapes).
* Enriching {{GET /api-docs/{resource}}} (Swagger helper, not a product API).
----
h2. Architecture (as implemented)
{code}
Maven (rest + extension REST modules)
→ openapi-enrich-maven-plugin (dev.inoyu.openapi:0.1.0)
→ META-INF/openapi-enrich/openapi-doc.json (pack)
packaged in OSGi bundle
Runtime
→ BundleContextDocPackLoader discovers packs from *installed* bundles
→ EnrichingOpenApiCustomizer merges ops/schemas/examples into CXF OpenAPI
→ OpenApiFeature serves complete /cxs/openapi.json
{code}
Unomi *wires* the toolkit and supplies Javadoc content; correctness (aliases,
{{@XmlTransient}} suppress, inherited JAX-RS methods, path-param regex
normalize, subclass override docs) lives in the Central library maintained by
Inoyu.
Servlet surface in scope: {{GET /health/check}} via servlet pack merge
(healthcheck module).
h2. Gold coverage (what it means + how much work)
h3. What "gold" means
We score each HTTP operation in the live {{/cxs/openapi.json}} as:
|| Tier || Criteria ||
| *Gold* | Has a *named* success/error status (e.g. {{200}}/{{204}}/{{400}})
whose description is *not* empty/{{default response}}, *and* the operation
carries at least one response *example* |
| *Partial* | Has statuses *or* an example, but not both to gold standard |
| *Weak* | Neither usable statuses nor examples |
That bar is what makes Swagger UI and codegen useful: developers see *what can
happen* and *what a valid body looks like*, not a CXF skeleton.
h3. Result on this branch
* *179 / 179* operations *gold* (excluding {{GET /api-docs/{resource}}},
intentionally skipped — Swagger helper, not a product API).
* *0* partial, *0* weak on the product surface after the final example pass.
* Critical schemas verified: Condition/Action expose wire {{type}} +
{{parameterValues}}; Event exposes {{profileId}}/{{sessionId}} (not leaked
nested/transient fields).
h3. Work that got us there
Not a thin status pass — end-to-end enrichment of the JAX-RS inventory (~180
ops) plus schema quality:
# *Toolkit (Inoyu, open-sourced):* openapi-enrich {{0.1.0}} — scan/Javadoc
tags, schema inheritance, wire aliases, {{@XmlTransient}} suppress, HTTP
overloads, inherited JAX-RS methods, path-param regex normalize, subclass
override docs, servlet merge — published to Maven Central so Unomi (and CI)
resolve a release, not a SNAPSHOT.
# *Exemplar content:* Tenant + Health to prove the pipeline and tag grammar.
# *Hot paths:* context, eventcollector, profiles (36 ops), rules, segments,
privacy — statuses, examples, shared models (Query, PartialList,
Condition/Action, …).
# *Mid + thin REST + extensions:* definitions, campaigns, scoring, goals,
events, tasks, scopes, query, cluster, client, patch, userList, test/ping, plus
json-schema, lists, geonames, router import/export, groovy, SFDC, healthcheck.
# *Gold completion pass:* every remaining partial (void DELETE/OPTIONS/thin
GETs, geonames regex-path ops, query metrics) got *context-specific*
{{@api.example}} values (entity illustrations, JS for {{context.js}}, CSV for
export, {{true}}/maps where appropriate)—so "examples everywhere" is
intentional and domain-relevant, not filler.
*Effort order of magnitude (tracker planning bands):* toolkit MVP roughly *4–8*
person-days; Unomi hot-path content roughly *4–7* person-days; full
Tenant-quality inventory across mid/thin/extensions a further multi-day content
push on top—plus the final gold example sweep after live scorecards.
----
h2. Delivery status (2026-07-15)
|| Area || Status ||
| Toolkit published Central {{0.1.0}} | Done |
| Unomi pin {{${openapi.enrich.version}=0.1.0}} | Done (PR #826) |
| Hot paths (context, events, profiles, rules, segments, privacy) | Done |
| Mid / thin REST + extensions (incl. geonames, lists, json-schema, router,
groovy, SFDC, health) | Done |
| Live verify | *179/179* **gold** excl. {{/api-docs}} — see *Gold coverage*
above for definition + work scope |
| ASF review | PR [https://github.com/apache/unomi/pull/826|#826] open |
----
h2. Acceptance criteria
h3. Pipeline
* [x] Maven Mojo extracts JAX-RS + Javadoc into versioned JSON packs (format
{{1.1}}).
* [x] Packs at {{META-INF/openapi-enrich/openapi-doc.json}} in REST OSGi
bundles.
* [x] Runtime discovery loads packs only from *installed* bundles.
* [x] {{OpenApiCustomizer}} merge for statuses, examples, schema property docs,
response {{$ref}}s.
* [x] Wired from {{RestServer}}; dependency on Central {{0.1.0}} (not SNAPSHOT).
h3. Coverage / quality
* [x] Core + common/optional extension REST inventory enriched (excl.
{{/api-docs}}).
* [x] {{Response}}/multi-status methods have named statuses where realistic.
* [x] Key DTOs (Profile, Event, Condition/Action, Query, PartialList, Tenant,
…) documented; wire aliases / transient suppress.
* [x] {{GET /health/check}} documented when health bundle installed.
* [x] No Swagger annotation dual-maint; Javadoc + {{@api.status}} /
{{@api.example}} only.
h3. Compatibility
* [x] Documentation-only (no intentional wire/behavior change).
* [ ] CI green on PR #826; REST ITs unchanged aside from build resolving
Central artifacts.
----
h2. References
* PR: [https://github.com/apache/unomi/pull/826]
* Toolkit:
[https://repo1.maven.org/maven2/dev/inoyu/openapi/cxf-openapi-enricher/0.1.0/]
* {{RestServer.java}} — OpenApiFeature / EnrichingOpenApiCustomizer
* Exemplars: {{TenantEndpoint}}, {{ContextJsonEndpoint}},
{{RulesServiceEndPoint}}, {{HealthCheckServlet}}
* Related: [UNOMI-899]
* Toolkit GitHub: [https://github.com/inoyu-dev/openapi-enrich]
* Toolkit README:
[https://github.com/inoyu-dev/openapi-enrich/blob/main/README.md]
* Toolkit on Central:
[https://repo1.maven.org/maven2/dev/inoyu/openapi/cxf-openapi-enricher/0.1.0/]
* Toolkit author/publisher: [https://inoyu.dev|Inoyu] (Apache-2.0)
> Improve OpenAPI completeness from Javadoc (openapi-enrich)
> ----------------------------------------------------------
>
> Key: UNOMI-963
> URL: https://issues.apache.org/jira/browse/UNOMI-963
> Project: Apache Unomi
> Issue Type: Improvement
> Components: unomi(-core)
> Affects Versions: unomi-3.0.0, unomi-2.7.0, unomi-3.1.0
> Reporter: Serge Huber
> Assignee: Serge Huber
> Priority: Major
> Fix For: unomi-3.1.0
>
> Time Spent: 20m
> Remaining Estimate: 0h
>
> h2. Summary
> Enrich Apache Unomi's *live* OpenAPI document (CXF {{OpenApiFeature}} / {{GET
> /cxs/openapi.json}} + Swagger UI) so developers get usable statuses,
> examples, and *wire-accurate* schemas—without changing REST behavior.
> *Approach (decided):* treat *Javadoc* as the source of truth. At build time,
> the external toolkit
> *[https://repo1.maven.org/maven2/dev/inoyu/openapi/|dev.inoyu.openapi]
> openapi-enrich {{0.1.0}}* (Maven Central) scans sources into enrichment
> packs; at runtime CXF merges them. Optional thin machine tags {{@api.status}}
> / {{@api.example}} where inference needs help.
> *Toolkit provenance:* *openapi-enrich* was *designed and developed for this
> Unomi need* (Javadoc-driven enrichment of a CXF/OSGi live OpenAPI, without
> mass Swagger annotations) and *open-sourced by [https://inoyu.dev|Inoyu]*
> under Apache-2.0 on Maven Central under the {{dev.inoyu.openapi}}
> coordinates. Unomi depends on the published artifacts as a normal third-party
> library—it does *not* vendor the toolkit sources.
> *Toolkit links:*
> * GitHub: [https://github.com/inoyu-dev/openapi-enrich]
> * README (usage, {{@api.status}} / {{@api.example}} grammar, pack format):
> [https://github.com/inoyu-dev/openapi-enrich/blob/main/README.md]
> * Maven Central: [https://repo1.maven.org/maven2/dev/inoyu/openapi/]
> *Explicitly not used:* Swagger/OpenAPI annotations such as {{@Operation}},
> {{@ApiResponse}}, {{@Schema(description=...)}}. Those would *duplicate*
> existing Javadoc, drift from code, and fight Unomi's OSGi/dynamic surface.
> (The issue *summary* previously mentioned Swagger annotations; that path was
> rejected.)
> *Primary consumers:* integration engineers (Swagger UI, curl/Postman),
> OpenAPI codegen / typed clients, {{unomi-ui}} / tooling, AI agents that need
> a real contract (not empty {{application/json: {}}}/{{default}} responses).
> *Related (not a duplicate):* [UNOMI-899] (replace jaxrs-analyzer / CXF
> OpenAPI *generation*). That covers *how* the live spec is produced; this
> ticket covers *documentation completeness* of that generation.
> *PR:* [https://github.com/apache/unomi/pull/826|#826] — branch
> {{UNOMI-963-openapi-javadoc-enrichment}}
> ----
> h2. Problem
> The live spec was path-complete but documentation-poor:
> * Methods returning {{javax.ws.rs.core.Response}} often showed empty bodies
> even when the wire JSON is a typed DTO.
> * Responses were overwhelmingly a single {{default}} entry; named
> {{200}}/{{204}}/{{400}}/{{403}}/{{404}}… were missing.
> * Schemas often lacked field descriptions, and sometimes leaked
> Java/transient names instead of *wire* JSON (e.g. Condition {{type}} +
> {{parameterValues}} vs internal ids).
> * Stock CXF {{JavaDocProvider}} scrapes *generated Javadoc HTML*—brittle
> across JDKs.
> * Mass Swagger annotations would duplicate Javadoc and drift.
> ----
> h2. Goals
> # Live OpenAPI remains *deployment-accurate* (CXF reflects OSGi-registered
> resources only).
> # Enrichment packs generated at *build time* from Java + Javadoc (+ JAX-RS
> annotations)—*no HTML scrape*, *no Swagger annotation dual-maint*.
> # Prose stays in Javadoc; thin {{@api.*}} tags only where
> status/example/schema binding needs an explicit signal.
> # OpenAPI useful for humans *and* agents: summaries, params, named statuses,
> examples, {{$ref}} schemas, stable operation keys, wire names.
> # Per-bundle packs so optional extensions contribute docs only when installed.
> ----
> h2. Non-goals
> * Mass {{@Schema(description=...)}} / {{@Operation(summary=...)}} /
> {{@ApiResponse}} copying Javadoc (*rejected*).
> * Using CXF {{JavaDocProvider}} HTML scraping in production.
> * Replacing CXF {{OpenApiFeature}} with a build-time-only OpenAPI as the sole
> live API.
> * Breaking HTTP wire contracts (paths, methods, status semantics, JSON
> shapes).
> * Enriching {{GET /api-docs/{resource}}} (Swagger helper, not a product API).
> ----
> h2. Architecture (as implemented)
> {code}
> Maven (rest + extension REST modules)
> → openapi-enrich-maven-plugin (dev.inoyu.openapi:0.1.0)
> → META-INF/openapi-enrich/openapi-doc.json (pack)
> packaged in OSGi bundle
> Runtime
> → BundleContextDocPackLoader discovers packs from *installed* bundles
> → EnrichingOpenApiCustomizer merges ops/schemas/examples into CXF OpenAPI
> → OpenApiFeature serves complete /cxs/openapi.json
> {code}
> Unomi *wires* the toolkit and supplies Javadoc content; correctness (aliases,
> {{@XmlTransient}} suppress, inherited JAX-RS methods, path-param regex
> normalize, subclass override docs) lives in the Central library maintained by
> Inoyu.
> Servlet surface in scope: {{GET /health/check}} via servlet pack merge
> (healthcheck module).
> ----
> ----
> h2. Gold coverage (what it means + how much work)
> h3. What "gold" means
> We score each HTTP operation in the live {{/cxs/openapi.json}} as:
> || Tier || Criteria ||
> | *Gold* | Has a *named* success/error status (e.g. {{200}}/{{204}}/{{400}})
> whose description is *not* empty/{{default response}}, *and* the operation
> carries at least one response *example* |
> | *Partial* | Has statuses *or* an example, but not both to gold standard |
> | *Weak* | Neither usable statuses nor examples |
> That bar is what makes Swagger UI and codegen useful: developers see *what
> can happen* and *what a valid body looks like*, not a CXF skeleton.
> h3. Result on this branch
> * *179 / 179* operations *gold* (excluding {{GET /api-docs/{resource}}},
> intentionally skipped — Swagger helper, not a product API).
> * *0* partial, *0* weak on the product surface after the final example pass.
> * Critical schemas verified: Condition/Action expose wire {{type}} +
> {{parameterValues}}; Event exposes {{profileId}}/{{sessionId}} (not leaked
> nested/transient fields).
> h3. Work that got us there
> Not a thin status pass — end-to-end enrichment of the JAX-RS inventory (~180
> ops) plus schema quality:
> # *Toolkit (Inoyu, open-sourced):* openapi-enrich {{0.1.0}} — scan/Javadoc
> tags, schema inheritance, wire aliases, {{@XmlTransient}} suppress, HTTP
> overloads, inherited JAX-RS methods, path-param regex normalize, subclass
> override docs, servlet merge — published to Maven Central so Unomi (and CI)
> resolve a release, not a SNAPSHOT.
> # *Exemplar content:* Tenant + Health to prove the pipeline and tag grammar.
> # *Hot paths:* context, eventcollector, profiles (36 ops), rules, segments,
> privacy — statuses, examples, shared models (Query, PartialList,
> Condition/Action, …).
> # *Mid + thin REST + extensions:* definitions, campaigns, scoring, goals,
> events, tasks, scopes, query, cluster, client, patch, userList, test/ping,
> plus json-schema, lists, geonames, router import/export, groovy, SFDC,
> healthcheck.
> # *Gold completion pass:* every remaining partial (void DELETE/OPTIONS/thin
> GETs, geonames regex-path ops, query metrics) got *context-specific*
> {{@api.example}} values (entity illustrations, JS for {{context.js}}, CSV for
> export, {{true}}/maps where appropriate)—so "examples everywhere" is
> intentional and domain-relevant, not filler.
> *Effort order of magnitude (tracker planning bands):* toolkit MVP roughly
> *4–8* person-days; Unomi hot-path content roughly *4–7* person-days; full
> Tenant-quality inventory across mid/thin/extensions a further multi-day
> content push on top—plus the final gold example sweep after live scorecards.
> ----
> h2. Delivery status (2026-07-15)
> || Area || Status ||
> | Toolkit published Central {{0.1.0}} | Done |
> | Unomi pin {{${openapi.enrich.version}=0.1.0}} | Done (PR #826) |
> | Hot paths (context, events, profiles, rules, segments, privacy) | Done |
> | Mid / thin REST + extensions (incl. geonames, lists, json-schema, router,
> groovy, SFDC, health) | Done |
> | Live verify | *179/179* **gold** excl. {{/api-docs}} — see *Gold coverage*
> above for definition + work scope |
> | ASF review | PR [https://github.com/apache/unomi/pull/826|#826] open |
> ----
> h2. Acceptance criteria
> h3. Pipeline
> * [x] Maven Mojo extracts JAX-RS + Javadoc into versioned JSON packs (format
> {{1.1}}).
> * [x] Packs at {{META-INF/openapi-enrich/openapi-doc.json}} in REST OSGi
> bundles.
> * [x] Runtime discovery loads packs only from *installed* bundles.
> * [x] {{OpenApiCustomizer}} merge for statuses, examples, schema property
> docs, response {{$ref}}s.
> * [x] Wired from {{RestServer}}; dependency on Central {{0.1.0}} (not
> SNAPSHOT).
> h3. Coverage / quality
> * [x] Core + common/optional extension REST inventory enriched (excl.
> {{/api-docs}}).
> * [x] {{Response}}/multi-status methods have named statuses where realistic.
> * [x] Key DTOs (Profile, Event, Condition/Action, Query, PartialList, Tenant,
> …) documented; wire aliases / transient suppress.
> * [x] {{GET /health/check}} documented when health bundle installed.
> * [x] No Swagger annotation dual-maint; Javadoc + {{@api.status}} /
> {{@api.example}} only.
> h3. Compatibility
> * [x] Documentation-only (no intentional wire/behavior change).
> * [ ] CI green on PR #826; REST ITs unchanged aside from build resolving
> Central artifacts.
> ----
> h2. References
> * PR: [https://github.com/apache/unomi/pull/826]
> * Toolkit:
> [https://repo1.maven.org/maven2/dev/inoyu/openapi/cxf-openapi-enricher/0.1.0/]
> * {{RestServer.java}} — OpenApiFeature / EnrichingOpenApiCustomizer
> * Exemplars: {{TenantEndpoint}}, {{ContextJsonEndpoint}},
> {{RulesServiceEndPoint}}, {{HealthCheckServlet}}
> * Related: [UNOMI-899]
> * Toolkit GitHub: [https://github.com/inoyu-dev/openapi-enrich]
> * Toolkit README:
> [https://github.com/inoyu-dev/openapi-enrich/blob/main/README.md]
> * Toolkit on Central:
> [https://repo1.maven.org/maven2/dev/inoyu/openapi/cxf-openapi-enricher/0.1.0/]
> * Toolkit author/publisher: [https://inoyu.dev|Inoyu] (Apache-2.0)
--
This message was sent by Atlassian Jira
(v8.20.10#820010)