| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Ecluse.Package.Filter
Description
The ecosystem-agnostic filtering decision for a single public-upstream
packument: which versions survive a rule set, which version dist-tags.latest
resolves to, and the per-version decisions a no-survivors outcome must report.
This mirrors Ecluse.Package.Merge — the pure fold above the registry handle that
emits a plan rather than a finished document. It reasons over the typed
PackageInfo domain model only; it never touches a registry's wire
format. The per-ecosystem adapter replays this plan onto the raw upstream
document, so unmodeled wire keys survive (the typed model is lossy, so re-encoding
it would drop them). See docs/architecture/registry-model.md → "Decision
surface vs served surface".
Decision, not served surface. A FilterPlan carries exactly the decisions the
filter owns:
- Survivors. A version key survives iff the rules engine
Approvedit; every other verdict — a denial, deny-by-default, or an undecidable outcome — drops it. Presence in the served packument is availability (seedocs/research/reverse-engineering/npm.md§8), so a non-approved version is removed rather than flagged. - Resolved
latest. The survivingdist-tags.latestunder the shared keep-unless-denied, stable-preferring rule (selectLatest): the upstreamlatestis kept untouched while it survives, and only repointed — to the highest stable survivor — when it was itself denied. This is thelatestwithin the public set, which the cross-upstream merge then re-resolves over the union; it is not the final servedlatest. - Decisions. Every version's
Decision, in version-key order, so a no-survivors outcome can render each denial and choose a status.
What the plan deliberately omits is any "dropped tags" list: a stale tag — one
whose target did not survive — is droppable structurally from the survivor set
alone (a tag is kept iff its target is in fpSurvivors), so the replay needs no
extra field to find them. The plan stays minimal: the decisions the filter owns,
nothing the replay can recompute.
This filters a single public packument (the gated set). Combining it with the trusted private set is the cross-upstream merge (Ecluse.Package.Merge).
Synopsis
- data FilterPlan = FilterPlan {
- fpSurvivors :: Set Text
- fpLatest :: Maybe Version
- fpDecisions :: [Decision]
- filterPlan :: EvalContext -> [PrecededRule] -> PackageInfo -> FilterPlan
- filterPlanFromDecisions :: Map Text Decision -> PackageInfo -> FilterPlan
Documentation
data FilterPlan Source #
The decisions filtering a single public packument owns, for the adapter to
replay onto the raw upstream Value. Carries only what the filter decides over the
typed model — never a finished, re-serialisable document (see this module's
header). The replay derives everything else (which stale tags to drop, which
time entries to prune) from these fields.
Constructors
| FilterPlan | |
Fields
| |
Instances
| Show FilterPlan Source # | |
Defined in Ecluse.Package.Filter Methods showsPrec :: Int -> FilterPlan -> ShowS # show :: FilterPlan -> String # showList :: [FilterPlan] -> ShowS # | |
| Eq FilterPlan Source # | |
Defined in Ecluse.Package.Filter | |
filterPlan :: EvalContext -> [PrecededRule] -> PackageInfo -> FilterPlan Source #
Decide a single public packument against a rule set: which versions survive,
where latest resolves, and every version's decision. Pure and total — it reasons
over the typed PackageInfo alone, with no registry wire format in sight.
A version survives iff evalRules Approved it; every other verdict drops it.
latest is resolved by selectLatest from the upstream-tagged
latest (looked up among the versions, so a tag aimed at an absent version
contributes nothing) and the surviving versions — kept while it survives, else
repointed downward to the highest stable survivor. The decisions are returned for
every version in key order, so the adapter has each denial's reason when
nothing survives.
filterPlanFromDecisions :: Map Text Decision -> PackageInfo -> FilterPlan Source #
Build a FilterPlan from per-version Decisions already taken, rather than
evaluating the pure tier here. This is the path the effectful tier feeds: it
decides each version in IO (see Ecluse.Rules.Effectful), then hands the decisions
here for the same pure survivor/latest resolution filterPlan performs. The
decision map is keyed by raw version string and must cover exactly the
packument's versions; a version with no decision is treated as not surviving.
A version survives iff its decision is an approval (pure or effectful); every other
verdict — denial, deny-by-default, or Undecidable — drops it,
so a fail-closed undecidable version is filtered out exactly like a denial, while its
decision is still carried in fpDecisions for the no-survivors status.