Output
Turning Your Graph into Actionable Artifacts
Output files, located in data/output/, are the final step in the processing pipeline. They
query the fully constructed, compliance-enriched graph and generate new, structured data
resources. This is ideal for creating artifacts like Terraform variable files, Kubernetes
manifests, compliance summaries, service catalogs, or inputs for other automation systems.
Similar to models, an [[output]] rule iterates over each matching origin_resource and creates
one new resource per match. Unlike models, which enrich the graph with structural components,
outputs are designed to generate final, structured data artifacts from the fully built graph. This
can include downloadable files like reports or manifests.
Processing order: Output files are processed last, after Asset Loading, Model Application, and Compliance Application. This guarantees that every output template sees the fully governed, enriched graph. See The Processing Model for the complete pipeline diagram.
File Header & Rule Structure
| Key | Scope | Mandatory | Description |
|---|---|---|---|
origin_resource |
Top Level | Yes | The resource type to iterate over (e.g., application). |
(any name) |
Top Level | No | Custom data for use in templates, such as { "json!" = "path/to/file.json" }. |
[[output]] |
Top Level | Yes | An array of rules, each defining an aggregate output resource to generate. |
Each [[output]] block defines a rule for creating a single aggregate resource.
| Key | Scope | Mandatory | Description |
|---|---|---|---|
resource_type |
[[output]] |
Yes | The type for the new output resource created for each matching origin_resource. |
name |
[[output]] |
Yes | A template for the primary key (name property) of the new output resource. It is rendered once for each matching origin_resource. |
match_on |
[[output]] |
No | An array of filter objects. The rule is applied only if the origin_resource matches all conditions. |
filename |
[[output]] |
No | A template for the filename when the output is downloaded via the API. If present along with mimetype, this enables a download endpoint for the resource. |
mimetype |
[[output]] |
No | The MIME type for the output content (e.g., application/json, text/csv). If present along with filename, this enables a download endpoint. |
template |
[[output]] |
Conditional | A multiline string template that renders a JSON object. This rendered JSON becomes the set of properties for the new output resource. It supports Tera for advanced object creation. Mutually exclusive with jsonnet. |
jsonnet |
[[output]] |
Conditional | A Jsonnet program string that evaluates to a JSON object, which becomes the set of properties for the new resource. This allows for complex logic, functions, and imports. Mutually exclusive with template. |
One of template or jsonnet is required.
Templating Engines
Tera Templates
Use the template key for straightforward JSON generation with string interpolation,
conditionals, and loops. All header variables, origin_resource, and any related graph nodes
are available. For a complete reference on Tera syntax and rescile’s custom filters, see
Tera Function & Filter Reference and
Templating & Data.
origin_resource = "application"
[[output]]
resource_type = "service_summary"
name = "summary-{{ origin_resource.name }}"
filename = "summary-{{ origin_resource.name }}.json"
mimetype = "application/json"
template = '''
{
"name": "{{ origin_resource.name }}",
"owner": "{{ origin_resource.owner }}",
"environment": "{{ origin_resource.environment }}",
"criticality": "{% if origin_resource.environment == 'prod' %}high{% else %}low{% endif %}"
}
'''
See Using Tera Templates for a full worked example including relationship traversal.
Jsonnet
Use the jsonnet key for complex JSON generation that requires local variables, functions,
conditionals, list comprehensions, or reusable imports. Data is injected as external
variables and accessed with std.extVar().
| External variable | How to access |
|---|---|
| The current resource | std.extVar("origin_resource") |
Any header variable foo |
std.extVar("foo") |
origin_resource = "server"
[[output]]
resource_type = "k8s_manifest"
name = "svc-{{ origin_resource.name }}"
filename = "svc-{{ origin_resource.name }}.json"
mimetype = "application/json"
jsonnet = """
local origin = std.extVar("origin_resource");
{
apiVersion: "v1",
kind: "Service",
metadata: { name: origin.name },
spec: {
ports: [{ port: p } for p in origin.ports]
}
}
"""
rescile supports sibling imports: .libsonnet files placed in the same directory as the
TOML file can be imported directly by filename. See Using Jsonnet for a full
example.
How Output Resources Are Created
Understanding the exact mechanics helps you predict what ends up in the graph and what is downloadable via the API.
- The engine finds all resources matching
origin_resource(andmatch_onif present). - For each match, the
nametemplate is rendered to produce the primary key of the new output resource. - The
templateorjsonnetprogram is evaluated. The result must be a valid JSON object. - A new resource of type
resource_typeis created. The keys of the JSON object become properties of this new resource. - If
filenameandmimetypeare both present, the resource gains a download endpoint automatically reachable via the REST API. - A
DESCRIBED_BYrelationship is created from the origin resource to the new output resource.
graph LR
App["application<br><b>billing-api</b>"] -- "DESCRIBED_BY" --> Out["service_summary<br><b>summary-billing-api</b><br>filename: summary-billing-api.json"]
Retrieving Artifacts via the REST API
Once the graph is built, every output resource that has filename and mimetype properties is
automatically available for download through the REST API.
List all outputs:
curl "http://localhost:7600/api/outputs/index"
Filter by origin type:
curl "http://localhost:7600/api/outputs/index?origin_type=application"
Download a specific artifact:
curl "http://localhost:7600/api/outputs/service_summary/summary-billing-api/summary-billing-api.json" \
-o summary-billing-api.json
The index endpoint returns a JSON array with download_url, type, name, filename,
mimetype, hash, and an origin object. For the full parameter reference, see
REST API Reference.
For usage in CI/CD pipelines, see Retrieving Outputs (REST API) in the End-User Guide.
Common Output Patterns
Terraform Variable Files
Generate .tfvars.json files by traversing related graph nodes and assembling the required
structure in a single output rule. The generated resource can then be queried via GraphQL or
downloaded directly.
origin_resource = "application"
[[output]]
resource_type = "terraform_variables"
name = "tfvars-{{ origin_resource.name }}"
filename = "tfvars-{{ origin_resource.name }}.json"
mimetype = "application/json"
match_on = [{ property = "environment", value = "prod" }]
template = """
{
"app_name": "{{ origin_resource.name }}",
"owner": "{{ origin_resource.owner }}",
"network": "{{ origin_resource.network[0].name }}",
"image": "{{ origin_resource.image[0].name }}"
}
"""
See Terraform Variable Generation for a complete walkthrough.
Kubernetes Manifests
Use Jsonnet’s list comprehensions to generate multi-resource Kubernetes manifests cleanly:
origin_resource = "server"
[[output]]
resource_type = "k8s_service"
name = "svc-{{ origin_resource.name }}"
filename = "svc-{{ origin_resource.name }}.yaml"
mimetype = "text/x-yaml"
jsonnet = """
local origin = std.extVar("origin_resource");
{
apiVersion: "v1",
kind: "Service",
metadata: { name: origin.name, labels: { app: origin.name } },
spec: {
selector: { app: origin.name },
ports: [{ port: p, targetPort: p } for p in origin.ports]
}
}
"""
Compliance and Audit Reports
The output engine integrates tightly with the compliance graph. After the compliance phase,
audit and control resources carry aggregated evidence_summary data that you can render
directly into Markdown or OSCAL documents.
# data/output/audit_markdown.toml
origin_resource = "audit"
[[output]]
resource_type = "compliance_report"
name = "report-{{ origin_resource.name }}"
filename = "{{ origin_resource.name }}-report.md"
mimetype = "text/markdown"
template = """
# Compliance Report: {{ origin_resource.audit_name }}
{% for ctrl in origin_resource.control %}
## {{ ctrl.name }} — {{ ctrl.control_name }}
{{ ctrl.description | default(value="") }}
**Evidence:** {{ ctrl.evidence_summary | default(value="{}") | json_encode | safe }}
{% endfor %}
"""
For the full OSCAL and Markdown examples, see Compliance Reports and Generating Audit Artifacts.
Service Catalogs and Summaries
Combine graph traversal with Tera to generate rich service catalog entries that pull data from related nodes:
origin_resource = "application"
[[output]]
resource_type = "catalog_entry"
name = "catalog-{{ origin_resource.name }}"
filename = "catalog-{{ origin_resource.name }}.json"
mimetype = "application/json"
match_on = [{ property = "network_zone", value = "edge" }]
template = '''
{
"application": "{{ origin_resource.name }}",
"owner": "{{ origin_resource.owner }}",
"databases": {{ origin_resource.database | map(attribute="name") | json_encode | safe }},
"criticality": "{% if origin_resource.environment == 'prod' %}high{% else %}low{% endif %}"
}
'''
Further Reading
| Topic | Link |
|---|---|
| Tera template syntax and rescile custom filters | Tera Function & Filter Reference |
| Templating & Data context (variables, global vs. iteration) | Templating & Data |
Full [[output]] directive reference |
Directive Reference |
| Worked example: Tera service summary | Using Tera Templates |
| Worked example: Jsonnet Kubernetes manifests | Using Jsonnet |
| Worked example: Terraform variable generation | Terraform Variable Generation |
| Compliance and OSCAL reports | Compliance Reports / Generating Audit Artifacts |
| REST API for downloading artifacts | REST API Reference |
| Retrieving outputs in CI/CD | Retrieving Outputs (REST API) |