Files
Jon Chery 5b99bbd2e8 docs(P00): create v0.11 phase plan (8 waves, 23 phases, 20 new REQs)
PLAN stage: 8-wave structure covering 23 phases. Wave 0 (P00 cache), Wave 1 (P01/P01.5/P02 observability+identity), Wave 2 (P03/P15.5 security+ingress hybrid+doctor mTLS), Wave 3 (P04/P06 backup+alloc history+logs), Wave 4 (P05/P07 drain+migrate+recovery), Wave 5 (P10/P11/P12 txn plane+drift+lint+verify), Wave 6 (P09/P13 aggregator+ns), Wave 7 (P14a/b/c migration+upgrade+rotate-lead), Wave 8 (P08/P15/P16 integration+docs+ship). P10 is the largest phase; grill may split into P10a/P10b.

---ci---
project: orca
phase: 0
milestone: v0.11
status: plan
---/ci---
2026-08-07 03:39:27 +00:00

25 KiB

Plan: v0.11 Production Hardening

Milestone: v0.11 — Production Hardening

  • Type: feature (multiple feat phases)
  • Tags: v0.10.0 (P0) → v0.10.1v0.10.20 (P00…P15.5) → v0.10.21 (P16 = v0.11.0 milestone release)
  • Branch: milestone/v0.11-production-hardening
  • New rules adopted: R-017 (ingress hybrid), R-018/R-019/R-020 (drift detection)
  • New decisions: D-215…D-237 (23 net-new, no collisions)
  • New REQs: REQ-099…REQ-118 (20 net-new; REQ count 98→118)

Wave ordering

Wave 0 — Foundation (serial)

  • P00 — CLI cache layer (R-008). Unblocks all subsequent CLI commands that need cached reads.

Wave 1 — Observability + identity (serial, gate-heavy)

  • P01 — Metrics endpoint (hand-rolled text exposition). Unblocks orca doctor mTLS live probe (C5).
  • P01.5 — SPIFFE SVID minting spike (gate C-08 — if spike fails, fall back to mTLS identity). Gates P02 ACL.
  • P02 — ACL (SPIFFE + token identities). Depends on P01.5.

Wave 2 — Security + secrets (serial)

  • P03 — Secrets subsystem (REQ-080; gate C-19 threat model).
  • P15.5 — Threat model + security review (gate C-19) + ingress hybrid (R-017; REQ-099..REQ-102) + orca doctor mTLS (REQ-118). Per Q3=A, ingress folds in here. This phase grows ~30% but stays one phase.

Wave 3 — Data durability (serial)

  • P04 — Backup/restore (tar + signed). Unblocks P07 recovery.
  • P06 — Alloc history (CLI-side SQLite; R-008 cache DB) + orca logs --all-nodes --since (REQ-117). The logs command uses the alloc-history cache DB.

Wave 4 — Lifecycle (serial)

  • P05 — Drain + daemon drain-and-stop (REQ-061) + orca job migrate --to (REQ-116; C3=drain+reschedule composite). Migrate composes P05 drain + P06 alloc history.
  • P07 — Recovery (orca restore). Depends on P04 backup.

Wave 5 — Transactional plane (serial, the big one)

  • P10 — Transactional plane (REQ-075, REQ-079; gate C-09) + drift detection (R-018/R-019/R-020; REQ-103..REQ-113). This is the largest phase. Grill may split into P10a (txn plane) + P10b (drift) if vertical slice is too large.
  • P11orca job lint (REQ-084). Depends on P10 txn plane for dry-run validation.
  • P12orca job verify (dry-run txn through lead). Depends on P10.

Wave 6 — Namespace + aggregation (parallel)

  • P09 — Collector + aggregator (opt-in; gates C-11, C-12, C-14) + drift-event aggregation extension (REQ-107, D-237). The aggregator timer is extended to pull drift-events/ and remediate. C-11 watchdog monitors this timer.
  • P13orca ns subcommands (full surface) + deprecation warnings (REQ-068).

Wave 7 — Migration (serial, gate-heavy)

  • P14a — v0.8→v1.0 data migration (REQ-066; gate C-07) + orca upgrade --to-vX (REQ-115; C2=thin wrapper, handles R-017 binding cutover).
  • P14b — Daemon cutover + running-allocation adoption + orca cluster rotate-lead (REQ-114).
  • P14c — Mixed-version tolerance + no-orca-on-server enforcement (REQ-065, REQ-086; implements C-13).

Wave 8 — Integration + docs + ship (serial)

  • P08 — Integration tests (expand hermetic harness, REQ-087) + drift-detection integration tests (auto-remediation success, NFS fallback, rate-limit cooldown, secret exclusion).
  • P15 — README quickstart (REQ-089; Q5=A Nomad-inspired framing, honest-trade-offs table from doc 3). All cited CLI commands must exist by this phase.
  • P16 — Final review + ship + audit — v0.11.0 milestone release.

Phase task tables

Phase P00 — CLI cache layer (Wave 0)

REQs: R-008 (cache floor) Persona: backend-engineer Territory: internal/cache/, internal/store/orca_cache.go Vertical slice: a CLI command that reads cached state → a cache-hit returns in <1ms, a cache-miss populates from the lead.

Task Description REQ
P00-T1 internal/cache/ package: orca_cache SQLite schema (per-class TTLs), Get(class, key), Set(class, key, val, ttl), Invalidate(class); stdlib database/sql + modernc/sqlite R-008
P00-T2 Wire cache into orca node list, orca job list, orca ns list (read path only; writes bypass cache) R-008
P00-T3 orca cache show / orca cache invalidate CLI for debugging R-008
P00-T4 Tests: cache-hit/miss/invalidate/TTL-expiry; bench <1ms cache-hit R-008

Must-haves: cache-hit <1ms; TTL-based invalidation; CLI commands use cache on read path.

Phase P01 — Metrics endpoint (Wave 1)

REQs: (new; metrics text exposition) Persona: backend-engineer Territory: internal/cli/metrics.go, internal/transport/metrics.go Vertical slice: curl localhost:9100/metrics → prometheus text exposition.

Task Description REQ
P01-T1 internal/transport/metrics.go: hand-rolled Prometheus text exposition (no client_golang dep); counters for txns applied/drifted/remediated; gauges for peers/nodes/allocs new
P01-T2 orca daemon --metrics :9100 flag (or sidecar listener); /metrics endpoint new
P01-T3 Tests: exposition format validity; counter increments on txn apply new

Must-haves: /metrics returns valid Prometheus text; no client_golang dependency.

Phase P01.5 — SPIFFE SVID minting spike (Wave 1, gate C-08)

REQs: REQ-076 Persona: security-engineer Territory: internal/identity/spiffe.go Gate: C-08 — if spike fails, fall back to mTLS identity (decision recorded).

Task Description REQ
P01.5-T1 Spike: mint a SPIFFE SVID via step-ca; verify URI SAN format (spiffe://orca.local/ns/<ns>/sa/<sa>/<alloc-id>) REQ-076
P01.5-T2 Decision record: if spike passes, proceed to P02 with SPIFFE; if fails, fall back to mTLS identity + record in PROJECT.md REQ-076

Must-haves: spike passes or fails with a recorded decision; C-08 gate cleared.

Phase P02 — ACL (Wave 1)

REQs: (new; ACL with SPIFFE + token identities) Persona: backend-engineer + security-engineer Territory: internal/acl/, internal/cli/acl.go Depends on: P01.5 (SPIFFE or mTLS fallback)

Task Description REQ
P02-T1 internal/acl/ package: identity → permissions mapping; SPIFFE URI → namespace scope; token identities for operators new
P02-T2 orca acl CLI: grant, revoke, list, check; scoped to namespace paths per R-002 new
P02-T3 Tests: SPIFFE identity grants ns-scoped access; token grants operator-scoped access; deny by default new

Must-haves: deny-by-default; SPIFFE URI maps to namespace; tokens for operator access.

Phase P03 — Secrets subsystem (Wave 2, gate C-19)

REQs: REQ-080 Persona: security-engineer Territory: internal/secrets/, internal/cli/secrets.go Gate: C-19 (threat model must land in P15.5; P03 implements the crypto)

Task Description REQ
P03-T1 internal/secrets/ package: AES-256-GCM encrypt/decrypt with master.key (R-011); per-line nonce; LoadCredential= integration REQ-080
P03-T2 orca secrets CLI: set, get, rotate, list; scoped to namespace .env.secrets REQ-080
P03-T3 Tests: encrypt/decrypt round-trip; rotation re-encrypts; master.key 0600 enforced REQ-080

Must-haves: AES-256-GCM; per-line nonce; master.key 0600; LoadCredential= integration.

Phase P15.5 — Threat model + ingress hybrid + doctor mTLS (Wave 2, gate C-19)

REQs: REQ-099, REQ-100, REQ-101, REQ-102, REQ-118; C-19 Persona: security-engineer + network-engineer + backend-engineer Territory: internal/emitter/nft.go, internal/emitter/traefik.go, internal/cli/nft.go, internal/cli/doctor_mtls.go, threat-model doc Vertical slice: orca init on a fresh cluster → Traefik binds 127.0.0.1:8443 + nft DNAT → orca doctor nft + orca doctor mTLS pass.

Task Description REQ
P15.5-T1 internal/emitter/nft.go: nftables emitter renders /etc/nftables.d/orca.nft (DNAT :443→127.0.0.1:8443, :80→127.0.0.1:8080; SYN-flood filter; ora_rl rate-limit meter; orca_trusted_probes set); idempotent nft -f apply; atomic rule-set swap (D-217, D-218) REQ-099
P15.5-T2 internal/emitter/traefik.go update: static config address: 127.0.0.1:8443 (default); --public-binding=traefik-on-public-ip opt-out emits :443; certs/mTLS/dynamic config unchanged (D-220, D-216) REQ-100
P15.5-T3 orca doctor nft: checks table exists, DNAT rules present, rate-limit meter present, file parses (nft -c -f), hash matches latest txn (D-221, D-226) REQ-101
P15.5-T4 orca nft CLI: show [--peer], diff --against <txn-id>, doctor, country block add <cc-list>, rate limit set --rate N/s (D-223, D-222) REQ-102
P15.5-T5 orca doctor mTLS: trust-chain verification (CA → server cert → workload SVIDs exist + not expired) + live mTLS handshake probe to each peer (reuses P01 metrics endpoint + P01.5 SPIFFE infra); C5=both REQ-118
P15.5-T6 Threat model doc: covers R-017 ingress trust boundary, R-020 drift deadlock, secret exclusion D-234, orca system user blast radius; clears C-19 C-19
P15.5-T7 Tests: nft emitter output validates (nft -c -f); Traefik static config has 127.0.0.1:8443; doctor nft passes on a clean cluster; doctor mTLS passes with valid chain + live probe REQ-099..102, 118

Must-haves: fresh orca init produces hybrid binding; orca doctor nft + orca doctor mTLS pass; C-19 cleared; opt-out flag works.

Phase P04 — Backup/restore (Wave 3)

REQs: (new; tar + signed backup) Persona: backend-engineer Territory: internal/backup/, internal/cli/backup.go

Task Description REQ
P04-T1 internal/backup/ package: tar ORCA_HOME (excl. secrets? or incl. with master.key?); sign with master.key (HMAC-SHA256); orca backup --out snap.tar.gz new
P04-T2 orca restore --in snap.tar.gz (P07 owns the full recovery; P04 owns the backup format + signing) new
P04-T3 Tests: backup→restore round-trip; signature verification; backup excludes /run/orca/* new

Must-haves: backup is a signed tarball; restore verifies signature.

Phase P06 — Alloc history + logs --all-nodes (Wave 3)

REQs: REQ-071 (cache DB), REQ-117 Persona: backend-engineer Territory: internal/store/alloc_history.go, internal/cli/logs.go Depends on: P00 (cache DB)

Task Description REQ
P06-T1 internal/store/alloc_history.go: CLI-side SQLite retention for alloc state transitions; TTL-based eviction REQ-071
P06-T2 orca logs --all-nodes --since 5m: aggregates journald logs across peers via SSH fanout; iter.Seq streaming (D-017); --since duration; --all-nodes fans out (Q2=C) REQ-117
P06-T3 Tests: alloc history retention/eviction; logs --all-nodes fans out + streams + cancels via ctrl-c REQ-071, 117

Must-haves: alloc history retained in cache DB; --all-nodes aggregates across peers with streaming.

Phase P05 — Drain + migrate (Wave 4)

REQs: REQ-061, REQ-116 Persona: backend-engineer Territory: internal/cli/drain.go, internal/cli/migrate.go Depends on: P06 (alloc history for migrate)

Task Description REQ
P05-T1 orca node drain <host>: drain a node (stop new allocs; migrate existing per update config); daemon drain-and-stop (REQ-061) REQ-061
P05-T2 orca job migrate <name> --to <node>: drain+reschedule composite (C3=a); uses P05 drain + P06 alloc history; idempotent (Q2=C) REQ-116
P05-T3 Tests: drain stops new allocs; migrate reschedules to target node; daemon drain-and-stop works REQ-061, 116

Must-haves: drain stops new allocs + migrates existing; migrate reschedules to a specific node.

Phase P07 — Recovery (Wave 4)

REQs: (new; orca restore) Persona: backend-engineer Territory: internal/cli/restore.go Depends on: P04 (backup format)

Task Description REQ
P07-T1 orca restore --in snap.tar.gz: verify signature, extract, reconcile with live state (don't clobber running allocs unless --force) new
P07-T2 Tests: restore from signed backup; signature mismatch fails; --force clobbers running allocs new

Must-haves: restore verifies signature; doesn't clobber running allocs without --force.

Phase P10 — Transactional plane + drift detection (Wave 5, gate C-09)

REQs: REQ-075, REQ-079, REQ-103..REQ-113; C-09; R-018/R-019/R-020 Persona: backend-engineer + devops-engineer + security-engineer Territory: internal/drift/, internal/cli/drift.go, scripts/orca-drift-notify.sh, scripts/orca-remediate.sh, internal/emitter/systemd.go (Path units), internal/paths/paths.go Vertical slice: operator edits /etc/traefik/dynamic/orca.yml on a peer → drift detected in ~10s → auto-remediated → orca drift watch shows the event. Note: This is the largest phase. Grill may split into P10a (txn plane, REQ-075/079) + P10b (drift detection, REQ-103..113) if the vertical slice is too large.

Task Description REQ
P10-T1 internal/txn/ package: render txn bundle (tarball + apply.sh + verify.sh) on operator host; SCP to lead's /run/orca/txns/<txn-id>/; lead's systemd timer runs apply.sh idempotently; CLI polls txn status via SSH (REQ-075, C-09) REQ-075
P10-T2 scripts/orca-pull.sh with C-09 failure contract: idempotent re-run, bounded retry, deterministic state, structured syslog (C-09) REQ-079, C-09
P10-T3 internal/drift/ package: Detector interface (Watch, Aggregate, Remediate, Acknowledge), Event, Config, PathSpec, RemediationPolicy; iter.Seq2[Event, error] (D-017); signal.NotifyContext (D-023) (D-236) REQ-103
P10-T4 orca drift CLI tree: watch [--interval=2s] [--paths=...] [--json], show [--peer], acknowledge <peer> <path>, remediate <peer> <path> [--force], config show, config validate (D-236) REQ-104
P10-T5 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); R-001-clean (D-227, D-228) REQ-105
P10-T6 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; stateless, idempotent; flock (D-228) REQ-106
P10-T7 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 (C4 refinement); transient failures retry next tick (D-231, D-232) REQ-108
P10-T8 Drift cadence config in config.md (kind: ClusterConfig): drift.polling, drift.paths.{critical,standard,excluded}, drift.remediate; critical defaults: Traefik dynamic, nftables, sudoers, orca-alloc services; secrets + /run/orca/* + drift-events dir excluded (R-018, D-231, D-234) REQ-109
P10-T9 Pre-flight consistency gate in orca-pull.sh: refuses new txns if drift detected on target peer/namespace; --force overrides; per-namespace scoping (drifted peer in ns-A doesn't block ns-B) (R-020, Q4=A) REQ-110
P10-T10 orca system user on peers: peer-setup emits useradd -r orca (system account, no login shell); orca-drift-*.service runs as User=orca; idempotent (REQ-111) REQ-111
P10-T11 NFS detection at peer setup: orca node join detects NFS mounts on orca state dirs; disables Path units for NFS paths; logs warning; falls back to polling (D-233) REQ-112
P10-T12 orca job restart <name>: restarts an alloc to pick up EnvironmentFile drift; normal allocation lifecycle (not file-level remediation) (D-235) REQ-113
P10-T13 Tests: txn apply idempotent + retry on failure; drift detected via Path unit ~10s; auto-remediation re-pushes; cooldown prevents loop; --force overrides pre-flight gate; per-ns scoping isolates drift; NFS fallback; secret exclusion REQ-075..113

Must-haves: txn apply idempotent (C-09); drift detected ~10s on critical paths; auto-remediation with cooldown; --force + per-ns override; orca user created; NFS detection works.

Phase P11 — orca job lint (Wave 5)

REQs: REQ-084 Persona: backend-engineer Territory: internal/cli/job_lint.go Depends on: P10 (txn plane for dry-run validation)

Task Description REQ
P11-T1 orca job lint <spec.md>: validates jobspec schema (kinds, blocks, CEL constraints, body preservation); reports errors with line numbers REQ-084
P11-T2 Tests: valid spec passes; invalid spec reports errors with line numbers REQ-084

Must-haves: lint catches schema errors; reports line numbers.

Phase P12 — orca job verify (Wave 5)

REQs: (new; dry-run txn through lead) Persona: backend-engineer Territory: internal/cli/job_verify.go Depends on: P10 (txn plane)

Task Description REQ
P12-T1 orca job verify <spec.md>: dry-run txn through lead (no apply); reports what would change (allocs created/removed, config files written) new
P12-T2 Tests: verify reports planned changes without applying; fails on pre-flight drift new

Must-haves: verify is a true dry-run (no side effects); reports planned changes.

Phase P09 — Collector + aggregator + drift-event aggregation (Wave 6)

REQs: (existing collector/aggregator) + REQ-107; C-11, C-12, C-14 Persona: devops-engineer + backend-engineer Territory: scripts/orca-aggregate.sh, internal/cli/collector.go Gates: C-11 (watchdog), C-12 (opt-in), C-14 (syncthing)

Task Description REQ
P09-T1 scripts/orca-aggregate.sh: existing 10s cadence (C-11); now also rsyncs each peer's /etc/orca/state/drift-events/, validates event hashes against applied txn manifest, triggers orca-remediate.sh for auto-remediable paths, consumes (deletes) event files on peers (D-229, D-237) REQ-107
P09-T2 Lead-side watchdog meta-timer (C-11): fires on orca-pull.sh starvation (>N seconds without successful run); structured alert path C-11
P09-T3 orca collector CLI: opt-in collector for per-peer state snapshots; writes to cluster.json (C-12 opt-in) C-12
P09-T4 Tests: aggregator pulls drift-events + triggers remediation; watchdog fires on starvation; collector opt-in REQ-107, C-11

Must-haves: aggregator pulls drift-events + remediation; watchdog fires on starvation; collector opt-in.

Phase P13 — orca ns subcommands + deprecation warnings (Wave 6)

REQs: REQ-068 Persona: lead-developer Territory: internal/cli/ns.go

Task Description REQ
P13-T1 Full orca ns surface: list, create, delete, inspect, validate, inherit, set-constraint (per R-002 namespace-as-path) REQ-068
P13-T2 Depprecation warnings: orca daemon, orca cert (v0.8 mTLS path), .hcl jobspec → printed on use; --no-deprecation-warnings suppresses (REQ-068) REQ-068
P13-T3 Tests: all ns subcommands work; deprecation warnings fire on deprecated surface REQ-068

Must-haves: full ns surface; deprecation warnings on deprecated surface.

Phase P14a — v0.8→v1.0 data migration + orca upgrade (Wave 7, gate C-07)

REQs: REQ-066; C-07; REQ-115 Persona: data-engineer + backend-engineer Territory: internal/migration/, internal/cli/upgrade.go Gate: C-07 (CA migration spec)

Task Description REQ
P14a-T1 internal/migration/ package: v0.8 flat layout → v0.9/v0.11 multi-namespace layout; schema migration (0006→next); CA migration per spec (C-07) REQ-066
P14a-T2 orca upgrade --to-vX: thin wrapper (C2=a) around install.sh + orca restore; handles R-017 Traefik binding cutover (:443127.0.0.1:8443) for existing v0.9/v0.10 clusters (Q2=C) REQ-115
P14a-T3 Tests: v0.8 layout migrates to v0.11 layout; orca upgrade handles binding cutover; idempotent REQ-066, 115

Must-haves: v0.8 data migrates to v0.11; orca upgrade handles binding cutover; C-07 cleared.

Phase P14b — Daemon cutover + rotate-lead (Wave 7)

REQs: (existing daemon cutover) + REQ-114 Persona: backend-engineer + lead-developer Territory: internal/cli/daemon.go, internal/cli/rotate_lead.go

Task Description REQ
P14b-T1 Daemon cutover: orca daemon becomes drain-and-stop (REQ-061 from P05); running-allocation adoption (orphaned allocs adopted by SSH-push path) existing
P14b-T2 orca cluster rotate-lead: moves cluster CA + lead state to a new bare-Linux peer (R-003); workloads keep running (certs distributed); SSH key rotation; idempotent (Q2=C) REQ-114
P14b-T3 Tests: daemon cutover adopts running allocs; rotate-lead moves CA + workloads keep running REQ-114

Must-haves: daemon cutover adopts running allocs; rotate-lead moves CA without downtime.

Phase P14c — Mixed-version tolerance (Wave 7)

REQs: REQ-065, REQ-086; C-13 Persona: backend-engineer Territory: internal/transport/, internal/cli/

Task Description REQ
P14c-T1 Mixed-version tolerance: lead and peers can run different orca versions during upgrade window; no-orca-on-server enforcement (R-001) REQ-065, REQ-086
P14c-T2 Tests: mixed-version cluster operates; orca-on-server detected + refused REQ-065, 086

Must-haves: mixed-version tolerance during upgrade; R-001 enforced.

Phase P08 — Integration tests + drift-detection tests (Wave 8)

REQs: REQ-087 Persona: devops-engineer Territory: tests/integration/, scripts/tests/

Task Description REQ
P08-T1 Expand hermetic test harness: multi-peer setup, txn apply, drift injection, remediation verification (REQ-087) REQ-087
P08-T2 Drift-detection integration tests: auto-remediation success (edit Traefik config → detect ~10s → remediated); NFS fallback (NFS mount → Path units disabled → polling); rate-limit cooldown (repeated drift → cooldown blocks loop); secret exclusion (edit /etc/orca/credentials/* → no drift event) REQ-087
P08-T3 Tests pass in CoreCI integration pipeline (nft exclusively, D-224) REQ-087

Must-haves: integration tests cover drift detection; pass in CoreCI.

Phase P15 — README quickstart (Wave 8)

REQs: REQ-089 Persona: lead-developer + docs-engineer (phase-specific) Territory: README.md Framing: Q5=A (Nomad-inspired, OS-as-cluster; honest-trade-offs table from doc 3; Proxmox as one node type, not the identity)

Task Description REQ
P15-T1 README.md: status line (v0.11 complete, v1.0 UAT-gated); install example; subcommand table expanded to ALL v0.11 commands (incl. drift, nft, migrate, rotate-lead, upgrade, logs --all-nodes, doctor mTLS); honest-trade-offs table (doc 3 §4.6); Nomad-inspired framing (Q5=A) REQ-089
P15-T2 Verify all cited CLI commands exist in internal/cli/ (C-22-style grounding gate) REQ-089

Must-haves: README subcommand table matches internal/cli/ exactly; honest-trade-offs table present; Nomad-inspired framing.

Phase P16 — Final review + ship + audit (Wave 8)

REQs: all (REQ-099..REQ-118 + existing v0.11 REQs) Persona: lead-developer Vertical slice: milestone complete → merged to main, tagged, released.

Task Description REQ
P16-T1 Code review across all phases; auto-apply P0 fixes, flag P1+ for post-hoc all
P16-T2 Audit: reconstruction test (git log matches .ciagent/), file discipline, branch hygiene, commit discipline all
P16-T3 Milestone ship: merge phase/16 → milestone → main; tag v0.10.21 (= v0.11.0 milestone release); release with Linux binary asset; delete all milestone branches all
P16-T4 Complete milestone: mark all v0.11 REQs complete in REQUIREMENTS.md; mark v0.11 complete in ROADMAP.md; clear checkpoint all

Must-haves: milestone merged to main; release carries Linux binary; all REQs marked complete; checkpoint cleared.

Risks

  • R1: P10 sizing — P10 is the largest phase (txn plane + drift detection, 13 tasks). Mitigation: grill may split into P10a/P10b. The plan is structured so P10a (T1-T2, txn plane) and P10b (T3-T13, drift) are separable.
  • R2: R-020 deadlock — hard-gate refusal could block all new txns if a peer is permanently drifted on a require_approval path. Mitigation: --force + per-ns scoping (Q4=A); documented in C-09 failure contract.
  • R3: Ingress default migration — existing v0.9/v0.10 clusters run Traefik on :443. R-017 makes 127.0.0.1:8443 + nft the default. Mitigation: orca upgrade (REQ-115, P14a) handles the binding cutover.
  • R4: orca system user — creating a system user on every peer is a new operational requirement. Mitigation: peer-setup emits useradd -r orca idempotently (REQ-111); documented in P10.
  • R5: Scope ceiling — v0.11 stays at 23 phases (no new phases), but P09/P10/P15.5 grow substantially. Mitigation: wave ordering isolates the largest work (Wave 5) so it can be split without affecting other waves.