diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,7 @@
+# Change log
+
+store-specs uses [Semantic Versioning][].
+The change log is available through the [releases on GitHub][].
+
+[Semantic Versioning]: http://semver.org/spec/v2.0.0.html
+[releases on GitHub]: https://github.com/githubuser/store-specs/releases
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,34 @@
+[The BSD-3 License (BSD3)][]
+
+Copyright (c) 2016, Yorick Laupa
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Yorick Laupa nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+[The BSD-3 License (BSD3)]: https://opensource.org/licenses/BSD-3-Clause
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# [eventsource-store-specs][]
+
+This project provides an open store specification, as a HUnit test, for store implementors.
+The goal is to make sure every `Store` implementation behaves the same regarding to those tests.
+[eventsource-store-specs]: https://github.com/YoEight/eventsource-api
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,7 @@
+-- This script is used to build and install your package. Typically you don't
+-- need to change it. The Cabal documentation has more information about this
+-- file: <https://www.haskell.org/cabal/users-guide/installing-packages.html>.
+import qualified Distribution.Simple
+
+main :: IO ()
+main = Distribution.Simple.defaultMain
diff --git a/eventsource-store-specs.cabal b/eventsource-store-specs.cabal
new file mode 100644
--- /dev/null
+++ b/eventsource-store-specs.cabal
@@ -0,0 +1,46 @@
+-- This file has been generated from package.yaml by hpack version 0.15.0.
+--
+-- see: https://github.com/sol/hpack
+
+name:           eventsource-store-specs
+version:        1.0.0
+synopsis:       Provides common test specification for Store implementation.
+description:    Provides common test specification for Store implementation.
+category:       Eventsourcing, Testing
+homepage:       https://github.com/YoEight/eventsource-api#readme
+bug-reports:    https://github.com/YoEight/eventsource-api/issues
+author:         Yorick Laupa
+maintainer:     yo.eight@gmail.com
+license:        BSD3
+license-file:   LICENSE.md
+build-type:     Simple
+cabal-version:  >= 1.10
+
+extra-source-files:
+    CHANGELOG.md
+    LICENSE.md
+    package.yaml
+    README.md
+    stack.yaml
+
+source-repository head
+  type: git
+  location: https://github.com/YoEight/eventsource-api
+
+library
+  hs-source-dirs:
+      library
+  default-extensions: NoImplicitPrelude
+  ghc-options: -Wall
+  build-depends:
+      base >=4.9 && <5
+    , protolude >= 0.1.10 && <0.2
+    , eventsource-api ==1.*
+    , tasty
+    , tasty-hspec
+    , mtl
+    , aeson
+    , uuid
+  exposed-modules:
+      Test.EventSource.Store.Specification
+  default-language: Haskell2010
diff --git a/library/Test/EventSource/Store/Specification.hs b/library/Test/EventSource/Store/Specification.hs
new file mode 100644
--- /dev/null
+++ b/library/Test/EventSource/Store/Specification.hs
@@ -0,0 +1,140 @@
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE RecordWildCards     #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+--------------------------------------------------------------------------------
+-- |
+-- Module : Test.EventSource.Store.Specification
+-- Copyright : (C) 2016 Yorick Laupa
+-- License : (see the file LICENSE)
+--
+-- Maintainer : Yorick Laupa <yo.eight@gmail.com>
+-- Stability : provisional
+-- Portability : non-portable
+--
+--------------------------------------------------------------------------------
+module Test.EventSource.Store.Specification (specification) where
+
+--------------------------------------------------------------------------------
+import Prelude (Show(..))
+
+--------------------------------------------------------------------------------
+import Control.Monad.Except
+import Data.Aeson.Types
+import Data.UUID
+import Data.UUID.V4
+import EventSource
+import Protolude hiding (show)
+import Test.Tasty.Hspec
+
+--------------------------------------------------------------------------------
+newtype TestEvent = TestEvent Int deriving (Eq, Show)
+
+--------------------------------------------------------------------------------
+instance EncodeEvent TestEvent where
+  encodeEvent (TestEvent v) = do
+    setEventType "test-event"
+    setEventPayload $ dataFromJson $ object [ "value" .= v ]
+
+--------------------------------------------------------------------------------
+instance DecodeEvent TestEvent where
+  decodeEvent Event{..} = do
+    unless (eventType == "test-event") $
+      Left "Wrong event type"
+
+    dataAsParse eventPayload $ withObject "" $ \o ->
+      fmap TestEvent (o .: "value")
+
+--------------------------------------------------------------------------------
+freshStreamName :: MonadIO m => m StreamName
+freshStreamName = liftIO $ fmap (StreamName . toText) nextRandom
+
+--------------------------------------------------------------------------------
+incr :: Int -> Int
+incr = (+1)
+
+--------------------------------------------------------------------------------
+specification :: Store store => store -> Spec
+specification store = do
+  specify "API - Add event" $ do
+    let expected = TestEvent 1
+    name <- freshStreamName
+    _ <- wait =<< appendEvent store name AnyVersion expected
+    res <- wait =<< readBatch store name (startFrom 0)
+
+    res `shouldSatisfy` isReadSuccess
+    let ReadSuccess slice = res
+
+    for_ (zip [0..] $ sliceEvents slice) $ \(num, e) ->
+      eventNumber e `shouldBe` num
+
+    sliceEventsAs slice `shouldBe` Right [expected]
+
+  specify "API - Read events in batch" $ do
+    let expected = fmap TestEvent [1..3]
+    name <- freshStreamName
+    _ <- wait =<< appendEvents store name AnyVersion
+                         expected
+    res <- streamIterator store name
+
+    res `shouldSatisfy` isReadSuccess
+
+    let ReadSuccess i = res
+    got <- iteratorReadAllEvents i
+
+    got `shouldBe` expected
+
+  specify "API - Subscription working" $ do
+    let expected = TestEvent 1
+    name <- freshStreamName
+    sub <- subscribe store name
+
+    _ <- wait =<< appendEvent store name AnyVersion expected
+
+    res <- nextEventAs sub
+    res `shouldSatisfy` either (const False) (const True)
+
+    let Right got = res
+    got `shouldBe` expected
+
+  specify "API - forEvents" $ do
+    let events = fmap TestEvent [0..9]
+    name <- freshStreamName
+    _ <- wait =<< appendEvents store name AnyVersion events
+
+    let action = do
+          forEvents store name $ \(_ :: TestEvent) ->
+            modify incr
+          get
+
+    res <- runExceptT $ mapExceptT (\m -> evalStateT m 0) action
+
+    res `shouldSatisfy` either (const False) (const True)
+    let Right st = res
+
+    st `shouldBe` (10 :: Int)
+
+  specify "API - foldEvents" $ do
+    let events = fmap TestEvent [0..9]
+    name <- freshStreamName
+    _ <- wait =<< appendEvents store name AnyVersion events
+
+    res <- runExceptT $ foldEvents store name
+                      (\s (_ :: TestEvent) -> s + 1)
+                      0
+
+    res `shouldSatisfy` either (const False) (const True)
+    let Right st = res
+
+    st `shouldBe` (10 :: Int)
+
+  specify "API - Iterator.readAllEvents" $ do
+    let events = fmap TestEvent [0..9]
+    name <- freshStreamName
+    _ <- wait =<< appendEvents store name AnyVersion events
+
+    res <- streamIterator store name
+    res `shouldSatisfy` isReadSuccess
+    let ReadSuccess i = res
+
+    got <- iteratorReadAllEvents i
+    got `shouldBe` events
diff --git a/package.yaml b/package.yaml
new file mode 100644
--- /dev/null
+++ b/package.yaml
@@ -0,0 +1,33 @@
+# This YAML file describes your package. Stack will automatically generate a
+# Cabal file when you run `stack build`. See the hpack website for help with
+# this file: <https://github.com/sol/hpack>.
+category: Eventsourcing, Testing
+description: Provides common test specification for Store implementation.
+extra-source-files:
+- CHANGELOG.md
+- LICENSE.md
+- package.yaml
+- README.md
+- stack.yaml
+ghc-options: -Wall
+github: YoEight/eventsource-api
+library:
+  default-extensions:
+    - NoImplicitPrelude
+  dependencies:
+  - base >=4.9 && <5
+  - protolude >= 0.1.10 && <0.2
+  - eventsource-api ==1.*
+  - tasty
+  - tasty-hspec
+  - mtl
+  - aeson
+  - uuid
+  source-dirs: library
+license: BSD3
+license-file: LICENSE.md
+author: Yorick Laupa
+maintainer: yo.eight@gmail.com
+name: eventsource-store-specs
+synopsis: Provides common test specification for Store implementation.
+version: '1.0.0'
diff --git a/stack.yaml b/stack.yaml
new file mode 100644
--- /dev/null
+++ b/stack.yaml
@@ -0,0 +1,66 @@
+# This file was automatically generated by 'stack init'
+#
+# Some commonly used options have been documented as comments in this file.
+# For advanced use and comprehensive documentation of the format, please see:
+# http://docs.haskellstack.org/en/stable/yaml_configuration/
+
+# Resolver to choose a 'specific' stackage snapshot or a compiler version.
+# A snapshot resolver dictates the compiler version and the set of packages
+# to be used for project dependencies. For example:
+#
+# resolver: lts-3.5
+# resolver: nightly-2015-09-21
+# resolver: ghc-7.10.2
+# resolver: ghcjs-0.1.0_ghc-7.10.2
+# resolver:
+#  name: custom-snapshot
+#  location: "./custom-snapshot.yaml"
+resolver: lts-7.14
+
+# User packages to be built.
+# Various formats can be used as shown in the example below.
+#
+# packages:
+# - some-directory
+# - https://example.com/foo/bar/baz-0.0.2.tar.gz
+# - location:
+#    git: https://github.com/commercialhaskell/stack.git
+#    commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
+# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a
+#   extra-dep: true
+#  subdirs:
+#  - auto-update
+#  - wai
+#
+# A package marked 'extra-dep: true' will only be built if demanded by a
+# non-dependency (i.e. a user package), and its test suites and benchmarks
+# will not be run. This is useful for tweaking upstream packages.
+packages:
+- '.'
+# Dependency packages to be pulled from upstream that are not in the resolver
+# (e.g., acme-missiles-0.3)
+extra-deps: []
+
+# Override default flag values for local packages and extra-deps
+flags: {}
+
+# Extra package databases containing global packages
+extra-package-dbs: []
+
+# Control whether we use the GHC we find on the path
+# system-ghc: true
+#
+# Require a specific version of stack, using version ranges
+# require-stack-version: -any # Default
+# require-stack-version: ">=1.2"
+#
+# Override the architecture used by stack, especially useful on Windows
+# arch: i386
+# arch: x86_64
+#
+# Extra directories used by stack for building
+# extra-include-dirs: [/path/to/dir]
+# extra-lib-dirs: [/path/to/dir]
+#
+# Allow a newer minor version of GHC than the snapshot specifies
+# compiler-check: newer-minor
