h&,&      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~                                                                                                                                                                                                                                + Safe-Inferred%&'()*568<  Safe-Inferred%&'()*568<hackage-securityCast from one type to anotherBy default (for language with type inference) we just compare the types returned by ; however, in languages in which terms can have more than one type this may not be the correct definition (indeed, for such languages we cannot give an instance of ).hackage-security&Embedded languages with type inferencehackage-security9Equality check that gives us a type-level equality proof.hackage-securityType equality proofsThis is a direct copy of "type-equality:Data.Type.Equality"; if we don't mind the dependency we can use that package directly.  Safe-Inferred%&'()*568<55 Safe-Inferred%&'()*568<hackage-securityProduce a human-readable string Safe-Inferred%&'()*568<Ghackage-securityType f satisfies  SomeShow f if f a satisfies Show independent of ahackage-securityType f satisfies  SomeShow f if f a satisfies Show independent of ahackage-securityType f satisfies SomeEq f if f a satisfies Eq independent of a !"#$"# !$ Safe-Inferred%&'()*568<s*hackage-security Abstract over a file system rootsee D,hackage-security?A file system root can be interpreted as an (absolute) FilePath-hackage-securityConvert a Path to an absolute FilePath (using native style directory separators).1hackage-security!Type-level tag for unrooted paths:Unrooted paths need a root before they can be interpreted.2hackage-securityPathsA 2 is simply a  with a type-level tag indicating where this path is rooted (relative to the current directory, absolute path, relative to a web domain, whatever). Most operations on 2? are just lifted versions of the operations on the underlying . The tag however allows us to give a lot of operations a more meaningful type. For instance, it does not make sense to append two absolute paths together; instead, we can only append an unrooted path to another path. It also means we avoid bugs where we use one kind of path where we expect another.4hackage-securityReinterpret the root of a pathThis literally just changes the type-level tag; use with caution!;hackage-securityReinterpret an unrooted pathThis is an alias for 4; see comments there.<hackage-securityForget a path's rootThis is an alias for 4; see comments there.=hackage-securityConvert a relative/unrooted Path to a FilePath (using POSIX style directory separators). See also ->hackage-securityConvert from a relative/unrooted FilePath (using POSIX style directory separators).?hackage-security5A path fragment (like a single directory or filename)Ghackage-securityWrapper around GHhackage-securityWrapper around (openBinaryTempFileWithDefaultPermissionsNOTE: The caller is responsible for cleaning up the temporary file.Vhackage-security,Return the immediate children of a directory Filters out "." and "..".Whackage-security(Recursive traverse a directory structureReturns a set of paths relative to the directory specified. The list is lazily constructed, so that directories are only read when required. (This is also essential to ensure that this function does not build the entire result in memory before returning, potentially running out of heap.)Xhackage-securityOldhackage-securityNew[hackage-security Path of the .tar filehackage-securityBase directoryhackage-security&Files to add, relative to the base dir  ()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_234567891:;<=>?@AB0/.,-*+CDEFGHIJKLMNOPQRSTUVWXY)Z[(\]^_   Safe-Inferred%&'()*568< hackage-securityMonomorphic traversalhackage-securityPolymorphic traversalhackage-securityMonomorphic lenshackage-securityPolymorphic lens Safe-Inferred%&'()*568<$ohackage-security?Attempt to create a filesystem lock in the specified directory.3This will use OS-specific file locking primitives: GHC.IO.Handle.Lock with #base-4.10" and later or a shim for base@ versions.&Blocks if the lock is already present.The logger callback passed as first argument is invoked before and after acquiring a lock, and after unlocking.May fallback to locking via creating a directory: Given a file pathto4, we do this by attempting to create the directory /pathto/hackage-security-lock, and deleting the directory again afterwards. Creating a directory that already exists will throw an exception on most OSs (certainly Linux, OSX and Windows) and is a reasonably common way to implement a lock file. Safe-Inferred%&'()*568<&Dhackage-securityMultiple exit points#We can simulate the imperative code if (cond1) return exp1; if (cond2) return exp2; if (cond3) return exp3; return exp4;as multipleExitPoints $ do when (cond1) $ exit exp1 when (cond2) $ exit exp2 when (cond3) $ exit exp3 return exp4hackage-securityFunction exit point (see ) Safe-Inferred%&'()*568<* hackage-security1Wrap an action that may throw a checked exceptionThis is used internally in l6 to avoid impredicative instantiation of the type of / unsafeCoerce.hackage-security7Wraps up an async exception as a synchronous exception.khackage-securityChecked exceptionshackage-security=Determine if an exception is asynchronous, based on its type.hackage-security, but immediately rethrows asynchronous exceptions (as determined by ).mhackage-securityThrow a checked exceptionnhackage-securityCatch a checked exceptionohackage-securityn with the arguments reversedphackage-securityLike try, but for checked exceptionsqhackage-security+Rethrow IO exceptions as checked exceptionsrhackage-securityThrow an unchecked exceptionThis is just an alias for throw, but makes it evident that this is a very intentional use of an unchecked exception.shackage-security Variation on r for internal errors klmnopqrs klmnopqrs Safe-Inferred%&'()*568<-xhackage-securityThe cache directoryyhackage-security/Paths relative to the root of the index tarballzhackage-securityThe root of the index tarball{hackage-security,Paths relative to the root of the repository|hackage-securityThe root of the repositoryRepository roots can be anchored at a remote URL or a local directory. Note that even for remote repos |" is (potentially) different from (& -- for a repository located at, say,  http://hackage.haskell.org4 they happen to coincide, but for one location at  $http://example.com/some/subdirectory they do not.hackage-security0Anchor a cache path to the location of the cache wxyz{|}~ Safe-Inferred%&'()*568<0Y hackage-securityLayout of a repositoryhackage-securityTUF root metadatahackage-security TUF timestamphackage-security TUF snapshothackage-securityTUF mirrors listhackage-securityCompressed index tarballhackage-securityUncompressed index tarballhackage-securityPath to the package tarballhackage-securityThe layout used on Hackagehackage-security/Layout used by cabal for ("legacy") local reposObviously, such repos do not normally contain any of the TUF files, so their location is more or less arbitrary here.  Safe-Inferred%&'()*568<58 hackage-security&Location of the various files we cacheAlthough the generic TUF algorithms do not care how we organize the cache, we nonetheless specify this here because as long as there are tools which access files in the cache directly we need to define the cache layout. See also comments for defaultCacheLayout.hackage-securityTUF root metadatahackage-security TUF timestamphackage-security TUF snapshothackage-securityTUF mirrors listhackage-securityUncompressed index tarballhackage-security'Index to the uncompressed index tarballhackage-securityCompressed index tarballWe cache both the compressed and the uncompressed tarballs, because incremental updates happen through the compressed tarball, but reads happen through the uncompressed one (with the help of the tarball index).hackage-security#The cache layout cabal-install usesWe cache the index as  cache /00-index.tar; this is important because `cabal-install` expects to find it there (and does not currently go through the hackage-security library to get files from the index).  Safe-Inferred%&'()*568<;hackage-securityVerification monad%The verification monad is similar to  ResourceT in intent, in that we can register handlers to be run to release resources. Unlike  ResourceT, however, we maintain _two_ handlers: a cleanup handler which is run whether or not verification succeeds, and a finalisation handler which is run only if verification succeeds.&Cleanup handlers are registered using , and are guaranteed to run just before the computation terminates (after the finalisation handler).The finalisation handlers are run only when verification succeeds, and can be registered with . Finalisation can be used for instance to update the local cache (which should only happen if verification is successful).hackage-securityRun an action in the  monadhackage-securityAcquire a resource and register the corresponding cleanup handlerNOTE: Resource acquisition happens with exceptions masked. If it is important that the resource acquistion can be timed out (or receive other kinds of asynchronous exceptions), you will need to use an interruptible operation. See  ?http://www.well-typed.com/blog/2014/08/asynchronous-exceptions/ for details.hackage-security:Register an action to be run only if verification succeedshackage-security#Create a short-lived temporary fileCreates the directory where the temp file should live if it does not exist.hackage-securityTemp directoryhackage-securityTemplate Safe-Inferred%&'()*568<>hackage-securityHasFormat fs f is a proof that f is a key in fs.See  and  for typical usage.hackage-securityAvailable formatsRather than having a general list here, we enumerate all possibilities. This means we are very precise about what we expect, and we avoid any runtime errors about unexpected format definitions.NOTE: If we add additional cases here (for dealing with additional formats) all calls to error "inaccessible" need to be reevaluated.hackage-security:Format is a singleton type (reflection type to term level)=NOTE: In the future we might add further compression formats. .(c) Galois, Inc. 2007-2009, Duncan Coutts 2015 Safe-Inferred%&'()*568<G$hackage-security54-bit integer values5JavaScript can only safely represent numbers between  -(2^53 - 1) and 2^53 - 1.TODO: Although we introduce the type here, we don't actually do any bounds checking and just inherit all type class instance from Int64. We should probably define  to do bounds checking, give different instances for type classes such as  and , etc.hackage-securityRender a JSON value in canonical form. This rendered form is canonical and so allows repeatable hashes.-For pretty printing, see prettyCanonicalJSON.NB: Canonical JSON's string escaping rules deviate from RFC 7159 JSON which requires"All Unicode characters may be placed within the quotation marks, except for the characters that must be escaped: quotation mark, reverse solidus, and the control characters (U+0000 through U+001F)."Whereas the current specification of Canonical JSON explicitly requires to violate this by only escaping the quotation mark and the reverse solidus. This, however, contradicts Canonical JSON's statement that "Canonical JSON is parsable with any full JSON parser"Consequently, Canonical JSON is not a proper subset of RFC 7159.hackage-securityParse a canonical JSON format string as a JSON value. The input string does not have to be in canonical form, just in the "canonical JSON" format.Use  to convert into canonical form.hackage-security Parse an intTODO: Currently this allows for a maximum of 15 digits (i.e. a maximum value of 999,999,999,999,999") as a crude approximation of the  range.hackage-securityRender a JSON value in a reasonable human-readable form. This rendered form is not the canonical form" used for repeatable hashes, use  for that.hackage-securityPunctuate in this style:  [ foo, bar ]$if it fits, or vertically otherwise:  [ foo , bar ]   Safe-Inferred%&'()*568<Hhackage-security+Monads in which we can report schema errorshackage-security Used in the  instance for hackage-security Used in the  instance for hackage-security"Extract a field from a JSON object Safe-Inferred%&'()*568<Ihackage-securitySimple wrapper around bytestring with ToJSON and FromJSON instances that use base64 encoding. Safe-Inferred%&'()*568<Khackage-securityCompute the key ID of a keyhackage-securityThe key ID of a key, by definition, is the hexdigest of the SHA-256 hash of the canonical JSON form of the key where the private object key is excluded.NOTE: The FromJSON and ToJSON instances for KeyId are intentionally omitted. Use writeKeyAsId instead.hackage-security*Sign a bytestring and return the signatureTODO: It is unfortunate that we have to convert to a strict bytestring for ed25519  Safe-Inferred%&'()*568<MQhackage-securityA key environment is a mapping from key IDs to the corresponding keys.It should satisfy the invariant that these key IDs actually match the keys; see .hackage-security7Verify that each key ID is mapped to a key with that ID    Safe-Inferred%&'()*568<Pkhackage-security7MonadReader-like monad, specialized to key environmentshackage-securityMalformed JSON has syntax errors in the JSON itself (i.e., we cannot even parse it to a JSValue)hackage-security3Invalid JSON has valid syntax but invalid structure6The string gives a hint about what we expected insteadhackage-security1The JSON file contains a key ID of an unknown keyhackage-securitySome verification step failedhackage-securityWrong file type"Records actual and expected types.hackage-securityRender to canonical JSON formathackage-security Variation on - for files that don't require the repo layout;; Safe-Inferred%&'()*568<\ hackage-security5A signature with a key ID (rather than an actual key)This corresponds precisely to the TUF representation of a signature.hackage-security"File with uninterpreted signaturesSometimes we want to be able to read a file without interpreting the signatures (that is, resolving the key IDs) or doing any kind of checks on them. One advantage of this is that this allows us to read many file types without any key environment at all, which is sometimes useful.hackage-securityA list of signaturesInvariant: each signature must be made with a different key. We enforce this invariant for incoming untrusted data (:) but not for lists of signatures that we create in code.hackage-security,Create a new document without any signatureshackage-securitySign a documenthackage-security Variation on " that doesn't need the repo layouthackage-security/Construct signatures for already rendered valuehackage-security.General FromJSON instance for signed datatypesWe don't give a general FromJSON instance for Signed because for some datatypes we need to do something special (datatypes where we need to read key environments); for instance, see the "Signed Root" instance.hackage-securitySignature verificationNOTES: 1. By definition, the signature must be verified against the canonical JSON format. This means we _must_ parse and then pretty print (as we do here) because the document as stored may or may not be in canonical format. 2. However, it is important that we NOT translate from the JSValue to whatever internal datatype we are using and then back to JSValue, because that may not roundtrip: we must allow for additional fields in the JSValue that we ignore (and would therefore lose when we attempt to roundtrip). 3. We verify that all signatures are valid, but we cannot verify (here) that these signatures are signed with the right key, or that we have a sufficient number of signatures. This will be the responsibility of the calling code.hackage-security&Convert a pre-signature to a signature9Verifies that the key type matches the advertised method.hackage-security"Convert signature to pre-signaturehackage-securityConvert a list of s to a list of sThis verifies the invariant that all signatures are made with different keys. We do this on the presignatures rather than the signatures so that we can do the check on key IDs, rather than keys (the latter don't have an Ord instance).hackage-security6Convert list of pre-signatures to a list of signatures  Safe-Inferred%&'()*568<>dhackage-security"Types for pattern and replacements1We intentially are not very precise here, saying String (instead of FileName, BaseName, or  Directory, say) so that we can, for example, use a matched filename in a pattern as a directory in a replacement.hackage-security A delegation6A delegation is a pair of a pattern and a replacement.See match for an example.hackage-securityReplacement patterns%These constructors match the ones in : wildcards must be used in the same order as they appear in the pattern, but they don't all have to be used (that's why the base constructors are polymorphic in the stack tail).hackage-securityStructured patterns over pathsThe type argument indicates what kind of function we expect when the pattern matches. For example, we have the pattern  "*/*.txt": PathPatternDirAny (PathPatternFileExt ".txt") :: PathPattern (Directory :- BaseName :- ())TODOs (see README.md):Update this to work with Path rather than / Add different kinds of wildcardsAdd path rootsCurrently this is a proof of concept more than anything else; the right structure is here, but it needs updating. However, until we add author signing (or out-of-tarball targets) we don't actually use this yet.NOTE: Haddock lacks GADT support so constructors have only regular comments.hackage-security?The identity replacement replaces a matched pattern with itselfhackage-securityParse a patternhackage-securityParse a replacementWe cheat and use the parser for patterns and then translate using the identity replacement.hackage-securityQuasi-quoter for delegations to make them easier to write in code#This allows to write delegations as 9$(qqd "targets/*/*/*.cabal" "targets/*/*/revisions.json")(The alternative syntax which actually uses a quasi-quoter doesn't work very well because the /** bits confuse CPP: "unterminated comment")! Safe-Inferred%&'()*568<hhackage-security. (Delegation keys satisfy a similar invariant, see Targets.)hackage-securityWe give an instance for Signed Root rather than Root because the key environment from the root data is necessary to resolve the explicit sharing in the signatures.* Safe-Inferred%&'()*568<wxyz{|}~+ Safe-Inferred%&'()*568<hackage-securitySome verification errors materialize as deserialization errorsFor example: if we try to deserialize a timestamp file but the timestamp key has been rolled over, deserialization of the file will fail with .hackage-securityThe spec stipulates that if a verification error occurs during the check for updates, we must download new root information and start over. However, we limit how often we attempt this.We record all verification errors that occurred before we gave up.hackage-securityTrusted values*Trusted values originate in only two ways:.Anything that is statically known is trusted ()If we have "dynamic" data we can trust it once we have verified the the signatures (trustSigned).9NOTE: Trusted is NOT a functor. If it was we could define trustAnything :: a -> Trusted a trustAnything a = fmap (const a) (trustStatic (static ()))Consequently, it is neither a monad nor a comonad. However, we _can_ apply trusted functions to trusted arguments ().The  constructor is exported, but any use of it should be verified.hackage-securityEquivalent of Trusted isn't quite applicative (no pure, not a functor), but it is somehow Applicative-like: we have the equivalent of hackage-security:Trust all elements of some trusted (traversable) containerIf we have, say, a trusted list of values, we should be able to get a list of trusted values out of it. (trustElems :: Trusted [a] -> [Trusted a]NOTE. It might appear that the more natural primitive to offer is a -like operator such as ;trustSeq :: Applicative f => Trusted (f a) -> f (Trusted a)5However, this is unsound. To see this, consider that ((->) a) is 4 (it's the reader monad); hence, we can instantiate trustSeq at .trustSeq :: Trusted (a -> a) -> a -> Trusted aand by passing trustStatic (static id) make  a functor, which we certainly don't want to do (see comments for ).$So why is it okay when we insist on  rather than ? To see this, it's instructive to consider how we might make a ((->) a) an instance of 0. If we define the domain of enumerable types as 3class Eq a => Enumerable a where enumerate :: [a]then we can make ((->) r) traversable by instance Enumerable r => Traversable ((->) r) where sequenceA f = rebuild <$> sequenceA ((\r -> (r,) <$> f r) <$> enumerate) where rebuild :: [(r, a)] -> r -> a rebuild fun arg = fromJust (lookup arg fun)The idea is that if the domain of a function is enumerable, we can apply the function to each possible input, collect the outputs, and construct a new function by pairing the inputs with the outputs. I.e., if we had something of type  a -> IO band a is enumerable, we just run the IO action on each possible a and collect all bs to get a pure function a -> b. Of course, you probably don't want to be doing that, but the point is that as far as the type system is concerned you could.In the context of , this means that we can derive *enumPure :: Enumerable a => a -> Trusted abut in a way this this makes sense anyway. If a domain is enumerable, it would not be unreasonable to change  Enumerable to =class Eq a => Enumerable a where enumerate :: [StaticPtr a]so we could define enumPure as enumPure :: Enumerable a => a -> Trusted a enumPure x = trustStatic $ fromJust (find ((== x) . deRefStaticPtr) enumerate)In other words, we just enumerate the entire domain as trusted values (because we defined them locally) and then return the one that matched the untrusted value.The conclusion from all of this is that the types of untrusted input (like the types of the TUF files we download from the server) should probably not be considered enumerable.hackage-securityRole verificationNOTE: We throw an error when the version number _decreases_, but allow it to be the same. This is sufficient: the file number is there so that attackers cannot replay old files. It cannot protect against freeze attacks (that's what the expiry date is for), so "replaying" the same file is not a problem. If an attacker changes the contents of the file but not the version number we have an inconsistent situation, but this is not something we need to worry about: in this case the attacker will need to resign the file or otherwise the signature won't match, and if the attacker has compromised the key then he might just as well increase the version number and resign.NOTE 2: We are not actually verifying the signatures _themselves_ here (we did that when we parsed the JSON). We are merely verifying the provenance of the keys.hackage-security Variation on  verifyRole# that uses key IDs rather than keys*This is used during the bootstrap process.See  3http://en.wikipedia.org/wiki/Public_key_fingerprint.hackage-securityFor signature validationhackage-security File source (for error messages)hackage-securityPrevious version (if available)hackage-securityTime now (if checking expiry)hackage-securityFor error messages Safe-Inferred%&'()*568<hackage-security-Apply a static function to a trusted argumenthackage-security Variation on  for  hackage-security Root datahackage-securitySource (for error messages)hackage-securityPrevious version (if available)hackage-securityTime now (if checking expiry)hackage-securityMirrors to verify  Safe-Inferred%&'()*568<-hackage-security#Is a particular remote file cached?hackage-securityRepository-specific exceptionsFor instance, for repositories using HTTP this might correspond to a 404; for local repositories this might correspond to file-not-found, etc.hackage-securityVerify a download filehackage-security,Read the file we just downloaded into memory)We never read binary data, only metadata.hackage-security)Copy a downloaded file to its destinationhackage-security>Records why we are downloading a file rather than updating it.hackage-security-Server does not support incremental downloadshackage-security0We don't have a local copy of the file to updatehackage-securityUpdate failed twiceIf we attempt an incremental update the first time, and it fails, we let it go round the loop, update local security information, and try again. But if an incremental update then fails _again_, we instead attempt a regular download.hackage-securityUpdate failed (for example: perhaps the local file got corrupted)hackage-security Log messages We use a  rather than a {# here because we might not have a { for the file that we were trying to download (that is, for example if the server does not provide an uncompressed tarball, it doesn't make much sense to list the path to that non-existing uncompressed tarball).hackage-securityRoot information was updatedThis message is issued when the root information is updated as part of the normal check for updates procedure. If the root information is updated because of a verification error WarningVerificationError is issued instead.hackage-securityA verification errorVerification errors can be temporary, and may be resolved later; hence these are just warnings. (Verification errors that cannot be resolved are thrown as exceptions.)hackage-security!Download a file from a repositoryhackage-security/Incrementally updating a file from a repositoryhackage-securitySelected a particular mirrorhackage-security;Updating a file failed (we will instead download it whole)hackage-securityWe got an exception with a particular mirror (we will try with a different mirror if any are available)hackage-securityThis log event is triggered before invoking a filesystem lock operation that may block for a significant amount of time; once the possibly blocking call completes successfully,  will be emitted.hackage-security7Denotes completion of the operation that advertised a  eventhackage-security>Denotes the filesystem lock previously acquired (signaled by ) has been released.hackage-securityAre we requesting this information because of a previous validation error?Clients can take advantage of this to tell caches to revalidate files.hackage-security RepositoryThis is an abstract representation of a repository. It simply provides a way to download metafiles and target files, without specifying how this is done. For instance, for a local repository this could just be doing a file read, whereas for remote repositories this could be using any kind of HTTP client.hackage-securityGet a file from the serverResponsibilies of :Download the file from the repository and make it available at a temporary locationUse the provided file length to protect against endless data attacks. (Repositories such as local repositories that are not susceptible to endless data attacks can safely ignore this argument.)Move the file from its temporary location to its permanent location if verification succeeds.NOTE: Calls to % should _always_ be in the scope of .hackage-security Get a cached file (if available)hackage-securityGet the cached rootThis is a separate method only because clients must ALWAYS have root information available.hackage-securityClear all cached dataIn particular, this should remove the snapshot and the timestamp. It would also be okay, but not required, to delete the index.hackage-securityOpen the tarball for reading%This function has this shape so that:We can read multiple files from the tarball without having to open and close the handle each time.We can close the handle immediately when done.hackage-securityRead the index indexhackage-securityLock the cache (during updates)hackage-securityMirror selectionThe purpose of ; is to scope mirror selection. The idea is that if we have )repWithMirror mirrorList $ someCallback5then the repository may pick a mirror before calling  someCallback, catch exceptions thrown by  someCallback, and potentially try the callback again with a different mirror.The list of mirrors may be Nothing if we haven't yet downloaded the list of mirrors from the repository, or when our cached list of mirrors is invalid. Of course, if we did download it, then the list of mirrors may still be empty. In this case the repository must fall back to its primary download mechanism.Mirrors as currently defined (in terms of a "base URL") are inherently a HTTP (or related) concept, so in repository implementations such as the local-repo repWithMirrors/ is probably just an identity operation (see  ignoreMirrors). Conversely, HTTP implementations of repositories may have other, out-of-band information (for example, coming from a cabal config file) that they may use to influence mirror selection.hackage-securityLogginghackage-securityLayout of this repositoryhackage-securityLayout of the indexSince the repository hosts the index, the layout of the index is not independent of the layout of the repository.hackage-security9Description of the repository (used in the show instance)hackage-security0Files that we might request from the local cachehackage-securityTimestamp metadata (timestamp.json)hackage-securityRoot metadata ( root.json)hackage-securitySnapshot metadata ( snapshot.json)hackage-securityMirrors list ( mirrors.json)hackage-security6Abstract definition of files we might have to download is parametrized by the type of the formats that we can accept from the remote repository, as well as with information on whether this file is metadata actual binary content.NOTE: Haddock lacks GADT support so constructors have only regular comments.hackage-security!Default format for each file typeFor most file types we don't have a choice; for the index the repository is only required to offer the GZip-compressed format so that is the default.hackage-securityDefault file info (see also )hackage-securityHelper function to implement repWithMirrors.hackage-security+Which remote files should we cache locally? Safe-Inferred%&'()*568<hackage-securityAn IO action that represents an incoming response body coming from the server.The action gets a single chunk of data from the response body, or an empty bytestring if no more data is available.#This definition is copied from the  http-client package.hackage-securityProxy configurationAlthough actually setting the proxy is the purview of the initialization function for individual  implementations and therefore outside the scope of this module, we offer this ProxyConfiguration? type here as a way to uniformly configure proxies across all s.hackage-securityDon't use a proxyhackage-securityUse this specific proxyIndividual HTTP backends use their own types for specifying proxies.hackage-securityUse automatic proxy settings"What precisely automatic means is < specific, though typically it will involve looking at the  HTTP_PROXY1 environment variable or the (Windows) registry.hackage-securityResponse headersSince different libraries represent headers differently, here we just abstract over the few response headers that we might want to know about.hackage-security$Server accepts byte-range requests (Accept-Ranges: bytes)hackage-securityHTTP status codehackage-security200 OKhackage-security206 Partial Contenthackage-securityAdditional request headersSince different libraries represent headers differently, here we just abstract over the few request headers that we might want to sethackage-securitySet Cache-Control: max-age=0hackage-securitySet Cache-Control: no-transformhackage-securityAbstraction over HTTP clientsThis avoids insisting on a particular implementation (such as the HTTP package) and allows for other implementations (such as a conduit based one).5NOTE: Library-specific exceptions MUST be wrapped in .hackage-securityDownload a filehackage-securityDownload a byte range6Range is starting and (exclusive) end offset in bytes.HTTP servers are normally expected to respond to a range request with a "206 Partial Content" response. However, servers can respond with a "200 OK" response, sending the entire file instead (for instance, this may happen for servers that don't actually support range requests, but for which we optimistically assumed they did). Implementations of + may accept such a response and inform the hackage-security library that the whole file is being returned; the security library can then decide to execute the  anyway (downloading the entire file) or abort the request and try something else. For this reason the security library must be informed whether the server returned the full file or the requested range.hackage-security Construct a Body reader from a lazy bytestringThis is appropriate if the lazy bytestring is constructed, say, by calling  hGetContents on a network socket, and the chunks of the bytestring correspond to the chunks as they are returned from the OS network layer.If the lazy bytestring needs to be re-chunked this function is NOT suitable. Safe-Inferred%&'()*568< hackage-security&Location and layout of the local cachehackage-security)Cache a previously downloaded remote filehackage-securityRebuild the tarball index5Attempts to add to the existing index, if one exists.TODO: Use throwChecked rather than throwUnchecked, and deal with the fallout. See  8https://github.com/well-typed/hackage-security/issues/84.hackage-security Get a cached file (if available)hackage-security#Get the cached index (if available)hackage-securityGet the cached rootCalling  without root info available is a programmer error and will result in an unchecked exception. See requiresBootstrap.hackage-security*Delete a previously downloaded remote filehackage-securityLock the cacheThis avoids two concurrent processes updating the cache at the same time, provided they both take the lock.hackage-security Variant of  which emits s before and after a possibly blocking file-locking system callhackage-security Variation on  that takes in the initial    Safe-Inferred%&'()*568<hackage-security%How much of the existing file to keephackage-securityRemote repository configuration(This is purely for internal convenience.hackage-securityThe file we requested from the server was larger than expected (potential endless data attack)hackage-security)Download method (downloading or updating)hackage-securityWe select a mirror in  (the implementation of ). Outside the scope of ' no mirror is selected, and a call to  will throw an exception. If this exception is ever thrown its a bug: calls to  (&) should _always_ be in the scope of .hackage-security,Repository options with a reasonable defaultClients should use defaultRepositoryOpts and override required settings.hackage-securityAllow additional mirrors?If this is set to True (default), in addition to the (out-of-band) specified mirrors we will also use mirrors reported by those out-of-band mirrors (that is,  mirrors.json).hackage-securityFor most files we download we know the exact size beforehand (because this information comes from the snapshot or delegated info)hackage-securityFor some files we might not know the size beforehand, but we might be able to provide an upper bound (timestamp, root info)hackage-securityInternal type recording the various server capabilities we supporthackage-security'Does the server support range requests?hackage-securityServer capabilitiesAs the library interacts with the server and receives replies, we may discover more information about the server's capabilities; for instance, we may discover that it supports incremental downloads.hackage-securityDefault repository optionshackage-securityVariation on getRemote where we only expect one type of resulthackage-securityRe-throw all exceptions thrown by the client API as unchecked exceptionshackage-securityLocal files are assumed trustedThere is no point tracking chain of trust for local files because that chain would necessarily have to start at an implicitly trusted (though unverified) file: the root metadata.hackage-securityJust a simple wrapper around verifyFileInfo2Throws a VerificationError if verification failed.hackage-security(To check expiry times against (if using)hackage-security Repositoryhackage-securityPackage to downloadhackage-securityDestination (see also )hackage-security Repositoryhackage-securityPackage to downloadhackage-security Destinationhackage-securityFor error messageshackage-securityFile to verifywxyz{|}~|{}~zyxw,-.,/0,12,34,35,36,37,/8,/9,/:,/;,<=,<>,<?,<@,AB,AC,AD,AE,AFGHIJKKLMNNOPQQRRSTUVWXYYZ[\]^_``abcdefghijklmnopqrstuvwxyz{|}~                                                                                                       !!!!!!!!!!!!!!!!"""""""""""""#######$$$$$$$$$$$$                       %%%%%&&&&&&&&&&&&&&&&''''''''''''(((((((()))))))))))))))))++++++++++++++++++++++                                                                               ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,                          )+,/hackage-security-0.6.2.3-KZFpmk1iqCdKoyTKr7eMpfHackage.Security.TrustedHackage.Security.Util.PathHackage.Security.Client.VerifyHackage.Security.Util.PrettyHackage.Security.Util.SomeHackage.Security.Util.CheckedHackage.Security.ServerHackage.Security.Client.FormatsText.JSON.CanonicalHackage.Security.JSONHackage.Security.Key.EnvHackage.Security.TUF.FileMap"Hackage.Security.Client.Repository*Hackage.Security.Client.Repository.HttpLib(Hackage.Security.Client.Repository.Cache)Hackage.Security.Client.Repository.Remote(Hackage.Security.Client.Repository.LocalHackage.Security.Client MyPrelude#Hackage.Security.Util.TypedEmbeddedHackage.Security.Util.StackHackage.Security.Util.LensHackage.Security.Util.IOHackage.Security.Util.ExitHackage.Security.TUF.Paths Hackage.Security.TUF.Layout.Repo!Hackage.Security.TUF.Layout.CacheHackage.Security.Util.JSONHackage.Security.Util.Base64Hackage.Security.KeyHackage.Security.TUF.SignedHackage.Security.TUF.PatternsHackage.Security.TUF.HeaderHackage.Security.TUF.MirrorsHackage.Security.TUF.CommonHackage.Security.TUF.FileInfoHackage.Security.TUF.TimestampHackage.Security.TUF.Targets!Hackage.Security.TUF.Layout.IndexHackage.Security.TUF.SnapshotHackage.Security.TUF.RootHackage.Security.TUFHackage.Security.Trusted.TCBbase GHC.StaticPtr StaticPtrGHC.IO.Handle.TypesHandleControl.Monad.IO.ClassliftIO GHC.IO.Handle hSetBufferinghSeek hFileSizehClose NoBuffering LineBufferingBlockBuffering BufferMode GHC.IO.Device SeekFromEnd RelativeSeek AbsoluteSeekSeekMode GHC.IO.IOMode WriteMode ReadWriteModeReadMode AppendModeIOModePrettypretty SomePretty somePretty DictPrettySomeShowsomeShowDictShowSomeEqsomeEqDictEqSome typecheckSome$fEqSome $fShowSome $fPrettySomeWebTarFsPathFsRoottoAbsoluteFilePathHomeDirAbsoluteRelativeUnrootedPathcastRoot takeDirectory takeFileName<.>splitExtension takeExtensionrootPath unrootPathtoUnrootedFilePathfromUnrootedFilePathfragment joinFragmentssplitFragmentsisPathPrefixOf toFilePath fromFilePath makeAbsolutefromAbsoluteFilePathwithFile openTempFile'readLazyByteStringreadStrictByteStringwriteLazyByteStringwriteStrictByteStringcopyFilecreateDirectorycreateDirectoryIfMissingremoveDirectory doesFileExistdoesDirectoryExistgetModificationTime removeFilegetTemporaryDirectorygetDirectoryContentsgetRecursiveContents renameFilegetCurrentDirectorytarIndexLookup tarAppend toURIPath fromURIPathuriPath modifyUriPath $fPrettyPath $fPrettyPath0 $fPrettyPath1 $fPrettyPath2$fFsRootHomeDir$fFsRootAbsolute$fFsRootRelative $fPrettyPath3 $fShowPath$fEqPath $fOrdPathThrowsunthrow throwChecked catchChecked handleChecked tryCheckedcheckIOthrowUnchecked internalError$fExceptionSyncException $fThrowsCatch$fShowSyncException CachePath CacheRoot IndexPath IndexRootRepoPathRepoRootanchorRepoPathLocallyanchorRepoPathRemotelyanchorCachePath RepoLayoutrepoLayoutRootrepoLayoutTimestamprepoLayoutSnapshotrepoLayoutMirrorsrepoLayoutIndexTarGzrepoLayoutIndexTarrepoLayoutPkgTarGzhackageRepoLayoutcabalLocalRepoLayout CacheLayoutcacheLayoutRootcacheLayoutTimestampcacheLayoutSnapshotcacheLayoutMirrorscacheLayoutIndexTarcacheLayoutIndexIdxcacheLayoutIndexTarGzcabalCacheLayoutVerify runVerifyacquire ifVerified openTempFile$fFunctorVerify$fApplicativeVerify $fMonadVerify$fMonadIOVerify HasFormatHFZHFSFormatsFsNoneFsUnFsGzFsUnGzFormatFUnFGzFormatGzFormatUnhasFormatAbsurd hasFormatGet formatsMap formatsMember formatsLookup $fUnifyFormat$fFunctorFormats$fShowHasFormat $fEqHasFormat $fShowFormats $fEqFormats $fEqFormat $fShowFormatInt54JSValueJSNullJSBoolJSNumJSStringJSArrayJSObjectrenderCanonicalJSONparseCanonicalJSONprettyCanonicalJSON $fReadInt54 $fShowInt54$fBoundedInt54 $fShowJSValue $fReadJSValue $fEqJSValue $fOrdJSValue $fEnumInt54 $fEqInt54$fIntegralInt54 $fDataInt54 $fNumInt54 $fOrdInt54 $fRealInt54 $fIxInt54$fFiniteBitsInt54 $fBitsInt54$fStorableInt54$fPrintfArgInt54GotExpectedReportSchemaErrorsexpected FromObjectKey fromObjectKey ToObjectKey toObjectKeyFromJSONfromJSONToJSONtoJSON expected' fromJSObject fromJSFieldfromJSOptFieldmkObjectHasKeyIdkeyIdKeyId keyIdStringKeyTypeKeyTypeEd25519 PrivateKeyPrivateKeyEd25519 PublicKeyPublicKeyEd25519Key KeyEd25519Ed25519 publicKey privateKey somePublicKeysomePublicKeyType someKeyId createKey createKey'signverifyKeyEnv keyEnvMapfromPublicKeysfromKeysemptynullinsertlookupunion$fFromJSONmKeyEnv$fToJSONmKeyEnv $fShowKeyEnv WriteJSONReadJSON_NoKeys_NoLayoutReadJSON_Keys_NoLayoutReadJSON_Keys_Layout MonadKeys localKeysaskKeysDeserializationErrorDeserializationErrorMalformedDeserializationErrorSchemaDeserializationErrorUnknownKeyDeserializationErrorValidationDeserializationErrorFileTypevalidate verifyType readKeyAsIdaddKeyswithKeys lookupKeyrunReadJSON_Keys_LayoutrunReadJSON_Keys_NoLayoutrunReadJSON_NoKeys_NoLayoutparseJSON_Keys_LayoutparseJSON_Keys_NoLayoutparseJSON_NoKeys_NoLayoutreadJSON_Keys_LayoutreadJSON_Keys_NoLayoutreadJSON_NoKeys_NoLayout runWriteJSON renderJSONrenderJSON_NoLayout writeJSONwriteJSON_NoLayout writeKeyAsId$fPrettyDeserializationError$fExceptionDeserializationError$fMonadKeysReadJSON_Keys_Layout+$fMonadReaderRepoLayoutReadJSON_Keys_Layout($fReportSchemaErrorsReadJSON_Keys_Layout!$fMonadKeysReadJSON_Keys_NoLayout*$fReportSchemaErrorsReadJSON_Keys_NoLayout,$fReportSchemaErrorsReadJSON_NoKeys_NoLayout$fFunctorWriteJSON$fApplicativeWriteJSON$fMonadWriteJSON $fMonadReaderRepoLayoutWriteJSON!$fFunctorReadJSON_NoKeys_NoLayout%$fApplicativeReadJSON_NoKeys_NoLayout$fMonadReadJSON_NoKeys_NoLayout8$fMonadErrorDeserializationErrorReadJSON_NoKeys_NoLayout$fFunctorReadJSON_Keys_NoLayout#$fApplicativeReadJSON_Keys_NoLayout$fMonadReadJSON_Keys_NoLayout6$fMonadErrorDeserializationErrorReadJSON_Keys_NoLayout$fFunctorReadJSON_Keys_Layout!$fApplicativeReadJSON_Keys_Layout$fMonadReadJSON_Keys_Layout4$fMonadErrorDeserializationErrorReadJSON_Keys_Layout$fShowDeserializationError PreSignature presignature presigMethod presigKeyIdUninterpretedSignaturesuninterpretedSigneduninterpretedSignatures Signature signature signatureKey SignaturesSignedsigned signaturesunsignedwithSignatureswithSignatures' signRenderedverifySignaturesignedFromJSONverifySignaturesfromPreSignaturetoPreSignaturefromPreSignaturestoPreSignatures DelegationHeader headerExpires headerVersion FileExpires FileVersion HasHeader fileExpires fileVersion expiresNever expiresInDays isExpiredversionInitialversionIncrementMirrorDescription MirrorContent MirrorFullMirror mirrorUrlBase mirrorContentMirrorsmirrorsVersionmirrorsExpiresmirrorsMirrorsdescribeMirrorHash KeyThreshold FileLength fileLengthFileInfofileInfoLengthfileInfoHashesHashFn HashFnSHA256 HashFnMD5fileInfocomputeFileInfocompareTrustedFileInfoknownFileInfoEqualfileInfoSHA256 FileChange FileChanged FileDeleted TargetPathTargetPathRepoTargetPathIndexFileMap!fromListfileMapChanges$fFromObjectKeymTargetPath$fToObjectKeymTargetPath$fPrettyTargetPath$fFromJSONmFileMap$fToJSONmFileMap$fShowFileChange $fShowFileMap$fShowTargetPath$fEqTargetPath$fOrdTargetPath TimestamptimestampVersiontimestampExpirestimestampInfoSnapshotDelegationSpecdelegationSpecKeysdelegationSpecThreshold delegation DelegationsdelegationsKeysdelegationsRolesTargetstargetsVersiontargetsExpirestargetsTargetstargetsDelegations targetsLookup IndexFileIndexPkgMetadata IndexPkgCabal IndexPkgPrefs IndexLayoutindexFileToPathindexFileFromPathhackageIndexLayoutindexLayoutPkgMetadataindexLayoutPkgCabalindexLayoutPkgPrefsSnapshotsnapshotVersionsnapshotExpiressnapshotInfoRootsnapshotInfoMirrorssnapshotInfoTarGzsnapshotInfoTarRoleSpec roleSpecKeysroleSpecThreshold RootRoles rootRolesRootrootRolesSnapshotrootRolesTargetsrootRolesTimestamprootRolesMirrorsRoot rootVersion rootExpiresrootKeys rootRolesVerificationHistory RootUpdatedVerificationErrorVerificationErrorSignaturesVerificationErrorExpiredVerificationErrorVersionVerificationErrorFileInfoVerificationErrorUnknownTargetVerificationErrorMissingSHA256 VerificationErrorDeserializationVerificationErrorLoopSignaturesVerifiedsignaturesVerifiedTrustedtrusted trustStatic trustVerified trustApply trustElems verifyRole'verifyFingerprints VerifyRole verifyRole<$$>trustedFileInfoEqual$fVerifyRoleMirrors$fVerifyRoleSnapshot$fVerifyRoleTimestamp$fVerifyRoleRootIsCachedCacheAs DontCache CacheIndexSomeRemoteErrorDownloadedFiledownloadedVerifydownloadedReaddownloadedCopyTo UpdateFailureUpdateImpossibleUnsupportedUpdateImpossibleNoLocalCopyUpdateFailedTwice UpdateFailed LogMessageLogRootUpdatedLogVerificationErrorLogDownloading LogUpdatingLogSelectedMirrorLogCannotUpdateLogMirrorFailed LogLockWaitLogLockWaitDone LogUnlock AttemptNr Repository repGetRemote repGetCachedrepGetCachedRoot repClearCache repWithIndexrepGetIndexIdx repLockCache repWithMirrorrepLog repLayoutrepIndexLayoutrepDescription CachedFileCachedTimestamp CachedRootCachedSnapshot CachedMirrors RemoteFileRemoteTimestamp RemoteRootRemoteSnapshot RemoteMirrors RemoteIndexRemotePkgTarGzBinaryMetadataremoteFileDefaultFormatremoteFileDefaultInfomirrorsUnsupportedremoteRepoPathremoteRepoPath' mustCache$fPrettyRemoteFile$fPrettyCachedFile$fPrettyUpdateFailure$fPrettyLogMessage$fPrettySomeRemoteError$fExceptionSomeRemoteError$fShowRepository $fEqAttemptNr$fOrdAttemptNr$fNumAttemptNr$fEqCachedFile$fOrdCachedFile$fShowCachedFile$fShowIsCached $fEqIsCached$fShowSomeRemoteError$fShowRemoteFile BodyReader ProxyConfigProxyConfigNoneProxyConfigUseProxyConfigAutoHttpResponseHeaderHttpResponseAcceptRangesBytes HttpStatusHttpStatus200OKHttpStatus206PartialContentHttpRequestHeaderHttpRequestMaxAge0HttpRequestNoTransformHttpLibhttpGet httpGetRangebodyReaderFromBS$fEqHttpResponseHeader$fOrdHttpResponseHeader$fShowHttpResponseHeader$fEqHttpRequestHeader$fOrdHttpRequestHeader$fShowHttpRequestHeaderCache cacheRoot cacheLayoutcacheRemoteFile getCachedgetCachedIndex getCachedRoot getIndexIdx withIndex clearCache lockCachelockCacheWithLogger RemoteTempRepoOptsrepoAllowAdditionalMirrorsFileSize FileSizeExact FileSizeBoundfileSizeWithinBoundsdefaultRepoOptswithRepository$fExceptionFileTooLarge$fPrettyFileTooLarge$fDownloadedFileRemoteTemp$fPrettyRemoteTemp$fShowFileSize$fShowFileTooLarge LocalFile LocalRepo$fDownloadedFileLocalFileInvalidFileInIndexinvalidFileInIndexinvalidFileInIndexRawinvalidFileInIndexErrorLocalFileCorruptedInvalidPackageExceptionIndexCallbacksindexLookupEntryindexLookupFileindexLookupFileEntryindexLookupCabalindexLookupMetadataindexLookupFileInfoindexLookupHashindexDirectory IndexEntryindexEntryPathindexEntryPathParsedindexEntryContentindexEntryContentParsedindexEntryTimeDirectoryEntrydirectoryEntryBlockNo DirectorydirectoryFirst directoryNextdirectoryLookupdirectoryEntries HasUpdates NoUpdatescheckForUpdatesdownloadPackagedownloadPackage' getDirectoryrequiresBootstrap bootstrapuncheckClientErrors$fReadDirectoryEntry$fShowDirectoryEntry$fPrettyInvalidPackageException"$fExceptionInvalidPackageException$fPrettyLocalFileCorrupted$fExceptionLocalFileCorrupted$fPrettyInvalidFileInIndex$fExceptionInvalidFileInIndex$fEqDirectoryEntry$fOrdDirectoryEntry$fShowHasUpdates$fEqHasUpdates$fOrdHasUpdates$fShowInvalidFileInIndex$fShowLocalFileCorrupted$fShowInvalidPackageExceptionGHC.Base++ghc-primGHC.PrimseqGHC.Listfilterzip System.IOprint Data.Tuplefstsnd otherwisemap$GHC.Real fromIntegral realToFracGHC.EnumBoundedminBoundmaxBoundEnumfromEnumpredsucctoEnumenumFromThenTo enumFromToenumFrom enumFromThen GHC.ClassesEq==/= GHC.FloatFloating**acosacoshasinasinhatanatanhcoscoshexploglogBasepisinsinhsqrttanhtan Fractional/ fromRationalrecipIntegraldivdivModmodquotquotRem toIntegerremMonadreturn>>=>>Functorfmap<$GHC.NumNum*+abssignumnegate fromInteger-Ordminmaxcompare><=>=<GHC.ReadRead readsPrecreadListReal toRational RealFloatatan2 decodeFloat encodeFloatexponent floatDigits floatRadix floatRangeisDenormalizedisIEEE isInfiniteisNaNisNegativeZero significand scaleFloatRealFracceilingfloorproperFractiontruncateroundGHC.ShowShowshow showsPrecshowListControl.Monad.Fail MonadFailfail Applicative<**><*>pure Data.FoldableFoldablefoldl1foldr1elemfoldMapfoldlfoldrlengthmaximumminimumsumproductData.Traversable TraversablesequencemapMtraverse sequenceA Semigroup<>Monoidmconcatmemptymappend GHC.TypesBoolFalseTrueStringCharDoubleFloatInt ghc-bignumGHC.Num.IntegerInteger GHC.MaybeMaybeNothingJustOrderingGTLTEQRationalIOWord Data.EitherEitherLeftRight||not&&GHC.ErrerrorerrorWithoutStackTrace undefined$!.=<<asTypeOfconstflipiduntilsubtractcurryuncurry Data.Functor<$> Data.Maybemaybe!!breakcycledrop dropWhileiteraterepeat replicatereversescanlscanl1scanrscanr1spansplitAttake takeWhileunzipunzip3zip3zipWithzipWith3showChar showParen showStringshowsShowS^^^evengcdlcmoddText.ParserCombinators.ReadPReadSlex readPareneither Text.Readreads Data.OldListlinesunlinesunwordswordsallandanyconcat concatMapnotElemor sequence_GHC.IO.Exception userErrorIOErrorGHC.IOFilePathioError appendFilegetChar getContentsgetLineinteractputCharputStrputStrLnreadFilereadIOreadLn writeFilemapM_readtaillastinitheadAsTypetypeOfTypedUnify:=:asTypeunifyTypeOfRefl:- Traversal' TraversalLens'Lensgetoverset withDirLockWithDirLockEventWithDirLockEventPreWithDirLockEventPostWithDirLockEventUnlock getFileSizehandleDoesNotExisttimedIOmultipleExitPointsexitWrapcoerce SyncExceptionisAsync catchSynccatchGHC.Bits FiniteBitsp_number punctuate'containers-0.6.5.1Data.Map.InternalMapBase64fromByteString toByteStringcheckKeyEnvInvariant PatternType ReplacementPatternidentityReplacement parsePatternparseReplacementqqd RepFileConst RepFileExt RepFileAny RepDirConst RepDirAny PatFileConst PatFileExt PatFileAny PatDirConst PatDirAnyBaseName ExtensionFileNamematchDelegationparseDelegation$fFromJSONmSignedDeclareTrustedrebuildTarIndex addEntries"tar-0.5.1.1-1hFLSnQnFT3Fhn8GEZhmOiCodec.Archive.Tar.Indexbuild IndexBuilder deltaSeek RemoteConfig FileTooLargeDownloadMethodSelectedMirror withMirror getRemoteServerCapabilities_serverAcceptRangesBytesServerCapabilitiesgetSelectedMirrorControl.Concurrent.MVarwithMVarhttpRequestHeadersgetFileexecBodyReaderremoteFileSizefileSizeBoundTimestampfileSizeBoundRoot uriTemplateverifyRemoteFile updateRoot getCachedInfo getRemote'trustLocalFileverifyFileInfo'