Files
orca/.ciagent/ARCHITECTURE.md
T
ciagent f1c55ca79b docs(audit): fix .ciagent/ file discipline issues
Audit findings addressed:
- PROJECT.md: add 'What This Is' and 'Key Decisions' sections (per audit Step 2)
- ARCHITECTURE.md: add internal/jobspec (HCL parser) and internal/model (domain types) to system diagram and component details
- PLANS.md: expand REQ coverage lines for Phase 1 and Phase 3 to include all REQ-IDs the work actually delivers (REQ-003 offline-first, REQ-008 slog, REQ-010 --json, REQ-020 hashicorp/hcl)

---ci---
project: orca
phase: 0
milestone: v0.1
status: fix
---/ci---
2026-06-03 20:14:03 +00:00

8.7 KiB

Architecture: Orca

System Overview

Orca is a single-binary, offline-first orchestration engine. The system consists of six 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)                       │
├─────────────────────────────────────────────────────────────┤
│  Job Spec Parser (hashicorp/hcl/v2)                         │
│  └── reads .hcl files → validates → hands to engine         │
├─────────────────────────────────────────────────────────────┤
│  Domain Model (internal/model)                              │
│  ├── Node, Job, Task structs (no I/O)                        │
│  └── shared by store, engine, daemon                        │
├─────────────────────────────────────────────────────────────┤
│  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

5. Job Spec Parser (internal/jobspec)

  • Parser: hashicorp/hcl/v2 (industry-standard, familiar to Nomad users)
  • Format: HCL files (.hcl); YAML fallback considered but deferred
  • Use: orca job run <spec.hcl> reads and validates the spec, hands off to the engine

6. Domain Model (internal/model)

  • Types: Node, Job, Task — pure data structs with no I/O
  • State machines: Node (pending/ready/left), Task (pending/running/complete/failed)
  • Use: shared by internal/store, internal/engine, internal/daemon to avoid circular dependencies

Data Model

Node

type Node struct {
    ID        string
    Name      string
    Address   string
    State     string
    JoinedAt  time.Time
    LastSeen  time.Time
    Metadata  map[string]string
}

Job

type Job struct {
    ID        string
    Name      string
    Spec      string
    Status    string
    CreatedAt time.Time
    StartedAt *time.Time
    EndedAt   *time.Time
}

Task

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.