diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Revision history for http-interchange
 
+## 0.3.2.1 -- 2024-02-07
+
+* List test suite file dependencies in `extra-source-files` so that Hackage
+  is able to run the test suite.
+* Update package metadata.
+
 ## 0.3.2.0 -- 2024-01-16
 
 * Add `Eq` and `Show` to all data types.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+# http-interchange
+
+Types, encode functions, and decode functions for HTTP requests and responses.
+This is similar in spirit to `http-types`, but it differs in these ways:
+
+* This library includes encoders and decoders for the parts of a
+  request/response leading up to the body (but not including the body).
+* This library does not have use types from `case-insensitive`.
+* This library defines data types instead of aliasing tuples. For example,
+  `Header` in `http-types` is defined as `type Header = (HeaderName, ByteString)`.
+  Here, it is defined as `data Header = Header {...}`.
+
+This library aims to provide just enough common functionality that someone
+could build an HTTP client on top of it. Things that are not goals:
+
+* This library does not use network sockets.
+
+Other notable design decisions:
+
+* This library tries to follow RFC 7230. Response header values are restricted
+  to the subset of visible ASCII characters (plus space and tab). This is
+  enforced by the decoders but not by the encoders.
diff --git a/golden/request/001.json b/golden/request/001.json
new file mode 100644
--- /dev/null
+++ b/golden/request/001.json
@@ -0,0 +1,9 @@
+{
+    "requestLine": {
+        "method": "PUT",
+        "path": "/foo/bar?baz=true",
+        "versionMajor": 1,
+        "versionMinor": 1
+    },
+    "headers": []
+}
diff --git a/golden/request/001.output b/golden/request/001.output
new file mode 100644
--- /dev/null
+++ b/golden/request/001.output
@@ -0,0 +1,2 @@
+PUT /foo/bar?baz=true HTTP/1.1
+
diff --git a/golden/request/002.json b/golden/request/002.json
new file mode 100644
--- /dev/null
+++ b/golden/request/002.json
@@ -0,0 +1,18 @@
+{
+    "requestLine": {
+        "method": "post",
+        "path": "/foo/bar?baz=true",
+        "versionMajor": 1,
+        "versionMinor": 1
+    },
+    "headers": [
+        {
+            "name": "Content-Type",
+            "value": "application/json"
+        },
+        {
+            "name": "Host",
+            "value": "example.com"
+        }
+    ]
+}
diff --git a/golden/request/002.output b/golden/request/002.output
new file mode 100644
--- /dev/null
+++ b/golden/request/002.output
@@ -0,0 +1,4 @@
+post /foo/bar?baz=true HTTP/1.1
+Content-Type: application/json
+Host: example.com
+
diff --git a/golden/response/001.input b/golden/response/001.input
new file mode 100644
--- /dev/null
+++ b/golden/response/001.input
@@ -0,0 +1,5 @@
+HTTP/1.1 200 OK
+Date: Tue, 18 Apr 2023 16:05:21 GMT
+Content-Type: text/html; charset=utf-8
+Transfer-Encoding: chunked
+
diff --git a/golden/response/001.output b/golden/response/001.output
new file mode 100644
--- /dev/null
+++ b/golden/response/001.output
@@ -0,0 +1,11 @@
+Response
+  { statusLine =
+      StatusLine { statusCode = 200 , statusReason = "OK" }
+  , headers =
+      [ Header
+          { name = "Date" , value = "Tue, 18 Apr 2023 16:05:21 GMT" }
+      , Header
+          { name = "Content-Type" , value = "text/html; charset=utf-8" }
+      , Header { name = "Transfer-Encoding" , value = "chunked" }
+      ]
+  }
diff --git a/golden/response/002.input b/golden/response/002.input
new file mode 100644
--- /dev/null
+++ b/golden/response/002.input
@@ -0,0 +1,4 @@
+HTTP/1.1 400 Bad Request
+Content-Type:    application/json   
+Content-Length:		100	
+
diff --git a/golden/response/002.output b/golden/response/002.output
new file mode 100644
--- /dev/null
+++ b/golden/response/002.output
@@ -0,0 +1,8 @@
+Response
+  { statusLine =
+      StatusLine { statusCode = 400 , statusReason = "Bad Request" }
+  , headers =
+      [ Header { name = "Content-Type" , value = "application/json" }
+      , Header { name = "Content-Length" , value = "100" }
+      ]
+  }
diff --git a/http-interchange.cabal b/http-interchange.cabal
--- a/http-interchange.cabal
+++ b/http-interchange.cabal
@@ -1,23 +1,40 @@
-cabal-version:   3.0
-name:            http-interchange
-version:         0.3.2.0
-license:         BSD-3-Clause
-license-file:    LICENSE
-author:          Andrew Martin
-maintainer:      andrew.thaddeus@gmail.com
-synopsis:        Types and serialization for HTTP
+cabal-version:      3.0
+name:               http-interchange
+version:            0.3.2.1
+license:            BSD-3-Clause
+license-file:       LICENSE
+author:             Andrew Martin
+maintainer:         amartin@layer3com.com
+homepage:           https://github.com/byteverse/http-interchange
+bug-reports:        https://github.com/byteverse/http-interchange/issues
+synopsis:           Types and serialization for HTTP
 description:
   Types and serialization for HTTP. This includes things like request
   line, status line, and headers. There is also a collection type
   for headers that supports fast, case-insensitive lookup.
 
-copyright:       2023 Andrew Martin
-category:        Data
-build-type:      Simple
-extra-doc-files: CHANGELOG.md
+copyright:          2023 Andrew Martin
+category:           Data
+build-type:         Simple
+extra-doc-files:
+  CHANGELOG.md
+  README.md
 
+extra-source-files:
+  golden/request/*.json
+  golden/request/*.output
+  golden/response/*.input
+  golden/response/*.output
+
+tested-with:        GHC ==9.4.8 || ==9.6.3 || ==9.8.1
+
+common build-settings
+  default-language: GHC2021
+  ghc-options:      -Wall -Wunused-packages
+
 library
-  ghc-options:      -Wall -O2
+  import:          build-settings
+  ghc-options:     -O2
   exposed-modules:
     Http.Bodied
     Http.Header
@@ -35,15 +52,13 @@
     , primitive   >=0.9.0
     , text        >=2.0
 
-  hs-source-dirs:   src
-  default-language: GHC2021
+  hs-source-dirs:  src
 
 test-suite test
-  ghc-options:      -Wall
-  default-language: GHC2021
-  type:             exitcode-stdio-1.0
-  hs-source-dirs:   test
-  main-is:          Main.hs
+  import:         build-settings
+  type:           exitcode-stdio-1.0
+  hs-source-dirs: test
+  main-is:        Main.hs
   build-depends:
     , aeson             >=2.1
     , base              >=4.16.3.0
@@ -55,3 +70,7 @@
     , primitive         >=0.9.0
     , tasty             >=1.4.3
     , tasty-golden      >=2.3.5
+
+source-repository head
+  type:     git
+  location: git://github.com/byteverse/http-interchange.git
