2c52b1634f
Fusion-Task-Id: FN-011 Fusion-Task-Lineage: 4a9aca6f-9d91-43aa-8d2a-d59657c1541a
260 lines
9.3 KiB
Markdown
260 lines
9.3 KiB
Markdown
# Headquarter Architecture
|
|
|
|
> Canonical architecture specification for the hosted workspace and tool-orchestration platform.
|
|
> Decisions in this document override ad-hoc choices in implementation tasks.
|
|
|
|
## 1. Overview & Goals
|
|
|
|
Headquarter is a hosted control plane where authenticated users create projects, connect Git repositories, and spawn containerized tools (RunFusion, code-server, and future tools). The platform is manifest-driven and provider-abstracted so new tools, Git providers, runtimes, and access providers can be added without rewriting core orchestration logic.
|
|
|
|
**MVP scope:** Single-user projects, Authentik OIDC auth, Docker runtime, Traefik subdomain routing, Portainer-managed Docker Compose deployment.
|
|
|
|
## 2. Domain Model
|
|
|
|
```text
|
|
User ──< Project ──< Repository
|
|
└──< ToolInstance
|
|
|
|
Tool (manifest-driven, global registry)
|
|
```
|
|
|
|
- **User:** Authentik-managed identity. MVP assumes individual users; schema leaves room for teams/shared projects later.
|
|
- **Project:** Owned by a user. Contains repositories and spawned tool instances.
|
|
- **Repository:** Git-backed workspace. Clone, fetch, and push via provider-independent adapters.
|
|
- **Tool:** Manifest-driven definition (image, ports, mounts, env, health checks, routing rules). Defined in FN-003.
|
|
- **ToolInstance:** A running container spawned from a Tool manifest for a specific project. Receives workspace mounts, config mounts, secrets, and Traefik routing labels.
|
|
|
|
## 3. Provider Interfaces
|
|
|
|
The backend must define provider contracts before implementing any concrete adapter.
|
|
|
|
### 3.1 GitProvider
|
|
|
|
> **Architecture divergence note (FN-011):** The original spec defined a single
|
|
> `GitProvider(Protocol)` with `clone/fetch/push` methods. The implementation
|
|
> intentionally splits this responsibility into two abstractions:
|
|
>
|
|
> - `GitProvider` (`app/git/provider.py`) — provider API adapter for remote
|
|
> operations (`validate_connection`, `list_repositories`, `create_deploy_key`,
|
|
> etc.).
|
|
> - `GitOperations` (`app/git/operations.py`) — local Git subprocess interface
|
|
> (`clone`, `fetch`, `push`, `get_status`).
|
|
>
|
|
> This separation keeps provider-specific API logic distinct from local Git CLI
|
|
> orchestration.
|
|
|
|
```python
|
|
class GitProvider(Protocol):
|
|
def validate_connection(self, repo_url: str, credential_id: str) -> ConnectionStatus: ...
|
|
def list_repositories(self, credential_id: str) -> list[dict[str, Any]]: ...
|
|
def create_deploy_key(self, repo_url: str, public_key: str) -> str: ...
|
|
def delete_deploy_key(self, repo_url: str, deploy_key_id: str) -> None: ...
|
|
def get_default_branch(self, repo_url: str, credential_id: str) -> str: ...
|
|
```
|
|
|
|
- Adapters: GitHub, GitLab, Gitea, Forgejo, etc.
|
|
- Credentials: generated SSH keys (per-repository) or access tokens.
|
|
- SSH keys must be scoped per repository connection for clean revocation.
|
|
|
|
```python
|
|
class GitOperations(Protocol):
|
|
def clone(self, repo_url: str, dest: Path, credential_id: str) -> None: ...
|
|
def fetch(self, repo_path: Path, credential_id: str) -> None: ...
|
|
def push(self, repo_path: Path, credential_id: str) -> None: ...
|
|
def get_status(self, repo_path: Path) -> dict[str, Any]: ...
|
|
```
|
|
|
|
### 3.2 RuntimeProvider
|
|
|
|
```python
|
|
class RuntimeProvider(Protocol):
|
|
def spawn(self, manifest: ToolManifest, project: Project, config: SpawnConfig) -> ToolInstance: ...
|
|
def stop(self, instance: ToolInstance) -> None: ...
|
|
def health(self, instance: ToolInstance) -> HealthStatus: ...
|
|
```
|
|
|
|
- MVP adapter: Docker Compose service generation + Docker API.
|
|
- Future adapters: Kubernetes, Nomad, etc.
|
|
|
|
### 3.3 AccessProvider
|
|
|
|
```python
|
|
class AccessProvider(Protocol):
|
|
def route(self, instance: ToolInstance, domain: str) -> RoutingConfig: ...
|
|
```
|
|
|
|
- MVP adapter: Traefik labels on Docker containers.
|
|
- Future adapter: Cloudflare Tunnel, etc.
|
|
|
|
## 4. Deployment Architecture
|
|
|
|
### 4.1 MVP Target
|
|
|
|
- **Orchestration:** Portainer-managed Docker Compose stack.
|
|
- **Reverse Proxy:** Existing Traefik instance (external to the app stack).
|
|
- **Network:** Shared Traefik Docker network; app stack attaches to it.
|
|
- **Certificate Resolution:** Let's Encrypt or internal CA via Traefik cert resolver.
|
|
|
|
### 4.2 Subdomain Routing
|
|
|
|
Path-based routing is avoided because many tools expect to run at `/`.
|
|
|
|
Pattern:
|
|
```
|
|
https://{tool}-{project}-{user}.{tool_domain}
|
|
```
|
|
|
|
Examples:
|
|
```
|
|
https://runfusion-myapp-alice.tools.example.com
|
|
https://code-myapp-alice.tools.example.com
|
|
```
|
|
|
|
### 4.3 Compose Skeleton
|
|
|
|
- `docker-compose.yml`: local development (backend, frontend, PostgreSQL).
|
|
- `docker-compose.traefik.yml`: deployment overlay with Traefik labels and external network.
|
|
- Environment-driven; no secrets committed to repository.
|
|
|
|
## 5. Security Boundaries
|
|
|
|
### 5.1 Authentication
|
|
|
|
- Authentik OIDC for user login.
|
|
- FastAPI backend validates JWT/id tokens at API boundaries.
|
|
- Frontend stores tokens securely (httpOnly cookie or secure storage pattern).
|
|
|
|
### 5.2 Secrets
|
|
|
|
- Never treat secrets as plaintext config.
|
|
- Support encrypted storage at rest and runtime injection as:
|
|
- Environment variables
|
|
- Mounted secret files
|
|
- Encryption key is an environment secret (`SECRET_ENCRYPTION_KEY`).
|
|
|
|
### 5.3 SSH Keys
|
|
|
|
- Generated per repository connection.
|
|
- Stored encrypted.
|
|
- Injected into tool containers at runtime for Git operations.
|
|
|
|
### 5.4 Container Isolation
|
|
|
|
- Each tool instance runs in its own container.
|
|
- Resource limits declared in tool manifest.
|
|
- Workspace and config mounts are scoped to user/project.
|
|
|
|
## 6. Data & Storage
|
|
|
|
### 6.1 Database
|
|
|
|
- PostgreSQL for relational data (users, projects, repositories, tool instances, manifests).
|
|
- Schema migrations managed by backend (Alembic or equivalent).
|
|
|
|
### 6.2 Filesystem Layout (Conceptual)
|
|
|
|
```text
|
|
/data/
|
|
users/{userId}/tool-configs/{toolId}/
|
|
projects/{projectId}/repo/
|
|
projects/{projectId}/tool-configs/{toolId}/
|
|
```
|
|
|
|
- Repository workspace storage: Docker volumes or local bind mounts.
|
|
- Tool config storage: persistent host mounts, separate from repository workspaces.
|
|
- Config scopes: global default → user-level → project-level → tool-instance override.
|
|
|
|
## 7. Tool Manifest & Orchestration
|
|
|
|
Tools are defined by manifests (FN-003) that declare:
|
|
|
|
- Runtime image / image tag
|
|
- Node/npm version expectations (for executable environments)
|
|
- Bootstrap / install commands
|
|
- Command execution needs
|
|
- Workspace mounts
|
|
- Config mounts
|
|
- Environment variables
|
|
- Secrets
|
|
- Ports
|
|
- Health checks
|
|
- Resource limits
|
|
- Traefik routing needs (subdomain pattern, middleware)
|
|
|
|
The platform reads manifests and generates:
|
|
- Docker Compose service definitions
|
|
- Traefik labels for routing
|
|
- Volume mounts for workspace and config
|
|
- Secret injection at runtime
|
|
|
|
## 8. MVP Phases
|
|
|
|
| Phase | Task | Deliverable |
|
|
|-------|------|-------------|
|
|
| Foundation | FN-002 | Monorepo scaffold, build/test/lint pipelines |
|
|
| Registry | FN-003 | Manifest schema, RunFusion and code-server manifests |
|
|
| Backend | FN-004 | FastAPI app, domain models, API endpoints, DB migrations |
|
|
| Frontend | FN-005 | Auth-ready shell, navigation, placeholder screens |
|
|
| Deployment | FN-006 | Docker Compose overlays, Traefik labels, Portainer config |
|
|
| Git Model | FN-007 | Provider interface, SSH key generation, credential storage |
|
|
| RunFusion POC | FN-008 | Executable environment proof of concept |
|
|
| Secrets & Config | FN-009 | Encrypted secrets, persistent config mounts |
|
|
| code-server Spawn | FN-010 | code-server manifest, spawn script, runtime integration |
|
|
|
|
## 9. Extension Points
|
|
|
|
- **New Git providers:** Implement `GitProvider` protocol.
|
|
- **New tools:** Add a manifest to the registry (no code changes required for standard containers).
|
|
- **New runtimes:** Implement `RuntimeProvider` protocol.
|
|
- **New access providers:** Implement `AccessProvider` protocol.
|
|
- **Teams/organizations:** Add `Organization` and `ProjectMember` entities later.
|
|
|
|
## 10. Environment Assumptions
|
|
|
|
Required environment variables (no defaults in production):
|
|
|
|
```env
|
|
APP_NAME=
|
|
ROOT_DOMAIN=
|
|
TOOL_DOMAIN=
|
|
API_URL=
|
|
TRAEFIK_NETWORK=
|
|
TRAEFIK_ENTRYPOINT=
|
|
TRAEFIK_CERT_RESOLVER=
|
|
AUTHENTIK_ISSUER_URL=
|
|
AUTHENTIK_CLIENT_ID=
|
|
AUTHENTIK_CLIENT_SECRET=
|
|
DATABASE_URL=
|
|
SECRET_ENCRYPTION_KEY=
|
|
```
|
|
|
|
Local development uses `.env.example` and safe defaults.
|
|
|
|
## 11. Technology Boundaries
|
|
|
|
| Layer | Choice | Migration Path |
|
|
|-------|--------|----------------|
|
|
| Frontend | React + Vite | Next.js, Vue, etc. if needed |
|
|
| Backend | FastAPI | Any ASGI framework |
|
|
| Database | PostgreSQL | Managed Postgres, CockroachDB |
|
|
| Runtime | Docker Compose | Kubernetes, Nomad |
|
|
| Access | Traefik | Cloudflare Tunnel, custom proxy |
|
|
| Auth | Authentik OIDC | Any OIDC provider |
|
|
|
|
## 12. Acceptance Criteria for Architecture Compliance
|
|
|
|
Any implementation task must:
|
|
|
|
1. Respect provider interfaces (no hardcoded GitHub/Traefik logic in core orchestration).
|
|
2. Keep secrets out of committed files and plaintext logs.
|
|
3. Use environment variables for deployment-specific values.
|
|
4. Leave schema room for multi-user teams without rewriting ownership models.
|
|
5. Support adding a new tool via manifest + registry entry alone (no new backend code for standard containers).
|
|
|
|
## 13. Deferred Decisions
|
|
|
|
- **Multi-tenancy:** MVP is single-tenant deployment. Multi-tenant routing and isolation are future concerns.
|
|
- **High availability:** No replicas or load balancing in MVP.
|
|
- **Backup strategy:** Out of MVP scope; rely on host-level volume backups.
|
|
- **Rate limiting:** Not in MVP; add at Traefik or API gateway layer later.
|