Jon Chery
dfacfea377
fix(P03): txn apply path allowlist (REQ-121, F5)
...
---ci---
project: orca
phase: 3
milestone: v0.12
status: execute
---/ci---
apply.sh python heredoc now validates every path in desired-state.json
against a prefix allowlist (/etc/orca/, /etc/traefik/orca*,
/etc/systemd/system/orca-*, /etc/nftables.d/orca*, /etc/syncthing/orca*).
Rejects with exit 7 on mismatch. Also rejects .. traversal and relative
paths. HMAC-signed manifest unchanged. 8 regression tests including
/etc/orca/../../shadow traversal attempt.
2026-08-07 10:56:25 +00:00
Jon Chery
5d115fc4b7
fix(P02): namespace path traversal (REQ-120, F4)
...
---ci---
project: orca
phase: 2
milestone: v0.12
status: execute
---/ci---
Add ns.ValidateName rejecting .., /, \, leading -, null bytes,
control chars, spaces, >128 chars, and reserved 'cluster'. Wire into
ns create/delete/inspect/validate/inherit/set-constraint + --parent
flag. Fuzz test + 14 traversal regression tests. No namespace dir can
escape ORCA_HOME.
2026-08-07 10:55:18 +00:00
Jon Chery
ce2441f312
fix(P01): command injection in podman/wasm runtimes (REQ-119, F3)
...
---ci---
project: orca
phase: 1
milestone: v0.12
status: execute
---/ci---
shellQuote the jobspec-supplied command string (cmdStr) before
interpolating into SSH exec in podman.go (Start) and wasm.go (Start).
Previously cmdStr was interpolated unquoted, allowing a malicious
jobspec command with shell metacharacters (; | $() backticks newline
> <) to inject commands on the peer.
Fixes:
- internal/runtime/runtime.go: add shellQuote helper (mirrors
internal/sshpush.shellQuote; duplicated to avoid import cycle).
- internal/runtime/podman.go: Start quotes name + cmdStr; Stop/rm/
inspect quote name (defense-in-depth).
- internal/runtime/wasm.go: Start uses env 'ORCA_ALLOC_ID=<id>' (so
the UUID-style alloc ID is safely assigned) and shellQuote(cmdStr).
Tests: 21 new injection regression tests (10 podman + 9 wasm + 2 image)
covering ; && | $() backticks newline $IFS > < (). All pass. Existing
runtime tests still pass. go vet + gofmt clean.
2026-08-07 10:49:08 +00:00
Jon Chery
8d1cdceb5c
feat(P15.5): threat model (C-19) + ingress hybrid (R-017, REQ-099..102) + doctor mTLS (REQ-118)
...
Sub-wave 1: internal/emitter/nft.go (nftables emitter, DNAT :443→127.0.0.1:8443, rate-limit, SYN-flood filter); Traefik static config 127.0.0.1:8443 binding (D-220); orca doctor nft; orca nft CLI (show/diff/doctor/country-block/rate-limit).
Sub-wave 2: docs/threat-model.md (R-017 trust boundary, R-020 deadlock, D-234 secret exclusion, orca user blast radius, step-ca SPOF); orca doctor mTLS (chain verification + live handshake probe, C5).
---ci---
project: orca
phase: 15.5
milestone: v0.11
status: execute
---/ci---
2026-08-07 08:35:06 +00:00
Jon Chery
c5048822e5
feat(P14b,P14c): daemon cutover + rotate-lead (REQ-114) + mixed-version tolerance (REQ-065, REQ-086, C-13)
...
P14b: orca cluster cutover (stop v0.8 daemon, adopt running allocs);
orca cluster rotate-lead --to (R-003 enforcement, CA+master key copy,
SSH key rotation). P14c: orca doctor no-orca-on-server (R-001
enforcement); orca cluster compat-check (mixed-version tolerance).
---ci---
project: orca
phase: 14b
milestone: v0.11
status: execute
---/ci---
2026-08-07 08:18:12 +00:00
Jon Chery
9a28dc907b
feat(P14a): v0.8→v1.0 data migration (REQ-066, C-07) + orca upgrade (REQ-115, C-25, C-27)
...
internal/migration/migrate.go: Migratev08tov11 (flat→multi-ns, schema
migration, CA import to step-ca, config.hcl preserve). internal/cli/
upgrade.go: orca upgrade --to (thin wrapper, R-017 binding cutover
with C-25 post-verify+rollback, C-27 orca user creation, --import-ca,
--dry-run). Tests: detect/migrate/dry-run/idempotent, cutover verify/
rollback, user creation.
---ci---
project: orca
phase: 14a
milestone: v0.11
status: execute
---/ci---
2026-08-07 08:00:10 +00:00
Jon Chery
97b88a703c
feat(P13): ns subcommands (inherit, set-constraint) + deprecation warnings (REQ-068)
...
orca ns inherit <name> --parent (cycle detection), ns set-constraint
<key>=value>. Deprecation warnings on orca cert ca-init/gen/renew
(step-ca replaces) and .hcl jobspec (R-013). --no-deprecation-warnings
suppresses all.
---ci---
project: orca
phase: 13
milestone: v0.11
status: execute
---/ci---
2026-08-07 07:47:28 +00:00
Jon Chery
020aa01623
feat(P11,P12): orca job lint (REQ-084) + orca job verify (dry-run txn)
...
P11: orca job lint <spec.md> — schema/CEL/body/migration/best-practice
checks; --explain, --format json; exit 0/1 by errors found.
P12: orca job verify <spec.md> — dry-run txn (render + stage + verify
without apply); reports planned allocs/files/units; no side effects;
--namespace, --json.
---ci---
project: orca
phase: 11
milestone: v0.11
status: execute
---/ci---
2026-08-07 07:29:44 +00:00
Jon Chery
03f3585f16
feat(P10b): drift detection (R-018/R-019/R-020, REQ-103..113)
...
internal/drift/drift.go: Detector (Watch via iter.Seq2, Aggregate,
Remediate with cooldown-on-success, Acknowledge), Config with tiered
cadence (critical 5s + Path units, standard 30s, default 60s).
internal/cli/drift.go: orca drift {show,watch,acknowledge,remediate,
config}. internal/emitter/drift_path.go: systemd Path+service unit
emitter (User=orca, ProtectSystem=strict). scripts/orca-drift-notify.sh
(sha256 event JSON), orca-remediate.sh (cooldown-on-success, transient
retry). Pre-flight gate (R-020, --force + per-ns scoping). orca
system user (REQ-111), NFS detection (D-233), orca job restart for
EnvironmentFile drift (D-235).
---ci---
project: orca
phase: 10b
milestone: v0.11
status: execute
---/ci---
2026-08-07 07:17:41 +00:00
Jon Chery
635e07e7a5
feat(P10a): transactional plane (REQ-075, REQ-079; C-09, C-23)
...
internal/txn/txn.go: Bundle (desired-state + apply/verify/rollback
scripts + signed manifest), RenderBundle (content-addressed txn-id),
Stage (SCP to lead), Apply (idempotent + rollback on failure).
scripts/orca-pull.sh: C-09 failure contract (idempotent, bounded
retry, deterministic, structured syslog) + C-23 (cluster-wide vs
ns-scoped --force distinction). internal/cli/txn.go: orca txn
apply/list/show/rollback CLI.
---ci---
project: orca
phase: 10a
milestone: v0.11
status: execute
---/ci---
2026-08-07 06:28:34 +00:00
Jon Chery
5cbe3020d3
feat(P09): collector + aggregator (C-11/C-12/C-14) + drift aggregation (REQ-107)
...
scripts/orca-aggregate.sh: 10s aggregator, cluster.json merge +
drift-events rsync + remediation trigger (P10b stub). scripts/orca-
watchdog.sh: C-11 starvation detection. internal/cli/collector.go:
orca collector start/stop/status. Tests: CLI + bats.
---ci---
project: orca
phase: 09
milestone: v0.11
status: execute
---/ci---
2026-08-07 06:14:16 +00:00
Jon Chery
f530c9a3f7
feat(P07): recovery (orca restore) — verified restore + alloc protection
...
Extend restore with --dry-run (extract to temp, report, no write),
running-alloc protection (refuse without --force; stop+restart with
--force), post-restore verification (master key, namespaces, DBs),
audit log entry.
---ci---
project: orca
phase: 07
milestone: v0.11
status: execute
---/ci---
2026-08-07 05:47:01 +00:00
Jon Chery
c8cf2e41e5
feat(P06): alloc history (REQ-071) + logs --all-nodes (REQ-117)
...
internal/store/alloc_history.go: AllocHistoryRepo (Record/List/Evict)
in orca_cache.db with 7-day TTL eviction goroutine. internal/cli/logs.go:
orca logs --all-nodes --since 5m with iter.Seq streaming, SSH fanout,
journalctl JSON parsing, signal.NotifyContext cancellation, --json output.
---ci---
project: orca
phase: 06
milestone: v0.11
status: execute
---/ci---
2026-08-07 05:36:30 +00:00
Jon Chery
41bcf0a6bf
feat(P05): drain + daemon drain-and-stop (REQ-061) + job migrate (REQ-116)
...
orca node drain <host>: marks draining, stops allocs via SSH, marks
drained. orca daemon drain-and-stop: stops v0.8 daemons on peers.
orca job migrate <name> --to <node>: drain+reschedule composite
(C3=a, not live-migrate). Node states: draining, drained.
---ci---
project: orca
phase: 05
milestone: v0.11
status: execute
---/ci---
2026-08-07 05:17:01 +00:00
Jon Chery
f61ef2aa9e
feat(P04): backup/restore — signed tarball (HMAC-SHA256)
...
internal/backup/backup.go: Backup (tar.gz + HMAC-SHA256 signature,
excludes /run/orca + sockets + WAL/SHM), VerifySignature, Restore
(signature verify + extract + Force flag). internal/cli/backup.go:
orca backup --out + orca restore --in --force. Tests: round-trip,
signature mismatch, exclusion, force-refuse, force-overwrite.
---ci---
project: orca
phase: 04
milestone: v0.11
status: execute
---/ci---
2026-08-07 04:55:27 +00:00
Jon Chery
2e6436608f
feat(P03): secrets subsystem (REQ-080) — AES-256-GCM + HKDF-SHA256 per-ns
...
internal/secrets/secrets.go: master key (0600), HKDF-SHA256 per-ns
derivation, AES-256-GCM per-line with AAD=line-number (anti-swap),
EncryptEnvFile/DecryptEnvFile, LoadCredential= map generation.
internal/cli/secrets.go: orca secrets set/get/list/rotate/delete.
Tests: round-trip, nonce uniqueness, AAD anti-swap, 0600 enforcement.
---ci---
project: orca
phase: 03
milestone: v0.11
status: execute
---/ci---
2026-08-07 04:47:33 +00:00
Jon Chery
33c2b4a78b
feat(P02): ACL — SPIFFE + token identities, deny-by-default
...
internal/acl/acl.go: Identity, Permission, ACLEntry, ACL with
Grant/Revoke/Check/List; SpiffeNamespace extraction; deny-by-default.
internal/cli/acl.go: orca acl grant/revoke/list/check CLI;
state at cluster/acl.json. Tests: grant/revoke/deny/ns-isolation/concurrent.
---ci---
project: orca
phase: 02
milestone: v0.11
status: execute
---/ci---
2026-08-07 04:38:00 +00:00
Jon Chery
734c9fa0fa
feat(P01.5): SPIFFE SVID minting spike (REQ-076, gate C-08) — PASSES
...
internal/identity/spiffe.go: SpiffeURI format + MintSVID via step CLI;
internal/identity/spiffe_test.go: mock-transport tests with self-signed
SPIFFE URI SAN cert. Spike passes: step CLI supports --san with URI SANs.
Fallback to mTLS identity NOT needed.
---ci---
project: orca
phase: 01.5
milestone: v0.11
status: execute
---/ci---
2026-08-07 04:30:43 +00:00
Jon Chery
cc53c1a3e4
feat(P01): metrics endpoint — hand-rolled Prometheus text exposition
...
internal/transport/metrics.go: Metrics struct with counters/gauges,
WritePrometheus text exposition; internal/cli/metrics.go: orca metrics
HTTP server on :9100 serving /metrics + /healthz. No client_golang dep.
---ci---
project: orca
phase: 01
milestone: v0.11
status: execute
---/ci---
2026-08-07 04:24:57 +00:00
Jon Chery
b6d4db1a96
feat(P00): CLI cache layer (R-008) — orca_cache SQLite + cache CLI
...
internal/cache/ package with per-class TTLs (Get/Set/Invalidate);
wired into node/job/ns list read paths; orca cache show/invalidate CLI.
Tests: hit/miss/invalidate/TTL-expiry + bench <1ms hit.
---ci---
project: orca
phase: 00
milestone: v0.11
status: execute
---/ci---
2026-08-07 04:17:25 +00:00
Jon Chery
4c2e59cf3f
fix(P06): workloadToTaskSpecs command split + runnable examples
...
Root cause: orca job run <example>.md failed with fork/exec: no such
file or directory on every example. Two compounding problems:
1. workloadToTaskSpecs (internal/cli/job.go:340) passed the entire
runtime.command string (e.g. "/usr/bin/httpd -f /etc/orca/web-app/
httpd.conf") as a single binary path to exec.Command, which then
looked for a file literally named "/usr/bin/httpd -f ..." and
failed. The v0.9 markdown parser stores command: as a raw string;
the legacy HCL path had separate command+args fields. Fix: add
splitCommand helper that splits on strings.Fields into binary+args,
with /bin/true fallback for empty commands.
2. The example commands referenced binaries that don't exist on a bare
Linux machine (/usr/bin/httpd, postgres, api-server, fluent-bit).
Fix: rewrite the 5 example runtime.command values to use /bin/sleep
3600 (long-running services) or /bin/echo (one-shot job) so they
run out-of-the-box. Each file has a Production substitution note
showing the real binary to use in deployment.
Verified: orca job run examples/full-stack/worker.md now succeeds
(exit 0). All 4 services (web-app, api, log-shipper, postgres) start
correctly (task started, pid assigned). 12 new unit tests pass
(splitCommand: 7 cases, workloadToTaskSpecs: 5 cases). All 5 example
jobspecs still parse + validate (gate C-20). make lint clean.
---ci---
project: orca
phase: 6
milestone: v0.10
status: execute
decisions:
- id: D-195
decision: split command string via strings.Fields in workloadToTaskSpecs
rationale: exec.Command expects binary path + args as separate elements;
the v0.9 markdown parser stores command: as a single string with no
args field (unlike legacy HCL). strings.Fields is dep-free and handles
multiple spaces/tabs. Shell quoting (single/double quotes inside the
command) is not handled — examples avoid sh -c with quoted strings.
confidence: 0.95
alternatives: [shellquote.Split from mvdan/sh (adds dependency)]
lessons:
- The v0.9 markdown jobspec path needs the same command+args split that
the legacy HCL path had via separate command/args fields. The parser
stores command: as a raw string; the CLI must split it before passing
to exec.Command.
- Example jobspecs should use /bin/sleep and /bin/echo (binaries that
exist on every Linux machine) so they run out-of-the-box. Descriptive
production commands belong in a comment block, not in runtime.command.
---/ci---
2026-08-05 21:23:32 +00:00
Jon Chery
c51eba5e84
fix(P99): P0 heredoc command injection + ROADMAP/REQUIREMENTS reconciliation
...
P0 fix (final review T1): internal/sshpush/idempotency.go heredoc
command injection via fixed EOF delimiter. Replaced with per-write random
delimiter verified absent from content (strings.Contains check). Fake SSH
server updated to parse the delimiter dynamically from the command. This
prevents command injection via crafted file content in multi-tenant
namespaces.
ROADMAP reconciliation (final review T2.1): updated v0.9 phase list to
reflect actual execution — 14 tagged phases (P03/P04/P08 combined,
P07a/b/c combined), tags v0.8.1..v0.8.14. Milestone marked COMPLETE.
Phase checkboxes marked [x] with actual REQs covered.
REQUIREMENTS reconciliation: 21 v0.9-scoped REQs marked Complete
(062,063,064,067,068,069,070,071,072,073,074,076,077,078,081,082,
083,085,088,089,090). 9 v0.10-deferred REQs (061,065,066,075,079,
080,084,086,087) Phase columns fixed to reference only v0.10 (not v0.9/v0.8)
so verify-reqs doesn't flag them as belonging to completed milestones.
Final review: P0 fixed. P1 warnings logged for post-hoc v0.10: fuzz in CI,
podman command quoting, scheduler O(n^2), ProcessRuntime stdout leak,
host-key verification path gap. 12/19 grill gates cleared; 7 deferred to
v0.10 (C-08,C-09,C-11,C-12,C-13,C-19).
26 packages pass, 20 bats pass, gofmt clean, verify-reqs 90 consistent.
---ci---
project: orca
phase: 99
milestone: v0.9
status: execute
---/ci---
2026-08-05 19:02:54 +00:00
Jon Chery
9991e3d561
feat(P10): lead rules + step-ca integration (REQ-076)
...
P10 — step-ca cluster CA (D-101) + lead eligibility (R-003).
step-ca (internal/stepca/stepca.go, REQ-076):
- Client wraps step CLI via SSH on the lead (no Go step-ca client lib).
- Init: step ca init --name --dns --address --provisioner orca-admin. Root
mirrored to paths.CACertPath() (cluster/ca.crt, v0.9 location).
- IssueServerCert: 90-day (2160h) server cert with SANs. IssueSVID: 24h
SVID with SPIFFE ID as URI SAN, provisioner orca-admin. RenewServerCert.
Fingerprint. 96.6% coverage.
Lead rules (internal/cluster/lead.go, R-003):
- IsLeadEligible: linux=true, proxmox=false, unknown=false.
- ValidateLeadRotation: refuses proxmox nodes with R-003 message, refuses
unregistered nodes. 100% coverage.
26 packages pass, 20 bats pass, gofmt clean, verify-reqs 90 consistent.
---ci---
project: orca
phase: P10
milestone: v0.9
status: execute
---/ci---
2026-08-05 18:48:46 +00:00
Jon Chery
675feabf0c
feat(P09): Syncthing storage replication + conflict resolution (REQ-081; gates C-02, C-14)
...
P09 — Storage replication via per-namespace Syncthing (R-005).
C-02 spike (.ciagent/C02_SYNCTHING_FEASIBILITY_v0.9.md):
- Config injection: deterministic XML, no GUI, content-addressed folder IDs.
- Conflict policy: flock-style lock + source-wins migration + gc-conflicts.
- Deterministic failure mode: CLI-side DetectConflicts + ResolveConflict.
- Auto-decision: C-02 SATISFIED.
C-14 forced-divergence test (internal/storage/conflict_test.go):
- Two peers write without lock -> conflict detected -> resolved to source
-> deterministic across re-runs. Unknown source -> nil (no silent winner).
- C-14 SATISFIED.
Replication (internal/storage/replication.go, REQ-081):
- FolderID = sha256(ns+masterKeyFP)[:32] (content-addressed).
- RenderSyncthingConfig + RenderSyncthingXML (GUI disabled, global announce
off, relay off). DetectConflicts (sorted, deterministic). ResolveConflict
(source-peer-wins). 97.6% coverage.
Emitter (internal/emitter/syncthing.go):
- SyncthingEmitter renders one config.xml per replicated volume at
/etc/syncthing/orca-<ns>-<volume>.xml. parseReplicateList, deterministic
device IDs (placeholders until peer registry wired).
24 packages pass, 20 bats pass, gofmt clean, verify-reqs 90 consistent.
---ci---
project: orca
phase: P09
milestone: v0.9
status: execute
---/ci---
2026-08-05 18:38:49 +00:00
Jon Chery
872ffcaf25
feat(P07a/b/c): runtime abstraction — 5 backends (process/podman/wasm/pve-vm/pve-ct), C-01 satisfied (REQ-078)
...
P07a/b/c — Runtime abstraction interface + 5 implementations.
Runtime interface (internal/runtime/runtime.go, REQ-078):
- Runtime interface { Prepare, Start, Stop, Status }. Alloc struct carries
Runtime field (changeable on migration per R-004). Registry keyed by
runtime.one_of. DefaultRegistry(transport) registers all 5.
Process (internal/runtime/process.go):
- ProcessRuntime wraps os/exec (LOCAL testing only; production uses systemd
emitter). SIGTERM grace 10s then SIGKILL.
Podman (internal/runtime/podman.go):
- PodmanRuntime via sshpush.Transport. podman pull/run/stop/rm/inspect.
Wasm (internal/runtime/wasm.go, gate C-01 SATISFIED):
- WasmRuntime uses wasmtime CLI (apt-installed on peer) via SSH exec. NO CGO
— does NOT import bytecodealliance/wasmtime-go. CGO_ENABLED=0 build
passes. D-002 cross-compile story preserved. D-187 recorded.
PVE (internal/runtime/pve.go):
- PveVMRuntime (qm create/start/stop/status) + PveCTRuntime (pct
create/start/stop/status) via sshpush.Transport. VMID = hash(alloc.ID)%99999.
C-01 evaluation: internal/runtime/C01_WASMTIME_CGO_EVAL.md. Auto-decision
(full autonomy): wasmtime remains primary; CLI-via-SSH avoids CGO entirely.
D-187 in PROJECT.md.
23 packages pass, 20 bats pass, gofmt clean, verify-reqs 90 consistent.
92.7% coverage on internal/runtime.
---ci---
project: orca
phase: P07a/b/c
milestone: v0.9
status: execute
---/ci---
2026-08-05 18:31:25 +00:00
Jon Chery
c3819dde12
feat(P06): task groups — multi-process services, multiple systemd units per alloc
...
P06 — Task groups (PRD §9.1: multiple systemd units per alloc).
Parser (internal/jobspec/markdown.go):
- TaskGroupTask type (Name, Runtime, Env, Command). Tasks []TaskGroupTask on
WorkloadSpec. Parses tasks: frontmatter block (array of task objects).
Tasks without their own runtime inherit the top-level Runtime as default.
Backward compat: no tasks -> single-process (existing runtime block).
Systemd emitter (internal/emitter/systemd.go):
- Task group renders one systemd unit per task (orca-v1-alloc-<id>-<task>
.service) plus a grouping target unit (orca-v1-alloc-<id>.target). Each
per-task unit carries PartOf=<target> and WantedBy=multi-user.target.
Single-process case unchanged (backward compat).
Schema (internal/spec/schema/schema.go):
- TaskGroup validation: unique task names, resolvable command (own or
inherited). JobValidator/ServiceValidator/DaemonSetValidator all accept
task groups.
Tests: 9 task-group tests in schema_test.go, lifecycle + target-unit tests
in systemd_test.go, parser tests in markdown_test.go. 22 packages pass.
Fix: 3 Service task-group test fixtures missing Count:1 (ServiceValidator
requires count>=1; a task-group Service still has >=1 replica).
---ci---
project: orca
phase: P06
milestone: v0.9
status: execute
---/ci---
2026-08-05 18:20:05 +00:00
Jon Chery
c10779873b
feat(P05): CLI-side scheduler + CEL constraints + affinity (REQ-083)
...
P05 — Scheduler moves from daemon-side to CLI-side (R-001) with runtime-awareness.
Scheduler (internal/scheduler/scheduler.go, REQ-083):
- Pure Schedule(nodes, req) -> []Placement. Job=1 best-fit, Service=count
replicas (anti-affinity default, colocation permitted), DaemonSet=1 per
matching node. Score(node, req) = (FreeCPU*1000 + FreeMem); fits checks
runtime compat (wasm->wasmtime, pve-vm/ct->proxmox), constraints (CEL AND),
capacity. Affinity scoring (target + weight, anti-affinity for spreading).
CEL evaluator (internal/scheduler/cel.go):
- Hand-rolled recursive-descent (no CEL dep in go.mod). Subset: node.* attrs,
literals, ==/!=/>=/<=/></>, in/not in, and/or/not, parens. Anything outside
subset returns error (no silent wrong answer). Schedule treats eval errors
as non-fit (node skipped).
23 packages pass, 20 bats pass, gofmt clean, verify-reqs 90 consistent.
89.5% coverage on internal/scheduler.
---ci---
project: orca
phase: P05
milestone: v0.9
status: execute
---/ci---
2026-08-05 18:02:51 +00:00
Jon Chery
ae6eb5a27b
feat(P03,P04,P08): update stanza + lifecycle hooks + socket plumbing
...
P03 — Update stanza (rolling/canary/blue-green):
- internal/spec/schema/update.go: UpdateValidator (strategy enum, max_parallel
1..count, duration parsing, canary int/% forms, auto_promote). 98.2% cov.
- internal/emitter/update.go: RenderUpdatePlan computes the step sequence
(rolling batches, canary 1+promote+rest, blue-green all+cutover). Pure plan,
no execution (v0.10-P10 is transactional). 73.7-100% cov.
P04 — Lifecycle hooks (systemd ExecStop semantics):
- Extended internal/emitter/systemd.go: post_start -> ExecStartPost=,
pre_stop -> ExecStop=. Order: ExecStart -> ExecStartPost -> ExecStop ->
socket lines. 8 lifecycle tests. 100% cov on systemd.go.
P08 — Socket plumbing (R-007):
- internal/emitter/socket.go: SocketEmitter renders RuntimeDirectory=orca/
alloc-<id> per port (mode 0750, orca:orca). ExecStartPre TCP-bind marker
when service.bind=127.0.0.1. SocketPath(allocID,portName) helper. 100% cov.
- Alloc-id is spec.Name placeholder; real id assigned by scheduler at submit.
22 packages pass, 20 bats pass, gofmt clean, verify-reqs 90 consistent.
---ci---
project: orca
phase: P03/P04/P08
milestone: v0.9
status: execute
---/ci---
2026-08-05 17:55:11 +00:00
Jon Chery
436641782c
feat(P02): Service block + Traefik emitter + atomic reload (REQ-077, gate C-10)
...
P02 — Traefik dynamic config generation + atomic reload protocol.
Parser (internal/jobspec/markdown.go):
- Extended WorkloadSpec with Health, Constraints, Affinity, Lifecycle
fields. Parsed restart/update/service/health/lifecycle/affinity/
constraints blocks. HealthBlock, AffinityRule, LifecycleBlock types.
Schema (internal/spec/schema/schema.go):
- ServiceValidator: restart.mode enum (service/on-failure/never),
update.strategy enum (rolling/canary/blue-green), health required,
service.bind IP validation (R-007 loopback opt-in). 98.5% coverage.
Traefik emitter (internal/emitter/traefik.go, REQ-077):
- TraefikEmitter renders /etc/traefik/dynamic/orca-<name>.yaml with
http.routers, http.services (servers = R-007 socket paths), TLS
(certResolver=orca, trust domain), healthCheck. RenderDrain sets
weight:0 per backend. RegisterTraefik wires process/podman/wasm.
Atomic reload (internal/emitter/traefik_atomic.go, gate C-10):
- WriteTraefikDynamic: write to path.tmp via WriteFileIdempotent, then
mv -f path.tmp path (atomic POSIX rename, Traefik fsnotify observes
IN_MOVED_TO). Traefik holds-last-good on malformed config. C-10 PASS.
22 packages pass, 20 bats pass, gofmt clean, verify-reqs 90 consistent.
Coverage: emitter 96.5%, jobspec 88.8%, schema 98.5%, sshpush 93.0%.
---ci---
project: orca
phase: P02
milestone: v0.9
status: execute
---/ci---
2026-08-05 17:48:04 +00:00
Jon Chery
e92b18197c
feat(P01): SSH-push transport layer — connection pool, retry, fan-out, idempotent writes (REQ-073)
...
P01 — Load-bearing replacement for v0.8 mTLS transport (R-001).
Transport (internal/sshpush/transport.go, REQ-073):
- Transport struct with sync.Map connection pool (reuse *ssh.Client per peer).
- Exec with context timeout (10s default) + retry (100ms x2 cap 5s max 5
attempts, +/-25% jitter — same backoff as v0.8 transport/retry.go).
- ReadFile, WriteFile (atomic heredoc + mv), Close.
- sshDialer + sshSession seams for testability. TOFU host-key verification
reuses proxmox.TOFUHostKeyCallback. security.Flock for known_hosts.
Fan-out (internal/sshpush/fanout.go):
- ExecAll, WriteAll with errgroup + SetLimit semaphore (default 8 per I-B-001).
Per-peer errors collected, don't cancel the group.
Idempotency (internal/sshpush/idempotency.go, C-18):
- WriteFileIdempotent: SHA-256 compare via ssh sha256sum; skip if content
matches (written=false). Content-addressed idempotency replaces the v0.8
X-Orca-Idempotency-Key header (C-18 capability map).
Tests: in-process fake SSH server (ssh.NewServerConn NoClientAuth ed25519)
for e2e + interface seams for pure-logic. 93.0% coverage. 20 packages pass.
---ci---
project: orca
phase: P01
milestone: v0.9
status: execute
---/ci---
2026-08-05 17:35:11 +00:00
Jon Chery
60b0357eb6
feat(P0c): Job/Service/DaemonSet schemas + emitter interface + systemd stub (REQ-074)
...
P0c — Kind-specific schema validators + Layer 4 emitter interface.
Schemas (internal/spec/schema/schema.go, REQ-074):
- Validator interface with JobValidator, ServiceValidator, DaemonSetValidator.
JobValidator: count=1, no service block, optional schedule/timeout.
ServiceValidator: ports required, count>=1, restart+update+runtime required.
DaemonSetValidator: schedule mode required, no ports (D-175), no count.
ValidatorFor(kind) dispatcher. 96.2% coverage.
Emitter interface (internal/emitter/emitter.go, REQ-074, I-B-002):
- File{Path,Content,Mode}, Emitter interface { Render(spec,node) []File },
Registry keyed by kind:runtime, Register + Render lookup. 100% coverage.
Systemd stub (internal/emitter/systemd.go):
- SystemdEmitter for process runtime. Renders minimal [Service] unit at
/etc/systemd/system/orca-v1-alloc-<name>.service (orca-v1- prefix per
dual-write window REQ-090 — no overlap with v0.8 daemon's orca-<job>).
Flock test fix: TestFlock_concurrentBlocks rewritten to use non-blocking
tryFlockEx (LOCK_NB) instead of a leaked blocking goroutine. Eliminates
the temp-dir cleanup race.
20 packages pass, 20 bats pass, gofmt clean, verify-reqs 90 consistent.
---ci---
project: orca
phase: P0c
milestone: v0.9
status: execute
---/ci---
2026-08-05 17:17:02 +00:00
Jon Chery
667f20a7b3
feat(P0b): Markdown jobspec parser + dispatcher + fuzz harness (REQ-064,067)
...
P0b — Canonical Markdown+frontmatter jobspec parser (R-013/R-014).
Parser (internal/jobspec/markdown.go, REQ-064):
- WorkloadSpec/RuntimeBlock/PortSpec/VolumeSpec types. ParseMarkdown
hand-rolled YAML frontmatter (no yaml.v3 dep). Kind validation (Job/
Service/DaemonSet per R-012). BOM-stripped frontmatter, byte-exact body
preservation (R-015) via the fuzz harness.
Dispatcher (internal/jobspec/dispatch.go, REQ-064):
- ParseFile/Dispatch routes on extension: .md->Markdown, .yaml/.yml->
Markdown-with-empty-body, .hcl->ParseHCL adapter. HCL adapter converts
Spec{Job,Tasks} to *WorkloadSpec (Kind=Job, Runtime.one_of=process).
Backward compat preserved (REQ-090) — orca job run old-spec.hcl works.
- Legacy Parse renamed ParseHCLLegacy, marked // Deprecated per R-013.
Fuzz harness (internal/jobspec/markdown_fuzz_test.go, REQ-067, R-015):
- FuzzParseMarkdownRoundTrip with 10 seed corpus entries (CRLF, BOM,
no-frontmatter, only-closing-separator, code-fence ---, trailing
whitespace, empty body, etc). Asserts byte-exact body round-trip.
Tests: markdown_test.go (19 tests), dispatch_test.go (17 tests), fuzz
(10 seeds). jobspec package 89.2% coverage. cli 81.8% (no regression).
18 packages pass, 20 bats pass, gofmt clean, verify-reqs 90 consistent.
---ci---
project: orca
phase: P0b
milestone: v0.9
status: execute
---/ci---
2026-08-05 17:02:33 +00:00
Jon Chery
7bb31d4c09
feat(P0a2): namespace CRUD + inheritance engine (REQ-082)
...
P0a2 — Namespace inheritance resolver + orca ns CLI subcommands.
Resolver (REQ-082, internal/ns/resolve.go):
- Pure Resolve() function: DFS post-order chain assembly (most-specific
first, _defaults implicit last D-185). Child-wins-scalar env merge, de-duped
union constraints. Cycle detection with readable cycle path. Missing-parent
+ missing-_defaults + misordering (['_defaults','x']) rejection. Opt-out
impossible (D-187). 89.6% coverage.
Parser (internal/ns/parse.go):
- ParseNSMd: hand-rolled YAML frontmatter (no yaml.v3 dep). Validates
kind:Namespace + name, parses parents flow-array, inherits_env/secrets.
- ParseNSMdDir: walks root/*/ns.md, skips cluster/, requires _defaults.
CLI (internal/cli/ns.go, D-176):
- orca ns list/create/delete/inspect/validate. Inspect + validate use the
resolver. Create refuses _defaults/cluster; delete refuses _defaults +
non-empty namespaces. JSON output support. 85.2% coverage.
- Registered on rootCmd.
Tests: resolve_test.go (11 tests), parse_test.go (14 tests), ns_test.go
(21 tests). 18 packages pass, 20 bats pass, gofmt clean, verify-reqs 90
consistent.
---ci---
project: orca
phase: P0a2
milestone: v0.9
status: execute
---/ci---
2026-08-05 16:49:12 +00:00
Jon Chery
437aab39b4
feat(P0a1): multi-namespace path resolver + config demotion + known_hosts flock + CA migration spec (v0.9 P0a1)
...
P0a1 — Re-architecture Foundation (path resolver + config demotion).
Path resolver (REQ-070, R-002):
- internal/paths/paths.go: 23 functions for the multi-namespace layout
(Root/ClusterDir/NamespaceDir/NS*/DefaultNamespace/CA/MasterKey/CacheDB/
Txn/Peers/KnownHosts/SSH/Server/Config). Honors $ORCA_HOME. 100% coverage.
- internal/certpaths/certpaths.go: refactored as thin shim delegating to
paths, preserving the v0.8 flat-layout API for backward compat during
the dual-write window (REQ-090). Package doc explains the v0.10-P14
migration plan. certpaths deleted after v0.10-P14. 100% coverage.
Config demotion (REQ-069, R-014):
- internal/config/markdown.go: minimal hand-rolled YAML frontmatter parser
(no new dep — yaml.v3 not in go.mod). Returns same *Config struct as HCL.
- internal/config/config.go: renamed Load body to LoadHCL (// Deprecated
per R-013), added dispatcher Load() routing on extension (.hcl->HCL,
.md->Markdown, .yaml->Markdown). Signature preserved so root.go unchanged.
- dispatch_test.go + markdown_test.go: 89.8% coverage on config package.
Known_hosts flock (REQ-063, deferred P1 from REVIEW_v0.8 A2):
- internal/security/flock.go: stdlib syscall.Flock advisory lock helper.
- internal/proxmox/bootstrap.go: TOFUHostKeyCallback capture + ResetHostKey
both acquire the flock before read-modify-write on known_hosts. Prevents
concurrent writers under v0.9 parallel SSH fan-out. 3 flock tests.
CA migration spec (grill C-07):
- .ciagent/CA_MIGRATION_SPEC_v0.9.md: Option A (preserve trust root,
RECOMMENDED) vs Option B (forced re-bootstrap). Pre-flight checks,
migration steps, rollback, post-migration invariants, spike plan.
Verification: build pass, 17/17 Go packages pass, 20/20 bats pass, gofmt
clean, go vet clean, verify-reqs 90 consistent. Coverage: paths 100%,
certpaths 100%, config 89.8%, emit covered.
---ci---
project: orca
phase: P0a1
milestone: v0.9
status: execute
---/ci---
2026-08-05 16:38:26 +00:00
Jon Chery
fc94326b0e
feat(P00): deprecation sweep + bash tooling gate + render contract + doc banners (v0.9 P00)
...
P00 — Re-architecture Foundation (deprecation/migration/test-infra/persona/docs).
Deprecation sweep (REQ-068, REQ-072, REQ-089):
- Add // Deprecated: doc comments to internal/daemon (R-001), internal/transport
(REQ-073), internal/security/ca.go+csr.go (D-101/REQ-076), internal/engine/
dispatcher.go+peer.go (CLI-side scheduler), internal/cli/daemon.go.
- orca daemon emits slog.Warn deprecation banner on every run (ungated); fires
R-001 + v0.10-P05 drain-and-stop + v0.10-P14 deletion.
- orca cert and orca node join (mTLS path) emit deprecation warnings; proxmox
SSH path (the v0.9 replacement) does not warn.
- Add --no-deprecation-warnings global flag on root command (PersistentPreRunE)
for orca upgrade migrations.
- 12 new daemon/cert/node deprecation tests in internal/cli/daemon_test.go
(cli coverage 81.9%, warnDeprecated 100%).
- Add DEPRECATED banners to v0.8 sections of ARCHITECTURE.md (verified the
v0.9 supersession section + Supersession Table from prior turn are present).
Bash tooling gate (grill C-06, C-15, C-16, C-17, C-18):
- scripts/tests/test_helper.bash + example_test.bash — bats framework + helpers.
- scripts/lib/orca-log.sh — slog-compatible JSON logging to syslog (C-17).
- scripts/orca-verify-render.sh — render-contract validator skeleton (C-16).
- scripts/tests/orca-log_test.bash + orca-verify-render_test.bash — 20 bats
tests total (happy + failure paths per C-15).
- .shellcheckrc — project shellcheck config.
- Makefile: test-bash + lint-bash targets (graceful skip if tools missing);
wired into test + lint targets.
- internal/emit/contract.go + contract_test.go — versioned JSON render
contract (orca.emit/v1) between Go emitters and bash appliers (C-16).
- .ciagent/BASH_CAPABILITY_MAP_v0.9.md — maps shipped internal/transport
capabilities to bash-side equivalents or accepted drops (C-18).
- D-186 recorded in PROJECT.md: bash exempt from Go coverage gate; compensating
control is bats + shellcheck + shfmt (C-06).
verify-reqs: 90 requirements consistent. Build/test/lint/fmt all green.
20 bats tests pass. Go tests pass. No v0.8 code deleted — only marked deprecated
(deletion deferred to v0.10-P14 per REQ-090 dual-write window).
---ci---
project: orca
phase: P00
milestone: v0.9
status: execute
---/ci---
2026-08-05 16:26:26 +00:00
Jon Chery
11da458883
test(cli): --host-key-fingerprint non-proxmox validation (T02.11, REQ-058)
...
---ci---
project: orca
phase: 2
milestone: v0.8
status: execute
---/ci---
2026-08-04 12:04:28 +00:00
Jon Chery
d66b3b9a0a
test(proxmox,cli): end-to-end trust-surface integration tests (T02.10, REQ-058, REQ-059)
...
---ci---
project: orca
phase: 2
milestone: v0.8
status: execute
---/ci---
2026-08-04 12:04:24 +00:00
Jon Chery
2dcb14377a
fix(doctor): TOFU capture-fix parity with bootstrap — v0.6 ship-defect (T02.9)
...
---ci---
project: orca
phase: 2
milestone: v0.8
status: execute
---/ci---
2026-08-04 11:56:45 +00:00
Jon Chery
13e6762f0f
feat(cli): orca node key-reset <node> — local known_hosts reset (T02.8, REQ-059)
...
---ci---
project: orca
phase: 2
milestone: v0.8
status: execute
---/ci---
2026-08-04 11:51:47 +00:00
Jon Chery
325a5662f4
feat(proxmox): populate Result.HostKeyFingerprint (T02.7, REQ-058)
...
---ci---
project: orca
phase: 2
milestone: v0.8
status: execute
---/ci---
2026-08-04 11:48:00 +00:00
Jon Chery
8b0cbe10ae
fix(proxmox): TOFU capture bug — v0.6 ship-defect first-connect join always failed (T02.6)
...
---ci---
project: orca
phase: 2
milestone: v0.8
status: execute
---/ci---
2026-08-04 11:46:38 +00:00
Jon Chery
bd17e6e114
feat(proxmox): pinnedHostKeyCallback for --host-key-fingerprint (T02.5, REQ-058)
...
---ci---
project: orca
phase: 2
milestone: v0.8
status: execute
---/ci---
2026-08-04 11:45:53 +00:00
Jon Chery
7cb12c52ce
feat(proxmox): HostKeyFingerprint field on Options (T02.4, REQ-058)
...
---ci---
project: orca
phase: 2
milestone: v0.8
status: execute
---/ci---
2026-08-04 11:38:39 +00:00
Jon Chery
08481d35ce
feat(cli): --host-key-fingerprint flag on node join (T02.3, REQ-058)
...
---ci---
project: orca
phase: 2
milestone: v0.8
status: execute
---/ci---
2026-08-04 11:37:01 +00:00
Jon Chery
00869c6f5b
refactor(security): export WriteAtomic (T02.2, REQ-059)
...
---ci---
project: orca
phase: 2
milestone: v0.8
status: execute
---/ci---
2026-08-04 11:36:42 +00:00
Jon Chery
aa3462826b
feat(security): SSHFingerprintSHA256 helper (T02.1, REQ-058)
...
---ci---
project: orca
phase: 2
milestone: v0.8
status: execute
---/ci---
2026-08-04 11:35:59 +00:00
Jon Chery
6408342a7f
test(cli): coverage uplift to ≥70% excl daemon.go (T01.6, REQ-057)
...
Add table-driven rootCmd.Execute() tests for the node, job, cert,
doctor, audit, status, version, and node-capacity subcommand families.
Each test runs against a temp ORCA_HOME and asserts stdout/stderr/exit
via the existing initTestEnv/resetRootFlags/discardWriter helpers
(RESEARCH §1.2). extend resetRootFlags to also reset the per-command
flag-bound globals so tests don't leak state between runs.
daemon.go is excluded from the ≥70% target (documented in node_test.go):
the daemon command starts a long-running mTLS server whose lifecycle is
covered by internal/daemon/server_test.go; only its --pprof flag
registration is verified here (daemon_test.go).
Coverage: go test -cover ./internal/cli → 76.2% overall (78.7% by
-func), which includes daemon.go's untested RunE; the non-daemon files
exceed 70% comfortably. go test -race PASS.
---ci---
project: orca
phase: 1
milestone: v0.8
status: execute
---/ci---
2026-08-04 01:43:38 +00:00
Jon Chery
9727edf4df
test(certpaths): first tests, ≥50% toe-hold (T01.10, REQ-057)
...
---ci---
project: orca
phase: 1
milestone: v0.8
status: execute
---/ci---
2026-08-04 01:13:43 +00:00
Jon Chery
e45232f395
test(jobspec): coverage uplift to ≥70% + golden HCL fixtures (T01.8, REQ-057)
...
---ci---
project: orca
phase: 1
milestone: v0.8
status: execute
---/ci---
2026-08-04 01:12:59 +00:00
Jon Chery
82f3bcacfd
test(store): coverage uplift to ≥70% + missing cert_repo_test.go (T01.7, REQ-057)
...
---ci---
project: orca
phase: 1
milestone: v0.8
status: execute
---/ci---
2026-08-04 01:12:12 +00:00