ecluse:ecluse-runtime
Safe HaskellNone
LanguageGHC2021

Ecluse.Runtime.Cve.Sync.Internal

Description

The fetch transport, the one-cycle step and the scheduled task behind Ecluse.Runtime.Cve.Sync, which documents the sync and re-exports the curated surface. Importing this module opts out of that stability promise, the convention text and bytestring use, so production code imports the public one.

Synopsis

The injected transport

data CveFetch Source #

The advisory transport supplied to syncStep by newS3CveSource.

Constructors

CveFetch 

Fields

data FetchedObject Source #

Metadata from one HEAD or GET response. A download carries its own metadata, so a publication racing HEAD cannot mislabel the downloaded bytes.

Constructors

FetchedObject 

Fields

newtype DbEtag #

Constructors

DbEtag Text 

Instances

Instances details
Show DbEtag 
Instance details

Defined in Ecluse.Core.Cve.Types

Eq DbEtag 
Instance details

Defined in Ecluse.Core.Cve.Types

Methods

(==) :: DbEtag -> DbEtag -> Bool #

(/=) :: DbEtag -> DbEtag -> Bool #

data OsvDbFetchFault Source #

Why an artifact fetch did not yield usable bytes. Every one is a value on the CveFetch channel, never an exception, and syncStep folds it into its outcome.

Constructors

OsvDbTooLarge Int

The object exceeds the configured byte cap (carried, in bytes).

OsvDbNoEtag

The response carried no ETag, so there is nothing truthful to record.

OsvDbTransport TransportFault

The transport could not deliver the object (carried, classified).

newtype OsvDbCapExceeded Source #

cappedAt sits in a conduit and has no value channel, so it reports an overstepped byte cap by throwing this confined exception. s3Download catches it and folds it into OsvDbTooLarge.

Constructors

OsvDbCapExceeded Int 

data S3CveSource Source #

An S3-backed advisory-fetch source. newS3CveSource captures one amazonka Env, so every mount's CveFetch shares one credential discovery. The composition shell never sees it.

newS3CveSource :: Maybe AwsEndpoint -> IO S3CveSource Source #

Build an S3CveSource over one S3 amazonka env, honouring the resolved endpoint override.

s3CveFetchFor :: S3CveSource -> Text -> Text -> Int -> CveFetch Source #

A CveFetch against one bucket, object key, and byte cap, over the captured env.

cappedAt :: forall (m :: Type -> Type). MonadIO m => Int -> ConduitT ByteString ByteString m () Source #

A breach throws OsvDbCapExceeded before yielding the excess chunk. The S3 adapter folds it into OsvDbTooLarge.

One sync cycle

data SyncEnv Source #

Everything one ecosystem's sync task operates on.

Constructors

SyncEnv 

Fields

  • syncFetch :: CveFetch

    The transport for this ecosystem's object key.

  • syncEcosystem :: Ecosystem

    The ecosystem the artifact must verify as.

  • syncEpssRequirement :: EpssRequirement

    Whether this ecosystem requires successful EPSS enrichment.

  • syncDbPath :: FilePath

    The canonical on-disk artifact path (the stable per-ecosystem name).

  • syncSlot :: CveSlot

    The slot this task's swaps publish to.

  • syncStoreRef :: Text

    How the configured store reads back, for the reports that name where an artifact belongs.

data SyncOutcome Source #

What one syncStep concluded. The caller (runCveSync) logs it and decides scheduling.

Constructors

SyncSwapped DbEtag [(Text, Text)]

Verification accepted a new artifact and it is now live (its ETag and provenance carried).

SyncUnchanged

No database replacement, though an accepted republication can advance publication time.

SyncAbsent

The object does not exist in the bucket (not yet published).

SyncRejected DbEtag CveDbRejected

The artifact downloaded, and verification refused it. The last-good generation keeps serving and the sync remembers the ETag.

SyncFetchFaulted OsvDbFetchFault

The fetch itself failed (carried). The step learned nothing about the remote artifact, so the last seen ETag stands and the schedule retries.

Instances

Instances details
Show SyncOutcome Source # 
Instance details

Defined in Ecluse.Runtime.Cve.Sync.Internal

syncStep :: SyncEnv -> Maybe DbEtag -> IO SyncOutcome Source #

One detect-download-verify-swap cycle against the last seen ETag. Total over the fetch and over verification: a failed fetch and a refused artifact are outcomes, not exceptions.

The scheduled task

data SyncSchedule Source #

The task's timing: the boot burst's backoff delays and the steady poll interval, both in microseconds. The composition root ships bootBackoffDelays and the configured poll interval.

Constructors

SyncSchedule 

Fields

data SyncHooks Source #

What the shell hangs off one sync task. Both run inside the task, so neither may block it, and both must tolerate being called again.

Constructors

SyncHooks 

Fields

  • hookFirstSync :: IO ()

    Runs after every swap, so it must be idempotent.

  • hookPushAge :: IO ()

    Runs after every step, settled or not, so the push age is read on a poll that changed nothing.

runCveSync :: (MonadUnliftIO m, KatipContext m) => AdvisorySyncMetricsPort -> AdvisorySyncTracingPort -> SyncEnv -> SyncSchedule -> SyncHooks -> m () Source #

Retry at boot, then poll forever. A refused artifact ends the boot burst.

bootBackoffDelays :: [Int] Source #

The shipped boot-burst backoff: an immediate first attempt, then a retry after each delay, then the burst concedes to the steady poll. The poll interval, not this, is the operator's knob.

absentReportInterval :: Int Source #

The shipped gap, in microseconds, between repeats of the unloaded-database and fetch-failure reports. The rules' outage reminder paces on the same gap.