Files
orca/.ciagent/ARCHITECTURE.md
T

173 lines
7.4 KiB
Markdown

# Architecture: Orca
## System Overview
Orca is a single-binary, offline-first orchestration engine. The system consists of three logical components, all compiled into one `orca` binary and selected via subcommands.
```
┌─────────────────────────────────────────────────────────────┐
│ orca (single binary) │
├─────────────────────────────────────────────────────────────┤
│ CLI Layer (Cobra) │
│ ├── orca version │
│ ├── orca init │
│ ├── orca status │
│ ├── orca node {join,leave,list} │
│ └── orca job {run,list,stop,logs} │
├─────────────────────────────────────────────────────────────┤
│ Daemon Layer (net/http server) │
│ ├── /healthz (liveness) │
│ ├── /readyz (readiness) │
│ ├── /v1/jobs/* (job control API) │
│ ├── /v1/nodes/* (node registry API) │
│ └── /v1/tasks/* (task lifecycle API) │
├─────────────────────────────────────────────────────────────┤
│ Core Engine │
│ ├── Node Registry (in-memory + SQLite persistence) │
│ ├── Task Executor (os/exec with WaitDelay, Go 1.25+) │
│ ├── Job Scheduler (single-node for v0.1) │
│ └── Audit Logger (log/slog JSON handler) │
├─────────────────────────────────────────────────────────────┤
│ State Store (modernc/sqlite, CGO-free) │
│ ~/.orca/orca.db │
└─────────────────────────────────────────────────────────────┘
```
## Component Details
### 1. CLI Layer (`cmd/orca`, `internal/cli`)
- **Framework**: Cobra (industry standard, familiar to operators)
- **Subcommands**: `version`, `init`, `status`, `node`, `job`
- **Output**: Human-readable by default; `--json` flag for machine consumption
- **Discovery**: All subcommands self-document via Cobra's auto-generated help
### 2. Daemon Layer (`internal/daemon`)
- **Server**: `net/http` with `http.ServeMux` (no external router for v0.1)
- **TLS**: `crypto/tls` with self-signed certs (mTLS-ready)
- **Ports**: Configurable (default `:8443` for API, `:8080` for health)
- **Graceful Shutdown**: `signal.NotifyContext` with SIGINT/SIGTERM
### 3. Core Engine (`internal/engine`)
- **Node Registry**: In-memory map of node IDs → metadata, persisted to SQLite
- **Task Executor**: `os/exec.CommandContext` with `WaitDelay` (Go 1.25+) for clean process termination
- **Job Scheduler**: Single-node FIFO queue (multi-node deferred to v0.2+)
- **Audit Logger**: `slog.NewJSONHandler(os.Stderr, ...)` with structured fields
### 4. State Store (`internal/store`)
- **Driver**: `modernc.org/sqlite` (pure Go, CGO-free)
- **Location**: `~/.orca/orca.db` (user-mode) or `/var/lib/orca/orca.db` (system-mode)
- **Schema**: `nodes`, `jobs`, `tasks`, `audit_log` tables
- **Migrations**: Embedded SQL files, applied on startup
## Data Model
### Node
```go
type Node struct {
ID string
Name string
Address string
State string
JoinedAt time.Time
LastSeen time.Time
Metadata map[string]string
}
```
### Job
```go
type Job struct {
ID string
Name string
Spec string
Status string
CreatedAt time.Time
StartedAt *time.Time
EndedAt *time.Time
}
```
### Task
```go
type Task struct {
ID string
JobID string
Command string
Args []string
Env []string
PID int
ExitCode int
Status string
CreatedAt time.Time
StartedAt *time.Time
EndedAt *time.Time
}
```
## Security Architecture
### Authentication
- **v0.1**: mTLS for all API endpoints (self-signed CA)
- **v0.2+**: Token-based auth as alternative
### Audit Logging
- All state-changing operations emit structured log records
- Fields: `timestamp`, `actor`, `action`, `resource`, `result`, `error`
- Stored in SQLite `audit_log` table and stderr (JSON)
### Input Validation
- All CLI inputs validated via Cobra's `Args`/`ValidArgs` functions
- All API inputs validated at handler boundary
- HCL/YAML specs parsed with strict schemas
## Key Architectural Decisions
| ID | Decision | Rationale |
|----|----------|-----------|
| AD-001 | Single binary with subcommands | Simpler distribution, aligns with simplicity pillar |
| AD-002 | modernc/sqlite (CGO-free) | Cross-compile friendly, no CGO toolchain needed |
| AD-003 | net/http (no framework) | Stdlib suffices; avoids external router dependency |
| AD-004 | os/exec with WaitDelay (Go 1.25+) | Clean process termination, native to Go |
| AD-005 | Cobra for CLI | Industry standard, familiar to operators |
| AD-006 | slog for logging | Native to Go 1.21+, no external dependency |
| AD-007 | HCL for job specs | Familiar to Nomad/HashiCorp users |
| AD-008 | Single-node scheduling (v0.1) | Multi-node scheduling deferred to v0.2+ |
## Anti-Patterns (Explicitly Avoided)
- No controller/agent split (single binary)
- No CRDs / custom resource definitions
- No web UI (CLI-only)
- No service mesh
- No container runtime integration
- No multi-tenancy
- No cloud provider integrations
- No auto-scaling
- No admission controllers
- No complex scheduling algorithms
## Dependency Map (minimal)
```
github.com/spf13/cobra # CLI framework
github.com/hashicorp/hcl/v2 # HCL parser
modernc.org/sqlite # SQLite (pure Go)
github.com/google/uuid # UUID generation
```
Total: ~4 direct dependencies. No web framework, no ORM, no RPC framework.
## Deployment Model
```
User Machine Server Node
┌──────────┐ ┌──────────────────┐
│ orca CLI │─────── mTLS ──────────▶│ orca daemon │
│ │ │ ├── API server │
│ │ │ ├── Engine │
│ │ │ └── SQLite store │
└──────────┘ └──────────────────┘
```
For v0.1, the CLI and daemon can be the same binary on the same machine. Multi-node is deferred.