| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Ecluse.Server.Pipeline.Internal
Description
Internal guts of the serve pipeline (Ecluse.Server.Pipeline), exposed for tests
without widening that module's two-handler public API — the .Internal convention, as
Ecluse.Credential.Refresh.Internal uses. Importing it opts out of the public
module's stability promise.
It holds the degrade signalling for two bad-upstream conditions the response-bound
guards leave silent: PackumentUndecodable (the upstream answered, but its body did
not decode into a usable packument) and PackumentNameMismatch (the upstream
answered with a packument whose self-reported name is for a different package).
Each is a typed throw raised at the fetch and caught by the origin fetcher's
tryAny, with a paired log* surfacing it at a WarningS before the contribution
degrades.
Synopsis
- data PackumentUndecodable = PackumentUndecodable
- data PackumentNameMismatch = PackumentNameMismatch
- logDecodeFailure :: LogEnv -> PackageName -> IO ()
- logNameMismatch :: LogEnv -> PackageName -> Text -> Text -> IO ()
- fetchCause :: SomeException -> Cause
- packumentServeDecision :: [ServeDecision] -> Decision
- serveDecisionClass :: ServeDecision -> Decision
- denialLabels :: RejectReason -> (Maybe Text, ReasonClass)
- evalTier :: [a] -> Tier
- transienceCause :: Transience -> Cause
- recordDenials :: Metrics -> [ServeDecision] -> IO ()
- recordEffectfulFailures :: Metrics -> [Decision] -> IO ()
Documentation
data PackumentUndecodable Source #
Raised when an upstream packument does not decode into both the typed view and the
raw document the serve path needs. A (typed) throw, not a stringly one, caught by the
origin fetcher's tryAny and degraded to a missing contribution like a bound breach.
Constructors
| PackumentUndecodable |
Instances
| Exception PackumentUndecodable Source # | |
Defined in Ecluse.Server.Pipeline.Internal | |
| Show PackumentUndecodable Source # | |
Defined in Ecluse.Server.Pipeline.Internal Methods showsPrec :: Int -> PackumentUndecodable -> ShowS # show :: PackumentUndecodable -> String # showList :: [PackumentUndecodable] -> ShowS # | |
| Eq PackumentUndecodable Source # | |
Defined in Ecluse.Server.Pipeline.Internal Methods (==) :: PackumentUndecodable -> PackumentUndecodable -> Bool # (/=) :: PackumentUndecodable -> PackumentUndecodable -> Bool # | |
data PackumentNameMismatch Source #
Raised when an upstream answered with a packument whose self-reported top-level
name is for a different package than the one requested. The route name is the
validation authority, so a misreporting origin is untrusted for this request: its
contribution is dropped from the merge. A (typed) throw, not a stringly one, caught
by the origin fetcher's tryAny and degraded like PackumentUndecodable — but kept
a distinct type so the serve layer can render the terminal no-valid-origin status as
a 502 (an upstream returned an invalid response), distinct from a genuine absence.
Constructors
| PackumentNameMismatch |
Instances
| Exception PackumentNameMismatch Source # | |
Defined in Ecluse.Server.Pipeline.Internal | |
| Show PackumentNameMismatch Source # | |
Defined in Ecluse.Server.Pipeline.Internal Methods showsPrec :: Int -> PackumentNameMismatch -> ShowS # show :: PackumentNameMismatch -> String # showList :: [PackumentNameMismatch] -> ShowS # | |
| Eq PackumentNameMismatch Source # | |
Defined in Ecluse.Server.Pipeline.Internal Methods (==) :: PackumentNameMismatch -> PackumentNameMismatch -> Bool # (/=) :: PackumentNameMismatch -> PackumentNameMismatch -> Bool # | |
logDecodeFailure :: LogEnv -> PackageName -> IO () Source #
Log a parse failure at WarningS — the one bad-upstream condition the
response-bound guards leave silent: the upstream answered, but its body did not decode
into the typed view and raw document the serve path needs. Same fail-closed degrade and
the same module/package payload convention as the breach log in
Ecluse.Server.Pipeline, so an operator sees an undecodable upstream distinctly rather
than as silence. The module tag names this module's own path.
logNameMismatch :: LogEnv -> PackageName -> Text -> Text -> IO () Source #
Log an upstream name mismatch at WarningS before the contribution degrades: the
origin answered, but its packument self-reported a name for a different package than
the one requested, so it is dropped as untrusted for this request. The structured
payload carries both names and the origin (its base URL) — the high-cardinality
identifiers that belong on the log line — so an operator can tell a misconfigured or
hostile upstream from an ordinary outage. Same fail-closed degrade and payload
convention as logDecodeFailure.
Metric-label projections (pure)
fetchCause :: SomeException -> Cause Source #
Classify a caught metadata-fetch failure into the bounded
ecluse.upstream.fetch.errors cause: an undecodable or name-mismatched body is a decode
fault, a transport error a connection fault, and a response-bound breach or anything else
the catch-all other. The cause is bounded by construction — never the exception text.
packumentServeDecision :: [ServeDecision] -> Decision Source #
Classify a no-survivors packument outcome into the bounded ecluse.serve.decision
value: a forbidden set is a denial, any other non-served status a transient
unavailability. (A served set is recorded as an admit at the call site, not here.)
serveDecisionClass :: ServeDecision -> Decision Source #
Classify a single artifact-path serve decision into the bounded metric decision: a policy or integrity refusal is a denial, an upstream outage or invalid response an unavailability.
denialLabels :: RejectReason -> (Maybe Text, ReasonClass) Source #
Map a reject reason to the ecluse.rule.denials labels: the deciding rule (only a
policy denial names one) and the bounded reason class.
evalTier :: [a] -> Tier Source #
The rule-evaluation tier a duration is attributed to, from the mount's effectful rule list: a mount with effectful rules configured runs the effectful tier (the pure tier first, the effectful tier only where it could change the outcome), otherwise the evaluation reduces to the structural tier. Polymorphic in the rule element — only emptiness is consulted — so it is exercised without constructing a rule.
transienceCause :: Transience -> Cause Source #
Map an undecidable verdict's transience to the bounded
ecluse.rule.effectful.failures cause: a retryable cause is a connection-class fault (the
source was unreachable now), a permanent one the catch-all other.
Metric emits (off a serve outcome)
recordDenials :: Metrics -> [ServeDecision] -> IO () Source #
Record the ecluse.rule.denials counter for each rejected decision, labelled by
the bounded reason class and — for a policy denial — the deciding rule name
(denialLabels). An admit records nothing.
recordEffectfulFailures :: Metrics -> [Decision] -> IO () Source #
Count each effectful-rule failure among a packument's per-version decisions: an
Undecidable is an effectful rule whose source could not be consulted, so it is the
effectful-failure signal, classified to a bounded cause by its transience
(transienceCause). A decided version (allowed or denied) is not a failure.