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:
- 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 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/*.yamland are discoverable by env/file gating. checks[].run.execexecutes CLI commands;checks[].parsedefines 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