packages feed

nova-cache 0.8.0.0 → 0.9.0.0

raw patch · 4 files changed

+42/−23 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- NovaCache.Xz: XzLimits :: Word64 -> Word64 -> XzLimits
- NovaCache.Xz: XzMemoryOverBound :: Word64 -> XzError
- NovaCache.Xz: XzOutputOverBound :: Word64 -> XzError
- NovaCache.Xz: XzStreamError :: String -> XzError
- NovaCache.Xz: [xzMaxDecoderMemoryBytes] :: XzLimits -> Word64
- NovaCache.Xz: [xzMaxOutputBytes] :: XzLimits -> Word64
- NovaCache.Xz: data XzError
- NovaCache.Xz: data XzLimits
- NovaCache.Xz: decompress :: XzLimits -> ByteString -> Either XzError ByteString
- NovaCache.Xz: defaultXzDecoderMemoryBytes :: Word64
- NovaCache.Xz: instance GHC.Internal.Classes.Eq NovaCache.Xz.XzError
- NovaCache.Xz: instance GHC.Internal.Classes.Eq NovaCache.Xz.XzLimits
- NovaCache.Xz: instance GHC.Internal.Exception.Type.Exception NovaCache.Xz.XzError
- NovaCache.Xz: instance GHC.Internal.Show.Show NovaCache.Xz.XzError
- NovaCache.Xz: instance GHC.Internal.Show.Show NovaCache.Xz.XzLimits
- NovaCache.Xz: withXzSource :: XzLimits -> IO ByteString -> (IO ByteString -> IO a) -> IO a

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Changelog +## Unreleased++- **`NovaCache.Xz` moves to the public `nova-cache:xz` sublibrary; the `xz` flag is gone.** A dependency's flag cannot be set from a consumer's `.cabal` file, so reaching the decoder forced a mirrored flag plus a matching `constraints: nova-cache +xz` in every downstream - two knobs that had to agree and that the solver could not see. `build-depends: nova-cache:xz` now expresses the need directly, and consumers without it still never build the bundled liblzma, keeping the 0.5.0.0 lesson. Builds that passed `-f xz` drop the flag and add the dependency; the module and its API are unchanged.+ ## 0.8.0.0 - 2026-08-20  - **Bounded xz decompression returns: the new `NovaCache.Xz`, behind a manual, off-by-default `xz` flag.** 0.5.0.0 removed xz support for having no consumer; foreign-cache substitution (cache.nixos.org serves `.nar.xz`) is the consumer, and the decoder comes back shaped for untrusted input. The consumer knows the narinfo's declared NarSize before decompressing, so `decompress` takes that bound and fails past it - a small compressed input cannot expand to arbitrary memory ahead of the hash check - and the decoder's own state is capped too (`xzMaxDecoderMemoryBytes`; the dictionary size is an attacker-chosen number read from the stream header, and upstream passes no limit there). `withXzSource` decompresses a chunk source into a chunk source under the same limits, pairing with streaming NAR consumption. Concatenated streams decode as one output, matching upstream's `LZMA_CONCATENATED` decoder. The `lzma-static` dependency bundles liblzma's C sources, so the flag needs no system library on any platform - and it stays off by default anyway: the 0.5.0.0 lesson was a compression dependency nobody asked for in every install.
README.md view
@@ -54,8 +54,8 @@  -- Stream a tree's NAR and hash it in one pass; the archive never -- exists in memory. The parsing side is NovaCache.NAR.Stream, a--- chunk-fed event machine, and the xz flag adds decompression--- bounded by a narinfo's declared NarSize.+-- chunk-fed event machine, and the nova-cache:xz sublibrary adds+-- decompression bounded by a narinfo's declared NarSize. narHash <- withNarSource defaultCaseHack path $ \pull ->   let go ctx = do         chunk <- pull@@ -116,7 +116,7 @@ cabal test ``` -Optional flags: `--flag server` builds the cache server; `--flag xz` builds the bounded xz decoder (liblzma is bundled - no system library needed). Requires GHC 9.14+ and cabal-install 3.10+.+Optional extras: `--flag server` builds the cache server, and the public `nova-cache:xz` sublibrary carries the bounded xz decoder (liblzma is bundled - no system library needed) - consumers depend on it with `build-depends: nova-cache:xz`. Requires GHC 9.14+ and cabal-install 3.10+.  --- 
nova-cache.cabal view
@@ -1,12 +1,13 @@ cabal-version:      3.0 name:               nova-cache-version:            0.8.0.0+version:            0.9.0.0 synopsis:           Pure-first Nix binary cache protocol library description:   A pure-first library implementing the Nix binary cache protocol -   nix-base32, NAR serialization (whole-tree and streaming), narinfo-  parsing, Ed25519 signing, store path handling, content validation,-  and bounded xz decompression - with an optional WAI server.+  parsing, Ed25519 signing, store path handling, and content+  validation - with an optional WAI server, and bounded xz+  decompression as the public @nova-cache:xz@ sublibrary.  license:            Apache-2.0 license-file:       LICENSE@@ -29,11 +30,6 @@   default:     False   manual:      True -flag xz-  description: Build NovaCache.Xz, bounded xz decompression (lzma-static bundles liblzma; no system library)-  default:     False-  manual:      True- library   exposed-modules:     NovaCache.Base32@@ -63,11 +59,27 @@     , vector              >= 0.12 && < 0.14     , wai                 >= 3.2 && < 3.3 --  if flag(xz)-    exposed-modules: NovaCache.Xz-    build-depends:   lzma-static >= 5.2.5 && < 5.3+  hs-source-dirs:   src+  default-language:  Haskell2010+  default-extensions:+    BangPatterns+    OverloadedStrings+  ghc-options:+    -Wall+    -Wcompat+    -Wincomplete-record-updates+    -Wincomplete-uni-patterns +-- The bounded xz decoder as a solver-visible opt-in: a consumer that+-- substitutes foreign caches writes build-depends: nova-cache:xz and+-- gets the module; everyone else never builds lzma-static's bundled+-- liblzma.  This replaces the manual xz flag - a dependency's flag+-- cannot be set from a consumer's .cabal file, which forced mirror+-- flags and matching constraints downstream (nova-nix#27) - while+-- keeping the 0.5.0.0 lesson: xz stays out of the default install.+library xz+  visibility:       public+  exposed-modules:  NovaCache.Xz   hs-source-dirs:   src   default-language:  Haskell2010   default-extensions:@@ -79,6 +91,11 @@     -Wincomplete-record-updates     -Wincomplete-uni-patterns +  build-depends:+      base                >= 4.22 && < 5+    , bytestring          >= 0.11 && < 0.13+    , lzma-static         >= 5.2.5 && < 5.3+ executable nova-cache-server   if !flag(server)     buildable: False@@ -124,9 +141,6 @@     , wai-extra           >= 3.1 && < 3.2  test-suite nova-cache-xz-test-  if !flag(xz)-    buildable: False-   type:             exitcode-stdio-1.0   main-is:          XzTest.hs   hs-source-dirs:   test@@ -138,7 +152,7 @@   build-depends:       base                >= 4.22 && < 5     , bytestring          >= 0.11 && < 0.13-    , nova-cache+    , nova-cache:xz  source-repository head   type:     git
src/NovaCache/Xz.hs view
@@ -14,13 +14,14 @@ -- Concatenated streams decode as one output, matching upstream's -- @LZMA_CONCATENATED@ decoder in libutil's compression sink. ----- This module builds only under the @xz@ cabal flag.  The+-- This module lives in the public @nova-cache:xz@ sublibrary.  The -- @lzma-static@ dependency bundles liblzma's C sources, so no system -- library is needed on any platform - but it is still an extra C -- build that consumers without foreign-cache needs should not pay--- for, and a default-on compression flag broke downstream installs--- once already (0.5.0.0).  The flag is manual and off by default;--- consumers that substitute from foreign caches turn it on.+-- for, and a default-on compression dependency broke downstream+-- installs once already (0.5.0.0).  Consumers that substitute from+-- foreign caches depend on @nova-cache:xz@; everyone else never+-- builds it. module NovaCache.Xz   ( XzLimits (..),     defaultXzDecoderMemoryBytes,