diff --git a/.travis.yml b/.travis.yml
new file mode 100644
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,152 @@
+sudo: true
+language: haskell
+os: linux
+
+git:
+  depth: 5
+
+cache:
+  directories:
+  - "$HOME/.ghc"
+  - "$HOME/.cabal"
+  - "$HOME/.stack"
+  - "$TRAVIS_BUILD_DIR/.stack-work"
+
+env:
+  global:
+    - PATH="$HOME/.cabal/bin:$HOME/.local/bin:$PATH"
+
+matrix:
+  include:
+#  - ghc: 8.2.2
+#    cabal: "2.4"
+#  - ghc: 8.6.5
+#    cabal: "2.4"
+
+  - env: BUILD=cabal
+    ghc: 8.2.2
+    cabal: "2.4"
+
+  #allow_failures:
+  #
+  #- ghc: 8.2.2
+  #  env: STACK_YAML="$TRAVIS_BUILD_DIR/stack-8.2.2.yaml"
+
+  # The Stack builds. We can pass in arbitrary Stack arguments via the ARGS
+  # variable, such as using --stack-yaml to point to a different file.
+  #  - env: BUILD=stack ARGS=""
+  #    compiler: ": #stack default"
+  #    addons: {apt: {packages: [libgmp-dev]}}
+
+  - env: BUILD=stack ARGS="--resolver lts-7 --stack-yaml stack-lts-13.yaml"
+    compiler: ": #stack 8.0.1"
+    addons: {apt: {packages: [libgmp-dev]}}
+
+  - env: BUILD=stack ARGS="--resolver lts-14 --stack-yaml stack-lts-13.yaml"
+    compiler: ": #stack 8.6.5"
+    addons: {apt: {packages: [libgmp-dev]}}
+
+before_install:
+# Using compiler above sets CC to an invalid value, so unset it
+- unset CC
+- export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$HOME/.local/bin:/opt/alex/$ALEXVER/bin:/opt/happy/$HAPPYVER/bin:$HOME/.cabal/bin:$PATH
+- mkdir -p ~/.local/bin
+- |
+  set -ex
+  if [ `uname` = "Darwin" ]
+  then
+    travis_retry curl --insecure -L https://get.haskellstack.org/stable/osx-x86_64.tar.gz | tar xz --strip-components=1 --include '*/stack' -C ~/.local/bin
+  else
+    # recent versions of stack fail to work with lts <= 7
+    if [[ $ARGS == *"lts-7"* ]]; then
+      url=https://github.com/commercialhaskell/stack/releases/download/v1.9.3/stack-1.9.3-linux-x86_64.tar.gz
+    else
+      url=https://get.haskellstack.org/stable/linux-x86_64.tar.gz
+    fi
+    travis_retry curl -L $url | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
+  fi
+  stack --version
+
+  # Use the more reliable S3 mirror of Hackage
+  mkdir -p $HOME/.cabal
+  echo 'remote-repo: hackage.haskell.org:http://hackage.fpcomplete.com/' > $HOME/.cabal/config
+  echo 'remote-repo-cache: $HOME/.cabal/packages' >> $HOME/.cabal/config
+  set +ex
+
+install:
+- echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
+  # HLint check
+- curl -sSL https://raw.github.com/ndmitchell/neil/master/misc/travis.sh | sh -s -- hlint src
+- |
+  set -ex
+  case "$BUILD" in
+    stack)
+      # Add in extra-deps for older snapshots, as necessary
+      #
+      # This is disabled by default, as relying on the solver like this can
+      # make builds unreliable. Instead, if you have this situation, it's
+      # recommended that you maintain multiple stack-lts-X.yaml files.
+
+      #stack --no-terminal --install-ghc $ARGS test --bench --dry-run || ( \
+      #  stack --no-terminal $ARGS build cabal-install && \
+      #  stack --no-terminal $ARGS solver --update-config)
+
+      # stack.yaml
+
+      # Build the dependencies
+      stack --no-terminal --install-ghc $ARGS test --bench --only-dependencies
+      ;;
+    cabal)
+      cabal --version
+      travis_retry cabal update
+
+      # Get the list of packages from the stack.yaml file. Note that
+      # this will also implicitly run hpack as necessary to generate
+      # the .cabal files needed by cabal-install.
+      PACKAGES=$(stack --install-ghc query locals | grep '^ *path' | sed 's@^ *path:@@')
+
+      # v1-install fails to correctly install happy as required build tool for
+      #  haskell-src-exts
+      cabal install --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS happy
+      cabal install --only-dependencies --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES
+      ;;
+  esac
+  set +ex
+
+script:
+- |
+  set -ex
+  case "$BUILD" in
+    stack)
+      stack --no-terminal $ARGS test --bench --no-run-benchmarks --haddock --no-haddock-deps
+      ;;
+    cabal)
+      cabal install --enable-tests --enable-benchmarks --force-reinstalls --ghc-options=-O0 --reorder-goals --max-backjumps=-1 $CABALARGS $PACKAGES
+
+      ORIGDIR=$(pwd)
+      for dir in $PACKAGES
+      do
+        cd $dir
+        cabal check || [ "$CABALVER" == "1.16" ]
+        cabal sdist
+        PKGVER=$(cabal info . | awk '{print $2;exit}')
+        SRC_TGZ=$PKGVER.tar.gz
+        cd dist
+        tar zxfv "$SRC_TGZ"
+        cd "$PKGVER"
+        cabal configure --enable-tests --ghc-options -O0
+        cabal build
+        if [ "$CABALVER" = "1.16" ] || [ "$CABALVER" = "1.18" ]; then
+          cabal test
+        else
+          cabal test --show-details=streaming --log=/dev/stdout
+        fi
+        cd $ORIGDIR
+      done
+      ;;
+  esac
+  set +ex
+
+
+notifications:
+  email: false
diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -2,9 +2,16 @@
 
 ## Unreleased changes
 
-## 0.2.0.0 changes
+## 0.2.0.1
 
-- Bug fixes
+- Bug fixes (#2, #7)
+- Bounds tightened - requires base >= 4.9
+
+## 0.2.0.0
+
+(Deprecated version, use 0.2.0.1)
+
+- Bug fixes (#1, #3, #4)
 - Instances of FromJSON and ToJSON have changed - field names now
   don't repeat the entity name (i.e., `Student` has field `name`,
   rather than `studentName`).
diff --git a/config/exigo.persistentmodels b/config/exigo.persistentmodels
--- a/config/exigo.persistentmodels
+++ b/config/exigo.persistentmodels
@@ -1,25 +1,30 @@
 
+-- | A student
 Student json
-    studNo              Text
+    studNo              Text    -- | unique 'Student' id
     Primary             studNo
-    name                Text
+    name                Text    -- | student name
     deriving Show
     deriving Eq
     deriving Generic
 
+-- | Submission made by a student
+-- for an assessment
 Submission json
-    student             StudentId
+    student             StudentId  -- | the submitting 'Student'
     Primary             student
-    studentLogin        Text
-    path                FilePath
+    studentLogin        Text       -- | the logon used
+    path                FilePath   -- | path to the submission
     deriving Show
     deriving Eq
     deriving Generic
 
+-- | Late penalty to be applied to
+-- a student's submission
 LatePenalty json
-    student             StudentId
+    student             StudentId   -- | the submitting 'Student'
     Primary             student
-    daysLate            Int
+    daysLate            Int         -- | no. of days late
     deriving Show
     deriving Eq
     deriving Generic
diff --git a/exigo-schema.cabal b/exigo-schema.cabal
--- a/exigo-schema.cabal
+++ b/exigo-schema.cabal
@@ -1,7 +1,7 @@
 cabal-version: 1.12
 
 name:           exigo-schema
-version:        0.2.0.0
+version:        0.2.0.1
 category:       Database
 synopsis:       database schema for exigo marking/assessment tools
 description:    Please see the README on GitHub at <https://github.com/phlummox/exigo-schema#readme>
@@ -16,8 +16,10 @@
 extra-source-files:
     README.md
     ChangeLog.md
+    stack-lts-13.yaml
     config/exigo.persistentmodels
--- builds & tests successfully as far back as stack lts-7
+    .travis.yml
+-- builds & tests successfully as far back as stack lts-7/ghc-8.0
 tested-with:         GHC == 8.0.1
                      GHC == 8.2.2
                      GHC == 8.6.5
@@ -35,7 +37,7 @@
   hs-source-dirs:
       src
   build-depends:
-      base >=4.0 && <5
+      base >=4.9 && <5
     , aeson
     , binary
     , bytestring
@@ -48,14 +50,15 @@
   ghc-options:
       -Wall
       -fwarn-tabs
-      -Wredundant-constraints
-      -Wno-type-defaults
-      -Wcompat
-      -Wextra
-      -Widentities
-      -Wincomplete-record-updates
-      -Wincomplete-uni-patterns
-      -Wno-name-shadowing
+  if impl(ghc >= 8.0)
+    ghc-options:        -Wredundant-constraints
+                        -Wno-type-defaults
+                        -Wcompat
+                        -Widentities
+                        -Wincomplete-record-updates
+                        -Wincomplete-uni-patterns
+                        -Wno-name-shadowing
+                        -Wextra
   if impl(ghc >= 8.2)
     ghc-options:        -fhide-source-paths
   if impl(ghc >= 8.4)
@@ -70,21 +73,40 @@
   type:                exitcode-stdio-1.0
   hs-source-dirs:      test
   main-is:             Spec.hs
-  build-depends:       base
-                     , exigo-schema
-                     , directory
-                     , exceptions
-                     , hint
-                     , hspec
-                     , hspec-core
-                     , interpolate
-                     , persistent
-                     , persistent-template
-                     -- , process
-                     -- ^^ used for debugging
-                     , quickcheck-text
-                     , QuickCheck
-                     , temporary
-                     , template-haskell
+  build-depends:      base
+                    , exigo-schema
+                    , aeson
+                    , bytestring
+                    , directory
+                    , exceptions
+                    , hint
+                    , hspec
+                    , hspec-core
+                    , interpolate
+                    , persistent
+                    , persistent-template
+                    -- , process
+                    -- ^^ used for debugging
+                    , quickcheck-text
+                    , QuickCheck
+                    , temporary
+                    , template-haskell
+                    , text
   ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+  if impl(ghc >= 8.0)
+    ghc-options:        -Wredundant-constraints
+                        -Wno-type-defaults
+                        -Wcompat
+                        -Widentities
+                        -Wincomplete-record-updates
+                        -Wincomplete-uni-patterns
+                        -Wno-name-shadowing
+                        -Wextra
+  if impl(ghc >= 8.2)
+    ghc-options:        -fhide-source-paths
+  if impl(ghc >= 8.4)
+    ghc-options:        -Wmissing-export-lists
+                        -Wpartial-fields
+  if impl(ghc >= 8.8)
+    ghc-options:        -Wmissing-deriving-strategies
   default-language:    Haskell2010
diff --git a/src/Exigo/Persistent/Schema.hs b/src/Exigo/Persistent/Schema.hs
--- a/src/Exigo/Persistent/Schema.hs
+++ b/src/Exigo/Persistent/Schema.hs
@@ -38,24 +38,31 @@
 
 module Exigo.Persistent.Schema
   (
+    -- * Database entities
     -- | Represents a student
-    Student
-    -- | A student ID
+    Student(..)
   , StudentId
-    -- | Submission made by a 'Student'.
-  , Submission
-    -- | 'Submission' ID
+    -- | Submission made by a 'Student'
+  , Submission(..)
   , SubmissionId
     -- | A late penalty applied
-  , LatePenalty
-    -- | 'LatePenalty' ID
+  , LatePenalty(..)
   , LatePenaltyId
+    -- * Runtime access to schema
     -- | Saved entities from this schema
   , savedMainModel
+    -- * Keys for entities
+  , Key(StudentKey,SubmissionKey
+        ,LatePenaltyKey
+        ,unStudentKey,unLatePenaltyKey
+        ,unSubmissionKey)
+  , StudentKey
+  , SubmissionKey
+  , LatePenaltyKey
   )
   where
 
-import          Data.Aeson
+import          Data.Aeson ()
 import          Data.Binary
 import          Data.Text               (Text)
 import          Database.Persist.TH     (
@@ -83,4 +90,7 @@
 instance Binary   Submission    where
 instance Binary   LatePenalty   where
 
+type StudentKey = Key Student
+type LatePenaltyKey = Key LatePenalty
+type SubmissionKey = Key Submission
 
diff --git a/stack-lts-13.yaml b/stack-lts-13.yaml
new file mode 100644
--- /dev/null
+++ b/stack-lts-13.yaml
@@ -0,0 +1,8 @@
+resolver: lts-13.30
+
+packages:
+- .
+
+extra-deps:
+- string-interpolate-0.2.0.1@sha256:1728854c36c1924aaa35173f0d0f43ebb39b3df6401800aa4b842764d8f4014b,2532
+
