---
title: "Read index version records"
description: "Interpret version states, SBOMs and install conflicts."
canonical_url: "https://docs.oz0.ai/build/plugins/indexes/version-records"
---
# Read index version records

> Interpret version states, SBOMs and install conflicts.

For: tenant administrators and plugin authors.

Interpret version states, SBOMs and install conflicts.

## Version states

Every installed plugin version, and every listed one, has three states, each a fact the platform checked, and none implies another:

<table>
<thead>
  <tr>
    <th>
      State
    </th>
    
    <th>
      It means
    </th>
    
    <th>
      Set by
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Saved
    </td>
    
    <td>
      The platform holds the version's bytes
    </td>
    
    <td>
      A Git commit installed, a workspace revision, an uploaded or pushed bundle
    </td>
  </tr>
  
  <tr>
    <td>
      Validated
    </td>
    
    <td>
      Its evals passed
    </td>
    
    <td>
      The install's <a href="https://docs.oz0.ai/improve/evals">
        quality gate
      </a>
      
       passing for that version, or a <code>
        plugin test
      </code>
      
       report of exactly the listed files that the index carries
    </td>
  </tr>
  
  <tr>
    <td>
      Published
    </td>
    
    <td>
      An index the cluster reads lists it, active or deprecated
    </td>
    
    <td>
      The index
    </td>
  </tr>
</tbody>
</table>

`plugin list` shows the furthest in its `STATE` column and the rest beside it ("published in acme, not validated"); the Plugins page, an agent's capability card and the hub do the same. A published version without evals is published and not validated, and every screen says so. "Validated" says only that the evals passed, with which engine and on which day; it says nothing about the plugin being safe or fit for a purpose.

## SBOMs

Each plugin version has a software bill of materials: a CycloneDX 1.6 JSON file of the packages it installs, for your vulnerability scanner.

<table>
<thead>
  <tr>
    <th>
      Where
    </th>
    
    <th>
      What it lists
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        plugin pack
      </code>
      
       writes <code>
        sbom.cdx.json
      </code>
      
       into the folder and the bundle
    </td>
    
    <td>
      The packages of the plugin's <code>
        uv.lock
      </code>
      
       and <code>
        package-lock.json
      </code>
      
      , each with its version, package URL and hashes
    </td>
  </tr>
  
  <tr>
    <td>
      A hub listing (<code>
        generated.sbom
      </code>
      
      )
    </td>
    
    <td>
      The same SBOM's SHA-256, how many packages it lists and their package URLs; whether the bundle carries the same file, or one that is out of date
    </td>
  </tr>
  
  <tr>
    <td>
      An installed version: <code>
        oz0 plugin sbom &lt;name> -o team.cdx.json
      </code>
      
      , the Plugins page
    </td>
    
    <td>
      Those packages, plus every package the edge <a href="https://docs.oz0.ai/build/plugins/packages#pinning-and-hashes">
        pinned by hash
      </a>
      
       when it installed the version, with the hashes of each file a node may install, and its tools' container images by digest
    </td>
  </tr>
  
  <tr>
    <td>
      An <a href="https://docs.oz0.ai/govern/audit-trail/evidence-bundles#evidence-bundles">
        evidence bundle
      </a>
    </td>
    
    <td>
      The installed SBOM of each plugin version the period used, next to its factsheet
    </td>
  </tr>
</tbody>
</table>

The file is the same for the same version, wherever it is made: components sorted, no scan time, a serial number made from the content. Its `metadata.component` is the plugin version, bound to the SHA-256 of its other files, so an SBOM cannot be passed off as another version's. Commit `sbom.cdx.json` with the lockfiles it comes from; `plugin inspect` says when the bundled one no longer matches them. An SBOM lists what the lockfiles pin; the [vulnerability scan](https://docs.oz0.ai/build/plugins/vulnerabilities) compares an installed version's with known advisories.

## Plugins that cannot be installed together

A tool ID belongs to one plugin of a tenant (see [the catalog](https://docs.oz0.ai/build/plugins/catalog)), and so do an agent or flow name and a plugin's own name. An index lists, for each version, the other plugins it lists that share one of them: `CLASHES` in `index plugins`, `clashes` in `--json`, and "Cannot be installed together with" on the hub's plugin pages. A hub install warns with them before it fetches anything, and says which of them the tenant has:

```text [Output]
warning: hub:com.example/team: index acme lists com.example/team 0.1.0 as not installable in one tenant with
io.github.bob/team-tools 1.0.0, 1.1.0 (tool team): a tool ID, an agent or flow name and a plugin name each belong to
one plugin of a tenant; tenant default has io.github.bob/team-tools 1.1.0 installed, so the install is refused unless
that clash is one the installed version of team already had: remove plugin team-tools first (oz0 plugin remove team-tools)
```

The warning is the index's view of the listed versions. The install still checks the bytes it installs against what the tenant has, and refuses a taken tool ID, agent or flow name whatever the index says. Two listings of the same plugin name by different publishers clash too. A hub install never replaces a plugin the tenant installed from another listing: it is refused before anything is fetched (`plugin preview` shows the refusal as a warning), and you remove the installed plugin first if you mean to swap them.

A plugin you installed from a Git URL, a path or an upload is replaced by a hub listing of the same name, with the warning.


## Sitemap

See the full [sitemap](https://docs.oz0.ai/sitemap.md) for all pages.
