diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,38 @@
 # Changelog
 
+## 0.7.0.0 — 2026-06-05
+
+Paired with `shibuya-core 0.7.0.0`.
+
+### Breaking Changes
+
+- Tracks the new `Envelope.headers :: Maybe Headers` field added in
+  `shibuya-core 0.7.0.0`. `pgmqMessageToEnvelope` sets it to `Nothing`:
+  pgmq does not deliver an ordered, duplicate-allowing raw broker-header
+  stream. The per-message JSONB `headers` object is unordered user
+  metadata and is consumed only to derive `partition` and
+  `traceContext`, so it is deliberately not re-presented as broker
+  headers. Callers that construct `Envelope` by record literal (e.g.
+  test fixtures) must add `headers = Nothing`. A `Future:` note in
+  `Shibuya.Adapter.Pgmq.Convert` records the option of surfacing
+  producer-supplied pgmq headers later — deferred because the JSONB
+  object's unordered, unique-key shape maps lossily onto the ordered,
+  duplicate-allowing `Headers` type.
+
+### Compatibility
+
+- Requires `shibuya-core ^>=0.7.0.0` for the `headers` field on
+  `Envelope`. The bound is bumped in the library and test stanzas.
+- Lowers `cabal-version` from `3.14` to `3.12` so Nix toolchains with an
+  older bundled Cabal can build the adapter. No package-description
+  syntax requiring 3.14 was in use.
+
+### Tests
+
+- `Shibuya.Adapter.Pgmq.ConvertSpec` gains two cases asserting `headers`
+  is `Nothing`, including one where the pgmq JSONB `headers` object is
+  non-empty.
+
 ## 0.6.0.0 — 2026-05-31
 
 Paired with `shibuya-core 0.6.0.0`.
diff --git a/shibuya-pgmq-adapter.cabal b/shibuya-pgmq-adapter.cabal
--- a/shibuya-pgmq-adapter.cabal
+++ b/shibuya-pgmq-adapter.cabal
@@ -1,6 +1,6 @@
-cabal-version: 3.14
+cabal-version: 3.12
 name: shibuya-pgmq-adapter
-version: 0.6.0.0
+version: 0.7.0.0
 synopsis: PGMQ adapter for the Shibuya queue processing framework
 description:
   A Shibuya adapter that integrates with pgmq (PostgreSQL Message Queue)
@@ -46,7 +46,7 @@
     pgmq-core ^>=0.3,
     pgmq-effectful ^>=0.3,
     pgmq-hasql ^>=0.3,
-    shibuya-core ^>=0.6.0.0,
+    shibuya-core ^>=0.7.0.0,
     stm ^>=2.5,
     streamly ^>=0.11,
     streamly-core ^>=0.3,
@@ -114,7 +114,7 @@
     pgmq-migration ^>=0.3,
     quickcheck-instances ^>=0.3,
     random,
-    shibuya-core ^>=0.6.0.0,
+    shibuya-core ^>=0.7.0.0,
     shibuya-pgmq-adapter,
     stm,
     streamly ^>=0.11,
diff --git a/src/Shibuya/Adapter/Pgmq/Convert.hs b/src/Shibuya/Adapter/Pgmq/Convert.hs
--- a/src/Shibuya/Adapter/Pgmq/Convert.hs
+++ b/src/Shibuya/Adapter/Pgmq/Convert.hs
@@ -83,6 +83,22 @@
 -- Extracts W3C trace context from headers if present.
 -- Populates the delivery 'attempt' counter from pgmq's 'readCount'.
 --
+-- 'Envelope.headers' is 'Nothing': pgmq does not deliver an ordered,
+-- duplicate-allowing raw broker-header stream. The per-message JSONB
+-- @headers@ object is unordered user metadata and is consumed here only
+-- to derive @partition@ and @traceContext@; it is deliberately not
+-- re-presented as broker headers.
+--
+-- Future: if handlers need to read arbitrary producer-supplied pgmq
+-- headers (beyond the @x-pgmq-group@/@traceparent@/@tracestate@ keys we
+-- already special-case), we could surface them here by flattening the
+-- JSONB @headers@ object into @Just [(key, value)]@ (UTF-8-encoding
+-- string-valued entries; deciding how to encode non-string JSON values).
+-- This was considered and deferred because the object is unordered with
+-- unique keys, so the mapping into the ordered, duplicate-allowing
+-- 'Headers' type is inherently lossy. Revisit if a concrete use case
+-- appears.
+--
 -- 'Envelope.attributes' is left empty: pgmq has no spec-defined typed
 -- messaging-attribute conventions in OpenTelemetry semantic-conventions
 -- v1.27. The framework's @processOne@ already sets the standard
@@ -99,6 +115,7 @@
       partition = extractPartition msg.headers,
       enqueuedAt = Just msg.enqueuedAt,
       traceContext = extractTraceHeaders msg.headers,
+      headers = Nothing,
       attempt = Just (readCountToAttempt msg.readCount),
       attributes = HashMap.empty,
       payload = Pgmq.unMessageBody msg.body
diff --git a/test/Shibuya/Adapter/Pgmq/ConvertSpec.hs b/test/Shibuya/Adapter/Pgmq/ConvertSpec.hs
--- a/test/Shibuya/Adapter/Pgmq/ConvertSpec.hs
+++ b/test/Shibuya/Adapter/Pgmq/ConvertSpec.hs
@@ -272,6 +272,17 @@
         Envelope {traceContext = envTraceContext} = pgmqMessageToEnvelope msg
     envTraceContext `shouldBe` Nothing
 
+  it "does not surface broker headers (headers is Nothing) when no headers" $ do
+    let msg = mkMessage 42 (String "test") Nothing
+        Envelope {headers = envHeaders} = pgmqMessageToEnvelope msg
+    envHeaders `shouldBe` Nothing
+
+  it "leaves headers Nothing even when the JSONB headers object is non-empty" $ do
+    let hdrs = Just $ object ["x-pgmq-group" .= ("tenant-a" :: Text.Text), "custom" .= ("v" :: Text.Text)]
+        msg = mkMessage 42 (String "test") hdrs
+        Envelope {headers = envHeaders} = pgmqMessageToEnvelope msg
+    envHeaders `shouldBe` Nothing
+
   describe "attempt field" $ do
     let mkMessageWithReadCount rc =
           Pgmq.Message
