Orion · 1.0.0

Deterministic, replayable index operations for any full-text engine.

Orion is not a search engine. It sits on Elasticsearch, SolrCloud, OpenSearch and Meilisearch and owns the part everyone hand-rolls and gets wrong: the index lifecycle. Schema as code, drift detection, deterministic migration plans, zero-downtime reindex by replaying a transactional outbox, versioned indices behind an alias, and a signed receipt for every operation, with a thin hybrid query layer on top, for any PHP application. Every engine adapter passes the same conformance suite, on 8 engine versions in CI.

$ bin/orion apply products --schema=products.yaml --bootstrap=orion.php --json
$ bin/orion reindex products --schema=products.yaml --dry-run
$ bin/orion outbox:drain && bin/orion verify --json

Elasticsearch · 9.5 / 8.19

orion-search/elasticsearch

new ElasticsearchEngine($client) on elasticsearch/elasticsearch; strict mappings, externally versioned writes.

/engines/elasticsearch packages/elasticsearch

SolrCloud · 10 / 9.11

orion-search/solr

SolrEngine on solarium/solarium, with Orion's configset; ORION_ENGINE=solr in the module.

packages/solr

OpenSearch · 3.9 / 2.19

orion-search/opensearch

OpenSearchEngine::connect($url); vectors through the bundled k-NN plugin, hybrid fusion in core.

/engines/opensearch packages/opensearch

Meilisearch · 1.56 / 1.13

orion-search/meilisearch

MeilisearchEngine::connect($url, $apiKey); schema as settings, versions kept by Orion, aliases emulated by core.

/engines/meilisearch packages/meilisearch

Why Orion

01

The engine is a disposable projection

Your database is the source of truth. The outbox row commits with your entity write, on the same connection (PostgreSQL, MySQL and SQLite through PDO, or the host's own), so a reindex is a replay, not a reconciliation.

02

Deterministic lifecycle, honest ranking

Plan, apply, reindex and swap are dry-runnable and reproducible, each with a signed receipt. Result order is not deterministic, and Orion never claims it is.

03

Proven on every engine

Every adapter passes the same engine conformance suite, with the tenancy isolation, determinism and fault-injection harnesses, on 8 engine versions in CI.

04

Dumb adapters, smart neutral core

Diffing, reindex, alias swap, replay and fusion live once in core. Each adapter is its own package with its own client, and bin/check-imports keeps it that way.

Features

The index lifecycle, owned once, in neutral code.

Each area is specified in the documentation and implemented by orion-search/core or one of the other 10 packages on its version line.

schema

Schema as code

Declare an index in PHP or in an api/<name>/search.yaml manifest. Every change is classified as additive or breaking, and an unrecognised one fails closed as breaking.

/docs/spec/orion-spec/
plan

Plans and drift

A plan is a pure diff of the declared schema against the live index. Additive changes apply in place; breaking ones never touch a live index and route to a reindex. orion drift reports where they part ways.

/docs/spec/orion-spec/
reindex

Zero-downtime reindex

Versioned physical indices behind a stable alias. A reindex replays the outbox into the next version, version-stamped writes converge, and the alias swaps atomically.

/docs/spec/orion-spec/
outbox

Transactional outbox

Record into the outbox as the last statement of your transaction, on your connection. Offsets stay in commit order; the drain retries and keeps dead letters.

/docs/spec/revision/
receipts

Signed receipts

Every apply and reindex issues an Ed25519-signed receipt in a hash chain. orion verify walks the chain; an auditor verifies with public keys only.

/docs/spec/revision/
tenancy

Tenancy on a shared index

An explicit choice at boot, with no default. Under a resolver the tenant filter is injected beneath every query, the escape hatch included; the tenant can come from the Polaris token.

/docs/spec/orion-spec/
query

A thin hybrid query layer

A neutral query AST for the common case, keyword plus vector with deterministic reciprocal rank fusion in core, the engine's native query for the rest, and a typed UnsupportedClause instead of a silent wrong result.

/docs/spec/orion-spec/
psr15

Endpoint and CLI

The search: endpoints as a PSR-15 middleware with RFC 9457 problems, and bin/orion for plan, apply, reindex, drift, verify and the outbox drain, in YAML or deterministic JSON.

/docs/packages/psr15/
mcp

An agent surface

compile_query, search, list_indices, describe_index, capabilities, plan, apply, reindex as tools, compile_query first: the native request search() would send, never sent. apply and reindex preview until confirmed.

/docs/spec/orion-spec/

Origin

Orion was specified in June 2026 as a search module for Univeros. On October 25, 2026 it was re-cut to be framework-agnostic from the start, modelled on polaris-core: a framework-free core with ports and working defaults, host integrations as packages, and the Univeros module, univeros/orion, in the same monorepo (its documentation), proven by the same CI run. 1.0.0 was tagged on October 27, 2026, with every work package of the specification done.

Version 1.0.0

Every package shares one version line, 1.x, tagged v1.0.0 in the monorepo. The per-package read-only repositories and their Packagist registration are the next step; until then, install from a clone with path repositories, as examples/univeros does. Roadmap · Security

Get started

Put Orion on your engine.

Elasticsearch, SolrCloud, OpenSearch, Meilisearch, from any PHP application, with storage on PostgreSQL, MySQL, SQLite or the Univeros module.