12 KiB
12 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:
- Wizard defaults to last used endpoint, auth mode, network settings
- Secrets are never auto-reused (explicit confirmation required)
- 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 DoctorCheckResult {
checkType: string;
status: "pass" | "warn" | "fail";
message: string;
details: Record<string, any>;
suggestions: string[];
runAt: DateTime;
durationMs: number;
}
interface DoctorReport {
integrationId: UUID;
overallStatus: "healthy" | "degraded" | "unhealthy";
checks: DoctorCheckResult[];
generatedAt: DateTime;
}
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