Files
git.stella-ops.org/docs/modules/release-orchestrator/modules/integration-hub.md
2026-01-13 18:53:39 +02:00

13 KiB

INTHUB: Integration Hub

Purpose: Central management of all external integrations (SCM, CI, registries, vaults, targets).

Modules

Module: integration-manager

Aspect Specification
Responsibility CRUD for integration instances; plugin type registry
Dependencies plugin-registry, authority (for credentials)
Data Entities Integration, IntegrationType, IntegrationCredential
Events Produced integration.created, integration.updated, integration.deleted, integration.health_changed
Events Consumed plugin.registered, plugin.unregistered

Key Operations:

CreateIntegration(type, name, config, credentials) → Integration
UpdateIntegration(id, config, credentials) → Integration
DeleteIntegration(id) → void
TestConnection(id) → ConnectionTestResult
DiscoverResources(id, resourceType) → Resource[]
GetIntegrationHealth(id) → HealthStatus
ListIntegrations(filter) → Integration[]

Integration Entity:

interface Integration {
  id: UUID;
  tenantId: UUID;
  type: string;                    // "scm.github", "registry.harbor"
  name: string;                    // user-defined name
  config: IntegrationConfig;       // type-specific config
  credentialId: UUID;              // reference to vault
  healthStatus: HealthStatus;
  lastHealthCheck: DateTime;
  createdAt: DateTime;
  updatedAt: DateTime;
}

interface IntegrationConfig {
  endpoint: string;
  authMode: "token" | "oauth" | "mtls" | "iam";
  timeout: number;
  retryPolicy: RetryPolicy;
  customHeaders?: Record<string, string>;
  // Type-specific fields added by plugin
  [key: string]: any;
}

Module: connection-profiles

Aspect Specification
Responsibility Default settings management; "last used" pattern
Dependencies integration-manager
Data Entities ConnectionProfile, ProfileTemplate

Behavior: When user adds a new integration instance:

  1. Wizard defaults to last used endpoint, auth mode, network settings
  2. Secrets are never auto-reused (explicit confirmation required)
  3. User can save as named profile for reuse

Profile Entity:

interface ConnectionProfile {
  id: UUID;
  tenantId: UUID;
  name: string;                    // "Production GitHub"
  integrationType: string;
  defaultConfig: Partial<IntegrationConfig>;
  isDefault: boolean;
  lastUsedAt: DateTime;
  createdBy: UUID;
}

Module: connector-runtime

Aspect Specification
Responsibility Execute plugin connector logic in controlled environment
Dependencies plugin-loader, plugin-sandbox
Protocol gRPC (preferred) or HTTP/REST

Connector Interface (implemented by plugins):

service Connector {
  // Connection management
  rpc TestConnection(TestConnectionRequest) returns (TestConnectionResponse);
  rpc GetHealth(HealthRequest) returns (HealthResponse);

  // Resource discovery
  rpc DiscoverResources(DiscoverRequest) returns (DiscoverResponse);
  rpc ListRepositories(ListReposRequest) returns (ListReposResponse);
  rpc ListBranches(ListBranchesRequest) returns (ListBranchesResponse);
  rpc ListTags(ListTagsRequest) returns (ListTagsResponse);

  // Registry operations
  rpc ResolveTagToDigest(ResolveRequest) returns (ResolveResponse);
  rpc FetchManifest(ManifestRequest) returns (ManifestResponse);
  rpc VerifyDigest(VerifyRequest) returns (VerifyResponse);

  // Secrets operations
  rpc GetSecretsRef(SecretsRequest) returns (SecretsResponse);
  rpc FetchSecret(FetchSecretRequest) returns (FetchSecretResponse);

  // Workflow step execution
  rpc ExecuteStep(StepRequest) returns (stream StepResponse);
  rpc CancelStep(CancelRequest) returns (CancelResponse);
}

Request/Response Types:

message TestConnectionRequest {
  string integration_id = 1;
  map<string, string> config = 2;
  string credential_ref = 3;
}

message TestConnectionResponse {
  bool success = 1;
  string error_message = 2;
  map<string, string> details = 3;
  int64 latency_ms = 4;
}

message ResolveRequest {
  string integration_id = 1;
  string image_ref = 2;  // "myapp:v2.3.1"
}

message ResolveResponse {
  string digest = 1;     // "sha256:abc123..."
  string manifest_type = 2;
  int64 size_bytes = 3;
  google.protobuf.Timestamp pushed_at = 4;
}

Module: doctor-checks

Aspect Specification
Responsibility Integration health diagnostics; troubleshooting
Dependencies integration-manager, connector-runtime

Doctor Check Types:

Check Purpose Pass Criteria
Connectivity Can reach endpoint TCP connect succeeds
TLS Certificate valid Chain validates, not expired
Authentication Credentials valid Auth request succeeds
Authorization Permissions sufficient Required scopes present
Version API version supported Version in supported range
Rate Limit Quota available >10% remaining
Latency Response time acceptable <5s p99

Doctor Check Output:

interface DoctorHowToFix {
  summary: string;
  commands: string[];
}

interface DoctorCheckResult {
  checkType: string;
  status: "pass" | "warn" | "fail";
  message: string;
  details: Record<string, any>;
  suggestions: string[];
  howToFix?: DoctorHowToFix;
  runAt: DateTime;
  durationMs: number;
}

interface DoctorReport {
  integrationId: UUID;
  overallStatus: "healthy" | "degraded" | "unhealthy";
  checks: DoctorCheckResult[];
  evidenceLog?: {
    jsonlPath: string;
    dssePath?: string;
  };
  generatedAt: DateTime;
}

Doctor JSON output for CLI/agents uses how_to_fix (snake case) as the alias of howToFix to preserve verbatim fix commands. Doctor fix executes only non-destructive commands; destructive steps are manual and never executed by Doctor. Evidence logs include doctor_command, and DSSE summaries include the same operator-invoked command note.

Declarative Packs (YAML):

  • Packs live in plugins/doctor/*.yaml and are discoverable by env/file gating.
  • checks[].run.exec executes CLI commands; checks[].parse defines pass/fail.
  • checks[].how_to_fix.commands[] must be printed verbatim and remain deterministic.

Sample manifest:

  • docs/benchmarks/doctor/doctor-plugin-release-orchestrator-gitlab.yaml

Evidence Artifacts:

  • JSONL evidence log per run (local by default).
  • Optional DSSE summary for audit export.

Cache Eviction Policies

Integration health status and connector results are cached to reduce load on external systems. All caches MUST have bounded size and TTL-based eviction:

Cache Type Purpose TTL Max Size Eviction Strategy
Health Checks Integration health status 5 minutes 1,000 entries Sliding expiration
Connection Tests Test connection results 2 minutes 500 entries Sliding expiration
Resource Discovery Discovered resources (repos, tags) 10 minutes 5,000 entries Sliding expiration
Tag Resolution Tag → digest mappings 1 hour 10,000 entries Absolute expiration

Implementation:

public class IntegrationHealthCache
{
    private readonly MemoryCache _cache;

    public IntegrationHealthCache()
    {
        _cache = new MemoryCache(new MemoryCacheOptions
        {
            SizeLimit = 1_000  // Max 1,000 integration health entries
        });
    }

    public void CacheHealthStatus(Guid integrationId, HealthStatus status)
    {
        _cache.Set(integrationId, status, new MemoryCacheEntryOptions
        {
            Size = 1,
            SlidingExpiration = TimeSpan.FromMinutes(5)  // 5-minute TTL
        });
    }

    public HealthStatus? GetCachedHealthStatus(Guid integrationId)
        => _cache.Get<HealthStatus>(integrationId);
}

Reference: See Implementation Guide for cache implementation patterns.


Integration Types

The following integration types are supported (via plugins):

SCM Integrations

Type Plugin Capabilities
scm.github Built-in repos, branches, commits, webhooks, status
scm.gitlab Built-in repos, branches, commits, webhooks, pipelines
scm.bitbucket Plugin repos, branches, commits, webhooks
scm.azure_repos Plugin repos, branches, commits, pipelines

Registry Integrations

Type Plugin Capabilities
registry.harbor Built-in repos, tags, digests, scanning status
registry.ecr Plugin repos, tags, digests, IAM auth
registry.gcr Plugin repos, tags, digests
registry.dockerhub Plugin repos, tags, digests
registry.ghcr Plugin repos, tags, digests
registry.acr Plugin repos, tags, digests

Vault Integrations

Type Plugin Capabilities
vault.hashicorp Built-in KV, transit, PKI
vault.aws_secrets Plugin secrets, IAM auth
vault.azure_keyvault Plugin secrets, certificates
vault.gcp_secrets Plugin secrets, IAM auth

CI Integrations

Type Plugin Capabilities
ci.github_actions Built-in workflows, runs, artifacts, status
ci.gitlab_ci Built-in pipelines, jobs, artifacts
ci.jenkins Plugin jobs, builds, artifacts
ci.azure_pipelines Plugin pipelines, runs, artifacts

Router Integrations (for Progressive Delivery)

Type Plugin Capabilities
router.nginx Plugin upstream config, reload
router.haproxy Plugin backend config, reload
router.traefik Plugin dynamic config
router.aws_alb Plugin target groups, listener rules

Database Schema

-- Integration types (populated by plugins)
CREATE TABLE release.integration_types (
    id TEXT PRIMARY KEY,                    -- "scm.github"
    plugin_id UUID REFERENCES release.plugins(id),
    display_name TEXT NOT NULL,
    description TEXT,
    icon_url TEXT,
    config_schema JSONB NOT NULL,           -- JSON Schema for config
    capabilities TEXT[] NOT NULL,           -- ["repos", "webhooks", "status"]
    created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Integration instances
CREATE TABLE release.integrations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES tenants(id),
    type_id TEXT NOT NULL REFERENCES release.integration_types(id),
    name TEXT NOT NULL,
    config JSONB NOT NULL,
    credential_ref TEXT NOT NULL,           -- vault reference
    health_status TEXT NOT NULL DEFAULT 'unknown',
    last_health_check TIMESTAMPTZ,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    created_by UUID NOT NULL REFERENCES users(id),
    UNIQUE(tenant_id, name)
);

-- Connection profiles
CREATE TABLE release.connection_profiles (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES tenants(id),
    name TEXT NOT NULL,
    integration_type TEXT NOT NULL,
    default_config JSONB NOT NULL,
    is_default BOOLEAN NOT NULL DEFAULT false,
    last_used_at TIMESTAMPTZ,
    created_by UUID NOT NULL REFERENCES users(id),
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    UNIQUE(tenant_id, name)
);

-- Doctor check history
CREATE TABLE release.doctor_checks (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    integration_id UUID NOT NULL REFERENCES release.integrations(id),
    check_type TEXT NOT NULL,
    status TEXT NOT NULL,
    message TEXT,
    details JSONB,
    duration_ms INTEGER NOT NULL,
    run_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_doctor_checks_integration ON release.doctor_checks(integration_id, run_at DESC);

API Endpoints

See API Documentation for full specification.

GET    /api/v1/integration-types              # List available types
GET    /api/v1/integration-types/{type}       # Get type details

GET    /api/v1/integrations                   # List integrations
POST   /api/v1/integrations                   # Create integration
GET    /api/v1/integrations/{id}              # Get integration
PUT    /api/v1/integrations/{id}              # Update integration
DELETE /api/v1/integrations/{id}              # Delete integration
POST   /api/v1/integrations/{id}/test         # Test connection
GET    /api/v1/integrations/{id}/health       # Get health status
POST   /api/v1/integrations/{id}/doctor       # Run doctor checks
GET    /api/v1/integrations/{id}/resources    # Discover resources

GET    /api/v1/connection-profiles            # List profiles
POST   /api/v1/connection-profiles            # Create profile
GET    /api/v1/connection-profiles/{id}       # Get profile
PUT    /api/v1/connection-profiles/{id}       # Update profile
DELETE /api/v1/connection-profiles/{id}       # Delete profile