Document Templating
Reference of the document templating mechanism in Ketryx
Ketryx can generate highly customizable documents based on user-managed templates in the form of Word or Excel files.
Getting started
To get started with custom templates in Ketryx:
Navigate to a project's Documents page
Create a folder called Templates
Create a folder called Release inside the Templates folder
Upload the sample file
sample-template.docxinto the Release folder
Create a few Requirement items and a new version, and navigate to the version's Documents page. The document sample-template.docx should show up as another release document that can be generated and approved.
For a demonstration of document templating, utilizing many of the concepts discussed on this page, see our Document Templating Introduction and Document Templating Deep Dive video guides.
Template locations
Templates are managed in dedicated folders in the Documents section:
Templates/System/[name].{docx,xlsx}with[name]being the name of a system document type, to override the built-in rendering of those documentsTemplates/Release/[name].{docx,xlsx}to add a custom release document with an arbitrary name to each (unreleased) versionTemplates/Milestones/[milestone]/[name].{docx,xlsx}to add a custom document with an arbitrary name to milestones that match the name[milestone]
The following system documents can be overwritten inside the Templates/System folder:
Authority MatrixChange Management FileChange Request Verification ReportCode Review ReportCyber Risk Management FileProblem ReportRelease HistoryRelease NotesRisk Control MatrixRisk Management FileRisk MatrixSystem Architecture ChartSystem Design SpecificationSystem Design Structure MatrixSystem Requirements SpecificationSBoM SOUP Software Configuration ReportTest PlanTesting ReportTraceability MatrixUnresolved Anomalies
Standard example templates
The templates at the bottom of this page are designed to closely resemble the out of the box release documents. There are also templates that utilize the Assistant SUMMARIZE feature to draft natural language summaries within the framework of the out of the box release documents.
If you would like to make small changes to the standard documents or just need a place to start, you can place these files in your project as specified in Template locations.
Template tags
A template can be a Word or Excel file with any user-defined content. Certain tags delimited by {...} are recognized by the Ketryx document generator and can be used to insert dynamic data from a Ketryx project into the document. The template syntax is inspired by the Mustache template language.
Data
{name}: insert template variablename{project.id}: insert the propertyidof an objectproject
Conditions and loops
{#condition}…{/}: insert the block within if the givenconditionis true{#items}…{/}: loop over a list ofitems, inserting the block within for each of them
Conditions and loops are expressed using the same template syntax. Whether data is looped over depends on whether it is a list.
In the block inside a loop, the properties of the item that is currently iterated over become available as template variables. Example (showing the id of each of the iterated items):
{#items}
{id}
{/}The item as a whole object is available using the special syntax . (a literal dot).
Loops can be used in tables (including Excel files) to create multiple rows, by putting the starting tag (e.g., {#items}) in the starting cell, and the ending tag {/} on another cell to right in the same row. Example:
ID
Title
Type
{#items}{id}
{title}
{typeName}{/}
The ending tag {/} is shorthand for repeating the full expression as in {#items} … {/items}.
If a variable is not set, a corresponding condition hides the contained block. This can be used to "comment out" a part of a document. Example (assuming there is no variable HIDDEN defined):
{#HIDDEN}
some text that will not be in the generated document
{/HIDDEN}Variable assignments
{$SET var = value}: set the variablevarto the givenvalue
Querying items
{$KQL items = query}: resolve the KQL queryqueryand assign the resulting list of items to the template variableitems{$KQL @version:version items = query}: resolve the KQL queryqueryfor the givenversion(specified by its Ketryx ID or by its full name){$KQL @version:(version1,version2) items = query}: resolve the KQL queryqueryfor several versions (concatenating the list of all records){@$KQL items = query}: resolve the KQL queryquerywithout leaving an empty line
Examples:
{$KQL reqs = type:Requirement}
{#reqs}
* {title}
{/}{@$KQL items = (RQ and diff:new) CR}
{#items}
* {title}
{/}{@$KQL @version:("Version 1.0","Version 2.0") items = RQ}
{#items}
* {title}
{/}Each item in the resulting list has the data type ItemRecordFull.
Traceability matrices
{$TRACE rtm}: stores data from the project's requirements traceability matrix in the template variablertm{$TRACE @version:version rtm}: compute traceability for the given version (specified by its Ketryx ID or by its full name){$TRACE rtm: extraConfigName}: uses the "extra" traceability configuration with the nameextraConfigName, as defined in the advanced project document setting Requirements Traceability Matrix (underextraConfigurations)
Example:
{$TRACE rtm}Req ID
Spec ID
Test Title
{#rtm.rows}{columns.req.itemRecord.docId}
{columns.spec.itemRecord.docId}
{columns.test.testStatus.title}{/}
The resulting object has the type TraceabilityMatrix.
Expressions
Conditions (as in {#expr}) and some filters (such as where : expr) involve expressions. Expressions may involve constants (e.g., "John", 42) as well as access to template data and properties (e.g. project.id). They may contain the following operators:
ternaries:
a ? b : cequality/inequality:
a == b,a != brelational:
a > b,a < b,a >= b,a <= blogical AND:
a && blogical OR:
a || baddition:
a + bsubtraction:
a - bmultiplication:
a * bdivision:
a / b
Parenthesis can be used for grouping, to enforce a particular operator precedence.
Filters
Filters can be used to transform data before it is displayed or used in a condition or loop.
Filters are applied to values using the | operator, potentially followed by one or more arguments separated by :.
The following filters are available:
datetime
datetimevalue | datetime: renders the date/timevaluein the default formatvalue | datetime:"yyyy-MM-dd": uses the specified format, based on the given Unicode date format stringvalue | datetime:"yyyy-MM-dd":"US/Eastern": uses the specified format and timezone, based on the given tz timezone ID
where
whereitems | where:'...': filter the givenitemsbased on the given filter expression; the expression can refer to properties of each item
Example:
{#items | where:'typeName=="Requirement"'}
{id}
{/}sort
sortitems | sort:'...': sort the givenitemsbased on the key determined by the given expression
When using this to sort by a string, there is no numeric collation and file_100.docx would be sorted before file_11.docx. To sort using numeric collation use sortByNumericTextField.
Example (sorting items by their id):
{#items | sort:'id'}
{id}
{/}sortByNumericTextField
sortByNumericTextFielditems | sortByNumericTextField:'...': sort the givenitemsbased on the key determined by the given expression
When using this to sort by a string, numeric collation would sort file_11.docx before file_100.docx.
Example (sorting items by their id):
{#items | sortByNumericTextField:'id'}
{id}
{/}reverse
reverseitems | reverse: reverse the order of the givenitems
Example (sorting items by their id in reverse order):
{#items | sort:'id' | reverse}
{id}
{/}group
groupitems | group:'...': group the givenitemsbased on the key determined by the given expression; the resulting list will contain entries with propertiesgroupKey(the unique key of the group) andgroupItems(list of items within that group)
Example (grouping items by their Requirement type and showing the item IDs in each group separately):
{#items | group:"fieldValue.Requirement_type"}
{groupKey}
{#groupItems}
{id}
{/}
{/}at
atitems | at:N: returns the item at indexNin the given list of items; the index is 0-based, so0denotes the first item; negative indices count from the end, so-1denotes the last itemobject | at:"...": returns the value for the given key in an object such as anItemRecord'sfieldValueobject; this could also be done using "dot" access (object.property), but thisatfilter can be useful for computed property names or names that contain spaces or other special characters
Example (accessing an object property for each vulnerability, equivalent to info.summary):
{#vulnerabilities}
{info | at:"summary"}
{/}Example (accessing a traceability column with a key containing a - dash):
{(columns | at:"system-requirements").itemRecord.docId}count
countitems | count: returns the number of items in a given list or properties in a given object
join
joinvalues | join: returns all the values in a list concatenated, using ", " as the separator between themvalues | join:"...": uses the given separator string between values in the list
Example (rendering list of items using a custom separator):
{#trainingStatus}
{groupNames | join:" - "}
{/}inMilestone
inMilestoneitem | inMilestone: determines whether an item is in the document's milestone
Example:
{#items | where:'. | inMilestone'}
{id}
{/}If the document is not generated for a particular milestone, inMilestone returns true.
inRegion
inRegionitem | inRegion: determines whether an item is in the document's region
Example:
{#items | where:'. | inRegion'}
{id}
{/}If the document is not generated for a particular region, inRegion returns true.
itemContent
itemContent{~~ item | itemContent}: display the givenitemusing the standard Ketryx rendering{~~ item | itemContent:"HEADINGS +2"}: shift the levels of headings in item content by 2 levels, to account for nested headings in the template itself while maintaining a sensible navigation hierarchy{~~ item | itemContent:"OMIT Context,Requirement type"}: omit the fieldsContextandRequirement typewhen rendering the item
Example:
{#items}
{~~ . | itemContent}
{/}createMap and getFromMap
createMap and getFromMapcreateMap creates a hash map and getFromMap allows getting items from that map.
createMap:<keyProperty>:<conflictResolutionMode> takes two parameters. The first parameter is a string that describes the property that will be used as the map key. The second property is either "first" or "last" and denotes whether the first or last item should be part of the map when duplicate keys are encountered.
getMap:<key> takes a single value as a parameter and returns the value associated with that key or null if there is no value associated with that key.
Example:
{$KQL rqs = RQ}
{$SET rqMap = rqs | createMap:”title”:”first”}
{#rqs}
{$SET rq1 = rqMap | getFromMap:title}
{rq1.title} | {rq1.obsoleteInVersion}
{/}Inserting other documents
{:include $DOC path}: include the EDMS document with the givenpath{:include $RELEASEDOC name}: include the release document with the givenname{:include $RELEASEDOC milestone / name}: include the milestone document with the givennamefrom the givenmilestone{:include $RELEASEDOC project -> name}: include a release document from a referenced project
Examples:
{:include $DOC Some folder/Subfolder/Document A}
{:include $RELEASEDOC Test Plan}
{:include $RELEASEDOC First milestone / Test Plan}
{:include $RELEASEDOC Other project -> Test Plan}Template variables are also available in the specified path with a $ prefix. However, arbitrary expressions are not supported, to avoid ambiguity with regards to where the expression would end. This can be circumvented by assigning an expression to another variable using $SET and using that in the included document path.
Included documents inherit the styling of the containing template document, including any named styles. For instance, paragraphs using the Normal style in the included document will be formatted according to the definition of the Normal style in the template.
Summarizing items
The $SUMMARIZE command allows summarizing an array of objects of the type ItemRecordFull into a textual summary using an LLM. This command is only available for projects that have Enable AI setting turned on in advanced settings.
{$SUMMARIZE mySummary = itemRecords:myItems}: summarize the item records saved in the variablemyItemsand store the result in the variablemySummary{$SUMMARIZE mySummary = itemRecords:myItems totalWordTarget:200}: summarize the item records saved in the variablemyItemswith a total target of 200 words{$SUMMARIZE mySummary = itemRecords:myItems wordTargetPerItem:20 instructions:"Some special instructions." systemPromptOverride:"Some special system prompt."}: summarize the item records saved in the variablemyItemswith a target of 20 words per item, special instructions, and a special system prompt
Example:
{@$KQL items = (RQ and diff:new) CR}
{@$SUMMARIZE summary = itemRecords:items totalWordTarget:500 instructions:"Summarize the given items into a release note summary. Do not use bullet points. Use paragraphs. End each paragraph with two newline characters. Add 2 lines between each paragraph."}
{~~ summary}Adding an @ symbol before the $KQL and $SUMMARIZE commands will prevent them from leaving an empty line. Without using the @ symbol, we would have to write all three commands into a single line, which hurts readability.
Template data
Templates receive data based on the containing project, version, etc. See the section on Data types below for more information about each type and its available fields.
ketryxVersion
string
Version of Ketryx used to generate the document
versionScopeDescription
string (async)
Scope description of the version
In addition, templates may query for certain items in a project using the $KQL tag (as explained here).
async variables
All variables marked as async are asynchronously resolved. These variables cannot be used as sub-parts of other expressions. They have to be output directly or assigned to a variable first using the $SET operation.
Data types
Data in templates consists of objects (with certain properties), lists, strings, numbers, and dates. The following object types may appear.
Organization
Organizationid
string
Ketryx ID of the organization
name
string
Organization name
Project
ProjectProjectReference
ProjectReferenceVersion
Versionid
string
Ketryx ID of the version
name
string
Version name
versionNumber
string
Version number
scopeDescription
string (async)
Scope description
Milestone
Milestoneid
string
Ketryx ID of the milestone
name
string
Milestone name
completedAt
date
Completion date
createdAt
date
Creation date
MeetingNote
MeetingNoteid
string
Ketryx ID of the meeting note
content
string
Content rendered to HTML
date
date
Date of the meeting
participants
string
Plain text string containing meeting participants
Document
Documentid
string
Ketryx ID of the document
title
string
Document title
date
date
Generation date
Item
Itemid
string
Ketryx ID of the item
jiraIssueKey
string
Jira work item key of the item
repositoryItemId
string
User-defined item ID from the source code
ItemRecordCore
ItemRecordCoreThe core data for an item record contains the following properties:
id
string
Ketryx ID of the record
docId
string
Document ID of the record
title
string
Title
typeName
string
Name of item type
typeShortName
string
Short name of item type
revision
number
Record revision number
controlledRevision
number
Controlled revision counter
uncontrolledRevision
number
Uncontrolled revision counter
status
string
Status name
createdAt
date
Record creation date
diff
"NEW", "CHANGED", "REMOVED", "SAME"
Diff of the item to the baseline version
regions
list of string
Regions
introducedInVersion
string
Version number introducing this item
obsoleteInVersion
string
Version number obsoleting this item
isControlled
boolean
Whether this record is in a controlled state
isRiskAcceptable
boolean
Whether this risk record has an acceptable risk
url
string
URL of the record's item record detail page
For controlled records, controlledRevision counts the number of controlled records so far (starting with 1 for the first controlled record), and uncontrolledRevision is 0. For uncontrolled records, controlledRevision is the controlled revision counter of the upcoming controlled revision (i.e., the controlled revision worked on towards), and uncontrolledRevision counts the number of revisions since the previous controlled revision. These counters can be used to establish a record numbering scheme such as 1-1 (first draft towards the first controlled record), 1-2, …, 1-0 (first controlled record), 2-1, etc.
Some other properties that are more expensive to compute are only exposed under ItemRecordFull, to improve performance and avoid a potential infinite recursion.
ItemRecordFull
ItemRecordFullA full item record contains all the properties from ItemRecordCore, plus the following:
contentSha256
string
Hash of the record contents (Base64-encoded SHA-256 value)
fieldContent
object
Rendered content of each field
fieldValue
object
Raw value of each field
fieldChanged
boolean
Whether the value of each field changed compared to the baseline release
fieldContentDiff
object
Rendered content of the difference ("diff" or "redline") of each field compared to the baseline release
testEnvironments
list of string
Test environments associated with an (Xray) Test Case
xrayData
object
Raw data from Xray
The keys in the objects fieldContent, fieldValue, fieldChanged, and fieldContentDiff are field names, where spaces are replaced by underscores (_), e.g., Rationale_for_deferring_resolution.
The values in fieldContent and fieldContentDiff are pieces of rich-text (HTML) content that need to be rendered with a ~~ prefix, similarly to the itemContent filter. Example:
{~~ item.fieldContent.Rationale_for_deferring_resolution}The raw Xray data exposed in xrayData is not currently documented in detail, as it might change depending on their data structure.
Comment
Commentid
string
Ketryx ID of the comment
content
string
Content of the comment
createdAt
date
Creation date
recordRevision
number
Record revision the comment is written on
Attachment
Attachmentid
string
ID of the resource
filename
string
File name associated with the resource
sizeBytes
number
File size in bytes
contentSha256
string
Hash of the file contents (Base64-encoded SHA-256 value)
createdAt
date
Timestamp of creation
url
date
Timestamp of creation
renderedContent
date
Timestamp of creation
isImage
boolean
Whether the resource is an image
The value in renderedContent is a piece of rich-text HTML that can be rendered with a ~~ prefix, similarly to the itemContent filter. If isImage is true, then {~~renderedContent} will render an image; otherwise, it will render a link to the resource, using the filename as the displayed text.
TestRun
TestRunstatusName
string
Status name
comment
string
Raw value of the comment field
commentContent
object
Formatted content for the comment field
xrayId
string
ID of the test run in Xray
xrayData
object
Raw data from Xray
TestStep
TestStepstatusName
string
Status name (from Xray)
action
string
Raw value of the action field
actionContent
object
Formatted content for the action field
data
string
Raw value of the data field
dataContent
object
Formatted content for the data field
result
string
Raw value of the result field
resultContent
object
Formatted content for the result field
actualResult
string
Raw value of the actual result field
actualResultContent
object
Formatted content for the actual result field
defects
list of strings
Xray IDs of defects found in this step
comment
string
Raw value of the comment field
commentContent
object
Formatted content for the comment field
xrayId
string
ID of the test step in Xray
xrayData
object
Raw data from Xray
Content fields such as actionContent, dataContent, resultContent, actualResultContent, commentContent are pieces of rich-text HTML that can be rendered with a ~~ prefix, similarly to the itemContent filter.
Actual results and evidence are only available for steps on a TestRun, but not on the ItemRecordFull of the underlying Test Case.
Iteration
Iterationrank
string
Index of the step
statusName
string
Execution status of the step in an iteration
xrayData
object
Raw data from Xray
IterationParameter
IterationParametername
string
Unique key
value
string
Value to specific to an iteration
IterationStepResult
IterationStepResultstatusName
string
Status name (from Xray)
comment
string
Raw value of the comment field
commentContent
object
Formatted content for the comment field
actualResult
string
Raw value of the actual result field
actualResultContent
object
Formatted content for the actual result field
xrayId
string
ID of the result in Xray
xrayData
object
Raw data from Xray
IterationDefect
IterationDefectid
string
Xray ID of the defect
Relation
Relationtype
string
For system relations will be the built-in type, such as "HAS_PARENT". For custom relations will be the key of the configuration object in the "Custom relations" advanced setting
name
string
Relation name
isReverse
boolean
Whether the relation is a reverse relation, i.e. the other item is the source item of the relation
TraceabilityMatrix
TraceabilityMatrixisFulfilled
boolean
Whether all checks are fulfilled, i.e. the matrix is "green"
TraceabilityCheck
TraceabilityChecktitle
string
Title of the check
progress
number
Progress percentage (0 – 100)
description
string
Description of the check
isPositiveProgress
boolean
Whether the check is complete upon reaching 100%
isComplete
boolean
Whether the check is complete
TraceabilityRow
TraceabilityRowcolumns
object containing TraceabilityCell
Data for each cell in the row, using each column's ID as the key
TraceabilityCell
TraceabilityCellTestStatus
TestStatustitle
string
Title of this test
isInTestPlan
boolean
Whether this test is in the test plan
executedAt
date
Execution time stamp (if any)
result
"FAIL", "FAIL_ACCEPTED", "PASS", "PASS_WITH_EXCEPTION"
Effective test result (if any)
AutomatedTestExecution
AutomatedTestExecutiontitle
string
Title of this automated test
createdAt
date
Timestamp
result
"FAIL", "FAIL_ACCEPTED", "PASS", "PASS_WITH_EXCEPTION"
Test status result
ApprovalData
ApprovalDataUser
Userid
string
Ketryx ID of the user
name
string
Full name of the user
email
string
Email of the user
TrainingStatus
TrainingStatusgroupNames
list of string
Names of groups the user is a member of
TrainingStatusDocument
TrainingStatusDocumentTrainingDocument
TrainingDocumentVulnerability
VulnerabilitydescriptionContent
string
Rendered content for the vulnerability description
The value of descriptionContent is a piece of rich-text (HTML) content that needs to be rendered with a ~~ prefix, similarly to the fieldContent field of ItemRecordFull and the itemContent filter. This is the HTML version of the raw value of info.description.
VulnerabilityInfo
VulnerabilityInfoid
string
Ketryx ID of the vulnerability
summary
string
Summary
description
string
Description (raw value)
version
string
Affected version(s)
urls
list of string
Vulnerability URLs
cveId
string
CVE ID of the vulnerability; filled for vulnerabilities coming from the National Vulnerability Database (NVD)
externalId
string
External ID of the vulnerability; filled for vulnerabilities submitted via the Build API
githubId
string
GHSA ID of the vulnerability; filled for vulnerabilities coming from the GitHub Security Advisory (GHSA)
cweIds
list of string
CWE IDs of the vulnerability
publishedDate
date
Date the vulnerability was published
modifiedDate
date
Date the vulnerability was modified
vulnerabilitySource
string ("NVD", "GHSA", "Build", "Import", or "Unknown")
The ingestion source of the vulnerability
cisaVulnerabilityName
string
The name of the vulnerability as listed in the CISA Known Exploited Vulnerabilities (KEV) catalog
cisaExploitAdd
Date
The date the vulnerability was added to the CISA KEV catalog
cisaActionDue
Date
The date the required action is due by CISA
cisaRequiredAction
string
The required action to address the vulnerability by CISA
The originalSeverity is set when the severity of the vulnerability was overwritten by a vulnerability impact assessment. It is not available when accessed through Dependency.
VulnerabilitySeverity
VulnerabilitySeveritylevel
string
Qualitative severity ratings
score
number
Numerical severity rating
vector
string
CVSS vector
Dependency
Dependencyname
string
Name of the dependency
type
string
Type of the dependency
record
Data associated with the dependency (only when dependencies as items is enabled)
declaredVersions
string
A ;-separated list of all declared versions of the dependency
lockedVersions
string
A ;-separated list of all locked versions of the dependency
earliestUsedVersion
string
Earliest used version of the dependency
latestUsedVersion
string
Latest used version of the dependency
latestAvailableVersion
string
Latest available version of the dependency
acceptedVersions
string
Accepted versions of the dependency
status
string
Review status of the dependency
riskLevel
string
Level of risk of the dependency
issuesUrl
string
Repository issues URL of the dependency
manufacturer
string
Manufacturer of the dependency
license
string
License of the dependency
intendedUse
string
Intended use of the dependency
securityImpact
string
Security impact of the dependency
securityImpactJustification
string
Security impact justification of the dependency
reliabilityImpact
string
Reliability impact of the dependency
reliabilityImpactJustification
string
Reliability impact justification of the dependency
additionalNotes
string
Additional notes of the dependency
manualVulnerabilities
string
Manual vulnerabilities of the dependency
levelOfSupport
string
Level of support for the dependency (e.g., Maintained, Deprecated, Abandoned)
levelOfSupportDescription
string
Description of the level of support for the dependency
endOfLife
date
End of life date for the dependency
endOfLifeDescription
string
Description of the end of life for the dependency
Library
Libraryid
string
Ketryx ID of the library
name
string
Name of the library
registry
string
Unique identifier of the library's registry
registryUrl
string
URL of the library's registry
ecosystem
string
Ecosystem name of the library
Standard templates
AI Templates
Additional templates
Last updated
Was this helpful?