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:
- Registration: Store connection configuration with encrypted credentials
- Health Monitoring: Periodic health checks with status tracking
- Test Connection: On-demand connectivity verification
- Audit trail: Create, update, delete and test are audited; status and health transitions are logged (no lifecycle event feed is published)
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
| Operation | GitHub | GitLab |
|---|---|---|
| PR/MR Comment | Issue comment / Review comment | MR Note / Discussion |
| Commit Status | Commit status API | Commit status API |
| Check Run | Checks API with annotations | Pipeline status (emulated) |
| Inline Annotation | Check run annotation | MR 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
- Uses GitHub App authentication (installation tokens)
- Supports: PR comments, commit status, check runs with annotations
- Handles rate limiting with exponential backoff
- Maps StellaOps severity to GitHub annotation levels
GitLab Plugin
- Uses Personal Access Token or CI Job Token
- Supports: MR notes, discussions, commit status
- Emulates check runs via pipeline status + MR discussions
- Handles project path encoding for API calls
Security
Credential Management
- All credentials stored as AuthRef URIs
- Resolved at runtime through Authority
- No plaintext secrets in configuration
- Audit trail for credential access
Token Scopes
| Provider | Required Scopes |
|---|---|
| GitHub App | checks:write, pull_requests:write, statuses:write |
| GitLab | api, 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
- Transient errors (rate limit, network): Retry with exponential backoff
- Permanent errors (auth, not found): Fail immediately
- Offline mode: Skip with warning, log payload for manual posting
Observability
Metrics
| Metric | Type | Labels |
|---|---|---|
integrations_health_check_total | Counter | provider, status |
integrations_test_connection_duration_seconds | Histogram | provider |
scm_annotation_total | Counter | provider, operation, status |
scm_annotation_duration_seconds | Histogram | provider, operation |
Structured Logging
All operations log with:
integrationId: Registration IDprovider: GitHub, GitLab, etc.operation: comment, status, check_runprNumber/commitSha: Target reference
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
GET /api/v1/integrations/providersreturnsProviderInfo[]withname,type,provider,isTestOnly,supportsDiscovery, andsupportedResourceTypes.- Test-only providers are hidden by default.
GET /api/v1/integrations/providers?includeTestOnly=trueonly exposes them when the current runtime or test harness explicitly registers a test-only connector such asInMemory. - Built-in provider coverage now includes Harbor, Docker Registry, GitLab Container Registry, GitHub App, Gitea, GitLab Server, GitLab CI, Jenkins, Nexus, Vault, Consul, eBPF Agent, the
S3Compatibleobject-storage provider, and feed mirror providers (StellaOpsMirror,NvdMirror,OsvMirror). TheInMemoryconnector remains test-only and is not part of the default host composition.
Discovery
POST /api/v1/integrations/{id}/discoveraccepts:
{
"resourceType": "repositories",
"filter": {
"namePattern": "team/*"
}
}
- Successful responses return
DiscoverIntegrationResponsewith the normalizedresourceType, the orderedsupportedResourceTypes, and the discoveredresources. - Unsupported discovery requests return
400 Bad Requestwith the supported resource types for that provider. - Missing or cross-tenant integration IDs return
404 Not Found.
Discovery-Capable Providers
- OCI registries:
repositories,tags - SCM:
projects,repositories - CI/CD:
jobs,pipelines - Feed mirror, object-storage, and secrets/runtime providers currently expose health/test flows only
Credential Resolution
- Integration secrets are supplied as AuthRef URIs such as
authref://vault/gitlab#access-token - The runtime resolver is Vault-backed; there is no product-path stub resolver in the shipped service
- Registry connectors accept bearer tokens and
username:passwordorusername:tokensecrets for Basic auth-compatible registries
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.
Related Documentation
- Integrations Module Dossier
- Integrations API Reference
- CI/CD Gate Flow
- Authority Architecture
- Scanner Architecture
AI Code Guard Standalone Run
The Integrations WebService also hosts deterministic, standalone execution for AI Code Guard checks.
API Surface
- Endpoint:
POST /api/v1/integrations/ai-code-guard/run - Mapped in:
src/Integrations/StellaOps.Integrations.WebService/IntegrationEndpoints.cs - Service contract:
IAiCodeGuardRunServiceinsrc/Integrations/StellaOps.Integrations.WebService/AiCodeGuard/AiCodeGuardRunService.cs
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:
secrets/enableSecretsScanattribution/enableAttributionChecklicense/enableLicenseHygienemaxFindingsallowedSpdxLicenses/licenseAllowListcustomSecretPatterns/secretPatterns
The loader is deterministic and rejects unsupported keys or invalid values with explicit FormatException errors.
Scanning Behavior
AiCodeGuardRunService adds deterministic checks for:
- Secrets (built-in + optional custom regex patterns)
- Attribution markers
- SPDX license presence / allow-list validation
Output ordering is stable:
- Severity descending
- Path ordinal
- Line number
- Rule ID
- Finding ID
Contracts
New contracts in src/Integrations/__Libraries/StellaOps.Integrations.Contracts/AiCodeGuardRunContracts.cs:
AiCodeGuardRunRequestAiCodeGuardSourceFileAiCodeGuardRunConfigurationAiCodeGuardRunResponse
Test Coverage
Behavior is validated in src/Integrations/__Tests/StellaOps.Integrations.Tests/AiCodeGuardRunServiceTests.cs:
- Deterministic repeated output
- YAML configuration application and max-finding truncation
- Invalid YAML validation failure
Run the adjacent suite with:
dotnet test src/Integrations/__Tests/StellaOps.Integrations.Tests/StellaOps.Integrations.Tests.csproj \
-p:BuildProjectReferences=false --no-restore
