diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Revision history for `canadian-income-tax`
 
+## 2024.0.0.1
+
+* Bumped the upper `deep-transformations` dependency bounds
+
 ## 2024.0
 
 * Breaking changes to the library:
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -10,10 +10,7 @@
 import Codec.Archive.Tar qualified as Tar
 import Codec.Archive.Tar.Entry (fileEntry, toTarPath)
 import Control.Applicative ((<**>), many, optional)
-import Control.Arrow ((&&&))
 import Control.Monad (unless, void, when)
-import Data.Bifunctor (bimap)
-import Data.ByteString (ByteString)
 import Data.ByteString qualified as ByteString
 import Data.ByteString.Lazy qualified as Lazy
 import Data.ByteString.Lazy qualified as ByteString.Lazy
@@ -23,18 +20,13 @@
 import Data.Functor.Compose (Compose(Compose, getCompose))
 import Data.List qualified as List
 import Data.Map.Lazy qualified as Map
-import Data.Set qualified as Set
 import Data.Maybe (catMaybes)
-import Data.Semigroup (Any (Any))
 import Data.Semigroup.Cancellative (isPrefixOf, isSuffixOf)
-import Data.Text (Text)
 import Data.Text qualified as Text
 import Options.Applicative (Parser, ReadM, long, metavar, short)
 import Options.Applicative qualified as OptsAp
-import Rank2 qualified
 import System.Directory (createDirectoryIfMissing, doesDirectoryExist, doesFileExist)
 import System.FilePath (combine, replaceDirectory, takeFileName)
-import System.IO (hPutStrLn, stderr)
 import Text.FDF (FDF, parse, serialize)
 
 import Paths_canadian_income_tax (getDataDir)
@@ -42,8 +34,6 @@
 import Tax.Canada.Federal (loadInputForms)
 import Tax.Canada.FormKey (FormKey)
 import Tax.Canada.FormKey qualified as FormKey
-import Tax.FDF (FDFs)
-import Tax.FDF qualified as FDF
 import Tax.PDFtk (fdf2pdf, pdf2fdf)
 
 main :: IO ()
@@ -72,7 +62,7 @@
    Options
    <$> OptsAp.argument readProvince (metavar "<two-letter province code>")
    <*> OptsAp.strOption (long "t1" <> metavar "<input T1 form file>")
-   <*> many (OptsAp.strOption (long "t4" <> metavar "<input t4 form file>"))
+   <*> many (OptsAp.strOption (long "t4" <> metavar "<input t4 slip file>"))
    <*> optional (OptsAp.strOption (long "428" <> metavar "<input 428 form file>"))
    <*> optional (OptsAp.strOption (long "479" <> metavar "<input 479 form file>"))
    <*> optional (OptsAp.strOption (long "s6" <> metavar "<input Schedule 6 form file>"))
@@ -81,8 +71,8 @@
    <*> optional (OptsAp.strOption (long "s9" <> metavar "<input Schedule 9 form file>"))
    <*> optional (OptsAp.strOption (long "s11" <> metavar "<input Schedule 11 form file>"))
    <*> OptsAp.strOption (short 'o' <> long "output" <> OptsAp.value "-" <> metavar "<output file or directory>")
-   <*> OptsAp.switch (long "only-given")
-   <*> OptsAp.switch (long "keep-irrelevant")
+   <*> OptsAp.switch (long "only-given" <> OptsAp.help "Complete only the forms given on the command line")
+   <*> OptsAp.switch (long "keep-irrelevant" <> OptsAp.help "Complete the forms that have no effect on T1")
    <*> OptsAp.switch (short 'v' <> long "verbose")
    <**> OptsAp.helper
 
@@ -110,7 +100,7 @@
 process :: Options -> IO ()
 process Options{province, t1InputPath, t4InputPaths, p428InputPath, p479InputPath,
                 schedule6InputPath, schedule7InputPath, schedule8InputPath, schedule9InputPath, schedule11InputPath,
-                outputPath, onlyGivenForms, keepIrrelevantForms, verbose} = do
+                outputPath, onlyGivenForms, keepIrrelevantForms} = do
    dataDir <- getDataDir
    let inputFiles :: [(FormKey, FilePath)]
        inputFiles = List.sortOn fst $
@@ -143,7 +133,6 @@
                    then ByteString.writeFile (replaceDirectory inputPath outputPath) content'
                    else ByteString.writeFile outputPath content'
        fdfs = getCompose <$> traverse (parse . Lazy.toStrict . snd) (Compose inputs) :: Either String [(FormKey, FDF)]
-       bytesMap = Lazy.toStrict . snd <$> Map.fromAscList inputs
    case do (inputFDFs, ioFDFs) <- List.partition ((FormKey.T4 ==) . fst) <$> fdfs
            inputForms <- loadInputForms inputFDFs
            let complete = if keepIrrelevantForms then completeForms else completeRelevantForms
diff --git a/canadian-income-tax.cabal b/canadian-income-tax.cabal
--- a/canadian-income-tax.cabal
+++ b/canadian-income-tax.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.4
 name:               canadian-income-tax
-version:            2024.0
+version:            2024.0.0.1
 
 synopsis: Canadian income tax calculation
 
@@ -25,7 +25,12 @@
   type:     git
   location: https://github.com/blamario/canadian-income-tax
 
+common stanzas
+    default-language: Haskell2010
+    GHC-options: -Wall
+
 library
+    import: stanzas
     exposed-modules:
         Tax.Canada
         Tax.Canada.Federal
@@ -89,13 +94,15 @@
     -- other-extensions:
     build-depends:    base == 4.*, text >= 1.0 && < 2.2, bytestring >= 0.10.4 && < 1,
                       time == 1.*, containers >= 0.5 && < 0.9, bitwise-enum ^>= 1.0.0, bifunctors ^>= 5.6,
-                      monoid-subclasses == 1.*, rank2classes ^>= 1.5.3, deep-transformations ^>= 0.2.2 || ^>= 0.3,
+                      monoid-subclasses == 1.*, rank2classes ^>= 1.5.3,
+                      deep-transformations ^>= 0.2.2 || ^>= 0.3 || ^>= 0.4,
                       ca-province-codes == 1.0.*, forms-data-format ^>= 0.2, typed-process >= 0.1 && ^>=0.2,
                       template-haskell == 2.*
     hs-source-dirs:   src
-    default-language: Haskell2010
+    GHC-options: -Wno-ambiguous-fields -Wno-simplifiable-class-constraints
 
 executable complete-canadian-taxes
+    import: stanzas
     main-is:          Main.hs
 
     -- Modules included in this executable, other than Main.
@@ -113,9 +120,9 @@
     other-modules:    Paths_canadian_income_tax
     autogen-modules:  Paths_canadian_income_tax
     hs-source-dirs:   app
-    default-language: Haskell2010
 
 executable serve-canadian-taxes
+    import: stanzas
     main-is:          Main.hs
     other-modules:    Paths_canadian_income_tax
     autogen-modules:  Paths_canadian_income_tax
@@ -127,16 +134,17 @@
     -- other-extensions:
     build-depends:
         base == 4.*, text, bytestring, containers, monoid-subclasses,
+        fast-logger ^>= 3.0 ||  ^>= 3.1 || ^>= 3.2.1,
         filepath >= 1.3 && < 1.6, unix >= 2.6 && < 2.9, directory >= 1.2 && < 1.4,
         time >= 1.9.1 && < 1.15, zip-archive ^>= 0.4, aeson ^>= 2.2,
         http-types ^>= 0.12, scotty ^>= 0.22, wai-extra ^>= 3.1.10, wai-middleware-static ^>= 0.9.1,
         forms-data-format, canadian-income-tax
 
     hs-source-dirs:   web
-    default-language: Haskell2010
     ghc-options: -threaded
 
 test-suite             properties
+    import: stanzas
     type:                exitcode-stdio-1.0
     build-depends:       base >= 4.7 && < 5, bytestring,
                          directory ^>= 1.3, filepath,
@@ -149,9 +157,10 @@
     other-modules:       Test.Transformations
                          Paths_canadian_income_tax
     autogen-modules:     Paths_canadian_income_tax
-    default-language:    Haskell2010
+    GHC-options:         -Wno-incomplete-uni-patterns
 
 test-suite             regression
+    import: stanzas
     type:                exitcode-stdio-1.0
     build-depends:       base >= 4.7 && < 5, bytestring, containers,
                          directory ^>= 1.3, filepath,
@@ -162,4 +171,4 @@
                          canadian-income-tax
     hs-source-dirs:      test
     main-is:             Regression.hs
-    default-language:    Haskell2010
+    GHC-options:         -Wno-incomplete-uni-patterns
diff --git a/src/Tax/Canada.hs b/src/Tax/Canada.hs
--- a/src/Tax/Canada.hs
+++ b/src/Tax/Canada.hs
@@ -7,9 +7,6 @@
 module Tax.Canada (completeForms, completeRelevantForms, formFileNames) where
 
 import Data.CAProvinceCodes qualified as Province
-import Data.Functor.Const (Const)
-import Data.Functor.Product (Product (Pair))
-import Data.Kind (Type)
 import Data.Map (Map)
 import Data.Map qualified as Map
 import Data.Set qualified as Set
@@ -24,7 +21,7 @@
 import Tax.Canada.Province.BC qualified as BC
 import Tax.Canada.Province.MB qualified as MB
 import Tax.Canada.Province.ON qualified as ON
-import Tax.Canada.T1 as T1 (T1, fixT1, t1FieldsForProvince, fileNameForProvince)
+import Tax.Canada.T1 as T1 (T1, fileNameForProvince)
 import Tax.FDF (FDFs)
 import Tax.FDF qualified as FDF
 
diff --git a/src/Tax/Canada/Federal.hs b/src/Tax/Canada/Federal.hs
--- a/src/Tax/Canada/Federal.hs
+++ b/src/Tax/Canada/Federal.hs
@@ -19,12 +19,11 @@
                            formFieldsForProvince, formFileNames, relevantFormKeys) where
 
 import Control.Applicative ((<|>))
-import Control.Monad ((=<<))
 import Data.CAProvinceCodes qualified as Province
 import Data.Fixed (Centi)
 import Data.Foldable (find)
 import Data.Functor.Compose (Compose(Compose))
-import Data.List.NonEmpty (NonEmpty((:|)), nonEmpty)
+import Data.List.NonEmpty (NonEmpty, nonEmpty)
 import Data.Maybe (isJust)
 import Data.Map (Map, fromList)
 import Data.Set (Set)
@@ -33,7 +32,6 @@
 import Data.Text (Text)
 import Data.Text qualified as Text
 import Data.Time (Day)
-import GHC.Stack (HasCallStack)
 import Rank2 qualified
 import Rank2.TH qualified
 import Transformation.Shallow.TH qualified
@@ -71,10 +69,10 @@
                             Page8Step6(line_43700_Total_income_tax_ded, line_44800_CPPOverpayment,
                                        line_45300_CWB, line_45350_CTC),
                             LanguageOfCorrespondence, MaritalStatus)
-import Tax.Canada.T4 (T4, t4Fields, T4Slip(box16_employeeCPP, box26_pensionableEarnings))
+import Tax.Canada.T4 (T4, T4Slip(box16_employeeCPP, box26_pensionableEarnings))
 import Tax.Canada.T4 qualified as T4
 import Tax.Canada.Shared (SubCalculation(result))
-import Tax.FDF (Entry (Amount), FieldConst (Field), load, within)
+import Tax.FDF (FieldConst, load, within)
 import Tax.Util (fixEq, totalOf)
 
 -- | All supported federal input forms, not to be filled in
@@ -115,8 +113,9 @@
 
 -- | Complete all the federal forms, also handling the inter-form field references.
 fixFederalForms :: Province.Code -> InputForms Maybe -> Forms Maybe -> Forms Maybe
-fixFederalForms province InputForms{t4} = fixEq $ \Forms{t1, schedule6, schedule7, schedule8, schedule9, schedule11}->
-                                                    let fromT4s' = fromT4s t4 in Forms{
+fixFederalForms province InputForms{t4 = t4s} = fixEq $
+                                                \Forms{t1, schedule6, schedule7, schedule8, schedule9, schedule11}->
+                                                  let fromT4s' = fromT4s t4s in Forms{
    t1 = fixT1 t1{
        page3 = fromT4s' (.slip1.box14_employmentIncome) (\amt pg-> pg{line_10100_EmploymentIncome = amt}) $
                fromT4s' (additionalT4 ["42"]) (\amt pg-> pg{line_10120_Commissions = amt}) $
@@ -124,7 +123,8 @@
        page4 = fromT4s' (.slip1.box52_pensionAdjustment) (\amt pg-> pg{line_20600_PensionAdjustment = amt}) $
                fromT4s' (.slip1.box20_employeeRPP) (\amt pg-> pg{line_20700_RPPDeduction = amt}) $
                fromT4s' (.slip1.box44_unionDues) (\amt pg-> pg{line_21200_Dues = amt}) $
-               fromT4s' (additionalT4 ["77"]) (\amt step-> step{line_22900_OtherEmployExpenses = amt}) $
+               fromT4s' (additionalT4 ["77"]) (\amt step-> step{line_22900_OtherEmployExpenses =
+                                                                amt <|> step.line_22900_OtherEmployExpenses}) $
                t1.page4{line_20800_RRSPDeduction = schedule7.page3.partC.line20_deduction,
                         line_22200_CPP_QPP_Contributions = schedule8.page6.line17_sum <|>
                                                            schedule8.page10.line97_sum,
@@ -143,12 +143,12 @@
                      fromT4s' (.slip1.box55_premiumPPIP) (\amt pg-> pg{line_31205 = amt}) t1.page6
                    _ -> fromT4s' (\t4-> totalOf [t4.slip1.box18_employeeEI, t4.slip1.box55_premiumPPIP])
                            (\amt pg-> pg{line_31200 = amt}) t1.page6)
-               {line_30800 = if any hasAnyField t4
+               {line_30800 = if any hasAnyField t4s
                              then schedule8.page5.part3a.line27_copy <|>
                                   schedule8.page5.part3b.line32_join <|>
                                   schedule8.page9.line60_least
                              else t1.page6.line_30800,
-                line_31000 = if any hasAnyField t4
+                line_31000 = if any hasAnyField t4s
                              then schedule8.page6.line15_half.result <|>
                                   schedule8.page9.line78_half.result
                              else t1.page6.line_31000,
@@ -171,8 +171,9 @@
    schedule8 = fixSchedule8 schedule8{
       page4 = schedule8.page4{
          line_50339_totalPensionableEarnings =
-            totalOf . (liftA2 (<|>) (.slip1.box26_pensionableEarnings) (.slip1.box14_employmentIncome) <$>) =<< t4,
-         line_50340_totalContributions = totalOf . fmap (.slip1.box16_employeeCPP) =<< t4},
+            totalOf . (liftA2 (<|>) (.slip1.box26_pensionableEarnings) (.slip1.box14_employmentIncome) <$>) =<< t4s,
+         line_50340_totalContributions = totalOf . fmap (.slip1.box16_employeeCPP) =<< t4s,
+         line_50341_totalSecondContributions = totalOf . fmap (.slip1.box16a_employeeCPP) =<< t4s},
       page6 = schedule8.page6{
          line1_netSelfEmploymentEarnings = totalOf [t1.page3.line_12200_PartnershipIncome,
                                                     t1.page3.line29_sum.result]},
diff --git a/src/Tax/Canada/Federal/Schedule11.hs b/src/Tax/Canada/Federal/Schedule11.hs
--- a/src/Tax/Canada/Federal/Schedule11.hs
+++ b/src/Tax/Canada/Federal/Schedule11.hs
@@ -18,7 +18,6 @@
 module Tax.Canada.Federal.Schedule11 where
 
 import Data.Fixed (Centi)
-import Data.Text (Text)
 import Language.Haskell.TH qualified as TH
 import Rank2 qualified
 import Rank2.TH qualified
@@ -28,7 +27,7 @@
 import Tax.Canada.T1.Types (T1)
 import Tax.Canada.T1.Types qualified
 import Tax.FDF (Entry (Amount, Checkbox, Count), FieldConst (Field), within)
-import Tax.Util (fixEq, fractionOf, difference, nonNegativeDifference, totalOf)
+import Tax.Util (fixEq, difference, nonNegativeDifference, totalOf)
 
 data Schedule11 line = Schedule11{
    page1 :: Page1 line,
diff --git a/src/Tax/Canada/Federal/Schedule6.hs b/src/Tax/Canada/Federal/Schedule6.hs
--- a/src/Tax/Canada/Federal/Schedule6.hs
+++ b/src/Tax/Canada/Federal/Schedule6.hs
@@ -18,13 +18,12 @@
 module Tax.Canada.Federal.Schedule6 where
 
 import Data.Fixed (Centi)
-import Data.Text (Text)
 import Language.Haskell.TH qualified as TH
 import Rank2 qualified
 import Rank2.TH qualified
 import Transformation.Shallow.TH qualified
 
-import Tax.Canada.Shared (SubCalculation(SubCalculation, calculation, result), fixSubCalculation, subCalculationFields)
+import Tax.Canada.Shared (SubCalculation(result), fixSubCalculation, subCalculationFields)
 import Tax.Canada.T1.Types (T1)
 import Tax.Canada.T1.Types qualified as T1
 import Tax.FDF (Entry (Amount, Constant, Percent, Switch'), FieldConst (Field), within)
diff --git a/src/Tax/Canada/Federal/Schedule7.hs b/src/Tax/Canada/Federal/Schedule7.hs
--- a/src/Tax/Canada/Federal/Schedule7.hs
+++ b/src/Tax/Canada/Federal/Schedule7.hs
@@ -17,18 +17,18 @@
 
 module Tax.Canada.Federal.Schedule7 where
 
+import Control.Applicative ((<|>))
 import Data.Fixed (Centi)
-import Data.Text (Text)
 import Language.Haskell.TH qualified as TH
 import Rank2 qualified
 import Rank2.TH qualified
 import Transformation.Shallow.TH qualified
 
-import Tax.Canada.Shared (SubCalculation(SubCalculation, result), fixSubCalculation, subCalculationFields)
+import Tax.Canada.Shared (SubCalculation(result), fixSubCalculation, subCalculationFields)
 import Tax.Canada.T1.Types (T1)
 import Tax.Canada.T1.Types qualified as T1
 import Tax.FDF (Entry (Amount, Checkbox), FieldConst (Field), within)
-import Tax.Util (fixEq, fractionOf, difference, nonNegativeDifference, totalOf)
+import Tax.Util (fixEq, difference, nonNegativeDifference, totalOf)
 
 data Schedule7 line = Schedule7{
    page2 :: Page2 line,
@@ -102,7 +102,7 @@
       partB = partB{
          line6_contributions_copy = page2.line5_sum,
          line9_repayments_sum = fixSubCalculation id $ totalOf [line_24600_hbp, line_24620_llp],
-         line10_difference = difference line6_contributions_copy line9_repayments_sum.result},
+         line10_difference = nonNegativeDifference line6_contributions_copy line9_repayments_sum.result},
       partC = partC{
          line12_prpp_copy = t1.page4.line_20810_PRPP,
          line13_difference = difference line11_deductionLimit line12_prpp_copy,
@@ -110,6 +110,7 @@
          line15_cont = line_24640_transfers,
          line16_difference = difference line14_copy line15_cont,
          line17_lesser = min line13_difference line16_difference,
+         line18_deducting = line18_deducting <|> line17_lesser,
          line19_sum = totalOf [line15_cont, line18_deducting],
          line20_deduction = min line10_difference line19_sum}},
    page4 = page4{
diff --git a/src/Tax/Canada/Federal/Schedule8.hs b/src/Tax/Canada/Federal/Schedule8.hs
--- a/src/Tax/Canada/Federal/Schedule8.hs
+++ b/src/Tax/Canada/Federal/Schedule8.hs
@@ -20,18 +20,15 @@
 
 import Control.Applicative ((<|>))
 import Data.Fixed (Centi)
-import Data.Text (Text)
 import Data.Time.Calendar (MonthOfYear)
 import Language.Haskell.TH qualified as TH
 import Rank2 qualified
 import Rank2.TH qualified
 import Transformation.Shallow.TH qualified
 
-import Tax.Canada.Shared (SubCalculation(SubCalculation, calculation, result), fixSubCalculation, subCalculationFields)
-import Tax.Canada.T1.Types (T1)
-import Tax.Canada.T1.Types qualified as T1
-import Tax.FDF (Entry (Amount, Constant, Count, Month, Percent), FieldConst (Field), within)
-import Tax.Util (fixEq, fractionOf, difference, nonNegativeDifference, totalOf)
+import Tax.Canada.Shared (SubCalculation(result), fixSubCalculation, subCalculationFields)
+import Tax.FDF (Entry (Amount, Count, Month), FieldConst (Field), within)
+import Tax.Util (fixEq, difference, nonNegativeDifference, totalOf)
 
 data Schedule8 line = Schedule8{
    page2 :: Page2 line,
diff --git a/src/Tax/Canada/Federal/Schedule9.hs b/src/Tax/Canada/Federal/Schedule9.hs
--- a/src/Tax/Canada/Federal/Schedule9.hs
+++ b/src/Tax/Canada/Federal/Schedule9.hs
@@ -27,7 +27,7 @@
 import Tax.Canada.T1.Types (T1)
 import Tax.Canada.T1.Types qualified
 import Tax.FDF (Entry (Amount, Constant, Textual), FieldConst (Field), within)
-import Tax.Util (fixEq, fractionOf, difference, nonNegativeDifference, totalOf)
+import Tax.Util (fixEq, difference, nonNegativeDifference, totalOf)
 
 data Schedule9 line = Schedule9{
    page1 :: Page1 line,
diff --git a/src/Tax/Canada/Province/AB.hs b/src/Tax/Canada/Province/AB.hs
--- a/src/Tax/Canada/Province/AB.hs
+++ b/src/Tax/Canada/Province/AB.hs
@@ -17,9 +17,8 @@
 import Tax.Canada.Federal.Schedule9 qualified as Schedule9
 import Tax.Canada.FormKey qualified as FormKey
 import Tax.Canada.FormKey (FormKey)
-import Tax.Canada.T1.Types (T1 (T1, page7, page8), Page7(Page7, step6_RefundOrBalanceOwing), Page8(Page8))
+import Tax.Canada.T1.Types (T1 (T1, page7), Page7(Page7, step6_RefundOrBalanceOwing))
 import Tax.Canada.T1.Types qualified as T1
-import Tax.Canada.T1.Types qualified as Page8 (Page8(..))
 import Tax.Canada.T1.FieldNames.AB (t1Fields)
 
 import Tax.Canada.Province.AB.AB428.Types qualified as AB
@@ -40,10 +39,9 @@
 fixReturns :: Federal.InputForms Maybe -> Returns Maybe -> Returns Maybe
 fixReturns inputs =
   fixEq $ \(Pair
-            ff@Federal.Forms{t1 = t1@T1{page7 = page7@Page7{step6_RefundOrBalanceOwing},
-                                        page8 = page8@Page8{step6_RefundOrBalanceOwing = page8step6}},
+            ff@Federal.Forms{t1 = t1@T1{page7 = page7@Page7{step6_RefundOrBalanceOwing}},
                              schedule9}
-            ab428@AB428{page1 = page1@AB.Page1{partA, partB = partB1@AB.Page1PartB{spouseAmount}},
+            ab428@AB428{page1 = page1@AB.Page1{partB = partB1@AB.Page1PartB{spouseAmount}},
                         page2 = page2@AB.Page2{AB.partB = partB2@AB.Page2PartB{AB.medicalExpenses}},
                         page3 = page3@AB.Page3{AB.partC}})
           -> (fixFederalForms AB inputs
diff --git a/src/Tax/Canada/Province/AB/AB428/FieldNames.hs b/src/Tax/Canada/Province/AB/AB428/FieldNames.hs
--- a/src/Tax/Canada/Province/AB/AB428/FieldNames.hs
+++ b/src/Tax/Canada/Province/AB/AB428/FieldNames.hs
@@ -12,19 +12,22 @@
 
 import Tax.Canada.Province.AB.AB428.Types
 import Tax.Canada.Shared (BaseCredit(..), MedicalExpenses(..), TaxIncomeBracket (..), subCalculationFields)
-import Tax.FDF (Entry (Count, Constant, Amount, Percent), FieldConst (Field, NoField), within)
+import Tax.FDF (Entry (Constant, Amount, Percent), FieldConst (Field), within)
 
+ab428Fields :: AB428 FieldConst
 ab428Fields = within "form1" Rank2.<$> AB428 {
    page1 = within "Page1" Rank2.<$> page1Fields,
    page2 = within "Page2" Rank2.<$> page2Fields,
    page3 = within "Page3" Rank2.<$> page3Fields}
 
 
+page1Fields :: Page1 FieldConst
 page1Fields = Page1 {
    income = Field ["Line1", "Amount"] Amount,
    partA = within "Chart" Rank2.<$> page1PartAFields,
    partB = page1PartBFields}
 
+page1PartAFields :: Page1PartA FieldConst
 page1PartAFields = Page1PartA {
    column1 = within "Column1" Rank2.<$> taxIncomeBracketFields "1"        0 0.10      0,
    column2 = within "Column2" Rank2.<$> taxIncomeBracketFields "2"  148_269 0.12 14_826.90,
@@ -43,6 +46,7 @@
    baseTax = Field ["Line7-C" <> column, "Amount"] $ Constant baseTax Amount,
    equalsTax = Field ["Line8-C" <> column, "Amount"] Amount}
 
+page1PartBFields :: Page1PartB FieldConst
 page1PartBFields = Page1PartB {
    line9_basic = Field ["Line9", "Amount"] Amount,
    line10_age = Field ["Line10", "Amount"] Amount,
@@ -66,9 +70,11 @@
    line24_sum = subCalculationFields "Line24" ["Amount1"] ["Amount2"],
    line25 = Field ["Line25", "Amount"] Amount}
 
+page2Fields :: Page2 FieldConst
 page2Fields = Page2 {
   partB = page2PartBFields}
 
+page2PartBFields :: Page2PartB FieldConst
 page2PartBFields = Page2PartB {
    line26 = Field ["Line26", "Amount"] Amount,
    line27_pension = Field ["Line27", "Amount"] Amount,
@@ -91,6 +97,7 @@
    line50_sum = subCalculationFields "Line50" ["Amount1"] ["Amount2"],
    line51 = Field ["Line51", "Amount"] Amount}
 
+medicalExpensesFields :: MedicalExpenses FieldConst
 medicalExpensesFields = MedicalExpenses {
    expenses = Field ["Line37", "Amount"] Amount,
    netIncome = Field ["Line38", "Amount"] Amount,
@@ -99,15 +106,18 @@
    lesser = Field ["Line41", "Amount"] Amount,
    difference = Field ["Line42", "Amount"] Amount}
 
+donationFields :: Donations FieldConst
 donationFields = Donations {
    line48_base = Field ["Line48", "Amount1"] Amount,
    line48_fraction = Field ["Line48", "Amount2"] Amount,
    line49_base = Field ["Line49", "Amount1"] Amount,
    line49_fraction = Field ["Line49", "Amount2"] Amount}
 
+page3Fields :: Page3 FieldConst
 page3Fields = Page3 {
    partC = within "PartC" Rank2.<$> partCFields}
 
+partCFields :: PartC FieldConst
 partCFields = PartC {
    line52_tax = Field ["Line52", "Amount"] Amount,
    line53_splitIncomeTax = Field ["Line53", "Amount"] Amount,
diff --git a/src/Tax/Canada/Province/AB/AB428/Fix.hs b/src/Tax/Canada/Province/AB/AB428/Fix.hs
--- a/src/Tax/Canada/Province/AB/AB428/Fix.hs
+++ b/src/Tax/Canada/Province/AB/AB428/Fix.hs
@@ -8,10 +8,7 @@
 
 module Tax.Canada.Province.AB.AB428.Fix (AB428, fixAB428) where
 
-import Control.Applicative (liftA2)
-import Control.Monad (guard)
 import Data.Fixed (Centi)
-import Rank2 qualified
 
 import Tax.Canada.Province.AB.AB428.Types
 import Tax.Canada.Shared (fixBaseCredit, fixMedicalExpenses, fixSubCalculation, fixTaxIncomeBracket,
diff --git a/src/Tax/Canada/Province/BC.hs b/src/Tax/Canada/Province/BC.hs
--- a/src/Tax/Canada/Province/BC.hs
+++ b/src/Tax/Canada/Province/BC.hs
@@ -39,7 +39,7 @@
 import Tax.Canada.Province.BC.BC428.Fix (fixBC428)
 import Tax.Canada.Province.BC.BC428.FieldNames (bc428Fields)
 import Tax.Canada.Province.BC.BC479.Types qualified as BCC
-import Tax.Canada.Province.BC.BC479.Types (BC479 (BC479))
+import Tax.Canada.Province.BC.BC479.Types (BC479)
 import Tax.Canada.Province.BC.BC479.Fix (fixBC479)
 import Tax.Canada.Province.BC.BC479.FieldNames (bc479Fields)
 
diff --git a/src/Tax/Canada/Province/BC/BC428/FieldNames.hs b/src/Tax/Canada/Province/BC/BC428/FieldNames.hs
--- a/src/Tax/Canada/Province/BC/BC428/FieldNames.hs
+++ b/src/Tax/Canada/Province/BC/BC428/FieldNames.hs
@@ -11,18 +11,21 @@
 
 import Tax.Canada.Province.BC.BC428.Types
 import Tax.Canada.Shared (BaseCredit(..), MedicalExpenses(..), TaxIncomeBracket (..), subCalculationFields)
-import Tax.FDF (Entry (Count, Constant, Amount, Percent, Textual), FieldConst (Field, NoField), within)
+import Tax.FDF (Entry (Constant, Amount, Percent, Textual), FieldConst (Field), within)
 
+bc428Fields :: BC428 FieldConst
 bc428Fields = within "form1" Rank2.<$> BC428 {
    page1 = within "Page1" Rank2.<$> page1Fields,
    page2 = within "Page2" Rank2.<$> page2Fields,
    page3 = within "Page3" Rank2.<$> page3Fields}
 
 
+page1Fields :: Page1 FieldConst
 page1Fields = Page1 {
    partA = within "PartA" Rank2.<$> page1PartAFields,
    partB = within "PartB" Rank2.<$> page1PartBFields}
 
+page1PartAFields :: Page1PartA FieldConst
 page1PartAFields = Page1PartA {
    income = Field ["Line1", "Amount"] Amount,
    column1 = within "Column1" Rank2.<$>  taxIncomeBracketFields        0 0.0506      0,
@@ -53,6 +56,7 @@
    baseTax = Field ["Line14", "Amount_ReadOnly"] $ Constant baseTax Amount,
    equalsTax = Field ["Line15", "Amount"] Amount}
 
+page1PartBFields :: Page1PartB FieldConst
 page1PartBFields = Page1PartB {
    line16_basic = Field ["Line16", "Amount"] Amount,
    line17_age = Field ["Line17", "Amount"] Amount,
@@ -69,9 +73,11 @@
    line24_caregiver = Field ["Line24", "Amount"] Amount,
    line25 = Field ["Line25", "Amount"] Amount}
 
+page2Fields :: Page2 FieldConst
 page2Fields = Page2 {
   partB = page2PartBFields}
 
+page2PartBFields :: Page2PartB FieldConst
 page2PartBFields = Page2PartB {
    line26 = Field ["Line26", "Amount"] Amount,
    line27_cppQpp = Field ["Line27", "Amount"] Amount,
@@ -105,6 +111,7 @@
    line59_fraction = Field ["Line59", "Amount"] Amount,
    line60 = Field ["Line60", "Amount"] Amount}
 
+medicalExpensesFields :: MedicalExpenses FieldConst
 medicalExpensesFields = MedicalExpenses {
    expenses = Field ["Line46", "Amount"] Amount,
    netIncome = Field ["Line47", "Amount"] Amount,
@@ -113,6 +120,7 @@
    lesser = Field ["Line50", "Amount"] Amount,
    difference = Field ["Line51", "Amount"] Amount}
 
+partCFields :: PartC FieldConst
 partCFields = PartC {
    line61_tax = Field ["Line61", "Amount"] Amount,
    line62_splitIncomeTax = Field ["Line62", "Amount"] Amount,
@@ -129,6 +137,7 @@
    line71_foreignCredit = Field ["Line71", "Amount"] Amount,
    line72 = Field ["Line72", "Amount"] Amount}
 
+page3Fields :: Page3 FieldConst
 page3Fields = Page3 {
    partC = partCFields,
    line73_basicReduction = Field ["Line73", "Amount"] Amount,
diff --git a/src/Tax/Canada/Province/BC/BC428/Fix.hs b/src/Tax/Canada/Province/BC/BC428/Fix.hs
--- a/src/Tax/Canada/Province/BC/BC428/Fix.hs
+++ b/src/Tax/Canada/Province/BC/BC428/Fix.hs
@@ -8,11 +8,6 @@
 
 module Tax.Canada.Province.BC.BC428.Fix (BC428, fixBC428) where
 
-import Control.Applicative (liftA2)
-import Control.Monad (guard, mfilter)
-import Data.Fixed (Centi)
-import Rank2 qualified
-
 import Tax.Canada.Province.BC.BC428.Types
 import Tax.Canada.Shared (fixBaseCredit, fixMedicalExpenses, fixSubCalculation, fixTaxIncomeBracket,
                           BaseCredit(cont), MedicalExpenses (difference),
diff --git a/src/Tax/Canada/Province/BC/BC479/FieldNames.hs b/src/Tax/Canada/Province/BC/BC479/FieldNames.hs
--- a/src/Tax/Canada/Province/BC/BC479/FieldNames.hs
+++ b/src/Tax/Canada/Province/BC/BC479/FieldNames.hs
@@ -4,18 +4,19 @@
 
 module Tax.Canada.Province.BC.BC479.FieldNames (bc479Fields) where
 
-import Data.Fixed (Centi)
 import Rank2 qualified
 
 import Tax.Canada.Province.BC.BC479.Types
 import Tax.Canada.Shared (subCalculationFields)
 import Tax.FDF (Entry (Amount, Checkbox, Constant, Count, Percent, Textual), FieldConst (Field), within)
 
+bc479Fields :: BC479 FieldConst
 bc479Fields = within "form1" Rank2.<$> BC479 {
    page1 = within "Page1" Rank2.<$> page1Fields,
    page2 = within "Page2" Rank2.<$> page2Fields,
    page3 = within "Page3" Rank2.<$> page3Fields}
 
+page1Fields :: Page1 FieldConst
 page1Fields = Page1 {
    line1_netIncome_self = Field ["Chart", "Line1", "NumWithoutCurrency"] Amount,
    line1_netIncome_spouse = Field ["Chart", "Line1", "NumWithoutCurrency2"] Amount,
@@ -40,6 +41,7 @@
    line14_fraction = Field ["BCSHRTC", "Line14", "Amount"] Amount,
    line15_sum = Field ["BCSHRTC", "Line15", "Amount"] Amount}
 
+page2Fields :: Page2 FieldConst
 page2Fields = Page2 {
    line16_copy = Field ["Line16", "Amount"] Amount,
    line17_venture = Field ["BCVCTC", "Line17", "Amount"] Amount,
@@ -59,6 +61,7 @@
    line31_sum = subCalculationFields "BCTTC" ["Line31", "I1", "Amount1"] ["Line31", "I2", "Amount2"],
    line32_credits = Field ["BCTTC", "Line32", "Amount"] Amount}
 
+page3Fields :: Page3 FieldConst
 page3Fields = Page3 {
    line33_copy = Field ["Line33", "Amount"] Amount,
    tenancy_months1 = Field ["Declaration-For-Renters", "Table", "Row1", "Numberofmonths"] Count,
diff --git a/src/Tax/Canada/Province/MB.hs b/src/Tax/Canada/Province/MB.hs
--- a/src/Tax/Canada/Province/MB.hs
+++ b/src/Tax/Canada/Province/MB.hs
@@ -18,10 +18,9 @@
 import Tax.Canada.Federal.Schedule9 qualified as Schedule9
 import Tax.Canada.FormKey (FormKey)
 import Tax.Canada.FormKey qualified as FormKey
-import Tax.Canada.T1.Types (T1 (T1, page7, page8), Page7(Page7, step6_RefundOrBalanceOwing), Page8(Page8))
+import Tax.Canada.T1.Types (T1 (T1, page7), Page7(Page7, step6_RefundOrBalanceOwing))
 import Tax.Canada.T1.Types qualified as T1
 import Tax.Canada.T1.FieldNames.AB (t1Fields)  -- same T1 form as Alberta
-import Tax.Canada.T1.Fix (fixT1)
 
 import Tax.Canada.Province.MB.MB428.Types qualified as MB
 import Tax.Canada.Province.MB.MB428.Types qualified as MB.Page1 (Page1(..))
@@ -40,10 +39,9 @@
 
 fixReturns :: Federal.InputForms Maybe -> Returns Maybe -> Returns Maybe
 fixReturns inputs =
-  fixEq $ \(Pair ff@Federal.Forms{t1 = t1@T1{page7 = page7@Page7{step6_RefundOrBalanceOwing},
-                                             page8 = page8@Page8{step6_RefundOrBalanceOwing = page8step6}},
+  fixEq $ \(Pair ff@Federal.Forms{t1 = t1@T1{page7 = page7@Page7{step6_RefundOrBalanceOwing}},
                                   schedule9}
-                 mb428@MB428{page1 = page1@MB.Page1{partA, partB = partB1@MB.Page1PartB{spouseAmount}},
+                 mb428@MB428{page1 = page1@MB.Page1{partB = partB1@MB.Page1PartB{spouseAmount}},
                              page2 = page2@MB.Page2{MB.partB = partB2@MB.Page2PartB{MB.medicalExpenses}},
                              page3 = page3@MB.Page3{MB.partC}})
           -> Pair (fixFederalForms MB inputs $
diff --git a/src/Tax/Canada/Province/MB/MB428/FieldNames.hs b/src/Tax/Canada/Province/MB/MB428/FieldNames.hs
--- a/src/Tax/Canada/Province/MB/MB428/FieldNames.hs
+++ b/src/Tax/Canada/Province/MB/MB428/FieldNames.hs
@@ -11,19 +11,22 @@
 
 import Tax.Canada.Province.MB.MB428.Types
 import Tax.Canada.Shared (BaseCredit(..), MedicalExpenses(..), TaxIncomeBracket (..), subCalculationFields)
-import Tax.FDF (Entry (Count, Constant, Amount, Percent), FieldConst (Field, NoField), within)
+import Tax.FDF (Entry (Constant, Amount, Percent), FieldConst (Field), within)
 
+mb428Fields :: MB428 FieldConst
 mb428Fields = within "form1" Rank2.<$> MB428 {
    page1 = within "Page1" Rank2.<$> page1Fields,
    page2 = within "Page2" Rank2.<$> page2Fields,
    page3 = within "Page3" Rank2.<$> page3Fields}
 
 
+page1Fields :: Page1 FieldConst
 page1Fields = Page1 {
    income = Field ["Line1", "Amount"] Amount,
    partA = within "Table" Rank2.<$> page1PartAFields,
    partB = page1PartBFields}
 
+page1PartAFields :: Page1PartA FieldConst
 page1PartAFields = Page1PartA {
    column1 = within "Column1" Rank2.<$> taxIncomeBracketFields       0  0.108       0,
    column2 = within "Column2" Rank2.<$> taxIncomeBracketFields   47_000 0.1275   5076,
@@ -39,6 +42,7 @@
    baseTax = Field ["Line7", "Amount"] $ Constant baseTax Amount,
    equalsTax = Field ["Line8", "Amount"] Amount}
 
+page1PartBFields :: Page1PartB FieldConst
 page1PartBFields = Page1PartB {
    line9_basic = Field ["Line9", "Amount"] Amount,
    line10_age = Field ["Line10", "Amount"] Amount,
@@ -66,9 +70,11 @@
    line28_sum = subCalculationFields "Line28" ["Amount1"] ["Amount2"],
    line29 = Field ["Line29", "Amount"] Amount}
 
+page2Fields :: Page2 FieldConst
 page2Fields = Page2 {
   partB = within "PartB" Rank2.<$> page2PartBFields}
 
+page2PartBFields :: Page2PartB FieldConst
 page2PartBFields = Page2PartB {
    line30 = Field ["Line30", "Amount"] Amount,
    line31_pension = Field ["Line31", "Amount"] Amount,
@@ -93,6 +99,7 @@
    line56_sum = subCalculationFields "Line56" ["Amount1"] ["Amount2"],
    line57 = Field ["Line57", "Amount"] Amount}
 
+medicalExpensesFields :: MedicalExpenses FieldConst
 medicalExpensesFields = MedicalExpenses {
    expenses = Field ["Line43", "Amount"] Amount,
    netIncome = Field ["Line44", "Amount"] Amount,
@@ -101,15 +108,18 @@
    lesser = Field ["Line47", "Amount"] Amount,
    difference = Field ["Line48", "Amount"] Amount}
 
+donationFields :: Donations FieldConst
 donationFields = Donations {
    line54_base = Field ["Line54", "Amount1"] Amount,
    line54_fraction = Field ["Line54", "Amount2"] Amount,
    line55_base = Field ["Line55", "Amount1"] Amount,
    line55_fraction = Field ["Line55", "Amount2"] Amount}
 
+page3Fields :: Page3 FieldConst
 page3Fields = Page3 {
    partC = within "PartC" Rank2.<$> partCFields}
 
+partCFields :: PartC FieldConst
 partCFields = PartC {
    line58_tax = Field ["Line58", "Amount"] Amount,
    line59_splitIncomeTax = Field ["Line59", "Amount"] Amount,
diff --git a/src/Tax/Canada/Province/MB/MB428/Fix.hs b/src/Tax/Canada/Province/MB/MB428/Fix.hs
--- a/src/Tax/Canada/Province/MB/MB428/Fix.hs
+++ b/src/Tax/Canada/Province/MB/MB428/Fix.hs
@@ -8,10 +8,7 @@
 
 module Tax.Canada.Province.MB.MB428.Fix (MB428, fixMB428) where
 
-import Control.Applicative (liftA2)
-import Control.Monad (guard)
 import Data.Fixed (Centi)
-import Rank2 qualified
 
 import Tax.Canada.Province.MB.MB428.Types
 import Tax.Canada.Shared (fixBaseCredit, fixMedicalExpenses, fixSubCalculation, fixTaxIncomeBracket,
diff --git a/src/Tax/Canada/Province/ON.hs b/src/Tax/Canada/Province/ON.hs
--- a/src/Tax/Canada/Province/ON.hs
+++ b/src/Tax/Canada/Province/ON.hs
@@ -39,7 +39,7 @@
 import Tax.Canada.Province.ON.ON428.Types (ON428 (ON428))
 import Tax.Canada.Province.ON.ON428.Fix (fixON428)
 import Tax.Canada.Province.ON.ON428.FieldNames (on428Fields)
-import Tax.Canada.Province.ON.ON479.Types (ON479 (ON479, page2), Page2(line23_credits))
+import Tax.Canada.Province.ON.ON479.Types (ON479 (page2), Page2(line23_credits))
 import Tax.Canada.Province.ON.ON479.Fix (fixON479)
 import Tax.Canada.Province.ON.ON479.FieldNames (on479Fields)
 
diff --git a/src/Tax/Canada/Province/ON/ON428/FieldNames.hs b/src/Tax/Canada/Province/ON/ON428/FieldNames.hs
--- a/src/Tax/Canada/Province/ON/ON428/FieldNames.hs
+++ b/src/Tax/Canada/Province/ON/ON428/FieldNames.hs
@@ -14,6 +14,7 @@
 import Tax.Canada.Shared (BaseCredit(..), MedicalExpenses(..), TaxIncomeBracket (..), subCalculationFields)
 import Tax.FDF (Entry (Count, Constant, Amount, Percent), FieldConst (Field, NoField), within)
 
+on428Fields :: ON428 FieldConst
 on428Fields = within "form1" Rank2.<$> ON428 {
    page1 = within "Page1" Rank2.<$> page1Fields,
    page2 = within "Page2" Rank2.<$> page2Fields,
@@ -21,11 +22,13 @@
    page4 = within "Page4" Rank2.<$> page4Fields}
 
 
+page1Fields :: Page1 FieldConst
 page1Fields = Page1 {
    line1 = Field ["Line1", "Amount"] Amount,
    partA = within "Chart" Rank2.<$> page1PartAFields,
    partB = within "Part_B" Rank2.<$> page1PartBFields}
 
+page1PartAFields :: Page1PartA FieldConst
 page1PartAFields = Page1PartA {
    column1 = within "Column1" Rank2.<$> taxIncomeBracketFields 0 0.0505 0,
    column2 = within "Column2" Rank2.<$> taxIncomeBracketFields 51_446.00 0.0915 2_598.02,
@@ -43,6 +46,7 @@
    baseTax = Field ["Line7", "Amount"] $ Constant baseTax Amount,
    equalsTax = Field ["Line8", "Amount"] Amount}
 
+page1PartBFields :: Page1PartB FieldConst
 page1PartBFields = Page1PartB {
    line9_basic = Field ["Line9", "Amount"] Amount,
    line10_age = Field ["Line10", "Amount"] Amount,
@@ -66,10 +70,12 @@
    line24_sum = subCalculationFields "Line24" ["Amount1"] ["Amount2"],
    line25 = Field ["Line25", "Amount"] Amount}
 
+page2Fields :: Page2 FieldConst
 page2Fields = Page2 {
   partB = page2PartBFields,
   partC = page2PartCFields}
 
+page2PartBFields :: Page2PartB FieldConst
 page2PartBFields = Page2PartB {
    line26 = Field ["Line26", "Amount"] Amount,
    line27_pension = Field ["Line27", "Amount"] Amount,
@@ -90,6 +96,7 @@
    donations = within "Donations" Rank2.<$> donationsFields,
    line50 = Field ["Line50", "Amount"] Amount}
 
+medicalExpensesFields :: MedicalExpenses FieldConst
 medicalExpensesFields = MedicalExpenses {
    expenses = Field ["Line36", "Amount"] Amount,
    netIncome = Field ["Line37", "Amount"] Amount,
@@ -98,6 +105,7 @@
    lesser = Field ["Line40", "Amount"] Amount,
    difference = Field ["Line41", "Amount"] Amount}
 
+donationsFields :: Donations FieldConst
 donationsFields = Donations {
    line47_base = Field ["Line47", "Amount1"] Amount,
    line47_fraction = Field ["Line47", "Amount2"] Amount,
@@ -105,6 +113,7 @@
    line48_fraction = Field ["Line48", "Amount2"] Amount,
    line49_sum = subCalculationFields "Line49" ["Amount1"] ["Amount2"]}
 
+page2PartCFields :: Page2PartC FieldConst
 page2PartCFields = Page2PartC {
    line51_tax = Field ["Line51", "Amount"] Amount,
    line52_credits = Field ["Line52", "Amount"] Amount,
@@ -119,6 +128,7 @@
    line60_lesser = Field ["Min-Tax-Carryover", "Line60", "Amount"] Amount,
    line61 = Field ["Line61", "Amount"] Amount}
 
+page3Fields :: Page3 FieldConst
 page3Fields = Page3 {
    line62 = Field ["Line62", "Amount"] Amount,
    line63 = Field ["ON-Surtax", "Line63", "Amount"] Amount,
@@ -145,6 +155,7 @@
    line82 = Field ["Line82", "Amount"] Amount,
    line83 = Field ["Line83", "Amount"] Amount}
 
+page4Fields :: Page4 FieldConst
 page4Fields = Page4 {
    line84 = Field ["Line84", "Amount"] Amount,
    line85_lift = Field ["Line85", "Amount"] Amount,
@@ -156,6 +167,7 @@
    line90 = Field ["Line90", "Amount"] Amount,
    healthPremium = within "ON_Health_Prenium-worksheet" . within "Chart_ON_Health_Prenium" Rank2.<$> healthPremiumFields}
 
+healthPremiumFields :: HealthPremium FieldConst
 healthPremiumFields = HealthPremium {
    row1 = within "Taxable_Line2" Rank2.<$> healthPremiumBracketFields{HealthPremiumBracket.equalsTax = NoField},
    row2 = within "Taxable_Line4" Rank2.<$> healthPremiumBracketFields,
@@ -163,6 +175,7 @@
    row4 = within "Taxable_Line8" Rank2.<$> healthPremiumBracketFields,
    row5 = within "Taxable_Line10" Rank2.<$> healthPremiumBracketFields}
 
+healthPremiumBracketFields :: HealthPremiumBracket FieldConst
 healthPremiumBracketFields = HealthPremiumBracket {
    taxableIncome = Field ["Amount1"] Amount,
    overThreshold = Field ["Amount2"] Amount,
diff --git a/src/Tax/Canada/Province/ON/ON428/Fix.hs b/src/Tax/Canada/Province/ON/ON428/Fix.hs
--- a/src/Tax/Canada/Province/ON/ON428/Fix.hs
+++ b/src/Tax/Canada/Province/ON/ON428/Fix.hs
@@ -9,8 +9,6 @@
 
 module Tax.Canada.Province.ON.ON428.Fix (ON428, fixON428) where
 
-import Control.Applicative (liftA2)
-import Control.Monad (guard, mfilter)
 import Data.Fixed (Centi)
 import Rank2 qualified
 
@@ -19,6 +17,8 @@
                           BaseCredit(cont), MedicalExpenses (difference),
                           SubCalculation (result), TaxIncomeBracket (equalsTax))
 import Tax.Util (fixEq, fractionOf, nonNegativeDifference, totalOf)
+
+import Prelude hiding (floor, ceiling)
 
 fixON428 :: ON428 Maybe -> ON428 Maybe
 fixON428 = fixEq $ \on428@ON428{..}-> ON428{page1 = fixPage1 page1,
diff --git a/src/Tax/Canada/Province/ON/ON479/FieldNames.hs b/src/Tax/Canada/Province/ON/ON479/FieldNames.hs
--- a/src/Tax/Canada/Province/ON/ON479/FieldNames.hs
+++ b/src/Tax/Canada/Province/ON/ON479/FieldNames.hs
@@ -6,18 +6,19 @@
 
 module Tax.Canada.Province.ON.ON479.FieldNames (on479Fields) where
 
-import Data.Fixed (Centi)
 import Rank2 qualified
 
 import Tax.Canada.Province.ON.ON479.Types
 import Tax.Canada.Shared (subCalculationFields)
 import Tax.FDF (Entry (Count, Constant, Amount, Percent, RadioButton, Textual), FieldConst (Field), within)
 
+on479Fields :: ON479 FieldConst
 on479Fields = within "form1" Rank2.<$> ON479 {
    page1 = within "Page1" Rank2.<$> page1Fields,
    page2 = within "Page2" Rank2.<$> page2Fields}
 
 
+page1Fields :: Page1 FieldConst
 page1Fields = Page1 {
    line_63050_childcare = Field ["Line1", "Amount"] Amount,
    line4_homecare_copy = Field ["Line2", "Amount"] Amount,
@@ -35,6 +36,7 @@
    line_63100_fraction = Field ["Line13", "Amount"] Amount,
    line16_sum = Field ["Line14", "Amount"] Amount}
 
+page2Fields :: Page2 FieldConst
 page2Fields = Page2 {
    line17_copy = Field ["Line15", "Amount"] Amount,
    line_63110_contributions = Field ["ON-Political-Contribution", "Line16", "Amount"] Amount,
diff --git a/src/Tax/Canada/Province/ON/ON479/Fix.hs b/src/Tax/Canada/Province/ON/ON479/Fix.hs
--- a/src/Tax/Canada/Province/ON/ON479/Fix.hs
+++ b/src/Tax/Canada/Province/ON/ON479/Fix.hs
@@ -8,11 +8,6 @@
 
 module Tax.Canada.Province.ON.ON479.Fix (ON479, fixON479) where
 
-import Control.Applicative (liftA2)
-import Control.Monad (guard, mfilter)
-import Data.Fixed (Centi)
-import Rank2 qualified
-
 import Tax.Canada.Province.ON.ON479.Types
 import Tax.Canada.Shared (fixSubCalculation, SubCalculation(result))
 import Tax.Util (fixEq, fractionOf, nonNegativeDifference, totalOf)
diff --git a/src/Tax/Canada/Shared.hs b/src/Tax/Canada/Shared.hs
--- a/src/Tax/Canada/Shared.hs
+++ b/src/Tax/Canada/Shared.hs
@@ -26,6 +26,8 @@
 import Tax.FDF (FieldConst(Field), Entry(Amount))
 import Tax.Util (fixEq, fractionOf, nonNegativeDifference)
 
+import Prelude hiding (floor, ceiling)
+
 data TaxIncomeBracket line = TaxIncomeBracket {
    income :: line Centi,
    threshold :: line Centi,
diff --git a/src/Tax/Canada/T1/FieldNames/AB.hs b/src/Tax/Canada/T1/FieldNames/AB.hs
--- a/src/Tax/Canada/T1/FieldNames/AB.hs
+++ b/src/Tax/Canada/T1/FieldNames/AB.hs
@@ -8,9 +8,7 @@
 import Rank2 qualified
 
 import Tax.FDF (FieldConst (Field, NoField), Entry (..), within)
-import Tax.Canada.Shared (subCalculationFields)
 import Tax.Canada.T1.Types
-import Tax.Canada.T1.Types qualified as Page8 (Page8(..))
 import Tax.Canada.T1.FieldNames.BC qualified as BC
 import Tax.Canada.T1.FieldNames.ON qualified as ON
 
@@ -25,6 +23,7 @@
    page7 = within "Page7" . within "Return-pg7" Rank2.<$> ON.page7Fields,
    page8 = within "Page8" . within "Return-pg8" Rank2.<$> BC.page8Fields}
 
+page2Fields :: Page2 FieldConst
 page2Fields = ON.page2Fields {
    cai = Field ["CAI", "AB_CAI", "Tick_box"] Checkbox,
    organ_donor = NoField}
diff --git a/src/Tax/Canada/T1/FieldNames/BC.hs b/src/Tax/Canada/T1/FieldNames/BC.hs
--- a/src/Tax/Canada/T1/FieldNames/BC.hs
+++ b/src/Tax/Canada/T1/FieldNames/BC.hs
@@ -17,12 +17,15 @@
    page2 = within "form1" . within "Page2" Rank2.<$> page2Fields,
    page8 = within "form1" . within "Page8" . within "Return-pg8" Rank2.<$> page8Fields}
 
+page2Fields :: Page2 FieldConst
 page2Fields = ON.page2Fields {
    cai = NoField,
    organ_donor = Field ["Organ_donor", "Authori"] $ Switch "Option1" "Option2" "OrganDonor_CheckBox"}
 
+page3Fields :: Page3 FieldConst
 page3Fields = ON.page3Fields
 
+page8Fields :: Page8 FieldConst
 page8Fields = ON.page8Fields {
    Page8.step6_RefundOrBalanceOwing = within "Step6-Cont" Rank2.<$> page8step6Fields,
    taxPreparer = within "Efile" Rank2.<$> taxPreparerFields,
@@ -30,11 +33,13 @@
    line_46500 = NoField,
    line_46600 = NoField}
 
+page8step6Fields :: Page8Step6 FieldConst
 page8step6Fields = ON.page8step6Fields {
    line_45350_CTC = Field ["Line45350", "Line_45300_Amount"] Amount,
    line_45355_MHRTC = Field ["Line45355", "Line_45300_Amount"] Amount,
    line_47555_TaxPaid = Field ["Line47555", "Line_47555_Amount"] Amount}
 
+taxPreparerFields :: TaxPreparer FieldConst
 taxPreparerFields = ON.taxPreparerFields {
    eFileNumber = Field ["Line48900", "EFile"] Textual,
    line_49000_WasAFeeCharged = Field ["Line49000", "Line49000_CheckBoxGroup"] $ Switch' "Line49000_CheckBox_EN"}
diff --git a/src/Tax/Canada/T1/FieldNames/NB.hs b/src/Tax/Canada/T1/FieldNames/NB.hs
--- a/src/Tax/Canada/T1/FieldNames/NB.hs
+++ b/src/Tax/Canada/T1/FieldNames/NB.hs
@@ -15,9 +15,11 @@
    page2 = within "form1" . within "Page2" Rank2.<$> page2Fields,
    page8 = within "form1" . within "Page8" . within "Return-pg8" Rank2.<$> page8Fields}
 
+page2Fields :: Page2 FieldConst
 page2Fields = PE.page2Fields{
    cai = Field ["CAI", "CAI_2024", "Tick_box"] Checkbox}
 
+page8Fields :: Page8 FieldConst
 page8Fields = PE.page8Fields {
    line_48400_Refund = Field ["Refund_or_Balance-Owing", "Line48400", "Line_48400_Amount"] Amount,
    line_48500_BalanceOwing = Field ["Refund_or_Balance-Owing", "Line48500", "Line_48500_Amount"] Amount}
diff --git a/src/Tax/Canada/T1/FieldNames/NL.hs b/src/Tax/Canada/T1/FieldNames/NL.hs
--- a/src/Tax/Canada/T1/FieldNames/NL.hs
+++ b/src/Tax/Canada/T1/FieldNames/NL.hs
@@ -8,8 +8,7 @@
 
 import Rank2 qualified
 
-import Tax.FDF (FieldConst (Field, NoField), Entry (..), within)
-import Tax.Canada.Shared (subCalculationFields, TaxIncomeBracket (timesRate))
+import Tax.FDF (FieldConst (Field), Entry (..), within)
 import Tax.Canada.T1.Types
 import Tax.Canada.T1.Types qualified as Page8 (Page8(..))
 import Tax.Canada.T1.FieldNames.ON qualified as ON
@@ -27,10 +26,12 @@
    page7 = within "Page7" . within "Return-pg7" Rank2.<$> ON.page7Fields,
    page8 = within "Page8" . within "Return-pg8" Rank2.<$> page8Fields}
 
+page2Fields :: Page2 FieldConst
 page2Fields = AB.page2Fields {
    foreign_property = Field ["Foreign_property", "Line26600"] $ Switch' "ForeignProperty_CheckBox",
    tax_exempt = Field ["Indian_Act", "IndianAct_Question", "Checkbox"] Checkbox}
 
+page8Fields :: Page8 FieldConst
 page8Fields = BC.page8Fields {
    Page8.step6_RefundOrBalanceOwing = within "Step6-Cont" Rank2.<$> BC.page8step6Fields,
    telephone = Field ["Certification", "Telephone"] Amount,
diff --git a/src/Tax/Canada/T1/FieldNames/NT.hs b/src/Tax/Canada/T1/FieldNames/NT.hs
--- a/src/Tax/Canada/T1/FieldNames/NT.hs
+++ b/src/Tax/Canada/T1/FieldNames/NT.hs
@@ -8,8 +8,7 @@
 
 import Rank2 qualified
 
-import Tax.FDF (FieldConst (Field, NoField), Entry (..), within)
-import Tax.Canada.Shared (subCalculationFields)
+import Tax.FDF (FieldConst (NoField), within)
 import Tax.Canada.T1.Types
 import Tax.Canada.T1.Types qualified as Page8 (Page8(..))
 import Tax.Canada.T1.FieldNames.ON
@@ -25,8 +24,10 @@
    page2 = within "form1" . within "Page2" Rank2.<$> page2Fields,
    page8 = within "form1" . within "Page8" . within "Return-pg8" Rank2.<$> page8Fields}
 
+page2Fields :: Page2 FieldConst
 page2Fields = BC.page2Fields{
    organ_donor = NoField}
 
+page8Fields :: Page8 FieldConst
 page8Fields = BC.page8Fields {
    Page8.step6_RefundOrBalanceOwing = within "Step6-Cont" Rank2.<$> BC.page8step6Fields}
diff --git a/src/Tax/Canada/T1/FieldNames/NU.hs b/src/Tax/Canada/T1/FieldNames/NU.hs
--- a/src/Tax/Canada/T1/FieldNames/NU.hs
+++ b/src/Tax/Canada/T1/FieldNames/NU.hs
@@ -7,7 +7,7 @@
 
 import Rank2 qualified
 
-import Tax.FDF (FieldConst (NoField), within)
+import Tax.FDF (FieldConst, within)
 import Tax.Canada.T1.Types
 import Tax.Canada.T1.FieldNames.PE qualified as PE
 import Tax.Canada.T1.FieldNames.ON qualified as ON
diff --git a/src/Tax/Canada/T1/FieldNames/ON.hs b/src/Tax/Canada/T1/FieldNames/ON.hs
--- a/src/Tax/Canada/T1/FieldNames/ON.hs
+++ b/src/Tax/Canada/T1/FieldNames/ON.hs
@@ -10,7 +10,7 @@
 
 import Data.Text (Text)
 import Data.Text.Lazy (toStrict)
-import Data.Text.Lazy.Builder (fromText, toLazyText)
+import Data.Text.Lazy.Builder (toLazyText)
 import Data.Text.Lazy.Builder.Int (decimal)
 import Tax.FDF (FieldConst (Field, NoField), Entry (..), within)
 import Tax.Canada.Shared (TaxIncomeBracket (..), subCalculationFields)
@@ -27,11 +27,13 @@
    page7 = within "Page7" . within "Return-pg7" Rank2.<$> page7Fields,
    page8 = within "Page8" Rank2.<$> page8Fields}
 
+page1Fields :: Page1 FieldConst
 page1Fields = Page1 {
    identification = within "Identification" Rank2.<$> page1IdentificationFields,
    residence = within "Residence_Info" Rank2.<$> page1ResidenceFields,
    spouse = within "Info_Spouse_CLP" Rank2.<$> page1SpouseFields}
 
+page1IdentificationFields :: Identification FieldConst
 page1IdentificationFields = Identification {
    emailAddress = Field ["EmailAddress"] Textual,
    dateDeath = Field ["DateDeath_Comb_BordersAll", "DateDeath_Comb"] Date,
@@ -48,6 +50,7 @@
    id_POBox = Field ["ID_POBox"] Textual,
    prov_DropDown = Field ["Prov_DropDown"] Province}
 
+page1ResidenceFields :: Residence FieldConst
 page1ResidenceFields = Residence {
    prov_DropDown_Business = Field ["Prov_DropDown-Business"] Province,
    prov_DropDown_Residence = Field ["Prov_DropDown-Residence"] Province,
@@ -55,6 +58,7 @@
    date_Entry = Field ["Date_Entry", "DateMMDD_Comb_BordersAll_Std", "DateMMDD_Comb"] Date,
    prov_DropDown = Field ["Prov_DropDown"] Textual}
   
+page1SpouseFields :: Spouse FieldConst
 page1SpouseFields = Spouse {
    line_23600 = Field ["Line23600", "Amount"] Amount,
    self_employment = Field ["Self-employment", "Checkbox"] Checkbox,
@@ -63,6 +67,7 @@
    line_21300 = Field ["Line21300", "Amount"] Amount,
    sin = Field ["SIN_Comb_BordersAll", "SIN_Comb"] Textual}
 
+page2Fields :: Page2 FieldConst
 page2Fields = Page2 {
    foreign_property = Field ["Foreign_property", "Line26600"] $ Switch "Option1" "Option2" "ForeignProperty_CheckBox",
    tax_exempt = Field ["Tax_exempt", "Exempt", "Spouse_SelfEmployed"] Checkbox,
@@ -71,10 +76,12 @@
    organ_donor = Field ["Organ_donor", "Question"] $ Switch "Option1" "Option2" "OrganDonor_CheckBox"
 }
 
+page2ElectionsCanadaFields :: ElectionsCanada FieldConst
 page2ElectionsCanadaFields = ElectionsCanada {
    citizenship = Field ["LineA"] $ Switch "Option1" "Option2" "A_CheckBox",
    authorization = Field ["LineB"] $ Switch "Option1" "Option2" "B_Authorize_CheckBox"}
 
+page3Fields :: Page3 FieldConst
 page3Fields = Page3 {
    line_10100_EmploymentIncome = Field ["Line1", "Line_10100_Amount"] Amount,
    line_10105_Taxexemptamount = Field ["Line10105", "Line_10105_Amount"] Amount,
@@ -118,6 +125,7 @@
    line_14700_sum = subCalculationFields "Line14700" ["Line_14700_Amount1"] ["Line_14700_Amount2"],
    line_15000_TotalIncome = Field ["Line15000", "Line_15000_Amount"] Amount}
 
+selfEmploymentFields :: SelfEmploymentIncome FieldConst
 selfEmploymentFields = SelfEmploymentIncome {
    line_13499_Amount = Field ["Line13500", "Line13499", "Line_13499_Amount"] Amount,
    line_13500_Amount = Field ["Line13500", "Line_13500_Amount"] Amount,
@@ -130,6 +138,7 @@
    line_14299_Amount = Field ["Line14300", "Line14299", "Line_14299_Amount"] Amount,
    line_14300_Amount = Field ["Line14300", "Line_14300_Amount"] Amount}
 
+page4Fields :: Page4 FieldConst
 page4Fields = Page4 {
    line_15000_TotalIncome_2 = Field ["Line36", "Amount"] Amount,
    line_20600_PensionAdjustment = Field ["Line20600", "Line_20600_Amount"] Amount,
@@ -162,11 +171,13 @@
    line_23500_SocialBenefits = Field ["Line23500", "Line_23500_Amount"] Amount,
    line_23600_NetIncome = Field ["Line23600", "Line_23600_Amount"] Amount}
 
+page5Fields :: Page5 FieldConst
 page5Fields = Page5 {
    step4_TaxableIncome = within "Step4" Rank2.<$> step4Fields,
    partA_FederalTax = within "PartA" Rank2.<$> partAFields "Column" 36,
    partB_FederalTaxCredits = within "PartB" Rank2.<$> partBFields}
 
+step4Fields :: Step4 FieldConst
 step4Fields = Step4 {
    line_23600_NetIncome_2 = Field ["Line59", "Amount"] Amount,
    line_24400_MilitaryPoliceDeduction = Field ["Line24400", "Line_24400_Amount"] Amount,
@@ -209,6 +220,7 @@
             equalsTax = Field [fieldNameAt (startLine + 6) n False] Amount}
          toText = toStrict . toLazyText
 
+partBFields :: Page5PartB FieldConst
 partBFields = Page5PartB {
    line_30000 = Field ["Line30000", "Line_30000_Amount"] Amount,
    line_30100 = Field ["Line30100", "Line_30100_Amount"] Amount,
@@ -220,6 +232,7 @@
    line_30500 = Field ["Line30500", "Line_30500_Amount"] Amount,
    pageBreakSummary = Field ["Line89", "Amount"] Amount}
                                                                                            
+page6Fields :: Page6 FieldConst
 page6Fields = Page6 {
    pageBreakCarry = Field ["Line90", "Amount"] Amount,
    line_30800 = Field ["Line30800", "Line_30800_Amount"] Amount,
@@ -255,6 +268,7 @@
    line_34900 = Field ["Line34900", "Line_34900_Amount"] Amount,
    line_35000 = Field ["Line35000", "Line_35000_Amount"] Amount}
 
+page6MedicalExpensesFields :: MedicalExpenses FieldConst
 page6MedicalExpensesFields = MedicalExpenses {
    familyExpenses = Field ["Line33099", "Line_33099_Amount"] Amount,
    taxableIncome = Field ["Line114", "Amount1"] Amount,
@@ -263,10 +277,12 @@
    difference = Field ["Line116", "Amount"] Amount,
    otherDependants = Field ["Line33199", "Line_33199_Amount"] Amount}
 
+page7Fields :: Page7 FieldConst
 page7Fields = Page7 {
    partC_NetFederalTax = within "PartC" Rank2.<$> partCFields,
    step6_RefundOrBalanceOwing = within "Step6" Rank2.<$> page7step6Fields}
 
+partCFields :: Page7PartC FieldConst
 partCFields = Page7PartC {
    tax_copy = Field ["Line124", "Amount"] Amount,
    line_40424 = Field ["Line40424", "Line_40424_Amount"] Amount,
@@ -295,6 +311,7 @@
    line_41800 = Field ["Line41800", "Line_41800_Amount"] Amount,
    line_42000 = Field ["Line42000", "Line_42000_Amount"] Amount}
 
+page7step6Fields :: Page7Step6 FieldConst
 page7step6Fields = Page7Step6 {
    tax_copy = Field ["Line148", "Amount"] Amount,
    line_42100_CPPContributions = Field ["Line42100", "Line_42100_Amount"] Amount,
@@ -304,6 +321,7 @@
    line_43200_FirstNationsTax = NoField,
    line_43500_TotalPayable = Field ["Line43500", "Line_43500_Amount"] Amount}
                                                                                            
+page8Fields :: Page8 FieldConst
 page8Fields = Page8 {
    step6_RefundOrBalanceOwing = within "Step6-Continued" Rank2.<$> page8step6Fields,
    line_48400_Refund = Field ["Refund_or_Balance-owing", "Line48400", "Line_48400_Amount"] Amount,
@@ -315,6 +333,7 @@
    line_46500 = Field ["ONOpportunitiesFund2", "Line_2", "Amount"] Amount,
    line_46600 = Field ["ONOpportunitiesFund2", "Line_3", "Amount"] Amount}
 
+page8step6Fields :: Page8Step6 FieldConst
 page8step6Fields = Page8Step6 {
    line_43500_totalpayable = Field ["Line154", "Amount"] Amount,
    line_43700_Total_income_tax_ded = Field ["Line43700", "Line_43700_Amount"] Amount,
@@ -344,6 +363,7 @@
    line_48200_sum = subCalculationFields "Line48200" ["Line_48200_Amount1"] ["Line_48200_Amount2"],
    line164_Refund_or_BalanceOwing = Field ["Line172", "Amount"] Amount}
 
+taxPreparerFields :: TaxPreparer FieldConst
 taxPreparerFields = TaxPreparer {
    eFileNumber = Field ["EFileNumber_Comb", "EFile"] Textual,
    nameOfPreparer = Field ["NameOfPreparer"] Textual,
diff --git a/src/Tax/Canada/T1/FieldNames/PE.hs b/src/Tax/Canada/T1/FieldNames/PE.hs
--- a/src/Tax/Canada/T1/FieldNames/PE.hs
+++ b/src/Tax/Canada/T1/FieldNames/PE.hs
@@ -6,7 +6,7 @@
 
 import Rank2 qualified
 
-import Tax.FDF (FieldConst (Field), Entry (..), within)
+import Tax.FDF (FieldConst, within)
 import Tax.Canada.T1.Types
 import Tax.Canada.T1.FieldNames.AB qualified as AB
 import Tax.Canada.T1.FieldNames.BC qualified as BC
diff --git a/src/Tax/Canada/T1/FieldNames/QC.hs b/src/Tax/Canada/T1/FieldNames/QC.hs
--- a/src/Tax/Canada/T1/FieldNames/QC.hs
+++ b/src/Tax/Canada/T1/FieldNames/QC.hs
@@ -18,7 +18,6 @@
 import Tax.Canada.T1.Types qualified as Page8 (Page8(..))
 import Tax.Canada.T1.Types qualified as MedicalExpenses (MedicalExpenses(..))
 import Tax.Canada.T1.FieldNames.ON qualified as ON
-import Tax.Canada.T1.FieldNames.BC qualified as BC
 
 t1Fields :: T1 FieldConst
 t1Fields = within "form1" Rank2.<$> T1 {
@@ -31,15 +30,18 @@
    page7 = within "Page7" Rank2.<$> page7Fields,
    page8 = within "Page8" Rank2.<$> page8Fields}
 
+page2Fields :: Page2 FieldConst
 page2Fields = ON.page2Fields {
    cai = NoField,
    organ_donor = NoField}
 
+page4Fields :: Page4 FieldConst
 page4Fields = ON.page4Fields{
    line_20810_PRPP = Field ["Line20810", "Amount"] Amount,
    line_21698_Amount = Field ["Line45", "Line21698", "Line_21699_Amount"] Amount,
    line_22300_DeductionPPIP = Field ["Line22300", "Line_22300_Amount"] Amount}
 
+page5Fields :: Page5 FieldConst
 page5Fields = Page5 {
    step4_TaxableIncome = within "Step4" Rank2.<$> step4Fields,
    partA_FederalTax = within "Part_A" Rank2.<$> partA1{column4 = column4, column5 = partA2.column5},
@@ -55,6 +57,7 @@
             toText $ "Line" <> decimal line <> (if isRate then "Rate" else "Amount") <> decimal column
          toText = toStrict . toLazyText
 
+step4Fields :: Step4 FieldConst
 step4Fields = ON.step4Fields {
    line_23600_NetIncome_2 = Field ["Line60", "Amount"] Amount,
    line_24901_SecurityDeductions = Field ["Line24901", "Line_24901_Amount"] Amount,
@@ -62,10 +65,12 @@
    line72_difference = Field ["Line73", "Line_26000_Amount"] Amount,
    line_25999_CapitalGainsReductionAddBack = Field ["Line25999", "Line_25999_Amount"] Amount}
 
+partBFields :: Page5PartB FieldConst
 partBFields = ON.partBFields {
    line_30500 = Field ["Line30500", "Line_30499_Amount"] Amount,
    pageBreakSummary = Field ["Line90", "Amount"] Amount}
 
+page6Fields :: Page6 FieldConst
 page6Fields = ON.page6Fields {
    pageBreakCarry = Field ["Line91", "Amount"] Amount,
    line_31205 = Field ["Line31205", "Line_31205_Amount"] Amount,
@@ -80,16 +85,19 @@
    line_33200_sum = subCalculationFields "Line33200" ["Line_33200_Amount1"] ["Line_33200_Line32Amount2"],
    line120_taxCreditRate = Field ["Line124", "Percent"] $ Constant 0.15 Percent}
 
+page6MedicalExpensesFields :: MedicalExpenses FieldConst
 page6MedicalExpensesFields = ON.page6MedicalExpensesFields {
    taxableIncome = Field ["Line118", "Amount1"] Amount,
    taxableIncomeFraction = Field ["Line118", "Amount2"] Amount,
    MedicalExpenses.threshold = Field ["Line119", "Amount"] Amount,
    difference = Field ["Line120", "Amount"] Amount}
 
+page7Fields :: Page7 FieldConst
 page7Fields = Page7 {
    partC_NetFederalTax = within "PartC" Rank2.<$> partCFields,
    step6_RefundOrBalanceOwing = within "Step6" Rank2.<$> page7step6Fields}
 
+partCFields :: Page7PartC FieldConst
 partCFields = ON.partCFields {
    tax_copy = Field ["Line128", "Amount"] Amount,
    credits_copy = Field ["Line131", "Amount"] Amount,
@@ -101,10 +109,12 @@
    line137_sum = Field ["Line141", "Amount"] Amount,
    line138_logging = Field ["Line142", "Amount"] Amount}
 
+page7step6Fields :: Page7Step6 FieldConst
 page7step6Fields = ON.page7step6Fields {
    tax_copy = Field ["Line152", "Amount"] Amount,
    line_42100_CPPContributions = NoField}
 
+page8Fields :: Page8 FieldConst
 page8Fields = ON.page8Fields {
    Page8.step6_RefundOrBalanceOwing = within "Step6-Continued" Rank2.<$> page8step6Fields,
    line1_ONOpportunitiesFund = NoField,
@@ -113,6 +123,7 @@
    line_48400_Refund = Field ["Refund_or_Balancing-owing", "Line48400", "Line_48400_Amount"] Amount,
    line_48500_BalanceOwing = Field ["Refund_or_Balancing-owing", "Line48500", "Line_48500_Amount"] Amount}
 
+page8step6Fields :: Page8Step6 FieldConst
 page8step6Fields = ON.page8step6Fields {
    line_43500_totalpayable = Field ["Line157", "Amount"] Amount,
    line_43800_TaxTransferQC = Field ["Line43800", "Line_43800_Amount"] Amount,
diff --git a/src/Tax/Canada/T1/FieldNames/YT.hs b/src/Tax/Canada/T1/FieldNames/YT.hs
--- a/src/Tax/Canada/T1/FieldNames/YT.hs
+++ b/src/Tax/Canada/T1/FieldNames/YT.hs
@@ -7,8 +7,7 @@
 
 import Rank2 qualified
 
-import Tax.FDF (FieldConst (Field, NoField), Entry (..), within)
-import Tax.Canada.Shared (subCalculationFields)
+import Tax.FDF (FieldConst (Field), Entry (..), within)
 import Tax.Canada.T1.Types
 import Tax.Canada.T1.Types qualified as Page8 (Page8(..))
 import Tax.Canada.T1.FieldNames.BC qualified as BC
@@ -21,21 +20,26 @@
    page7 = within "form1" . within "Page7" Rank2.<$> page7Fields,
    page8 = within "form1" . within "Page8" Rank2.<$> page8Fields}
 
+page7Fields :: Page7 FieldConst
 page7Fields = Page7 {
    partC_NetFederalTax = within "PartC" Rank2.<$> partCFields,
    step6_RefundOrBalanceOwing = within "Step6" Rank2.<$> page7step6Fields}
 
+partCFields :: Page7PartC FieldConst
 partCFields = ON.partCFields {
    line_40900 = Field ["Line4100", "Line40900", "Line_40900_Amount"] Amount,
    line_41000 = Field ["Line4100", "Line_41000_Amount"] Amount}
 
+page7step6Fields :: Page7Step6 FieldConst
 page7step6Fields = ON.page7step6Fields {
    line_43200_FirstNationsTax = Field ["Line43200", "Line_43200_Amount"] Amount}
 
+page8Fields :: Page8 FieldConst
 page8Fields = BC.page8Fields {
    Page8.step6_RefundOrBalanceOwing = within "Step6-Cont" Rank2.<$> page8step6Fields,
    taxPreparer = within "Line_49000_IfFeeWasCharged" Rank2.<$> BC.taxPreparerFields}
 
+page8step6Fields :: Page8Step6 FieldConst
 page8step6Fields = ON.page8step6Fields {
    line_43500_totalpayable = Field ["Line155", "Amount"] Amount,
    line_44100 = Field ["Line44100", "Line_44000_Amount"] Amount,
diff --git a/src/Tax/Canada/T1/Fix.hs b/src/Tax/Canada/T1/Fix.hs
--- a/src/Tax/Canada/T1/Fix.hs
+++ b/src/Tax/Canada/T1/Fix.hs
@@ -10,17 +10,16 @@
 module Tax.Canada.T1.Fix (T1, fixT1) where
 
 import Control.Applicative ((<|>))
-import Data.Fixed (Centi)
 import Data.Maybe (fromMaybe)
-import Data.Text (Text)
 import Data.Time.Calendar (Year, dayPeriod)
 import GHC.Stack (HasCallStack)
-import Rank2 qualified
 
 import Tax.Canada.T1.Types
 import Tax.Canada.Shared (fixSubCalculation, fixTaxIncomeBracket, SubCalculation(result), TaxIncomeBracket (equalsTax))
 import Tax.Util (difference, fixEq, fractionOf, nonNegativeDifference, totalOf)
 
+import Prelude hiding (floor, ceiling)
+
 fixT1 :: HasCallStack => T1 Maybe -> T1 Maybe
 fixT1 = fixEq $ \t1@T1{..}-> T1{page1 = fixPage1 page1,
                                 page2 = fixPage2 page2,
@@ -141,7 +140,7 @@
    step6_RefundOrBalanceOwing = fixPage7Step6 t1 step6_RefundOrBalanceOwing}
 
 fixPage8 :: T1 Maybe -> Page8 Maybe -> Page8 Maybe
-fixPage8 t1 = fixEq $ \page@Page8{..}-> Page8{
+fixPage8 t1 = fixEq $ \Page8{..}-> Page8{
    step6_RefundOrBalanceOwing = fixPage8Step6 t1 step6_RefundOrBalanceOwing,
    line_48400_Refund = step6_RefundOrBalanceOwing.line164_Refund_or_BalanceOwing
                       >>= \x-> if x < 0 then Just (negate x) else Nothing,
@@ -169,7 +168,7 @@
    line_26000_TaxableIncome = totalOf [line72_difference, line_25999_CapitalGainsReductionAddBack]}
 
 fixPage5PartA :: HasCallStack => T1 Maybe -> Page5PartA Maybe -> Page5PartA Maybe
-fixPage5PartA t1 = fixEq $ \part@Page5PartA{..}-> part{
+fixPage5PartA t1 = fixEq $ \part-> Page5PartA{
    column1 = fixTaxIncomeBracket income (Just part.column2) part.column1,
    column2 = fixTaxIncomeBracket income (Just part.column3) part.column2,
    column3 = fixTaxIncomeBracket income (Just part.column4) part.column3,
diff --git a/src/Tax/Canada/T1/Types.hs b/src/Tax/Canada/T1/Types.hs
--- a/src/Tax/Canada/T1/Types.hs
+++ b/src/Tax/Canada/T1/Types.hs
@@ -17,7 +17,6 @@
 module Tax.Canada.T1.Types where
 
 import Data.Fixed (Centi)
-import Data.Monoid (Ap(Ap, getAp))
 import Data.Text (Text)
 import Data.Time (Day)
 import Data.CAProvinceCodes qualified as Province
diff --git a/src/Tax/Canada/T4.hs b/src/Tax/Canada/T4.hs
--- a/src/Tax/Canada/T4.hs
+++ b/src/Tax/Canada/T4.hs
@@ -20,7 +20,7 @@
 import Rank2.TH qualified
 import Transformation.Shallow.TH qualified
 
-import Tax.FDF (FieldConst (Field, NoField), Entry (Amount, Province, Textual, Year), within)
+import Tax.FDF (FieldConst (Field), Entry (Amount, Province, Textual, Year), within)
 
 data T4 line = T4{
    slip1 :: T4Slip line,
diff --git a/src/Tax/FDF.hs b/src/Tax/FDF.hs
--- a/src/Tax/FDF.hs
+++ b/src/Tax/FDF.hs
@@ -11,10 +11,9 @@
 module Tax.FDF (FDFs, FieldConst(..), Entry(..),
                 mapForm, mapForm2, mapForms, load, loadAll, store, storeAll, update, updateAll, formKeys, within) where
 
-import Control.Monad (join)
 import Data.Biapplicative (biliftA2, biliftA3)
 import Data.Bifunctor (bimap)
-import Data.Bitraversable (bisequence, bitraverse)
+import Data.Bitraversable (bisequence)
 import Data.CAProvinceCodes qualified as Province
 import Data.Char (isDigit, isSpace)
 import Data.Fixed (Centi)
@@ -28,9 +27,8 @@
 import Data.Text (Text)
 import Data.Text qualified as Text
 import Data.Time (Day, MonthOfYear, defaultTimeLocale, formatTime, parseTimeM)
-import Data.Void (Void)
 import Rank2 qualified
-import Text.FDF (FDF (FDF, body), Field, foldMapWithKey, mapWithKey, parse, serialize, traverseWithKey)
+import Text.FDF (FDF, foldMapWithKey, mapWithKey)
 import Text.Read (readEither, readMaybe)
 
 -- | A form field path serves to uniquely identify and locate the field inside a form
@@ -162,7 +160,7 @@
         pairKey Field {path, entry = Switch' leaf} (Just True) = Const $ Just (addIndex <$> (path ++ [leaf]), Right "1")
         pairKey Field {path, entry = Switch' leaf} (Just False) =
           Const $ Just (map addIndex path ++ [leaf <> "[1]"], Right "1")
-        pairKey Field {path, entry = Constant c e} (Just v)
+        pairKey Field {path, entry = Constant c _} (Just v)
           | c == v = Const Nothing
           | otherwise = Const $ Just (path, Left ("Trying to replace constant field " ++ show (path, c) ++ " with " ++ show v))
         pairKey Field {path, entry} v = Const $ Just (addIndex <$> path, maybe (Right "") (fromEntry entry) v)
@@ -188,7 +186,7 @@
 fromFieldMap fieldForm fieldMap = Rank2.traverse (fill fieldMap) fieldForm
 
 fill :: forall a. Map [Text] Text -> FieldConst a -> Either String (Maybe a)
-fill fieldValues NoField = Right Nothing
+fill _ NoField = Right Nothing
 fill fieldValues Field {path, entry}
   | Just v <- Map.lookup path fieldValues = toEntry entry v
   | Just v <- Map.lookup (addIndex <$> path) fieldValues = toEntry entry v
@@ -256,8 +254,8 @@
   | Right n <- readEither $ Text.unpack v, n > 0, x:_ <- drop (n - 1) values = Right $ Just x
   | otherwise = Left ("Bad radio button value: " <> show (e, v))
 toEntry e@RadioButtons{} v = Left (show (e, v))
-toEntry e@(Switch a b leaf) v = Left (show (e, v))
-toEntry e@(Switch' leaf) v = Left (show (e, v))
+toEntry e@Switch{} v = Left (show (e, v))
+toEntry e@Switch'{} v = Left (show (e, v))
 
 addIndex :: Text -> Text
 addIndex key
diff --git a/src/Tax/Util.hs b/src/Tax/Util.hs
--- a/src/Tax/Util.hs
+++ b/src/Tax/Util.hs
@@ -2,8 +2,7 @@
 module Tax.Util where
 
 import Data.Fixed (Centi)
-import Data.List.NonEmpty (nonEmpty)
-import Data.Maybe (fromMaybe, mapMaybe)
+import Data.Maybe (fromMaybe)
 
 -- | Repeatedly apply the function to the argument until it reaches the fixed point.
 fixEq :: Eq a => (a -> a) -> a -> a
@@ -27,7 +26,8 @@
 -- | Non-negative subtraction under 'Maybe', returning @Just 0@ instead of negative results
 nonNegativeDifference :: Maybe Centi -> Maybe Centi -> Maybe Centi
 nonNegativeDifference Nothing Nothing = Nothing
-nonNegativeDifference a b = Just (max 0 $ fromMaybe 0 a - fromMaybe 0 b)
+nonNegativeDifference Nothing (Just x) | x >= 0 = Nothing
+nonNegativeDifference x y = Just (max 0 $ fromMaybe 0 x - fromMaybe 0 y)
 
 -- | Multiplication under 'Maybe'
 fractionOf :: Maybe Rational -> Maybe Centi -> Maybe Centi
diff --git a/test/Properties.hs b/test/Properties.hs
--- a/test/Properties.hs
+++ b/test/Properties.hs
@@ -11,7 +11,6 @@
 import Tax.Canada.Province.AB qualified as AB
 import Tax.Canada.Province.BC qualified as BC
 import Tax.Canada.Province.MB qualified as MB
-import Tax.Canada.Province.NB qualified as NB
 import Tax.Canada.Province.NL qualified as NL
 import Tax.Canada.Province.ON qualified as ON
 import Tax.Canada.Province.PE qualified as PE
@@ -19,7 +18,7 @@
 import Tax.Canada.Territory.NT qualified as NT
 import Tax.Canada.Territory.NU qualified as NU
 import Tax.Canada.Territory.YT qualified as YT
-import Tax.Canada.T1 (T1, fixT1)
+import Tax.Canada.T1 (fixT1)
 import Tax.Canada.T4 (t4Fields)
 import Tax.Canada.Federal qualified as Federal
 import Tax.Canada.Federal.Schedule6 (schedule6Fields)
@@ -27,7 +26,7 @@
 import Tax.Canada.Federal.Schedule8 (schedule8Fields)
 import Tax.Canada.Federal.Schedule9 (schedule9Fields)
 import Tax.Canada.Federal.Schedule11 (schedule11Fields)
-import Tax.FDF as FDF
+import Tax.FDF qualified as FDF
 import Paths_canadian_income_tax (getDataDir)
 
 import Test.Transformations qualified as Transformations
@@ -35,26 +34,24 @@
 import Data.ByteString qualified as ByteString
 import Data.Char qualified as Char
 import Data.Either (isLeft, isRight)
-import Data.Functor.Const (Const (Const, getConst))
 import Data.List qualified as List
 import Data.Maybe (fromMaybe)
 import Data.Monoid.Textual qualified as Textual
 import Data.Semigroup.Cancellative (isSuffixOf, stripPrefix)
-import Data.Semigroup (All (All, getAll))
 import Data.Text (Text, isInfixOf, stripSuffix)
 import Rank2 qualified
 import System.Directory (listDirectory)
 import System.Exit (die)
-import System.FilePath.Posix (combine, isExtensionOf)
+import System.FilePath.Posix (combine)
 import Transformation.Shallow qualified as Shallow
-import Text.FDF (FDF (body), Field, parse)
+import Text.FDF (FDF, parse)
 import Text.FDF qualified
 
 import Hedgehog (Gen, Property, (===), annotateShow, assert, forAll, property)
-import Hedgehog.Gen qualified as Gen
 import Test.Tasty
 import Test.Tasty.Hedgehog
 
+main :: IO ()
 main = do
   dataDir <- getDataDir
   fdfMaps <- traverse (readFDFs . combine dataDir) ["fdf", "fdf/T1", "fdf/428", "fdf/479"]
@@ -129,17 +126,17 @@
 
 checkFormIdempotent :: (Eq (g Maybe), Show (g Maybe),
                         Rank2.Applicative g, Shallow.Traversable Transformations.Gen g)
-                    => g FieldConst -> (g Maybe -> g Maybe) -> Property
+                    => g FDF.FieldConst -> (g Maybe -> g Maybe) -> Property
 checkFormIdempotent fields f = checkIdempotent (generateForm fields) f
 
 checkFederalFormIdempotent :: (Eq (g Maybe), Show (g Maybe),
                                Rank2.Applicative g, Shallow.Traversable Transformations.Gen g)
-                           => g FieldConst -> (Federal.InputForms Maybe -> g Maybe -> g Maybe) -> Property
+                           => g FDF.FieldConst -> (Federal.InputForms Maybe -> g Maybe -> g Maybe) -> Property
 checkFederalFormIdempotent fields f = checkIdempotent (generateForm fields) (f mempty)
 
 checkFormFields :: (Eq (g Maybe), Show (g Maybe),
                     Rank2.Applicative g, Shallow.Traversable Transformations.Gen g)
-                => g FieldConst -> Maybe FDF -> Property
+                => g FDF.FieldConst -> Maybe FDF -> Property
 checkFormFields _ Nothing = error "Missing FDF template"
 checkFormFields fields (Just fdf) = property $ do
   annotateShow $ FDF.load fields fdf
@@ -159,7 +156,7 @@
   FDF.load fields fdf' === Right form
   List.sort (noCheckbox formKeys) === List.sort (noCheckbox $ filter (\x-> any (`List.isPrefixOf` x) keyHeads) fdfKeys)
 
-generateForm :: (Rank2.Applicative g, Shallow.Traversable Transformations.Gen g) => g FieldConst -> Gen (g Maybe)
+generateForm :: (Rank2.Applicative g, Shallow.Traversable Transformations.Gen g) => g FDF.FieldConst -> Gen (g Maybe)
 generateForm = Shallow.traverse Transformations.Gen
 
 checkIdempotent :: (Eq a, Show a) => Gen a -> (a -> a) -> Property
diff --git a/test/Regression.hs b/test/Regression.hs
--- a/test/Regression.hs
+++ b/test/Regression.hs
@@ -12,32 +12,24 @@
 import Tax.Canada.FormKey (FormKey)
 import Tax.Canada.FormKey qualified as FormKey
 import Tax.Canada.Province.ON qualified as ON
-import Tax.Canada.Province.AB qualified as AB (t1Fields)
-import Tax.Canada.Province.BC qualified as BC (t1Fields)
-import Tax.Canada.T1 (T1, fixT1)
-import Tax.FDF as FDF
+import Tax.Canada.T1 (fixT1)
+import Tax.FDF qualified as FDF
 
 import Control.Monad.IO.Class (liftIO)
 import Data.ByteString qualified as ByteString
 import Data.ByteString.Lazy (fromStrict)
 import Data.Foldable (toList)
-import Data.Functor.Const (Const (Const, getConst))
 import Data.List qualified as List
 import Data.Map qualified as Map
-import Data.Maybe (fromMaybe)
-import Data.Semigroup (All (All, getAll))
-import Data.Text (Text)
-import Data.Text qualified as Text
-import Rank2 qualified
 import System.Directory (doesDirectoryExist, listDirectory)
 import System.Exit (die)
 import System.FilePath.Posix (combine)
-import Text.FDF (FDF, parse, serialize)
-import Text.FDF qualified
+import Text.FDF (parse, serialize)
 
 import Test.Tasty
 import Test.Tasty.Golden
 
+main :: IO ()
 main = listDirectory inputDir >>= traverse test >>= defaultMain . testGroup "Regression"
 
 rootDir, inputDir, outputDir, referenceDir :: FilePath
@@ -81,11 +73,11 @@
        Right filled
          | let fdfOutputs = fromStrict . serialize <$> filled
                diff ref new = ["diff", "-uw", ref, new]
-               compare key fdfOutput
+               verify key fdfOutput
                  | let Just fileName = List.find ((key ==) . formKey) fdfFileNames
-                         = pure $ goldenVsStringDiff fileName diff (combine referenceDir $ combine path fileName)
-                           $ pure fdfOutput
-           -> testGroup path . toList <$> Map.traverseWithKey compare fdfOutputs
+                 = pure $ goldenVsStringDiff fileName diff (combine referenceDir $ combine path fileName)
+                   $ pure fdfOutput
+           -> testGroup path . toList <$> Map.traverseWithKey verify fdfOutputs
 
 
 formKey :: FilePath -> FormKey
diff --git a/test/Test/Transformations.hs b/test/Test/Transformations.hs
--- a/test/Test/Transformations.hs
+++ b/test/Test/Transformations.hs
@@ -15,7 +15,6 @@
 
 import Data.Functor.Compose
 import Data.Void (Void)
-import Data.Word (Word)
 import Data.Text (Text)
 import Data.Time (Day)
 import Data.Time.Calendar (fromGregorian)
@@ -27,8 +26,6 @@
 
 import Transformation (Transformation (Domain, Codomain), At)
 import Transformation qualified
-import Transformation.Shallow qualified as Shallow
-import Transformation.Shallow.TH qualified as Shallow.TH
 
 import Tax.FDF (FieldConst (Field, NoField), Entry (Constant))
 import Tax.Canada.T1 (LanguageOfCorrespondence, MaritalStatus)
diff --git a/web/Main.hs b/web/Main.hs
--- a/web/Main.hs
+++ b/web/Main.hs
@@ -1,15 +1,15 @@
 {-# LANGUAGE ImportQualifiedPost #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedRecordDot #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Main where
 
 import Codec.Archive.Zip (addEntryToArchive, emptyArchive, fromArchive, toEntry)
 import Control.Category ((>>>))
-import Control.Monad (forM, join)
+import Control.Monad (forM)
 import Control.Monad.IO.Class (liftIO)
-import Control.Exception (assert)
 import Data.Aeson (decode)
 import Data.Bifunctor (first)
 import Data.ByteString (ByteString)
@@ -18,7 +18,6 @@
 import Data.ByteString.Lazy qualified as ByteString.Lazy
 import Data.Fixed (Centi)
 import Data.Foldable (fold, toList)
-import Data.Functor.Compose (Compose(..))
 import Data.List qualified as List
 import Data.Map.Lazy (Map)
 import Data.Map.Lazy qualified as Map
@@ -30,13 +29,15 @@
 import Data.Text (Text)
 import Data.Text qualified as Text
 import Data.Text.Lazy qualified as Text.Lazy
-import Network.HTTP.Types.Status (ok200, internalServerError500,
+import Network.HTTP.Types.Status (statusCode, ok200, internalServerError500,
                                   notFound404, unsupportedMediaType415, unprocessableEntity422)
 import Network.Wai.Middleware.RequestLogger
 import Network.Wai.Middleware.Static
 import Network.Wai.Parse (FileInfo (..))
 import System.Directory (removeDirectoryRecursive)
 import System.FilePath.Posix ((</>))
+import System.Log.FastLogger (LogType'(LogFile), FileLogSpec(FileLogSpec), toLogStr, withTimedFastLogger)
+import System.Log.FastLogger.Date (newTimeCache, simpleTimeFormat)
 import System.Posix.Temp (mkdtemp)
 import Text.FDF qualified as FDF (mapWithKey, parse, serialize)
 import Text.Read (readMaybe)
@@ -48,9 +49,10 @@
 import Tax.Canada.Federal qualified as Federal
 import Tax.Canada.FormKey (FormKey)
 import Tax.Canada.FormKey qualified as FormKey
-import Tax.FDF qualified as FDF
 import Tax.PDFtk (fdf2pdf, pdfFile2fdf)
 
+import Prelude hiding (log)
+
 main :: IO ()
 main = do
   dataDir <- getDataDir
@@ -62,7 +64,11 @@
   let t4fdf = case FDF.parse t4fdfBytes of
         Left err -> error ("Can't load built-in T4 FDF: " <> err)
         Right parsed -> parsed
-  scotty 3000 $ do
+      logDestination = LogFile (FileLogSpec "taxell.log" (2^(20::Int)) 16) 1024
+  timer <- newTimeCache simpleTimeFormat
+  withTimedFastLogger timer logDestination
+    $ \l-> let log msg = liftIO $ l (\timestamp-> toLogStr timestamp <> " - " <> msg <> "\n") in (log "Started" >>)
+    $ scotty 3000 $ do
    middleware logStdoutDev
    get "/" $ do
       setHeader "Content-Type" "text/html; charset=utf-8"
@@ -75,6 +81,8 @@
       provinceCode <- pathParam "province"
       t4param <- formParamMaybe "T4"
       pdfFiles <- files
+      log ("Save " <> toLogStr provinceCode <> ": "
+           <> maybe "no" (const "with") t4param <> " T4s, " <> toLogStr (show (fst <$> pdfFiles)))
       now <- liftIO $ round . nominalDiffTimeToSeconds <$> getPOSIXTime
       let pdfArchive = foldr addPDF emptyArchive pdfFiles
           addPDF (_, FileInfo name _ c) = addEntryToArchive (toEntry (fromUTF8 name) now c)
@@ -98,11 +106,13 @@
           resolveForm (key, FileInfo name _ content)
             | Just formKey <- readMaybe (Text.unpack key) = Right (formKey, (fromUTF8 name, content))
             | otherwise = Left key
-      pdfFiles <- files >>= \fs-> case traverse resolveForm fs of
+      pdfFiles <- (traverse resolveForm <$> files) >>= \case
         Left name -> status notFound404
                      >> text ("No such form key as " <> Text.Lazy.fromStrict name)
                      >> finish
         Right fs -> pure fs
+      log ("Complete " <> toLogStr provinceCode <> ": "
+           <> toLogStr (length t4m) <> " T4s, " <> toLogStr (show (fst <$> pdfFiles)))
       let allPdfFiles = Map.toList (Map.fromList pdfFiles <> emptyForms)
       dir <- liftIO $ mkdtemp "tax"
       fdfBytes <- liftIO $ fmap sequenceA $ forM allPdfFiles $ \(key, (name, content))-> do
@@ -112,7 +122,7 @@
         pure ((,) key <$> fdf)
       case do fdfs <- first ((,) unsupportedMediaType415)
                       $ fdfBytes >>= traverse (traverse $ Lazy.toStrict >>> FDF.parse)
-              let (inputFDFs, ioFDFs) = List.partition ((FormKey.T4 ==) . fst) fdfs
+              let (inputFDFs, _ioFDFs) = List.partition ((FormKey.T4 ==) . fst) fdfs
                   inputT4s = foldMap injectT4 t4m
                   injectT4 values = [(FormKey.T4, FDF.mapWithKey injectT4box t4fdf)]
                     where injectT4box keyPath ""
@@ -121,8 +131,11 @@
                           injectT4box _ v = v
               inputForms <- first ((,) unprocessableEntity422) $ Federal.loadInputForms $ inputFDFs <> inputT4s
               first ((,) unprocessableEntity422) $ completeRelevantForms province inputForms (Map.fromList fdfs)
-        of Left (code, err) -> status code >> text (fromString err)
+        of Left (code, err) ->
+             log ("Error " <> toLogStr code.statusCode <> ": " <> toLogStr err)
+             >> status code >> text (fromString err)
            Right fdfs' -> do
+             log ("Completed " <> toLogStr provinceCode <> ": " <> toLogStr (show (Map.keys fdfs')))
              let fdfBytes' = Lazy.fromStrict . FDF.serialize <$> fdfs'
                  replaceContent :: FormKey -> Lazy.ByteString
                                 -> IO (Either String (FilePath, Lazy.ByteString))
@@ -132,6 +145,7 @@
              pdfFiles' <- liftIO $ Map.traverseWithKey replaceContent fdfBytes'
              case toList <$> sequenceA pdfFiles' of
                Left err -> do
+                 log ("Error 500: " <> toLogStr err)
                  status internalServerError500 >> text (fromString err)
                Right [(name, pdf)] -> do
                  status ok200
