diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,16 @@
 ## [Unreleased]
 
 
+## [0.5.0.0] — 2026-07-31
+
+### Added
+
+- `Natural` registers are supported on the wire alongside `keiki`'s new
+  `Natural` symbolic domain. A `Natural` slot round-trips as a JSON number,
+  and decoding rejects negative and fractional numbers rather than truncating
+  them. The property suite pins both directions.
+
+
 ## [0.4.0.0] — 2026-07-28
 
 ### Changed
diff --git a/keiki-codec-json.cabal b/keiki-codec-json.cabal
--- a/keiki-codec-json.cabal
+++ b/keiki-codec-json.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               keiki-codec-json
-version:            0.4.0.0
+version:            0.5.0.0
 synopsis:           Optional JSON codec for keiki's RegFile.
 description:
   Sibling package to keiki providing a JSON encoder, decoder, and
@@ -81,7 +81,7 @@
     , aeson             ^>=2.2
     , base              ^>=4.21
     , containers        ^>=0.7
-    , keiki             ^>=0.4
+    , keiki             ^>=0.5
     , scientific        ^>=0.3
     , template-haskell  ^>=2.23
     , text              ^>=2.1
@@ -96,8 +96,8 @@
     , base              ^>=4.21
     , bytestring        ^>=0.12
     , deepseq           ^>=1.5
-    , keiki             ^>=0.4
-    , keiki-codec-json  ^>=0.4
+    , keiki             ^>=0.5
+    , keiki-codec-json  ^>=0.5
     , tasty-bench       ^>=0.4  || ^>=0.5
     , text              ^>=2.1
 
@@ -124,8 +124,8 @@
     , bytestring            ^>=0.12
     , containers            ^>=0.7
     , hspec                 ^>=2.11
-    , keiki                 ^>=0.4
-    , keiki-codec-json      ^>=0.4
+    , keiki                 ^>=0.5
+    , keiki-codec-json      ^>=0.5
     , QuickCheck            ^>=2.15
     , quickcheck-instances  ^>=0.3
     , text                  ^>=2.1
diff --git a/test/Keiki/Codec/JSON/PropSpec.hs b/test/Keiki/Codec/JSON/PropSpec.hs
--- a/test/Keiki/Codec/JSON/PropSpec.hs
+++ b/test/Keiki/Codec/JSON/PropSpec.hs
@@ -22,7 +22,8 @@
   )
 import Keiki.Core (RegFile)
 import Keiki.Core qualified as Core
-import Test.Hspec (Spec, describe, it, shouldBe)
+import Numeric.Natural (Natural)
+import Test.Hspec (Spec, describe, expectationFailure, it, shouldBe)
 import Test.QuickCheck (Property, forAllShow, (===))
 
 -- | RegFile rs has no Show instance (the slot list is heterogeneous);
@@ -35,6 +36,7 @@
   describe "ExemplarSlots" (codecProps @ExemplarSlots)
   describe "MaybeSlots" (codecProps @MaybeSlots)
   nestedMaybeSpec
+  naturalSpec
 
 codecProps ::
   forall rs.
@@ -125,3 +127,29 @@
   case regFileFromJSON @NestedMaybeSlots (regFileToJSON rf) of
     Left message -> error ("nested Maybe decode failed: " <> message)
     Right (Core.RCons _ actual Core.RNil) -> actual `shouldBe` expected
+
+type NaturalSlots = '[ '("revision", Natural)]
+
+naturalSpec :: Spec
+naturalSpec = describe "Natural wire semantics" $ do
+  it "round-trips zero and a positive revision as JSON numbers" $ do
+    assertNaturalDecode 0
+    assertNaturalDecode 42
+
+  it "rejects negative and fractional JSON numbers" $ do
+    assertNaturalRejected (Aeson.object ["revision" Aeson..= (-1 :: Int)])
+    assertNaturalRejected (Aeson.object ["revision" Aeson..= (1.5 :: Double)])
+
+assertNaturalDecode :: Natural -> IO ()
+assertNaturalDecode expected =
+  case regFileFromJSON @NaturalSlots (regFileToJSON naturalRegister) of
+    Left message -> error ("Natural decode failed: " <> message)
+    Right (Core.RCons _ actual Core.RNil) -> actual `shouldBe` expected
+  where
+    naturalRegister = Core.RCons (Proxy @"revision") expected Core.RNil
+
+assertNaturalRejected :: Aeson.Value -> IO ()
+assertNaturalRejected value =
+  case regFileFromJSON @NaturalSlots value of
+    Left _ -> pure ()
+    Right _ -> expectationFailure "expected an invalid Natural JSON value to be rejected"
