| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Ecluse.Core.Server.Pipeline.Internal
Description
Internal guts of the serve pipeline (Ecluse.Core.Server.Pipeline), exposed for
tests without widening that module's two-handler public API -- the .Internal convention,
as Ecluse.Core.Credential.Refresh.Internal uses. Importing it opts out of the public
module's stability promise.
It holds the operator-facing warning helpers for two bad-upstream conditions the
response-bound guards leave silent -- an upstream whose body does not decode into a
usable packument (logDecodeFailure), and one whose packument self-reports a name for
a different package (logNameMismatch) -- each surfaced at a WarningS through the
ambient katip context before the contribution degrades. The conditions themselves are
classified on the serve path as a typed MetadataError;
this module only renders their warning lines. Alongside them sit the pure integrity-floor
admission and the metric-label projections the serve path records.
Synopsis
- logDecodeFailure :: KatipContext m => PackageName -> m ()
- logNameMismatch :: KatipContext m => PackageName -> Text -> Text -> m ()
- admitByIntegrity :: IntegrityFloor floor => floor -> ServeDecision -> ServeDecision -> PackageInfo -> (PackageInfo, [ServeDecision])
- packumentServeDecision :: [ServeDecision] -> Decision
- serveDecisionClass :: ServeDecision -> Decision
- denialLabels :: RejectReason -> (Maybe Text, ReasonClass)
- evalTier :: [PreparedRule] -> Tier
- transienceCause :: Transience -> Cause
- recordDenials :: MetricsPort -> [ServeDecision] -> IO ()
- recordEffectfulFailures :: MetricsPort -> [Decision] -> IO ()
Documentation
logDecodeFailure :: KatipContext m => PackageName -> m () 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.Core.Server.Pipeline, so an operator sees an undecodable upstream distinctly
rather than as silence. Emitted through the ambient katip context (the request's, so
the line carries its trace-correlation dd).
logNameMismatch :: KatipContext m => PackageName -> Text -> Text -> m () 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.
Integrity-floor admission (pure)
admitByIntegrity :: IntegrityFloor floor => floor -> ServeDecision -> ServeDecision -> PackageInfo -> (PackageInfo, [ServeDecision]) Source #
Apply an integrity-floor admission policy to a PackageInfo, keeping only the versions
whose strongest digest meets the floor and projecting the rest to refusals. A version
whose digests are all weaker than the floor (or absent) cannot be tied to a
floor-strength tamper-evident fingerprint, so it is dropped from the served listing rather
than served a client could never safely verify. Used by both gates: the public gate
(gatePublic) with the hard-floored MinIntegrity, and the
trusted gate (admitTrusted) with the loosenable
MinTrustedIntegrity. Returns the admissible PackageInfo
(with dist-tags pruned to the kept keys, exactly as restrictToSurvivors prunes for the
rules; each kept version carries its own publish time, so restricting the versions carries
the times with it) and the refusals for the dropped versions: BelowIntegrityFloor for a
too-weak digest, MissingIntegrity for none at all, each feeding the no-survivors
status.
Metric-label projections (pure)
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 :: [PreparedRule] -> Tier Source #
The rule-evaluation tier a duration is attributed to, from the mount's rule set: a mount with any resilient (effectful) rule is attributed to the effectful tier; a purely-pure rule set reduces to the structural tier. The resilience policy a prepared rule carries -- not a separate list -- is what distinguishes an effectful rule now that the two tiers are one engine.
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 :: MetricsPort -> [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 :: MetricsPort -> [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.