Skip to main content

Python client library for the Transparency Exchange API (TEA)

Project description

libtea

CI PyPI version Python License

Python client library for the Transparency Exchange API (TEA) v0.3.0-beta.2.

TEA is an open standard for discovering and retrieving software transparency artifacts (SBOMs, VEX, build metadata) for any software product or component. A TEI identifier resolves via DNS to the right endpoint, similar to how email uses MX records — so consumers can fetch artifacts without knowing which server hosts them.

Specification: Ecma TC54-TG1 | OpenAPI spec

Status: Alpha — API is subject to change.

Features

  • Auto-discovery via .well-known/tea and TEI URNs
  • Products, components, releases, and versioned collections
  • Search by PURL, CPE, or TEI identifier
  • Common Lifecycle Enumeration (CLE) — ECMA-428 lifecycle events
  • Artifact download with on-the-fly checksum verification (MD5 through BLAKE2b)
  • Endpoint failover with SemVer-compatible version selection
  • Bearer token and HTTP basic auth authentication
  • Bearer token isolation — tokens are never sent to artifact download hosts
  • Typed Pydantic v2 models with full camelCase/snake_case conversion
  • Structured exception hierarchy with error context
  • CLI with rich-formatted output and JSON mode

Installation

pip install libtea

To include the CLI (tea-cli):

pip install libtea[cli]

Quick start

from libtea import TeaClient

# Auto-discover the sbomify TEA server from its .well-known/tea
with TeaClient.from_well_known("trust.sbomify.com", token="your-bearer-token") as client:
    # Discover a product by TEI
    results = client.discover(
        "urn:tei:purl:trust.sbomify.com:pkg:github/sbomify/sbomify"
    )
    for info in results:
        print(info.product_release_uuid, info.servers)

    # Get a product release
    pr = client.get_product_release(results[0].product_release_uuid)
    print(pr.version, pr.product_name)

Or connect directly to a known endpoint:

client = TeaClient(
    base_url="https://trust.sbomify.com/tea/v0.3.0-beta.2",
    token="your-bearer-token",
    timeout=30.0,
)

Using from_well_known, you can also override the spec version and timeout:

client = TeaClient.from_well_known(
    "trust.sbomify.com",
    token="your-bearer-token",
    timeout=15.0,
    version="0.3.0-beta.2",  # default
)

Usage

Discovery

from libtea import TeaClient

# Discover sbomify products via TEI
with TeaClient.from_well_known("trust.sbomify.com") as client:
    results = client.discover(
        "urn:tei:purl:trust.sbomify.com:pkg:github/sbomify/sbomify"
    )
    for info in results:
        print(info.product_release_uuid, info.servers)

Low-level discovery functions are also available:

from libtea.discovery import parse_tei, fetch_well_known, select_endpoint

# Parse a TEI URN
tei_type, domain, identifier = parse_tei(
    "urn:tei:purl:trust.sbomify.com:pkg:github/sbomify/sbomify"
)

# Fetch and select an endpoint manually
well_known = fetch_well_known("trust.sbomify.com")
endpoint = select_endpoint(well_known, "0.3.0-beta.2")
print(endpoint.url, endpoint.priority)

Supported TEI types: uuid, purl, hash, swid, eanupc, gtin, asin, udi.

Search

with TeaClient.from_well_known("trust.sbomify.com") as client:
    # Search by PURL
    results = client.search_products("PURL", "pkg:github/sbomify/sbomify")
    for product in results.results:
        print(product.name, product.uuid)

    # Search product releases (with pagination)
    releases = client.search_product_releases(
        "PURL", "pkg:github/sbomify/sbomify",
        page_offset=0, page_size=100,
    )
    print(releases.total_results)

Products and releases

with TeaClient.from_well_known("trust.sbomify.com") as client:
    product = client.get_product("product-uuid")
    print(product.name, product.identifiers)

    releases = client.get_product_releases("product-uuid", page_size=25)
    for release in releases.results:
        print(release.version, release.created_date)

    # Single product release
    pr = client.get_product_release("release-uuid")
    print(pr.version, pr.components)

    # Product release collections
    latest = client.get_product_release_collection_latest("release-uuid")
    all_versions = client.get_product_release_collections("release-uuid")
    specific = client.get_product_release_collection("release-uuid", 3)

Components

with TeaClient.from_well_known("trust.sbomify.com") as client:
    component = client.get_component("component-uuid")
    releases = client.get_component_releases("component-uuid")

    # Get a component release with its latest collection
    cr = client.get_component_release("release-uuid")
    print(cr.release.version, len(cr.latest_collection.artifacts))

Collections and artifacts

with TeaClient.from_well_known("trust.sbomify.com") as client:
    collection = client.get_component_release_collection_latest("release-uuid")
    for artifact in collection.artifacts:
        print(artifact.name, artifact.type)

    # All collection versions for a component release
    all_versions = client.get_component_release_collections("release-uuid")

    # Specific collection version
    collection_v3 = client.get_component_release_collection("release-uuid", 3)

Downloading artifacts with checksum verification

from pathlib import Path

with TeaClient.from_well_known("trust.sbomify.com") as client:
    artifact = client.get_artifact("artifact-uuid")
    fmt = artifact.formats[0]

    # Downloads and verifies checksums on-the-fly; returns the dest path
    path = client.download_artifact(
        fmt.url,
        Path("sbom.json"),
        verify_checksums=fmt.checksums,
    )

Supported checksum algorithms: MD5, SHA-1, SHA-256, SHA-384, SHA-512, SHA3-256, SHA3-384, SHA3-512, BLAKE2b-256, BLAKE2b-384, BLAKE2b-512. BLAKE3 is recognized in the model but not verifiable (Python's hashlib has no BLAKE3 support — a clear error is raised).

Artifact downloads use a separate unauthenticated HTTP session so the bearer token is never leaked to third-party hosts (CDNs, Maven Central, etc.). On checksum mismatch, the downloaded file is automatically deleted.

Common Lifecycle Enumeration (CLE)

with TeaClient.from_well_known("trust.sbomify.com") as client:
    # Get lifecycle events for a product release
    cle = client.get_product_release_cle("release-uuid")
    for event in cle.events:
        print(event.type, event.effective)

    # CLE is available for all entity types
    client.get_product_cle("product-uuid")
    client.get_component_cle("component-uuid")
    client.get_component_release_cle("release-uuid")

Authentication

from libtea import TeaClient

# Bearer token
client = TeaClient.from_well_known("trust.sbomify.com", token="your-token")

# HTTP basic auth
client = TeaClient.from_well_known("trust.sbomify.com", basic_auth=("user", "password"))

CLI

The tea-cli command provides a terminal interface for all TEA operations. Install with pip install libtea[cli]. See the full CLI reference for detailed documentation.

Global options

--json       Output raw JSON instead of rich-formatted tables
--debug, -d  Show debug output (HTTP requests, timing)
--version    Show version

All commands accept connection options: --base-url, --domain, --token, --auth, --use-http, --port.

Discover

# Discover sbomify product releases via TEI
tea-cli discover "urn:tei:purl:trust.sbomify.com:pkg:github/sbomify/sbomify"

# UUIDs only (for scripting)
tea-cli discover -q "urn:tei:purl:trust.sbomify.com:pkg:github/sbomify/sbomify"

# JSON output
tea-cli --json discover "urn:tei:purl:trust.sbomify.com:pkg:github/sbomify/sbomify"

Inspect (full flow)

# TEI -> discovery -> releases -> components -> artifacts in one shot
tea-cli inspect "urn:tei:purl:trust.sbomify.com:pkg:github/sbomify/sbomify"

# Limit component resolution
tea-cli inspect --max-components 10 "urn:tei:purl:trust.sbomify.com:pkg:github/sbomify/sbomify"

Search

# Search products by PURL
tea-cli search-products --id-type PURL --id-value "pkg:github/sbomify/sbomify" \
    --domain trust.sbomify.com

# Search product releases
tea-cli search-releases --id-type PURL --id-value "pkg:github/sbomify/sbomify" \
    --domain trust.sbomify.com --page-size 50

Products and releases

# Get product details
tea-cli get-product <product-uuid> --domain trust.sbomify.com

# List releases for a product
tea-cli get-product-releases <product-uuid> --domain trust.sbomify.com

# Get a specific release (product or component)
tea-cli get-release <release-uuid> --domain trust.sbomify.com
tea-cli get-release <release-uuid> --component --domain trust.sbomify.com

Components

# Get component details
tea-cli get-component <component-uuid> --domain trust.sbomify.com

# List component releases
tea-cli get-component-releases <component-uuid> --domain trust.sbomify.com

Collections and artifacts

# Get latest collection (default) or specific version
tea-cli get-collection <release-uuid> --domain trust.sbomify.com
tea-cli get-collection <release-uuid> --version 3 --domain trust.sbomify.com

# List all collection versions
tea-cli list-collections <release-uuid> --domain trust.sbomify.com

# Get artifact metadata
tea-cli get-artifact <artifact-uuid> --domain trust.sbomify.com

Download

# Download an artifact with checksum verification
tea-cli download "https://cdn.example.com/sbom.json" ./sbom.json \
    --checksum "SHA-256:abc123..." \
    --domain trust.sbomify.com

Lifecycle (CLE)

# Get lifecycle events for different entity types
tea-cli get-cle <uuid> --entity product-release --domain trust.sbomify.com
tea-cli get-cle <uuid> --entity product --domain trust.sbomify.com
tea-cli get-cle <uuid> --entity component --domain trust.sbomify.com
tea-cli get-cle <uuid> --entity component-release --domain trust.sbomify.com

Environment variables

Variable Description
TEA_BASE_URL TEA server base URL (alternative to --base-url)
TEA_TOKEN Bearer token (alternative to --token)
TEA_AUTH Basic auth as USER:PASSWORD (alternative to --auth)

Shell completion

# Bash (add to ~/.bashrc)
eval "$(_TEA_CLI_COMPLETE=bash_source tea-cli)"

# Zsh (add to ~/.zshrc)
eval "$(_TEA_CLI_COMPLETE=zsh_source tea-cli)"

# Fish (add to ~/.config/fish/completions/tea-cli.fish)
_TEA_CLI_COMPLETE=fish_source tea-cli | source

Error handling

All exceptions inherit from TeaError:

from libtea.exceptions import TeaError, TeaNotFoundError, TeaChecksumError

try:
    product = client.get_product("unknown-uuid")
except TeaNotFoundError as exc:
    print(exc.error_type)  # "OBJECT_UNKNOWN" or "OBJECT_NOT_SHAREABLE"
except TeaError:
    print("Something went wrong")

Exception hierarchy:

Exception When
TeaConnectionError Network failure or timeout
TeaAuthenticationError HTTP 401/403
TeaNotFoundError HTTP 404 (.error_type has the TEA error code)
TeaRequestError Other HTTP 4xx
TeaServerError HTTP 5xx
TeaDiscoveryError Invalid TEI, .well-known failure, or no compatible endpoint
TeaChecksumError Checksum mismatch (.algorithm, .expected, .actual)
TeaValidationError Malformed server response
TeaInsecureTransportWarning Warning emitted when using plaintext HTTP

Using a bearer token over plaintext HTTP raises ValueError immediately — HTTPS is required for authenticated requests.

Requirements

  • Python >= 3.11
  • requests >= 2.32.4 for HTTP
  • Pydantic >= 2.1.0 for data models
  • semver >= 3.0.4 for version selection

Optional (for CLI): click >= 8.0, rich >= 13.0.0

Not yet supported

  • Publisher API (spec is consumer-only in beta.2)
  • Async client (httpx migration)

Development

This project uses uv for dependency management.

uv sync                        # Install dependencies
uv run pytest                  # Run tests (with coverage)
uv run ruff check .            # Lint
uv run ruff format --check .   # Format check
uv build                       # Build wheel and sdist

License

Apache 2.0 — see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

libtea-0.2.0.tar.gz (149.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

libtea-0.2.0-py3-none-any.whl (43.6 kB view details)

Uploaded Python 3

File details

Details for the file libtea-0.2.0.tar.gz.

File metadata

  • Download URL: libtea-0.2.0.tar.gz
  • Upload date:
  • Size: 149.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for libtea-0.2.0.tar.gz
Algorithm Hash digest
SHA256 2d9430eef5d89b30c702bda4e1a672f227141a33074f0abd5ffbbf4dd3a303fc
MD5 63a0058132eda3ebd6c98caee98e666a
BLAKE2b-256 554b3534e68bd654fb425b1d4a07145197a1dfe933682bc95cb4fb908b837083

See more details on using hashes here.

Provenance

The following attestation bundles were made for libtea-0.2.0.tar.gz:

Publisher: pypi.yaml on sbomify/py-libtea

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file libtea-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: libtea-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 43.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for libtea-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f6e7403094711f06bf84b94c0f041a66c3d2df2528b74d536c98a6f6e7b81fb2
MD5 76b38f35219281ac04eb5fd426e92082
BLAKE2b-256 f93e6bb648c1a137c18ce32f801f079e8c4d0c4446c2a9a638eed7d71fdf1f37

See more details on using hashes here.

Provenance

The following attestation bundles were made for libtea-0.2.0-py3-none-any.whl:

Publisher: pypi.yaml on sbomify/py-libtea

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page