ADR-001: Domain Plugin Architecture

Status: Accepted Date: 2026-01-04 Deciders: QNTX Core Team

Context

QNTX initially had software development functionality (git ingestion, GitHub integration, gopls language server, code editor) tightly coupled to the core. This created challenges:

  1. Scope Creep: Core repository accumulated domain-specific code (code, biotech, finance, etc.)
  2. Coupling: Domain logic mixed with core attestation/graph infrastructure
  3. Maintenance: Changes to one domain risked breaking others
  4. Third-Party Extensions: No mechanism for private/external domain implementations

Decision

We adopt a domain plugin architecture where functional domains are implemented as plugins with:

Minimal Core Philosophy

QNTX core is minimal and runs without any plugins:

This ensures QNTX core remains focused on infrastructure, not domain logic.

Plugin Boundary

Unified Plugin Model

All plugins are external - standalone binaries loaded at runtime via gRPC:

From the Registry's perspective, all plugins are identical:

// All plugins registered the same way
registry.Register(externalProxy)  // Loaded via gRPC from ~/.qntx/plugins/

Plugin characteristics:

Interface Contract

type DomainPlugin interface {
    Metadata() Metadata                                              // Plugin info, version
    Initialize(ctx context.Context, services ServiceRegistry) error  // Lifecycle
    Shutdown(ctx context.Context) error
    Commands() []*cobra.Command                                      // CLI integration
    RegisterHTTP(mux *http.ServeMux) error                          // HTTP API
    RegisterWebSocket() (map[string]WebSocketHandler, error)        // Real-time features
    Health(ctx context.Context) HealthStatus                         // Monitoring
}

Security Model

Failure Handling

Versioning

HTTP Routing

Consequences

Positive

Isolation: Domain failures don't cascade to core or other domains ✅ Scalability: Each plugin can be developed/deployed independently ✅ Third-party: External developers can build private plugins (finance, legal, etc.) ✅ Process isolation: Plugin crashes don't crash QNTX server ✅ Language agnostic: gRPC enables plugins in any language (Go, Python, Rust)

Negative

⚠️ gRPC overhead: Extra hop for plugin calls vs in-process ⚠️ Complexity: More moving parts (multiple processes, config files, gRPC) ⚠️ No shared state: Plugins can't share in-memory caches (intentional isolation)

Neutral

Implementation Plan

Phase 1: Restructure to plugin/ (Completed - PR #130)

Phase 2: Decouple Server Handlers (Completed - PR #134)

Phase 3: Plugin Discovery and Optional Loading (Completed - PR #136)

Phase 4: Extract to Separate Repository (Planned - Issue #135)

Alternatives Considered

Monolithic with Feature Flags

Microservices per Domain

Lua/WebAssembly Scripting

Related