Files
hub/docs/architecture/hub-architecture.md
glm-5.1 2b63cda1c7 Setup repo: migrate architecture specs, code stubs, and tasks from alkhub_ts
Copy architecture docs, ADRs, storage domain specs, research, reviews,
and 56 storage architecture tasks from the alkhub_ts monorepo. Adapt for
standalone @alkdev/hub repo structure (src/ not packages/hub/).

Sanitize all sensitive information:
- Replace private IPs (10.0.0.1) with localhost defaults
- Remove internal server hostnames (dev1, ns528096)
- Replace /workspace/ private paths with npm package references
- Remove hardcoded credentials from examples
- Rewrite infrastructure.md without private network details

Add Deno project scaffolding: deno.json (pinned deps), .gitignore,
AGENTS.md, entry point. Migrate existing code stubs (crypto, config
types, logger) with updated import paths.
2026-05-25 10:56:32 +00:00

104 lines
7.1 KiB
Markdown

---
status: draft
last_updated: 2026-05-18
---
# Hub Architecture: alk.dev API
## Overview
The hub is the central API server hosted at `api.alk.dev`. It extends the spoke with orchestration capabilities, persistent storage, and coordination logic. The hub manages agent sessions, coordinates work across spoke runners, and exposes the public-facing API.
**Reference**: See spoke-runner.md (hub/spoke model). The `ade_hub` package contains directional stubs (WorkerPool, Dispatcher) — coherent but not production architecture. See spoke-runner.md for the actual design.
## Design Principles
1. **Hub shares core with spoke, adds orchestration** — both hub and spoke depend on `@alkdev/operations` and `@alkdev/pubsub` for operations, pubsub, and call protocol. Hub adds stateful coordination, persistence, and HTTP serving on top.
2. **Stabilize API in TS, rewrite in Rust later** — Deno + TypeScript for initial production. API contract matters more than runtime performance until scale demands it
3. **Postgres for all persistent state** — single Postgres instance (configured host:port from encrypted config)
4. **Redis for cross-process events** — replaces opencode's single-process EventEmitter/Effect PubSub. Redis 7 is deployed on the hub server (configured Redis host:port from encrypted config). See infrastructure.md.
5. **Operations as the universal abstraction** — everything is a typed operation with TypeBox schemas
## Components
### From core (shared with spoke)
| Component | Location | Notes |
| ----------------- | ------------------------------------------------------ | ------------------------------------------------------------------------- |
| Operations system | `@alkdev/operations` | Registry, scanner, types, env, FromOpenAPI, FromSchema, SchemaAdapter |
| PubSub | `@alkdev/pubsub` | createPubSub + operators, Redis/WebSocket/Worker EventTargets |
| MCP client | `@alkdev/operations/from-mcp` | createMCPClient, MCPClientLoader (for connecting to external MCP servers) |
| Call protocol | `@alkdev/operations` (see call-graph.md) | PendingRequestMap, CallHandler, call ≡ subscribe |
| Call graph | `@alkdev/taskgraph` (see call-graph.md) | Graphology-based, needed for SDD workflow orchestration |
| Operation graph | `@alkdev/taskgraph` (see call-graph.md) | Static type-compatibility graph, call templates |
### New / Simplified for alk.dev
| Component | Description | Replaces |
| -------------------- | ---------------------------------------------------- | -------------------------------------------------- |
| Storage | Drizzle + Postgres with `@alkdev/drizzlebox` pattern | Previous DbType.Table abstraction (too complex, dropped) |
| Redis EventTarget | Available in `@alkdev/pubsub` as `RedisEventTarget`. `TypedEventTarget` impl backed by Redis pub/sub | opencode's in-process EventEmitter/Effect PubSub |
| Container spoke (deferred) | Spoke that extends base spoke with Docker + opencode container lifecycle. Will also need a variant for vast.ai compute. | opencode's multi-project-in-process model |
| Agent session system | AI SDK `streamText` + `UIMessage` persistence | opencode's Effect-based SessionProcessor |
| MCP server | `@hono/mcp` StreamableHTTPTransport with discovery+call pattern | per-container MCP servers |
### Dropped (not needed)
| Component | Reason |
| -------------------------------- | -------------------------------------------------- |
| Sandbox (QuickJS) | Hub doesn't execute untrusted code |
| iroh-gossip / P2P | Redis pub/sub covers multi-process; P2P is future |
| DbType.Table storage abstraction | `@alkdev/drizzlebox` pattern from ade-v0 is cleaner |
| Effect dependency | Unnecessary complexity; AI SDK handles LLM streams |
## Hub Responsibilities
1. **Serve public API** at `api.alk.dev` — Hono HTTP server
2. **Manage spoke runners** — registration, heartbeat, capability discovery
3. **Orchestrate agent workflows** — coordinator, decomposer, implementation specialist roles from SDD process
4. **Persist all state** — sessions, messages, projects, task graphs, coordination mappings
5. **Route events** — Redis pub/sub for cross-process, WebSocket for hub↔spoke, SSE for compatibility
6. **Proxy LLM calls** — OpenAI-compatible proxy endpoint that keeps provider keys server-side
7. **Expose MCP endpoint** — shared tools (websearch, coordination, git operations) for all opencode containers
8. **Track call graph** — observe, abort cascade, and replay agent workflows
## Data Flow
```
Client (browser/CLI)
├── HTTP ──→ Hono API (api.alk.dev)
│ ├── Operations registry
│ ├── Drizzle + Postgres
│ └── Redis pub/sub (hub-internal)
├── WebSocket ──→ Call protocol (hub ↔ spokes bidirectional)
│ ├── Dispatches call.requested to spokes
│ └── Receives call.responded/call.error from spokes
└── MCP ──→ @hono/mcp endpoint (search/schema/call for legacy systems)
└── Thin adapter over hub.list/hub.search/hub.schema/hub.call
Spokes (dev env, client, compute)
├── Connect ──→ Hub via WebSocket (wss://api.alk.dev/ws)
├── Register ──→ hub.register (identity, operations, spokeType)
├── Receive ──→ call.requested from hub, execute, respond
└── Call ──→ hub operations over same WS (bidirectional)
```
## Relationship to ade_ts
The hub design was informed by prior work on API server patterns for spoke orchestration:
- **Same**: Operation registry, pubsub, call protocol, call graph, operation graph
- **Different**: Postgres instead of DbType.Table, Redis instead of iroh-gossip, AI SDK instead of Effect, WebSocket spoke transport instead of in-process WorkerPool, discovery+call MCP pattern instead of direct tool exposure
- **Shared**: Both projects share the same spoke foundation. Architecture docs can be cross-referenced. When ade_ts stabilizes its call protocol and graph patterns, alk.dev can adopt them.
## Open Questions
1. **Redis deployment topology** — Redis is deployed on the hub server. For production with many spokes on a compute server, may want Redis closer to containers for lower pub/sub latency.
2. **API auth model** — API keys with Keypal pattern? Or simpler token auth for stopgap? (Related: spoke-runner.md WebSocket auth question)
3. **SSO with Gitea** — Gitea at git.alk.dev uses its own auth. Should api.alk.dev share sessions?