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

262 lines
7.1 KiB
Markdown

# Development Guide
## Prerequisites
- **Node.js** ≥ 20 and **pnpm** ≥ 9
- **Python** ≥ 3.11 with `venv` support
- **Docker** and **Docker Compose** (for local services)
## Installation
```bash
# 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:
```bash
cp .env.example .env
```
Copy the frontend environment example:
```bash
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
```bash
cd apps/web
pnpm dev # Vite dev server on http://localhost:5173
```
### Backend only
```bash
cd apps/api
.venv/bin/uvicorn app.main:app --reload --port 8000
```
### Both (via root script)
```bash
pnpm dev # Runs frontend and backend in parallel
```
### With Docker Compose
```bash
docker compose up --build -d
```
### Alembic Migrations
Generate a new migration after modifying models:
```bash
cd apps/api
.venv/bin/alembic revision --autogenerate -m "description"
```
Apply migrations:
```bash
cd apps/api
.venv/bin/alembic upgrade head
```
Downgrade one revision:
```bash
cd apps/api
.venv/bin/alembic downgrade -1
```
Or use the Makefile targets:
```bash
cd apps/api
make revision msg="description"
make upgrade
make downgrade
```
## Testing
### Frontend
```bash
pnpm --filter @headquarter/web test
```
Uses **Vitest** + **Testing Library** + **jsdom**.
### Backend
```bash
pnpm --filter @headquarter/api test
```
Or directly with pytest:
```bash
cd apps/api && .venv/bin/pytest
```
### All tests
```bash
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
```bash
pnpm --filter @headquarter/web lint
pnpm --filter @headquarter/web typecheck
```
### Backend
```bash
pnpm --filter @headquarter/api lint
pnpm --filter @headquarter/api typecheck
```
### All
```bash
make lint
make typecheck
```
## Building
```bash
make build
# or
pnpm build
```
## Project Layout
```text
├── 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:
```bash
docker network create tools # One-time setup
```
Spawned containers use the `tools` network for Traefik routing.