0.6.0.0 batch: the small-fix backlog - #27
Merged
Merged
Conversation
… marker check, SecretKey redaction, TTL-cached root stat
This was referenced Jul 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #18, #19, #21, #16, #22; part of #20 (the remaining item, entry names as bytes, stays open for 0.7.0.0 - it is a breaking rework that interacts with the fresh checkName guards). Rides the 0.6.0.0 major already opened by #26, so the batch ships in one release.
#18 - store-path names reject dot segments. parseBaseName accepted ".", "..", ".-x", "..-y", so paths no Nix client parses could be stored and signed. The rule is upstream's checkName dot rule - the first dash-separated component may not be "." or ".." - with ".config-1.0"-style names staying valid. Same rule nova-nix enforces at its parse and construction boundaries.
#19 - size fields are length-bounded before parsing. NarSize/FileSize parsed digit-by-digit into an unbounded Integer, quadratic in field length, before any consumer looked at the value. Sizes are uint64 on the wire (at most 20 digits, named constant); longer fields reject first, making the parse cost constant. The uint64 maximum itself still parses, pinned.
#20 (two of three) - executable marker must be empty; duplicate scalar keys last-wins. The parser accepted any marker value where the format fixes the empty string, and duplicated narinfo keys resolved first-wins where upstream's assign-as-read parser takes the last. lookupFirst is now lookupLast (Sig stays the intentionally repeatable key via lookupAll).
#21 - SecretKey no longer derives Show or Eq. The derived Show rendered the raw Ed25519 bytes through any enclosing Show - a config record, a debug trace - and the derived Eq compared secret material in input-dependent time. Show now renders the key name plus a redaction marker (deliberately not read-back-able); Eq compares the bytes with Data.ByteArray.constEq. The name compares normally - it is public. This also covers the nova-nix PushConfig exposure noted in its class G register.
#16 - the fingerprint sort test pins the whole references field. The old isSuffixOf needle also matched the pre-fix unsorted rendering; the needle now includes the leading field separator, so a regression to unsorted output fails.
#22 - the landing page's store scan is TTL-bounded. New NovaCache.Server.newTTLCache (monotonic clock, so wall-time jumps cannot starve the refresh; concurrent refreshes may double-run the idempotent read). The bundled server counts the store at most once per minute; the unauthenticated root route does bounded work per request regardless of store size. landingResponse takes the count action injected, keeping the library brand-free.
cabal test passes (all 9 groups), -Werror build with the server flag clean, ormolu and hlint clean, cabal check and sdist clean.