diff --git a/calm-hub/pom.xml b/calm-hub/pom.xml
index e5ec065af..9e37b4d4f 100644
--- a/calm-hub/pom.xml
+++ b/calm-hub/pom.xml
@@ -97,6 +97,40 @@
owasp-java-html-sanitizer
20240325.1
+
+
+
+ io.quarkus
+ quarkus-caffeine
+
+
+
+
+ org.eclipse.jgit
+ org.eclipse.jgit
+ 7.2.0.202503040940-r
+
+
+
+
+ io.quarkus
+ quarkus-scheduler
+
+
+
+
+ io.quarkus
+ quarkus-opentelemetry
+
+
+ io.quarkus
+ quarkus-micrometer-opentelemetry
+
+
io.quarkus
quarkus-oidc
diff --git a/calm-hub/src/main/resources/application.properties b/calm-hub/src/main/resources/application.properties
index bb30515be..127bd6f21 100644
--- a/calm-hub/src/main/resources/application.properties
+++ b/calm-hub/src/main/resources/application.properties
@@ -155,4 +155,37 @@ calm.mcp.enabled=false
# Log every JSON-RPC message in dev mode for easier debugging of MCP clients.
%dev.quarkus.mcp.server.traffic-logging=true
quarkus.log.category."org.finos.calm".level=DEBUG
-quarkus.log.category."org.mongodb.driver".level=OFF
\ No newline at end of file
+quarkus.log.category."org.mongodb.driver".level=OFF
+
+# OpenTelemetry — the extension is always compiled in (quarkus.otel.enabled is a
+# build-time flag; a build-once-deploy-many pipeline can't flip it per environment)
+# and disabled at runtime by default via the genuinely runtime-mutable
+# quarkus.otel.sdk.disabled. Set CALM_OTEL_DISABLED=false on the deployed
+# container/process to turn it on — no rebuild required.
+quarkus.otel.service.name=${OTEL_SERVICE_NAME:calm-hub}
+quarkus.otel.enabled=true
+quarkus.otel.sdk.disabled=${CALM_OTEL_DISABLED:true}
+quarkus.otel.exporter.otlp.endpoint=${OTEL_EXPORTER_OTLP_ENDPOINT:http://localhost:4317}
+quarkus.otel.traces.sampler=parentbased_traceidratio
+quarkus.otel.traces.sampler.arg=${CALM_OTEL_SAMPLING_RATIO:1.0}
+# Micrometer has no equivalent runtime-mutable switch — quarkus.micrometer.enabled
+# and the binder .enabled properties below are all build-time-fixed (they decide
+# which binder beans get compiled in at all), so CALM_OTEL_METRICS_ENABLED is a
+# build-time knob: it must be set when the artifact is built, not per-deployment.
+quarkus.micrometer.enabled=true
+quarkus.micrometer.binder.http-server.enabled=${CALM_OTEL_METRICS_ENABLED:false}
+quarkus.micrometer.binder.http-client.enabled=${CALM_OTEL_METRICS_ENABLED:false}
+
+# Disable Micrometer to avoid noise across every test profile in this module —
+# quarkus.micrometer.enabled is build/run-time-fixed per active profile NAME (the
+# same pitfall the jacoco comment above documents), so a %test. prefix only
+# applies when a test's QuarkusTestProfile.getConfigProfile() is literally "test";
+# each custom profile name used in this module needs its own override or
+# Micrometer's core registry (and its auto-enabled binders) stays active under it.
+# quarkus.otel.sdk.disabled needs no such per-profile treatment: it's genuinely
+# RUN_TIME-scoped and already defaults to disabled everywhere, tests included.
+%test.quarkus.micrometer.enabled=false
+%integration-test.quarkus.micrometer.enabled=false
+%nitrite-integration-test.quarkus.micrometer.enabled=false
+%secure.quarkus.micrometer.enabled=false
+%proxy-auth.quarkus.micrometer.enabled=false
\ No newline at end of file