dashboards

Specification

What a project must publish for a dashboard to read it, and what a dashboard may assume in return. This is the only contract between the two. A project that satisfies it needs to know nothing about the pages, and a page needs to know nothing about how a project builds.

It also describes the dependencies file, deps.json: the one file the dependencies page reads. This site’s own build writes it, so it asks nothing of a project.

The status file

Each project publishes one file to its own Pages site, at the root:

https://codesweep.ai/<project>/ci-status.json

It is written by action/ci-status during that project’s Pages build, from that project’s own workflow runs. See README.md for how a project wires it up.

Shape

{
  "schema": 2,                       // integer, bumped on a breaking change
  "generated": "2026-09-10T07:00:00Z",  // when this file was written, UTC
  "window": 20,                      // the cap on runs summarised per workflow
  "repo": {
    "name": "lint",
    "full_name": "codesweep-ai/lint",
    "description": "…",              // may be empty
    "url": "https://github.com/codesweep-ai/lint",
    "branch": "main",                // the branch the runs are from
    "pushed_at": "2026-09-09T22:00:00Z"  // copied from the repository, may be null
  },
  "built": [                         // the newest passing push builds of ci, newest first
    {
      "commit": "70fa2864…",         // its full SHA
      "versions": { /* see below */ } // what it was published under
    }
  ],
  "workflows": [ /* see below */ ]
}

Each entry in workflows has this shape:

{
  "name": "ci",
  "path": ".github/workflows/ci.yml", // "" when the workflow is gone but its runs remain
  "declared": true,                   // active in .github/workflows
  "latest": { /* run, or null when it has never run */ },
  "runs": [ /* newest first, at most `window` of them */ ],
  "counted": 20,                      // entries in `runs` that reached a verdict
  "pass_rate": 85,                    // whole percent of `counted`, or null when counted is 0
  "failures": 3,                      // of `counted`
  "median_duration": 218,             // seconds across `counted`, or null
  "green_streak": 12,                 // passes at the tip of `counted`
  "last_failure": { /* run, or null — from all history, not only `runs` */ }
}

Each run:

{
  "state": "success",                 // conclusion, or status when still running
  "started": "2026-09-09T21:00:00Z",
  "duration": 218,                    // seconds, or null
  "title": "Bump dependencies",
  "sha": "70fa286",                   // the first 7 characters of the head SHA
  "event": "push",
  "attempt": 1,
  "actor": "octocat",
  "url": "https://github.com/…/actions/runs/123",
  "commit": "70fa2864…",              // the full head SHA
  "versions": { /* see below */ }     // what that commit was published under
}

The versions a commit was published under, in each built entry and in every run:

{
  "go": "v0.0.0-20260923200616-70fa28640a2b",   // Go's version of it, or null
  "images": {                                   // ghcr.io/<owner>/<repository>: tag
    "npm/lint": "0.0.0-20260923200616-70fa28640a2b"
  },
  "npm": {                                      // package on npmjs.com: version
    "@codesweep-ai/lint": "0.0.0-20260923200616-70fa28640a2b"
  }
}

Workflows are ordered ci first, then by name, and a page renders them in the order it is given. The primary gate leads because it is the one a reader came for.

Rules

The index

projects.json in this repository says where the status files are:

{
  "schema": 1,
  "title": "codesweep-ai CI",         // optional, used in the document title
  "projects": [
    { "name": "lint", "status": "../lint/ci-status.json" }
  ]
}

scripts/check-projects.py enforces the first two.

The dependencies file

The dependencies page reads one file, published beside it:

https://codesweep.ai/dashboards/deps.json

No project writes it. This site’s own build writes it with python3 -m collector, on every push and once a day. The collection is its own workflow, dashboard-deps.yml, which pages.yml calls before it assembles and deploys the site. The collector reads each project’s default branch over plain git, and asks public registries about every dependency it finds there. It needs no API key. README.md says why it runs on a schedule when nothing else here does.

What the collector reads

Kind Declared in Upstream read from
Go modules go.mod, go.<name>.mod, go install x@v proxy.golang.org
npm packages package.json, resolved through package-lock.json registry.npmjs.org, with release dates from deps.dev
Python packages pip install pypi.org
GitHub Actions uses: in workflows and in action.yml, and installs in run: steps GitHub releases, or tags where a project publishes no releases
Toolchains the go directive, go-version, node-version, nvm install, pyenv install, download URLs endoflife.date, the Go module proxy, nodejs.org, Maven Central
Images and runners FROM, image:, image references in .env files, runs-on and matrix os: labels, a WSL distribution: GitHub’s runner-images table for what a label runs, endoflife.date for an OS release, the registry for tags
System packages dnf install in a Containerfile Fedora’s mdapi for the version each name resolves to, and Bodhi for security updates
Native and binaries an ARG *_VERSION whose download URL names its upstream, a Renovate annotation, a declared pin GitHub releases, or the datasource the pin names; Firecracker’s own support tables
Vendored code an AboutCode .ABOUT file beside the copy the registry its package_url names, or the upstream its download_url names

Release lines for anything else come from endoflife.date’s index of package identifiers, which knows React and ESLint by their npm names. Vulnerabilities come from api.osv.dev for Go modules, the Go standard library, every package an npm lockfile installs, and PyPI. Manifests under a directory named testdata, cassettes, examples, vendor or node_modules are skipped, since they describe something other than the project.

Install scripts come from the hasInstallScript flag npm writes into a lockfile. The table below names every source and what each gives.

Running the collector

The collector is python3 -m collector, run from this repository’s root. It is standard-library Python, and it needs git. Reachability also needs Go, which builds govulncheck from this repository’s go.mod. A token in GH_TOKEN or GITHUB_TOKEN is used for GitHub when present, and nothing needs one.

Option Default What it does
--projects projects.json the projects to read
--config deps-config.json pins, snapshots and policies
--output deps.json where the dependencies file goes; - for standard output
--actions   also write the actions file
--feed   also write the Atom feed
--sbom   also write the CycloneDX SBOM
--previous   an earlier dependencies file, as a path or URL, for history and known facts
--only every project comma-separated project names
--keep a temporary directory clone here and leave the clones
--jobs 12 records resolved at once
--no-reachability   skip govulncheck
--owner $GITHUB_REPOSITORY_OWNER, else org the GitHub owner whose repositories are read
--site the config’s site, when the owner is org where this site is published, for status files and links

The site’s build runs it with --actions, --feed and --sbom. It passes --site as the address this repository’s Pages settings give, and --previous as the dependencies file published there.

A fork reads its own projects. org names the namespace of the Go modules, npm packages and images that count as siblings, and a fork does not rename those. --owner names whose repositories are cloned, and --site where the status files and the previous file are read. So a fork’s build reads the fork’s repositories and its own history, and still knows github.com/codesweep-ai/ledger for a sibling. With no site, no status file is read and the links the collector writes are relative.

The collector clones nothing for an owner that cannot be a GitHub name, such as a path, or for a $GITHUB_REPOSITORY that is not owner/name. It exits 2 and names the setting, because the clone would otherwise fail as Authentication failed, which points at credentials instead of at the owner.

Every request identifies the collector in its User-Agent, and gives up after 30 seconds. A request that fails is retried up to four times with a growing pause, and a 429 waits as long as its Retry-After asks. A few hosts that throttle bursts get a cap on requests in flight at once.

Information sources

Every source the collector reads is public and needs no key. The build’s own token goes to GitHub’s hosts and no other, where it lifts limits shared by every runner. data_sources in the file carries this list in short, and the page shows it under Sources.

The projects

Source Read from What the collector takes Access Data terms Notes
GitHub repositories github.com/<owner>/<project> over git Manifests, lockfiles, workflows, Containerfiles, env files, deployment YAML, .ABOUT files and pinned files; commit history for internal pins; the full source govulncheck reads; tags, over git ls-remote, for an action with no releases the build’s token, sent only to github.com each repository’s own Clones are blobless and sparse, so only manifest files are downloaded until govulncheck needs the rest.
Project status files each project’s status file, resolved against --site The one-line description a project card shows none each project’s own The same files the CI page reads.
The previous deps.json deps.json under --site, as --previous history, seen, and each exact version’s licenses, provenance and source repository, and each Fedora build’s source package and license none this site’s own A missing file starts history again, and every fact is asked for afresh.

Versions and releases

Source Read from What the collector takes Access Data terms Notes
Go module proxy proxy.golang.org, and sum.golang.org through go The newest version and release dates of direct Go modules, the next major, and Go release dates from the golang.org/toolchain module; the modules govulncheck builds none none stated Indirect modules are not looked up.
npm registry registry.npmjs.org/<name>/latest The newest version and repository of each direct npm package none none stated Transitive packages are not looked up. A 429 is retried after its Retry-After.
PyPI pypi.org/pypi/<name>/json The newest version of each Python package none none stated  
Maven Central repo1.maven.org maven-metadata.xml Maven releases, for a Maven toolchain pin none none stated  
Node.js release index nodejs.org/dist/index.json Node.js releases and their dates none none stated  
GitHub releases api.github.com/repos/<repo>/releases, or github.com/<repo>/releases.atom Releases, their dates and pre-release flags for GitHub Actions and binaries downloaded from GitHub the build’s token; the Atom feed without one each repository’s own The feed lists only recent releases, so a run without a token can see fewer.
Container registries /v2/<repo>/tags/list on Docker Hub, ghcr.io, registry.fedoraproject.org and gcr.io The tags of each container image anonymous registry tokens none stated  

Support windows

Source Read from What the collector takes Access Data terms Notes
endoflife.date endoflife.date/api/v1/products/<product> and /api/v1/identifiers/purl Each release line’s release, support and end-of-life dates and newest release; which package identifiers belong to which product none MIT Its v1 API. A 429 is retried after its Retry-After.
GitHub runner images actions/runner-images README, as raw text The image, OS version and architecture each hosted runner label runs, and which labels are deprecated or in preview the build’s token MIT A table in a README, not an API: a change of shape leaves runners unresolved rather than wrong.
Firecracker policies docs/RELEASE_POLICY.md and docs/kernel-policy.md in Firecracker’s repository, as raw text Firecracker’s supported release lines and their end dates, and the guest kernel lines each supports the build’s token Apache-2.0 Tables in documents, read the same way as the runner images.

Security

Source Read from What the collector takes Access Data terms Notes
OSV api.osv.dev/v1/querybatch and /v1/vulns/<id> Which advisories affect each Go module, npm package and PyPI version and the Go standard library, with aliases, severity, fixed releases and dates; the same for each proposed fix none each source database’s, such as CC-BY-4.0 for GitHub’s  
Go vulnerability database, through govulncheck vuln.go.dev, read by govulncheck Whether a project’s code calls, imports or only requires what a Go advisory names, and which modules its build includes none CC-BY-4.0 govulncheck is built from the version this repository’s go.mod pins.
CISA KEV catalog CISA’s known_exploited_vulnerabilities.json, or its cisagov/kev-data copy on GitHub Which CVEs are exploited in the wild, and the day each was listed none; the build’s token for the GitHub copy CC0-1.0 The GitHub copy is CISA’s own and syncs within minutes, so both give the same answer.
FIRST EPSS api.first.org/data/v1/epss?cve=… Each CVE’s probability of exploitation within 30 days, and its percentile none free, with attribution requested CVEs go in batches whose query stays under 2,000 characters.
Fedora Bodhi bodhi.fedoraproject.org/updates/ Security updates pushed to a Fedora release since an image was built, with their builds and severity; the newest kernel build of a release none none stated  

Packages and licenses

Source Read from What the collector takes Access Data terms Notes
deps.dev api.deps.dev/v3 version, dependencies and project endpoints Each version’s licenses, publish date, deprecation, provenance and source repository; each repository’s license, stars and OpenSSF Scorecard checks; what installing an npm version brings in none CC-BY-4.0 One stable v3 call per version the previous file does not already describe. Deprecation is asked for every direct record. The dependency graph is asked only of a version an upgrade moves to, when a vulnerable lockfile package hangs from it.
ClearlyDefined api.clearlydefined.io/definitions, in batches, without file lists The licenses scans found in a shipped package’s files, and its license score none CC0-1.0 Evidence only: a failure leaves no verdict changed.
ScanCode LicenseDB scancode-licensedb.aboutcode.org/index.json The category of each license, shown beside a license the policy does not name none CC-BY-4.0 A hint only: no verdict depends on it.
Fedora mdapi mdapi.fedoraproject.org/<branch>/pkg/<name> The version a package name resolves to in a Fedora release, its architecture, and the packages built from the same source none none stated  
Fedora Koji koji.fedoraproject.org/kojihub, XML-RPC getRPM and getBuild The source package each binary package was built from none none stated A call times out after 30 seconds and is tried twice. When Koji cannot answer, name rules pick the source package.
Fedora dist-git src.fedoraproject.org/rpms/<source>/raw/f<release>/f/<source>.spec The License: tag of each source package’s spec, an SPDX expression none each package’s own An HTML page in place of the spec, such as a bot filter’s challenge, is a failure.

Shape

{
  "schema": 1,
  "generated": "2026-09-13T05:17:00Z",
  "org": "codesweep-ai",              // the namespace whose packages count as siblings
  "owner": "codesweep-ai",            // whose repositories were read; a fork's own owner in a fork
  "levels": ["idle", "good", "info", "warning", "serious", "critical"],
  "projects": [ /* see below */ ],
  "lifecycle": [ /* every release cycle in use, once: the record's lifecycle fields, plus
                    "projects": the projects using it, and "dependencies": the records' names */ ],
  "actions": [ /* every action across the org, as "Actions" below describes */ ],
  "history": [ /* one row a day: date, dependencies, attention, vulnerabilities, eol, major, libyears */ ],
  "data_sources": [ { "id": "osv", "group": "security", "name": "OSV", "url": "https://osv.dev",
                      "gives": "…", "license": "…", "hosts": ["api.osv.dev"] } ],  // as the table below
  "seen": { "lint|go|golang.org/x/mod|vulnerable": "2026-09-13T02:44:09Z",  // first sightings: of a gap,
            "action|eol|linux|6.19": "2026-09-13T05:17:00Z" },            // and of an action the feed announces
  "sources": [ { "host": "proxy.golang.org", "requests": 23, "failures": 0, "errors": [] } ],
  "authenticated": true              // whether GitHub was read with the build's token
}

Each entry in projects has this shape:

{
  "name": "sandbox",
  "repo": { "full_name": "codesweep-ai/sandbox", "url": "…", "branch": "main",
            "sha": "fe9796d…", "committed": "2026-09-11T22:06:08Z", "description": "…" },
  "error": "…",                      // present only when the repository could not be read
  "manifests": ["go.mod", "image/Containerfile.base"],
  "dependencies": [ /* records, see below */ ],
  "summary": {
    "dependencies": 151,             // records that are not indirect
    "indirect": 214,                 // indirect and transitive records
    "attention": 22,                 // records that need attention
    "by_status": { "minor": 6 },
    "by_ecosystem": { "go": { "total": 10, "levels": { "info": 4, "good": 6 } } },
    "vulnerabilities": 2,            // distinct advisories
    "libyears": 8.5,
    "state": "critical",             // the highest level that needs attention
    "licenses": { "allowed": 147, "not-shipped": 320 },
    "signals": 6,                    // declared records carrying a supply-chain signal
    "sla": { "breached": 0, "due-soon": 0, "within": 0 },
    "tiers": { "fix": 3, "plan": 3, "routine": 5 }   // the project's own actions, by tier
  },
  "actions": [ /* this project's actions on their own, titled for it */ ],
  "reachability": "govulncheck",     // present when govulncheck read the project
  "unmatched": [ { "path": "…", "match": "…", "name": "…", "reason": "pattern did not match" } ],
  "snapshot": { "built": "…", "from": "image/tiers.env", "packages": "image/Containerfile.base",
                "release": "44", "updates": 23, "matched": 2 },
  "notes": [ "…" ]                   // optional: a lookup that failed for the whole project
}

Each record in dependencies has this shape:

{
  "ecosystem": "native",             // go, npm, pypi, actions, runtime, image, package or native
  "name": "github.com/firecracker-microvm/firecracker",
  "label": "Firecracker",            // optional display name
  "version": "1.16.0",               // as pinned, or null when nothing is pinned
  "constraint": "^18.3.1",           // optional: the range as written, when it differs
  "scope": "build",                  // direct, dev, tool, build, toolchain, ci, deploy, engines,
                                     // optional, vendored, indirect or transitive
  "internal": false,                 // pins a repository of the org
  "dev": true,                       // npm: installed only for development, by the lockfile's reckoning
  "floating": false,                 // names a line rather than a release: `v7`, `24`, a dnf package
  "sources": [ { "path": "internal/fcdisk/build.go", "line": 73 } ],   // every place it is declared
  // A source folded in from a Containerfile ARG names it: { "path": "…", "line": 3, "arg": "GO_VERSION" }
  // A Go module file naming the module's commands as tools lists them: "tools": ["…/cmd/golangci-lint"]
  "datasource": "github",            // where its upstream is read: github, npm, goproxy, pypi, golang, node,
                                     // python, temurin, maven, oci, runner, rpm or fedora-kernel
  "package": "firecracker-microvm/firecracker",   // its name at that datasource, when it differs
  "tag_prefix": "v",                 // GitHub: what a release tag puts before the version
  "declared": true,                  // named by a pin in deps-config.json or an .ABOUT file
  "arg": "FC_VERSION",               // a Containerfile ARG that holds the version
  "variable": "AGENTS_IMAGE",        // an .env variable that holds an image reference
  "subpath": "save",                 // an action inside a repository: actions/cache/save
  "pinned_sha": false,               // an action pinned by a full commit
  "self_hosted": true, "os": "macos",   // a self-hosted runner, and the OS its labels name
  "manager": "dnf",                  // a system package: dnf, microdnf or yum
  "release": "44",                   // a system package or kernel: the Fedora release it comes from
  "snapshot": "2026-09-07T21:57:45Z",   // a system package: when its image was built
  "lockfile": "apps/viewer/package-lock.json",   // npm: the lockfile that resolved it
  "via": ["vitest"],                 // a vulnerable transitive package: the declared dependencies that install it
  "cleared_by": [ { "name": "vitest", "version": "4.1.11" } ],   // …and the moves that drop every affected copy
  "upstream_repo": "github.com/vitest-dev/vitest",   // the source repository, for grouping and Scorecard
  "upstream": {
    "latest": "1.17.0",
    "latest_date": "2026-09-10T10:42:35Z",
    "version_date": "2026-05-12T09:01:12Z",
    "line_latest": "1.16.2",         // the newest release on the pin's major.minor
    "effective": "4.3.0",            // what a floating pin resolves to
    "next_major": "…",               // Go: the next major version's module path
    "url": "…"
  },
  "behind": "minor",                 // major, minor or patch; absent when not behind
  "libyears": 0.27,
  "lifecycle": { "product": "linux", "cycle": "6.19", "release": "2026-02-08", "support": null,
                 "eol_is_floor": false,    // true when the end is only "supported at least until"
                 "eol": "2026-04-22", "lts": false, "latest": "6.19.14", "phase": "eol", "url": "…" },
  "lag": { "commits": 8, "commits_touching": 1, "paths": ["action"], "days": 0.5,
           "head": "d687ad5b27750000…",   // the whole commit the sibling's default branch is at
           "built": "a48d212425fe0000…",  // the sibling's last passing build: the first its status file names
           "pinned": "4c204c69b8b2",
           "version": "0.3.1-dev.20260922202805.27eb21f",   // npm: the version that commit's build published
           "image_only": true,            // npm: npmjs.com lists no such version yet, and the build's image carries it
           "builds": 3,                   // an image: newer tier builds, in place of commits
           "held": "ledger lists no build",   // why nothing moves the pin, when its status is `held`
           "off_branch": true },          // the pinned commit is not on the default branch
  "provider": "dashboards",          // internal: the project pinned
  "runner": { "image": "macOS 26 Arm64", "os": "macos", "version": "26", "arch": "arm64",
              "deprecated": false, "preview": false },   // a GitHub-hosted runner label, resolved
  "compat": {                        // a declared compatibility check
    "with": "Firecracker", "line": "6.19", "ok": false, "url": "…",
    "validated": ["5.10", "6.1", "6.18"],                 // the guest lines its policy lists
    "guaranteed": { "6.18": "2028-06-01" },              // each line's minimum end of support
    "requires": { "6.18": "1.16.1" },                    // each line's first Firecracker release
    "target": { "line": "6.18", "lts": true, "eol": "2028-12-31", "latest": "6.18.51",
                "guaranteed": "2028-06-01", "min_firecracker": "1.16.1" },   // the line to move to
    "newer": { "ended": ["6.19", "7.0", "7.1"], "not_validated": ["7.2"] },  // why not a newer line
    "distribution": { "name": "Fedora 44", "latest": "7.2.4-200.fc44", "line": "7.2", "has_target": false },
    "firecracker": { "name": "github.com/firecracker-microvm/firecracker", "pinned": "1.16.0",
                     "needs": "1.16.1", "ok": false }  // the project's own Firecracker pin, against the target
  },
  "source_package": "openssl",       // a Fedora package: the source package it builds from
  "note": "…",                       // something true that is not a verdict
  "purl": "pkg:npm/react@18.3.1",    // the package URL of the pinned release, where a purl type fits
  "tier": "routine",                 // needing attention: the tier its own action sits in
  "how": "npm install react@18.3.2", // needing attention: the command or edit that makes its change
  "after": [ { "run": "make viewer-build build", "cwd": "." } ],   // deps-config.json's steps after a move
  "fix_advisories": ["GO-2026-6180"], // advisories on the first fixed release, which `fix` steps past
  "in_build": true,                  // Go: whether the project's packages build this module
  "reachability": "not-in-build",    // Go: the closest the code comes to any advisory on it
  "licenses": ["MIT"],               // SPDX expressions, as its registry or spec states them
  "license": { "expression": "MIT", "verdict": "allowed",
               "found": ["MPL-2.0"], "found_verdict": "review",  // flagged or unnamed licenses a scan found in its files
               "unlisted": { "MPL-2.0": "Copyleft Limited" },   // licenses the policy does not name, with a hint
               "found_url": "https://clearlydefined.io/definitions/…", "score": 46,
               "opened": "…", "sla": { /* as below */ } },  // graded against the policy
  "signals": [ { "kind": "abandoned", "text": "no release since 2019-06-19 and …" } ],
  "repo_signals": { "scorecard": { "score": 6.2, "date": "2026-08-24", "checks": { "Maintained": 2 } },
                    "stars": 44592 },
  "provenance": true,                // published with a build attestation
  "install_script": true,            // npm runs a script when it installs this package
  "installer": "scripts/with-npmrevs.sh",   // npm, internal: the script the project's installs run through
  "opened": "2026-08-13T21:43:54Z",  // when a security or end-of-life gap opened
  "sla": { "since": "…", "due": "…", "days": 7, "state": "breached" },  // only with a policy
  "accepted": { "reason": "not_used", "note": "…", "until": "2026-12-01T00:00:00Z",
                "finding": "GO-2026-6179", "lapsed": false },
  "vulnerabilities": [ { "id": "GHSA-…", "aliases": ["CVE-…"], "severity": "high",
                         "summary": "…", "fixed": "6.4.3", "published": "…", "url": "…",
                         "reachable": "called",       // Go: called, imported, required or not-in-build
                         "exploited": "2026-09-01",   // the day CISA's KEV catalog listed it
                         "epss": { "probability": 0.42, "percentile": 0.97 } } ],
  "fix": "6.4.3",                    // the release that clears every advisory
  "fix_partial": true,               // no known release clears every advisory
  "deprecated": "…",
  "error": "HTTP 503 (proxy.golang.org)",
  "status": "minor",
  "level": "info"
}

Scopes

A record’s scope says what the dependency is for, and so whether its code reaches what the project ships:

Scope Declared as Ships
direct a require in go.mod, dependencies in package.json yes
indirect an // indirect require in go.mod yes, unless govulncheck finds it outside the build
transitive a package only a lockfile installs yes, unless the lockfile marks it dev
dev devDependencies no
optional optionalDependencies no
engines engines.node in package.json no
tool a module a tool directive names no
toolchain a toolchain directive no
build the go directive, a Containerfile, a download URL, a declared pin yes
ci a workflow or an action’s action.yml no

An install command in a run: step or a RUN line, such as go install x@v, npm install -g x@v or pip install, takes the scope of the file it is in: ci or build. | deploy | a deployment manifest or a compose file | yes | | vendored | an .ABOUT file beside a copy | yes |

“Ships” is the question a license verdict asks. It never changes a status, and a vulnerable record needs attention whatever its scope.

Statuses and levels

Every record carries one status and one level. The status says what is true, and the level says how urgent it is. The collector decides both, so a page renders them rather than re-deriving them. The first row that applies wins:

Status When Level
vulnerable an advisory affects the pinned version critical for a high or critical advisory in something that ships, or for any advisory exploited in the wild; serious otherwise
eol its release cycle is past its end of life critical, serious for a dev, CI or optional scope, or warning for an engines floor
eol-soon its release cycle ends within 90 days serious, or info for an engines floor
held an internal pin whose project lists no build, so a repin has nothing to move it to idle
behind an internal pin trails the last passing build of the project it pins info up to 14 days of work, warning to 60, serious past that
major a newer major version exists warning, or serious once that release is a year old
deprecated its publisher deprecated the pinned version warning
minor, patch a newer minor or patch release exists info, or warning once that release is 90 days old
unknown a lookup failed idle
current the newest release is what runs good
floating nothing pins a release, and no row above applies idle
untracked an indirect or transitive record no advisory affects idle

The two release-age windows are Chromium’s policy for third-party code. An advisory counts as shipping unless its scope is dev, ci or optional. A record needs attention at info or above. An indirect or transitive record needs attention only when it is vulnerable.

One more rule changes a level after the table has set it. A vulnerable Go module the code never calls drops to warning. govulncheck read the project and found no call to what any advisory names, so the version sits in the module graph while the hole sits outside every path the code takes. An advisory exploited in the wild drops only to serious, since a scanner can miss a call an attacker finds.

“Exploited in the wild” means CISA’s KEV catalog lists a CVE the advisory aliases. The catalog lists what attackers have used against real systems, whatever an advisory’s score says.

Evidence beside the verdict

A status says how current a dependency is. The fields below say what else is true of it, and none of them changes the status.

Reachability. reachable on a Go advisory says how close the project’s code comes to it:

Value Meaning
called a function the advisory names is reachable from the project’s packages
imported a package the advisory names is imported, and nothing calls the vulnerable code
required the module is required, and no package the advisory names is imported
not-in-build the module is not in what the project’s packages build at all

govulncheck can miss a call made through reflection or unsafe code, so a not-in-build advisory stays on the record and in the queue, one level lower.

Exploitation. exploited on an advisory is the day KEV listed one of its CVEs. epss is EPSS’s probability that the CVE is exploited within 30 days, and the share of scored CVEs it ranks above. Neither is set for an advisory with no CVE alias. The page orders work by exploitation, then by EPSS, within a level.

Fixed releases. fix is the release to move to. It starts as the highest first-fixed release among the record’s advisories. That release is looked up in turn, and when an advisory affects it too, fix steps to the release that clears that one, up to three times. fix_advisories lists what was stepped past. When no release is known to clear them, fix_partial is true.

License verdicts. license.verdict grades a record’s license expression against the policy in deps-config.json. A license is graded by an exact entry first, then by a wildcard entry. Nothing fetched changes a verdict, so the same policy and the same declared license always grade the same way:

Verdict Meaning
allowed the policy allows every license the expression requires
review the policy asks for a human to read at least one of them
denied the policy denies a license the expression requires
unknown no registry or spec states a license, or the policy names none of the licenses stated
not-shipped the dependency never reaches what the project ships, so its license binds nobody downstream
aggregate a separate program an image redistributes, graded only against deny_aggregate

An expression is graded the way SPDX reads it: A AND B takes the worse of the two, and A OR B the better. A WITH exception is graded as that pair when the policy names it, and by A otherwise. A dependency is shipped unless its scope is dev, ci, tool, toolchain, engines or optional. A Go module is also not shipped when govulncheck found it outside the project’s build, or when only a second module file such as go.golangci.mod requires it. The org’s own packages carry no verdict.

license.unlisted maps each license the policy does not name to its LicenseDB category, as a hint for which list it belongs in. The category is empty when LicenseDB does not know the license.

Licenses found in files. A shipped package’s declared license can hide code under another: a bundled font, a vendored file. license.found lists licenses ClearlyDefined’s scans found in the package’s files, from each expression that grades worse than the declared one as a whole. Each is a license the policy flags, or one it does not name. found_verdict is the worst of them, and score is ClearlyDefined’s 0 to 100 measure of how clearly the package states its licensing. Direct npm, Go and PyPI packages that ship are looked up. Only SPDX ids count, because some of ScanCode’s own license keys are loose matches, such as a copyright line read as a proprietary license. A found license is evidence on the record, and never an action of its own.

Supply chain signals. signals lists what a reviewer would want to know before trusting a dependency:

Kind When
deprecated the registry marks the version deprecated
abandoned no release in two years, and OpenSSF Scorecard finds no repository activity in 90 days
stale no release in a year
quiet OpenSSF Scorecard finds no repository activity in 90 days
scorecard OpenSSF Scorecard fails Dangerous-Workflow, Binary-Artifacts or Code-Review outright
install-script npm runs a script when it installs the package
unpinned-action a third-party action is pinned by a tag its owner can move

When a gap opened. opened dates a gap from its public start. For a vulnerable record that is the earliest advisory’s date, and for an end of life the date support ended. For a version behind it is the day the newest release came out. Anything else, a license finding or an end of life still ahead, opens on the first run that saw it, carried forward in seen. The page shows the gap’s age and orders work by it.

Fix-by dates. sla exists only when deps-config.json sets a number of days for the record’s level. It says when the fix is due and whether that date is within, due-soon or breached. due-soon is the last quarter of the window, and at least the last three days.

Acceptances. accepted records a decision from deps-config.json to leave a finding be. Its reason is one of Dependabot’s dismissal reasons: fix_started, inaccurate, no_bandwidth, not_used or tolerable_risk. An accepted record needs no attention until its until date. After that date lapsed is true and it needs attention again.

Rules

Actions

An action is one change to make: moving one dependency, or several that move together, in one project or in several. The collector turns records into actions, as it turns facts into statuses, so the page and an agent follow the same work. deps.json carries them twice: actions across every project, and projects[].actions for each project on its own.

{
  "id": "action-eol-linux-6-19",     // the page's anchor for the card
  "key": "eol|linux|6.19",           // what groups items onto the action
  "kind": "eol",                     // one of the kinds below
  "tier": "fix",                     // fix, plan or routine: when to act
  "level": "critical",               // the highest level among its items
  "type": "eol",                     // security, eol, license, supply, sync or update: what kind of work
  "status": "eol",                   // the status of its most urgent item
  "title": "Move off Linux kernel 6.19 in sandbox",
  "result": "Linux kernel 6.19 ended 2026-04-22",
  "why": "Firecracker supports guest kernels 6.18, not 6.19",
  "released": { "version": "19.3.0", "date": "…" },   // for a version gap: when the target came out
  "how": "set the version to a Fedora kernel build on the 6.18 line   at internal/fcdisk/build.go:28",
  "evidence": ["…"],
  "projects": ["sandbox"],
  "opened": "…", "ends": "…", "sla": { /* the earliest */ },
  "exploited": false, "epss": 0.0091,
  "items": [ { "project": "sandbox", "record": 3, "tier": "fix", "reason": null, "to": "6.18 line" } ],
  "requires": ["action-eol-firecracker-1-16"],   // actions to make first
  "options": [ { "recommended": true, "text": "6.18 LTS microVM kernel: …", "url": "…" },
               { "text": "Fedora 44 kernel 7.2.5-200.fc44: patched, not validated by Firecracker" } ],   // a choice for a person
  "steps": [ /* every step, as the actions file lists them, when there are requires or options */ ]
}

record is the index of the record in that project’s dependencies. reason is license, unlisted or abandoned when the item is there for that rather than for its status, and to is the version it moves to.

Kind One action per Its items
lock lockfile vulnerable packages the lockfile installs, fixed by refreshing it
rebuild Containerfile Fedora packages with a security update newer than the image
sync internal pin the same sibling pinned across projects
eol release line everything on a release line past, or near, its end of life
actions org every GitHub Action a major behind
devtools package.json majors in one project’s dev tooling
routine ecosystem minor and patch releases
license package and verdict a license the policy denies or asks to review
unlisted package a license the policy does not name
replace package an abandoned package
dep upstream repository packages one upstream releases together, such as react, react-dom and their types

The actions file

deps-actions.json, published beside the dependencies file, is the same actions arranged for an agent to follow in a clone of each project. It needs no key and no parsing of the page:

https://codesweep.ai/dashboards/deps-actions.json
{
  "schema": 1,
  "generated": "2026-09-12T20:56:03Z",
  "org": "codesweep-ai",
  "owner": "codesweep-ai",           // whose repositories to clone and edit
  "about": "…",
  "workflow": ["…"],                 // how to take the actions: order, commits, checks, declining
  "tiers": { "fix": "…", "plan": "…", "routine": "…" },
  "links": { "page": "…", "data": "…", "sbom": "…", "feed": "…", "spec": "…" },
  "data_sources": [ { "name": "OSV", "url": "…", "gives": "…", "license": "…" } ],
  "projects": [ {
    "name": "tracer",
    "repo": { "url": "…", "clone": "https://github.com/codesweep-ai/tracer.git", "branch": "main", "sha": "…" },
    "counts": { "fix": 4, "plan": 5, "routine": 5 },
    "actions": [ {
      "id": "tracer:dep:github-com-vitest-dev-vitest",
      "tier": "fix", "level": "serious", "type": "security",
      "title": "Upgrade vitest to 4.1.11 in tracer",
      "result": "Fixes 2 advisories", "why": "…", "evidence": ["…"],
      "opened": "…", "ends": "…", "due": "…", "exploited": true, "epss": 0.42,
      "requires": ["sandbox:eol:firecracker-1-16"],   // actions to make first, listed before this one
      "options": [ { "recommended": true, "text": "…", "url": "…" }, { "text": "…" } ],
      "steps": [
        { "run": "npm install -D vitest@4.1.11", "cwd": "apps/viewer" },
        { "edit": "internal/fcdisk/build.go", "line": 73, "text": "set the version to 1.17.0", "from": "1.16.0", "to": "1.17.0" },
        { "do": "Rebuild the image that image/Containerfile.base describes, then point the pinned tag at the new build." }
      ],
      "changes": [ {
        "ecosystem": "npm", "name": "vitest", "label": "…", "purl": "pkg:npm/vitest@2.1.9", "scope": "dev", "dev": true,
        "status": "vulnerable", "level": "serious", "from": "2.1.9", "to": "4.1.11",
        "reason": "license",           // present when the change is there for a license or an abandoned package
        "files": ["apps/viewer/package.json:45"],
        "advisories": [ { "id": "GHSA-…", "aliases": ["CVE-…"], "severity": "critical", "summary": "…",
                          "fixed": "3.2.6", "url": "…", "reachable": "called", "exploited": "…", "epss": { } } ],
        "fix_advisories": ["GHSA-…"],
        "license": { /* the record's, for a license change */ },
        "lifecycle": { "product": "…", "cycle": "…", "eol": "…", "phase": "…", "url": "…" },
        "compat": { /* the record's */ }, "lag": { /* the record's */ },
        "cleared_by": ["vitest"],      // a lockfile package this action's own moves clear, with no step of its own
        "signals": [ /* the record's, for an abandoned package */ ],
        "done_when": "apps/viewer/package-lock.json carries no copy of vitest that GHSA-… affects"
      } ],
      "page": "https://codesweep.ai/dashboards/deps?project=tracer#action-…",
      "decline": { "file": "deps-config.json", "repo": "codesweep-ai/dashboards",  // the repository that built this file
                   "accepted": { "project": "tracer", "name": "vitest", "finding": "GHSA-…", "reason": "tolerable_risk",
                                 "note": "…", "until": "YYYY-MM-DD", "version": "2.1.9" },
                   "reasons": ["fix_started", "inaccurate", "no_bandwidth", "not_used", "tolerable_risk"] }
    } ]
  } ]
}

The dependencies configuration

deps-config.json in this repository holds what no manifest says:

{
  "schema": 1,
  "comment": "…",                             // for a reader of the file; nothing reads it
  "org": "codesweep-ai",                      // the namespace whose modules, packages and images are siblings
  "site": "https://codesweep.ai/dashboards/",  // where org publishes this site; a fork passes --site instead
  "include": ["dashboards"],                  // repositories read besides the projects in projects.json
  "pins": [ {
    "project": "sandbox",
    "path": "internal/fcdisk/build.go",
    "match": "DefaultFCVersion = \"v?([^\"]+)\"",
    "name": "github.com/firecracker-microvm/firecracker",
    "label": "Firecracker",
    "datasource": "github",
    "package": "firecracker-microvm/firecracker",
    "tag_prefix": "v",                        // optional: what a release tag puts before the version
    "ecosystem": "native",                    // optional, native by default
    "scope": "build",                         // optional, build by default
    "internal": false,                        // optional: a pin on the org's own package
    "compat": "firecracker-guest",            // optional: a compatibility check to run
    "cycle": "1.16",                          // optional: the release line, when the version does not say
    "note": "…"                               // optional: shown on the record
  } ],
  "snapshots": [ {
    "project": "sandbox",
    "packages": "image/Containerfile.base",
    "built": { "path": "image/tiers.env", "match": "^AGENTS_REF=\\S+:v0\\.0\\.0-(\\d{14})-" }
  } ],
  "after": [ {
    "project": "ledger",
    "name": "@codesweep-ai/ui",
    "steps": [ { "run": "make viewer-repin", "cwd": "." } ]
  } ]
}

The configuration also carries three policies:

{
  "licenses": {
    "allow": ["MIT", "Apache-2.0", "BSD-3-Clause"],   // SPDX identifiers, with * as a wildcard
    "review": ["MPL-*", "LGPL-*"],
    "deny": ["GPL-*", "AGPL-*", "SSPL-*"],
    "deny_aggregate": ["LicenseRef-Callaway-*"],     // denied even for a program an image carries
    "aggregate": ["package", "image", "native", "runtime"]
  },
  "sla": { "critical": 7, "serious": 30 },          // optional: fix-by days per level
  "accepted": [ {
    "name": "golang.org/x/mod",
    "project": "lint",                               // optional, * for every project
    "version": "v0.39.0",                            // optional
    "finding": "GO-2026-6179",                       // optional: an advisory id, a status, or "license"
    "reason": "not_used",
    "note": "only the ledger tool requires it",
    "until": "2026-12-01"
  } ]
}

Mechanisms and prior art

The dependencies page borrows most of what it does from existing projects and products. Each mechanism below has a table of how others do the same job, and its last row says how this dashboard does it. The comparisons are about approach, and each approach buys something different.

These are the projects and products it is compared with:

Finding dependencies

How a tool finds what a project depends on.

Who How
Renovate A manager per manifest format reads the repository it runs in, and regex managers and comment annotations cover the rest.
Dependabot GitHub’s dependency graph reads the manifests it supports, and a pin outside them is not tracked.
zeitgeist A dependencies.yaml lists each version with the files and patterns where it appears, then checks each upstream.
Dependency-Track It ingests the CycloneDX SBOM a build produces, so it sees what the SBOM generator saw.
Grype, Trivy They scan a directory or an image, which finds installed packages that no manifest names.
ScanCode.io Its pipelines scan a codebase or a container image, and write a CycloneDX SBOM of the packages they find.
AboutCode .ABOUT files A small text file beside vendored code states its name, version, purl and license.
This dashboard It clones each default branch without file contents and reads only the files a manifest can live in, so nothing is built, pulled or added to a project. A version kept elsewhere is declared in deps-config.json, a Renovate annotation or an .ABOUT file. A package an image installs only as another’s dependency is missed.

Freshness

How a tool says a dependency is behind.

Who How
Renovate, Dependabot Each update becomes a pull request with release notes, so freshness is a queue of pull requests per repository.
libyear, CHAOSS Libyears sum drift into one number per project.
Chromium Its policy states how long bundled third-party code may trail upstream.
Anitya, Repology They map upstream releases onto distribution packages.
This dashboard Versions compare as numbers, and libyears measure drift. Chromium’s release-age windows raise a gap’s level as the newer release ages. It opens no pull request: each action names the command or edit, once for every project it spans.

Release lines and end of life

Where support dates come from.

Who How
endoflife.date It publishes support dates per release cycle, and an index from package identifiers to products.
xeol It matches an SBOM or an image against endoflife.date’s data.
Docker Scout It recommends a newer base image tag for an image it scans.
Chainguard Its images are rebuilt as upstream releases land, so freshness becomes the image publisher’s job.
This dashboard It reads endoflife.date by product or package identifier, and the publisher’s own policy where that has none: Firecracker, GitHub’s runner images, nodejs.org and go.dev. A support end known only as a floor is shown as one. A guest kernel is checked against the lines Firecracker validates, and pointed at the newest long-term one.

Vulnerabilities

Where advisories come from, and how a fix is chosen.

Who How
OSV, osv-scanner OSV aggregates advisory sources, and the scanner reads lockfiles, SBOMs and images.
Dependabot Alerts come from the GitHub Advisory Database, repository by repository.
Dependency-Track It matches SBOM components against several vulnerability feeds.
Grype, Trivy, Docker Scout They match the distribution packages inside an image against each distribution’s security data.
Snyk It matches against its own curated database.
VulnerableCode It aggregates advisories by purl, and names the next version no advisory affects.
This dashboard Advisories come from OSV for Go, npm and PyPI. A Fedora package is vulnerable when Bodhi pushed a security update after its image was built, which needs no image pull. The proposed fix is looked up in OSV too, as VulnerableCode does, so it has no advisory of its own. A package installed only as another’s dependency is missed.

Reachability

Whether a project’s code calls what an advisory names.

Who How
govulncheck It analyses calls down to the vulnerable function, for Go only.
osv-scanner Its call analysis for Go uses govulncheck’s analysis.
Endor Labs, Snyk They trace calls to vulnerable functions in several languages, as commercial services.
This dashboard It runs govulncheck over each Go project. An advisory nothing calls drops to warning, or to serious when it is exploited in the wild, and stays on the record. npm advisories have no reachability, so each counts as called.

License policy

How licenses are found and graded.

Who How
Dependency-Track A policy engine groups licenses and raises a violation per component.
Snyk, Sonatype Lifecycle, FOSSA License policies carry severities and waivers across an organisation.
deps.dev It serves the licenses a registry declares, as SPDX expressions.
ScanCode, ClearlyDefined ScanCode finds license text in a package’s files. ClearlyDefined serves those results with a score for how clearly a package is licensed.
ScanCode LicenseDB It sorts licenses into categories such as permissive, copyleft and proprietary, as static JSON.
DejaCode, ScanCode.io Usage policies attach to licenses and packages, and flag what a product must not ship.
This dashboard Declared licenses come from deps.dev, and from spec files for Fedora packages. Each SPDX expression is graded against deps-config.json alone, and only what a project ships counts. A license the policy does not name stays unknown, with its LicenseDB category as a hint. It scans no file itself: ClearlyDefined’s scans show what shipped packages’ files carry.

Supply chain signals

How a tool flags risk beyond a dependency’s version.

Who How
OpenSSF Scorecard Automated checks grade a repository’s maintenance and security practices.
deps.dev It serves Scorecard results, deprecation and provenance attestations per package version.
Socket Static analysis of package code flags install scripts, network access, obfuscation and typosquats. Its API needs an account.
zizmor It audits GitHub Actions workflows, unpinned third-party actions included.
This dashboard Only what public sources already say: deprecation, lockfile install scripts, release age, OpenSSF Scorecard results, provenance and third-party actions pinned by tag. Package code is not analysed, which is the part of Socket’s signal that needs its service.

Internal lag

How far a pin on a sibling project trails it.

Who How
Renovate Digest updates move commit pins and Go pseudo-versions forward, one pull request at a time.
Go’s moddeps test The test fails when a vendored module trails its newest version.
This dashboard It counts the commits the sibling’s default branch has made since the pin, up to the last one the sibling built and passed: under an action’s own directory for an action, and newer tier builds for an image. A project’s card shows its pins on siblings and who pins it.

Grouping and ordering work

How findings become work, and in what order.

Who How
Renovate Group presets move packages that release together, such as a monorepo’s, in one pull request.
Dependabot Grouped updates batch by pattern or update type, and alerts sort by severity.
Snyk A priority score weighs severity, exploit maturity and reachability.
Endor Labs A funnel narrows findings to those that are reachable and fixable.
VulnerableCode A risk score multiplies weighted severity by exploitability. Exploitability rises for a CVE in CISA’s catalog of known exploited vulnerabilities, or with a high FIRST EPSS score.
This dashboard Dependencies from one upstream repository share a card, and one change across projects is one card. Tiers say when to act. Within a tier, work is ordered by level, then exploitation, EPSS and gap age. A listing in CISA’s KEV catalog makes an advisory critical, and EPSS orders work without changing a level.

Gap age and fix-by dates

How long a gap has been open, and when it is due.

Who How
Dependency-Track A finding records when it was first attributed to a component.
Snyk, Sonatype Lifecycle Reports measure open issues against remediation targets.
GitHub security campaigns A campaign gives a set of alerts a due date.
This dashboard Each gap is dated from its public start: the advisory, the end of life or the release. Fix-by dates exist only when deps-config.json sets a policy.

Accepted exceptions

How a finding is left be on purpose.

Who How
Dependabot A dismissed alert records one of five reasons.
osv-scanner Its configuration ignores an advisory with a reason and an ignoreUntil date.
Trivy .trivyignore accepts an expiry date per entry.
Snyk A .snyk policy file ignores an issue until a date.
Dependency-Track Analysis states and VEX justifications record why a finding does not apply. VEX, the Vulnerability Exploitability eXchange, is a standard way to say so.
DejaCode A vulnerability analysis per product records its state and justification in VEX terms.
This dashboard An entry in deps-config.json names the finding, one of Dependabot’s reasons and a date it lapses. The SBOM carries it as a VEX analysis.

Alerting

How people hear about new work.

Who How
Dependabot Alerts arrive as GitHub notifications.
Dependency-Track Notifications go out by webhook, email or chat integration.
Anitya New upstream releases are published as messages on Fedora’s message bus.
This dashboard deps-feed.xml is an Atom feed with one entry per action to fix now. It needs no secret in the build and no account for the reader, where email and chat would need both.

Sharing findings with other tools

How findings reach other tools.

Who How
Dependency-Track It imports CycloneDX SBOMs and VEX, and exports both.
ScanCode.io Its load_sbom pipeline imports CycloneDX and SPDX documents.
osv-scanner It scans an SBOM’s purls against OSV.
GitHub The dependency graph exports a repository’s SBOM as SPDX.
This dashboard deps.cdx.json is the inventory as a CycloneDX SBOM, with a purl on each record and a VEX analysis on each advisory where one is known. deps-actions.json gives agents the page’s actions.

Presentation

How the work is shown.

Who How
Renovate A Dependency Dashboard issue per repository lists pending updates as checkboxes.
Dependency-Track Portfolio views chart risk across projects over time.
Snyk, Socket Hosted dashboards list findings by organisation and project.
This dashboard A static page reads one same-origin file. It opens on the next action, puts urgency in three tiers, and keeps reference detail closed until it is opened.

What a page may assume