SPECIFY stage: adopt 5 research docs into authoritative ciagent files. - PRD_v0.11.md: new file extending R-series 16->20 (R-017 ingress hybrid, R-018/R-019/R-020 drift detection) - PROJECT.md: append D-215..D-237 (23 new decisions, no collisions with D-001..D-206) - REQUIREMENTS.md: append REQ-099..REQ-118 (20 net-new; ingress 099-102, drift 103-113, CLI 114-118) - ROADMAP.md: update v0.11 section (fold ingress into P15.5 per Q3=A, expand P09/P10, add CLI REQs to P05/P06/P14a/P14b per Q2=C) ---ci--- project: orca phase: 0 milestone: v0.11 status: specify ---/ci---
37 KiB
Requirements: Orca
The canonical requirements table. Each row carries the REQ-ID, the milestone it belongs to, the requirement summary, priority, the phase that addresses it, and the current status. This single table is the source of truth — superseded any per-milestone status tables in earlier versions of this file.
| ID | Requirement | Priority | Phase | Status |
|---|---|---|---|---|
| REQ-001 | Go 1.25+ toolchain support | High | v0.1 P01 | Complete |
| REQ-002 | CLI-first interface for all operations (single binary) | High | v0.1 P01 | Complete |
| REQ-003 | Offline-first operational mode (no cloud deps) | High | v0.1 | Complete |
| REQ-004 | Basic task deployment (single-node process execution) | Medium | v0.1 P03 | Complete (single-node); multi-node dispatch in v0.2 P02 |
| REQ-005 | Local state storage via modernc/sqlite (CGO-free) | Medium | v0.1 P02 | Complete |
| REQ-006 | Security-first audit logging via log/slog |
High | v0.1 P04 | Complete |
| REQ-007 | CoreCI full release flow integration via .coreci.yml |
High | v0.1 P06 | Complete (per-phase releases) |
| REQ-008 | Structured JSON logging (slog) | High | v0.1 P05 | Complete |
| REQ-009 | HCL/YAML job spec parsing | Medium | v0.1 P03 | Complete |
| REQ-010 | --json output flag for machine consumption |
High | v0.1 P01 | Complete |
| REQ-011 | mTLS for inter-node communication | Medium | v0.2 P01 | Complete (P01 shipped v0.2.1) |
| REQ-012 | ~/.orca/config.hcl and /etc/orca/orca.hcl config locations |
Low | v0.1 P01 | Complete (CLI uses ~/.orca/ + ORCA_DB env) |
| REQ-013 | Pre-push git hook triggers CoreCI on every push | High | v0.1 P01 | Complete |
| REQ-014 | gosec + govulncheck in CI pipeline |
High | v0.2 P03 | Complete (P10 shipped v0.2.3) |
| REQ-015 | MIT LICENSE | Low | v0.1 P01 | Complete |
| REQ-016 | README.md with quickstart | Medium | v0.1 P01 | Complete |
| REQ-017 | context.Context propagation in all I/O |
High | v0.1 | Complete |
| REQ-018 | Error wrapping with fmt.Errorf("...: %w", err) |
High | v0.1 | Complete |
| REQ-019 | Cobra CLI framework | High | v0.1 P01 | Complete |
| REQ-020 | HCL parser integration (hashicorp/hcl) |
Medium | v0.1 P03 | Complete |
| REQ-021 | os/exec with WaitDelay (Go 1.25+) |
Medium | v0.1 P03 | Complete |
| REQ-022 | iter.Seq for streaming job lists (Go 1.25+) |
Low | v0.3 P01 | Complete (v0.3 P01 shipped v0.3.1) |
| REQ-023 | Self-signed mTLS cert generation | Medium | v0.2 P01 | Complete (P01 shipped v0.2.1) |
| REQ-024 | Makefile with standard targets |
High | v0.1 P01 | Complete |
| REQ-025 | Bounded cert rotation history: retain last N=3 server certs per node for rollback | Medium | v0.2 P01 | Complete (P01 shipped v0.2.1) |
| REQ-026 | Trusted-CA fingerprint pinned in config; daemon refuses to start on mismatch | High | v0.2 P01 | Complete (P01 shipped v0.2.1) |
| REQ-027 | govulncheck runs in offline mode in CI (no vuln.go.dev calls; pre-mirrored DB or -format json + jq gate) |
High | v0.2 P03 | Complete (P10 shipped v0.2.3) |
| REQ-028 | HCL/YAML schema for NodeCapacity declaration (orca node join flag and/or ~/.orca/node.hcl) |
High | v0.2 P02 | Complete (P09 shipped v0.2.2; orca node capacity CLI) |
| REQ-029 | gitleaks baseline file committed to repo to suppress pre-existing .env SHA-1 leak in git history |
Medium | v0.2 P03 | Complete (P10 shipped v0.2.3) |
| REQ-030 | --watch output format mode: table (default) vs streaming one-line JSON per event |
Low | v0.3 P01 | Complete (v0.3 P01 shipped v0.3.1) |
| REQ-031 | go test -race enabled in CI for all v0.2 packages |
High | v0.2 P01–P04 | Complete (P10; .coreci.yml test pipeline runs -race) |
| REQ-032 | orca doctor subcommand for diagnostics (CA/cert health, db integrity, peer reachability) |
Medium | v0.2 P01 / v0.3 P02 | Complete (cert checks P01 v0.2.1; network + db P02 v0.3.2) |
| REQ-033 | Cert file mode enforcement: 0600 for keys, 0644 for certs (refuses to start on violation) | High | v0.2 P01 | Complete (P01 shipped v0.2.1) |
| REQ-034 | Cert proactive rotation alarm: structured slog WARN 30 days before not_after |
Medium | v0.2 P01 | Complete (P01 shipped v0.2.1) |
| REQ-035 | orca cert show redacts private key material from default and --json output |
High | v0.2 P01 | Complete (P01 shipped v0.2.1) |
| REQ-036 | Server cert SAN validation: SAN entries (DNS + IP) populated at sign-time; refuses to sign a CSR without them | High | v0.2 P01 | Complete (P01 shipped v0.2.1) |
| REQ-037 | X-Orca-Idempotency-Key header on cross-node POST; dispatcher retries only when header is present |
Medium | v0.2 P02 | Complete (P09 shipped v0.2.2; internal/transport/idempotency.go) |
| REQ-038 | Structured slog fields for mTLS failures: event=mtls.handshake, peer, cert_fp, err |
Medium | v0.2 P01 | Complete (P01 shipped v0.2.1) |
| REQ-039 | .gitleaks.toml extended with stopwords for test data paths and CA cert PEM blocks |
Medium | v0.2 P03 | Complete (P10 shipped v0.2.3) |
| REQ-040 | .golangci.yml unified lint config superseding per-tool invocations |
Low | v0.2 P03 | Complete (P10 shipped v0.2.3) |
| REQ-041 | Unified namespace root via ORCA_HOME for all components (db, certs, init, daemon) |
High | v0.5 P1 | Complete (P1 shipped v0.4.2) |
| REQ-042 | --system flag selects system-level namespace root /root/.orca |
High | v0.5 P1 | Complete (P1 shipped v0.4.2) |
| REQ-043 | install.sh 1-liner pulling release binary from public Gitea URL; user-level default, --system for system-level |
High | v0.5 P2 | Complete (P2 shipped v0.4.3) |
| REQ-044 | install.sh in-place update preserves config/state; idempotent re-run |
High | v0.5 P2 | Complete (P2 shipped v0.4.3) |
| REQ-045 | Gitea repo + releases publicly accessible (unauthenticated download) | High | v0.5 P0 | Complete (P0 ship: repo + org visibility public) |
| REQ-046 | Docker image published to Gitea container registry per release | Medium | v0.5 P3 | Complete (P3 shipped v0.4.4) |
v0.1 Milestone Summary
Status: Complete — all 6 phases shipped (P00–P06) plus P07 backfill,
4-layer verification passed at every phase, tagged v0.2.0 per
run.md versioning logic (next-minor after all feature-patches
v0.1.1..v0.1.7 ship).
Coverage: 21/24 v0.1-declared requirements complete by v0.1 ship; the 3 deferred (REQ-011, REQ-014, REQ-022, REQ-023) all moved to v0.2. Plus REQ-025..REQ-040 (16 net-new) added by v0.2 IDEATE stage.
v0.2 Milestone Summary
Status: Functionally Complete (pending merge to main) — P08 (mTLS),
P09 (scheduling), P10 (security scan) all shipped to the
milestone/v0.2-networking-observability-security branch as v0.2.1,
v0.2.2, v0.2.3. The milestone branch has NOT been merged to main yet.
REQ-022/030 (iter.Seq streaming) and REQ-032 (doctor network/db) were
deferred to v0.3.
v0.3 Milestone Summary
Status: Complete — P01 (iter.Seq streaming, v0.3.1) and P02 (doctor network+db, v0.3.2) both shipped. REQ-022, REQ-030, REQ-032 all complete. Re-init SPECIFY audit confirmed all other v0.2-deferred REQs (014, 027, 028, 029, 031, 037, 039, 040) already shipped in P08-P10.
Deferred to v0.4
- pprof endpoint on
orca daemon(idea I-308, 0.70 confidence): deferred to keep v0.2 lean; revisit in v0.3 once P02's dispatcher is stable.
v0.5 Milestone Summary
Status: Complete — all 3 execution phases + final review shipped. P0 (v0.4.1), P1 (v0.4.2), P2 (v0.4.3), P3 (v0.4.4), P4 final (v0.4.5). REQ-041..046 all complete. Repo + releases publicly accessible (REQ-045). Docker image published to Gitea container registry (REQ-046).
- P0 (v0.4.1): pre-execution + repo visibility flipped to public (REQ-045).
- P1 (v0.4.2): namespace unification —
ORCA_HOME+--system(REQ-041/042). - P2 (v0.4.3):
install.sh1-liner + in-place update (REQ-043/044) + README quickstart (REQ-016). - P3 (v0.4.4): Docker release — distroless image + Gitea container registry (REQ-046).
- P4 (v0.4.5): final review + audit + milestone release.
v0.6 Requirements — Node Bootstrap & Proxmox
| ID | Requirement | Priority | Phase | Status |
|---|---|---|---|---|
| REQ-047 | orca init auto-provisions CA + server cert + DB migrations + localhost node (idempotent; safe re-run) |
High | v0.6 P1 | Complete (P1 shipped v0.5.1) |
| REQ-048 | orca init registers a default localhost node with auto-detected OS via /etc/os-release ID |
High | v0.6 P1 | Complete (P1 shipped v0.5.1) |
| REQ-049 | Node schema extension: nodes.kind (localhost|linux|proxmox) + nodes.os columns (migration 0006, backward-compatible) |
High | v0.6 P1 | Complete (P1 shipped v0.5.1) |
| REQ-050 | orca node join --type proxmox SSH bootstrap via golang.org/x/crypto/ssh (new direct dep); password auth, deploy orca pubkey, create orca user (config-overridable), assign PVE role, drop sudoers allowlist; idempotent |
High | v0.6 P2 | Complete (P2 shipped v0.5.2) |
| REQ-051 | Proxmox least-privilege OrcaOperator PVE role (VM.Audit, Datastore.AllocateSpace, SDN.Use) + orca user + /etc/sudoers.d/orca allowlist (pct, qm, pvesh, apt-get, dpkg); config-overridable user/role names |
High | v0.6 P2 | Complete (P2 shipped v0.5.2; refined: pvesh excluded per AD-020, orca@pam per AD-019) |
| REQ-052 | orca doctor extensions: doctor os (verify localhost OS detection matches stored node row) + doctor proxmox (SSH-probe each kind=proxmox node with pveversion/pvecmd status, 3s timeout, PASS/WARN/FAIL); audit log all bootstrap + join actions |
Medium | v0.6 P3 | Complete (P3 shipped v0.5.3) |
v0.6 Milestone Summary
Status: Complete — all 3 execution phases + final review shipped. P0 (v0.5.0), P1 (v0.5.1), P2 (v0.5.2), P3 (v0.5.3), P4 final (v0.5.4). REQ-047..052 all complete.
- P0 (v0.5.0): pre-execution (specify → clarify → research → plan). 8 decisions (D-030..D-037).
- P1 (v0.5.1):
orca initfull bootstrap + schema 0006 (REQ-047/048/049). - P2 (v0.5.2): Proxmox SSH join + OrcaOperator role + sudoers (REQ-050/051).
- P3 (v0.5.3):
doctor os+doctor proxmox+ audit logging (REQ-052). - P4 (v0.5.4): final review + audit + milestone release.
v0.7 Requirements — Hardening & Completion
| ID | Requirement | Priority | Phase | Status |
|---|---|---|---|---|
| REQ-053 | orca cert command tree registered on root command (cert ca-init, cert gen, cert show, cert renew, cert fingerprint) — code exists in internal/cli/cert.go but is never AddCommand'd; unreachable today |
High | v0.7 P1 | Complete (P1 shipped v0.6.1) |
| REQ-054 | HCL config file parsing: internal/config package loads ~/.orca/config.hcl / /etc/orca/orca.hcl (keys: db_path, listen_addr, ca_path, server_cert_path, server_key_path, node_capacity); merge precedence flag > env > file > default; --config flag on root command |
High | v0.7 P2 | Complete (P2 shipped v0.6.2) |
| REQ-055 | Test coverage uplift: every package ≥ 50% — adds tests for internal/engine (executor, dispatcher, peer), internal/transport (mtls, dispatch, handshake_log), internal/proxmox (bootstrap SSH path), internal/audit |
Medium | v0.7 P3 | Complete (P3 shipped v0.6.3) |
| REQ-056 | --pprof <addr> opt-in flag on orca daemon (default disabled); net/http/pprof mounted on a separate mux, never on the mTLS daemon listener |
Low | v0.7 P4 | Complete (P4 shipped v0.6.4) |
v0.8 Requirements — Coverage & Trust Hardening
| ID | Requirement | Priority | Phase | Status |
|---|---|---|---|---|
| REQ-057 | Test coverage uplift round 2: raise internal/engine (8.3%), internal/proxmox (5.1%), internal/cli (27.6%), internal/transport (26.3%), internal/store (46.7%), internal/jobspec (47.6%) to ≥ 70%; add first tests for internal/audit, internal/certpaths, cmd/orca (currently 0%) to ≥ 50% (D-047 tiered floor) |
High | v0.8 P1 | Complete (P1 shipped v0.7.1; all 9 packages exceeded floor) |
| REQ-058 | --host-key-fingerprint <SHA256:base64> pre-pin flag on orca node join (validated when --type proxmox): when supplied, join fails fast if the SSH host key's OpenSSH SHA-256 fingerprint does not match; supersedes TOFU (D-035) for pre-pinned deployments (D-044, D-045) |
Medium | v0.8 P2 | Complete (P2 shipped v0.7.2) |
| REQ-059 | orca node key-reset <node> command: clears the persisted SSH host key entry for the node from ~/.orca/known_hosts only (local, not remote authorized_keys — D-046); audit-logs event=node.key_reset; next doctor proxmox/dispatch re-pins via TOFU or --host-key-fingerprint |
Low | v0.8 P2 | Complete (P2 shipped v0.7.2) |
| REQ-060 | Requirement-status hygiene sweep: REQUIREMENTS.md v0.7 rows were stale ("Pending" after ship); add a verify-stage assertion that every REQ listed as Complete in ROADMAP.md has a matching Complete row in REQUIREMENTS.md, enforced by make verify-reqs |
Medium | v0.8 P3 | Complete (P3 shipped v0.7.3) |
v0.9/v0.10 Requirements — Re-architecture Foundation & Production Hardening
The v0.9/v0.10 milestones supersede the shipped v0.1–v0.8 architecture per the
adopted PRD (.ciagent/PRD_v0.9.md). The re-architecture is justified on six
grounds recorded in the PROJECT.md Supersession Table. 30 net-new requirements
(REQ-061..REQ-090) derive from the v0.9 IDEATION; their phase placement and
binding grill conditions (C-01..C-19) are documented in IDEATION_v0.9.md
and GRILL_v0.9.md.
| ID | Requirement | Priority | Phase | Status |
|---|---|---|---|---|
| REQ-061 | orca daemon deprecation command and build-tag removal path: v0.9 emits deprecation warning + still runs (dual-write window); v1.0 repurposes to orca daemon drain-and-stop (stops v0.8 daemons on peers via SSH, confirms workloads survive via systemd); post-v1.0 the command and internal/daemon/ are deleted. // Deprecated Go doc comments + slog.Warn on every run (I-M-001) |
High | v0.10 P14 (warn v0.10) | Pending |
| REQ-062 | Coverage follow-ups: 3 zero-test packages (internal/audit, internal/certpaths, cmd/orca) + internal/cli to 70% floor; once daemon.go is deprecated/removed the exclusion reason disappears and the floor applies to the whole package; all net-new subsystems carry a 70% floor from their first phase (I-M-002) |
Medium | v0.9 P0X + each new pkg | Complete |
| REQ-063 | known_hosts flock concurrency gap (deferred P1 from REVIEW_v0.8 A2): add flock-style advisory lock (stdlib syscall.Flock wrapper) around the read-modify-write in TOFUHostKeyCallback capture path (bootstrap.go:290-302) and ResetHostKey (bootstrap.go:479-523); lock file at cluster/known_hosts.lock (R-002) (I-M-003) |
Medium | v0.9 P0a1 | Complete |
| REQ-064 | HCL→Markdown jobspec adapter/bridge layer: keep internal/jobspec/spec.go as legacy HCL path behind // Deprecated; add internal/jobspec/markdown.go (canonical) + internal/jobspec/dispatch.go (extension-based dispatcher: .md→Markdown, .hcl→legacy, .yaml→Markdown-with-empty-body); unified *WorkloadSpec populated via adapter; preserves orca job run old-spec.hcl during migration window (I-M-004) |
High | v0.9 P0b | Complete |
| REQ-065 | orca doctor --legacy-paths detection: detects v0.8 residue (orca.db at ORCA_HOME root, ca.crt/ca.key, config.hcl, flat server.crt, namespace column in any *.db); outputs list of legacy artifacts with migration recommendations; the detection half of v0.10-P14 (I-M-005) |
Medium | v0.10 P14c | Pending |
| REQ-066 | Legacy CA state migration to step-ca: orca upgrade --to-v1.0 --import-ca reads ~/.orca/ca.key, initializes step-ca with it, re-issues workload SVIDs; preserves audit history even if live trust root changes (I-M-006). Gated by C-07 |
High | v0.10 P14a | Pending |
| REQ-067 | Fuzz test harness for Markdown frontmatter parser: testing.F fuzz target in internal/jobspec/markdown_test.go round-trips random frontmatter+body through ParseMarkdown asserting byte-exact body preservation; corpus of adversarial fixtures (CRLF, BOM, no-frontmatter, empty-frontmatter, frontmatter-with-only-separator) (I-M-007) |
Medium | v0.9 P0b | Complete |
| REQ-068 | Deprecation warnings on removed/repurposed CLI subcommands: each removed/changed command (orca cert, orca node join mTLS semantics, orca job run <spec.hcl>) emits slog.Warn deprecation banner with v1.0 replacement except under orca upgrade; --no-deprecation-warnings global flag via root.go PersistentPreRunE (I-M-008) |
Low | v0.9 P0X + v0.10 P13 | Complete |
| REQ-069 | internal/config/config.go HCL config demotion via adapter: keep internal/config/ as legacy_config.go with // Deprecated; add internal/config/markdown.go for new Markdown-frontmatter loader (R-014); root.go dispatches on file extension (.hcl→legacy, .md→new); --config semantics: .hcl read-only legacy, .md canonical (I-M-009) |
High | v0.9 P0a1 | Complete |
| REQ-070 | internal/certpaths/ replacement with multi-namespace path resolver: new internal/paths package with paths.NamespaceDir(ns), paths.ClusterDir(), paths.CacheDB(), paths.MasterKey(), paths.NSDb(ns), paths.NSEnv(ns), paths.NSSecrets(ns); keep certpaths as thin shim for v0.8 compat then remove post-v1.0 (R-002) (I-M-010) — highest blast radius |
High | v0.9 P0a1 | Complete |
| REQ-071 | internal/store/ schema: per-namespace DBs, drop namespace column: store.Open gains namespace parameter (or caller passes paths.NSDb(ns)); migrate.go runs migrations per namespace DB; cert_repo (0004) removed (step-ca handles certs); audit_log moves to CLI-side cache DB (R-008) (I-M-011) |
High | v0.9 P0a1 + v0.10 P06 | Complete |
| REQ-072 | internal/transport/ deletion + SSH-push package: delete mtls.go, dispatch.go, handshake_log.go; extract retry/idempotency patterns into internal/sshpush/; existing transport.IdempotencyStore directly reusable (I-M-012). Deletion deferred to v0.10-P14 to keep dual-write window open |
High | v0.9 P00 (delete v0.10 P14) | Complete |
| REQ-073 | SSH-push transport layer design: connection pooling (reuse *ssh.Client per peer), idempotency (content-addressed filenames), retry (exponential backoff 100ms×2 cap 5s max 5), timeout (30s SCP, 10s exec), fan-out (errgroup bounded concurrency default 8), known_hosts reuse proxmox.TOFUHostKeyCallback (I-B-001) |
High | v0.9 P01 (design P0a1) | Complete |
| REQ-074 | Emitter template system (Layer 4): internal/emitter/ package with Emitter interface Render(spec *WorkloadSpec, node *Node) ([]File, error); implementations systemdEmitter/traefikEmitter/syncthingEmitter/socketEmitter; SSH-push SCPs []File atomically (write-to-tmp + rename); emitters registered per kind + runtime (I-B-002) |
High | v0.9 P0c | Complete |
| REQ-075 | Lead applier execution model: CLI renders transaction bundle (tarball + apply.sh + verify.sh) on operator host, SCPs to lead's /run/orca/txns/<txn-id>/, lead's systemd timer runs apply.sh idempotently, CLI polls txn status via SSH; bash scripts generated by emitter not hand-written (I-B-003). Gated by C-09 |
High | v0.10 P10 (design v0.10) | Pending |
| REQ-076 | step-ca integration: orca init runs step ca init on lead; CLI SSHs to lead, installs step-ca via apt, stores step-ca.json; workload SVIDs via step ca token (JWE minted by CLI) → step ca certificate; SPIFFE ID as SAN; new internal/stepca/ package wraps step CLI via SSH (I-B-004). Reverses AD-010 per override justification ground 2 |
High | v0.9 P07 + v0.10 P02 | Complete |
| REQ-077 | Traefik dynamic config generation + atomic reload: Traefik emitter renders /etc/traefik/dynamic/orca-<ns>-<svc>.yaml with backends (socket paths R-007), health checks, mTLS config pointing at step-ca root; atomic reload via tmpfile+fsync+rename triggering fsnotify; drain writes weight=0 or removes backend (I-B-005). Gated by C-10 |
High | v0.9 P02 | Complete |
| REQ-078 | Runtime abstraction interface (5 backends): Runtime interface in internal/runtime/ with Prepare/Start/Stop/Status; processRuntime (wraps existing executor.go), wasmRuntime (wasmtime via SSH), podmanRuntime, pveVMRuntime (qm via proxmox SSH), pveCTRuntime (pct); runtimeRegistry keyed by runtime: frontmatter value; Alloc carries runtime field changeable on migration (I-B-006). Split P07a/b/c per PC-10. P07b gated by C-01 |
High | v0.9 P07a/b/c | Complete |
| REQ-079 | Transaction bundle format + N-peer atomicity: bundle = tarball with desired-state.json + apply.sh + verify.sh + rollback.sh + manifest.sig (signed with master.key); content-addressed <txn-id>=sha256(desired-state.json) stored in cluster/txns/<txn-id>/; lead applies to self first then fans out; failure on any peer runs rollback.sh on applied peers (I-B-007). Gated by C-09 |
High | v0.10 P10 (design v0.10) | Pending |
| REQ-080 | Master key management + HKDF-SHA256 per-line .env.secrets encryption: cluster/master.key 32-byte random (generated at orca init using WriteAtomic pattern); each line `base64(nonce |
ciphertext | ||
| REQ-081 | Syncthing config rendering + folder-ID content-addressing: per-namespace Syncthing folder orca-<ns> with content-addressed folder ID sha256(ns + master-key-fingerprint); CLI renders config.xml per peer; Syncthing runs as systemd unit (emitted by systemd emitter); CLI discovers peers via cluster/peers/; migration works because new node joins folder and syncs before workload starts (I-B-009). Gated by C-02 + C-14 |
Medium | v0.9 P09 (spike v0.9 P00) | Complete |
| REQ-082 | Namespace inheritance resolver algorithm: DFS parent walker with visited set for cycle detection; _defaults/ implicit root (always exists, no parent); merge semantics: child overrides parent for scalars, arrays unioned (child adds to parent); pure function (no I/O) taking map[nsName→*NSConfig] returning map[nsName→*ResolvedNS] (I-B-010) |
High | v0.9 P0a2 | Complete |
| REQ-083 | CLI-side scheduler redesign: Score(node, workload) (score int, fits bool) where fits checks runtime compatibility + constraints, score is bin-packing (most free capacity = highest); Services pick count distinct nodes (anti-affinity default); DaemonSets pick all matching nodes; Job = one-shot; CLI-side not daemon-side (R-001) (I-B-011) |
High | v0.9 P05 (skeleton P0c) | Complete |
| REQ-084 | orca job lint category-driven lint engine: Linter runs Rule checks returning Finding{Category, Severity, Message, Explanation}; categories schema/runtime/security/migration/best-practice; --explain prints rationale; pure (no I/O) checks against static rules (I-B-012) |
Medium | v0.10 P11 | Pending |
| REQ-085 | v0.8→v1.0 migration ordering: v0.9 ships new parser + kinds + runtime + SSH-push alongside old daemon (dual-write window); orca job run dispatches on extension (.md→SSH-push, .hcl→old daemon); v0.10-P05 drains old daemons; v0.10-P14 converts remaining .hcl specs and removes daemon (I-C-001). Most important cross-cutting idea |
High | v0.9 P00 → v0.10 P14 | Complete |
| REQ-086 | "No orca on server" enforcement: orca doctor no-orca-on-server SSHs to each peer verifying no orca binary in PATH, no orca systemd service, no orca process, no /etc/orca/ directory; runs after v0.10-P05 before v0.10-P16; reuses v0.8 proxmox SSH session infrastructure (I-C-002). Implements grill C-13 |
High | v0.10 P14c | Pending |
| REQ-087 | Test infrastructure: hermetic 3-linux + 1-proxmox cluster pipeline: test/integration/ with docker-compose/vagrant creating 4 containers/VMs; Go test harness SSHes to each, runs CLI, asserts end-to-end workflows (ns create → workload submit → migrate → drain); proxmox simulated via mock pct/qm; v0.8 e2e tests (bootstrapE2ESetup) are foundation (I-C-003) |
Medium | v0.10 P08 (bootstrap v0.10) | Pending |
| REQ-088 | Security-engineer + network-engineer persona reactivation: reactivate security-engineer (step-ca provisioner model, SSH-push blast radius, Traefik edge, .env.secrets crypto) and network-engineer (socket exposure R-007, Syncthing P2P ports, Traefik routing); cross-cutting review not single phase (I-C-004). Implements grill C-05 | High | v0.9 P00 → v0.10 P16 | Complete |
| REQ-089 | Documentation rewrite: ARCHITECTURE.md/PROJECT.md/README + AD-010 supersession: v0.9-P00 adds "v0.9 Architecture (Supersedes v0.8)" section + banners + Superseded Decisions table; v0.10-P15 rewrites README quickstart for new curl | sh + orca init + orca ns create flow (I-C-005) | Medium | v0.9 P00 + v0.10 P15/P16 |
| REQ-090 | Dual-write window: v0.9 orca job run dispatches on extension (.md→SSH-push new path, .hcl→old daemon path) via parser dispatcher (REQ-064); daemon not removed until v0.10-P05; SSH-push path writes to separate systemd unit namespace (orca-v1-<alloc>.service) while daemon uses orca-<job>.service — no unit name overlap = no conflict (I-C-006) |
High | v0.9 P00 | Complete |
v0.10 Docs & Install Milestone Requirements
The following requirements are scoped to the v0.10 docs/cli-examples milestone. They cover the CLI reference documentation, jobspec reference, ingress guide, full-stack example jobspecs, README refresh, namespace.md v0.9 layout update, and the release/install pipeline fix that guarantees every Gitea release carries a Linux binary asset.
| ID | Requirement | Priority | Phase | Status |
|---|---|---|---|---|
| REQ-091 | docs/cli.md comprehensive CLI reference: every command/subcommand with synopsis, flags (name/type/default/description), and one-line example; global flags (--json, --system, --config, --no-deprecation-warnings); output modes (text vs --json, --watch table vs NDJSON); exit codes; deprecated surface (orca daemon, orca cert, orca node join mTLS path, legacy .hcl jobspec) flagged with callout boxes pointing to v0.10 removal |
High | v0.10 P2 | Complete |
| REQ-092 | docs/jobspec.md markdown frontmatter schema reference: all top-level keys, block reference (runtime, ports, env/secrets, volumes, restart, update, service, health, lifecycle, constraints, affinity, tasks), kinds matrix (Job/Service/DaemonSet required vs allowed), CEL subset grammar, body byte-exact preservation (R-015), deprecated HCL form callout |
High | v0.10 P2 | Complete |
| REQ-093 | docs/ingress.md Traefik ingress reference: kind: Service implies Traefik route (D-175), R-007 socket-vs-TCP-bind semantics, generated Traefik YAML shape (routers/services/healthCheck), atomic reload (C-10), drain (weight: 0), TLS (certResolver, trust domain, step-ca), worked-example pointer to examples/full-stack/, v0.10 forward limitations (socket activation, transactional update) |
High | v0.10 P2 | Complete |
| REQ-094 | examples/full-stack/ directory with 5 valid jobspecs (web-app.md, api.md, worker.md, log-shipper.md, postgres.md) exercising ports/service/health/restart/update/constraints/affinity/lifecycle/task-groups/volumes/replication/DaemonSet; rendered/ subdir showing the Traefik dynamic YAML + systemd units orca generates; README.md walkthrough (init → node join → capacity set → ns create → job run → list --watch → inspect rendered) |
High | v0.10 P3 | Complete |
| REQ-095 | README.md refresh: status line (v0.9 complete, v0.10 in progress), install --version example updated to current tag, subcommand table expanded to all commands with deprecation markers, update-in-place example updated, development targets complete (verify-reqs, security-scan, test-race, changelog), new Documentation + Examples sections linking all docs/*.md and examples/ |
High | v0.10 P4 | Complete |
| REQ-096 | docs/namespace.md v0.9 multi-namespace layout update: replace v0.8 flat path table with v0.9 layout (cluster/, _defaults/, per-ns db/jobs/alloc/ns.md), ORCA_HOME/--system resolution, orca ns subcommand cross-link, v0.8 flat layout flagged deprecated |
Medium | v0.10 P4 | Complete |
| REQ-097 | scripts/release.sh release pipeline fix: cross-build linux-amd64 tarball regardless of host arch (GOOS=linux GOARCH=amd64 go build); post-create asset verification (query /releases/tags/$VERSION, assert the tarball in attachments, retry/fail loudly if missing). Guarantees every Gitea release carries the Linux binary asset (root cause of v0.4.5 install) |
High | v0.10 P1 | Complete |
| REQ-098 | scripts/install.sh asset fallback walk: if the latest/pinned release lacks the matching orca-<ver>-<os>-<arch>.tar.gz, walk backward through /releases?limit=20 to the most recent release that has it, with a clear warning. Keeps pulling from releases (not main). Optional --check dry-run mode |
High | v0.10 P1 | Complete |
v0.11 Production Hardening Milestone Requirements
The following requirements (REQ-099…REQ-NN) are scoped to the v0.11 production-hardening milestone. They cover the ingress hybrid default (R-017), drift detection (R-018/R-019/R-020), the systemd Path unit implementation (D-227…D-237), and five net-new CLI commands added per operator decision Q2=C.
Ingress hybrid (R-017, D-215…D-226)
| ID | Requirement | Priority | Phase | Status |
|---|---|---|---|---|
| REQ-099 | internal/emitter/nft.go: nftables emitter renders /etc/nftables.d/orca.nft with DNAT (:443→127.0.0.1:8443, :80→127.0.0.1:8080), SYN-flood tcp-flags filter, ora_rl rate-limit meter (default 100/s burst 200), orca_trusted_probes set; idempotent nft -f apply; atomic rule-set swap (R-017, D-217, D-218, D-222) |
High | v0.11 P15.5 | Pending |
| REQ-100 | Traefik static config emitter update: entryPoints.websecure.address changes from :443 to 127.0.0.1:8443 (default); entryPoints.web.address changes to 127.0.0.1:8080; --public-binding=traefik-on-public-ip opt-out emits :443/:80 instead; certs/mTLS/dynamic config unchanged (R-017, D-220, D-216) |
High | v0.11 P15.5 | Pending |
| REQ-101 | orca doctor nft: checks table inet orca-ingress exists, expected DNAT rules present, rate-limit meter present, /etc/nftables.d/orca.nft parses cleanly (nft -c -f), file hash matches latest applied txn; drift detection via hash comparison (R-018 critical_paths, D-221, D-226) |
High | v0.11 P15.5 | Pending |
| REQ-102 | orca nft CLI: show [--peer], diff --against <txn-id>, doctor (alias for orca doctor nft), country block add <cc-list> (opt-in GeoIP), rate limit set --rate N/s; all Layer-5 orchestrators that SSH into peers and parse nft output (D-223, D-222) |
Medium | v0.11 P15.5 | Pending |
Drift detection (R-018/R-019/R-020, D-227…D-237)
| ID | Requirement | Priority | Phase | Status |
|---|---|---|---|---|
| REQ-103 | internal/drift package: Detector interface (Watch, Aggregate, Remediate, Acknowledge), Event, Config, PathSpec, RemediationPolicy types; iter.Seq2[Event, error] per D-017; signal.NotifyContext per D-023 (R-018, D-236) |
High | v0.11 P10 | Pending |
| REQ-104 | orca drift CLI tree: watch [--interval=2s] [--paths=...] [--json], show [--peer], acknowledge <peer> <path>, remediate <peer> <path> [--force], config show, config validate; uses iter.Seq2 + signal.NotifyContext (D-236) |
High | v0.11 P10 | Pending |
| REQ-105 | systemd Path unit emitter: for each critical path, emit orca-drift-<name>.path (PathChanged=, RateLimitIntervalSec=1s, RateLimitBurst=5) + orca-drift-<name>.service (Type=oneshot, ExecStart=/usr/local/bin/orca-drift-notify.sh %f, User=orca, security hardening: NoNewPrivileges, ProtectSystem=strict); R-001-clean (R-018, D-227, D-228) |
High | v0.11 P10 | Pending |
| REQ-106 | scripts/orca-drift-notify.sh: receives changed path as $1, computes sha256 (or "DELETED"), writes event JSON to /etc/orca/state/drift-events/<event-id>.json (event_id, ts, host, path, status, new_sha256, latest_txn, triggered_by); stateless, idempotent; flock for serialization (D-228) |
High | v0.11 P10 | Pending |
| REQ-107 | scripts/orca-aggregate.sh extension: existing 10s aggregator cadence (C-11) now also rsyncs each peer's /etc/orca/state/drift-events/, validates event hashes against /etc/orca/state/applied/<txn>/manifest.json, triggers orca-remediate.sh for auto-remediable paths, consumes (deletes) event files on peers (D-229, D-237) |
High | v0.11 P09 | Pending |
| REQ-108 | scripts/orca-remediate.sh: re-pushes latest applied txn's per-peer render tree via rsync, runs peer-side applier; 5-min cooldown per path applies ONLY on successful remediation (transient failures retry next tick); cooldown state at /etc/orca/state/remediation-cooldown/ (D-231, D-232 refined per CLARIFY C4) |
High | v0.11 P10 | Pending |
| REQ-109 | Drift cadence config in config.md (kind: ClusterConfig): drift.polling.{enabled,default_interval,max_concurrent_peers}, drift.paths.{critical,standard,excluded} (each with systemd_path_unit, interval, paths list), drift.remediate.{auto,auto_paths,require_approval_paths,notify_on_remediation}; critical defaults: Traefik dynamic, nftables, sudoers, orca-alloc services; secrets + /run/orca/* + drift-events dir excluded (R-018, D-231, D-234) |
High | v0.11 P10 | Pending |
| REQ-110 | Pre-flight consistency gate in applier: orca-pull.sh (C-09) refuses new txns if drift detected on the target peer/namespace; --force flag overrides; per-namespace scoping means a drifted peer in ns-A does not block ns-B (R-020, Q4=A) |
High | v0.11 P10 | Pending |
| REQ-111 | orca system user on peers: peer-setup emits useradd -r orca (system account, no login shell); orca-drift-*.service runs as User=orca Group=orca; SSH key access to lead for aggregator; idempotent at peer setup (net-new operational requirement from doc 5) |
High | v0.11 P10 | Pending |
| REQ-112 | NFS detection at peer setup: orca node join / peer-setup detects NFS mounts on orca state dirs; if /etc/orca is on NFS, systemd Path units are disabled for those paths and polling is the only detection; logs a warning (D-233) |
Medium | v0.11 P10 | Pending |
| REQ-113 | orca job restart <name>: restarts an allocation to pick up EnvironmentFile drift; goes through normal allocation lifecycle (not file-level remediation); triggers on drift of /etc/orca/allocs/<id>/env (D-235) |
Medium | v0.11 P10 | Pending |
Net-new CLI surface (Q2=C — all five commands added to v0.11)
| ID | Requirement | Priority | Phase | Status |
|---|---|---|---|---|
| REQ-114 | orca cluster rotate-lead: moves cluster CA + lead state to a new bare-Linux peer (R-003 enforces bare-Linux-only lead); workloads keep running (certs already distributed); SSH key rotation; idempotent (Q2=C, folds into P14b daemon cutover) |
High | v0.11 P14b | Pending |
| REQ-115 | orca upgrade --to-vX: thin wrapper around install.sh + orca restore (binary upgrade only, not full cluster rolling upgrade); handles Traefik binding cutover from :443 to 127.0.0.1:8443 for existing v0.9/v0.10 clusters (R-017 migration path, CLARIFY C1, C2=a thin wrapper); full cluster-rolling-upgrade defers to v1.x (Q2=C) |
High | v0.11 P14a | Pending |
| REQ-116 | orca job migrate <name> --to <node>: drain+reschedule composite (uses P05 drain + P06 alloc history); live-migrate with storage replication defers to v1.x (CLARIFY C3=a); idempotent (Q2=C) |
Medium | v0.11 P05 | Pending |
| REQ-117 | orca logs --all-nodes --since 5m: aggregates journald logs across peers via SSH; uses P06 alloc-history cache DB; iter.Seq streaming per D-017; --since duration flag; --all-nodes fans out (Q2=C, folds into P06) |
Medium | v0.11 P06 | Pending |
| REQ-118 | orca doctor mTLS: verifies trust chain (CA → server cert → workload SVIDs exist + not expired) AND live mTLS handshake probe to each peer (reuses P01 metrics endpoint + P01.5 SPIFFE spike infra); both chain verification + live probe (CLARIFY C5, Q2=C, folds into P15.5) |
High | v0.11 P15.5 | Pending |
Scope notes
- REQ-099…REQ-118 = 20 net-new requirements (REQ count grows 98→118).
- No new phases added (Q3=A folds ingress into P15.5; Q2=C folds CLI commands into existing phases).
- P09 expands (REQ-107 aggregator extension); P10 expands (REQ-103…REQ-113, the largest phase); P15.5 expands (REQ-099…REQ-102 ingress + REQ-118 mTLS doctor).
- P05 gains REQ-116 (migrate); P06 gains REQ-117 (logs --all-nodes); P14a gains REQ-115 (upgrade); P14b gains REQ-114 (rotate-lead).