Skip to main content

Ershu API

简体中文

Ershu API is the HTTP backend for the Ershu web application and other HTTP clients. It is intended for people who operate Ershu and contributors working on its web boundary. The service handles account setup and login, project access, analysis run control, documents, search, chat, administration, browser sessions, and streamed responses.

Repository analysis runs in Ershu Worker. This service queues and controls that work, then serves the stored results. It does not import Worker or MCP code.

What the API owns

Area Responsibility
Authentication Initial administrator setup, OPAQUE login, access and refresh tokens, session cookies, logout, and login rate limiting
Browser security CORS, origin checks, CSRF protection, production HTTPS checks, and proxy header handling
Projects Projects, repositories, members, groups, directory groups, grants, repository credentials, and access rules
Analysis runs Create, list, cancel, retry, resume, and follow up on runs; read snapshots, usage, final results, and event streams
Documents and context Document views, imports and exports, project context, code context, graph queries, and search
Chat Private project chat sessions, streamed answers, and source citations
Administration Users, audit logs, model channels, dependency sources, vault credentials, system settings, and maintenance operations
Repository triggers Signed webhooks and a separate scheduled polling process

The API can rebuild search entries from data already stored in Ershu and expose maintenance operations. Ershu Worker owns repository analysis and the generation of project documents, code facts, and knowledge relationships.

Where it fits

Frontend and HTTP clients
           |
           v
       Ershu API --------------> PostgreSQL
           |                     Redis
           |                     Milvus
           |
           +---- queued runs ---> Ershu Worker

Ershu MCP uses shared Core services and storage. MCP traffic does not pass
through Ershu API.
Component Relationship to this repository
ershu-core Required Python package for shared data models, permissions, queries, queue state, and database migrations
ershu-worker Consumes queued runs and performs repository analysis and generation work
ershu-mcp Publishes project context tools through shared Core services; it is not an API route
frontend Uses the public HTTP, cookie, CSRF, and streaming contracts from this service
ershu Deployment repository that pins compatible component versions and runs the complete system

Each component is released independently. The deployment repository selects the exact set of component versions used together.

Install and commands

Item Value
Python distribution ershu-api
Python requirement Python 3.14 or newer
HTTP service ershu-api
Scheduled repository poller ershu-api-poller
Database migration command ershu-db, provided by ershu-core
API prefix /api/v1

Install the API as part of a tested component set through the ershu installer package:

pip install "ershu[api]"

Projects that depend on the API package directly can pin the component with UV:

uv add "ershu-api==1.0.0.post20260812"

Requirements

Development requires:

  • Python 3.14 or newer
  • UV
  • A compatible ershu-core release

Running the service also requires PostgreSQL, Redis, and Milvus. PostgreSQL stores application state, Redis backs login rate limiting and the poller lease, and Milvus holds vectors used by semantic search.

Run from source

Install the locked runtime dependencies:

uv sync --locked

Copy .env.example to .env. Generate three independent values for SECRET_KEY, ENCRYPTION_KEY, and MCP_KEY_PEPPER:

uv run python -c "import secrets; print(*(secrets.token_urlsafe(48) for _ in range(3)), sep='\n')"

Use one output line for each setting. Do not reuse a value. The example placeholders are rejected at startup, and .env must not be committed.

Start PostgreSQL, Redis, and Milvus, then apply the database migrations:

uv run ershu-db upgrade head

Start the API:

uv run ershu-api

The development server listens on 127.0.0.1:8000 by default and reloads when source files change. OpenAPI pages are available only in development:

  • http://127.0.0.1:8000/docs
  • http://127.0.0.1:8000/redoc

Health checks

The root and versioned health endpoints report whether the HTTP process can respond:

curl -fsS http://127.0.0.1:8000/health
curl -fsS http://127.0.0.1:8000/api/v1/health

Both return {"status":"ok"}. Check PostgreSQL and Milvus separately:

curl -fsS http://127.0.0.1:8000/api/v1/health/dependencies

The dependency response is degraded when either check fails. It does not test Redis.

Configuration

The service reads .env from its working directory. .env.example lists the supported deployment settings.

Group Settings Purpose
Runtime ENVIRONMENT, LOG_LEVEL, HOST, PORT Runtime mode, logging, and listener address
Data services DATABASE_URL, database pool settings, REDIS_URL, MILVUS_URI, MILVUS_TOKEN, MILVUS_DB_NAME Application state, rate limiting, polling lease, and vector search
Service secrets SECRET_KEY, ENCRYPTION_KEY, MCP_KEY_PEPPER Sessions, encrypted stored credentials, and MCP key hashing
Browser sessions token lifetimes, cookie names, SESSION_COOKIE_SECURE, SESSION_COOKIE_SAMESITE, CORS_ORIGINS Login state and browser request policy
Reverse proxy PROXY_HEADERS, FORWARDED_ALLOW_IPS Forwarded scheme and client information from trusted proxies
Repository access repository cache path, trusted local paths, Git host and protocol controls, provider tokens Repository checkout and context access
Scheduled polling POLLER_INTERVAL_SECONDS, POLLER_LEASE_SECONDS, POLLER_BATCH_SIZE Poll frequency, ownership lease, and batch size
Maintenance and search run lease, retention count, and search batch size Queue recovery, retained history, and index maintenance

LLM, embedding, and reranker channels are managed through the administration endpoints. Their API keys are encrypted before storage and do not belong in .env.

Some non-secret operational settings can be overridden in the database through the system settings endpoints. Environment values remain the startup defaults.

OPAQUE server setup

Development can leave OPAQUE_SERVER_SETUP empty. On first startup, the API creates an OPAQUE server setup and stores it encrypted in PostgreSQL.

Production requires an explicit, stable value. Generate it once:

uv run python -c "import base64, opaque_ke_py; print(base64.urlsafe_b64encode(opaque_ke_py.server_setup().to_bytes()).decode('ascii').rstrip('='))"

Store the output in the deployment secret store. Changing this value prevents existing OPAQUE password records from being used.

Repository polling

Repositories with polling enabled need a separate long-running process:

uv run ershu-api-poller

Cron expressions use UTC. Poller instances coordinate through a renewable Redis lease, so more than one instance can run without processing the same schedule at once. A single cycle can be run manually:

uv run ershu-api-poller --once

The API and poller must use the same PostgreSQL database, Redis instance, and encryption settings. The poller detects revisions and queues refresh runs. A running Worker is still required to process them.

Repository webhooks

Repository webhooks use HMAC-SHA256 over this byte sequence:

timestamp + NUL + nonce + NUL + raw request body

Send the lowercase hexadecimal digest in X-Ershu-Webhook-Signature, the Unix timestamp in X-Ershu-Webhook-Timestamp, and a unique nonce in X-Ershu-Webhook-Nonce. The timestamp must be within five minutes of the server clock. The exact raw body used to compute the signature must be sent unchanged.

The webhook endpoint is under /api/v1/webhooks/repositories/{repository_id}. A valid webhook queues work; it does not run repository analysis inside the request.

Production checklist

  • Set ENVIRONMENT=production and SESSION_COOKIE_SECURE=true.
  • Keep SECRET_KEY, ENCRYPTION_KEY, MCP_KEY_PEPPER, and OPAQUE_SERVER_SETUP in a secret store. Use different, stable values.
  • Terminate TLS at the service or a trusted reverse proxy. Production API requests over plain HTTP are rejected.
  • Limit FORWARDED_ALLOW_IPS to the actual proxy addresses and pass the external host and scheme correctly.
  • Add only the real frontend origins to CORS_ORIGINS.
  • Keep ALLOW_DEV_OPEN_LOCAL_REPOSITORY_PATHS=false.
  • Route /api/v1/ to this service. Route /mcp/ to Ershu MCP, not to Ershu API.

The API rejects weak or reused service secrets at startup. The development OpenAPI pages are disabled in production.

Development

Install the development dependencies:

uv sync --extra dev --locked

Run the repository checks:

uv run --extra dev pytest -q
uv run --extra dev ruff check src tests
uv run --extra dev ruff format --check src tests
uv build --wheel --out-dir dist

The test suite uses temporary SQLite databases and replaces external services, so it does not require live PostgreSQL, Redis, or Milvus instances.

Repository layout

Path Purpose
src/ershu/api_main.py FastAPI application, middleware, lifecycle, and HTTP runner
src/ershu/api/router.py Route registration under /api/v1
src/ershu/api/routes/ HTTP routes grouped by domain
src/ershu/api/schemas/ API request and response models
src/ershu/api/services/ API-specific orchestration
src/ershu/api/runtime_settings.py API settings and runtime validation
src/ershu/api/poller.py Scheduled repository polling process
tests/ Route, permission, security, streaming, and maintenance tests

Changes to HTTP requests, responses, errors, cookies, CSRF behavior, or stream events can affect the frontend and other clients. Changes to shared data, permissions, or query behavior belong in ershu-core; analysis and generation changes belong in ershu-worker; MCP tool changes belong in ershu-mcp.

License

Ershu API is licensed under the Apache License 2.0.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ershu_api-1.0.0.post20260812.tar.gz (126.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ershu_api-1.0.0.post20260812-py3-none-any.whl (176.0 kB view details)

Uploaded Python 3

File details

Details for the file ershu_api-1.0.0.post20260812.tar.gz.

File metadata

  • Download URL: ershu_api-1.0.0.post20260812.tar.gz
  • Upload date:
  • Size: 126.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for ershu_api-1.0.0.post20260812.tar.gz
Algorithm Hash digest
SHA256 68cc534dcf6d460ced084a3622b2481c356ed5487c33eb098982e4077ef27aea
MD5 3a6fdea6e60a66d0dcba06fa7b087dfa
BLAKE2b-256 3fb56f2684300df99eaf6cfd0ee15f919078ec7cadb169e91eaca5804dea8ae9

See more details on using hashes here.

File details

Details for the file ershu_api-1.0.0.post20260812-py3-none-any.whl.

File metadata

  • Download URL: ershu_api-1.0.0.post20260812-py3-none-any.whl
  • Upload date:
  • Size: 176.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for ershu_api-1.0.0.post20260812-py3-none-any.whl
Algorithm Hash digest
SHA256 f5f17d0fb830209b28f11c59e840608fc95c71b010dd7bad1ae77284727408a9
MD5 abfd6fdf61813c9ad7f3e928339b8b69
BLAKE2b-256 7a011249f3bfbd816acaafe213b3c0c8aaaa439c3d165d859566e1cc86337fb0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page