Repository navigation
Earnie CLI 0.4.0
Added
-
earnie model scan <file>uploads one AI model file (weights such as
.safetensors,.ggufor.onnx, or a Hugging Face snapshot as.tar,
.tar.gzor.tgz) to the Project and waits for its AI provenance result,
listing each finding with its status, component, confidence and license. The
file is sent in 16 MiB windows, and scanning the same file again after an
interruption resumes from the bytes the server already holds.--no-wait
returns once the upload is sealed, and--timeoutbounds the wait. It exits 0
when the model was identified or not matched, 3 withmodel_scan_failedwhen
its scan failed, and 8 withmodel_too_largewhen the file exceeds the
deployment's model size cap (larger models cannot be scanned yet).--json
prints the report in a newmodelmember of the envelope. It needs an API key
scoped to theaiscanner withscans:readandscans:write. The generated
Go clientpkg/earnieclientgains the model upload and read operations. -
The notification kinds
earnie notifications rules create --kindaccepts now
includecra_deadline, the security reminder that a CRA reporting stage is
near, at or past its due time. It is a security kind, so it cannot be turned
off andearnie notifications healthcounts a rule for it as a security
route. -
earnie integrations list [--provider github|gitlab]lists the GitHub and
GitLab connections with their recorded health, the permissions each is missing
(with the level needed) and the provider page where an admin grants them.
earnie integrations verify <connection-id>asks the provider again, records
its answer as the connection's health and exits 9 when the connection is
degraded or disconnected; when the provider cannot be reached it fails and the
recorded health is kept. Both need an API key withintegrations:readand
change no setting.earnie integrations connect <github|gitlab>prints the
Settings > Integrations link where a person signed in to Earnie connects the
provider; it makes no request, because an API key cannot connect a provider.
--jsonprints the report. The commands need a server that serves
POST /v1/integrations/connections/{connection_id}:verify. -
earnie doctorchecks the SCANOSS API key before it reads the integrations
status: the server calls the SCANOSS API once with its configured key, and the
SCANOSS API key entry then says whether the key works, was refused, is rate
limited or out of quota, or could not be checked because the SCANOSS API was
unreachable. A refused key shows up as a disconnected integration with a link
to get a key, so the command exits 9. A server that does not have the check
yet, or a key that may not run it, still gets the status as before. The
command needs a server that servesPOST /v1/integrations/scanoss-api-key:test
to run the check. -
earnie doctorshows one status for every integration the server knows
(source-code connections, single sign-on, notification channels, the SCANOSS
API key and API keys), each with a link to fix it when it is degraded or
disconnected, and runs the checks ofearnie mcp doctorafter it. It reads
what the server already recorded and changes nothing. It exits 9 when an
integration is degraded or disconnected or an MCP check fails; an integration
that was never configured is not a problem. A key withoutintegrations:read
still gets the MCP checks and the output says the integrations were not
checked. An integration whose settings the caller may not read (single
sign-on needssso:read, notification channelsorganization:read, API keys
apikeys:read:all) is left out.--jsonprints{ok, integrations, mcp}. The command needs a
server that servesGET /v1/integrations/status. -
earnie notifications test <channel>sends a real test message through a saved
notification channel and reports how it ended.<channel>is a channel id or the
exact name of a channel; a name is looked up in the channel list, so a key that
tests by id needs onlynotifications:write. The output names the channel, the
outcome and the message that says what to fix, plus the address an email test went
to. It exits 0 when the message was sent and exits 3 with
notification_test_failedand the failure reason when it was not. It never
repeats a test on its own, because the message is real. A key without
notifications:writeexits 5, and an unknown channel exits 8 with
channel_not_found. No flag takes a secret: a secret is set by a person in the
web app. The JSON output gains an optionalnotification_testmember with the
channel, outcome, reason, message and recipient. It needs a server that has the
channel test endpoint and a key withnotifications:write. -
earnie notifications channels list|create|update|deletesets up notification
channels from a terminal or an agent. A channel is a channel id or an exact name.
channels createtakes--kind,--name,--enabled, the--email-*settings
and--webhook-url.channels updatesends only the flags you pass. No flag takes
a secret: a channel that needs one is saved disabled, and the output says so and
prints the web link<server>/settings/notifications?channel=<id>where a person
enters it. Reads needorganization:readand changesnotifications:write. A
missing scope exits 5 naming it, an unknown channel exits 8, and writes are never
repeated on their own. An API key cannot change where a stored secret is sent:
channels updatethat moves it exits 5 withsecret_requires_member. The JSON output gains the optionalnotification_channels,
notification_channelandnotification_deletedmembers. It needs a server that
serves the notification channel routes of the REST API. -
earnie notifications rules list|create|deleteandearnie notifications health
finish the setup.rules create --class <class> [--kind <kind>]... --channel <channel>routes a class of notification to a channel, andrules delete <rule-id>removes a rule.healthsays whether the server holds the
notifications key and whether security notifications have a route outside the
inbox. Reads needorganization:readand changesnotifications:write. An
unknown rule exits 8. The JSON output gains the optionalnotification_rules,
notification_ruleandnotification_healthmembers. -
The bulk-resolve response model gains an optional
needs_decisioncount,
present only on anintroduced_viadry run: how many of the selected findings
a policy flags. Nothing the CLI sends or prints changes. -
earnie scan retry <scan-id> --producer crypto|airuns a failed scanner again
on a scan that completed without it. The scan and the findings of the scanners
that finished stay as they are; when the new attempt succeeds, that scanner's
findings and the scan's gate update. Asking again while an attempt is in
flight opens no second one. Without--waitit exits 0 once the attempt is
accepted; with--wait(and--timeout) it waits for the attempt to end and
exits likeearnie scan wait, or exits 3 withproducer_retry_failedand the
failure code when the attempt fails again. A scanner that cannot be retried
exits 8 with the server's code, such asproducer_not_failedor
scan_superseded. The JSON output gains an optionalretrymember with the
producer, whether this call opened the attempt, its outcome and every
attempt. It needs a server that has the retry endpoint and a key with
scans:write. -
A scan read now says whether a failed scanner can be retried: each failed
scanner in a scan'sproducerscarriesretry_refusalwhen a retry would be
refused (scan_not_retryable,producer_not_retryableorscan_superseded),
and carries none when a person who can run scans may retry it. -
earnie scan ciscans what the pipeline checks. In a GitHub pull request or
GitLab merge request pipeline it diffs against the base the pipeline names;
in any other pipeline it scans the whole tree; outside a CI it exits 8 with
ci_not_detected.--base <ref>replaces the base. A shallow clone without
the base exits 8 withshallow_cloneand namesfetch-depth: 0or
GIT_DEPTH: 0. -
Each policy approval in the JSON output of
earnie policy violationsand
earnie policy shownow carriesdifferent_approver_required: whether the
organization setting "Require a different approver" was on when the approval
was decided. It isfalsefor a pending request and for every decision made
before the setting existed. -
The generated
earnieclientmodels gain fields the CLI does not read, so its
behaviour is unchanged:inventoryon the AI usage rollup, andinventory,
files_inventoryandfindings_inventoryon the review file queue, and
needs_decisionon a finding, for AI usage findings that need no decision. -
The generated
earnieclientmodels gainrootsanddevon dependency
evidence: the root manifests whose lockfile graph holds the package, and
whether the project needs it only to develop it. A package only a lockfile
names carries no declarations. The CLI does not readrootsordev, so its
behaviour is unchanged.dependency_countin a scan or project summary now
counts the packages of the lockfile graph when the scan has one. -
The generated
earnieclientmodels gain the GitLab import hook plan
(hookson the bulk import preview,hook_scopeon the bulk import request
and batch, and per-repository hook results on the batch). The CLI does not
read them, so its behaviour is unchanged. -
The generated
earnieclientmodels gain theinventorycomponent state and
itsstatefilter value, for a component whose declared dependencies need no
decision. The CLI does not read them, so its behaviour is unchanged. -
The model finding status gains
declared: a repository the knowledge base
knows whose files were not matched.earniereports it as a model status that
is not identified. The generatedearnieclientmodels gain the matching
declaredcount andModelDeclaredDetail. -
A Model gains
source(uploadorhuggingface) andsource_ref, its
weightsgainnonefor a Model that was never uploaded, and the server gains
POST /v1/projects/{projectId}/models/huggingface, which adds a Model by its
Hugging Face id. The generatedearnieclientmodels carry them. No CLI command
uses them, so its behaviour is unchanged. -
A declared model finding gains the reason
gated: Hugging Face hides the file
hashes of a gated repository, so none could be looked up. The generated
earnieclientmodels carry it. The CLI does not read it. -
A scan read of a single scan now carries
degraded, true when the scan
completed but one of its scanners failed, andproducers, the outcome and
attempts of each scanner. The generatedearnieclientmodels gain both
fields, plusScanProducerResultandScanProducerAttempt. The CLI does not
read them, so its behaviour is unchanged. -
Each version in a component of
GET /v1/findings/componentsnow carries its
owntotal_countanddecided_count, its ownvulnerabilitiesand a
canonical_purl, and the generatedearnieclientmodels gain those fields on
ComponentVersionRef. The component's counts are still the sums of its
versions. The CLI does not read them, so its behaviour is unchanged.
Changed
-
earnie exportno longer lists dev dependencies (test runners, build tools and the
packages only they pull in, as the lockfile marks them) in the CycloneDX or SPDX document.
The server now leaves them out unless the snapshot is generated with
include_dev_dependencies; the CLI has no flag for it yet, so a CLI export always omits them.
A package your code matched in the tree stays. This needs no CLI release: the change is in the server. -
The SBOM that
earnie exportdownloads now carries the dependency graph
Earnie stored for the scan: CycloneDXdependenciesand per-manifest
compositions, SPDXDEPENDS_ONrelationships. The change is on the server,
so it needs no new CLI release; snapshots made before it keep their old
statement that the graph was not assessed. -
The GitHub Action and the GitLab template now run
earnie scan ciby
default instead ofearnie scan path ., so a pull or merge request scans only
its changes. Check out withfetch-depth: 0in GitHub Actions; the GitLab
template setsGIT_DEPTH: 0. Setargs: path .to keep the old scan. -
On macOS and Windows the CLI now honours
SSL_CERT_FILEandSSL_CERT_DIR
over the system keychain. Unset them, or set
GODEBUG=x509sslcertoverrideplatform=0, to keep using the keychain. -
The macOS builds now need macOS 13 Ventura or later.
-
Dependency updates:
charm.land/bubbletea/v22.1.0,golang.org/x/mod
0.42.0,golang.org/x/sys0.49.0 andgolang.org/x/term0.47.0. No
behaviour change is expected.
Security
- The CLI is built with Go 1.27.3 instead of 1.25.8, picking up the standard
library security fixes since, includingcrypto/tls,crypto/x509and
net/http. 1.27.3 fixes GO-2026-6809 incrypto/x509. Building the CLI from
source now needs Go 1.27.