mellon-core 0.8.0.3 → 0.8.0.4
raw patch · 4 files changed
+331/−4 lines, 4 filesdep ~QuickCheckdep ~hlintPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: QuickCheck, hlint
API changes (from Hackage documentation)
Files
- .hlint.yaml +1/−0
- changelog.md +8/−0
- mellon-core.cabal +6/−4
- package.yaml +316/−0
+ .hlint.yaml view
@@ -0,0 +1,1 @@+- ignore: { name: Use newtype instead of data, within: Mellon.Device }
changelog.md view
@@ -1,3 +1,11 @@+## 0.8.0.4 (2018-01-26)++- Require hlint 2.0.x.++- Bump QuickCheck bounds.++- New and improved Nix packaging.+ ## 0.8.0.3 (2018-01-11) - Use hpack.
mellon-core.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 03b9d6e60a651567d584825fe6863c4f050e9deb4b6986d9d668be39fb4bbdff+-- hash: c241c1dea92ace19196c4e4721144b03ede6c6f16f531f177adb9296e10611b0 name: mellon-core-version: 0.8.0.3+version: 0.8.0.4 synopsis: Control physical access devices description: /Speak, friend, and enter./ .@@ -125,7 +125,9 @@ cabal-version: >= 1.10 extra-source-files:+ .hlint.yaml changelog.md+ package.yaml README.md source-repository head@@ -185,7 +187,7 @@ buildable: False else build-depends:- QuickCheck >=2.8 && <2.11+ QuickCheck >=2.8 && <2.12 , base , doctest >=0.11 && <0.14 , quickcheck-instances ==0.3.*@@ -206,7 +208,7 @@ else build-depends: base- , hlint >=1.9 && <2.1+ , hlint ==2.0.* default-language: Haskell2010 test-suite spec
+ package.yaml view
@@ -0,0 +1,316 @@+name: mellon-core+version: 0.8.0.4+synopsis: Control physical access devices+category: System+stability: experimental+author: Drew Hess <dhess-src@quixoftic.com>+maintainer: Drew Hess <dhess-src@quixoftic.com>+copyright: Copyright (c) 2017, Quixoftic, LLC+license: BSD3+github: quixoftic/mellon++description: ! '/Speak, friend, and enter./+++ @mellon-core@ is a Haskell package for controlling physical access++ devices designed for human factors, e.g., electric strikes. The++ access control protocol is quite simple: a device is either locked,++ or it is unlocked until a particular date and time (an++ /expiration date/). Once the expiration date passes, the device is++ automatically locked again. In the meantime, the device can be++ locked immediately, overriding the unlocked state; or the unlock++ period can be extended.+++ User programs incorporate @mellon-core@ functionality via a++ /controller/, which is responsible for handling user lock and unlock++ commands, and for scheduling and canceling unlock expirations.+++ User programs must also adapt their physical access devices to the++ interface expected by the controller. For this purpose,++ @mellon-core@ defines a /device/ type with 2 simple ''IO'' actions for++ locking and unlocking the device. (@mellon-core@ does not provide++ any useful device implementations; see the companion @mellon-gpio@++ package for a GPIO-driven implementation.)+++ Note that @mellon-core@ does not provide authentication mechanisms++ or network services for interacting with controllers; that is the++ domain of higher-level packages which use the base @mellon-core@++ package (e.g., @mellon-web@).+++ /On the use of UTC dates for timers/+++ @mellon-core@ uses UTC dates for unlock expiration, rather than a++ time delta or a monotonic clock. You might disagree with this++ decision based on the common wisdom that it''s a bad idea to use++ \"wall clock time\" (of which UTC is one flavor) for timers. In++ general, the common wisdom is correct. Wall clocks have lots of++ problems: they may not be accurate, they may disagree from one++ system to the next, they may \"jump around\" if the system is running++ a time daemon such as NTP, and they occasionally do something++ unexpected like adding a leap second.+++ If your timers must be high-precision (i.e., this timer must run for++ exactly /n/ microseconds, for some definition of \"exactly\"), then++ there''s no argument: using a wall clock is a bad idea. However, as++ @mellon-core@ is designed for use with physical access devices,++ which themselves are typically designed for human factors, accuracy++ to within a second or two is acceptable in most cases. (If you have++ higher-precision needs, especially for extreme safety- or++ security-related scenarios, you should probably be using a real-time++ system anyway, not a Haskell program.)+++ Once the need for high precision is eliminated, and assuming that++ the system(s) controlling your physical access devices use a++ synchronized time source such as that provided by++ <https://en.wikipedia.org/wiki/Network_Time_Protocol NTP>, the++ advantages of using UTC over most of the alternatives become++ apparent:+++ * Absolute time deltas without a common reference do not work well++ in networked environments, where network problems may appreciably++ delay the delivery of commands from client to server. If a user++ wants to unlock a device for 7 seconds, does that mean 7 seconds++ from the clock time @T@ when the user presses \"send,\" or does it++ mean 7 seconds from opening to close, regardless of when the++ server receives the command? Without a common reference, there is++ no way for the user to communicate her intent.+++ * Monotonic clocks never go backwards, which is a nice invariant and++ eliminates a problem that occurs in some NTP implementations.++ However, monotonic clocks are a) non-portable, and not even++ supported on all systems; b) usually system-dependent, which++ renders them useless when attempting to communicate time across++ two systems; c) sometimes even process-dependent, in which case++ they''re not even useful for communicating time between two++ processes on the same system; and d) often idle while the system++ is suspending or sleeping, in which case the clock does not move++ forward while the system is suspended, rendering the clock useless++ for absolute timers if there''s any possibility that the system++ will be suspended or otherwise go into a low-power mode.+++ Using the TAI coordinate system rather than UTC has the advantage of++ guaranteeing that every (TAI) day is exactly 86400 (TAI) seconds,++ unlike UTC and all of the time systems based on it, where very++ rarely a day may have 86401 seconds, i.e., one standard day plus 1++ leap second. If TAI were well-supported and generally available,++ @mellon-core@ would probably use it, but circa 2016 it is not.++ Anyway, at worst, a @mellon-core@ unlock command which spans a time++ period in which a leap second is added will expire approximately 1++ second too soon / too early, depending on whether the user accounted++ for the leap second when she issued the command. As this error is++ more or less within the expected accuracy of a @mellon-core@ system++ under normal operation (due to the vagaries of thread scheduling,++ and not even accounting for clock drift and other real-world++ factors), it doesn''t really seem worth the effort just to avoid the++ minor inconvenience of leap seconds.+++ In short, synchronizing time (and timers) across multiple systems is++ a very difficult problem, and one which the universally-supported++ Network Time Protocol attempts to address, mostly successfully.++ Given its intended application to controlling physical access for++ human beings, most likely in a networked environment, @mellon-core@++ makes the choice of relying on a working, accurate NTP (or other++ wall-clock synchronization) deployment for coordinating and++ synchronizing time across devices. If you cannot guarantee accurate++ wall clock time in your system, @mellon-core@ will not work++ properly, and you should look for an alternative solution.'++tested-with: GHC==7.10.3 GHC==8.0.1 GHC==8.0.2 GHC==8.2.1 GHC==8.2.2++flags:+ test-hlint:+ description: Build hlint test+ manual: true+ default: true+ test-doctests:+ description: Build doctests+ manual: true+ default: true++when:+ - condition: impl(ghc >= 8.0)+ then:+ ghc-options:+ - -Wall+ - -Wincomplete-uni-patterns+ - -Wincomplete-record-updates+ else:+ ghc-options:+ - -Wall+ - -fwarn-incomplete-uni-patterns+ - -fwarn-incomplete-record-updates++library:+ when:+ - condition: impl(ghc >= 8.0)+ then:+ ghc-options:+ - -Wcompat+ - -Wnoncanonical-monad-instances+ - -Wnoncanonical-monadfail-instances+ else:+ # provide/emulate `Control.Monad.Fail` and `Data.Semigroups` API for pre-GHC8+ dependencies:+ - fail == 4.9.*+ - semigroups == 0.18.*+ source-dirs: src+ other-extensions:+ - DeriveDataTypeable+ - DeriveGeneric+ - Safe+ dependencies:+ - base >=4.8 && <5+ - async ==2.1.*+ - mtl ==2.2.*+ - time >=1.5 && <2+ - transformers >=0.4.2 && <0.6++tests:+ hlint:+ main: hlint.hs+ source-dirs: test+ other-modules: []+ ghc-options:+ - -w+ - -threaded+ - -rtsopts+ - -with-rtsopts=-N+ when:+ - condition: "!(flag(test-hlint))"+ then:+ buildable: false+ else:+ dependencies:+ - base+ - hlint ==2.0.*+ doctest:+ main: doctest.hs+ source-dirs: test+ other-modules: []+ ghc-options:+ - -threaded+ when:+ - condition: "!(flag(test-doctests))"+ then:+ buildable: false+ else:+ dependencies:+ - base+ - QuickCheck >=2.8 && <2.12+ - quickcheck-instances ==0.3.*+ - doctest >=0.11 && <0.14+ spec:+ main: Main.hs+ source-dirs:+ - test+ other-extensions:+ - DeriveDataTypeable+ ghc-options:+ - -w+ - -threaded+ - -rtsopts+ - -with-rtsopts=-N+ dependencies:+ - base+ - async+ - hspec >=2.2 && <2.5+ - mellon-core+ - mtl+ - time+ - transformers++extra-source-files:+ - .hlint.yaml+ - changelog.md+ - README.md+ - package.yaml