Skip to main content

Run Spire

Spire is the Suite's authoring backend: a Python FastAPI service (managed with uv) that holds everything Scribe and Slate store — documentation content and coverage, stale alerts, style guides, the LLM gateway with its credentials, budgets and audit log, and Slate sites and builds. It keeps all authoring data in its own authoring schema of the Apiome database, so the open-source product never carries an authoring table or route.

Start it​

cd spire
uv sync --extra dev
uv run spire-migrate # apply migrations (see below)
uv run uvicorn app.main:app --app-dir src --reload --port 8099

yarn workspace @suite/spire dev runs the same server, and yarn workspace @suite/spire migrate the same migrations. Spire listens on port 8099; GET /health answers without authentication. The studio reaches it through SPIRE_API_BASE_URL (http://spire:8099/v1 in Docker).

Set the variables in the environment reference. Two rules catch most failed deployments:

  • BETTER_AUTH_SECRET must be byte-identical to the studio's: every call the studio makes carries a bearer signed with it, and Spire verifies against BETTER_AUTH_SECRET and then JWT_SECRET.
  • NEXTAUTH_SECRET must not be set at all. Spire refuses to start while it is present — even blank — so a pre-cutover value left in an environment file is found at boot rather than as a silent 401.

In production (APP_ENV=production) a missing secret stops the service. Outside production Spire falls back to a built-in insecure value and logs a warning.

Migrations​

Spire ships a Flyway-compatible runner. Scripts are migrations/V<nnnn>__<name>.sql, applied in order with a CRC32 checksum recorded in public.flyway_schema_history:

uv run spire-migrate # apply what is pending
uv run spire-migrate status # what is applied, what is pending
uv run spire-migrate --dry-run # print without applying
uv run spire-migrate repair # fix a checksum after an edited script
MigrationCreates
V0002–V0004Tenant LLM credentials, settings, usage, budget, audit log and idempotency keys
V0005Target provenance, dependency edges and documentation anchors
V0006Documentation content, style guides and coverage snapshots
V0007The authoring schema; earlier tables move into it
V0008Stale alerts
V0009Slate sites and builds
V0010The style guide's tone preset
V0011Scribe bulk-generation jobs

Run the migrations against the same database SPIRE_DATABASE_URL names, after Apiome's own migrations; Spire's schema has no foreign keys into Apiome's tables (it references versions by id), so the two can be applied independently.

Authentication and entitlement​

Every route except /health and the hosted reader surface needs Authorization: Bearer <JWT> (the studio's service bearer, see Authentication) or an X-API-Key. The caller must also hold the authoring entitlement, resolved user override → tenant override → plan bundle (see Licensing). SPIRE_AUTHORING_GATING_ENABLED=false turns the flag check off for a development database without turning authentication off.

A two-factor elevation gate exists (403 {"reason": "two_factor_required"}), but the list of routes that require it is empty today.

LLM providers​

The gateway stores one API key per provider per tenant, encrypted with SPIRE_CREDENTIAL_ENCRYPTION_KEY; reads only ever return a …last4 fingerprint. Users set the active provider, model and temperature from Scribe settings.

ProviderStatus
anthropicSupported
openaiSupported
azure_openaiDeclared, no adapter yet
ollamaDeclared, no adapter yet — the studio calls Ollama directly for the canvas AI buttons (OLLAMA_BASE_URL)

Budgets (PUT /v1/llm/{tenant}/budget), usage and the audit log are per tenant; the endpoint groups are listed in the Spire API reference.

Tests and the corpus gate​

uv run --extra dev ruff check .
uv run --extra dev pytest # DB tests skip unless SPIRE_DATABASE_URL is set
uv run --extra dev python -m app.llm.corpus

The last command is the AI evaluation corpus report: a per-format regression gate over citation and example validation that the Suite workflow runs on every push.