Errata
Operations

Self-hosting

Run the API, MCP adapter, and ETL worker with Bun and containers.

Install and verify

bun install
bun run verify

Local development

Run the MCP stdio adapter:

bun run dev:mcp

Run REST and Streamable HTTP MCP locally:

bun run dev:api

Development is anonymous on localhost. Production fails closed unless security settings and a policy-approved release are present.

Production API

NODE_ENV=production \
ERRATA_ALLOWED_HOSTS=api.example.com \
ERRATA_API_KEYS='replace-with-a-long-random-secret' \
ERRATA_OPENAPI_SHA256='sha256:reviewed-openapi-digest' \
bun run start:api

The hosted REST contract is dated with Errata-Version: 2026-08-26 and published at /openapi.json. Bind ERRATA_OPENAPI_SHA256 to the reviewed document in production; startup fails if the running contract drifts. The standard production bounds are a 65,536-byte JSON body, a 15-second request timeout, 64 active protected requests per instance, and 6 per credential.

Build the non-root API and ETL images:

docker build -t errata:0.9.2 .
docker build -f Dockerfile.worker -t errata-worker:0.9.2 .

Route TLS traffic to the platform-provided PORT. Use /livez for liveness and /readyz for release-aware readiness.

Release selection

The default local runtime loads data/catalog/releases/current.json. To serve one standalone release database:

ERRATA_RELEASE_DB=/absolute/path/release.sqlite bun run start:mcp

Production should use the pointer-bound release bundle. Set ERRATA_EXPECTED_RELEASE_ID only for an intentionally frozen deployment.

Documentation app

The Fumadocs site is isolated under docs/ and uses Bun for dependency management:

cd docs
bun install
bun run build
bun run start

Deploy it independently from the API so Next.js dependencies and search indexing never enter the MCP runtime image.