diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,27 @@
 # Changelog
 
+## 0.6.0.0 — 2026-05-31
+
+### Breaking Changes
+
+- OpenTelemetry messaging spans now emit `messaging.operation.type =
+  "process"` instead of the deprecated `messaging.operation = "process"`
+  wire key. The Haskell constant `attrMessagingOperation` keeps the same
+  name and now resolves to the current semantic-conventions key, so source
+  imports continue to compile. Dashboards, alerts, and trace queries that
+  filter on `messaging.operation` must be updated to
+  `messaging.operation.type`.
+
+### Other Changes
+
+- Upgrade OpenTelemetry dependencies to the 1.0 ecosystem:
+  `hs-opentelemetry-api ^>= 1.0`,
+  `hs-opentelemetry-propagator-w3c ^>= 1.0`, and test-only
+  `hs-opentelemetry-exporter-in-memory ^>= 1.0`.
+- Move `hs-opentelemetry-semantic-conventions` to the latest Haskell
+  generated package available with the 1.0 release, `^>= 1.40`, and source
+  Shibuya's generic messaging keys from its typed exports.
+
 ## 0.5.0.0 — 2026-05-05
 
 ### Breaking Changes
diff --git a/shibuya-core.cabal b/shibuya-core.cabal
--- a/shibuya-core.cabal
+++ b/shibuya-core.cabal
@@ -1,6 +1,6 @@
 cabal-version: 3.14
 name: shibuya-core
-version: 0.5.0.0
+version: 0.6.0.0
 synopsis: Supervised queue processing framework for Haskell
 description:
   A supervised queue processing framework inspired by Broadway (Elixir).
@@ -70,9 +70,9 @@
     effectful ^>=2.6.1.0,
     effectful-core ^>=2.6.1.0,
     generic-lens ^>=2.3.0.0,
-    hs-opentelemetry-api ^>=0.3,
-    hs-opentelemetry-propagator-w3c ^>=0.1,
-    hs-opentelemetry-semantic-conventions ^>=0.1,
+    hs-opentelemetry-api ^>=1.0,
+    hs-opentelemetry-propagator-w3c ^>=1.0,
+    hs-opentelemetry-semantic-conventions ^>=1.40,
     lens ^>=5.3.5,
     nqe ^>=0.6,
     random ^>=1.2,
@@ -128,9 +128,8 @@
     bytestring,
     effectful,
     hs-opentelemetry-api,
-    hs-opentelemetry-exporter-in-memory ^>=0.0,
+    hs-opentelemetry-exporter-in-memory ^>=1.0,
     hspec ^>=2.11,
-    memory,
     nqe,
     shibuya-core,
     stm,
diff --git a/src/Shibuya/Core/Types.hs b/src/Shibuya/Core/Types.hs
--- a/src/Shibuya/Core/Types.hs
+++ b/src/Shibuya/Core/Types.hs
@@ -23,7 +23,7 @@
 import Data.ByteString (ByteString)
 import Data.HashMap.Strict (HashMap)
 import Data.String (IsString)
-import OpenTelemetry.Attributes (Attribute (..), PrimitiveAttribute (..))
+import OpenTelemetry.Attributes (Attribute (..))
 import Shibuya.Prelude
 
 -- | Stable identity for idempotency & observability.
diff --git a/src/Shibuya/Telemetry/Effect.hs b/src/Shibuya/Telemetry/Effect.hs
--- a/src/Shibuya/Telemetry/Effect.hs
+++ b/src/Shibuya/Telemetry/Effect.hs
@@ -38,7 +38,7 @@
   )
 where
 
-import Control.Exception (Exception, bracket_)
+import Control.Exception (Exception, bracket)
 import Data.ByteString qualified as BS
 import Data.HashMap.Strict (HashMap)
 import Data.HashMap.Strict qualified as HashMap
@@ -280,10 +280,10 @@
       let parentSpan = OTel.wrapSpanContext parentCtx
           newContext = Ctx.insertSpan parentSpan Ctx.empty
       withEffToIO (ConcUnlift Persistent Unlimited) $ \runInIO ->
-        bracket_
+        bracket
           (Ctx.attachContext newContext)
           Ctx.detachContext
-          (runInIO action)
+          (\_token -> runInIO action)
 
 --------------------------------------------------------------------------------
 -- Internal Helpers
diff --git a/src/Shibuya/Telemetry/Semantic.hs b/src/Shibuya/Telemetry/Semantic.hs
--- a/src/Shibuya/Telemetry/Semantic.hs
+++ b/src/Shibuya/Telemetry/Semantic.hs
@@ -91,12 +91,12 @@
 attrMessagingDestinationName :: Text
 attrMessagingDestinationName = unkey Sem.messaging_destination_name
 
--- | The messaging operation (@messaging.operation@).
+-- | The messaging operation type (@messaging.operation.type@).
 --
--- One of the spec-defined enum values: @publish@, @receive@, @process@,
--- @settle@, @create@. Shibuya's per-message span uses @"process"@.
+-- One of the spec-defined enum values: @create@, @send@, @receive@,
+-- @process@, @settle@. Shibuya's per-message span uses @"process"@.
 attrMessagingOperation :: Text
-attrMessagingOperation = unkey Sem.messaging_operation
+attrMessagingOperation = unkey Sem.messaging_operation_type
 
 --------------------------------------------------------------------------------
 -- Attribute Keys (Shibuya-specific)
@@ -129,7 +129,7 @@
 
 -- | A generic partition identifier (@shibuya.partition@).
 --
--- Shibuya-specific: in semantic-conventions v1.24 there is no portable
+-- Shibuya-specific: there is no portable
 -- @messaging.destination.partition.id@ key — only system-specific ones
 -- (@messaging.kafka.destination.partition@,
 -- @messaging.eventhubs.destination.partition.id@). System-specific
diff --git a/test/Shibuya/Telemetry/PropagationSpec.hs b/test/Shibuya/Telemetry/PropagationSpec.hs
--- a/test/Shibuya/Telemetry/PropagationSpec.hs
+++ b/test/Shibuya/Telemetry/PropagationSpec.hs
@@ -3,10 +3,10 @@
 -- | Tests for W3C Trace Context propagation.
 module Shibuya.Telemetry.PropagationSpec (spec) where
 
-import Data.ByteArray.Encoding (Base (..))
 import Data.ByteString (ByteString)
 import Effectful (runEff)
 import OpenTelemetry.Attributes (emptyAttributes)
+import OpenTelemetry.Exporter.InMemory (inMemoryListExporter)
 import OpenTelemetry.Trace.Core
   ( InstrumentationLibrary (..),
     createTracerProvider,
@@ -17,6 +17,7 @@
     tracerOptions,
   )
 import OpenTelemetry.Trace.Core qualified as OTel
+import OpenTelemetry.Trace.Id (Base (..))
 import OpenTelemetry.Trace.Id qualified as OTel.Id
 import Shibuya.Telemetry.Effect (runTracing, runTracingNoop, withSpan)
 import Shibuya.Telemetry.Propagation (currentTraceHeaders, extractTraceContext)
@@ -60,38 +61,29 @@
           headers = [("traceparent", "invalid-format")]
       extractTraceContext headers `shouldBe` Nothing
 
-    it "parses traceparent with non-standard version (permissive)" $ do
-      -- Note: hs-opentelemetry propagator is permissive and accepts non-00 versions
+    it "rejects traceparent with non-standard version" $ do
+      -- hs-opentelemetry 1.0 validates the traceparent version strictly.
       let headers :: [(ByteString, ByteString)]
           headers =
             [ ("traceparent", "ff-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01")
             ]
-      -- Library accepts this - validation is left to the application
-      case extractTraceContext headers of
-        Nothing -> expectationFailure "Library should parse non-standard version"
-        Just _ctx -> pure ()
+      extractTraceContext headers `shouldBe` Nothing
 
-    it "parses traceparent with all-zero trace ID (permissive)" $ do
-      -- Note: hs-opentelemetry propagator doesn't reject all-zero trace IDs
+    it "rejects traceparent with all-zero trace ID" $ do
+      -- hs-opentelemetry 1.0 rejects all-zero trace IDs.
       let headers :: [(ByteString, ByteString)]
           headers =
             [ ("traceparent", "00-00000000000000000000000000000000-b7ad6b7169203331-01")
             ]
-      -- Library accepts this - validation is left to the application
-      case extractTraceContext headers of
-        Nothing -> expectationFailure "Library should parse all-zero trace ID"
-        Just ctx -> OTel.Id.traceIdBaseEncodedText Base16 (OTel.traceId ctx) `shouldBe` "00000000000000000000000000000000"
+      extractTraceContext headers `shouldBe` Nothing
 
-    it "parses traceparent with all-zero span ID (permissive)" $ do
-      -- Note: hs-opentelemetry propagator doesn't reject all-zero span IDs
+    it "rejects traceparent with all-zero span ID" $ do
+      -- hs-opentelemetry 1.0 rejects all-zero span IDs.
       let headers :: [(ByteString, ByteString)]
           headers =
             [ ("traceparent", "00-0af7651916cd43dd8448eb211c80319c-0000000000000000-01")
             ]
-      -- Library accepts this - validation is left to the application
-      case extractTraceContext headers of
-        Nothing -> expectationFailure "Library should parse all-zero span ID"
-        Just ctx -> OTel.Id.spanIdBaseEncodedText Base16 (OTel.spanId ctx) `shouldBe` "0000000000000000"
+      extractTraceContext headers `shouldBe` Nothing
 
     it "handles unsampled trace flag (00)" $ do
       let headers :: [(ByteString, ByteString)]
@@ -151,11 +143,12 @@
               )
               tracerOptions
       result <- runEff $ runTracing tracer currentTraceHeaders
-      _ <- shutdownTracerProvider provider
+      _ <- shutdownTracerProvider provider (Just 5_000_000)
       result `shouldBe` Nothing
 
     it "returns headers carrying the active span's traceparent" $ do
-      provider <- createTracerProvider [] emptyTracerProviderOptions
+      (processor, _spansRef) <- inMemoryListExporter
+      provider <- createTracerProvider [processor] emptyTracerProviderOptions
       let tracer =
             makeTracer
               provider
@@ -168,7 +161,7 @@
               )
               tracerOptions
       result <- runEff $ runTracing tracer $ withSpan "outer" defaultSpanArguments currentTraceHeaders
-      _ <- shutdownTracerProvider provider
+      _ <- shutdownTracerProvider provider (Just 5_000_000)
       case result of
         Nothing -> expectationFailure "expected currentTraceHeaders to return Just"
         Just hs -> case lookup "traceparent" hs of
diff --git a/test/Shibuya/Telemetry/SemanticSpec.hs b/test/Shibuya/Telemetry/SemanticSpec.hs
--- a/test/Shibuya/Telemetry/SemanticSpec.hs
+++ b/test/Shibuya/Telemetry/SemanticSpec.hs
@@ -24,13 +24,16 @@
     getAttributeMap,
     toAttribute,
   )
-import OpenTelemetry.Exporter.InMemory.Span (inMemoryListExporter)
+import OpenTelemetry.Exporter.InMemory (inMemoryListExporter)
 import OpenTelemetry.Trace.Core
   ( Event (..),
     ImmutableSpan (..),
     InstrumentationLibrary (..),
     createTracerProvider,
     emptyTracerProviderOptions,
+    hotAttributes,
+    hotEvents,
+    hotName,
     makeTracer,
     shutdownTracerProvider,
     tracerOptions,
@@ -77,20 +80,21 @@
       _ <- runWithMetrics 4 procId adapter handler
       pure ()
 
-    _ <- shutdownTracerProvider provider
+    _ <- shutdownTracerProvider provider (Just 5_000_000)
     spans <- readIORef spansRef
     case spans of
       [s] -> do
-        spanName s `shouldBe` "test-proc process"
-        let attrs = getAttributeMap (spanAttributes s)
+        hot <- readIORef (spanHot s)
+        hotName hot `shouldBe` "test-proc process"
+        let attrs = getAttributeMap (hotAttributes hot)
         attrs `shouldHaveTextAttribute` ("messaging.system", "shibuya")
         attrs `shouldHaveTextAttribute` ("messaging.message.id", "m-1")
         attrs `shouldHaveTextAttribute` ("messaging.destination.name", "test-proc")
-        attrs `shouldHaveTextAttribute` ("messaging.operation", "process")
+        attrs `shouldHaveTextAttribute` ("messaging.operation.type", "process")
         attrs `shouldHaveTextAttribute` ("shibuya.ack.decision", "ack_ok")
         attrs `shouldHaveIntAttribute` ("shibuya.inflight.count", 1)
         attrs `shouldHaveIntAttribute` ("shibuya.inflight.max", 1)
-        let evNames = map eventName (toList (appendOnlyBoundedCollectionValues (spanEvents s)))
+        let evNames = map eventName (toList (appendOnlyBoundedCollectionValues (hotEvents hot)))
         evNames `shouldContain` ["shibuya.handler.started"]
         evNames `shouldContain` ["shibuya.handler.completed"]
       _ ->
@@ -139,11 +143,12 @@
       _ <- runWithMetrics 4 procId adapter handler
       pure ()
 
-    _ <- shutdownTracerProvider provider
+    _ <- shutdownTracerProvider provider (Just 5_000_000)
     spans <- readIORef spansRef
     case spans of
       [s] -> do
-        let attrs = getAttributeMap (spanAttributes s)
+        hot <- readIORef (spanHot s)
+        let attrs = getAttributeMap (hotAttributes hot)
         -- Adapter override wins.
         attrs `shouldHaveTextAttribute` ("messaging.system", "kafka")
         -- Adapter-typed attributes appear on the framework span.
@@ -151,7 +156,7 @@
         attrs `shouldHaveIntAttribute` ("messaging.kafka.message.offset", 42)
         -- Framework defaults still set where the adapter did not override.
         attrs `shouldHaveTextAttribute` ("messaging.destination.name", "orders-consumer")
-        attrs `shouldHaveTextAttribute` ("messaging.operation", "process")
+        attrs `shouldHaveTextAttribute` ("messaging.operation.type", "process")
         attrs `shouldHaveTextAttribute` ("messaging.message.id", "orders-2-42")
       _ ->
         expectationFailure $
