Closes a 15-commit-old TODO on MetaController and unifies the
version story across /api/v1/_meta/info, /v3/api-docs, and the
api-v1.jar manifest.
**Build metadata wiring.** `distribution/build.gradle.kts` now
calls `buildInfo()` inside the `springBoot { }` block. This makes
Spring Boot's Gradle plug-in write `META-INF/build-info.properties`
into the bootJar at build time with group / artifact / version /
build time pulled from `project.version` + timestamps. Spring
Boot's `BuildInfoAutoConfiguration` then exposes a `BuildProperties`
bean that injection points can consume.
**MetaController enriched.** Now injects:
- `ObjectProvider<BuildProperties>` — returns the real version
(`0.28.0-SNAPSHOT`) and the build timestamp when packaged
through the distribution bootJar; falls back to `0.0.0-test`
inside a bare platform-bootstrap unit test classloader with
no build-info file on the classpath.
- `Environment` — returns `spring.profiles.active` so a
dashboard can distinguish "dev" from "staging" from a prod
container that activates no profile.
The GET /api/v1/_meta/info response now carries:
- `name`, `apiVersion` — unchanged
- `implementationVersion` — from BuildProperties (was stuck at
"0.1.0-SNAPSHOT" via an unreachable `javaClass.package` lookup)
- `buildTime` — ISO-8601 string from BuildProperties, null if
the classpath has no build-info file
- `activeProfiles` — list of effective spring profiles
**OpenApiConfiguration now reads version from BuildProperties too.**
Previously OPENAPI_INFO_VERSION was a hardcoded "v0.28.0"
constant. Now it's injected via ObjectProvider<BuildProperties>
with the same fallback pattern as MetaController. A single
version bump in gradle.properties now flows to:
gradle.properties
→ Spring Boot's buildInfo()
→ build-info.properties (on the classpath)
→ BuildProperties bean
→ MetaController (/_meta/info)
→ OpenApiConfiguration (/v3/api-docs + Swagger UI)
→ api-v1.jar manifest (already wired)
No more hand-maintained version strings in code. Bump
`vibeerp.version` in gradle.properties and every display follows.
**Version bump.** `gradle.properties` `vibeerp.version`:
`0.1.0-SNAPSHOT` → `0.28.0-SNAPSHOT`. This matches the numeric
label used on PROGRESS.md's "Latest version" row and carries a
documentation comment explaining the propagation chain so the
next person bumping it knows what to update alongside (just the
one line + PROGRESS.md).
**KDoc trap caught.** A literal `/api/v1/_meta/**` path pattern
in MetaController's KDoc tripped the Kotlin nested-comment
parser (`/**` starts a KDoc). Rephrased as "the whole `/api/v1/_meta`
prefix" to sidestep the trap — same workaround I saved in
feedback memory after the first time it bit me.
**Smoke-tested end-to-end against real Postgres:**
- GET /api/v1/_meta/info returns
`{"implementationVersion": "0.28.0-SNAPSHOT",
"buildTime": "2026-04-09T09:48:25.646Z",
"activeProfiles": ["dev"]}`
- GET /v3/api-docs `info.version` = "0.28.0-SNAPSHOT" (was
the hardcoded "v0.28.0" constant before this chunk)
- Single edit to gradle.properties propagates cleanly.
24 modules, 355 unit tests, all green.