---
title: "Custom Artifacts"
description: "Creating custom artifact types for your specific traceability needs"
---

# Custom Artifacts

TraceRTM's 16 built-in artifact types cover most needs, but sometimes you need custom types for domain-specific artifacts. This guide covers creating, configuring, and using custom artifact types.

## When to Use Custom Types

Create custom types when:

| Scenario | Custom Type Example |
|----------|---------------------|
| Domain-specific artifacts | `clinical_trial`, `regulatory_submission` |
| Specialized workflows | `change_request`, `incident`, `risk` |
| Integration needs | `jira_epic`, `confluence_page` |
| Reporting categories | `milestone`, `deliverable`, `kpi` |

## Defining Custom Types

### Basic Definition

```yaml
# .tracertm/types/custom_types.yaml
custom_types:
  # Risk artifact for risk management
  - name: risk
    display_name: "Risk Item"
    description: "Identified risk with mitigation plan"
    id_prefix: "RISK"

    # Required fields
    fields:
      - name: probability
        type: enum
        values: [low, medium, high, critical]
        required: true

      - name: impact
        type: enum
        values: [low, medium, high, critical]
        required: true

      - name: mitigation_plan
        type: text
        required: true

      - name: owner
        type: user
        required: true

    # Computed fields
    computed:
      - name: risk_score
        formula: "probability_value * impact_value"
        # low=1, medium=2, high=3, critical=4

    # Allowed link types
    link_types:
      - type: affects
        targets: [feature, design, code]
      - type: mitigated_by
        targets: [test, task]

  # Decision record
  - name: decision
    display_name: "Architecture Decision Record"
    description: "Documented architectural decision"
    id_prefix: "ADR"

    fields:
      - name: status
        type: enum
        values: [proposed, accepted, deprecated, superseded]
        required: true

      - name: context
        type: text
        required: true

      - name: decision
        type: text
        required: true

      - name: consequences
        type: text
        required: true

      - name: alternatives
        type: list
        item_type: text

    link_types:
      - type: affects
        targets: [architecture, design, code]
      - type: superseded_by
        targets: [decision]
```

### Complex Field Types

```yaml
custom_types:
  - name: incident
    display_name: "Incident Report"
    id_prefix: "INC"

    fields:
      # Enum with display values
      - name: severity
        type: enum
        values:
          - value: sev1
            label: "Severity 1 - Critical"
            color: red
          - value: sev2
            label: "Severity 2 - Major"
            color: orange
          - value: sev3
            label: "Severity 3 - Minor"
            color: yellow
          - value: sev4
            label: "Severity 4 - Low"
            color: green

      # Date/time field
      - name: detected_at
        type: datetime
        required: true

      - name: resolved_at
        type: datetime

      # Duration (computed)
      - name: time_to_resolve
        type: computed
        formula: "resolved_at - detected_at"

      # User reference
      - name: assigned_to
        type: user

      # Multi-select
      - name: affected_services
        type: list
        item_type: string

      # Nested object
      - name: timeline
        type: list
        item_type: object
        schema:
          - name: timestamp
            type: datetime
          - name: event
            type: text
          - name: actor
            type: user
```

## Creating Custom Artifacts

### Python SDK

```python
from tracertm import TraceRTMClient

client = TraceRTMClient()

# Create risk artifact
risk = client.create_item(
    title="Authentication bypass vulnerability",
    item_type="risk",
    description="Potential for auth bypass via token manipulation",
    metadata={
        "probability": "medium",
        "impact": "critical",
        "mitigation_plan": """
        1. Add token signature validation
        2. Implement token rotation
        3. Add anomaly detection
        """,
        "owner": "security@company.com",
        "identified_date": "2024-12-01",
        "category": "security"
    }
)

# Link to affected artifacts
client.create_link(risk.id, "FEAT-001", "affects")
client.create_link(risk.id, "CODE-015", "affects")

# Link to mitigating test
client.create_link(risk.id, "TEST-042", "mitigated_by")
```

### CLI

```bash
# Create custom artifact
tracertm create risk "Auth bypass vulnerability" \
  --field probability=medium \
  --field impact=critical \
  --field owner=security@company.com \
  --metadata '{"mitigation_plan": "Add token validation"}'

# List custom types
tracertm list --type risk
tracertm list --type decision

# Link custom artifact
tracertm link RISK-001 FEAT-001 --type affects
```

## Custom Workflows

### Workflow for Custom Type

```yaml
# .tracertm/workflows/risk.yaml
name: risk
applies_to: [risk]

states:
  - name: identified
    description: "Risk identified, not yet analyzed"
    initial: true
    color: yellow

  - name: analyzing
    description: "Risk being analyzed"
    color: orange

  - name: mitigating
    description: "Mitigation in progress"
    color: blue

  - name: mitigated
    description: "Mitigation complete"
    color: green
    terminal: false  # Can be reopened

  - name: accepted
    description: "Risk accepted (not mitigating)"
    color: gray
    terminal: true

  - name: closed
    description: "Risk no longer relevant"
    color: gray
    terminal: true

transitions:
  - from: identified
    to: analyzing
    requires:
      - field: owner
        not_null: true

  - from: analyzing
    to: mitigating
    requires:
      - field: mitigation_plan
        not_empty: true
      - field: probability
        not_null: true
      - field: impact
        not_null: true

  - from: mitigating
    to: mitigated
    requires:
      - link_type: mitigated_by
        min_count: 1
        message: "Must have at least one mitigating action"

  - from: analyzing
    to: accepted
    requires:
      - approval:
          role: risk_manager
      - field: acceptance_rationale
        not_empty: true

  - from: [mitigated, accepted]
    to: closed
    requires:
      - approval:
          role: risk_manager
```

## Custom Validation

### Field Validation

```yaml
custom_types:
  - name: change_request
    id_prefix: "CR"

    fields:
      - name: requested_by
        type: user
        required: true

      - name: priority
        type: enum
        values: [low, medium, high, critical]
        required: true

      - name: target_date
        type: date
        validation:
          min: today
          message: "Target date must be in the future"

      - name: estimated_hours
        type: number
        validation:
          min: 0.5
          max: 500
          message: "Estimate must be between 0.5 and 500 hours"

      - name: affected_items
        type: list
        item_type: reference
        validation:
          min_items: 1
          message: "Must specify at least one affected item"
```

### Cross-Field Validation

```yaml
validation:
  rules:
    # If priority is critical, must have justification
    - when:
        field: priority
        equals: critical
      require:
        field: critical_justification
        not_empty: true
        message: "Critical priority requires justification"

    # Target date must be after creation
    - condition: "target_date > created_at"
      message: "Target date must be after creation date"

    # High impact + high probability = requires risk review
    - when:
        all:
          - field: impact
            in: [high, critical]
          - field: probability
            in: [high, critical]
      require:
        link_type: reviewed_by
        target_type: risk_review
        message: "High risk items require risk review"
```

## Custom Reports

### Report Template

```yaml
# .tracertm/reports/risk_register.yaml
name: Risk Register
description: "Current risk status across all projects"
type: custom

data_sources:
  - type: items
    item_type: risk
    filters:
      status:
        not_in: [closed]

columns:
  - field: id
    header: "Risk ID"
  - field: title
    header: "Risk"
  - field: metadata.probability
    header: "Probability"
  - field: metadata.impact
    header: "Impact"
  - computed: risk_score
    header: "Score"
  - field: status
    header: "Status"
  - field: metadata.owner
    header: "Owner"

grouping:
  - field: metadata.category

sorting:
  - field: computed.risk_score
    direction: desc

output_formats:
  - pdf
  - csv
  - html
```

### Generate Report

```bash
# Generate risk register
tracertm report risk_register --output risk-report.pdf

# Filter by project
tracertm report risk_register --project PROJ-001

# Output:
# Risk Register Report
# ════════════════════
#
# Security Risks (3):
#   RISK-001: Auth bypass [Critical] - Mitigating
#   RISK-005: SQL injection [High] - Mitigated
#   RISK-012: XSS vulnerability [Medium] - Identified
#
# Performance Risks (2):
#   RISK-003: Database scaling [High] - Analyzing
#   RISK-008: API latency [Medium] - Mitigating
#
# Summary:
#   Total: 5 active risks
#   Critical: 1
#   High: 2
#   Medium: 2
```

## Importing Custom Data

### CSV Import

```python
import csv
from tracertm import TraceRTMClient

client = TraceRTMClient()

# Import risks from CSV
with open("risks.csv") as f:
    reader = csv.DictReader(f)
    for row in reader:
        client.create_item(
            title=row["title"],
            item_type="risk",
            metadata={
                "probability": row["probability"],
                "impact": row["impact"],
                "mitigation_plan": row["mitigation"],
                "owner": row["owner"],
                "external_id": row["id"]
            }
        )
```

### API Import

```python
# Import from external risk management system
def import_from_risk_system():
    risks = external_api.get_risks()

    for risk in risks:
        # Create or update
        existing = client.find_item(
            item_type="risk",
            metadata={"external_id": risk["id"]}
        )

        if existing:
            client.update_item(
                existing.id,
                title=risk["title"],
                metadata={
                    "probability": risk["likelihood"],
                    "impact": risk["severity"],
                    "external_id": risk["id"],
                    "last_sync": datetime.now().isoformat()
                }
            )
        else:
            client.create_item(
                title=risk["title"],
                item_type="risk",
                metadata={
                    "probability": risk["likelihood"],
                    "impact": risk["severity"],
                    "external_id": risk["id"]
                }
            )
```

## Best Practices

### 1. Use Meaningful Prefixes

```yaml
# Good: Clear, unique prefixes
- name: risk
  id_prefix: "RISK"

- name: decision
  id_prefix: "ADR"

- name: incident
  id_prefix: "INC"

# Bad: Confusing prefixes
- name: risk
  id_prefix: "R"  # Too short, conflicts with "requirement"
```

### 2. Define Required Fields

```yaml
# Ensure data quality with required fields
fields:
  - name: owner
    type: user
    required: true
    message: "Every risk must have an owner"

  - name: probability
    type: enum
    required: true

  - name: impact
    type: enum
    required: true
```

### 3. Configure Appropriate Links

```yaml
# Define valid link types for custom artifacts
link_types:
  - type: affects
    targets: [feature, code]
    description: "What this risk impacts"

  - type: mitigated_by
    targets: [test, task]
    description: "Actions that reduce the risk"

  - type: monitored_by
    targets: [alert, dashboard]
    description: "How the risk is tracked"
```

### 4. Create Matching Workflows

```yaml
# Every custom type should have a workflow
workflows:
  risk:
    states: [identified, analyzing, mitigating, mitigated, closed]
    # ...

  decision:
    states: [proposed, accepted, deprecated, superseded]
    # ...
```

## Related Topics

- [Artifacts Overview](/docs/wiki/concepts/artifacts) - Built-in types
- [Workflows](/docs/wiki/concepts/workflows) - State machines
- [Custom Workflows](/docs/wiki/concepts/workflows/custom) - Custom state machines
- [Reports](/docs/getting-started/first-project/reports) - Reporting on artifacts

