40b5e781ce
Operator decision (resolves grill C-04 + escalation E-03): keep 2 milestones (v0.9 + v0.10), keep all phases (40 total, exceeds 35 soft limit), v1.0 is UAT-gated and cut as a separate tag (v1.0.0) after v0.10 completion per operator sign-off — not a separate milestone. Relabels all v1.0 milestone references to v0.10 across ROADMAP, REQUIREMENTS, GRILL_v0.9, IDEATION_v0.9, PRD_v0.9, PROJECT. Phase content unchanged; only the milestone label moves. Historical grill narrative (the original PRD §23 counts and the E-03 auto-split reasoning) preserved verbatim for audit integrity. C-04 and E-03 marked RESOLVED in GRILL_v0.9.md. Milestone structure: - v0.9: Re-architecture Foundation & Workloads (13 phases P00..P0X) - v0.10: Production Hardening (19 phases P00..P16, milestone tag v0.10.0) - v1.0: UAT-gated production-ready cut (separate v1.0.0 tag, not a milestone) verify-reqs: 90 requirements consistent. ---ci--- project: orca phase: 0 milestone: v0.9 status: complete gate: C-04 resolved ---/ci---
485 lines
30 KiB
Markdown
485 lines
30 KiB
Markdown
# Grill v0.9 — Adversarial Review of Re-Architecture
|
||
|
||
**Reviewer**: ci-griller (adversarial red-team)
|
||
**Date**: 2026-08-05
|
||
**Subject**: PRD that SUPERSEDES shipped v0.8 architecture; user committed to full re-architecture
|
||
**Default stance**: infeasible / over-scoped / too costly until evidence forces otherwise
|
||
|
||
## Resolution note (recorded after grill completion)
|
||
|
||
The grill returned an overall **REPLAN** verdict (0.74) on three axes
|
||
(Scope, Migration, Re-architecture Justification). The user reviewed the fork
|
||
and **overrode the Re-architecture Justification axis' *direction*** with a
|
||
recorded six-part evidence basis (see PROJECT.md Supersession Table):
|
||
|
||
1. The v0.8 daemon model is operationally failing in the target environment.
|
||
2. step-ca is externally mandated.
|
||
3. Multi-tenancy is a hard product requirement.
|
||
4. WASM is a hard workload requirement.
|
||
5. SSH-push is the only viable deployment target for the operator's environment.
|
||
6. Simplicity/vision correction — the v0.1-v0.8 daemon model was a wrong turn.
|
||
|
||
Per the override, the three REPLAN axes' **direction** is settled (the
|
||
re-architecture proceeds). Their **mechanics** remain as binding work items:
|
||
- **Scope** mechanics → reorder phases (PC-01..PC-10), add deprecation sweep
|
||
phase, split heavy phases.
|
||
- **Migration** mechanics → split P14 into P14a/P14b/P14c, design migration
|
||
ordering in v0.9-P00.
|
||
- **Security** mechanics → threat model in v0.10-P15.5 (C-19).
|
||
|
||
The 19 binding conditions (C-01..C-19) and 10 phase challenges (PC-01..PC-10)
|
||
are adopted in full as execution gates.
|
||
|
||
---
|
||
|
||
## Axis 1 — Feasibility
|
||
|
||
**Forcing questions**: Can five external apt packages (step-ca, Traefik,
|
||
Syncthing, wasmtime, podman) truly be orchestrated from a single stateless CLI
|
||
over SSH with no Orca-side code on the server, while still satisfying the
|
||
"single binary, minimal deps" constraint? Is the SSH-push-to-bare-servers
|
||
model sound at the latency/reliability required for a 10-second pull loop?
|
||
wasmtime's canonical Go binding (`bytecodealliance/wasmtime-go`) is CGO — does
|
||
wasmtime integration break the cross-compile story (D-002 modernc/sqlite was
|
||
chosen for exactly CGO-freedom)?
|
||
|
||
**Evidence**: Constraint conflict between PROJECT.md:5 ("no container runtime")
|
||
and PRD R-001 (podman as one of 5 runtimes). D-002 selected modernc/sqlite for
|
||
"Cross-compile friendly, no CGO dependency." No evidence in the PRD that a
|
||
CGO-free wasmtime binding exists. The PRD itself was not checked in (now
|
||
resolved: `.ciagent/PRD_v0.9.md`).
|
||
|
||
**Verdict**: PROCEED-WITH-CONDITION
|
||
**Confidence**: 0.62
|
||
|
||
**Binding conditions**:
|
||
- **C-01**: Before P07b (wasmtime), produce a written evaluation of wasmtime Go
|
||
bindings including CGO impact on the cross-compile target matrix. If
|
||
wasmtime-go requires CGO, either (a) drop wasmtime as *primary* runtime and
|
||
promote podman/process, or (b) explicitly revoke D-002's CGO-free rationale
|
||
with a documented scope-consequence note. No silent reversal.
|
||
- **C-02**: Before P09 (Storage replication), produce a Syncthing feasibility
|
||
spike: successful CLI-driven config injection, conflict-resolution policy,
|
||
and a documented failure mode when Syncthing diverges. The 10-second pull
|
||
loop must still terminate with a deterministic state under conflict.
|
||
- **C-03**: The PRD must be checked into `.ciagent/` before any v0.9 phase
|
||
begins execution. ✅ Resolved — committed as `.ciagent/PRD_v0.9.md`.
|
||
|
||
**Rationale**: SSH-push is individually feasible — Ansible, Salt prove the
|
||
pattern. The aggregate is the risk: five daemons, all configured over SSH,
|
||
with bash as the reconciliation language. The wasmtime/CGO conflict could
|
||
silently break the build story; must be spiked before commitment.
|
||
|
||
## Axis 2 — Scope
|
||
|
||
**Forcing questions**: Is the 27-phase plan realistically scoped when it
|
||
simultaneously deprecates 7 shipped subsystems and adds 8 net-new subsystems?
|
||
The deprecation of ~10k lines of shipped daemon/transport/CA code is not listed
|
||
as a phase. v0.9 P0a..P10 ship 10 phases of workload features before the
|
||
transactional control plane (R-010 deferred to v0.10 P10) — is that intentional
|
||
or a sequencing error? Hidden requirements (step-ca self-upgrade, master.key
|
||
rotation, Syncthing version drift)?
|
||
|
||
**Evidence**: v0.9 phase ordering ships P0a..P10 workloads, then P10 lead rules
|
||
+ migration *last*. The transactional plane (R-010) is deferred to v0.10 P10 —
|
||
two milestones away. v0.8 was a 4-phase NFR milestone; v0.6 was 4-phase feature.
|
||
The PRD's v0.9 (11) + v1.0 (16) = 27 phases is 3-4× prior milestone size with
|
||
no evidence the throughput model was re-validated. No phase is labeled
|
||
"deprecate daemon/transport/internal-CA."
|
||
|
||
**Verdict**: REPLAN (mechanics — direction settled by override)
|
||
**Confidence**: 0.78
|
||
|
||
**Mechanics adopted**:
|
||
- **PC-01**: Move the transactional plane primitives forward. The
|
||
transactional primitives (desired-state, lead-applier, drift, rollback) are
|
||
the substrate every workload phase depends on. Design spike in v0.9-P00;
|
||
full implementation in v0.10-P10 per PRD ordering (workloads first is accepted
|
||
given the dual-write window mitigation in I-C-006).
|
||
- **PC-02**: Add `v0.9-P00 — Deprecation sweep` as an explicit phase. Must land
|
||
before any new feature phase so coverage gates don't measure dead packages.
|
||
- **PC-03**: Split migration: `v0.9-P00b — Migration design + dry-run` (early,
|
||
parallel to deprecation) and `v0.10-P14 — Production migration` (final).
|
||
Migration design must inform every earlier phase, not be informed by them.
|
||
|
||
**Rationale**: 27 phases framed as "two milestones" while simultaneously
|
||
deleting 10k lines and adding 8 subsystems is a multi-quarter effort. The
|
||
deprecation work is a real phase that was not on the plan. With the override
|
||
and the v0.9-P00 additions, the plan is now structurally sound.
|
||
|
||
## Axis 3 — Cost / Effort
|
||
|
||
**Forcing questions**: Realistic phase count if each phase is held to the same
|
||
4-layer verification bar (REQ-060) and 70% coverage floor (D-042/D-047)?
|
||
Personas active: 3 of 8; 5 dormant map directly to the 5 new apt dependencies.
|
||
Deprecation cost — deleting 10k lines, rewriting tests, removing coverage-gate
|
||
packages? The bash scripts (8 in §26.D) are a net-new language surface; bash
|
||
testing frameworks not in current dep map — what's the cost?
|
||
|
||
**Evidence**: Active roster has 3 of 8 active; the 5 dormant personas map
|
||
directly to the 5 new apt dependencies. v0.8 took 4 phases for a pure
|
||
test/coverage milestone; v0.10 includes 11 distinct subsystems in one
|
||
"milestone." No bash test infrastructure exists today.
|
||
|
||
**Verdict**: PROCEED-WITH-CONDITION
|
||
**Confidence**: 0.70
|
||
|
||
**Binding conditions**:
|
||
- **C-04**: Produce a per-phase sizing estimate using v0.6/v0.7/v0.8 actuals
|
||
as the analogous baseline. If realistic phase count exceeds 35, the
|
||
milestone must be split into v0.9 + v0.10 (three milestones), not two.
|
||
- **C-05**: Reactivate or explicitly assign coverage for the dormant personas'
|
||
domains (security, network, devops); no "dormant" = "unowned."
|
||
- **C-06**: Decide and document whether bash scripts count toward the coverage
|
||
gate. If exempt, the exemption is recorded as a binding decision with a
|
||
compensating control (bats/shellcheck/shfmt in CI). If not exempt, the effort
|
||
estimate must include bash test authoring.
|
||
|
||
**Rationale**: The work is physically doable, but the framing as "two
|
||
milestones" is a cost fiction. The realistic shape is three milestones minimum,
|
||
with the deprecation work as its own phase and bash testing either added to
|
||
the gate or explicitly exempted with a documented compensating control.
|
||
|
||
## Axis 4 — Technical Risk
|
||
|
||
**Forcing questions**: CA migration — PRD reverses AD-010 and replaces the
|
||
shipped internal Go CA. What is the migration path for existing `ca.crt`/
|
||
`ca.key`/`server.crt`/`server.key` on every running cluster? SPIFFE SVID
|
||
minting at submit time (D-068) reverses the PROJECT.md:94 SPIFFE rejection —
|
||
has anyone prototyped the mint-at-submit path? Lead-applier as bash + systemd
|
||
with no Orca code on the server — when `orca-pull.sh` fails mid-render, what
|
||
is the recovery? Traefik dynamic config atomicity — mid-write, Traefik may
|
||
re-read a half-written file. Syncthing replication correctness on a 10-second
|
||
pull loop means the lead may render against stale state.
|
||
|
||
**Evidence**: AD-010 (ARCHITECTURE.md:463) is an explicit documented decision
|
||
*against* step-ca. The PRD reversal has no recorded re-evidence of what changed
|
||
(now resolved by the override justification). SPIFFE rejection at PROJECT.md:94
|
||
is the same pattern. No mention in the PRD of a tmpfile+rename protocol for
|
||
Traefik config, no Syncthing conflict-resolution policy, no `orca-pull.sh`
|
||
failure semantics. The shipped `internal/transport/mtls.go` had
|
||
retry+backoff+idempotency (REQ-037). The bash replacement has no equivalent
|
||
specified.
|
||
|
||
**Verdict**: PROCEED-WITH-CONDITION
|
||
**Confidence**: 0.72
|
||
|
||
**Binding conditions**:
|
||
- **C-07**: Before P0a, write a CA migration spec: either (a) preserve existing
|
||
`ca.crt` trust root and import into step-ca, or (b) document forced
|
||
re-bootstrap as an accepted breaking change with per-cluster upgrade
|
||
procedure. Cannot be deferred.
|
||
- **C-08**: Before the first SPIFFE-touching phase (v0.10 P02 ACL), produce a
|
||
working spike of step-ca JWT-SVID or X.509-SVID minting from the orca CLI
|
||
(v0.10-P01.5). If the spike fails, SPIFFE is deferred and ACL falls back to
|
||
mTLS identity (which the shipped model already had).
|
||
- **C-09**: Define and test the `orca-pull.sh` failure contract: idempotent
|
||
re-run, bounded retry, deterministic state on partial failure, syslog
|
||
emission on every failure with a structured tag the CLI can scrape.
|
||
- **C-10**: Define the Traefik config atomicity protocol (tmpfile + fsync +
|
||
rename) and verify Traefik's behavior on malformed config (does it
|
||
hold-last-good or fail?). Documented, tested.
|
||
|
||
**Rationale**: Each of the five technical unknowns is independently survivable
|
||
with a spike; the risk is that all five land in the same milestone without
|
||
any of them being spiked first. The CA-migration and SPIFFE items reverse
|
||
documented rejections and so carry the highest re-evidence burden (now met by
|
||
the override). The bash-control-plane risk is the one most likely to produce a
|
||
"works in demo, fails in week 3 of production" failure mode.
|
||
|
||
## Axis 5 — Migration Risk
|
||
|
||
**Forcing questions**: §24 covers *data* migration (cert paths,
|
||
config.hcl→config.md, db relocation). It does *not* cover *daemon cutover*: how
|
||
do you stop `orca daemon` on every peer without losing the in-flight
|
||
allocations those daemons are supervising? What happens to running
|
||
allocations during `orca upgrade --to-v1.0`? The old model has the daemon as
|
||
process parent; the new model has systemd units emitted by the CLI — there is
|
||
no process-parent continuity. The transition period where some peers are v0.8
|
||
(daemon) and some are v1.0 (no daemon) — what is the failure mode? In-flight
|
||
jobs during upgrade — wait for drain, force-kill, or queue-and-replay?
|
||
|
||
**Evidence**: §24 covers cert paths, config.hcl→config.md, db relocation —
|
||
three file-layout migrations. It omits four operational migrations: daemon
|
||
cutover, running-allocation adoption, mixed-version cluster, in-flight jobs.
|
||
The shipped executor (`internal/engine/executor.go:163`) uses
|
||
`os/exec.CommandContext` — the daemon is the process parent. systemd units
|
||
emit by the CLI would be a *different* parent (systemd). Process reparenting
|
||
is not portable across the orca model. "Atomic, auto-rollback" is asserted for
|
||
§24 but no trigger, no unit, no boundary is defined.
|
||
|
||
**Verdict**: REPLAN (mechanics — direction settled by override)
|
||
**Confidence**: 0.82
|
||
|
||
**Mechanics adopted**:
|
||
- **PC-04**: Split P14 into `v0.10-P14a — Data migration` (current scope),
|
||
`v0.10-P14b — Daemon cutover + running-allocation adoption`,
|
||
`v0.10-P14c — Mixed-version cluster tolerance + no-orca-on-server enforcement`.
|
||
Three sub-phases, each with its own integration test.
|
||
|
||
**Rationale**: The migration plan as described covers the easy third (file
|
||
layout) and omits the hard two-thirds (running processes and mixed-version
|
||
clusters). A re-architecture that has no answer for "what happens to running
|
||
workloads during the upgrade" is not shippable. With the P14 split, the plan
|
||
is now complete.
|
||
|
||
## Axis 6 — Operational Risk
|
||
|
||
**Forcing questions**: When `orca-pull.sh` fails on the lead, what happens to
|
||
workloads? When step-ca is down, can new workloads start? When Syncthing
|
||
conflicts, what is the conflict-resolution policy? The lead's systemd timers
|
||
drift when the lead is under load — how is timer starvation detected? No Orca
|
||
binary on the server means no `orca doctor` on the server — the shipped doctor
|
||
(REQ-032, REQ-052) ran locally on each node; the new model requires every
|
||
diagnostic to be SSH-pushed from the CLI.
|
||
|
||
**Evidence**: The shipped `orca doctor` runs locally (ARCHITECTURE.md §5,
|
||
REQ-032). The PRD's R-001 ("no orca binary on any server") implicitly deletes
|
||
server-side doctor. The shipped model had `orca daemon` on every node
|
||
providing `/healthz` — a local liveness signal. The new model has no
|
||
server-side health producer. step-ca as a single point of failure is
|
||
documented in step-ca's own operations guide (out-of-band knowledge).
|
||
|
||
**Verdict**: PROCEED-WITH-CONDITION
|
||
**Confidence**: 0.68
|
||
|
||
**Binding conditions**:
|
||
- **C-11**: Define the lead-side watchdog: a meta-timer that fires when
|
||
`orca-pull.sh` has not successfully run in N seconds, emitting a structured
|
||
alert. Document the alert path (syslog? CLI-pull?).
|
||
- **C-12**: Document step-ca's HA story. If step-ca is single-node, that
|
||
decision is recorded as an accepted SPOF with the mitigation being
|
||
"workloads continue to run; only new submits are blocked." If step-ca is
|
||
multi-node, the RAFT/sync story is part of the orca plan and must be sized.
|
||
- **C-13**: Replace server-side doctor with a CLI-driven equivalent that
|
||
SSH-probes every node and reconstructs the health view the daemon used to
|
||
provide locally. This is a new requirement, not a feature; added as
|
||
I-C-002 / v0.10-P14c.
|
||
- **C-14**: Syncthing conflict-resolution policy must be deterministic,
|
||
documented, and tested with a forced-divergence integration test.
|
||
|
||
**Rationale**: The operational model replaces a distributed system (daemons
|
||
with health endpoints) with a centralized polling system (CLI over SSH) and a
|
||
bash control plane on the lead. The mitigations are knowable but unspecified.
|
||
|
||
## Axis 7 — Security
|
||
|
||
**Forcing questions**: The master.key (AES-256-GCM for `.env.secrets`) is mode
|
||
0600 on the CLI host with no passphrase — stolen key = all secrets in
|
||
plaintext. The shipped model distributed keys with operator mediation (D-012).
|
||
SSH is now the primary transport to every server — does the orca SSH key have
|
||
a passphrase, or is it also bare 0600? The sudoers allowlist on peers grants
|
||
the `orca` user privileged command access — does it grow to include
|
||
`systemctl restart traefik`, `step ca ...`, `podman ...`? Five new attack
|
||
surfaces: step-ca, Traefik, Syncthing, wasmtime, podman. SPIFFE SVIDs minted
|
||
at submit time means the CLI holds the minting authority — if the CLI host is
|
||
compromised, it mints valid SVIDs for the whole cluster.
|
||
|
||
**Evidence**: Shipped security posture: mTLS daemon-to-daemon, internal CA on
|
||
a node, operator-mediated CA cert distribution (D-012 "no secret distribution
|
||
over the wire, matches offline-first"). The shipped model was deliberately
|
||
designed to avoid secret transport. New posture: CLI holds master.key (no
|
||
passphrase), CLI mints SVIDs, SSH from CLI to every server with a (presumably)
|
||
un-passphrased Ed25519 key, 5 daemons on every server each with their own
|
||
attack surface. ARCHITECTURE.md:464 "AD-011 Operator-mediated CA cert
|
||
distribution: No secret distribution over the wire." The new model puts a
|
||
master.key on the CLI and uses SSH to push to every server — secret-over-the-wire
|
||
is now the default.
|
||
|
||
**Verdict**: REPLAN (mechanics — direction settled by override)
|
||
**Confidence**: 0.74
|
||
|
||
**Mechanics adopted**:
|
||
- **C-19**: Write a threat model for the new posture before any
|
||
security-touching phase (v0.10-P15.5). Defend master.key + CLI mint authority
|
||
or revise. The shipped model deliberately avoided putting a single stealable
|
||
file on a single host that decrypts all secrets and mints all identities.
|
||
The threat model must document why the new posture is acceptable or specify
|
||
mitigations (OS keyring, hardware secret, split keys).
|
||
|
||
**Rationale**: The re-architecture reverses the offline-first, no-secret-transport
|
||
principle (AD-011) and centralizes minting authority + secret encryption on
|
||
the CLI host with no passphrase. A threat model must be written and the
|
||
master.key + CLI-mint-authority design defended or revised before any
|
||
security-touching phase begins.
|
||
|
||
## Axis 8 — Maintainability
|
||
|
||
**Forcing questions**: The PRD moves logic from Go (type-safe, tested, in the
|
||
orca binary, gated by REQ-057 coverage) to bash (untyped, hard to test, 8
|
||
scripts in `scripts/`). How will the 8 bash scripts be tested under the
|
||
project's coverage gate? Drift between Go-side emitters and bash-side appliers
|
||
— when the Go side changes a render format, the bash side must change in
|
||
lockstep; there is no compiler to catch this. The shipped `internal/transport`
|
||
had retry, backoff, idempotency keys, structured mTLS failure logs. The bash
|
||
replacement has none specified. Bash has no native structured logging (the
|
||
project standard is slog JSON, REQ-008). The 8 scripts are a new language
|
||
surface in a Go-only project.
|
||
|
||
**Evidence**: PROJECT.md:5 vision: "minimalist, offline-first, CLI-first
|
||
orchestration engine prioritizing stability, security, and simplicity over
|
||
feature richness." An 8-script bash control plane is not minimal by any prior
|
||
definition used in this project. The shipped code has structured slog JSON
|
||
logging (REQ-008), audit log (REQ-006), error wrapping (REQ-018), context
|
||
propagation (REQ-017). Bash has none of these natively. No bash test
|
||
framework in current dep map; no `bats`/`shunit2` reference. The 70%/50%
|
||
coverage gate (D-042/D-047) is Go-specific.
|
||
|
||
**Verdict**: PROCEED-WITH-CONDITION
|
||
**Confidence**: 0.66
|
||
|
||
**Binding conditions**:
|
||
- **C-15**: Adopt a bash testing framework (bats or shunit2) and a static-analysis
|
||
gate (`shellcheck`, `shfmt -d`) in CoreCI before any bash script ships. Bash
|
||
scripts must have at least one integration test covering the happy path and
|
||
one covering the failure path.
|
||
- **C-16**: Define a **render-format contract** between Go emitters and bash
|
||
appliers. Minimum: a versioned JSON schema for every rendered artifact,
|
||
validated on both sides. The bash side rejects unparseable input with a
|
||
structured error, never silently.
|
||
- **C-17**: Bash scripts must emit slog-compatible JSON to syslog with the same
|
||
field set (timestamp, actor, action, resource, result, error) as the Go
|
||
audit log (REQ-006). No unstructured text in audit.
|
||
- **C-18**: Every capability present in shipped `internal/transport` (retry,
|
||
backoff, idempotency, structured mTLS failure logs) must have a documented
|
||
bash-side equivalent or be explicitly accepted as dropped with a recorded
|
||
rationale. Capability regressions must be visible, not silent.
|
||
|
||
**Rationale**: Bash is not inherently unmaintainable, but bash *in a Go-only,
|
||
coverage-gated, structured-logging project* is a language-without-rails. Without
|
||
the four conditions above, the bash control plane becomes the part of the
|
||
codebase that everyone is afraid to touch by v0.10 P05. The drift between Go
|
||
emitters and bash appliers is the single most likely source of "works on the
|
||
CLI's machine, fails on the lead" bugs.
|
||
|
||
## Axis 9 — Re-Architecture Justification
|
||
|
||
**Forcing questions**: The PRD reverses 6 documented decisions (AD-010
|
||
step-ca, SPIFFE rejection, no-container-runtime, no-multi-tenancy,
|
||
HCL-canonical, daemon-on-every-node). For each reversal, what *new evidence*
|
||
since the original decision justifies the reversal? The shipped v0.8 model is
|
||
*working* — 8 milestones, REQ-001..060 Complete, 4-layer verification passing,
|
||
coverage gates met. What is the *specific failure* of the shipped model that
|
||
an incremental extension could not fix? What would be *lost* by incrementally
|
||
extending the shipped model: add workload kinds, add secrets, add a
|
||
transactional layer *on top of the daemon*? Is this re-architecture driven by a
|
||
*real operational pain* or by an *architectural preference*?
|
||
|
||
**Evidence**: ROADMAP.md and PROJECT.md: every milestone from v0.1 to v0.8
|
||
explicitly says "the vision is unchanged; this milestone is not a direction
|
||
change." v0.9/v0.10 is the *first* milestone in the project's history that
|
||
reverses the vision's anti-patterns. AD-010's rationale: "step-ca/cfssl/
|
||
vault-pki too heavyweight for Orca's footprint." Nothing in the original PRD
|
||
suggested Orca's footprint changed. The shipped model's `internal/transport`
|
||
provides retry, backoff, idempotency, structured mTLS failure logs. The PRD
|
||
replaces this with bash + systemd + SSH. No evidence the shipped transport
|
||
was a source of operational pain.
|
||
|
||
**Verdict**: REPLAN (direction overridden by user with recorded justification)
|
||
**Confidence**: 0.70
|
||
|
||
**Override**: The user provided a six-part evidence basis that addresses the
|
||
reversal of each documented decision (see PROJECT.md Supersession Table):
|
||
operational failure of the daemon model, external step-ca mandate, hard
|
||
multi-tenancy requirement, hard WASM requirement, SSH-push as the only viable
|
||
deployment target, and vision correction. The override is recorded; the
|
||
direction holds.
|
||
|
||
**Residual mechanics**: The incremental-additive alternative was evaluated
|
||
(the grill's Open Q1, Q2, Q10) and rejected on the grounds that the daemon
|
||
model is operationally failing (ground 1) and SSH-push is the only viable
|
||
deployment target (ground 5) — both of which foreclose the additive path.
|
||
|
||
**Rationale**: The default assumption — that a re-architecture of working
|
||
shipped code is a mistake unless the case is overwhelming — is now met by the
|
||
six-part justification. The re-architecture proceeds.
|
||
|
||
---
|
||
|
||
# Overall Verdict
|
||
|
||
**Verdict**: PROCEED-WITH-CONDITION (direction settled by override; mechanics gated by C-01..C-19)
|
||
**Confidence**: 0.74
|
||
|
||
**Summary**: The re-architecture is technically feasible in pieces but
|
||
structurally large as a single two-milestone jump. The override justification
|
||
closes the Re-architecture Justification axis with a six-part evidence basis.
|
||
The remaining mechanics: reorder phases (PC-01..PC-10), split heavy phases,
|
||
add the v0.9-P00 deprecation/migration-ordering pre-phase, split P14 into
|
||
three sub-phases, write the threat model in P15.5, and gate the 19 binding
|
||
conditions (C-01..C-19) as execution gates. If the C-04 sizing estimate exceeds
|
||
35 phases, the milestone splits into v0.9 + v0.10 + v1.0.
|
||
|
||
# Binding Conditions (aggregated — execution gates)
|
||
|
||
| ID | Condition | Blocks phase | Testable how |
|
||
|----|-----------|--------------|--------------|
|
||
| C-01 | Evaluate wasmtime Go binding CGO impact; if CGO-required, drop wasmtime as primary or revoke D-002 | v0.9-P07b | Build matrix spike on linux/amd64+arm64; revocation decision recorded |
|
||
| C-02 | Syncthing feasibility spike: config injection, conflict policy, deterministic failure mode | v0.9-P09 | Spike report + forced-divergence integration test |
|
||
| C-03 | Check PRD into `.ciagent/PRD_v0.9.md` before any v0.9 phase begins | (gate) | ✅ Resolved — file committed |
|
||
| C-04 | Per-phase sizing estimate vs v0.6/v0.7/v0.8 actuals; if >35, split into v0.9+v0.10 | v0.9 start | ✅ RESOLVED — operator decision: keep 2 milestones (v0.9+v0.10), keep all phases (40 total), v1.0 UAT-gated after v0.10 |
|
||
| C-05 | Reactivate or assign dormant persona domains (security, network, devops) | v0.9-P00 | PERSONAS.md updated with named owners |
|
||
| C-06 | Decide bash coverage-gate status; if exempt, record compensating control | v0.9-P00 | Decision recorded in PROJECT.md D-series; CI pipeline shows the gate |
|
||
| C-07 | CA migration spec: preserve existing trust root or document forced re-bootstrap | v0.10-P14a | Spec doc + migration dry-run on test cluster |
|
||
| C-08 | SPIFFE SVID minting spike; if fails, fall back to mTLS identity | v0.10-P02 (spike in P01.5) | Working SVID mint from orca CLI in sandbox |
|
||
| C-09 | `orca-pull.sh` failure contract: idempotent re-run, bounded retry, deterministic state, structured syslog | v0.10-P10 | Failure-path integration test + syslog structured-tag verification |
|
||
| C-10 | Traefik config atomicity protocol (tmpfile+fsync+rename) + malformed-config behavior verified | v0.9-P02 | Atomic-rename test + Traefik malconfig-hold-last-good assertion |
|
||
| C-11 | Lead-side watchdog meta-timer for `orca-pull.sh` starvation, with structured alert path | v0.10-P09 | Watchdog fires on injected pull failure; alert received |
|
||
| C-12 | Document step-ca HA story; if single-node, record as accepted SPOF with mitigation | v0.10-P09 | Decision doc; if HA, RAFT/sync story in orca plan |
|
||
| C-13 | Replace server-side doctor with CLI-SSH-driven equivalent | v0.10-P14c | New REQ-086 in REQUIREMENTS.md; integration test SSH-probes N nodes |
|
||
| C-14 | Syncthing conflict-resolution policy deterministic + forced-divergence integration test | v0.10-P09 | Test induces divergence; resolves to single deterministic state |
|
||
| C-15 | Bash testing framework (bats/shunit2) + shellcheck + shfmt in CoreCI before any bash ships | v0.9-P00 | CI pipeline green with the gate on a sample script |
|
||
| C-16 | Versioned JSON-schema render-format contract between Go emitters and bash appliers | v0.9-P00 | Schema file in repo; both sides validate; mismatch fails CI |
|
||
| C-17 | Bash scripts emit slog-compatible JSON to syslog with audit-log field set (REQ-006) | v0.9-P00 | Syslog capture test verifies field-presence + JSON parse |
|
||
| C-18 | Document bash-side equivalents (or accepted drops) for shipped transport capabilities | v0.9-P00 | Capability-mapping doc in `.ciagent/` |
|
||
| C-19 | Write a threat model for the new posture; defend master.key + CLI mint authority or revise | v0.10-P15.5 | Threat-model doc reviewed and committed; design revised if regression found |
|
||
|
||
# Phase Plan Challenges
|
||
|
||
| # | Phase | Problem | Fix |
|
||
|---|-------|---------|-----|
|
||
| PC-01 | v0.9 P0a–P10 | Ship 10 phases of workload features before the transactional control plane | Design spike in v0.9-P00; full impl in v0.10-P10 per PRD ordering (workloads first accepted with dual-write mitigation) |
|
||
| PC-02 | (missing) | Deprecation of ~10k lines of daemon/transport/CA code is not a phase | Add `v0.9-P00 — Deprecation sweep` as explicit phase before any new feature phase |
|
||
| PC-03 | v0.9 P10 | Migration is the last phase of v0.9 but is highest-risk | Split: migration design in v0.9-P00 (early), implementation in v0.10-P14 (final) |
|
||
| PC-04 | v0.10 P14 | Covers data migration only; omits running-allocation cutover, mixed-version cluster, rollback trigger | Split into P14a (data), P14b (daemon cutover), P14c (mixed-version tolerance) |
|
||
| PC-05 | v0.10 P02 | SPIFFE is a documented reversal with no spike; lands before spike possible | Insert `v0.10-P01.5 — SPIFFE mint spike` as hard gate before P02 |
|
||
| PC-06 | v0.10 P10 | Transactional plane depends on lead-applier bash scripts (C-09) not gated | Reorder to v0.9-P00 design + add C-09 gate |
|
||
| PC-07 | v0.10 P15/P16 | README before security threat model | Add `v0.10-P15.5 — Threat model + security review` before final review |
|
||
| PC-08 | (missing) | No phase replaces server-side `orca doctor` | Add as I-C-002 / v0.10-P14c (CLI-SSH-driven doctor) |
|
||
| PC-09 | v0.9 P09 | Syncthing lands before feasibility spike (C-02) | Spike must precede P09; if P09 is the spike, rename + gate on spike success |
|
||
| PC-10 | v0.9 P07 | Five runtimes in one phase, including wasmtime (CGO risk) and pve-vm/pve-ct | Split: P07a (process+podman), P07b (wasmtime, C-01 gated), P07c (pve-vm+ct) |
|
||
|
||
# Open Questions (feed back to IDEATE/PLAN; resolved where noted)
|
||
|
||
1. **What measured operational failure of the shipped v0.8 daemon model is the re-architecture responding to?** — ✅ Resolved by override ground 1.
|
||
2. **Can the v0.9 scope be delivered as additive extensions?** — ✅ Resolved: rejected per override grounds 1 + 5.
|
||
3. **What is the wasmtime/CGO resolution?** — Closes via C-01 spike in v0.9-P07b.
|
||
4. **What is the master.key threat model?** — Closes via C-19 in v0.10-P15.5.
|
||
5. **What is the rollback unit of work for §24, and what triggers it?** — Must be answered in v0.9-P00 txn-design spike (I-B-007).
|
||
6. **Is step-ca single-node acceptable as a cluster SPOF?** — Closes via C-12 in v0.10-P09.
|
||
7. **Can the bash control plane be reduced?** — Closes in v0.9-P00 (fold 3+ scripts into Go-side SSH invocations where possible).
|
||
8. **What is the realistic phase count?** — Closes via C-04 sizing before v0.9 starts; if >35, the plan becomes three milestones.
|
||
9. **Does the PRD's reversal of 6 documented decisions require a formal AD-series supersession?** — ✅ Resolved: supersession table recorded in PROJECT.md + ARCHITECTURE.md.
|
||
10. **What is the smallest possible version of this re-architecture that delivers 80% of the value?** — ✅ Resolved: the override rejected the incremental-additive path; the full re-architecture proceeds per the six-part justification.
|
||
|
||
# Binding Decisions (this grill session, G-001..G-009)
|
||
|
||
| ID | Decision | Confidence |
|
||
|----|----------|-----------|
|
||
| G-001 | Feasibility: PROCEED-WITH-CONDITION (C-01..C-03) | 0.62 |
|
||
| G-002 | Scope: REPLAN mechanics (PC-01..PC-03) — direction settled by override | 0.78 |
|
||
| G-003 | Cost: PROCEED-WITH-CONDITION (C-04..C-06) | 0.70 |
|
||
| G-004 | Tech Risk: PROCEED-WITH-CONDITION (C-07..C-10) | 0.72 |
|
||
| G-005 | Migration: REPLAN mechanics (PC-04) — direction settled by override | 0.82 |
|
||
| G-006 | Op Risk: PROCEED-WITH-CONDITION (C-11..C-14) | 0.68 |
|
||
| G-007 | Security: REPLAN mechanics (C-19) — direction settled by override | 0.74 |
|
||
| G-008 | Maintainability: PROCEED-WITH-CONDITION (C-15..C-18) | 0.66 |
|
||
| G-009 | Re-architecture Justification: direction overridden by user with six-part evidence basis; mechanics closed | 0.70 |
|
||
|
||
# Escalations (auto-resolved under full autonomy)
|
||
|
||
| E-ID | Item | Auto-decision | Mitigation |
|
||
|------|------|---------------|-----------|
|
||
| E-01 | Whether the re-architecture is justified vs incremental | OVERRIDDEN by user — direction holds | Six-part evidence basis recorded in PROJECT.md Supersession Table |
|
||
| E-02 | Whether master.key passphrase-less posture is acceptable | REPLAN mechanics — threat model first | C-19 in v0.10-P15.5; if threat model shows regression vs shipped, revise design |
|
||
| E-03 | Whether 27 phases fit in 2 milestones | Auto-split if sizing exceeds 35 | ✅ RESOLVED — operator: keep 2 milestones (v0.9+v0.10), keep all phases, v1.0 UAT-gated | |