ecluse:ecluse-core
Safe HaskellNone
LanguageGHC2021

Ecluse.Core.Registry.WireSupport

Description

Cross-ecosystem scaffolding for projecting an untrusted registry wire document into the domain model, shared by every ecosystem's projection (Ecluse.Core.Registry.Npm.Project):

  • Per-entry lenient degradation. partitionLenient splits a raw key -> Value map into the entries that decode and the ones that do not, dropping each malformed entry and recording it as an InvalidEntry rather than failing the whole document. This is the one place per-entry leniency and drop-tracking are realised; every ecosystem's element-wise-lenient axis (npm's versions/dist-tags/time, or another ecosystem's element-wise list) layers its own decode on top.
  • Name agreement. checkNameAgreement is the anti-shadowing check that the name an upstream self-reports agrees with the name the proxy resolved from the route. The requested name is the validation authority, never a rewrite: a disagreement carries the reported name verbatim so the caller can drop that origin's contribution as untrusted for this request.
Synopsis

Per-entry lenient degradation

partitionLenient :: InvalidEntryKind -> (Value -> Either String a) -> Map Text Value -> (Map Text a, [InvalidEntry]) Source #

Partition a raw key -> Value map into the entries that decode and the ones that do not: each undecodable entry is dropped and recorded as an InvalidEntry of the given InvalidEntryKind, carrying its key, the raw offending Value (verbatim, for diagnostics), and the decode error as the reason. The dropped list is in ascending-key order (foldrWithKey visits keys ascending and each step prepends), so it is deterministic. This is the one place per-entry leniency and drop-tracking are realised, shared across every ecosystem's element-wise-lenient projection axes.

Name agreement

data NameAgreement Source #

The outcome of checking an upstream's self-reported name against the requested name (the identity the proxy resolved from the route). The requested name validates the document; it never rewrites it.

Constructors

NameAgrees

The self-reported name agreed with the request.

NameDisagrees Text

The self-reported name disagreed, reporting this different name (carried verbatim for the audit log).

checkNameAgreement :: PackageName -> PackageName -> NameAgreement Source #

Check an upstream's self-reported PackageName against the requested one via ecosystem-aware PackageName equality (npm's case sensitivity is honoured, so this is never a byte-for-byte compare an encoding variant could slip past). Agreement is NameAgrees; a disagreement is NameDisagrees carrying the reported name (rendered), so the caller can treat that origin as untrusted for this request and drop its contribution. The name is never substituted.