Documentation
¶
Overview ¶
Package tea is a client for the OWASP Transparency Exchange API.
It speaks both halves of the same API: the consumption operations any conformant server serves, and the publication operations that create the objects those consumers read. That is deliberate — they are one API at one root, and a client that treated them as two would have to be told twice which server it is talking to.
The default server is Vulnetix, but nothing here assumes it. A --server pointing at another organisation's TEA endpoint works for every read; writes will simply be refused by a server that does not know the caller, which is the correct outcome rather than something to guard against locally.
Index ¶
- Constants
- func ArtifactTypeForFile(path string) string
- func ContentDigest(body []byte) string
- func MediaTypeForFile(path string) string
- func NormaliseDomain(in string) (string, error)
- func RootFrom(doc *WellKnown) string
- type AccessPolicy
- type AccessStatus
- type Artifact
- type Checksum
- type Client
- func (c *Client) AccessPolicy(ctx context.Context, uuid string) (*AccessStatus, error)
- func (c *Client) AttachSignature(ctx context.Context, artifactUUID string, formatIndex int, sig map[string]any) error
- func (c *Client) CreateArtifact(ctx context.Context, collectionUUID, name, artifactType string, ...) (*Artifact, error)
- func (c *Client) CreateProduct(ctx context.Context, name string, identifiers []Identifier, ...) (*Product, error)
- func (c *Client) CreateProductRelease(ctx context.Context, productUUID, version, releaseDate string, preRelease bool, ...) (*Release, error)
- func (c *Client) DeleteProduct(ctx context.Context, uuid string) error
- func (c *Client) Do(ctx context.Context, method, path string, body any, out any, ...) error
- func (c *Client) LatestCollection(ctx context.Context, releaseUUID string) (*Collection, error)
- func (c *Client) Product(ctx context.Context, uuid string) (*Product, error)
- func (c *Client) ProductReleases(ctx context.Context, uuid string) (*Page[Release], error)
- func (c *Client) Products(ctx context.Context, pageSize int, pageToken string) (*Page[Product], error)
- func (c *Client) Publications(ctx context.Context) ([]map[string]any, error)
- func (c *Client) PublishCollection(ctx context.Context, releaseUUID string, reason UpdateReason) (*Collection, error)
- func (c *Client) ResolveTEI(ctx context.Context, tei string) (map[string]any, error)
- func (c *Client) SetAccessPolicy(ctx context.Context, uuid string, policy AccessPolicy) (*AccessStatus, error)
- func (c *Client) UploadArtifactFile(ctx context.Context, artifactUUID string, formatIndex int, ...) (map[string]any, error)
- type Collection
- type Error
- type Format
- type Identifier
- type Page
- type Product
- type Release
- type ShareGrant
- type UpdateReason
- type WellKnown
Constants ¶
const DefaultServer = "https://www.vulnetix.com/tea/v1"
DefaultServer is Vulnetix's own TEA root. It is the `rootUrl` advertised in https://vulnetix.com/.well-known/tea.
Variables ¶
This section is empty.
Functions ¶
func ArtifactTypeForFile ¶
ArtifactTypeForFile maps a document to the TEA artifact type enum.
Defaults to OTHER rather than BOM: claiming a file is a bill of materials when it might not be tells a consumer to parse it as one.
func ContentDigest ¶
ContentDigest renders the RFC 9530 header for a body.
The server verifies this before storing anything, which is what makes an upload safe to retry: a truncated transfer fails loudly instead of being published under a checksum asserting it arrived intact.
func MediaTypeForFile ¶
MediaTypeForFile guesses the media type of a transparency document from its name.
Only the formats TEA actually carries are recognised. Anything else becomes application/octet-stream rather than a guess: an artifact served under the wrong media type is one a consumer's parser will reject, and being wrong is worse than being unspecific.
func NormaliseDomain ¶
NormaliseDomain reduces what a person pastes — a bare domain, a URL, or a TEI — to the domain-name component discovery starts from.
func RootFrom ¶
RootFrom picks the endpoint and version to use from a discovery document.
Highest priority wins, and among an endpoint's versions the newest STABLE one is chosen. Plain SemVer ordering would rank 1.1.0-beta.1 above 1.0.0, and pointing a user's tooling at a provider's beta API is not a decision to make on their behalf.
Types ¶
type AccessPolicy ¶
type AccessPolicy struct {
ObjectKind string `json:"objectKind,omitempty"`
ObjectUUID string `json:"objectUuid,omitempty"`
Visibility string `json:"visibility"`
}
AccessPolicy is who may read an object.
type AccessStatus ¶
type AccessStatus struct {
UUID string `json:"uuid"`
Declared *AccessPolicy `json:"declared,omitempty"`
Effective AccessPolicy `json:"effective"`
InheritedFrom string `json:"inheritedFrom,omitempty"`
}
AccessStatus reports what an object declares against what is enforced.
type Artifact ¶
type Artifact struct {
UUID string `json:"uuid"`
Version int `json:"version,omitempty"`
Name string `json:"name"`
Type string `json:"type,omitempty"`
CreatedDate string `json:"createdDate,omitempty"`
Formats []Format `json:"formats,omitempty"`
}
Artifact is one published document.
type Client ¶
type Client struct {
BaseURL string
Creds *auth.Credentials
HTTP *http.Client
}
Client talks to one TEA server.
func New ¶
func New(baseURL string, creds *auth.Credentials) *Client
New builds a client. Credentials may be nil: the consumption operations of a public catalogue need none, and requiring them would make the CLI useless for reading somebody else's open transparency log.
func (*Client) AccessPolicy ¶
AccessPolicy reads the policy in force for an object.
func (*Client) AttachSignature ¶
func (c *Client) AttachSignature(ctx context.Context, artifactUUID string, formatIndex int, sig map[string]any) error
AttachSignature records a detached signature and, crucially, the scheme it was produced with. The consumption API exposes only a URL, so a consumer without the scheme has to guess how to verify — which in practice means not verifying.
func (*Client) CreateArtifact ¶
func (c *Client) CreateArtifact(ctx context.Context, collectionUUID, name, artifactType string, formats []Format, idempotencyKey string) (*Artifact, error)
CreateArtifact registers an artifact within a collection. It does not carry the bytes: those go up per format afterwards, so correcting a metadata field does not mean resending a multi-megabyte document.
func (*Client) CreateProduct ¶
func (c *Client) CreateProduct(ctx context.Context, name string, identifiers []Identifier, idempotencyKey string) (*Product, error)
CreateProduct registers a product. The server assigns the UUID and the TEI — a TEI names the server's authority over the object, which a publisher cannot assert on its behalf.
func (*Client) CreateProductRelease ¶
func (c *Client) CreateProductRelease(ctx context.Context, productUUID, version, releaseDate string, preRelease bool, idempotencyKey string) (*Release, error)
CreateProductRelease publishes a release of a product.
func (*Client) DeleteProduct ¶
DeleteProduct removes a product and everything beneath it.
func (*Client) Do ¶
func (c *Client) Do(ctx context.Context, method, path string, body any, out any, headers map[string]string) error
Do performs one request and decodes the result into out.
headers are applied last so a caller can set Idempotency-Key and Content-Digest, which are the two the publication API acts on and which a generic client would otherwise have no way to send.
func (*Client) LatestCollection ¶
LatestCollection reads the current collection for a product release.
func (*Client) ProductReleases ¶
ProductReleases lists a product's releases.
func (*Client) Products ¶
func (c *Client) Products(ctx context.Context, pageSize int, pageToken string) (*Page[Product], error)
Products lists products.
func (*Client) Publications ¶
Publications lists what this organisation has published, with the visibility of each — the half a publisher cannot see through the consumption API, because that API will not show anyone anything private.
func (*Client) PublishCollection ¶
func (c *Client) PublishCollection(ctx context.Context, releaseUUID string, reason UpdateReason) (*Collection, error)
PublishCollection publishes the next version of a release's collection.
func (*Client) ResolveTEI ¶
ResolveTEI asks the server to resolve an identifier to the object it names.
func (*Client) SetAccessPolicy ¶
func (c *Client) SetAccessPolicy(ctx context.Context, uuid string, policy AccessPolicy) (*AccessStatus, error)
SetAccessPolicy replaces an object's own policy.
Going public requires the server's confirmation parameter. That is not ceremony: no later request undoes it, because whatever was fetched while an object was public stays fetched.
type Collection ¶
type Collection struct {
UUID string `json:"uuid"`
Version int `json:"version"`
Date string `json:"date,omitempty"`
BelongsTo string `json:"belongsTo,omitempty"`
UpdateReason *UpdateReason `json:"updateReason,omitempty"`
Artifacts []Artifact `json:"artifacts,omitempty"`
}
Collection is a versioned set of artifacts for one release.
type Error ¶
type Error struct {
Status int `json:"-"`
Code string `json:"error"`
Message string `json:"message,omitempty"`
Field string `json:"field,omitempty"`
}
Error is a TEA error response, in either the consumption or publication envelope. Both carry a machine-readable code; only the publication one carries a message and field.
func (*Error) IsNotFound ¶
IsNotFound reports whether the server said the object does not exist, under either envelope's spelling.
type Format ¶
type Format struct {
MediaType string `json:"mediaType"`
Description string `json:"description,omitempty"`
URL string `json:"url,omitempty"`
SignatureURL string `json:"signatureUrl,omitempty"`
Checksums []Checksum `json:"checksums,omitempty"`
}
Format is one representation of an artifact.
type Identifier ¶
Identifier is a TEA identifier: a type and its value.
type Page ¶
type Page[T any] struct { Results []T `json:"results"` HasNext bool `json:"hasNext"` NextPageToken string `json:"nextPageToken"` }
Page is the consumption API's pagination envelope.
type Product ¶
type Product struct {
UUID string `json:"uuid"`
Name string `json:"name"`
Identifiers []Identifier `json:"identifiers,omitempty"`
}
Product is a lineage of releases.
type Release ¶
type Release struct {
UUID string `json:"uuid"`
Product string `json:"product,omitempty"`
ProductName string `json:"productName,omitempty"`
Component string `json:"component,omitempty"`
ComponentName string `json:"componentName,omitempty"`
Version string `json:"version"`
CreatedDate string `json:"createdDate,omitempty"`
ReleaseDate string `json:"releaseDate,omitempty"`
PreRelease bool `json:"preRelease,omitempty"`
Identifiers []Identifier `json:"identifiers,omitempty"`
}
Release covers both flavours. The consumption API distinguishes a product release from a component release; the fields that differ are the parent and its name, so one struct carries both rather than duplicating the rest.
type ShareGrant ¶
type ShareGrant struct {
}
ShareGrant entitles one organisation to read one object.
type UpdateReason ¶
UpdateReason says why a collection changed. Required on publication: a collection whose contents change without saying why is indistinguishable, to a consumer, from one that was tampered with.
type WellKnown ¶
type WellKnown struct {
SchemaVersion int `json:"schemaVersion"`
Endpoints []struct {
URL string `json:"url"`
Versions []string `json:"versions"`
Priority *float64 `json:"priority,omitempty"`
} `json:"endpoints"`
}
WellKnown is the discovery document at /.well-known/tea.
func Discover ¶
Discover resolves a domain to a TEA root, following the specification: query DNS for the domain, fetch /.well-known/tea over HTTPS, then pick an endpoint and append its version.
The domain may be given as a bare name, a URL, or a TEI — those are the three forms a person actually has to hand, and requiring them to convert between them would be busywork.