Integrations Architecture

Audience: Platform and connector engineers integrating Stella Ops with external SCM, registry, CI, and runtime systems. Read this for the module’s plugin contracts, the SCM annotation flow, and the live catalog API surface.

Overview

The Integrations module provides a unified catalog for external service connections — SCM providers (GitHub, GitLab, Gitea, Bitbucket), container registries (Harbor, Docker Registry, ECR, GCR, ACR), CI systems, secrets/runtime backends, and feed mirrors. It implements a plugin-based architecture for extensibility while maintaining consistent security and observability patterns across every connector.

Architecture Diagram

┌─────────────────────────────────────────────────────────────────────────────┐
│                         Integrations Module                                  │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  ┌──────────────────────┐    ┌──────────────────────┐                       │
│  │   WebService Host    │    │   Plugin Loader      │                       │
│  │   (ASP.NET Core)     │────│   (DI Registration)  │                       │
│  └──────────┬───────────┘    └──────────┬───────────┘                       │
│             │                           │                                    │
│  ┌──────────▼───────────────────────────▼───────────┐                       │
│  │              Integration Catalog                  │                       │
│  │  - Registration CRUD                              │                       │
│  │  - Health Polling                                 │                       │
│  │  - Test Connection                                │                       │
│  └──────────┬───────────────────────────────────────┘                       │
│             │                                                                │
│  ┌──────────▼───────────────────────────────────────┐                       │
│  │              Plugin Contracts                     │                       │
│  │  - IIntegrationConnectorPlugin                    │                       │
│  │  - IScmAnnotationClient                           │                       │
│  │  - IRegistryConnector                             │                       │
│  └──────────────────────────────────────────────────┘                       │
│             │                                                                │
│  ┌──────────▼───────────────────────────────────────┐                       │
│  │              Provider Plugins                     │                       │
│  │  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │                       │
│  │  │ GitHub  │ │ GitLab  │ │ Harbor  │ │  ECR    │ │                       │
│  │  │  App    │ │         │ │         │ │         │ │                       │
│  │  └─────────┘ └─────────┘ └─────────┘ └─────────┘ │                       │
│  │  ┌─────────┐ ┌─────────┐ ┌─────────┐            │                       │
│  │  │  GCR    │ │  ACR    │ │InMemory │            │                       │
│  │  │         │ │         │ │ (test)  │            │                       │
│  │  └─────────┘ └─────────┘ └─────────┘            │                       │
│  └──────────────────────────────────────────────────┘                       │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

Core Components

Integration Catalog

The central registry for all external service connections:

Plugin System

Extensible plugin architecture for provider support:

public interface IIntegrationConnectorPlugin : IAvailabilityPlugin
{
    IntegrationType Type { get; }
    IntegrationProvider Provider { get; }
    Task<TestConnectionResult> TestConnectionAsync(IntegrationConfig config, CancellationToken ct);
    Task<HealthCheckResult> CheckHealthAsync(IntegrationConfig config, CancellationToken ct);
}

SCM Annotation Client

Interface for PR/MR comments and status checks:

public interface IScmAnnotationClient
{
    Task<ScmOperationResult<ScmCommentResponse>> PostCommentAsync(
        ScmCommentRequest request, CancellationToken ct);
    
    Task<ScmOperationResult<ScmStatusResponse>> PostStatusAsync(
        ScmStatusRequest request, CancellationToken ct);
    
    Task<ScmOperationResult<ScmCheckRunResponse>> CreateCheckRunAsync(
        ScmCheckRunRequest request, CancellationToken ct);
}

SCM Annotation Architecture

Comment and Status Flow

┌────────────┐     ┌─────────────┐     ┌────────────────┐     ┌──────────┐
│  Scanner   │────▶│ Integrations│────▶│ SCM Annotation │────▶│ GitHub/  │
│  Service   │     │   Service   │     │    Client      │     │ GitLab   │
└────────────┘     └─────────────┘     └────────────────┘     └──────────┘
      │                                        │
      │         ┌─────────────────┐            │
      └────────▶│ Annotation      │◀───────────┘
                │ Payload Builder │
                └─────────────────┘

Supported Operations

OperationGitHubGitLab
PR/MR CommentIssue comment / Review commentMR Note / Discussion
Commit StatusCommit status APICommit status API
Check RunChecks API with annotationsPipeline status (emulated)
Inline AnnotationCheck run annotationMR discussion on line

Payload Models

Comment Request

public record ScmCommentRequest
{
    public required string Owner { get; init; }
    public required string Repository { get; init; }
    public required int PullRequestNumber { get; init; }
    public required string Body { get; init; }
    public string? CommentId { get; init; }  // For updates
    public bool UpdateExisting { get; init; } = true;
}

Status Request

public record ScmStatusRequest
{
    public required string Owner { get; init; }
    public required string Repository { get; init; }
    public required string CommitSha { get; init; }
    public required ScmStatusState State { get; init; }
    public required string Context { get; init; }
    public string? Description { get; init; }
    public string? TargetUrl { get; init; }
}

public enum ScmStatusState
{
    Pending,
    Success,
    Failure,
    Error
}

Check Run Request

public record ScmCheckRunRequest
{
    public required string Owner { get; init; }
    public required string Repository { get; init; }
    public required string HeadSha { get; init; }
    public required string Name { get; init; }
    public string? Status { get; init; }  // queued, in_progress, completed
    public string? Conclusion { get; init; }  // success, failure, neutral, etc.
    public string? Summary { get; init; }
    public string? Text { get; init; }
    public IReadOnlyList<ScmCheckRunAnnotation>? Annotations { get; init; }
}

public record ScmCheckRunAnnotation
{
    public required string Path { get; init; }
    public required int StartLine { get; init; }
    public required int EndLine { get; init; }
    public required string AnnotationLevel { get; init; }  // notice, warning, failure
    public required string Message { get; init; }
    public string? Title { get; init; }
}

Provider Implementations

GitHub App Plugin

GitLab Plugin

Security

Credential Management

Token Scopes

ProviderRequired Scopes
GitHub Appchecks:write, pull_requests:write, statuses:write
GitLabapi, read_repository, write_repository

Error Handling

Offline-Safe Operations

All SCM operations return ScmOperationResult<T>:

public record ScmOperationResult<T>
{
    public bool Success { get; init; }
    public T? Result { get; init; }
    public string? ErrorMessage { get; init; }
    public bool IsTransient { get; init; }  // Retry-able
    public bool SkippedOffline { get; init; }
}

Retry Policy

Observability

Metrics

MetricTypeLabels
integrations_health_check_totalCounterprovider, status
integrations_test_connection_duration_secondsHistogramprovider
scm_annotation_totalCounterprovider, operation, status
scm_annotation_duration_secondsHistogramprovider, operation

Structured Logging

All operations log with:

Current Catalog Contract

The live Integration Catalog contract is served by the Integrations WebService and is the source of truth for provider discovery and resource discovery.

Provider Metadata

Discovery

{
  "resourceType": "repositories",
  "filter": {
    "namePattern": "team/*"
  }
}

Discovery-Capable Providers

Credential Resolution

Scanner completion projection (X12)

Integrations does not read Scanner tables or accept a Scanner database connection. When ScannerProjection:Enabled=true, ScannerProjectionService authenticates as the named stellaops-integrations-web client with the tenant-bound machine scope scanner:projection:read, pulls only the configured exact tenant from Scanner’s retained GET /api/v1/scans/completed/events owner route, and folds verified scanner.scan.completed v2 envelopes into integrations.registry_image_scan_projections in stellaops_integrations.

The logical wire stream remains scanner.scans; local inbox/checkpoint and lease identities use Scanner’s injective tenant physical key. Projection upsert, inbox admission and checkpoint advance commit under one fenced destination transaction. The service then reports that durable (streamEpoch, seq) to POST /api/v1/scans/completed/consumers/{consumerId}. Reporting before the commit is forbidden: a failed report may retain too much producer history, but it must never permit Scanner to prune an event the destination has not committed. Epoch reset clears and rebuilds only the configured tenant’s derived projection.

The consumer validates exact equality among its configured token tenant, the catch-up response tenantId, and payload tenant; it recomputes both embedded set hashes with the producer-owned ScanFactsDigest helper and validates the list/summary counts before admission. Tampering fails before inbox or projection mutation. severityCounts: null remains unknown; this seam does not restore the former Scanner or vulnerability-database SQL joins. The feature remains deployment-controlled, so source presence does not by itself claim that an estate has activated or caught up the projection. These X12 statements are verified against the source tree at this document’s commit. Re-verify the admission gate with rg -n "VerifyPurlSet|VerifyFindingSet" src/Integrations and the targeted ScanCompletedProjectionConsumerTests class.

AI Code Guard Standalone Run

The Integrations WebService also hosts deterministic, standalone execution for AI Code Guard checks.

API Surface

The endpoint executes the equivalent of stella guard run behavior through an offline-safe API surface inside the Integrations module.

YAML-Driven Configuration

Configuration is parsed by AiCodeGuardPipelineConfigLoader:

The loader is deterministic and rejects unsupported keys or invalid values with explicit FormatException errors.

Scanning Behavior

AiCodeGuardRunService adds deterministic checks for:

Output ordering is stable:

  1. Severity descending
  2. Path ordinal
  3. Line number
  4. Rule ID
  5. Finding ID

Contracts

New contracts in src/Integrations/__Libraries/StellaOps.Integrations.Contracts/AiCodeGuardRunContracts.cs:

Test Coverage

Behavior is validated in src/Integrations/__Tests/StellaOps.Integrations.Tests/AiCodeGuardRunServiceTests.cs:

Run the adjacent suite with:

dotnet test src/Integrations/__Tests/StellaOps.Integrations.Tests/StellaOps.Integrations.Tests.csproj \
  -p:BuildProjectReferences=false --no-restore