173 lines
7.4 KiB
Markdown
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.
|