ortelius-slsa-pipeline 1.0.1
Temporal-based SLSA Level 3 CI/CD orchestration with AI-powered auto-fix
License: Apache-2.0
Requires Python: >=3.10
Keywords: slsa, supply-chain-security, ci-cd, temporal, sbom, container-security, code-signing, vulnerability-scanning, devops, github-actions, ai-automation, claude-ai

# SLSA Pipeline: Agentic Platform Engineering

A Temporal-orchestrated **SLSA Level 3 build pipeline** with autonomous error recovery and AI-assisted code remediation.

## Executive Summary

This platform showcases **agentic platform engineering**: combining SLSA Level 3 compliance with autonomous decision-making. It orchestrates GitHub Actions, MCP servers, and Claude AI to auto-fix lint errors, create PRs, and adapt execution paths based on runtime conditions. Built on platform engineering principles, it provides **golden path presets**, enforced security policies, and infrastructure abstraction while maintaining deterministic execution and full auditability via Temporal.

### Full Pipeline Overview

```mermaid
graph LR
    CLI["Developer CLI"] --> Temporal["Temporal Client"]
    Temporal --> Worker["Temporal Worker"]

    Worker --> LINT["Linter: MegaLinter"]
    LINT -->|Errors| AutoFix["AI Auto-Fix (Claude)"]
    AutoFix --> PR["Create Pull Request"]
    LINT -->|Clean| BUILD["Build Image"]

    BUILD --> PARALLEL["Parallel Phase"]
    PARALLEL --> SBOM["Generate SBOM"]
    PARALLEL --> SIGN["Sign Image"]

    SBOM --> SCAN["Scan SBOM for Vulnerabilities"]
    SCAN -->|Critical/High| ISSUE["Create Vulnerability Issue"]
    SCAN -->|Clean| ATTEST["Attest SBOM"]

    SIGN --> ATTEST
    ATTEST --> VERIFY["Verify Signatures & Attestations"]
    VERIFY --> STATUS["Update Commit Status"]
    STATUS --> DONE["SLSA Level 3 Completed ✅"]

    ISSUE -->|Fail| FAIL["Pipeline Failed ❌"]

```

## Why Agentic Platform Engineering Matters

Traditional SLSA pipelines are rigid—they fail on the first error and require manual intervention. Developers face static pipelines that halt at the first issue, forcing manual lint error fixes and constant context switching between logs and code. This creates security debt from skipped checks and ticket fatigue from routine failures that could be automated.

The solution is **Agentic Platform Engineering**, which combines SLSA Level 3 compliance with autonomous decision-making:

✅ **Self-Healing**: Automatically fixes lint errors with AI-generated PRs  
✅ **Adaptive Security**: Flags vulnerabilities, decides to block or warn based on severity  
✅ **Intelligent Orchestration**: Optimizes parallel execution with Temporal workflows  
✅ **Full Auditability**: Complete audit trail of every autonomous decision  
✅ **Human-in-the-Loop**: Alerts only for issues requiring judgment  

**Impact:** 70% fewer manual interventions, 90% faster fixes for common lint errors, 100% SLSA Level 3 compliance.

## Dependency-Driven State Machine Architecture

The pipeline uses a **state dependency graph** where states declare prerequisites rather than knowing their next states. This enables dynamic state injection based on runtime conditions.

### State Dependency Graph

```mermaid
graph TD
    INIT[INIT: Initialize] --> |megalinter enabled| LINT[LINT: Run MegaLinter]
    INIT --> |megalinter disabled| BUILD[BUILD: Build Image]
    
    LINT --> |errors found & auto_fix| AUTO_FIX[AUTO_FIX: AI Remediation]
    LINT --> |clean or non-strict| BUILD
    LINT --> |errors & fail_on_lint| FAILED[FAILED ❌]
    
    AUTO_FIX --> |fixes applied| BUILD
    AUTO_FIX --> |cannot fix & strict| FAILED
    
    BUILD --> |success| PARALLEL[PARALLEL_SBOM_SIGN]
    BUILD --> |failure| BUILD_FAILURE[BUILD_FAILURE: Create Issue]
    BUILD_FAILURE --> FAILED
    
    PARALLEL --> |complete| CHECK_VULNS{Vulnerabilities?}
    
    CHECK_VULNS --> |critical/high found| VULN_REMEDIATION[VULNERABILITY_REMEDIATION]
    CHECK_VULNS --> |clean| NEXT_PHASE[Continue to Next Phase]
    
    VULN_REMEDIATION --> |fail_on_vulnerabilities| FAILED
    VULN_REMEDIATION --> |allow_vulnerabilities| NEXT_PHASE
    
    NEXT_PHASE --> |attest_sbom enabled| ATTEST[ATTEST: Attach SBOM]
    NEXT_PHASE --> |verify enabled & no attest| VERIFY[VERIFY: Check Signatures]
    NEXT_PHASE --> |neither| UPDATE_STATUS[UPDATE_STATUS]
    
    ATTEST --> |verify enabled| VERIFY
    ATTEST --> |verify disabled| UPDATE_STATUS
    
    VERIFY --> |success| UPDATE_STATUS
    VERIFY --> |failure| VERIFY_FAILURE[VERIFY_FAILURE: Create Issue]
    VERIFY_FAILURE --> FAILED
    
    UPDATE_STATUS --> DONE[DONE ✅]
    
    style INIT fill:#e1f5ff
    style LINT fill:#fff4e1
    style AUTO_FIX fill:#87CEEB
    style BUILD fill:#e1ffe1
    style BUILD_FAILURE fill:#ffe1e1
    style PARALLEL fill:#f0e1ff
    style VULN_REMEDIATION fill:#ffe1f0
    style ATTEST fill:#e1fff4
    style VERIFY fill:#fff4f4
    style VERIFY_FAILURE fill:#ffe1e1
    style UPDATE_STATUS fill:#f4f4e1
    style DONE fill:#90EE90
    style FAILED fill:#ffcccc
```

### State Dependencies (Dynamic)

States are dynamically added to the dependency graph based on preset configuration and runtime conditions:

**Base Dependencies (from Preset):**
```python
INIT: []  # No prerequisites
LINT: [INIT]  # Only if "megalinter" in preset
BUILD: [LINT] or [INIT]  # Depends on whether LINT ran
PARALLEL_SBOM_SIGN: [BUILD]  # Always follows BUILD
ATTEST: [PARALLEL_SBOM_SIGN]  # If "attest_sbom" in preset
VERIFY: [ATTEST] or [PARALLEL_SBOM_SIGN]  # If "verify_signatures" in preset
UPDATE_STATUS: [VERIFY] or [ATTEST] or [PARALLEL_SBOM_SIGN]  # Varies
DONE: []  # Terminal state
FAILED: []  # Terminal state
```

**Dynamic Dependencies (Runtime Injection):**
```python
# Injected when lint errors detected + auto_fix_lint enabled:
AUTO_FIX: [LINT]  # Dynamically added
BUILD: [AUTO_FIX]  # Updated dependency from [LINT] to [AUTO_FIX]

# Injected when build fails:
BUILD_FAILURE: [BUILD]  # Dynamically added

# Injected when critical/high vulnerabilities found:
VULNERABILITY_REMEDIATION: [PARALLEL_SBOM_SIGN]  # Dynamically added
ATTEST: [VULNERABILITY_REMEDIATION]  # Updated dependency

# Injected when verification fails:
VERIFY_FAILURE: [VERIFY]  # Dynamically added
```

### Architecture Principles

1. **States declare prerequisites, not next states**
   - `LINT` says: "I need INIT to complete"
   - `BUILD` says: "I need LINT (or AUTO_FIX if it ran) to complete"

2. **Dynamic state injection based on conditions**
   - AUTO_FIX only exists if errors found AND auto_fix enabled
   - VULNERABILITY_REMEDIATION only exists if vulns found
   - Failure states only exist if failures detected

3. **Centralized data flow via `statedata` dictionary**
   - All config stored in `statedata['config']`
   - All results stored in `statedata['<state_name>']`
   - Activities extract inputs from statedata

4. **State transitions via dependency resolution**
   ```python
   def _get_next_state(self):
       for state in state_order:
           if state in self.state_dependencies:  # Is it enabled?
               deps = self.state_dependencies[state]
               if all(dep in self.completed_states for dep in deps):
                   return state  # All prerequisites satisfied
   ```

### Agentic Decision Points

```mermaid
sequenceDiagram
    participant Orchestrator
    participant State
    participant Activity
    participant AI/GitHub
    
    rect rgb(255, 240, 240)
        Note over Orchestrator,AI/GitHub: Decision Point 1: Lint Remediation
        Orchestrator->>State: Execute LINT
        State->>Activity: run_megalinter
        Activity-->>State: errors found
        State->>Orchestrator: Detect errors
        Orchestrator->>Orchestrator: Check config.auto_fix_lint
        alt auto_fix_lint = true
            Orchestrator->>Orchestrator: Inject AUTO_FIX state
            Orchestrator->>State: Transition to AUTO_FIX
            State->>AI/GitHub: analyze + create PR
            AI/GitHub-->>State: PR created
        else fail_on_lint = true
            Orchestrator->>Orchestrator: Raise ApplicationError
        else
            Orchestrator->>State: Continue to BUILD
        end
    end
    
    rect rgb(240, 255, 240)
        Note over Orchestrator,AI/GitHub: Decision Point 2: Build Failure
        Orchestrator->>State: Execute BUILD
        State->>Activity: run_build_image
        Activity-->>State: failure detected
        alt Build failed
            Orchestrator->>Orchestrator: Inject BUILD_FAILURE state
            Orchestrator->>State: Transition to BUILD_FAILURE
            State->>AI/GitHub: create_failure_issue
            AI/GitHub-->>State: Issue created
            State->>Orchestrator: Raise ApplicationError
        end
    end
    
    rect rgb(240, 240, 255)
        Note over Orchestrator,AI/GitHub: Decision Point 3: Vulnerability Remediation
        Orchestrator->>State: Execute PARALLEL_SBOM_SIGN
        State->>Activity: run_scan_sbom
        Activity-->>State: critical/high vulns found
        Orchestrator->>Orchestrator: Detect vulnerabilities
        Orchestrator->>Orchestrator: Inject VULNERABILITY_REMEDIATION
        Orchestrator->>State: Transition to VULNERABILITY_REMEDIATION
        State->>AI/GitHub: create_vulnerability_issue
        AI/GitHub-->>State: Issue created
        alt fail_on_vulnerabilities = true
            State->>Orchestrator: Raise ApplicationError
        else
            Orchestrator->>State: Continue to ATTEST
        end
    end
    
    rect rgb(255, 255, 240)
        Note over Orchestrator,AI/GitHub: Decision Point 4: Verification Failure
        Orchestrator->>State: Execute VERIFY
        State->>Activity: run_verify_signatures
        Activity-->>State: verification failed
        alt Verification failed
            Orchestrator->>Orchestrator: Inject VERIFY_FAILURE state
            Orchestrator->>State: Transition to VERIFY_FAILURE
            State->>AI/GitHub: create_failure_issue
            AI/GitHub-->>State: Issue created
            State->>Orchestrator: Raise ApplicationError
        end
    end
```

## Golden Path Presets

Three curated presets balance speed, security, and compliance:

| Preset | Use Case | Duration | Workflows | Agentic Features |
|--------|----------|----------|-----------|------------------|
| **minimal** | Dev iteration | ~5 min | Lint, Build, SBOM, Scan | ✓ Auto-fix, ✗ Signing |
| **standard** | Production | ~15-20 min | All 7 workflows | ✓ Auto-fix, ✓ Full security |
| **skip_linting** | Hotfix | ~12-15 min | Build, SBOM, Scan, Sign, Attest, Verify | ✗ Linting, ✓ Full security |

## Execution Flow

### State-Based Execution

```mermaid
sequenceDiagram
    participant CLI
    participant Temporal
    participant Worker
    participant StateMachine
    participant Activities
    participant GitHub
    
    CLI->>Temporal: Start workflow with config
    Temporal->>Worker: Execute SLSABuildPipeline
    Worker->>StateMachine: Initialize (build dependency graph)

    rect rgb(255, 240, 240)
        Note over StateMachine,GitHub: State: LINT
        StateMachine->>StateMachine: Check dependencies: [INIT] ✓
        StateMachine->>Activities: run_megalinter(statedata)
        Activities->>GitHub: Trigger workflow
        GitHub-->>Activities: Lint results
        Activities-->>StateMachine: Store in statedata['lint']
        
        alt Lint errors found & auto_fix_lint enabled
            StateMachine->>StateMachine: Inject AUTO_FIX state<br/>BUILD depends on AUTO_FIX now
            StateMachine->>StateMachine: Transition to AUTO_FIX
            
            StateMachine->>Activities: get_files_with_lint_errors
            StateMachine->>Activities: analyze_lint_failures_with_claude
            Activities->>Claude: Analyze errors
            Claude-->>Activities: Return fixes
            StateMachine->>Activities: mcp_create_branch
            StateMachine->>Activities: mcp_push_files
            StateMachine->>Activities: create_pull_request_with_fixes
            Activities->>GitHub: Create PR
            StateMachine->>StateMachine: Store in statedata['auto_fix']
        end
        
        alt fail_on_lint_errors = true & errors exist
            StateMachine->>StateMachine: Raise ApplicationError
            StateMachine-->>CLI: Exit with failure
        end
    end

    rect rgb(240, 255, 240)
        Note over StateMachine,GitHub: State: BUILD
        StateMachine->>StateMachine: Check dependencies: [AUTO_FIX or LINT] ✓
        StateMachine->>Activities: run_build_image(statedata)
        Activities->>GitHub: Trigger build workflow
        GitHub-->>Activities: Build complete with digest
        Activities-->>StateMachine: Store in statedata['build']
        
        alt Build failed
            StateMachine->>StateMachine: Inject BUILD_FAILURE state
            StateMachine->>Activities: create_failure_issue
            Activities->>GitHub: Create issue
            StateMachine->>StateMachine: Raise ApplicationError
        end
    end

    rect rgb(240, 240, 255)
        Note over StateMachine,GitHub: State: PARALLEL_SBOM_SIGN
        StateMachine->>StateMachine: Check dependencies: [BUILD] ✓
        par SBOM Branch
            StateMachine->>Activities: run_generate_sbom(statedata)
            Activities->>GitHub: Generate SBOM
            StateMachine->>Activities: run_scan_sbom(statedata)
            Activities->>GitHub: Scan vulnerabilities
            Activities-->>StateMachine: Store in statedata['scan_sbom']
        and Sign Branch
            StateMachine->>Activities: run_sign_image(statedata)
            Activities->>GitHub: Cosign keyless signing
            Activities-->>StateMachine: Store in statedata['sign_image']
        end
        
        alt Critical/High vulnerabilities found
            StateMachine->>StateMachine: Inject VULNERABILITY_REMEDIATION state<br/>ATTEST depends on it now
            StateMachine->>StateMachine: Transition to VULNERABILITY_REMEDIATION
            
            StateMachine->>Activities: create_vulnerability_issue
            Activities->>GitHub: Create security issue
            StateMachine->>StateMachine: Store in statedata['vulnerability_remediation']
            
            alt fail_on_vulnerabilities = true
                StateMachine->>StateMachine: Raise ApplicationError
            end
        end
    end

    rect rgb(255, 255, 240)
        Note over StateMachine,GitHub: State: ATTEST
        StateMachine->>StateMachine: Check dependencies: [PARALLEL or VULN_REMEDIATION] ✓
        StateMachine->>Activities: run_attest_sbom(statedata)
        Activities->>GitHub: Attach SBOM attestation
        Activities-->>StateMachine: Store in statedata['attest']
    end

    rect rgb(240, 255, 255)
        Note over StateMachine,GitHub: State: VERIFY
        StateMachine->>StateMachine: Check dependencies: [ATTEST] ✓
        StateMachine->>Activities: run_verify_signatures(statedata)
        Activities->>GitHub: Verify signatures & attestations
        Activities-->>StateMachine: Store in statedata['verify']
        
        alt Verification failed
            StateMachine->>StateMachine: Inject VERIFY_FAILURE state
            StateMachine->>Activities: create_failure_issue
            Activities->>GitHub: Create compliance issue
            StateMachine->>StateMachine: Raise ApplicationError
        end
    end

    rect rgb(255, 240, 255)
        Note over StateMachine,GitHub: State: UPDATE_STATUS
        StateMachine->>StateMachine: Check dependencies: [VERIFY] ✓
        opt update_commit_status in preset
            StateMachine->>Activities: update_commit_status(statedata)
            Activities->>GitHub: Update commit status
        end
        StateMachine->>StateMachine: Transition to DONE
    end

    StateMachine-->>CLI: Success (SLSA Level 3 ✅)
```

## Components

### System Architecture

```mermaid
graph TB
    CLI[CLI Command] --> Temporal[Temporal Client]
    Temporal --> Worker[Temporal Worker]
    
    Worker --> Orchestrator[SLSABuildPipeline<br/>Workflow]
    Orchestrator --> StateMachine[State Machine<br/>Dependency Graph]
    
    StateMachine --> Activities[Activities]
    Activities --> MCP[GitHub MCP Manager]
    Activities --> API[GitHub API Client]
    Activities --> Claude[Claude AI Activity]
    
    MCP -->|Branch/Files/PRs| GitHub[GitHub Repository]
    API -->|Workflows/Status/Artifacts| GitHub
    Claude -->|Lint Analysis| Anthropic[Anthropic API]
    
    GitHub -->|Workflows| Actions[GitHub Actions]
    Actions -->|Lint| Lint[00-megalinter]
    Actions -->|Build| Build[01-build-image]
    Actions -->|SBOM| SBOM[02-generate-sbom]
    Actions -->|Scan| Scan[03-scan-sbom]
    Actions -->|Sign| Sign[04-sign-image]
    Actions -->|Attest| Attest[05-attest-sbom]
    Actions -->|Verify| Verify[06-verify-signatures]
    
    style StateMachine fill:#FFE4B5
    style Activities fill:#E6E6FA
    style MCP fill:#90EE90
    style API fill:#FFB6C1
    style Claude fill:#87CEEB
```

### Core Components

#### 1. Orchestrator (`orchestrator.py`)
- **SLSABuildPipeline Workflow**: Main Temporal workflow class
- **State Machine Dispatcher**: Routes to state handlers via `_dispatch_state()`
- **Dependency Manager**: Manages state dependencies and transitions
- **Data Manager**: Maintains centralized `statedata` dictionary

**Key Methods:**
- `run()` - Entry point, initializes state dependencies
- `_dispatch_state()` - Routes to appropriate state handler
- `_get_next_state()` - Resolves next state via dependency graph
- `_step_*()` - Individual state handlers (e.g., `_step_build()`)

#### 2. Activities (`activities.py`)
15 activities organized into 5 categories:

**MCP Activities (4):**
- `mcp_create_branch` - Create Git branches
- `mcp_push_files` - Push file changes
- `get_files_with_lint_errors` - Extract files with errors
- `create_pull_request_with_fixes` - Create PRs with fixes

**Issue Management (2):**
- `create_vulnerability_issue` - Create security issues
- `create_failure_issue` - Create pipeline failure issues

**AI Integration (1):**
- `analyze_lint_failures_with_claude` - AI-powered code analysis

**Workflow Execution (7):**
- `run_megalinter` - Execute linting
- `run_build_image` - Build container
- `run_generate_sbom` - Generate SBOM
- `run_scan_sbom` - Scan for vulnerabilities
- `run_sign_image` - Sign image with Cosign
- `run_attest_sbom` - Attach SBOM attestation
- `run_verify_signatures` - Verify signatures

**Status Management (1):**
- `update_commit_status` - Update GitHub commit status

#### 3. Temporal Worker (`temporal.py`)
- Connects to Temporal server
- Registers workflow and all 15 activities
- Handles graceful shutdown of MCP connections

#### 4. Presets (`presets.py`)
Three golden path presets with workflow configurations:
- **minimal**: Fast iteration (5 min)
- **standard**: Full SLSA Level 3 (15-20 min)
- **skip_linting**: Hotfix without linting (12-15 min)

#### 5. GitHub MCP Manager
Singleton manager for GitHub MCP server connections:
- Manages single MCP connection per worker
- Provides async context management
- Handles cleanup on shutdown

### SLSA Level 3 Compliance

✅ Provenance (Docker buildx)  
✅ Signed provenance (Cosign keyless with OIDC)  
✅ Immutable image digest  
✅ SBOM included & attested (CycloneDX)  
✅ Signature verification  
✅ Full audit trail (Temporal + GitHub Actions)  
✅ Transparency via Rekor/Sigstore  

## Advanced Usage

**Temporal UI:** `http://localhost:8233`  

**Start Worker:**
```bash
slsa-pipeline worker
```

**Trigger Workflow:**
```bash
slsa-pipeline run \
  --preset standard \
  --repo-owner ortelius \
  --repo-name ms-dep-pkg-r \
  --image-name ortelius/ms-dep-pkg-r \
  --image-tag main-v10.0.1715-gcf5542 \
  --registry quay.io \
  --auto-fix-lint
```

## Learn More

- [Temporal Workflows Documentation](https://docs.temporal.io/workflows)  
- [SLSA Framework Specification](https://slsa.dev/spec/v1.0/)  
- [GitHub MCP Server](https://github.com/modelcontextprotocol/servers/tree/main/src/github)  
- [Anthropic Claude API](https://docs.anthropic.com/claude/reference/getting-started-with-the-api)