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:
gRPC sandbox: Plugins run in separate processes with limited access
Service Registry: Plugins access QNTX via controlled ServiceRegistry interface
No direct access: Plugins cannot access QNTX internals, only exposed services
Failure Handling
Optional by default: QNTX runs in minimal core mode without any plugins
Warning on failure: If enabled plugin fails to load, log warning and continue without it
Runtime error notification: Plugin errors broadcast to UI for user awareness
Rationale: Minimal core philosophy - plugins are optional enhancements, not essential features
Versioning
Strict semver: Plugins declare required QNTX version using semver constraints
Validation at registration: Registry checks compatibility before loading plugin
Breaking changes in QNTX API trigger major version bump
HTTP Routing
Namespace enforcement: All plugin routes must be /api/<domain>/*
No conflicts by design: Domain namespaces prevent routing collisions
Example: code plugin owns all /api/code/* routes
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
Code domain (qntx-code-plugin) serves as reference implementation
First-party plugins maintained by QNTX team follow same patterns as third-party plugins
Implementation Plan
Phase 1: Restructure to plugin/ (Completed - PR #130)
✅ DomainPlugin interface and Registry
✅ ServiceRegistry for dependency injection
✅ Moved domains → plugin, code → qntx-code
✅ HTTP and WebSocket handler registration
Phase 2: Decouple Server Handlers (Completed - PR #134)
✅ Migrated gopls lifecycle to qntx-code plugin
✅ Server dynamically registers plugin WebSocket handlers