Skip to content

Repository files navigation

Business Traceability

Early alpha — first iteration. This code and documentation are in a barely alpha state. Expect breaking changes, missing features, and rough edges.

A compliance control tool that enforces every commit in a release references a valid Jira ticket in an approved state. It ingests commit history and Jira ticket data, attests the result to a Kosli trail, and evaluates the trail against an OPA/Rego policy.

Overview

The tool has two parts:

  • Ingestor (src/) — a TypeScript CLI that walks the git commit range between two tags, extracts Jira ticket IDs from commit messages and branch names, fetches ticket details from Jira, and writes a JSON attestation file.
  • Policy (business-traceability.rego) — an OPA/Rego policy evaluated by Kosli that checks every commit has at least one Jira ticket, that tickets exist, and that they are in a permitted state and issue type.

Example commit graph

gitGraph
   commit id: "A"
   commit id: "B" tag: "BASE_TAG"
   branch feature
   commit id: "C"
   branch hotfix
   commit id: "P"
   commit id: "Q"
   commit id: "R"
   checkout main
   commit id: "I"
   merge hotfix id: "J"
   checkout feature
   commit id: "D"
   commit id: "F"
   checkout main
   commit id: "K"
   merge feature id: "G"
   commit id: "H" tag: "RELEASE_TAG"
   commit id: "S"
   commit id: "T"
Loading

Prerequisites

  • Node.js 18+
  • OPA (for running Rego tests locally)
  • Kosli CLI (for simulation)

Installation

npm install
npm run build

Configuration

bt.config.json

Place in the working directory (or pass --config <path>):

{
  "jiraConfigType": "cloud",
  "exemptions": {
    "serviceAccounts": ["svc_.*", "dependabot\\[bot\\]"]
  }
}
Field Values Description
jiraConfigType standard, cloud, safe Selects the permitted issue types and states for the target Jira instance
exemptions.serviceAccounts array of regex strings Commits whose author name or email matches any pattern are exempt from ticket requirements

Jira config types

Config Permitted issue types Example permitted states
standard Story, Bug, Technical Task, Change, Problem, Improvement, New Feature, Sub-task IN PROGRESS, CODE REVIEW, DONE, CLOSED, …
cloud Story, Bug, Task, Sub-task, Improvement IN PROGRESS, READY FOR VERIFY, DONE, …
safe Story, Enabler, Feature, Bug, Task, Sub-task BUILD (IP), PO ACCEPTED, DONE, CLOSED, …

See business-traceability.rego for the full list of permitted states per config type.

Environment variables

Variable Required Description
CURRENT_TAG Yes Git tag or SHA of the release being attested
BASE_TAG No Git tag or SHA of the previous release. Auto-resolved from Kosli when omitted.
GITHUB_REPOSITORY Yes owner/repo — recorded in the attestation for reference
JIRA_API_URL Yes Base URL of your Jira instance, e.g. https://your-org.atlassian.net
JIRA_CRED Yes Base64-encoded email:api-token (the ingestor prepends Basic)
PROXY_URL No HTTP/HTTPS proxy for Jira API calls
KOSLI_FLOW No Kosli flow name, used for base-tag auto-resolution
KOSLI_ATTESTATION_NAME No Defaults to bt-data

Usage

Running the ingestor

CURRENT_TAG=v1.2.0 \
BASE_TAG=v1.1.0 \
GITHUB_REPOSITORY=your-org/your-repo \
JIRA_API_URL=https://your-org.atlassian.net \
JIRA_CRED=$(printf 'you@example.com:YOUR_API_TOKEN' | base64 -w 0) \
node dist/index.js --repo /path/to/repo --config ./bt.config.json

This writes att_data_<CURRENT_TAG>.json in the current directory.

CLI flags

Flag Default Description
--repo <path> cwd Path to the git repository
--config <path> ./bt.config.json Path to the config file
--env-file <path> Load variables from a .env file
--flow <name> $KOSLI_FLOW Kosli flow name for base-tag auto-resolution
--first-parent off Walk only the mainline (first-parent) history; omit to consider all commits including those from merged branches

Base tag auto-resolution

When BASE_TAG is not set and a --flow name is provided, the ingestor queries Kosli to find the most recently attested commit in the first-parent history and uses that as the base. This means the first run of each release needs an explicit BASE_TAG; subsequent runs in the same flow resolve it automatically.

Attesting and evaluating in Kosli

After running the ingestor, the typical Kosli workflow is:

# 1. Begin a trail for the release commit
kosli begin trail <commit-sha> \
  --flow <flow-name> \
  --commit <commit-sha> \
  --repo-root /path/to/repo

# 2. Attest the ingestor output to the trail
kosli attest custom \
  --type bt-data \
  --name bt-data \
  --attestation-data att_data_<tag>.json \
  --trail <commit-sha> \
  --flow <flow-name>

# 3. Evaluate the trail against the policy
kosli evaluate trail <commit-sha> \
  --policy business-traceability.rego \
  --flow <flow-name> \
  --output json > eval_result.json

# 4. Attest the evaluation result
kosli attest generic \
  --name bt-result \
  --user-data eval_result.json \
  --attachments business-traceability.rego \
  --compliant=true \
  --trail <commit-sha> \
  --flow <flow-name>

See simulate.sh for a complete end-to-end example.

Policy

The Rego policy (business-traceability.rego) enforces the following rules for every non-exempt commit:

Rule Violation message
Commit has at least one Jira ID no Jira ticket ID found in commit message or branch name
Referenced ticket exists in Jira was not found
Jira API was reachable could not be fetched
Ticket issue type is permitted non-permitted issue type
Ticket status is permitted non-permitted state

For sub-tasks, both the sub-task and its parent are evaluated against all rules.

Running the Rego tests

npm run test:rego
# or directly:
opa test business-traceability.rego business-traceability_test.rego -v

Testing

npm test

Unit tests cover the extractor (Jira ID parsing) and Jira fetcher (found, not found, fetch error, sub-tasks, deduplication).

Registering the attestation type in Kosli

Before the first attestation, register the bt-data custom type:

KOSLI_API_TOKEN=<token> KOSLI_ORG=<your-org> ./setup-kosli-attestation-type.sh

This only needs to be done once per Kosli organisation.

Simulation

simulate.sh replays a sequence of historical staging tags through the full ingest → attest → evaluate pipeline against a real Jira and Kosli environment:

SIMULATE_REPO=/path/to/local-clone-of-the-test-repo ./simulate.sh

Credentials

The script reads credentials from files in the repository root (these are gitignored):

File Contents
kosli.key Kosli API token
jira.key Jira API token

What it does

Each iteration processes one tag-pair (previous → current):

  1. Begins a Kosli trail for the current commit
  2. Runs the ingestor (auto-resolving BASE_TAG from Kosli on all but the first iteration)
  3. Attests att_data_<tag>.json to the trail
  4. Evaluates the trail against the policy
  5. Attests the evaluation result (compliant or not) to the trail

Each run creates a uniquely named flow (business-traceability-<timestamp>) so runs do not interfere with each other.

File structure

.
├── src/
│   ├── index.ts           # CLI entry point
│   ├── config.ts          # Env var and config file loading
│   ├── git.ts             # Git log parsing and SHA resolution
│   ├── extractor.ts       # Jira ID extraction from text
│   ├── jira.ts            # Jira REST API fetcher (two-phase)
│   ├── reporter.ts        # Writes att_data_*.json
│   ├── kosli.ts           # Kosli CLI wrapper for trail listing
│   ├── baseTagResolver.ts # Auto-resolves BASE_TAG from Kosli
│   └── types.ts           # Shared TypeScript interfaces
├── tests/
│   ├── extractor.test.ts
│   └── jira.test.ts
├── business-traceability.rego       # OPA policy
├── business-traceability_test.rego  # OPA policy tests
├── bt.config.json                   # Jira config and exemptions
├── jsonschema.json                  # JSON Schema for att_data_*.json
├── setup-kosli-attestation-type.sh  # One-time Kosli setup
├── simulate.sh                      # End-to-end simulation script
├── package.json
└── tsconfig.json

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages