Proposed
QNTX has no search infrastructure. Plugins that need to find things — search documents by keyword, query attestations beyond exact field matching — have no service to call.
Fuzzy-ax exists as a workaround: approximate string matching over attestation queries. It's fragile, slow on large datasets, and conflates query parsing with search. The decision to deprecate fuzzy-ax has already been taken.
MeiliSearch is a proven full-text search engine with typo tolerance, faceted filtering, and sub-millisecond queries. Rather than building a custom search layer, QNTX should expose MeiliSearch through the same plugin-provided service pattern established by LLMService (ADR-014).
Add SearchService as a plugin-provided gRPC service. A new plugin — qntx-meili (Rust) — owns the MeiliSearch instance and registers as the search backend. Core routes search calls to the provider. Consumers call SearchService.Search without knowing or caring about the underlying engine.
qntx-meili is a dedicated search provider plugin, separate from any domain plugin. Domain plugins are consumers of SearchService, not providers. qntx-meili lives in qntx-plugins/qntx-meili/ in this repository.
This is the second plugin-provided service on ServiceRegistry, after LLMService.
plugin/grpc/protocol/search.proto
service SearchService {
rpc Search(SearchRequest) returns (SearchResponse);
rpc IndexDocuments(IndexDocumentsRequest) returns (IndexDocumentsResponse);
rpc DeleteDocuments(DeleteDocumentsRequest) returns (DeleteDocumentsResponse);
}
message SearchRequest {
string query = 1; // search query text
string index = 2; // which index to search
int32 top_k = 3; // max results to return
bytes filters = 4; // filter expression as JSON — interpreted by the provider
}
message SearchResponse {
repeated SearchHit hits = 1;
int32 total = 2; // total matches (before top_k limit)
int32 processing_ms = 3;
}
message SearchHit {
string id = 1;
float score = 2;
bytes document = 3; // indexed content as JSON
}
message IndexDocumentsRequest {
string index = 1; // index name (created implicitly if needed)
repeated bytes documents = 2; // documents as JSON — schema is qntx-meili's concern
}
message IndexDocumentsResponse {
int32 accepted = 1; // number of documents accepted for indexing
}
message DeleteDocumentsRequest {
string index = 1;
repeated string ids = 2; // document IDs to remove
}
message DeleteDocumentsResponse {
int32 deleted = 1;
}
Domain plugins decide what gets indexed and when — they push JSON documents and search by query. qntx-meili decides how — index creation, schema detection, field configuration, async task management, and all MeiliSearch-specific mechanics. The proto is engine-agnostic: documents in, results out.
Any plugin that needs full-text search over indexed documents. A plugin calls services.Search() with a query and index name, gets ranked results back. The plugin does not need a MeiliSearch client or any knowledge of the search engine.
QNTX core is also a future consumer — AX queries can route through SearchService for full-text matching instead of fuzzy string approximation, providing the path to fuzzy-ax deprecation.
Fuzzy-ax is string-level approximation over attestation fields. SearchService replaces it with actual search infrastructure — typo tolerance, relevance ranking, faceted filtering. The deprecation is incremental: new query paths use SearchService, existing fuzzy-ax paths are removed as consumers migrate. Not a priority now, but part of the plan.
Same pattern as LLMService: SearchServer in core holds a reference to the provider backend. Provider plugins register via SetService. Callers go through services.Search() on ServiceRegistry.
If a plugin calls services.Search() before qntx-meili has initialized, the call fails. The plugin should fail its own initialization and be restarted until SearchService is available.
qntx-meili registers a panel glyph for index management visibility. Shows indexes, document counts, indexing status. Without this, the search infrastructure is a black box.
qntx-meili is a standalone Rust plugin — search infrastructure lives in its own processqntx-meili's concern — domain plugins push documents, the provider handles the rest