Files
headquarter/docs/development.md
T
alex 62640daf36 docs: update all documentation for OpenCode and deployment
- Update architecture.md with spawn service and auth proxy sections
- Update deployment.md with production stack details
- Update development.md with spawn workflow documentation
- Update mvp-scope.md, project-brief.md, tool-manifest-spec.md
- Update conversation-handoff.md with current status
- Replace all RunFusion references with OpenCode
2026-05-14 17:30:03 +02:00

7.1 KiB

Development Guide

Prerequisites

  • Node.js ≥ 20 and pnpm ≥ 9
  • Python ≥ 3.11 with venv support
  • Docker and Docker Compose (for local services)

Installation

# Install Node dependencies and Python virtualenv + packages
make install

# Or manually:
pnpm install
cd apps/api && python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"

Environment Setup

Copy the root environment example and fill in local values:

cp .env.example .env

Copy the frontend environment example:

cp apps/web/.env.example apps/web/.env

Frontend Authentication (OIDC)

The frontend uses OpenID Connect (OIDC) with PKCE for authentication. Configure the following environment variables in apps/web/.env:

Variable Description Example
VITE_API_URL Backend API base URL http://localhost:8000
VITE_OIDC_ISSUER OIDC provider issuer URL https://authentik.example.com/application/o/headquarter
VITE_OIDC_CLIENT_ID OIDC client ID headquarter-web
VITE_OIDC_REDIRECT_URI Post-login redirect URL http://localhost:5173/callback

Authentication Flow:

  1. User clicks login → redirected to OIDC provider authorize endpoint
  2. User authenticates with provider
  3. Provider redirects to /callback with authorization code
  4. Frontend exchanges code for access token (PKCE)
  5. Token stored in localStorage, user info fetched from /api/v1/users/me

Logout:

  • Clears local token
  • Redirects to login page
  • User can re-authenticate via OIDC flow

Running Locally

Frontend only

cd apps/web
pnpm dev        # Vite dev server on http://localhost:5173

Backend only

cd apps/api
.venv/bin/uvicorn app.main:app --reload --port 8000

Both (via root script)

pnpm dev        # Runs frontend and backend in parallel

With Docker Compose

docker compose up --build -d

Alembic Migrations

Generate a new migration after modifying models:

cd apps/api
.venv/bin/alembic revision --autogenerate -m "description"

Apply migrations:

cd apps/api
.venv/bin/alembic upgrade head

Downgrade one revision:

cd apps/api
.venv/bin/alembic downgrade -1

Or use the Makefile targets:

cd apps/api
make revision msg="description"
make upgrade
make downgrade

Testing

Frontend

pnpm --filter @headquarter/web test

Uses Vitest + Testing Library + jsdom.

Backend

pnpm --filter @headquarter/api test

Or directly with pytest:

cd apps/api && .venv/bin/pytest

All tests

make test
# or
pnpm test

CI / Testing

A GitHub Actions workflow (.github/workflows/ci.yml) runs on every push and pull request to main. It executes two jobs in parallel:

  • web-ci — checks out the repo, installs Node.js ≥ 20 and pnpm, then runs lint, typecheck, and test for @headquarter/web.
  • api-ci — checks out the repo, sets up Python 3.11, installs API dev dependencies (pytest, ruff, mypy, httpx), starts a PostgreSQL service container, then runs ruff check, mypy, and pytest for the API.

The workflow reports pass/fail status directly on pull requests as required status checks. All commands must pass before a PR can be merged.

Linting and Type Checking

Frontend

pnpm --filter @headquarter/web lint
pnpm --filter @headquarter/web typecheck

Backend

pnpm --filter @headquarter/api lint
pnpm --filter @headquarter/api typecheck

All

make lint
make typecheck

Building

make build
# or
pnpm build

Project Layout

├── apps/
│   ├── web/          # Vite React TypeScript frontend
│   └── api/          # FastAPI Python backend
├── packages/         # Shared packages (future)
├── docs/             # Documentation
├── deploy/           # Deployment skeleton files
├── docker-compose.yml
└── package.json      # Root monorepo scripts

Conventions

  • Frontend: React functional components, TypeScript strict mode, ESLint + Ruff-like rules.
  • Backend: FastAPI, Pydantic settings, pytest, ruff, mypy.
  • Commits: Conventional commits with task ID prefix, e.g. feat(FN-002): description.

Git Abstraction

The app/git/ package in the backend provides provider-independent Git orchestration. It is split into two layers so that remote provider API logic and local CLI operations evolve independently:

Module Responsibility
types Enumerations (ProviderKind, CredentialKind, ConnectionStatus, SshKeyStatus)
provider Abstract GitProvider — remote operations (validate_connection, list_repositories, create_deploy_key, …)
credentials GitCredential / AccessTokenCredential models and CredentialStorage ABC
ssh_key SshKeyPair model and SshKeyLifecycle (Ed25519 generation via cryptography)
connection RepositoryConnection ORM mapping and ConnectionManager orchestration
operations Abstract GitOperations and concrete LocalGitOperations (subprocess-based get_status)

Security rules for the package:

  • Credential models store only encrypted_payload — no plaintext token or private_key fields.
  • SSH private keys are encrypted before storage; the field uses repr=False.
  • Real encryption of the payload is deferred to FN-009; the current placeholder is base64-only.

Tool Spawn Workflow

The platform supports spawning development tools (e.g., code-server) as Docker containers via Docker Compose.

Architecture

  1. Tool Manifest (apps/api/app/tools/manifests/*.yml):

    • Defines Docker image, ports, volumes, environment variables, health checks
    • Loaded into in-memory registry at application startup
  2. Spawn Service (apps/api/app/services/spawn.py):

    • Generates Docker Compose service definitions from manifests
    • Handles container lifecycle: spawn, stop, status polling
    • Integrates Traefik label generation for subdomain routing
  3. API Endpoints (apps/api/app/routers/tool_instances.py):

    • POST /projects/{id}/tool-instances — Spawn a new tool instance
    • POST /projects/{id}/tool-instances/{id}/stop — Stop a running instance
    • POST /projects/{id}/tool-instances/{id}/start — Restart a stopped instance
    • GET /projects/{id}/tool-instances/{id}/status — Get container status
  4. Frontend UI:

    • /tools/spawn — Form to select tool, project, and spawn
    • /projects/{id}/instances/{id} — Instance detail with status, controls, and "Open Tool" link

Auth Proxy

Spawned tools are protected behind Traefik forwardAuth middleware:

  • Traefik forwards requests to /api/v1/auth/validate for session validation
  • code-server built-in auth is disabled (PASSWORD: "")
  • Only authenticated platform users can access spawned tools

Local Development

Ensure Docker socket is accessible and the tools network exists:

docker network create tools  # One-time setup

Spawned containers use the tools network for Traefik routing.