Extra Object
Objects named extra are the only supported extension points in CTRF.
They allow producers to include tool-specific or domain-specific metadata
without adding unknown properties to the core format.
Unknown properties outside an extra object are invalid. Consumers must ignore
extensions they do not recognize and must not reject a report solely because an
extra object contains them.
Where extra Can Appear
| Location | Example use |
|---|---|
| Root | Report-wide pipeline metadata |
| Results | Run or shard context |
| Tool | Reporter-specific configuration |
| Summary | Custom aggregate metrics |
| Test | Traceability or test-management data |
| Environment | Custom execution context |
| Attachment | Artifact metadata |
| Step | Step-specific context |
| Retry attempt | Attempt-specific data |
| Insights | Custom analysis metrics |
| Baseline | Custom comparison metadata |
Extension Keys
Each property inside extra is a distinct extension. Extension keys should:
- use a stable, recognizable namespace prefix that identifies the owner
- include a delimiter such as
.or/ - use the same namespace prefix consistently throughout the document
For example:
{
"extra": {
"myorg.ci": {
"buildId": "build-1234",
"trigger": "pull_request"
}
}
}
The complete key myorg.ci is an opaque identifier. Consumers must not treat
the delimiter as a path or infer a hierarchy from it.
The ctrf. and ctrf/ prefixes are reserved for CTRF-defined extensions.
Other producers must not use extension keys beginning with either prefix.
Extension Values
An extension value may be any valid JSON type. Related fields should normally be grouped in an object under one extension key, while an extension containing one value may use a scalar.
The producer defines the structure and meaning of its values. CTRF does not validate their internal shape, and consumers must treat unrecognized extension values as opaque.
Documenting Extensions
Extension producers should publish enough information for consumers that choose to support their metadata. Useful documentation includes:
- the extension key and its owner
- the CTRF object levels where it may appear
- the structure and meaning of its value
- any compatibility or versioning policy
A producer may publish a JSON Schema for an extension value when machine validation or generated types would be useful. That schema complements CTRF; it does not add the extension fields to the core CTRF schema.
Consistency Across a Document
A producer contributing metadata at several levels should use the same namespace prefix at each location. Different producers can then add metadata without colliding:
{
"reportFormat": "CTRF",
"specVersion": "0.1.0",
"extra": {
"myorg.ci": {
"pipelineId": "pipeline-1234"
}
},
"results": {
"tool": {
"name": "example-runner"
},
"summary": {
"tests": 1,
"passed": 1,
"failed": 0,
"skipped": 0,
"pending": 0,
"other": 0,
"start": 1700000000000,
"stop": 1700000005000,
"extra": {
"myorg.ci": {
"retryBudgetUsed": 0
}
}
},
"tests": [
{
"name": "checkout flow completes",
"status": "passed",
"duration": 5000,
"extra": {
"myorg.ci": {
"featureFlag": "new-checkout-ui"
},
"acme.test-management": {
"issueKey": "SHOP-1234",
"testCycle": "Sprint 42"
}
}
}
],
"extra": {
"myorg.ci": {
"environment": "staging"
}
}
}
}
Here, myorg.ci contributes CI metadata at several levels and
acme.test-management independently contributes test-management data.
Producer and Consumer Responsibilities
Producers:
- must place custom properties inside
extra - should namespace extension keys to avoid collisions
- should document the structure and semantics of extensions they publish
- should use a consistent namespace prefix throughout a document
Consumers:
- must ignore unrecognized extensions
- must treat unrecognized extension keys and values as opaque
- may validate or require an extension only when they explicitly support it
- must not require custom fields to appear outside
extra