Skip to content

Releases: sowoi/check-opencloud-security

v1.31.2

Choose a tag to compare

@github-actions github-actions released this 25 Sep 06:03

check-opencloud-security 1.31.2

Security

  • The erasure credential throttle counts an IPv6 client by its /64. Failed
    guesses at the DELETE /api/purge token were counted per single address,
    while every other limit counts an IPv6 client by the /64 it is handed - so
    rotating the interface identifier bought five fresh guesses each time. The
    32-character minimum on the token kept guessing impractical regardless.
  • The scan service refuses a guessable token on a wide bind. Serving
    anywhere but loopback required a token but accepted any non-empty one -
    --token a, or the placeholder secrets/scanner_token.example ships with -
    and nothing counts failed attempts, so a short token let anybody who reached
    the port make it scan whatever they named. Such a bind now needs a token of
    at least 32 characters that is not that placeholder, or it refuses to start.
    openssl rand -hex 32, which every guide already uses, is unaffected.

Fixed

  • A check only one of two scans made is no longer called new or resolved.
    Comparisons read a finding missing from the earlier scan as passing, so a
    check added by a newer scanner - or by turning the extra checks on - was
    reported as a regression of the instance, and a check the later scan no
    longer made as fixed. The baseline, check-opencloud-scanner diff, the web
    comparison and compare_scans now list these as newly measured or no
    longer measured, based on each scan's coverage block, and the explanation
    files them as scanner changes. A newly measured failure still alerts, and
    --warn-on-new still does not suppress it. A report or baseline that does
    not list its checks is compared as before. See ADR 0079.
  • Aligned the report expiry footer, warning and live countdown to round remaining
    minutes up consistently in every language.
  • A comparison page rounds its expiry up too. It rounded the minutes
    left down, so it announced one minute fewer than the result page would.

Documentation

  • Added German, Spanish and French operator architecture and operations documentation, including
    localized document navigation and operator search. Section anchors and commands
    remain aligned with English; ADRs and release-note bodies remain English.

  • Clarified grouped remediation, upgrade estimates, report expiry and operator
    messages in English, German, Spanish and French. A simulated upgrade whose
    grade is limited by findings no longer implies that the grade cannot improve.
    Count labels also read correctly for a single finding.

  • Expanded all-language tests for remediation groups, upgrade estimates,
    escaped version strings, singular and plural expiry warnings, and the
    translated decision-record interface around English source documents.

  • Decision records are never translated. ADR 0077 records that every
    record in adr/ exists in English only, and once: the operator area shows
    it untranslated in every locale, and translation work leaves adr/ alone.

  • Changelogs and release notes are never translated. ADR 0078 records
    that CHANGELOG.md, RELEASE.md and the GitHub release body exist in
    English only, and that the operator area's Releases tab shows them
    untranslated in every locale.

What's Changed

Full Changelog: v1.31.1...v1.31.2

v1.31.1

Choose a tag to compare

@github-actions github-actions released this 24 Sep 18:57

check-opencloud-security 1.31.1

Changed

  • The coverage warning's alert line is now covered by mutation testing.
    tests/test_coverage_regression.py drives _apply_baseline in process but
    was missing from the mutmut selection, so eleven mutants of the branch that
    lifts an OK to WARNING when a measured check turns inconclusive survived.
    It is now listed, and its test asserts the whole alert line: three of those
    mutants left OK: inside the WARNING message without a test noticing.

Fixed

  • The web report no longer offers "What gets you to A+" under an A+. When
    no step in the remediation plan raises the grade, because the instance
    already has the top grade or something no setting can change holds it down,
    the plan is headed "Still worth fixing, the grade stays A+" (or whichever
    grade it holds) instead.
    This applies to the dashboard, its contents list, and the PDF and HTML
    exports, in all four languages.
  • check-opencloud-scanner fleet lists waiver deadlines in the order they
    end.
    Deadlines were sorted by their text, so a waiver written with a
    +02:00 offset could be listed after one that ends later in UTC.
  • The fleet summary's "Not covered" count counts each host once. A host
    whose last scan failed long enough ago to be stale was counted twice.
  • The remediation plan no longer fails on a result document whose
    ratingExplanation.base is null.
    The update step's detail is then left
    empty, instead of remediation_plan() raising.

Security

  • An empty listen address no longer counts as loopback for the scan
    service.
    Binding "" listens on every interface, but the check that
    demands a token for anything but loopback let it through. The command line,
    COS_SERVICE_LISTEN and the configuration file all fall back to
    127.0.0.1 when empty, so only a program calling build_server() or
    serve() with listen="" could reach it.
  • The container images install the dependencies uv.lock pins, with their
    hashes.
    Both docker/Dockerfile and docker/Dockerfile.web resolved
    their dependencies from PyPI at build time, so an image could ship versions
    that CI, pip-audit and the SBOM never saw.

What's Changed

Full Changelog: v1.31.0...v1.31.1

v1.31.0

Choose a tag to compare

@github-actions github-actions released this 24 Sep 16:32

check-opencloud-security 1.31.0

Documentation

  • Polished scan progress, errors, downloads and sharing text in English,
    German, Spanish and French. Corrected informal Spanish instructions and
    clarified that saved downloads remain available after a scan expires.
  • Updated all four web-service guides to describe every export format,
    including offline HTML reports and remediation bundles. Expanded tests for
    translated error pages, email drafts, link-free summaries and download links.
  • Translation checks now catch additional Spanish forms of informal address
    and report broken guide links at their original line numbers, ignoring
    links shown only in code examples. Added regression tests for both cases.

Added

  • Coverage regression alerts. With --baseline, a check that an earlier
    run reached a conclusion on and that is inconclusive now raises an OK to
    WARNING, even when the grade has not moved. The rating, its perfdata and
    the findings are untouched: the scan saw less, the instance did not change.
    The warning lasts until the check is measured again, --warn-on-new does
    not suppress it, the webhook's baseline_diff carries the lost checks as
    coverage_regressed, and the two-document comparison reports a
    coverageRegressed scanner change. See ADR 0074 and
    Reporting only what changed.
  • Grouped remediation plans. remediationPlan.groups places every open
    finding in the system its fix is made in - the reverse proxy, the identity
    provider, OpenCloud or the DNS zone - and merges the findings one edit
    resolves into a single change: every missing header is one header block,
    every exposed path one proxy rule, and the update closes every matching
    advisory. Each change carries the rating it alone would give, replayed
    through the rating function, and groupSummary names the changes that
    resolve several findings at once. Shown by --debug, on the web dashboard
    ("What to change where"), in the remediation bundle, and returned by the
    plan_remediation MCP tool. See ADR 0075 and
    What would raise the rating.
  • Architecture decisions in the operator area. A new Decisions tab at
    /admin/decisions lists every architecture decision record with its
    status, and a filter narrows the list by number, title or status. Each
    record opens as its own page in English, and links between records, or from
    the Architecture tab, stay inside the area. The area's search now indexes
    every record's full text. Like the rest of the area, the records are never
    public: a stranger gets a 404, and they are absent from the public search,
    the sitemap and /documentation.
  • check-opencloud-scanner review-waivers. It reads the configured
    waivers (ignore_hardenings and temporary_waivers, or the
    --ignore-hardening and --waive-until values given to it) and lists five
    kinds that need attention. Expired waivers no longer suppress anything.
    Expiring soon ones run out within the waiver_warning window. Unused
    ones match no failing check in a --result document, or with no document,
    no identifier the scanner knows. Overlapping ones are already covered by
    another waiver, such as a deadline hidden under a permanent *.
    Permanent ones have no reason and no deadline. Each item has a suggested
    cleanup, for a permanent waiver a --waive-until record to copy. The
    command never changes the configuration. It exits 1 when it lists
    anything, unless given --exit-zero, and --format json suits scripts. See
    the scanner command.
  • check-opencloud-scanner fleet. It turns saved scan result
    documents into one summary of a fleet. Give it files, or directories that
    it searches for *.json, and it keeps the newest report of each host. It
    lists end-of-life releases and releases whose support ends soon. The
    recorded version is placed in today's release schedule again, so a line
    that closed after the report was written is listed too. It lists waivers
    that let a failing check alert again within --window days (default
    30), measured against today. It counts the failing findings that most
    hosts share, and leaves out the ones no operator can change. Under missing
    coverage it lists stale reports (--stale-after, default 7 days), failed
    scans, checks the scans could not evaluate, and hosts named by --expect
    or --inventory that have no report. The output is text, Markdown, JSON,
    or one self-contained HTML page that fetches nothing. It never scans,
    stores nothing and applies no threshold, so it exits 0 whenever it
    printed a summary. See
    the scanner command.

Fixed

  • The .deb install smoke test survives a mirror caught mid-sync. When
    the Ubuntu or Debian mirror lists a dependency it no longer serves (a
    404), packaging/tests/install-smoke.sh refreshes the package index and
    tries the install once more before the release dry run fails.

What's Changed

Full Changelog: v1.30.2...v1.31.0

v1.30.2

Choose a tag to compare

@github-actions github-actions released this 24 Sep 12:07

check-opencloud-security 1.30.2

Changed

  • Tests now cover code that no test reached before. The advisory refresh
    script scripts/update_vulnerability_db.py has tests. They prove that it
    writes new advisories and that --check writes nothing. If the feed is
    down, the script keeps the file. scripts/verify_export.py has tests too. They
    prove that it refuses edited bytes, the wrong key and a missing key. The scan
    child process in webapp/scan_process.py has tests for a rejected target, a
    failed scan and a crash. A rejected target stays a rejection in the worker,
    and a crash sends no exception text. The approval mode in
    webapp/approval.py has tests that prove DNS never approves an address
    target, and that a failed TXT lookup is a refusal.
    tests/test_verify_remediation.py now makes sure that every extra check and
    hardening flag of a full scan verifies to the same answer, not only three of
    them.

Documentation

  • Clarified operator status, comparison results, monitoring instructions and
    TLS explanations in English, German, Spanish and French. Corrected Spanish
    forms of address and translated two overlooked deployment settings rows.
  • Expanded translation tests to cover copied English table descriptions,
    duplicate catalogue keys, repeated placeholders, and formatting and HTML
    escaping across every language, including messages on conditional pages.

Fixed

  • --waiver-warning and waiver_days_left no longer count a waiver that
    only covers a flag OpenCloud hardcodes, such as
    publicLinkExpirationEnforced. That flag never alerts, so the end of its
    waiver changes nothing. Before this fix, such a waiver raised a WARNING.
  • The plugin output now says "1 day left" instead of "1 days left" in the
    end-of-life warning, the lifecycle line and the waiver warning. If one
    waiver covers several checks, the waiver warning now says that they
    "alert again".
  • If two waivers end at the same moment, the waiver warning now names both.
    Before this fix, it named only one waiver but listed the checks of both.

What's Changed

  • chore: regenerate the Homebrew formula for the newest release by @github-actions[bot] in #115
  • chore(release): 1.30.2 by @sowoi in #114

Full Changelog: v1.30.1...v1.30.2

v1.30.1

Choose a tag to compare

@github-actions github-actions released this 23 Sep 15:54

check-opencloud-security 1.30.1

Added

  • --waiver-warning DAYS (COS_WAIVER_WARNING, YAML waiver_warning)
    sets a warning window for --waive-until waivers. If a waiver that hides
    a failing check ends within DAYS days, an otherwise OK result becomes
    WARNING. Before this, a waiver gave no lead time. The check was silent
    until the deadline and alerted on the next run after it. The long output
    also names the next waiver to end. The default 0 turns the warning off.
  • The waiver_days_left performance value counts the days until that
    waiver ends. With --waiver-warning it carries the window as its warning
    range. Checkmk reports it under the same name, and Prometheus and OTLP as
    opencloud_security_waiver_days_remaining. The webhook payload adds
    waiver_days_left, waiver_warning_days and waiver_warning, and
    contrib/prometheus/alerts.yml adds an OpenCloudWaiverExpiring rule.
  • The coverage_inconclusive and coverage_not_checked performance values
    put the coverage block on a graph. A graph now shows the day that checks
    become unreadable. Checkmk uses the same names, and Prometheus and OTLP use
    opencloud_security_coverage_inconclusive_total and
    opencloud_security_coverage_not_checked_total. The grade does not change.

Documentation

  • Replaced vague and literal wording in the interface, scanner guides and
    README. Aligned English, German, Spanish and French explanations and
    corrected inconsistent forms of address.
  • Completed the remaining French guide translations while preserving commands,
    technical values and section links.
  • Expanded wording checks to current repository documentation and Python
    product strings, including phrases split across lines. Added regression
    cases and a translation review checklist. Corrected inconsistent exemption
    terminology and Spanish plural recognition in the glossary check. Recorded
    reviewed plain-language alternatives so they no longer produce warnings.

What's Changed

  • chore: regenerate the Homebrew formula for the newest release by @github-actions[bot] in #112
  • chore(release): 1.30.1 by @sowoi in #113

Full Changelog: v1.30.0...v1.30.1

v1.30.0

Choose a tag to compare

@github-actions github-actions released this 22 Sep 18:42

check-opencloud-security 1.30.0

Documentation

  • Listed tests/test_monitoring_export.py in the test index, so the
    scheduler-export tests can be found by purpose.

  • Clarified German operator messages about wildcard DNS and temporary
    application updates, and replaced the literal TLS introduction with a
    description of the measured values. Added three wording regression cases.

  • Clarified configuration-drift explanations in the English, German, Spanish
    and French baseline guides. Older baselines lack fingerprints, so an absent
    drift report does not establish that the configuration is unchanged.
    Added regression cases for vague and anthropomorphic wording in all four
    languages. Fixed four French guide links to the documentation index found
    by the translation tests.

  • Reworded literal German and Spanish translations in the baseline and scanner CLI
    guides, including severity comparisons and missing measurements. Added
    regression cases for the awkward phrases found during review.

Added

  • The setup wizard exports the scheduled check, not just the configuration.
    check-opencloud-scanner configure now offers to write the monitoring
    configuration next to the file it saved, and --export-monitoring
    (icinga, systemd, both, none) answers that question up front for a
    provisioning script. It produces an Icinga 2 Service object, and a systemd
    oneshot service, daily timer and COS_ environment file, each carrying
    the thresholds, the release track and every other answer just given - so the
    check that runs every day is the one that was configured rather than an
    example adjusted from memory. Two rules shape the output: nothing is
    installed
    (the files are written for review and the install commands are
    printed, never run), and no credential is written into them - a webhook
    URL or release token stays in the owner-only configuration file, which both
    artefacts point at with vars.opencloud_config and COS_CONFIG_FILE, and
    the settings withheld are named rather than silently dropped. The generated
    unit carries the same hardening directives as the one in contrib/systemd/,
    asserted by a test so it cannot quietly become a weaker copy.

  • check-opencloud-scanner diff compares two results finding by finding.
    A new --format side-by-side states both scans as two columns, one finding
    per row, so a reader does not have to rebuild each side from a list of
    changes; --all-findings adds the findings that did not move. Every
    comparison now reports per-finding severity movement - a ~ line and a
    Failing by severity: tally - which the baseline's comparison of two sets
    of names cannot express: a check that stayed open and moved from high to
    critical never enters or leaves that set, and caps the rating a grade
    lower. --category narrows the comparison to one area, taking a value
    either from the finding categories (exposure, headers, transport,
    advisory, ...) or from the change categories (instance,
    referenceData, scanner, policy, unknown); an unknown value is
    refused rather than silently showing nothing. --format json carries the
    same as findings and severityTotals. A side that was never measured is
    reported as such and never as a pass, and a waived finding is still counted.

  • A finished scan downloads as a remediation bundle: only the work that is
    left, with the configuration that closes it.
    The result page and
    GET /api/scans/{uuid}/export/{format} gained remediation-md and
    remediation-html. A bundle carries only the open, actionable findings

    • waived entries and the flags OpenCloud hardcodes are left out - each with
      what the scanner observed, what it means and what to change, followed by the
      nginx, Caddy, Traefik, Docker Compose and .env fragments that satisfy
      them, rendered from the hardening catalogue's own env_fix and
      header_fix entries. Every flavour is written out rather than one, each
      naming which findings it covers and which belong in the other kind of file,
      and a finding whose right value is a decision about the deployment is listed
      as having no mechanical fix rather than given a placeholder to edit. The
      grade, the passed checks and the advisory list stay in the full report:
      repeating them here would bury the one thing the file is for.
  • SARIF output now carries what a code-scanning dashboard needs to act on a
    finding.
    --format sarif previously named a rule and a level and left the
    rest to a reader's own research. Each rule now carries the hardening
    catalogue's remediation sentence, the official documentation link
    (helpUri), the catalogue entry that explains a per-path finding
    (catalogueId - exposed for exposed:/opencloud.yaml), the setting
    behind it, and the security-severity, problem.severity and tags
    properties GitHub code scanning sorts and filters alerts on. Each result
    carries the severity, category, remediation and reference beside the host,
    and a partialFingerprints entry stable across runs, so a finding that has
    been open for a month stays one alert with a history rather than a new one
    every night. An advisory additionally names fixedIn and the release
    window it covers (affectedRanges, e.g. >= 1.0.0, < 4.0.8), and the run
    reports the rating, version and end-of-life state per scanned host. The web
    application's own SARIF export gained the same properties and fingerprints,
    keeping the two renderers in convention-sync as ADR 0026 requires.

  • A scan result's vulnerabilities entries name the release range they
    apply to.
    affectedRanges (and introduced) join fixedIn, so a reader
    can tell whether an older release was ever affected rather than only which
    release ends the window.

Fixed

  • The French scanner CLI guide no longer ships the newly added comparison
    sections in English.
    Its diff explanation, severity view, side-by-side
    output and category filtering are now translated, and regression tests catch
    those copied-English phrases in future guide updates.

  • The German operator area no longer leaves avoidable English labels in
    place.
    Advisory status is shown as Sicherheitsmeldungen, update controls
    as Aktualisierungen, and the audit section consistently names its log.

What's Changed

Full Changelog: v1.29.3...v1.30.0

v1.29.3

Choose a tag to compare

@github-actions github-actions released this 22 Sep 14:14

check-opencloud-security 1.29.3

Fixed

  • Sloppy generated wording was removed from the English, German and French
    documentation.
    Replaced vague promotional phrases and awkward literal
    translations in the Kubernetes, scanner and reference-data guides, rebuilt
    their frontend pages, and expanded the translation-quality tests with
    regression cases for these patterns.

What's Changed

  • chore: regenerate the Homebrew formula for the newest release by @github-actions[bot] in #109
  • chore(release): 1.29.3 by @sowoi in #110

Full Changelog: v1.29.2...v1.29.3

v1.29.2

Choose a tag to compare

@github-actions github-actions released this 22 Sep 04:08

check-opencloud-security 1.29.2

Fixed

  • /llms.txt and /llms-full.txt described an older version of the
    service.
    They are the map an agent reads before deciding what this
    service can do, and four of their facts had fallen behind the code:
    /mcp was described as six tools and six prompts where it registers seven
    of each, compare_scans was missing from the tool list in the long form,
    the export formats omitted html, and the endpoint summary never mentioned
    GET /api/scans/{uuid}/badge.svg. An agent that trusts the map would have
    concluded the badge and the HTML export do not exist. All four now match
    what webapp/mcp_server.py, wf.EXPORT_FORMATS and webapp/openapi.py
    actually serve.

  • A page's <lastmod> in sitemap.xml now moves only when the page really
    changed.
    The date came from the modification time of the template that
    renders the page, and a checkout, a container build and an unpacked release
    tarball all write every template at once - so every public page claimed to
    have changed on release day, and a crawler told that everything changed
    learns nothing from the file. Each public page's date is now recorded next
    to a digest of its template in webapp/data/page-revisions.json, and
    scripts/update_page_revisions.py moves a date only when that digest does.
    A page the record has never seen, or one edited since it was written, still
    falls back to the modification time rather than publishing a date that is
    no longer true. CI checks the record with --check, as it does for the
    generated documentation.

  • The German, Spanish and French pages no longer drop names the English
    text uses to say what this is.
    The translated "About" paragraph called the
    plugin a generic monitoring plugin, so a reader of those pages never learned
    it plugs into Nagios and Icinga, and it also lost the English sentence's
    point that running it yourself has no rate limit or queue. The German and
    French descriptions of the method page said "what the scanner checks"
    without naming an OpenCloud instance, and the Spanish search summary for the
    API page dropped OpenAPI, Arazzo and MCP - the three things somebody
    searching for that page is searching for. All four strings now carry the
    names again; the search index is rebuilt with them.

What's Changed

Full Changelog: v1.29.1...v1.29.2

v1.29.1

Choose a tag to compare

@github-actions github-actions released this 21 Sep 22:30

check-opencloud-security 1.29.1

Changed

  • The --policy deployment gate is now covered by tests mutation testing
    can run.
    Its behaviour was only ever exercised through the real CLI, which
    runs the plugin as a subprocess, so mutation testing could delete the scan
    document, the rating or the vulnerability list that _apply_policy is
    handed - and drop the policy verdict from the webhook payload - without a
    single test noticing. A violation that should fail a pipeline could have
    stopped failing it silently. tests/test_policy_gate.py now drives the same
    gate in process and is listed in the mutmut selection; the five surviving
    mutants it was written for are killed.

  • A result list that no longer lines up with the checks that produced it is
    now an error rather than a shorter report.
    Every place the scanner and the
    plugin pair a list of checks with the results _run_all returned for them -
    the exposed paths, the protected endpoints, the debug endpoints and ports,
    the demo accounts, and the per-host rows of the checkmk and summary
    output formats - zipped the two without asserting they were the same length.
    The lengths match by construction today, so nothing changes for any scan that
    runs; what changes is the failure mode if a later edit breaks that pairing.
    Silently dropping the tail would have meant a report that omits checks
    without saying so, which reads as an instance that passed them. The one
    pairing deliberately left lenient is the lifecycle page parser, where the two
    lists come from somebody else's HTML and a tab without a panel must be
    dropped rather than raise.

Fixed

  • The browser test for the severity filter no longer drops its own press in
    WebKit on CI. Pressing a counter hides most of the list and reveals the
    status line above it, so the page it leaves behind is a different height
    from the one that was pressed; the test read the new count back with a
    single sample and pressed clear straight away, on a control that was
    still settling. WebKit dropped that press rather than delivering it, the
    filter stayed on, and the run failed counting a list nobody had asked for.
    Each press is now waited out for the count it asked for before the next one
    is aimed, which still fails - loudly - if a press is ever genuinely lost.

What's Changed

Full Changelog: v1.29.0...v1.29.1

v1.29.0

Choose a tag to compare

@github-actions github-actions released this 21 Sep 18:59

check-opencloud-security 1.29.0

Added

  • A scan fingerprints the configuration it measured, so drift is visible
    without the grade moving.
    A rewritten content security policy, a replaced
    reverse proxy, public links that stopped requiring a password, a certificate
    at a different issuer - none of that has to change a grade, and an operator
    watching only the grade saw none of it. The result document now carries a
    configuration block: grouped digests for transport, headers, sharing,
    authentication and proxy, plus one over all five. Digests only, never the
    configuration
    - a policy, an issuer and a server banner go in and a hash
    comes out, so the block is safe on a public page, in a webhook and in an
    uploaded report. The plugin prints Configuration fingerprint: 9e3c4428,
    --baseline reports No new findings, but the configuration changed (headers), check-opencloud-scanner diff adds a configurationChanged
    change, and the web application shows the groups under Has this deployment
    changed?
    . Routine churn is deliberately excluded: a renewed certificate and
    a proxy's new build number are not drift, and a group the two scans looked
    at differently is reported as not comparable rather than as a change.
    Nothing in it touches a rating, an exit code or an alert line. See
    ADR 0073.
  • --policy fails a deployment on explicit requirements, not on a grade.
    -w/-c and --profile judge an instance by its rating, which is the
    wrong shape for a CI gate: a team that requires HTTPS enforcement and no
    demo accounts cannot express that as a number. A policy file states it
    directly - minimum_rating, required_hardenings and forbidden (a
    missing measure, a failed check or a vulnerability id) - and anything it
    asks for that an instance does not meet ends the run CRITICAL. A policy
    only ever makes a verdict worse, a waiver does not excuse a requirement,
    and an unknown key or measure is a usage error rather than a rule that
    quietly requires nothing. --format json and the webhook payload carry the
    verdict under policy. See CI policy mode and
    config/policy.example.yml.
  • --format summary reads a whole fleet in one table. Checking a dozen
    instances printed a dozen result blocks written for a monitoring system,
    which is a lot to read when the question is just "which of these needs me
    today". The new format prints one aligned row per host instead - host,
    grade, version, end-of-life state, how many advisories apply, and how much
    moved since --baseline - followed by the same tally the Nagios output
    starts with. Rows keep the order the hosts were given and the exit code is
    unchanged, so it works from a cron job that mails its output. The NEW
    column distinguishes "no baseline given" (-) from "no new findings" (0),
    and a host whose scan failed shows its Nagios status where the grade would
    be. See Reading a fleet in one table.
  • The output says how much it could actually measure. A check that
    passed and one that never ran left the same trace in the plugin's output -
    nothing - so the plugin now prints a Coverage: line such as 84 checks evaluated, 6 skipped, 2 indeterminate, 1 network-limited, and the webhook
    payload and --format json carry the same counts under coverage. The web
    application's What this scan did not measure section shows the same four
    numbers. network_limited is split out of the skipped and indeterminate
    counts because a timeout or a missing route - DNSSEC, an external identity
    provider, an optional endpoint - is the gap another vantage point might
    close. Nothing in it changes a grade, an exit code or an alert line.

What's Changed

Full Changelog: v1.28.1...v1.29.0