packages feed

nova-cache 0.12.0.0 → 0.12.0.1

raw patch · 3 files changed

+29/−22 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Changelog +## 0.12.0.1 - 2026-11-05++- **The README in the package describes 0.12: its version bounds, the server's required `CACHE_API_KEY`, and which codecs are pure.** The README in the 0.12.0.0 tarball, the one Hackage shows, gave bounds that exclude 0.12 itself and a server command that exits at once, since the server refuses to start without `CACHE_API_KEY` unless given `--allow-open-writes`. It also called the WAI server optional, where `NovaCache.Server` is always part of the library and only the executable sits behind `-f server`, and counted one-shot xz decompression and zstd compression among the `IO` operations, where both are pure. The test command now passes `--enable-tests`, as CI's does.+ ## 0.12.0.0 - 2026-11-01  - **`nova-cache-server reclaim-nars` lists, and with `--delete` removes, the NARs no narinfo references.** A client uploads a path's NAR before its narinfo, as upstream's `BinaryCacheStore::addToStoreCommon` does, so a NAR whose narinfo the server refuses, or whose push dies before the narinfo, stayed under `nar/` for good: the server has no route that deletes, and gains none. The subcommand runs on the host against the store directory. A narinfo names its NAR by its `URL` alone, as upstream reads it (`getFile(info->url)`), with the compression suffix part of the name. Three rules guard a run. A NAR is eligible only once it is two weeks old by its modification time (`--min-age-hours` overrides), because a NAR is unreferenced until its push sends the narinfo and nothing bounds how long a push takes; git's `gc.pruneExpire` gives unreferenced objects the same two weeks against the same race. A narinfo that cannot be read, parsed, or resolved to `nar/<file>` blocks the whole run instead of being skipped, since the NAR it names would otherwise look unreferenced. And a store holding NARs and no narinfo at all blocks it too, since one that lost its `narinfo/` directory, which the server recreates empty when it starts, looks the same as one whose every NAR is unreferenced. A run is not atomic with the server, so it belongs on a cache with no push in progress: a narinfo that arrives during a run for a NAR past the minimum age, as upstream's `nix copy` can send after skipping a NAR already present, loses that NAR. Upstream ships no garbage collection for binary caches, so there is no behavior to match beyond the URL. The library gains `NovaCache.Reclaim` (the pure selection and the store scan) and, in `NovaCache.Store`, `listNarFiles`, `listNarInfoFiles`, `removeNar` and `fileStoreAt`, a constructor that creates no directories; `time` joins the dependencies.
README.md view
@@ -6,26 +6,28 @@  nova-cache implements the Nix binary cache protocol in Haskell: nix-base32, NAR serialization (whole-tree and streaming), narinfo parsing, store paths,-Ed25519 signing and upload validation, and an optional WAI cache server.+Ed25519 signing and upload validation, a WAI application for a cache server,+and an optional server executable. Bounded xz, zstd and bzip2 codecs are the public `nova-cache:xz`, `nova-cache:zstandard` and `nova-cache:bzip2` sublibraries, and the zstd codec also compresses for uploads. -Parsing, formatting, hashing, signing and validation are pure. Reading and-writing trees, hashing files, the codecs, the store and the server run in-`IO`. nova-cache is the protocol layer under+Parsing, formatting, hashing, signing, validation, one-shot xz decompression+and zstd compression are pure. Reading and writing trees, hashing files, the+streaming codecs, zstd and bzip2 decompression, the store and the server run+in `IO`. nova-cache is the protocol layer under [nova-nix](https://github.com/Novavero-AI/nova-nix).  ## Installation  ```cabal-build-depends: nova-cache >= 0.11 && < 0.12+build-depends: nova-cache >= 0.12 && < 0.13 ```  The codecs are separate sublibraries, named alongside the main library:  ```cabal-build-depends: nova-cache:{nova-cache, xz, zstandard} >= 0.11 && < 0.12+build-depends: nova-cache:{nova-cache, xz, zstandard} >= 0.12 && < 0.13 ```  libbz2 and libzstd are bundled. liblzma comes from the `xz` package, which@@ -50,7 +52,8 @@ -- Parse a narinfo and sign it case (parseNarInfo raw, parseSecretKey "mykey:base64...") of   (Right ni, Right sk) -> print (sign sk ni)  -- Right "mykey:<base64 sig>"-  _                    -> error "parse failed"+  (Left err, _)        -> putStrLn err+  (_, Left err)        -> putStrLn err ```  ```haskell@@ -83,9 +86,12 @@ ## Server  ```bash-cabal run --flag server nova-cache-server -- --port 5000 --store ./nix-cache+CACHE_API_KEY=change-me cabal run --flag server nova-cache-server -- --port 5000 --store ./nix-cache ``` +Without `CACHE_API_KEY` the server refuses to start. `--allow-open-writes` runs+it with unauthenticated writes, for local testing only.+ The protocol lives in the `NovaCache.Server` library module as a WAI `Application`, so the cache can be embedded in another server with its own root page. The bundled executable is one such embedding.@@ -147,11 +153,10 @@  ### Public cache -A public instance runs at `cache.novavero.ai`. It serves store paths that-nova-nix builds, which today means its Windows MinGW-w64 toolchain seed-([nova-nix#207](https://github.com/Novavero-AI/nova-nix/issues/207)). To use-it from Nix, add it to `/etc/nix/nix.conf`. On a multi-user install, Nix-ignores substituters set by users it does not trust.+A public instance runs at `cache.novavero.ai`. It serves the closure of+nova-nix's Windows `hello` recipe, which nova-nix's CI publishes on every push+to its main branch. To use it from Nix, add it to `/etc/nix/nix.conf`. On a+multi-user install, Nix ignores substituters set by users it does not trust.  ``` extra-substituters = https://cache.novavero.ai@@ -165,7 +170,7 @@ ```bash cabal update cabal build all -f server --enable-tests --ghc-options="-Werror"-cabal test -f server --ghc-options="-Werror"+cabal test -f server --enable-tests --ghc-options="-Werror" ```  ## License
nova-cache.cabal view
@@ -4,7 +4,7 @@ -- 3.0 an in-package component name shadowed its external namesake -- (the hazard the zstandard library's name dodges, documented there). name:               nova-cache-version:            0.12.0.0+version:            0.12.0.1 synopsis:           Nix binary cache protocol: NAR, narinfo, signing and a WAI server description:   The Nix binary cache protocol in Haskell: nix-base32, NAR serialization@@ -84,13 +84,11 @@     -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 the xz package'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.+-- The bounded xz decoder as a public sublibrary: a consumer that+-- substitutes from xz caches depends on nova-cache:xz, and nobody else+-- builds the xz package's bundled liblzma.  A sublibrary rather than a+-- flag, because a dependency's flag cannot be set from a consumer's+-- .cabal file. library xz   visibility:       public   exposed-modules:  NovaCache.Xz