licence_audit/notice
Types
Injected HTTP clients for every network operation the notices flow performs. Bundling them keeps call signatures stable as the fallback grows and lets tests substitute deterministic fakes without touching the network.
pub type Clients {
Clients(
fetch_hex_tarball: fn(String, String) -> Result(
BitArray,
FetchError,
),
fetch_git_archive: fn(repository.Repository, String) -> Result(
BitArray,
FetchError,
),
resolve_commit: fn(repository.Repository, String) -> Result(
option.Option(String),
FetchError,
),
fetch_repo_archive: fn(repository.Repository, String) -> Result(
BitArray,
FetchError,
),
fetch_spdx_index: fn(spdx.IndexKind) -> Result(
List(String),
FetchError,
),
fetch_spdx: fn(spdx.Requirement) -> Result(
option.Option(String),
FetchError,
),
)
}
Constructors
-
Clients( fetch_hex_tarball: fn(String, String) -> Result( BitArray, FetchError, ), fetch_git_archive: fn(repository.Repository, String) -> Result( BitArray, FetchError, ), resolve_commit: fn(repository.Repository, String) -> Result( option.Option(String), FetchError, ), fetch_repo_archive: fn(repository.Repository, String) -> Result( BitArray, FetchError, ), fetch_spdx_index: fn(spdx.IndexKind) -> Result( List(String), FetchError, ), fetch_spdx: fn(spdx.Requirement) -> Result( option.Option(String), FetchError, ), )Arguments
- fetch_git_archive
-
Fetch a git package’s source archive at its immutable manifest commit. Provider-agnostic: the
repository.Repositorycontains the parsed provider (GitHub, GitLab, or Codeberg) so the correct archive endpoint is used. Never resolves tags or HEAD — the commit is fixed. - resolve_commit
-
Resolve a repository tag to an immutable commit SHA.
Ok(Some(sha))resolved,Ok(None)tag not found (try the next candidate),Errortransient network/API failure (surface a warning and fall through). - fetch_spdx
-
Fetch canonical SPDX text for a requirement.
Ok(Some(text))resolved,Ok(None)unknown identifier,Errortransient network failure.
pub type Error {
UnknownPackages(packages: List(String))
MissingLicenceText(packages: List(String))
MetadataFailed(package: String, reason: String)
UnsupportedSource(
package: String,
source: String,
detail: String,
)
FetchFailed(package: String, reason: String)
ArchiveFailed(package: String, reason: String)
ChecksumMismatch(
package: String,
expected: String,
actual: String,
)
PathReadFailed(package: String, path: String, reason: String)
SpdxFetchFailed(package: String, id: String, reason: String)
OutputWriteFailed(path: String, reason: String)
}
Constructors
-
UnknownPackages(packages: List(String)) -
MissingLicenceText(packages: List(String)) -
MetadataFailed(package: String, reason: String) -
UnsupportedSource( package: String, source: String, detail: String, ) -
FetchFailed(package: String, reason: String) -
ArchiveFailed(package: String, reason: String) -
ChecksumMismatch( package: String, expected: String, actual: String, ) -
PathReadFailed(package: String, path: String, reason: String) -
SpdxFetchFailed(package: String, id: String, reason: String) -
OutputWriteFailed(path: String, reason: String)
pub type FetchError {
FetchNetworkFailure
FetchTimeout
FetchTimeoutAfter(seconds: Int)
FetchUnexpectedResponse(status: Int)
FetchDownloadTooLarge(limit: Int)
}
Constructors
-
FetchNetworkFailure -
FetchTimeoutA request timed out at the 30s source-archive default. Kept as a nullary variant for source compatibility with existing callers/tests that construct or match on
FetchTimeoutdirectly. -
FetchTimeoutAfter(seconds: Int)A request timed out at a duration other than the 30s source-archive default (e.g. the 10s metadata fetches used by the repository/SPDX fallback). Includes the timeout in seconds so
describe_fetch_errorreports the actual configured duration rather than assuming 30s. -
FetchUnexpectedResponse(status: Int) -
FetchDownloadTooLarge(limit: Int)
pub type NoticeEntry {
NoticeEntry(package: NoticePackage, files: List(NoticeFile))
}
Constructors
-
NoticeEntry(package: NoticePackage, files: List(NoticeFile))
pub type NoticeFile {
NoticeFile(path: String, contents: String)
}
Constructors
-
NoticeFile(path: String, contents: String)
pub type NoticePackage {
NoticePackage(
name: String,
version: String,
declared_licences: List(String),
repo_links: List(String),
source: PackageSource,
scope: manifest.Scope,
)
}
Constructors
-
NoticePackage( name: String, version: String, declared_licences: List(String), repo_links: List(String), source: PackageSource, scope: manifest.Scope, )Arguments
- repo_links
-
Candidate source-repository URLs (from Hex
meta.linksor a localgleam.toml), consulted by the repository fallback when the package’s own source archive ships no licence text.
pub type PackageSource {
HexPackage(outer_checksum: String)
GitPackage(
repository: repository.Repository,
url: String,
commit: String,
path: option.Option(String),
)
PathPackage(path: String)
}
Constructors
-
HexPackage(outer_checksum: String) -
GitPackage( repository: repository.Repository, url: String, commit: String, path: option.Option(String), )A dependency fetched directly from a git host at an immutable manifest commit.
repositoryis the normalized provider identity used to build the archive request;urlis the original manifest-recorded source URL, preserved verbatim for rendering. -
PathPackage(path: String)
Values
pub fn commit_response(
repo: repository.Repository,
status: Int,
body: String,
) -> Result(option.Option(String), FetchError)
Pure mapping of a repository commit-resolution HTTP #(status, body) to an
outcome, split out from the network call so status handling is testable
without live traffic: 404 → tag not found, 2xx → decode the SHA (a missing
field is also “not found”), any other status → transient failure.
pub fn decode_notice_files(
encoded: String,
) -> Result(List(NoticeFile), Nil)
Parse notice files written by encode_notice_files. Returns Error(Nil) on
any malformed or blank entry so old blank results become cache misses.
pub fn default_clients() -> Clients
The default clients, wired to the real Hex, provider, and SPDX endpoints.
pub fn describe_error(error: Error) -> String
pub fn describe_fetch_error(error: FetchError) -> String
pub fn encode_notice_files(files: List(NoticeFile)) -> String
Serialise notice files for the on-disk cache as a JSON array of
{path, contents} objects.
pub fn fetch_json(
request: request.Request(String),
) -> Result(#(Int, String), FetchError)
Dispatch a small JSON GET, returning #(status, body) or a transport
error mapped onto FetchError.
pub fn fetch_tarball(
request: request.Request(BitArray),
) -> Result(BitArray, FetchError)
pub fn fetch_verified_hex_tarball(
name: String,
version: String,
expected_checksum: String,
fetch_hex_tarball: fn(String, String) -> Result(
BitArray,
FetchError,
),
) -> Result(BitArray, Error)
Fetch a Hex package tarball and verify it against the lockfile checksum.
pub fn filter_entries(
selected: List(manifest.SbomEntry),
locked: List(manifest.SbomEntry),
configuration: config.Notices,
) -> Result(List(manifest.SbomEntry), Error)
pub fn has_licence_file(files: List(NoticeFile)) -> Bool
Whether files already contain an actual licence-text file (LICENSE,
LICENCE, or COPYING). A package whose source ships only a NOTICE file — or
nothing, or blank licence files — returns False and must use the fallback.
pub fn has_text(contents: String) -> Bool
Check Unicode whitespace too: string.trim leaves spaces such as NBSP.
pub fn licence_files(
files: List(source_archive.ArchiveFile),
) -> Result(List(NoticeFile), source_archive.ArchiveError)
pub fn licence_files_only(
files: List(NoticeFile),
) -> List(NoticeFile)
Keep only the licence-text files from a list, dropping ancillary NOTICE files. Used to lift a licence out of a fallback repository archive without pulling in that repo’s own NOTICE.
pub fn package_source(
entry: manifest.SbomEntry,
) -> Result(PackageSource, Error)
pub fn packages_from_entries(
entries: List(manifest.SbomEntry),
scopes: dict.Dict(String, manifest.Scope),
metadata_for: fn(manifest.SbomEntry) -> #(
Result(hex.PackageMetadata, Error),
option.Option(String),
),
) -> #(Result(List(NoticePackage), Error), option.Option(String))
pub fn read_remote_source(
package: NoticePackage,
fetch_hex_tarball: fn(String, String) -> Result(
BitArray,
FetchError,
),
fetch_git_archive: fn(repository.Repository, String) -> Result(
BitArray,
FetchError,
),
) -> Result(List(source_archive.ArchiveFile), Error)
pub fn read_source_notices(
package: NoticePackage,
clients: Clients,
) -> Result(List(NoticeFile), Error)
Read only the selected notice files, preserving selection against the full source inventory rather than inferring an archive root from a subset.
pub fn render(
entries: List(NoticeEntry),
manifest_path manifest_path: String,
) -> String
pub fn repo_licence_files(
package_name: String,
bytes: BitArray,
) -> Result(List(NoticeFile), Error)
Extract the licence-text files from a fallback repository’s gzip tar
archive. Ancillary NOTICE files from the repository are dropped; only the
actual licence text is lifted. Extraction failures are tagged to
package_name.
pub fn selected_entries(
manifest_value: manifest.SbomManifest,
scopes: dict.Dict(String, manifest.Scope),
include_dev include_dev: Bool,
) -> List(manifest.SbomEntry)
pub fn selected_notice_paths(
paths: List(String),
) -> List(#(String, String))
pub fn spdx_file(
requirement: spdx.Requirement,
text: String,
) -> NoticeFile
Build the synthetic notice file for a resolved SPDX record, labelling its
origin via a SPDX-License-List/<id>.txt path. The canonical text is stored
verbatim.
pub fn spdx_response(
requirement: spdx.Requirement,
status: Int,
body: String,
) -> Result(option.Option(String), FetchError)
Pure mapping of an SPDX detail-record HTTP #(status, body) to an outcome,
split out from the network call so status handling is testable without live
traffic: 404 → unknown identifier, 2xx → decode the canonical text (a
missing field is also “unknown”), any other status → transient failure.