diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,17 @@
+## 0.8.0.3 (2018-01-11)
+
+- Use hpack.
+
+- Support for GHC 8.2.2.
+
+- Bump swagger2, optparse-applicative, doctest, QuickCheck, hspec-wai
+  upper bounds.
+
+- Try to make the Mellon/Web/ClientSpec.hs test a little less
+  time-sensitive.
+
+- Maintainer-related changes (better Nix support, Makefile, etc.).
+
 ## 0.8.0.2 (2017-09-04)
 
 - Fix .cabal file for now-removed Paw file.
diff --git a/mellon-web.cabal b/mellon-web.cabal
--- a/mellon-web.cabal
+++ b/mellon-web.cabal
@@ -1,254 +1,294 @@
-Name:                   mellon-web
-Version:                0.8.0.2
-Cabal-Version:          >= 1.18
-Build-Type:             Simple
-Author:                 Drew Hess <dhess-src@quixoftic.com>
-Maintainer:             Drew Hess <dhess-src@quixoftic.com>
-Homepage:               https://github.com/quixoftic/mellon/
-Bug-Reports:            https://github.com/quixoftic/mellon/issues/
-Stability:              experimental
-License:                BSD3
-License-File:           LICENSE
-Copyright:              Copyright (c) 2017, Quixoftic, LLC
-Tested-With:            GHC == 7.10.3, GHC == 8.0.1, GHC == 8.0.2
-Category:               Web
-Synopsis:               A REST web service for Mellon controllers
-Description:
-  The @mellon-web@ package wraps a @mellon-core@ controller in a REST
-  web service, making it possible to control physical access devices
-  from an HTTP client. The package includes both a WAI application
-  server, and native Haskell client bindings for the service.
-  .
-  Like the @mellon-core@ controller interface, the @mellon-web@ REST API
-  is quite simple. There are only 3 methods:
-  .
-  * @GET /time@ returns the system time on the server. This is made
-    available for diagnostic purposes, primarily to ensure the server
-    has an accurate clock.
-  .
-  * @GET /state@ returns the controller's current state (either @Locked@
-    or @Unlocked date@ where @date@ is the UTC time at which the
-    controller will automatically lock again).
-  .
-  * @PUT /state@ sets the controller's current state. Use this method to
-    lock and unlock the controller.
-  .
-  See the included <API.md API.md> document for detailed documentation
-  on the REST service.
-  .
-  Note that the @mellon-web@ server does not provide an authentication
-  mechanism! You should proxy it behind a secure, authenticating HTTPS
-  server such as Nginx.
-Extra-Doc-Files:        README.md
-                      , swagger.json
-Extra-Source-Files:     changelog.md
-                      , examples/*.hs
+-- This file has been generated from package.yaml by hpack version 0.21.2.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: 6f888996b5b3eb2e33aad7453edcf072a41751dc7e2fa46cfed52530a1a930d1
 
--- Build doctests
-Flag test-doctests
-  Default: True
-  Manual: True
+name:                   mellon-web
+version:                0.8.0.3
+synopsis:               A REST web service for Mellon controllers
+description:            The @mellon-web@ package wraps a @mellon-core@ controller in a REST
+                        web service, making it possible to control physical access devices
+                        from an HTTP client. The package includes both a WAI application
+                        server, and native Haskell client bindings for the service.
+                        .
+                        Like the @mellon-core@ controller interface, the @mellon-web@ REST API
+                        is quite simple. There are only 3 methods:
+                        .
+                        * @GET /time@ returns the system time on the server. This is made
+                        available for diagnostic purposes, primarily to ensure the server
+                        has an accurate clock.
+                        .
+                        * @GET /state@ returns the controller's current state (either @Locked@
+                        or @Unlocked date@ where @date@ is the UTC time at which the
+                        controller will automatically lock again).
+                        .
+                        * @PUT /state@ sets the controller's current state. Use this method to
+                        lock and unlock the controller.
+                        .
+                        See the included <API.md API.md> document for detailed documentation
+                        on the REST service.
+                        .
+                        Note that the @mellon-web@ server does not provide an authentication
+                        mechanism! You should proxy it behind a secure, authenticating HTTPS
+                        server such as Nginx.
+category:               Web
+stability:              experimental
+homepage:               https://github.com/quixoftic/mellon#readme
+bug-reports:            https://github.com/quixoftic/mellon/issues
+author:                 Drew Hess <dhess-src@quixoftic.com>
+maintainer:             Drew Hess <dhess-src@quixoftic.com>
+copyright:              Copyright (c) 2017, Quixoftic, LLC
+license:                BSD3
+license-file:           LICENSE
+tested-with:            GHC==7.10.3 GHC==8.0.1 GHC==8.0.2 GHC==8.2.1 GHC==8.2.2
+build-type:             Simple
+cabal-version:          >= 1.10
 
--- Build hlint test
-Flag test-hlint
-  Default: True
-  Manual: True
+extra-source-files:
+    changelog.md
+    README.md
+    swagger.json
 
--- Build the mock server example
-Flag mock-example
-  Default: True
-  Manual: True
+source-repository head
+  type: git
+  location: https://github.com/quixoftic/mellon
 
--- Build the GPIO server example
-Flag gpio-example
-  Default: True
-  Manual: True
+flag client-unlock-example
+  description: Build the unlock client example
+  manual: True
+  default: True
 
--- Build the unlock client example
-Flag client-unlock-example
-  Default: True
-  Manual: True
+flag gpio-example
+  description: Build the GPIO server example
+  manual: True
+  default: True
 
-Library
-  Default-Language:     Haskell2010
-  HS-Source-Dirs:       src
-  GHC-Options:          -Wall -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
-  If impl(ghc > 8)
-    GHC-Options:        -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-redundant-constraints
-  Exposed-Modules:      Mellon.Web.Client
-                      , Mellon.Web.Server
-                      , Mellon.Web.Server.API
-                      , Mellon.Web.Server.SwaggerAPI
-  Other-Extensions:     DataKinds
-                      , DeriveGeneric
-                      , MultiParamTypeClasses
-                      , OverloadedStrings
-                      , TypeOperators
-  Build-Depends:        base               >= 4.8   && < 5
-                      , aeson              >= 0.11  && < 1.3
-                      , aeson-pretty       == 0.8.*
-                      , bytestring         == 0.10.*
-                      , http-client        >= 0.4   && < 0.6
-                      , http-types         == 0.9.*
-                      , lens               >= 4     && < 5
-                      , lucid              == 2.9.*
-                      , mellon-core        == 0.8.*
-                      , servant            == 0.11.*
-                      , servant-client     == 0.11.*
-                      , servant-docs       >= 0.10  && < 0.12
-                      , servant-lucid      == 0.7.*
-                      , servant-server     == 0.11.*
-                      , servant-swagger    == 1.1.*
-                      , servant-swagger-ui == 0.2.*
-                      , swagger2           == 2.1.*
-                      , text               == 1.2.*
-                      , time               >= 1.5   && < 2
-                      , transformers       >= 0.4.2 && < 0.6
-                      , wai                == 3.2.*
-                      , warp               == 3.2.*
+flag mock-example
+  description: Build the mock server example
+  manual: True
+  default: True
 
-Executable mock-mellon-server
-  Main-Is:              MockServer.hs
-  Default-Language:     Haskell2010
-  HS-Source-Dirs:       examples
-  GHC-Options:          -Wall -threaded -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
-  If impl(ghc > 8)
-    GHC-Options:        -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-redundant-constraints
-  If !flag(mock-example)
-    Buildable:         False
-  Else                        
-    Build-Depends:      base
-                      , mellon-core
-                      , mellon-web
-                      , warp
+flag test-doctests
+  description: Build doctests
+  manual: True
+  default: True
 
-Executable gpio-mellon-server
-  Main-Is:              GpioServer.hs
-  Default-Language:     Haskell2010
-  HS-Source-Dirs:       examples
-  GHC-Options:          -Wall -threaded -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
-  If impl(ghc > 8)
-    GHC-Options:        -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-redundant-constraints
-  Other-Extensions:     OverloadedStrings
-  If !flag(gpio-example)
-    Buildable:         False
-  Else                        
-    Build-Depends:      base
-                      , exceptions           >= 0.8.0  && < 1
-                      , hpio                 >= 0.8    && < 1
-                      , mellon-core
-                      , mellon-gpio          == 0.8.*
-                      , mellon-web
-                      , mtl
-                      , network              == 2.6.*
-                      , optparse-applicative >= 0.11.0 && < 0.14
-                      , time
-                      , transformers
-                      , warp
+flag test-hlint
+  description: Build hlint test
+  manual: True
+  default: True
 
-Executable mellon-schedule-unlock
-  Main-Is:              ScheduleUnlock.hs
-  Default-Language:     Haskell2010
-  HS-Source-Dirs:       examples
-  GHC-Options:          -Wall -threaded -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
-  If impl(ghc > 8)
-    GHC-Options:        -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-redundant-constraints
-  Other-Extensions:     LambdaCase
-                      , OverloadedStrings
-  If !flag(client-unlock-example)
-    Buildable:         False
-  Else                        
-    Build-Depends:      base
-                      , bytestring
-                      , exceptions
-                      , http-client
-                      , http-client-tls
-                      , http-types
-                      , mellon-core
-                      , mellon-web
-                      , mtl
-                      , network
-                      , optparse-applicative
-                      , servant-client
-                      , time
-                      , transformers
-                        
-Test-Suite hlint
-  Type:                 exitcode-stdio-1.0
-  Default-Language:     Haskell2010
-  Hs-Source-Dirs:       test
-  Ghc-Options:          -w -threaded -rtsopts -with-rtsopts=-N
-  Main-Is:              hlint.hs
-  If !flag(test-hlint)
-    Buildable:          False
-  Else
-    Build-Depends:      base
-                      , hlint >= 1.9 && < 2.1
+library
+  hs-source-dirs:
+      src
+  other-extensions: DataKinds DeriveDataTypeable DeriveGeneric MultiParamTypeClasses OverloadedStrings OverloadedLists ScopedTypeVariables TypeOperators
+  build-depends:
+      aeson >=0.11 && <1.3
+    , aeson-pretty ==0.8.*
+    , base >=4.8 && <5
+    , bytestring ==0.10.*
+    , http-client >=0.4 && <0.6
+    , http-types ==0.9.*
+    , lens >=4 && <5
+    , lucid ==2.9.*
+    , mellon-core ==0.8.*
+    , servant ==0.11.*
+    , servant-client ==0.11.*
+    , servant-docs >=0.10 && <0.12
+    , servant-lucid ==0.7.*
+    , servant-server ==0.11.*
+    , servant-swagger ==1.1.*
+    , servant-swagger-ui ==0.2.*
+    , swagger2 >=2.1 && <2.3
+    , text ==1.2.*
+    , time >=1.5 && <2
+    , transformers >=0.4.2 && <0.6
+    , wai ==3.2.*
+    , warp ==3.2.*
+  if impl(ghc >= 8.0)
+    ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates
+  else
+    ghc-options: -Wall -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
+  if impl(ghc >= 8.0)
+    ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances
+  else
+    build-depends:
+        fail ==4.9.*
+      , semigroups ==0.18.*
+  exposed-modules:
+      Mellon.Web.Client
+      Mellon.Web.Server
+      Mellon.Web.Server.API
+      Mellon.Web.Server.SwaggerAPI
+  other-modules:
+      Paths_mellon_web
+  default-language: Haskell2010
 
-Test-Suite doctest
-  Type:                 exitcode-stdio-1.0
-  Default-Language:     Haskell2010
-  Hs-Source-Dirs:       test
-  Ghc-Options:          -Wall -threaded
-  If impl(ghc > 8)
-    GHC-Options:        -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-redundant-constraints -fno-warn-redundant-constraints
-  Main-Is:              doctest.hs
-  If !flag(test-doctests)
-    Buildable: False
-  Else
-    Build-Depends:      base
-                      , doctest >= 0.10.1 && < 1
+executable gpio-mellon-server
+  main-is: GpioServer.hs
+  hs-source-dirs:
+      examples
+  other-extensions: OverloadedStrings
+  ghc-options: -threaded -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
+  if impl(ghc >= 8.0)
+    ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates
+  else
+    ghc-options: -Wall -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
+  if impl(ghc >= 8.0)
+    ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-redundant-constraints
+  if !(flag(gpio-example))
+    buildable: False
+  else
+    build-depends:
+        base
+      , exceptions >=0.8.0 && <1
+      , hpio >=0.8 && <1
+      , mellon-core
+      , mellon-gpio ==0.8.*
+      , mellon-web
+      , mtl
+      , network ==2.6.*
+      , optparse-applicative >=0.11.0 && <0.15
+      , time
+      , transformers
+      , warp
+  default-language: Haskell2010
 
-Test-Suite spec
-  Type:                 exitcode-stdio-1.0
-  Default-Language:     Haskell2010
-  Hs-Source-Dirs:       src
-                      , test
-  Ghc-Options:          -w -threaded -rtsopts -with-rtsopts=-N
-  Main-Is:              Main.hs
-  Other-Extensions:     ScopedTypeVariables
-  Build-Depends:        base
-                      , QuickCheck
-                      , quickcheck-instances
-                      , aeson
-                      , aeson-pretty
-                      , bytestring
-                      , hspec          >= 2.2   && < 2.5
-                      , hspec-wai      >= 0.6.6 && < 0.9
-                      , http-client
-                      , http-types
-                      , lens
-                      , lucid
-                      , mellon-core
-                      , network
-                      , servant
-                      , servant-client
-                      , servant-docs
-                      , servant-lucid
-                      , servant-server
-                      , servant-swagger
-                      , servant-swagger-ui
-                      , swagger2
-                      , text
-                      , time
-                      , transformers
-                      , wai
-                      , wai-extra      == 3.0.*
-                      , warp
-  Other-Modules:        Mellon.Web.Client
-                      , Mellon.Web.Server
-                      , Mellon.Web.Server.API
-                      , Mellon.Web.Server.SwaggerAPI
-                      , Spec
-                      , Mellon.Web.ClientSpec
-                      , Mellon.Web.ServerSpec
-                      , Mellon.Web.SwaggerAPISpec
+executable mellon-schedule-unlock
+  main-is: ScheduleUnlock.hs
+  hs-source-dirs:
+      examples
+  other-extensions: LambdaCase OverloadedStrings
+  ghc-options: -threaded -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
+  if impl(ghc >= 8.0)
+    ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates
+  else
+    ghc-options: -Wall -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
+  if impl(ghc >= 8.0)
+    ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-redundant-constraints
+  if !(flag(client-unlock-example))
+    buildable: False
+  else
+    build-depends:
+        base
+      , bytestring
+      , exceptions
+      , http-client
+      , http-client-tls
+      , http-types
+      , mellon-core
+      , mellon-web
+      , mtl
+      , network
+      , optparse-applicative
+      , servant-client
+      , time
+      , transformers
+  default-language: Haskell2010
 
-Source-Repository head
-  Type:                 git
-  Location:             git://github.com/quixoftic/mellon.git
+executable mock-mellon-server
+  main-is: MockServer.hs
+  hs-source-dirs:
+      examples
+  ghc-options: -threaded -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
+  if impl(ghc >= 8.0)
+    ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates
+  else
+    ghc-options: -Wall -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
+  if impl(ghc >= 8.0)
+    ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances -fno-warn-redundant-constraints
+  if !(flag(mock-example))
+    buildable: False
+  else
+    build-depends:
+        base
+      , mellon-core
+      , mellon-web
+      , warp
+  default-language: Haskell2010
 
-Source-Repository this
-  Type:                 git
-  Location:             git://github.com/quixoftic/mellon.git
-  Tag:                  v0.8.0.2
+test-suite doctest
+  type: exitcode-stdio-1.0
+  main-is: doctest.hs
+  hs-source-dirs:
+      test
+  ghc-options: -threaded
+  if impl(ghc >= 8.0)
+    ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates
+  else
+    ghc-options: -Wall -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
+  if !(flag(test-doctests))
+    buildable: False
+  else
+    build-depends:
+        base
+      , doctest >=0.11 && <0.14
+  default-language: Haskell2010
+
+test-suite hlint
+  type: exitcode-stdio-1.0
+  main-is: hlint.hs
+  hs-source-dirs:
+      test
+  ghc-options: -w -threaded -rtsopts -with-rtsopts=-N
+  if impl(ghc >= 8.0)
+    ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates
+  else
+    ghc-options: -Wall -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
+  if !(flag(test-hlint))
+    buildable: False
+  else
+    build-depends:
+        base
+      , hlint >=1.9 && <2.1
+  default-language: Haskell2010
+
+test-suite spec
+  type: exitcode-stdio-1.0
+  main-is: Main.hs
+  hs-source-dirs:
+      test
+  other-extensions: OverloadedStrings ScopedTypeVariables
+  ghc-options: -w -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      QuickCheck >=2.8 && <2.11
+    , aeson
+    , aeson-pretty
+    , base
+    , bytestring
+    , hspec >=2.2 && <2.5
+    , hspec-wai >=0.6.6 && <0.10
+    , http-client
+    , http-types
+    , lens
+    , lucid
+    , mellon-core
+    , mellon-web
+    , network
+    , quickcheck-instances ==0.3.*
+    , servant
+    , servant-client
+    , servant-docs
+    , servant-lucid
+    , servant-server
+    , servant-swagger
+    , servant-swagger-ui
+    , swagger2
+    , text
+    , time
+    , transformers
+    , wai
+    , wai-extra ==3.0.*
+    , warp
+  if impl(ghc >= 8.0)
+    ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates
+  else
+    ghc-options: -Wall -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates
+  other-modules:
+      Mellon.Web.ClientSpec
+      Mellon.Web.ServerSpec
+      Mellon.Web.SwaggerAPISpec
+      Spec
+      Paths_mellon_web
+  default-language: Haskell2010
diff --git a/test/Mellon/Web/ClientSpec.hs b/test/Mellon/Web/ClientSpec.hs
--- a/test/Mellon/Web/ClientSpec.hs
+++ b/test/Mellon/Web/ClientSpec.hs
@@ -45,7 +45,7 @@
        do it "returns the server time" $ \(_, clientEnv) ->
             do now <- getCurrentTime
                Right (Time serverTime) <- runClientM getTime clientEnv
-               let delta = 1.0 :: NominalDiffTime
+               let delta = 2.0 :: NominalDiffTime
                ((serverTime `diffUTCTime` now) < delta) `shouldBe` True
 
      describe "getState" $
