SOIT Docs
Developer Guides

Backend Development

Work on the SOIT FastAPI backend with kernel, module, adapter, and API boundaries.

The SOIT backend lives under soit/server and uses Python 3.11, FastAPI, SQLModel, SQLAlchemy, Alembic, Celery, PostgreSQL, Redis, Milvus, MinIO, Vault, and OpenTelemetry. This page summarizes the mandatory engineering standard.

Local commands

uv sync
uv run uvicorn app.main:app --reload
uv run pytest
uv run lint-imports --config importlinter.ini
uv run ruff check app tests
uv run mypy app tests

The six non-negotiables

  1. Spec-First — any new capability starts with a JSON Schema update under app/kernel/specs/, with examples; runtime validates incoming spec JSON against the schema.
  2. Scope-By-Default — workspace resources are isolated by tenant_id + workspace_id. Business APIs never accept tenant or workspace ids as free parameters; scope resolves from RequestContext only.
  3. Trace-Everything — every executable action creates a run and at least one run step; large payloads become artifacts; costs go to cost entries. See Runtime Ledger.
  4. Port-Only — LLM, tools, MCP, vector DB, object storage, and secrets are accessed through kernel ports, which enforce retry, timeout, audit, and rate limits consistently. Modules never call provider SDKs directly.
  5. Immutable-Versions — agent_version, workflow_version, and plugin_version rows are immutable; publish and rollback only move pointers.
  6. Secure-by-Default — egress is deny-by-default, secrets are references only (never plaintext), and high-risk runtimes stay disabled unless explicitly enabled.

Import rules

Allowed dependency directions:

  • app/api → app/modules, and kernel contracts/policies
  • app/modules → app/kernel
  • app/adapters → app/kernel/ports (implements gateway interfaces)

Forbidden (fails import-linter and code review): kernel importing modules or API, modules importing API, and any module importing another module's domain models directly — depend on contracts and ports instead.

Identity and scope

  • Every request resolves a RequestContext: tenant_id and user_id from the JWT or session, workspace_id from header or path, plus membership and role checks. All services accept ctx: RequestContext.
  • Scope-aware repositories enforce WHERE tenant_id = ctx.tenant_id AND workspace_id = ctx.workspace_id on every workspace-scoped query.
  • Services use guard decorators rather than hard-coded checks: rbac_guard(resource_type, action) for resource actions (create | read | update | delete | run) and workspace_guard(...) for workspace/tenant-level checks. The API layer stays thin and does not enforce permissions directly.

API conventions

All responses use a stable envelope:

{
  "success": true,
  "code": "OK",
  "message": "OK",
  "data": { "any": "json" },
  "request_id": "req_...",
  "run_id": "run_..."
}

Errors use the same shape with success: false, an enum code, and a details object. Pagination is cursor-based (page_size / page_token in, items / next_page_token out), and write APIs should support an Idempotency-Key header.

Directory placement

  • HTTP request/response schemas → app/api/v1/schemas/
  • Domain schemas → app/modules/<domain>/**/schemas.py
  • Cross-layer stable contracts → app/kernel/contracts/
  • Provider implementations → app/adapters/
  • Dependency wiring → app/wiring/
  • JSON Schemas → app/kernel/specs/v1/

Cross-resource references follow refs.schema.json, e.g. model:openai:gpt-4.1, knowledge:kb_support, tool:http:ticket_create, secret:zendesk_token.

Migrations and testing

  • Schema changes go through reviewed Alembic migrations, reversible when feasible; avoid long locks on large tables.
  • Minimum mandatory tests: cross-tenant and cross-workspace access return 403/404, spec validation rejects invalid JSON, every execution produces a run plus steps, and gateway mocks keep tests deterministic.

PR checklist

  • Spec updated with examples for any new capability.
  • Tenant/workspace scope enforced, with tests.
  • run / run_step emitted for new execution paths.
  • Gateway (port) used for any external call.
  • Breaking-change impact assessed.
  • CI passes — see Testing and Quality Gate.

On this page