diff --git a/Aws/DynamoDb/Commands/Scan.hs b/Aws/DynamoDb/Commands/Scan.hs
--- a/Aws/DynamoDb/Commands/Scan.hs
+++ b/Aws/DynamoDb/Commands/Scan.hs
@@ -36,20 +36,24 @@
 
 -- | A Scan command that uses primary keys for an expedient scan.
 data Scan = Scan {
-      sTableName     :: T.Text
+      sTableName      :: T.Text
     -- ^ Required.
-    , sFilter        :: Conditions
+    , sConsistentRead :: Bool
+    -- ^ Whether to require a consistent read
+    , sFilter         :: Conditions
     -- ^ Whether to filter results before returning to client
-    , sStartKey      :: Maybe [Attribute]
+    , sStartKey       :: Maybe [Attribute]
     -- ^ Exclusive start key to resume a previous query.
-    , sLimit         :: Maybe Int
+    , sLimit          :: Maybe Int
     -- ^ Whether to limit result set size
-    , sSelect        :: QuerySelect
+    , sIndex          :: Maybe T.Text
+    -- ^ Optional. Index to 'Scan'
+    , sSelect         :: QuerySelect
     -- ^ What to return from 'Scan'
-    , sRetCons       :: ReturnConsumption
-    , sSegment       :: Int
+    , sRetCons        :: ReturnConsumption
+    , sSegment        :: Int
     -- ^ Segment number, starting at 0, for parallel queries.
-    , sTotalSegments :: Int
+    , sTotalSegments  :: Int
     -- ^ Total number of parallel segments. 1 means sequential scan.
     } deriving (Eq,Show,Read,Ord,Typeable)
 
@@ -57,7 +61,7 @@
 -- | Construct a minimal 'Scan' request.
 scan :: T.Text                   -- ^ Table name
      -> Scan
-scan tn = Scan tn def Nothing Nothing def def 0 1
+scan tn = Scan tn False def Nothing Nothing Nothing def def 0 1
 
 
 -- | Response to a 'Scan' query.
@@ -76,6 +80,7 @@
       catMaybes
         [ (("ExclusiveStartKey" .= ) . attributesJson) <$> sStartKey
         , ("Limit" .= ) <$> sLimit
+        , ("IndexName" .= ) <$> sIndex
         ] ++
       conditionsJson "ScanFilter" sFilter ++
       querySelectJson sSelect ++
@@ -83,6 +88,7 @@
       , "ReturnConsumedCapacity" .= sRetCons
       , "Segment" .= sSegment
       , "TotalSegments" .= sTotalSegments
+      , "ConsistentRead" .= sConsistentRead
       ]
 
 
diff --git a/Aws/DynamoDb/Commands/UpdateItem.hs b/Aws/DynamoDb/Commands/UpdateItem.hs
--- a/Aws/DynamoDb/Commands/UpdateItem.hs
+++ b/Aws/DynamoDb/Commands/UpdateItem.hs
@@ -79,7 +79,10 @@
 instance ToJSON AttributeUpdates where
     toJSON = object . map mk
         where
-          mk AttributeUpdate{..} = (attrName auAttr) .= object
+          mk AttributeUpdate { auAction = UDelete, auAttr = auAttr } =
+            (attrName auAttr) .= object
+            ["Action" .= UDelete]
+          mk AttributeUpdate { .. } = (attrName auAttr) .= object
             ["Value" .= (attrVal auAttr), "Action" .= auAction]
 
 
diff --git a/Aws/DynamoDb/Core.hs b/Aws/DynamoDb/Core.hs
--- a/Aws/DynamoDb/Core.hs
+++ b/Aws/DynamoDb/Core.hs
@@ -31,6 +31,7 @@
     , ddbUsWest1
     , ddbUsWest2
     , ddbEuWest1
+    , ddbEuCentral1
     , ddbApNe1
     , ddbApSe1
     , ddbApSe2
@@ -44,6 +45,7 @@
     , DynVal(..)
     , toValue, fromValue
     , Bin (..)
+    , OldBool(..)
 
     -- * Defining new 'DynVal' instances
     , DynData(..)
@@ -150,6 +152,7 @@
 import qualified Data.Text.Encoding           as T
 import           Data.Time
 import           Data.Typeable
+import qualified Data.Vector                  as V
 import           Data.Word
 import qualified Network.HTTP.Conduit         as HTTP
 import qualified Network.HTTP.Types           as HTTP
@@ -158,6 +161,11 @@
 import           Aws.Core
 -------------------------------------------------------------------------------
 
+-------------------------------------------------------------------------------
+-- | Boolean values stored in DynamoDb. Only used in defining new
+-- 'DynVal' instances.
+newtype DynBool = DynBool { unDynBool :: Bool }
+    deriving (Eq,Show,Read,Ord,Typeable)
 
 
 -------------------------------------------------------------------------------
@@ -195,6 +203,22 @@
     fromData :: a -> DValue
     toData :: DValue -> Maybe a
 
+instance DynData DynBool where
+    fromData (DynBool i) = DBool i
+    toData (DBool i) = Just $ DynBool i
+    toData (DNum i) = DynBool `fmap` do
+        (i' :: Int) <- toIntegral i
+        case i' of
+          0 -> return False
+          1 -> return True
+          _ -> Nothing
+    toData _ = Nothing
+
+instance DynData (S.Set DynBool) where
+    fromData set = DBoolSet (S.map unDynBool set)
+    toData (DBoolSet i) = Just $ S.map DynBool i
+    toData _ = Nothing
+
 instance DynData DynNumber where
     fromData (DynNumber i) = DNum i
     toData (DNum i) = Just $ DynNumber i
@@ -273,6 +297,10 @@
     fromRep = Just
     toRep   = id
 
+instance DynVal Bool where
+    type DynRep Bool = DynBool
+    fromRep (DynBool i) = Just i
+    toRep i = DynBool i
 
 instance DynVal Int where
     type DynRep Int = DynNumber
@@ -400,19 +428,7 @@
       diff = fromRational ((toRational secs) / pico)
 
 
--- | Encoded as 0 and 1.
-instance DynVal Bool where
-    type DynRep Bool = DynNumber
-    fromRep (DynNumber i) = do
-        (i' :: Int) <- toIntegral i
-        case i' of
-          0 -> return False
-          1 -> return True
-          _ -> Nothing
-    toRep b = DynNumber (if b then 1 else 0)
 
-
-
 -- | Type wrapper for binary data to be written to DynamoDB. Wrap any
 -- 'Serialize' instance in there and 'DynVal' will know how to
 -- automatically handle conversions in binary form.
@@ -426,8 +442,19 @@
     fromRep (DynBinary i) = either (const Nothing) (Just . Bin) $
                             Ser.decode i
 
+newtype OldBool = OldBool Bool
 
+instance DynVal OldBool where
+    type DynRep OldBool = DynNumber
+    fromRep (DynNumber i) = OldBool `fmap` do
+        (i' :: Int) <- toIntegral i
+        case i' of
+          0 -> return False
+          1 -> return True
+          _ -> Nothing
+    toRep (OldBool b) = DynNumber (if b then 1 else 0)
 
+
 -------------------------------------------------------------------------------
 -- | Encode a Haskell value.
 toValue :: DynVal a  => a -> DValue
@@ -448,7 +475,8 @@
 -- | Value types natively recognized by DynamoDb. We pretty much
 -- exactly reflect the AWS API onto Haskell types.
 data DValue
-    = DNum Scientific
+    = DNull
+    | DNum Scientific
     | DString T.Text
     | DBinary B.ByteString
     -- ^ Binary data will automatically be base64 marshalled.
@@ -456,6 +484,11 @@
     | DStringSet (S.Set T.Text)
     | DBinSet (S.Set B.ByteString)
     -- ^ Binary data will automatically be base64 marshalled.
+    | DBool Bool
+    | DBoolSet (S.Set Bool)
+    -- ^ Composite data
+    | DList (V.Vector DValue)
+    | DMap (M.Map T.Text DValue)
     deriving (Eq,Show,Read,Ord,Typeable)
 
 
@@ -560,12 +593,16 @@
 
 
 instance ToJSON DValue where
+    toJSON DNull = object ["NULL" .= True]
     toJSON (DNum i) = object ["N" .= showT i]
     toJSON (DString i) = object ["S" .= i]
     toJSON (DBinary i) = object ["B" .= (T.decodeUtf8 $ Base64.encode i)]
     toJSON (DNumSet i) = object ["NS" .= map showT (S.toList i)]
     toJSON (DStringSet i) = object ["SS" .= S.toList i]
     toJSON (DBinSet i) = object ["BS" .= map (T.decodeUtf8 . Base64.encode) (S.toList i)]
+    toJSON (DBool i) = object ["BOOL" .= i]
+    toJSON (DList i) = object ["L" .= i]
+    toJSON (DMap i) = object ["M" .= i]
     toJSON x = error $ "aws: bug: DynamoDB can't handle " ++ show x
 
 
@@ -573,6 +610,7 @@
     parseJSON o = do
       (obj :: [(T.Text, Value)]) <- M.toList `liftM` parseJSON o
       case obj of
+        [("NULL", _)] -> return DNull
         [("N", numStr)] -> DNum <$> parseScientific numStr
         [("S", str)] -> DString <$> parseJSON str
         [("B", bin)] -> do
@@ -585,6 +623,9 @@
             xs <- mapM (either fail return . Base64.decode . T.encodeUtf8)
                   =<< parseJSON s
             return $ DBinSet $ S.fromList xs
+        [("BOOL", b)] -> DBool <$> parseJSON b
+        [("L", attrs)] -> DList <$> parseJSON attrs
+        [("M", attrs)] -> DMap <$> parseJSON attrs
 
         x -> fail $ "aws: unknown dynamodb value: " ++ show x
 
@@ -740,8 +781,11 @@
 ddbUsWest2 = Region "dynamodb.us-west-2.amazonaws.com" "us-west-2"
 
 ddbEuWest1 :: Region
-ddbEuWest1 = Region "dynamodb.eu-west-1.amazonaws.com" "us-west-1"
+ddbEuWest1 = Region "dynamodb.eu-west-1.amazonaws.com" "eu-west-1"
 
+ddbEuCentral1 :: Region
+ddbEuCentral1 = Region "dynamodb.eu-central-1.amazonaws.com" "eu-central-1"
+
 ddbApNe1 :: Region
 ddbApNe1 = Region "dynamodb.ap-northeast-1.amazonaws.com" "ap-northeast-1"
 
@@ -1112,12 +1156,17 @@
     dynSize :: a -> Int
 
 instance DynSize DValue where
+    dynSize DNull = 8
+    dynSize (DBool _) = 8
+    dynSize (DBoolSet s) = sum $ map (dynSize . DBool) $ S.toList s
     dynSize (DNum _) = 8
     dynSize (DString a) = T.length a
     dynSize (DBinary bs) = T.length . T.decodeUtf8 $ Base64.encode bs
     dynSize (DNumSet s) = 8 * S.size s
     dynSize (DStringSet s) = sum $ map (dynSize . DString) $ S.toList s
     dynSize (DBinSet s) = sum $ map (dynSize . DBinary) $ S.toList s
+    dynSize (DList s) = sum $ map dynSize $ V.toList s
+    dynSize (DMap s) = sum $ map dynSize $ M.elems s
 
 instance DynSize Attribute where
     dynSize (Attribute k v) = T.length k + dynSize v
@@ -1305,9 +1354,3 @@
 -- instance.
 fromItem :: FromDynItem a => Item -> Either String a
 fromItem i = runParser (parseItem i) Left Right
-
-
-
-
-
-
diff --git a/Aws/Iam/Commands.hs b/Aws/Iam/Commands.hs
--- a/Aws/Iam/Commands.hs
+++ b/Aws/Iam/Commands.hs
@@ -7,6 +7,7 @@
     , module Aws.Iam.Commands.GetUser
     , module Aws.Iam.Commands.GetUserPolicy
     , module Aws.Iam.Commands.ListAccessKeys
+    , module Aws.Iam.Commands.ListMfaDevices
     , module Aws.Iam.Commands.ListUserPolicies
     , module Aws.Iam.Commands.ListUsers
     , module Aws.Iam.Commands.PutUserPolicy
@@ -22,6 +23,7 @@
 import           Aws.Iam.Commands.GetUser
 import           Aws.Iam.Commands.GetUserPolicy
 import           Aws.Iam.Commands.ListAccessKeys
+import           Aws.Iam.Commands.ListMfaDevices
 import           Aws.Iam.Commands.ListUserPolicies
 import           Aws.Iam.Commands.ListUsers
 import           Aws.Iam.Commands.PutUserPolicy
diff --git a/Aws/Iam/Commands/ListMfaDevices.hs b/Aws/Iam/Commands/ListMfaDevices.hs
new file mode 100644
--- /dev/null
+++ b/Aws/Iam/Commands/ListMfaDevices.hs
@@ -0,0 +1,80 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE RecordWildCards       #-}
+module Aws.Iam.Commands.ListMfaDevices
+       ( ListMfaDevices(..)
+       , ListMfaDevicesResponse(..)
+       ) where
+
+import Aws.Core
+import Aws.Iam.Core
+import Aws.Iam.Internal
+import Control.Applicative
+import Data.Text (Text)
+import Data.Typeable
+import Text.XML.Cursor (laxElement, ($//), (&|))
+-- | Lists the MFA devices. If the request includes the user name,
+-- then this action lists all the MFA devices associated with the
+-- specified user name. If you do not specify a user name, IAM
+-- determines the user name implicitly based on the AWS access key ID
+-- signing the request.
+--
+-- <https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListMFADevices.html>
+
+data ListMfaDevices = ListMfaDevices
+                      { lmfaUserName :: Maybe Text
+                        -- ^ The name of the user whose MFA devices
+                        -- you want to list.  If you do not specify a
+                        -- user name, IAM determines the user name
+                        -- implicitly based on the AWS access key ID
+                        -- signing the request
+                      , lmfaMarker   :: Maybe Text
+                        -- ^ Used for paginating requests. Marks the
+                        -- position of the last request.
+                      , lmfaMaxItems :: Maybe Integer
+                        -- ^ Used for paginating requests. Specifies
+                        -- the maximum number of items to return in
+                        -- the response. Defaults to 100.
+                      } deriving (Eq, Ord, Show, Typeable)
+
+instance SignQuery ListMfaDevices where
+  type ServiceConfiguration ListMfaDevices = IamConfiguration
+  signQuery ListMfaDevices{..} = iamAction' "ListMFADevices"
+                                 ([ ("UserName",) <$> lmfaUserName ]
+                                 <> markedIter lmfaMarker lmfaMaxItems)
+
+data ListMfaDevicesResponse = ListMfaDevicesResponse
+                              { lmfarMfaDevices :: [MfaDevice]
+                                -- ^ List of 'MFA Device's.
+                              , lmfarIsTruncated :: Bool
+                                -- ^ @True@ if the request was
+                                -- truncated because of too many
+                                -- items.
+                              , lmfarMarker :: Maybe Text
+                                -- ^ Marks the position at which the
+                                -- request was truncated. This value
+                                -- must be passed with the next
+                                -- request to continue listing from
+                                -- the last position.
+                              } deriving (Eq, Ord, Show, Typeable)
+
+instance ResponseConsumer ListMfaDevices ListMfaDevicesResponse where
+  type ResponseMetadata ListMfaDevicesResponse = IamMetadata
+  responseConsumer _req =
+    iamResponseConsumer $ \ cursor -> do
+      (lmfarIsTruncated, lmfarMarker) <- markedIterResponse cursor
+      lmfarMfaDevices <-
+        sequence $ cursor $// laxElement "member" &| parseMfaDevice
+      return ListMfaDevicesResponse{..}
+
+instance Transaction ListMfaDevices ListMfaDevicesResponse
+
+instance IteratedTransaction ListMfaDevices ListMfaDevicesResponse where
+    nextIteratedRequest request response
+        = case lmfarMarker response of
+            Nothing     -> Nothing
+            Just marker -> Just $ request { lmfaMarker = Just marker }
+
+instance AsMemoryResponse ListMfaDevicesResponse where
+    type MemoryResponse ListMfaDevicesResponse = ListMfaDevicesResponse
+    loadToMemory = return
diff --git a/Aws/Iam/Core.hs b/Aws/Iam/Core.hs
--- a/Aws/Iam/Core.hs
+++ b/Aws/Iam/Core.hs
@@ -14,6 +14,8 @@
     , AccessKeyStatus(..)
     , User(..)
     , parseUser
+    , MfaDevice(..)
+    , parseMfaDevice
     ) where
 
 import           Aws.Core
@@ -200,3 +202,30 @@
 
 data AccessKeyStatus = AccessKeyActive | AccessKeyInactive
     deriving (Eq, Ord, Show, Typeable)
+
+-- | The IAM @MFADevice@ data type.
+--
+-- <https://docs.aws.amazon.com/IAM/latest/APIReference/API_MFADevice.html>
+data MfaDevice = MfaDevice
+                 { mfaEnableDate   :: UTCTime
+                   -- ^ The date when the MFA device was enabled for
+                   -- the user.
+                 , mfaSerialNumber :: Text
+                   -- ^ The serial number that uniquely identifies the
+                   -- MFA device. For virtual MFA devices, the serial
+                   -- number is the device ARN.
+                 , mfaUserName     :: Text
+                   -- ^ The user with whom the MFA device is
+                   -- associated. Minimum length of 1. Maximum length
+                   -- of 64.
+                 } deriving (Eq, Ord, Show, Typeable)
+
+-- | Parses the IAM @MFADevice@ data type.
+parseMfaDevice :: MonadThrow m => Cu.Cursor -> m MfaDevice
+parseMfaDevice cursor = do
+  mfaEnableDate   <- attr "EnableDate" >>= parseDateTime . Text.unpack
+  mfaSerialNumber <- attr "SerialNumber"
+  mfaUserName     <- attr "UserName"
+  return MfaDevice{..}
+ where attr name = force ("Missing " ++ Text.unpack name) $
+               cursor $// elContent name
diff --git a/Aws/S3/Commands/Multipart.hs b/Aws/S3/Commands/Multipart.hs
--- a/Aws/S3/Commands/Multipart.hs
+++ b/Aws/S3/Commands/Multipart.hs
@@ -12,7 +12,6 @@
 import           Data.Conduit
 import qualified Data.Conduit.List     as CL
 import           Data.Maybe
-import           Data.Monoid
 import           Text.XML.Cursor       (($/))
 import qualified Data.ByteString.Char8 as B8
 import qualified Data.ByteString.Lazy  as BL
@@ -385,26 +384,22 @@
         Nothing -> return ()
 
 chunkedConduit :: (MonadResource m) => Integer -> Conduit B8.ByteString m BL.ByteString
-chunkedConduit size = do
-  loop 0 ""
+chunkedConduit size = loop 0 []
   where
-    loop :: MonadResource m => Int -> BL.ByteString -> Conduit B8.ByteString m BL.ByteString
-    loop cnt str = do
-      line' <- await
-      case line' of 
-        Nothing -> do
-          yield str
-          return ()
-        Just line -> do
-          let len = B8.length line+cnt
-          let newStr = str <> BL.fromStrict line
-          if len >= (fromIntegral size)
-            then do
-            yield newStr
-            loop 0 ""
-            else
-            loop len newStr
+    loop :: Monad m => Integer -> [B8.ByteString] -> Conduit B8.ByteString m BL.ByteString
+    loop cnt str = await >>= maybe (yieldChunk str) go
+      where
+        go :: Monad m => B8.ByteString -> Conduit B8.ByteString m BL.ByteString
+        go line
+          | size <= len = yieldChunk newStr >> loop 0 []
+          | otherwise   = loop len newStr
+          where
+            len = fromIntegral (B8.length line) + cnt
+            newStr = line:str
 
+    yieldChunk :: Monad m => [B8.ByteString] -> Conduit i m BL.ByteString
+    yieldChunk = yield . BL.fromChunks . reverse
+
 multipartUpload ::
   Configuration
   -> S3Configuration NormalQuery
@@ -422,6 +417,16 @@
            $$ CL.consume
   liftIO $ sendEtag cfg s3cfg mgr bucket object uploadId etags
 
+multipartUploadSink :: MonadResource m
+  => Configuration
+  -> S3Configuration NormalQuery
+  -> HTTP.Manager
+  -> T.Text    -- ^ Bucket name
+  -> T.Text    -- ^ Object name
+  -> Integer   -- ^ chunkSize (minimum: 5MB)
+  -> Sink B8.ByteString m ()
+multipartUploadSink cfg s3cfg = multipartUploadSinkWithInitiator cfg s3cfg postInitiateMultipartUpload
+
 multipartUploadWithInitiator ::
   Configuration
   -> S3Configuration NormalQuery
@@ -438,4 +443,20 @@
            $= chunkedConduit chunkSize
            $= putConduit cfg s3cfg mgr bucket object uploadId
            $$ CL.consume
+  liftIO $ sendEtag cfg s3cfg mgr bucket object uploadId etags
+
+multipartUploadSinkWithInitiator :: MonadResource m
+  => Configuration
+  -> S3Configuration NormalQuery
+  -> (Bucket -> T.Text -> InitiateMultipartUpload) -- ^ Initiator
+  -> HTTP.Manager
+  -> T.Text    -- ^ Bucket name
+  -> T.Text    -- ^ Object name
+  -> Integer   -- ^ chunkSize (minimum: 5MB)
+  -> Sink B8.ByteString m ()
+multipartUploadSinkWithInitiator cfg s3cfg initiator mgr bucket object chunkSize = do
+  uploadId <- liftIO $ imurUploadId <$> memoryAws cfg s3cfg mgr (initiator bucket object)
+  etags <- chunkedConduit chunkSize
+           $= putConduit cfg s3cfg mgr bucket object uploadId
+           $= CL.consume
   liftIO $ sendEtag cfg s3cfg mgr bucket object uploadId etags
diff --git a/Aws/S3/Commands/PutBucket.hs b/Aws/S3/Commands/PutBucket.hs
--- a/Aws/S3/Commands/PutBucket.hs
+++ b/Aws/S3/Commands/PutBucket.hs
@@ -3,6 +3,7 @@
 import           Aws.Core
 import           Aws.S3.Core
 import           Control.Monad
+import           Data.Maybe
 import qualified Data.Map             as M
 import qualified Data.Text            as T
 import qualified Data.Text.Encoding   as T
@@ -14,9 +15,13 @@
         pbBucket :: Bucket
       , pbCannedAcl :: Maybe CannedAcl
       , pbLocationConstraint :: LocationConstraint
+      , pbXStorageClass :: Maybe StorageClass -- ^ Google Cloud Storage S3 nonstandard extension
       }
     deriving (Show)
 
+putBucket :: Bucket -> PutBucket
+putBucket bucket = PutBucket bucket Nothing locationUsClassic Nothing
+
 data PutBucketResponse
     = PutBucketResponse
     deriving (Show)
@@ -38,7 +43,7 @@
                                                                  Just acl -> [("x-amz-acl", T.encodeUtf8 $ writeCannedAcl acl)]
                                            , s3QOtherHeaders = []
                                            , s3QRequestBody
-                                               = guard (not . T.null $ pbLocationConstraint) >>
+                                               = guard (not (null elts)) >>
                                                  (Just . HTTP.RequestBodyLBS . XML.renderLBS XML.def)
                                                  XML.Document {
                                                           XML.documentPrologue = XML.Prologue [] Nothing []
@@ -49,14 +54,22 @@
         where root = XML.Element {
                                XML.elementName = "{http://s3.amazonaws.com/doc/2006-03-01/}CreateBucketConfiguration"
                              , XML.elementAttributes = M.empty
-                             , XML.elementNodes = [
-                                                   XML.NodeElement (XML.Element {
-                                                                             XML.elementName = "{http://s3.amazonaws.com/doc/2006-03-01/}LocationConstraint"
-                                                                           , XML.elementAttributes = M.empty
-                                                                           , XML.elementNodes = [XML.NodeContent pbLocationConstraint]
-                                                                           })
-                                                  ]
+                             , XML.elementNodes = elts
                              }
+              elts = catMaybes
+                             [ if T.null pbLocationConstraint then Nothing else Just (locationconstraint pbLocationConstraint)
+                             , fmap storageclass pbXStorageClass
+                             ]
+              locationconstraint c = XML.NodeElement (XML.Element {
+                               XML.elementName = "{http://s3.amazonaws.com/doc/2006-03-01/}LocationConstraint"
+                             , XML.elementAttributes = M.empty
+                             , XML.elementNodes = [XML.NodeContent c]
+                             })
+              storageclass c = XML.NodeElement (XML.Element {
+                               XML.elementName = "StorageClass"
+                             , XML.elementAttributes = M.empty
+                             , XML.elementNodes = [XML.NodeContent (writeStorageClass c)]
+                             })
 
 instance ResponseConsumer r PutBucketResponse where
     type ResponseMetadata PutBucketResponse = S3Metadata
diff --git a/Aws/S3/Core.hs b/Aws/S3/Core.hs
--- a/Aws/S3/Core.hs
+++ b/Aws/S3/Core.hs
@@ -326,20 +326,25 @@
 
 data StorageClass
     = Standard
+    | StandardInfrequentAccess
     | ReducedRedundancy
     | Glacier
+    | OtherStorageClass T.Text
     deriving (Show)
 
-parseStorageClass :: MonadThrow m => T.Text -> m StorageClass
-parseStorageClass "STANDARD"           = return Standard
-parseStorageClass "REDUCED_REDUNDANCY" = return ReducedRedundancy
-parseStorageClass "GLACIER"            = return Glacier
-parseStorageClass s = throwM . XmlException $ "Invalid Storage Class: " ++ T.unpack s
+parseStorageClass :: T.Text -> StorageClass
+parseStorageClass "STANDARD"           = Standard
+parseStorageClass "STANDARD_IA"        = StandardInfrequentAccess
+parseStorageClass "REDUCED_REDUNDANCY" = ReducedRedundancy
+parseStorageClass "GLACIER"            = Glacier
+parseStorageClass s                    = OtherStorageClass s
 
 writeStorageClass :: StorageClass -> T.Text
-writeStorageClass Standard          = "STANDARD"
-writeStorageClass ReducedRedundancy = "REDUCED_REDUNDANCY"
-writeStorageClass Glacier           = "GLACIER"
+writeStorageClass Standard                 = "STANDARD"
+writeStorageClass StandardInfrequentAccess = "STANDARD_IA"
+writeStorageClass ReducedRedundancy        = "REDUCED_REDUNDANCY"
+writeStorageClass Glacier                  = "GLACIER"
+writeStorageClass (OtherStorageClass s) = s
 
 data ServerSideEncryption
     = AES256
@@ -392,7 +397,7 @@
          lastModified <- forceM "Missing object LastModified" $ el $/ elContent "LastModified" &| time
          eTag <- force "Missing object ETag" $ el $/ elContent "ETag"
          size <- forceM "Missing object Size" $ el $/ elContent "Size" &| textReadInt
-         storageClass <- forceM "Missing object StorageClass" $ el $/ elContent "StorageClass" &| parseStorageClass
+         storageClass <- forceM "Missing object StorageClass" $ el $/ elContent "StorageClass" &| return . parseStorageClass
          owner <- case el $/ Cu.laxElement "Owner" &| parseUserInfo of
                     (x:_) -> fmap' Just x
                     [] -> return Nothing
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,233 @@
+
+** 0.13 series
+
+NOTE: 0.13 brings breaking changes compared to 0.12.1!
+
+- 0.13
+  - DDB: Add support for scanning an index
+  - DDB: Allow deleting an attribute on update
+  - DDB: !BREAKING! Add support for native boolean values via "Bool". Can read old values,
+         and there's a compatibility wrapper OldBool that behaves exactly the same way it
+         used to.
+  - DDB: Add support for Null, L (list) and M (map) data types.
+  - DDB: Support consistent reads in Scan requests
+  - IAM: Add list-mfa-devices command
+  - S3: Extend StorageClass to support arbitrary classes, and StandardInfrequentAccess
+  - S3: Add a Sink interface for multipart uploading
+  - S3: Performance improvement for chunkedConduit
+  - S3: Partial support for Google Nearline
+
+** 0.12 series
+
+- 0.12.1
+  - DDB: Fix eu-west-1, add eu-central-1
+  - attoparsec 0.13
+  - xml-conduit 1.3
+
+- 0.12
+  - S3: Support for "Expect: 100-continue" (optional, technically API breaking)
+  - S3: Properly treat errors with a "301 Permanent Redirect" as errors and expose endpoint information
+
+** 0.11 series
+
+- 0.11.4
+  - Url-encode S3 object names in URLs
+  - filepath 1.4
+  - tagged 0.8.x
+  - limit errors to <2 to avoid compatibility problems
+
+- 0.11.3
+  - Support for blaze-builder 0.4
+  - Support for utf8-string 1.0
+  - New function: multipartUploadWithInitiator
+  - Fix issue in DynamoDB error parsing
+  - Ord instance for Aws.Core.Method
+
+- 0.11.2
+  - Support for time 1.5 (we previously forgot to relax the upper bound in Cabal)
+
+- 0.11.1
+  - Support time 1.5
+  - Fix duplicate sending of query when using PostQuery
+
+- 0.11
+  - New functions for running AWS transactions
+  - Performance optimizations for DynamoDB and S3 MultiPartUpload
+  - New DynamoDB commands & features
+  - S3 endpoint eu-central-1
+
+** 0.10 series
+
+- 0.10.5
+  - support for conduit 1.2
+
+- 0.10.4
+  - S3: support for multi-part uploads
+  - DynamoDB: fixes for JSON serialization
+      WARNING: This includes making some fields in TableDescription Maybe fields, which is breaking. But DynamoDB support was
+               and is also marked as EXPERIMENTAL.
+  - DynamoDB: TCP connection reuse where possible (improving performance)
+  - DynamoDB: Added test suite
+  - SES: support for additional regions
+
+- 0.10.3
+  - fix bug introduced in 0.10.2 that broke SQS and IAM connections without STS
+
+- 0.10.2
+  - support STS / IAM temporary credentials in all services
+
+- 0.10
+  - [EXPERIMENTAL!] DynamoDB: support for creating/updating/querying and scanning items
+  - SQS: complete overhaul to support 2012-11-05 features
+  - SQS: test suite
+  - S3: use Maybe for 404 HEAD requests on objects instead of throwing a misleading exception
+  - S3: support of poAutoMakeBucket for Internet Archive users
+  - S3: implement GetBucketLocation
+  - S3: add South American region
+  - S3: allow specifying the Content-Type when copying objects
+  - core: fix typo in NoCredentialsException accessor
+
+** 0.9 series
+
+- 0.9.4
+  - allow conduit 1.2
+
+- 0.9.3
+  - fix performance regression for loadCredentialsDefault
+  - add generic makeCredentials function
+  - add S3 DeleteBucket operation
+  - add S3 NukeBucket example
+  - SES: use security token if enabled (should allow using it with IAM roles on EC2 instances)
+
+- 0.9.2
+  - Support for credentials from EC2 instance metadata (only S3 for now)
+  - aeson 0.8 compatibility
+
+- 0.9.1
+  - Support for multi-page S3 GetBucket requests
+  - S3 GLACIER support
+  - Applicative instance for Response to conform to the Applicative-Monad Proposal
+  - Compatibility with transformers 0.4
+
+- 0.9
+  - Interface changes:
+    - attempt and failure were deprecated, remove
+    - switch to new cryptohash interface
+  - updated version bounds of conduit and xml-conduit
+
+** 0.8 series
+
+- 0.8.6
+  - move Instance metadata functions out of ResourceT to remove problem with exceptions-0.5
+    (this makes a fresh install of aws on a clean system possible again)
+
+- 0.8.5
+  - compatibility with case-insensitive 1.2
+  - support for V4 signatures
+  - experimental support for DynamoDB
+
+- 0.8.4
+  - compatibility with http-conduit 2.0
+
+- 0.8.3
+  - compatibility with cryptohash 0.11
+  - experimental IAM support
+
+- 0.8.2
+  - compatibility with cereal 0.4.x
+
+- 0.8.1
+  - compatibility with case-insensitive 1.1
+
+- 0.8.0
+  - S3, SQS: support for US-West2 (#58)
+  - S3: GetObject now has support for Content-Range (#22, #50)
+  - S3: GetBucket now supports the "IsTruncated" flag (#39)
+  - S3: PutObject now supports web page redirects (#46)
+  - S3: support for (multi-object) DeleteObjects (#47, #56)
+  - S3: HeadObject now uses an actual HEAD request (#53)
+  - S3: fixed signing issues for GetObject call (#54)
+  - SES: support for many more operations (#65, #66, #70, #71, #72, #74)
+  - SES: SendRawEmail now correctly encodes destinations and allows multiple destinations (#73)
+  - EC2: support fo Instance metadata (#37)
+  - Core: queryToHttpRequest allows overriding "Date" for the benefit of Chris Dornan's Elastic Transcoder bindings (#77)
+
+** 0.7 series
+
+- 0.7.6.4
+  - CryptoHash update
+- 0.7.6.3
+  - In addition to supporting http-conduit 1.9, it would seem nice to support conduit 1.0. Previously slipped through the radar.
+
+- 0.7.6.2
+  - Support for http-conduit 1.9
+
+- 0.7.6.1
+  - Support for case-insensitive 1.0 and http-types 0.8
+
+- 0.7.6
+  - Parsing of SimpleDB error responses was too strict, fixed
+  - Support for cryptohash 0.8
+  - Failure 0.1 does not work with aws, stricter lower bound
+
+- 0.7.5
+  - Support for http-conduit 1.7 and 1.8
+
+- 0.7.1-0.7.4
+  - Support for GHC 7.6
+  - Wider constraints to support newer versions of various dependencies
+  - Update maintainer e-mail address and project categories in cabal file
+
+- 0.7.0
+  - Change ServiceConfiguration concept so as to indicate in the type whether this is for URI-only requests
+    (i.e. awsUri)
+  - EXPERIMENTAL: Direct support for iterated transaction, i.e. such where multiple HTTP requests might be necessary due to e.g. response size limits.
+  - Put aws functions in ResourceT to be able to safely return Sources and streams.
+    - simpleAws* does not require ResourceT and converts streams into memory values (like ByteStrings) first.
+  - Log response metadata (level Info), and do not let all aws runners return it.
+  - S3:
+    - GetObject: No longer require a response consumer in the request, return the HTTP response (with the body as a stream) instead.
+    - Add CopyObject (PUT Object Copy) request type.
+  - Add Examples cabal flag for building code examples.
+  - Many more, small improvements.
+
+** 0.6 series
+
+- 0.6.2
+  - Properly parse Last-Modified header in accordance with RFC 2616.
+
+- 0.6.1
+  - Fix for MD5 encoding issue in S3 PutObject requests.
+
+- 0.6.0
+  - API Cleanup
+    - General: Use Crypto.Hash.MD5.MD5 when a Content-MD5 hash is required, instead of ByteString.
+    - S3: Made parameter order to S3.putObject consistent with S3.getObject.
+  - Updated dependencies:
+    - conduit 0.5 (as well as http-conduit 1.5 and xml-conduit 1.0).
+    - http-types 0.7.
+  - Minor changes.
+  - Internal changes (notable for people who want to add more commands):
+    - http-types' new 'QueryLike' interface allows creating query lists more conveniently.
+
+** 0.5 series
+
+- 0.5.0 ::
+    New configuration system: configuration split into general and service-specific parts.
+
+    Significantly improved API reference documentation.
+
+    Re-organised modules to make library easier to understand.
+
+    Smaller improvements.
+
+** 0.4 series
+
+- 0.4.1 :: Documentation improvements.
+- 0.4.0.1 :: Change dependency bounds to allow the transformers 0.3 package.
+- 0.4.0 :: Update conduit to 0.4.0, which is incompatible with earlier versions.
+
+** 0.3 series
+
+- 0.3.2 :: Add awsRef / simpleAwsRef request variants for those who prefer an =IORef= over a =Data.Attempt.Attempt= value.
+           Also improve README and add simple example.
diff --git a/Examples/DynamoDb.hs b/Examples/DynamoDb.hs
--- a/Examples/DynamoDb.hs
+++ b/Examples/DynamoDb.hs
@@ -11,7 +11,9 @@
 import           Control.Concurrent
 import           Control.Monad
 import           Control.Monad.Catch
+import           Control.Applicative
 import           Data.Conduit
+import           Data.Maybe
 import qualified Data.Conduit.List     as C
 import qualified Data.Text             as T
 import           Network.HTTP.Conduit  (withManager)
@@ -33,6 +35,25 @@
   resp1 <- runCommand req1
   print resp1
 
+data ExampleItem = ExampleItem {
+      name :: T.Text
+    , class_ :: T.Text
+    , boolAttr :: Bool
+    , oldBoolAttr :: Bool
+    }
+    deriving (Show)
+
+instance ToDynItem ExampleItem where
+    toItem (ExampleItem name class_ boolAttr oldBoolAttr) =
+        item [ attr "name" name
+             , attr "class" class_
+             , attr "boolattr" boolAttr
+             , attr "oldboolattr" (OldBool oldBoolAttr)
+             ]
+
+instance FromDynItem ExampleItem where
+    parseItem x = ExampleItem <$> getAttr "name" x <*> getAttr "class" x <*> getAttr "boolattr" x <*> getAttr "oldboolattr" x
+
 main :: IO ()
 main = do
   cfg <- Aws.baseConfiguration
@@ -41,10 +62,10 @@
 
   putStrLn "Putting an item..."
 
-  let x = item [ attrAs text "name" "josh"
-               , attrAs text "class" "not-so-awesome"]
+  let x = ExampleItem { name = "josh", class_ = "not-so-awesome",
+                        boolAttr = False, oldBoolAttr = True }
 
-  let req1 = (putItem "devel-1" x ) { piReturn = URAllOld
+  let req1 = (putItem "devel-1" (toItem x)) { piReturn = URAllOld
                                     , piRetCons =  RCTotal
                                     , piRetMet = RICMSize
                                     }
@@ -59,6 +80,9 @@
   resp2 <- runCommand req2
   print resp2
 
+  let y = fromItem (fromMaybe (item []) $ girItem resp2) :: Either String ExampleItem
+  print y
+
   print =<< runCommand
     (updateItem "devel-1" (hk "name" "josh") [au (Attribute "class" "awesome")])
 
@@ -74,7 +98,7 @@
 
   echo "Updating with true conditional"
   print =<< runCommand
-    (updateItem "devel-1" (hk "name" "josh") [au (Attribute "class" "awesomer")])
+    (updateItem "devel-1" (hk "name" "josh") [au (Attribute "class" "awesomer"), au (attr "oldboolattr" False)])
       { uiExpect = Conditions CondAnd [Condition "name" (DEq "josh")] }
 
   echo "Getting the item back..."
diff --git a/Examples/MultipartUpload.hs b/Examples/MultipartUpload.hs
--- a/Examples/MultipartUpload.hs
+++ b/Examples/MultipartUpload.hs
@@ -2,10 +2,11 @@
 
 import qualified Aws
 import qualified Aws.S3 as S3
-import           Data.Conduit (($$+-))
+import           Data.Conduit (($$))
 import           Data.Conduit.Binary (sourceFile)
 import qualified Data.Text as T
 import           Network.HTTP.Conduit (withManager, responseBody)
+import           Control.Monad.Trans.Resource (ResourceT)
 import           System.Environment (getArgs)
 
 main :: IO ()
@@ -18,12 +19,12 @@
 
   let doUpload bucket obj file chunkSize =
         withManager $ \mgr -> do
-          S3.multipartUpload cfg s3cfg mgr (T.pack bucket) (T.pack obj) (sourceFile file) (chunkSize*1024*1024)
+          (sourceFile file $$ S3.multipartUploadSink cfg s3cfg mgr (T.pack bucket) (T.pack obj) (chunkSize*1024*1024)) :: ResourceT IO ()
 
   case args of
-    [bucket,obj,file] -> 
+    [bucket,obj,file] ->
       doUpload bucket obj file 10
-    [bucket,obj,file,chunkSize] -> 
+    [bucket,obj,file,chunkSize] ->
       doUpload bucket obj file (read chunkSize)
     _ -> do
       putStrLn "Usage: MultipartUpload bucket objectname filename (chunksize(MB)::optinal)"
diff --git a/Examples/PutBucketNearLine.hs b/Examples/PutBucketNearLine.hs
new file mode 100644
--- /dev/null
+++ b/Examples/PutBucketNearLine.hs
@@ -0,0 +1,37 @@
+-- | Example of creating a Nearline bucket on Google Cloud Storage.
+
+{-# LANGUAGE OverloadedStrings #-}
+
+import qualified Aws
+import qualified Aws.Core as Aws
+import qualified Aws.S3 as S3
+import           Data.Conduit (($$+-))
+import           Data.Conduit.Binary (sinkFile)
+import           Network.HTTP.Conduit (withManager, RequestBody(..))
+import Control.Monad.IO.Class
+import Control.Concurrent
+import System.IO
+import Control.Applicative
+import qualified Data.Text as T
+import System.Environment
+
+sc :: S3.StorageClass
+sc = S3.OtherStorageClass (T.pack "NEARLINE")
+
+main :: IO ()
+main = do
+  [bucket] <- fmap (map T.pack) getArgs
+
+  {- Set up AWS credentials and S3 configuration using the Google Cloud
+   - Storage endpoint. -}
+  Just creds <- Aws.loadCredentialsFromEnv
+  let cfg = Aws.Configuration Aws.Timestamp creds (Aws.defaultLog Aws.Debug)
+  let s3cfg = S3.s3 Aws.HTTP "storage.googleapis.com" False
+
+  {- Set up a ResourceT region with an available HTTP manager. -}
+  withManager $ \mgr -> do
+    {- Create a request object with S3.PutBucket and run the request with pureAws. -}
+    rsp <-
+      Aws.pureAws cfg s3cfg mgr $
+        S3.PutBucket bucket Nothing "US" (Just sc)
+    liftIO $ print rsp
diff --git a/Examples/Sqs.hs b/Examples/Sqs.hs
--- a/Examples/Sqs.hs
+++ b/Examples/Sqs.hs
@@ -67,11 +67,11 @@
   let receiveMessageReq = Sqs.ReceiveMessage Nothing [] (Just 1) [] sqsQName (Just 20)
   let numMessages = length messages
   removedMsgs <- replicateM numMessages $ do
-      msgs <- eitherT (const $ return []) return . retryT 2 $ do
+      msgs <- exceptT (const $ return []) return . retryT 2 $ do
         Sqs.ReceiveMessageResponse r <- liftIO $ Aws.simpleAws cfg sqscfg receiveMessageReq
         case r of
-          [] -> left "no message received"
-          _ -> right r
+          [] -> throwE "no message received"
+          _ -> return r
       putStrLn $ "number of messages received: " ++ show (length msgs)
       forM msgs (\msg -> do
                      -- here we remove a message, delete it from the queue, and then return the
@@ -88,7 +88,7 @@
   {- | Let's make sure the queue was actually deleted and that the same number of queues exist at when
      | the program ends as when it started.
   -}
-  eitherT T.putStrLn T.putStrLn . retryT 4 $ do
+  exceptT T.putStrLn T.putStrLn . retryT 4 $ do
     qUrls <- liftIO $ do
       putStrLn $ "Listing all queueus to check to see if " ++ show (Sqs.qName sqsQName) ++ " is gone"
       Sqs.ListQueuesResponse qUrls_ <- Aws.simpleAws cfg sqscfg $ Sqs.ListQueues Nothing
@@ -96,16 +96,16 @@
       return qUrls_
 
     if qUrl `elem` qUrls
-        then left $ " *\n *\n * Warning, '" <> sshow qName <> "' was not deleted\n"
+        then throwE $ " *\n *\n * Warning, '" <> sshow qName <> "' was not deleted\n"
                     <> " * This is probably just a race condition."
-        else right $ "     The queue '" <> sshow qName <> "' was correctly deleted"
+        else return $ "     The queue '" <> sshow qName <> "' was correctly deleted"
 
-retryT :: MonadIO m => Int -> EitherT T.Text m a -> EitherT T.Text m a
+retryT :: MonadIO m => Int -> ExceptT T.Text m a -> ExceptT T.Text m a
 retryT i f = go 1
   where
     go x
         | x >= i = fmapLT (\e -> "error after " <> sshow x <> " retries: " <> e) f
-        | otherwise = f `catchT` \_ -> do
+        | otherwise = f `catchE` \_ -> do
             liftIO $ threadDelay (1000000 * min 60 (2^(x-1)))
             go (succ x)
 
diff --git a/README.org b/README.org
--- a/README.org
+++ b/README.org
@@ -88,220 +88,7 @@
 
 * Release Notes
 
-** 0.12 series
-
-- 0.12.1
-  - DDB: Fix eu-west-1, add eu-central-1
-  - attoparsec 0.13
-  - xml-conduit 1.3
-
-- 0.12
-  - S3: Support for "Expect: 100-continue" (optional, technically API breaking)
-  - S3: Properly treat errors with a "301 Permanent Redirect" as errors and expose endpoint information
-
-** 0.11 series
-
-- 0.11.4
-  - Url-encode S3 object names in URLs
-  - filepath 1.4
-  - tagged 0.8.x
-  - limit errors to <2 to avoid compatibility problems
-
-- 0.11.3
-  - Support for blaze-builder 0.4
-  - Support for utf8-string 1.0
-  - New function: multipartUploadWithInitiator
-  - Fix issue in DynamoDB error parsing
-  - Ord instance for Aws.Core.Method
-
-- 0.11.2
-  - Support for time 1.5 (we previously forgot to relax the upper bound in Cabal)
-
-- 0.11.1
-  - Support time 1.5
-  - Fix duplicate sending of query when using PostQuery
-
-- 0.11
-  - New functions for running AWS transactions
-  - Performance optimizations for DynamoDB and S3 MultiPartUpload
-  - New DynamoDB commands & features
-  - S3 endpoint eu-central-1
-
-** 0.10 series
-
-- 0.10.5
-  - support for conduit 1.2
-
-- 0.10.4
-  - S3: support for multi-part uploads
-  - DynamoDB: fixes for JSON serialization
-      WARNING: This includes making some fields in TableDescription Maybe fields, which is breaking. But DynamoDB support was
-               and is also marked as EXPERIMENTAL.
-  - DynamoDB: TCP connection reuse where possible (improving performance)
-  - DynamoDB: Added test suite
-  - SES: support for additional regions
-
-- 0.10.3
-  - fix bug introduced in 0.10.2 that broke SQS and IAM connections without STS
-
-- 0.10.2
-  - support STS / IAM temporary credentials in all services
-
-- 0.10
-  - [EXPERIMENTAL!] DynamoDB: support for creating/updating/querying and scanning items
-  - SQS: complete overhaul to support 2012-11-05 features
-  - SQS: test suite
-  - S3: use Maybe for 404 HEAD requests on objects instead of throwing a misleading exception
-  - S3: support of poAutoMakeBucket for Internet Archive users
-  - S3: implement GetBucketLocation
-  - S3: add South American region
-  - S3: allow specifying the Content-Type when copying objects
-  - core: fix typo in NoCredentialsException accessor
-
-** 0.9 series
-
-- 0.9.4
-  - allow conduit 1.2
-
-- 0.9.3
-  - fix performance regression for loadCredentialsDefault
-  - add generic makeCredentials function
-  - add S3 DeleteBucket operation
-  - add S3 NukeBucket example
-  - SES: use security token if enabled (should allow using it with IAM roles on EC2 instances)
-
-- 0.9.2
-  - Support for credentials from EC2 instance metadata (only S3 for now)
-  - aeson 0.8 compatibility
-
-- 0.9.1
-  - Support for multi-page S3 GetBucket requests
-  - S3 GLACIER support
-  - Applicative instance for Response to conform to the Applicative-Monad Proposal
-  - Compatibility with transformers 0.4
-
-- 0.9
-  - Interface changes:
-    - attempt and failure were deprecated, remove
-    - switch to new cryptohash interface
-  - updated version bounds of conduit and xml-conduit
-
-** 0.8 series
-
-- 0.8.6
-  - move Instance metadata functions out of ResourceT to remove problem with exceptions-0.5
-    (this makes a fresh install of aws on a clean system possible again)
-
-- 0.8.5
-  - compatibility with case-insensitive 1.2
-  - support for V4 signatures
-  - experimental support for DynamoDB
-
-- 0.8.4
-  - compatibility with http-conduit 2.0
-
-- 0.8.3
-  - compatibility with cryptohash 0.11
-  - experimental IAM support
-
-- 0.8.2
-  - compatibility with cereal 0.4.x
-
-- 0.8.1
-  - compatibility with case-insensitive 1.1
-
-- 0.8.0
-  - S3, SQS: support for US-West2 (#58)
-  - S3: GetObject now has support for Content-Range (#22, #50)
-  - S3: GetBucket now supports the "IsTruncated" flag (#39)
-  - S3: PutObject now supports web page redirects (#46)
-  - S3: support for (multi-object) DeleteObjects (#47, #56)
-  - S3: HeadObject now uses an actual HEAD request (#53)
-  - S3: fixed signing issues for GetObject call (#54)
-  - SES: support for many more operations (#65, #66, #70, #71, #72, #74)
-  - SES: SendRawEmail now correctly encodes destinations and allows multiple destinations (#73)
-  - EC2: support fo Instance metadata (#37)
-  - Core: queryToHttpRequest allows overriding "Date" for the benefit of Chris Dornan's Elastic Transcoder bindings (#77)
-
-** 0.7 series
-
-- 0.7.6.4
-  - CryptoHash update
-- 0.7.6.3
-  - In addition to supporting http-conduit 1.9, it would seem nice to support conduit 1.0. Previously slipped through the radar.
-
-- 0.7.6.2
-  - Support for http-conduit 1.9
-
-- 0.7.6.1
-  - Support for case-insensitive 1.0 and http-types 0.8
-
-- 0.7.6
-  - Parsing of SimpleDB error responses was too strict, fixed
-  - Support for cryptohash 0.8
-  - Failure 0.1 does not work with aws, stricter lower bound
-
-- 0.7.5
-  - Support for http-conduit 1.7 and 1.8
-
-- 0.7.1-0.7.4
-  - Support for GHC 7.6
-  - Wider constraints to support newer versions of various dependencies
-  - Update maintainer e-mail address and project categories in cabal file
-
-- 0.7.0
-  - Change ServiceConfiguration concept so as to indicate in the type whether this is for URI-only requests
-    (i.e. awsUri)
-  - EXPERIMENTAL: Direct support for iterated transaction, i.e. such where multiple HTTP requests might be necessary due to e.g. response size limits.
-  - Put aws functions in ResourceT to be able to safely return Sources and streams.
-    - simpleAws* does not require ResourceT and converts streams into memory values (like ByteStrings) first.
-  - Log response metadata (level Info), and do not let all aws runners return it.
-  - S3:
-    - GetObject: No longer require a response consumer in the request, return the HTTP response (with the body as a stream) instead.
-    - Add CopyObject (PUT Object Copy) request type.
-  - Add Examples cabal flag for building code examples.
-  - Many more, small improvements.
-
-** 0.6 series
-
-- 0.6.2
-  - Properly parse Last-Modified header in accordance with RFC 2616.
-
-- 0.6.1
-  - Fix for MD5 encoding issue in S3 PutObject requests.
-
-- 0.6.0
-  - API Cleanup
-    - General: Use Crypto.Hash.MD5.MD5 when a Content-MD5 hash is required, instead of ByteString.
-    - S3: Made parameter order to S3.putObject consistent with S3.getObject.
-  - Updated dependencies:
-    - conduit 0.5 (as well as http-conduit 1.5 and xml-conduit 1.0).
-    - http-types 0.7.
-  - Minor changes.
-  - Internal changes (notable for people who want to add more commands):
-    - http-types' new 'QueryLike' interface allows creating query lists more conveniently.
-
-** 0.5 series
-
-- 0.5.0 ::
-    New configuration system: configuration split into general and service-specific parts.
-
-    Significantly improved API reference documentation.
-
-    Re-organised modules to make library easier to understand.
-
-    Smaller improvements.
-
-** 0.4 series
-
-- 0.4.1 :: Documentation improvements.
-- 0.4.0.1 :: Change dependency bounds to allow the transformers 0.3 package.
-- 0.4.0 :: Update conduit to 0.4.0, which is incompatible with earlier versions.
-
-** 0.3 series
-
-- 0.3.2 :: Add awsRef / simpleAwsRef request variants for those who prefer an =IORef= over a =Data.Attempt.Attempt= value.
-           Also improve README and add simple example.
+See CHANGELOG
 
 * Resources
 
diff --git a/aws.cabal b/aws.cabal
--- a/aws.cabal
+++ b/aws.cabal
@@ -1,5 +1,5 @@
 Name:                aws
-Version:             0.12.1
+Version:             0.13.0
 Synopsis:            Amazon Web Services (AWS) for Haskell
 Description:         Bindings for Amazon Web Services (AWS), with the aim of supporting all AWS services. To see a high level overview of the library, see the README at <https://github.com/aristidb/aws/blob/master/README.org>.
 Homepage:            http://github.com/aristidb/aws
@@ -12,6 +12,7 @@
 Build-type:          Simple
 
 Extra-source-files:  README.org
+                     CHANGELOG
                      Examples/GetObject.hs
                      Examples/SimpleDb.hs
 
@@ -20,7 +21,7 @@
 Source-repository this
   type: git
   location: https://github.com/aristidb/aws.git
-  tag: 0.12.1
+  tag: 0.13.0
 
 Source-repository head
   type: git
@@ -56,6 +57,7 @@
                        Aws.Iam.Commands.GetUser
                        Aws.Iam.Commands.GetUserPolicy
                        Aws.Iam.Commands.ListAccessKeys
+                       Aws.Iam.Commands.ListMfaDevices
                        Aws.Iam.Commands.ListUserPolicies
                        Aws.Iam.Commands.ListUsers
                        Aws.Iam.Commands.PutUserPolicy
@@ -128,7 +130,7 @@
                        directory            >= 1.0     && < 1.3,
                        filepath             >= 1.1     && < 1.5,
                        http-conduit         >= 2.1     && < 2.2,
-                       http-types           >= 0.7     && < 0.9,
+                       http-types           >= 0.7     && < 0.10,
                        lifted-base          >= 0.1     && < 0.3,
                        monad-control        >= 0.3,
                        mtl                  == 2.*,
@@ -198,7 +200,8 @@
                        http-conduit,
                        conduit,
                        conduit-extra,
-                       text
+                       text,
+                       resourcet
 
   Default-Language: Haskell2010
 
@@ -239,6 +242,25 @@
 
   Default-Language: Haskell2010
 
+Executable PutBucketNearLine
+  Main-is: PutBucketNearLine.hs
+  Hs-source-dirs: Examples
+
+  if !flag(Examples)
+    Buildable: False
+  else
+    Buildable: True
+    Build-depends:
+                       base == 4.*,
+                       aws,
+                       http-conduit,
+                       conduit,
+                       conduit-extra,
+                       text >=0.1,
+                       transformers
+
+  Default-Language: Haskell2010
+
 Executable SimpleDb
   Main-is: SimpleDb.hs
   Hs-source-dirs: Examples
@@ -285,7 +307,7 @@
     Build-depends:
                        base == 4.*,
                        aws,
-                       errors >= 1.4 && < 2.0,
+                       errors >= 2.0,
                        text >=0.11,
                        transformers >= 0.3
 
@@ -306,7 +328,7 @@
         aws,
         base == 4.*,
         bytestring >= 0.10,
-        errors >= 1.4.7 && < 2.0,
+        errors >= 2.0,
         http-client >= 0.3,
         lifted-base >= 0.2,
         monad-control >= 0.3,
@@ -339,7 +361,7 @@
         aws,
         base == 4.*,
         bytestring >= 0.10,
-        errors >= 1.4.7 && < 2.0,
+        errors >= 2.0,
         http-client >= 0.3,
         lifted-base >= 0.2,
         monad-control >= 0.3,
@@ -353,4 +375,3 @@
         time,
         transformers >= 0.3,
         transformers-base >= 0.4
-
diff --git a/tests/DynamoDb/Main.hs b/tests/DynamoDb/Main.hs
--- a/tests/DynamoDb/Main.hs
+++ b/tests/DynamoDb/Main.hs
@@ -112,12 +112,12 @@
     :: Int -- ^ read capacity (#(non-consistent) reads * itemsize/4KB)
     -> Int -- ^ write capacity (#writes * itemsize/1KB)
     -> T.Text -- ^ table name
-    -> EitherT T.Text IO ()
+    -> ExceptT T.Text IO ()
 prop_createDescribeDeleteTable readCapacity writeCapacity tableName = do
     tTableName <- testData tableName
     tryT $ createTestTable tTableName readCapacity writeCapacity
     let deleteTable = retryT 6 . void $ simpleDyT (DY.DeleteTable tTableName)
-    handleT (\e -> deleteTable >> left e) $ do
+    flip catchE (\e -> deleteTable >> throwE e) $ do
         retryT 6 . void . simpleDyT $ DY.DescribeTable tTableName
         deleteTable
 
@@ -130,7 +130,7 @@
         ]
 
 prop_connectionReuse
-    :: EitherT T.Text IO ()
+    :: ExceptT T.Text IO ()
 prop_connectionReuse = do
     c <- liftIO $ do
         cfg <- baseConfiguration
@@ -138,14 +138,14 @@
         -- counts the number of TCP connections
         ref <- newIORef (0 :: Int)
 
-        void . HTTP.withManager (managerSettings ref) $ \manager -> runEitherT $
-            handleT (error . T.unpack) . replicateM_ 3 $ do
+        void . HTTP.withManager (managerSettings ref) $ \manager -> runExceptT $
+            flip catchE (error . T.unpack) . replicateM_ 3 $ do
                 void $ dyT cfg manager DY.ListTables
                 mustFail . dyT cfg manager $ DY.DescribeTable "____"
 
         readIORef ref
     unless (c == 1) $
-        left "The TCP connection has not been reused"
+        throwE "The TCP connection has not been reused"
   where
     managerSettings ref = HTTP.defaultManagerSettings
         { HTTP.managerRawConnection = do
diff --git a/tests/DynamoDb/Utils.hs b/tests/DynamoDb/Utils.hs
--- a/tests/DynamoDb/Utils.hs
+++ b/tests/DynamoDb/Utils.hs
@@ -96,7 +96,7 @@
 simpleDyT
     :: (AsMemoryResponse a, Transaction r a, ServiceConfiguration r ~ DY.DdbConfiguration, MonadBaseControl IO m, MonadIO m)
     => r
-    -> EitherT T.Text m (MemoryResponse a)
+    -> ExceptT T.Text m (MemoryResponse a)
 simpleDyT = tryT . simpleDy
 
 dyT
@@ -104,7 +104,7 @@
     => Configuration
     -> HTTP.Manager
     -> r
-    -> EitherT T.Text IO a
+    -> ExceptT T.Text IO a
 dyT cfg manager req = do
     Response _ r <- liftIO . runResourceT $ aws cfg dyConfiguration manager req
     hoistEither $ fmapL sshow r
@@ -129,17 +129,17 @@
       tTableName <- if prefix then testData tableName else return tableName
 
       let deleteTable = do
-            r <- runEitherT . retryT 6 $
-                void (simpleDyT $ DY.DeleteTable tTableName) `catchT` \e ->
+            r <- runExceptT . retryT 6 $
+                void (simpleDyT $ DY.DeleteTable tTableName) `catchE` \e ->
                     liftIO . T.hPutStrLn stderr $ "attempt to delete table failed: " <> e
             either (error . T.unpack) (const $ return ()) r
 
       let createTable = do
-            r <- runEitherT $ do
+            r <- runExceptT $ do
                 retryT 3 $ tryT $ createTestTable tTableName readCapacity writeCapacity
                 retryT 6 $ do
                     tableDesc <- simpleDyT $ DY.DescribeTable tTableName
-                    when (DY.rTableStatus tableDesc == "CREATING") $ left "Table not ready: status CREATING"
+                    when (DY.rTableStatus tableDesc == "CREATING") $ throwE "Table not ready: status CREATING"
             either (error . T.unpack) return r
 
       bracket_ createTable deleteTable $ f tTableName
diff --git a/tests/Sqs/Main.hs b/tests/Sqs/Main.hs
--- a/tests/Sqs/Main.hs
+++ b/tests/Sqs/Main.hs
@@ -141,7 +141,7 @@
     => Configuration
     -> HTTP.Manager
     -> r
-    -> EitherT T.Text IO a
+    -> ExceptT T.Text IO a
 sqsT cfg manager req = do
     Response _ r <- liftIO . runResourceT $ aws cfg sqsConfiguration manager req
     hoistEither $ fmapL sshow r
@@ -157,7 +157,7 @@
 simpleSqsT
     :: (AsMemoryResponse a, Transaction r a, ServiceConfiguration r ~ SQS.SqsConfiguration, MonadBaseControl IO m, MonadIO m)
     => r
-    -> EitherT T.Text m (MemoryResponse a)
+    -> ExceptT T.Text m (MemoryResponse a)
 simpleSqsT = tryT . simpleSqs
 
 withQueueTest
@@ -186,16 +186,16 @@
 --
 prop_createListDeleteQueue
     :: T.Text -- ^ queue name
-    -> EitherT T.Text IO ()
+    -> ExceptT T.Text IO ()
 prop_createListDeleteQueue queueName = do
     tQueueName <- testData queueName
     SQS.CreateQueueResponse queueUrl <- simpleSqsT $ SQS.CreateQueue Nothing tQueueName
     let queue = sqsQueueName queueUrl
-    handleT (\e -> deleteQueue queue >> left e) $ do
+    flip catchE (\e -> deleteQueue queue >> throwE e) $ do
         retryT 6 $ do
             SQS.ListQueuesResponse allQueueUrls <- simpleSqsT (SQS.ListQueues Nothing)
             unless (queueUrl `elem` allQueueUrls)
-                . left $ "queue " <> sshow queueUrl <> " not listed"
+                . throwE $ "queue " <> sshow queueUrl <> " not listed"
         deleteQueue queue
   where
     deleteQueue queueUrl = void $ simpleSqsT (SQS.DeleteQueue queueUrl)
@@ -221,7 +221,7 @@
 --
 prop_sendReceiveDeleteMessage
     :: SQS.QueueName
-    -> EitherT T.Text IO ()
+    -> ExceptT T.Text IO ()
 prop_sendReceiveDeleteMessage queue = do
 
     -- a visibility timeout should be used only if either @receiveBatch == 1@
@@ -241,10 +241,10 @@
         msgs <- retryT 5 $ do
             r <- simpleSqsT $ SQS.ReceiveMessage visTimeout [] (Just receiveBatch) [] queue poll
             case r of
-                SQS.ReceiveMessageResponse [] -> left "no message received"
+                SQS.ReceiveMessageResponse [] -> throwE "no message received"
                 SQS.ReceiveMessageResponse t
-                    | length t <= receiveBatch -> right t
-                    | otherwise -> left $ "unexpected number of messages received: " <> sshow (length t)
+                    | length t <= receiveBatch -> return t
+                    | otherwise -> throwE $ "unexpected number of messages received: " <> sshow (length t)
         forM_ msgs $ \msg -> retryT 5 $
             simpleSqsT $ SQS.DeleteMessage (SQS.mReceiptHandle msg) queue
         return (map SQS.mBody msgs)
@@ -252,7 +252,7 @@
     let recv = L.sort recMsgs
     let sent = L.sort messages
     unless (sent == recv)
-        $ left $ "received messages don't match send messages; sent: "
+        $ throwE $ "received messages don't match send messages; sent: "
             <> sshow sent <> "; got: " <> sshow recv
 
 -- | Checks for consistent receive: There is no message delay, so all messages
@@ -261,7 +261,7 @@
 --
 prop_sendReceiveDeleteMessageLongPolling
     :: SQS.QueueName
-    -> EitherT T.Text IO ()
+    -> ExceptT T.Text IO ()
 prop_sendReceiveDeleteMessageLongPolling queue = do
 
     let delay = Nothing
@@ -279,10 +279,10 @@
         msgs <- do
             r <- simpleSqsT $ SQS.ReceiveMessage visTimeout [] (Just receiveBatch) [] queue poll
             case r of
-                SQS.ReceiveMessageResponse [] -> left "no messages received"
+                SQS.ReceiveMessageResponse [] -> throwE "no messages received"
                 SQS.ReceiveMessageResponse t
-                    | length t == receiveBatch -> right t
-                    | otherwise -> left $ "unexpected number of messages received: " <> sshow (length t)
+                    | length t == receiveBatch -> return t
+                    | otherwise -> throwE $ "unexpected number of messages received: " <> sshow (length t)
         forM_ msgs $ \msg -> retryT 5 $
             simpleSqsT $ SQS.DeleteMessage (SQS.mReceiptHandle msg) queue
         return (map SQS.mBody msgs)
@@ -290,7 +290,7 @@
     let recv = L.sort recMsgs
     let sent = L.sort messages
     unless (sent == recv)
-        $ left $ "received messages don't match send messages; sent: "
+        $ throwE $ "received messages don't match send messages; sent: "
             <> sshow sent <> "; got: " <> sshow recv
 
 -- | Checks that long polling is actually enabled. We add a delay to the messages
@@ -301,7 +301,7 @@
 --
 prop_sendReceiveDeleteMessageLongPolling1
     :: SQS.QueueName
-    -> EitherT T.Text IO ()
+    -> ExceptT T.Text IO ()
 prop_sendReceiveDeleteMessageLongPolling1 queue = do
 
     let delay = Just 2
@@ -317,10 +317,10 @@
         msgs <- do
             r <- simpleSqsT $ SQS.ReceiveMessage visTimeout [] (Just receiveBatch) [] queue poll
             case r of
-                SQS.ReceiveMessageResponse [] -> left "no messages received"
+                SQS.ReceiveMessageResponse [] -> throwE "no messages received"
                 SQS.ReceiveMessageResponse t
-                    | length t == receiveBatch -> right t
-                    | otherwise -> left $ "unexpected number of messages received: " <> sshow (length t)
+                    | length t == receiveBatch -> return t
+                    | otherwise -> throwE $ "unexpected number of messages received: " <> sshow (length t)
         forM_ msgs $ \m -> retryT 5 $
             simpleSqsT $ SQS.DeleteMessage (SQS.mReceiptHandle m) queue
         return (map SQS.mBody msgs)
@@ -328,7 +328,7 @@
     let recv = L.sort recMsgs
     let sent = L.sort messages
     unless (sent == recv)
-        $ left $ "received messages don't match send messages; sent: "
+        $ throwE $ "received messages don't match send messages; sent: "
             <> sshow sent <> "; got: " <> sshow recv
 
 
@@ -344,7 +344,7 @@
 
 prop_connectionReuse
     :: SQS.QueueName
-    -> EitherT T.Text IO ()
+    -> ExceptT T.Text IO ()
 prop_connectionReuse queue = do
     c <- liftIO $ do
         cfg <- baseConfiguration
@@ -353,9 +353,9 @@
         ref <- newIORef (0 :: Int)
 
         -- Use a single manager for all HTTP requests
-        void . HTTP.withManager (managerSettings ref) $ \manager -> runEitherT $
+        void . HTTP.withManager (managerSettings ref) $ \manager -> runExceptT $
 
-            handleT (error . T.unpack) . replicateM_ 3 $ do
+            flip catchE (error . T.unpack) . replicateM_ 3 $ do
                 void . sqsT cfg manager $ SQS.ListQueues Nothing
                 mustFail . sqsT cfg manager $
                     SQS.SendMessage "" (SQS.QueueName "" "") [] Nothing
@@ -366,7 +366,7 @@
 
         readIORef ref
     unless (c == 1) $
-        left "The TCP connection has not been reused"
+        throwE "The TCP connection has not been reused"
   where
 
     managerSettings ref = HTTP.defaultManagerSettings
diff --git a/tests/Utils.hs b/tests/Utils.hs
--- a/tests/Utils.hs
+++ b/tests/Utils.hs
@@ -86,13 +86,13 @@
 
 -- | Catches all exceptions except for asynchronous exceptions found in base.
 --
-tryT :: MonadBaseControl IO m => m a -> EitherT T.Text m a
+tryT :: MonadBaseControl IO m => m a -> ExceptT T.Text m a
 tryT = fmapLT (T.pack . show) . syncIO
 
 -- | Lifted Version of 'syncIO' form "Control.Error.Util".
 --
-syncIO :: MonadBaseControl IO m => m a -> EitherT LE.SomeException m a
-syncIO a = EitherT $ LE.catches (Right <$> a)
+syncIO :: MonadBaseControl IO m => m a -> ExceptT LE.SomeException m a
+syncIO a = ExceptT $ LE.catches (Right <$> a)
     [ LE.Handler $ \e -> LE.throw (e :: LE.ArithException)
     , LE.Handler $ \e -> LE.throw (e :: LE.ArrayException)
     , LE.Handler $ \e -> LE.throw (e :: LE.AssertionFailed)
@@ -116,15 +116,15 @@
 testData :: (IsString a, Monoid a, MonadBaseControl IO m) => a -> m a
 testData a = fmap (<> a) testDataPrefix
 
-retryT :: MonadIO m => Int -> EitherT T.Text m a -> EitherT T.Text m a
+retryT :: (Functor m, MonadIO m) => Int -> ExceptT T.Text m a -> ExceptT T.Text m a
 retryT n f = snd <$> retryT_ n f
 
-retryT_ :: MonadIO m => Int -> EitherT T.Text m a -> EitherT T.Text m (Int, a)
+retryT_ :: (Functor m, MonadIO m) => Int -> ExceptT T.Text m a -> ExceptT T.Text m (Int, a)
 retryT_ n f = go 1
   where
     go x
         | x >= n = fmapLT (\e -> "error after " <> sshow x <> " retries: " <> e) ((x,) <$> f)
-        | otherwise = ((x,) <$> f) `catchT` \e -> do
+        | otherwise = ((x,) <$> f) `catchE` \e -> do
             liftIO $ T.hPutStrLn stderr $ "Retrying after error: " <> e
             liftIO $ threadDelay (1000000 * min 60 (2^(x-1)))
             go (succ x)
@@ -132,31 +132,31 @@
 sshow :: (Show a, IsString b) => a -> b
 sshow = fromString . show
 
-mustFail :: Monad m => EitherT e m a -> EitherT T.Text m ()
-mustFail = EitherT . eitherT
+mustFail :: Monad m => ExceptT e m a -> ExceptT T.Text m ()
+mustFail = ExceptT . exceptT
     (const . return $ Right ())
     (const . return $ Left "operation succeeded when a failure was expected")
 
 evalTestTM
     :: Functor f
     => String -- ^ test name
-    -> f (EitherT T.Text IO a) -- ^ test
+    -> f (ExceptT T.Text IO a) -- ^ test
     -> f (PropertyM IO Bool)
 evalTestTM name = fmap $
-    (liftIO . runEitherT) >=> \r -> case r of
+    (liftIO . runExceptT) >=> \r -> case r of
         Left e ->
             fail $ "failed to run test \"" <> name <> "\": " <> show e
         Right _ -> return True
 
 evalTestT
     :: String -- ^ test name
-    -> EitherT T.Text IO a -- ^ test
+    -> ExceptT T.Text IO a -- ^ test
     -> PropertyM IO Bool
 evalTestT name = runIdentity . evalTestTM name . Identity
 
 eitherTOnceTest0
     :: String -- ^ test name
-    -> EitherT T.Text IO a -- ^ test
+    -> ExceptT T.Text IO a -- ^ test
     -> TestTree
 eitherTOnceTest0 name test = testProperty name . once . monadicIO
     $ evalTestT name test
@@ -164,7 +164,7 @@
 eitherTOnceTest1
     :: (Arbitrary a, Show a)
     => String -- ^ test name
-    -> (a -> EitherT T.Text IO b)
+    -> (a -> ExceptT T.Text IO b)
     -> TestTree
 eitherTOnceTest1 name test = testProperty name . once $ monadicIO
     . evalTestTM name test
@@ -172,7 +172,7 @@
 eitherTOnceTest2
     :: (Arbitrary a, Show a, Arbitrary b, Show b)
     => String -- ^ test name
-    -> (a -> b -> EitherT T.Text IO c)
+    -> (a -> b -> ExceptT T.Text IO c)
     -> TestTree
 eitherTOnceTest2 name test = testProperty name . once $ \a b -> monadicIO
     $ (evalTestTM name $ uncurry test) (a, b)
