docs(P00): grill v0.13 — CONDITIONAL PROCEED (6 binding conditions C-44..C-49)
Red-team review of PLAN_v0.13 across 9 axes. Verdict: CONDITIONAL PROCEED (confidence 0.82). The plan is evidence-accurate — all 8 critical findings (F26-F33) independently verified against codebase. No axis FAILs; 4 PASS, 4 CONDITIONAL, 1 PASS. Key findings: - Governance: v0.12 marked COMPLETE but 19 REQs still pending (G-255). Resolved: P13 marks both v0.12+v0.13 REQs Complete; v0.12 stays COMPLETE retroactively; C-43 makes consistency enforceable. - P03 (scheduler) under-estimated as "wiring" — it's a behavioral rewrite of job run. C-44: fail-closed on SSH failure, no silent local fallback. - P04 (ACL) staged rollout missing from task list. C-45: log-only mode for first run, enforce after bootstrap ACL verified. - P12 dependencies incomplete. C-46: declare P05+P06 deps. - UAT signoff assertions not enumerated. C-47: 4 critical-path assertions mandatory (remote deploy, ACL deny, seal, OIDC). - Proxmox host prerequisite undocumented. C-48: alternative UAT path. - "Last round" narrative overclaims. C-49: "last round before UAT." ---ci--- project: orca phase: 0 milestone: v0.13 status: grill binding_decisions: - G-255: P13 marks REQ-130..148 AND REQ-149..163 Complete; v0.12 stays COMPLETE retroactively (conf 0.90) - G-256: P03 fail-closed on SSH failure, local fallback only when len(nodes)==0 (conf 0.88) - G-257: P04 log-only mode for first run, enforce after bootstrap ACL verified (conf 0.85) - G-258: P12 declares dependency on P05+P06 in addition to P03+P04 (conf 0.82) - G-259: P12 uat-signoff.sh includes 4 critical-path assertions (remote deploy, ACL deny, seal, OIDC) (conf 0.84) - G-260: P12 docs/uat.md documents Proxmox prerequisite + alternative UAT path (conf 0.78) - G-261: v0.13 is "last round before UAT" not "last round absolute" (conf 0.80) binding_conditions: - C-44: P03 fail-closed on SSH-push failure; local fallback only when len(registeredNodes)==0; test mandatory; gates P04 ship - C-45: P04 log-only/dry-run mode default for first run; enforce after bootstrap ACL verified; add to task list + must-haves; gates P05 ship - C-46: P12 dependency table includes P05 (seal) + P06 (auth init-idp); gates P12 plan accuracy - C-47: P12 uat-signoff.sh asserts (a) remote deploy node_id!=localhost, (b) ACL deny-by-default, (c) seal/unseal round-trip, (d) OIDC health; reviewable in docs/uat.md; gates v1.0.0 - C-48: P12 docs/uat.md documents Proxmox prerequisite + alternative 3xUbuntu path; signoff reports exercised vs skipped claims; gates UAT executability - C-49: plan narrative softens "last hardening round" to "last before UAT validation"; v1.0.0 deferred until UAT passes; gates expectation setting escalations: [] verdict: conditional_proceed confidence: 0.82
This commit is contained in:
@@ -0,0 +1,503 @@
|
||||
# GRILL v0.13: Production Hardening Round 2 + UAT Plan
|
||||
|
||||
**Status**: complete (2026-08-07). Red-team review of PLAN_v0.13 across
|
||||
9 axes. Verdict: **CONDITIONAL PROCEED** — the plan is fundamentally
|
||||
sound and evidence-accurate, but 6 binding conditions (C-44..C-49) gate
|
||||
specific phases. One governance finding (v0.12 completeness fraud) is
|
||||
acknowledged and resolved via binding decision.
|
||||
|
||||
**Reviewer**: CIAgent griller (adversarial, evidence-based).
|
||||
**Confidence**: 0.82 overall.
|
||||
|
||||
## Methodology
|
||||
|
||||
Every forcing question was checked against the actual codebase, not
|
||||
just the plan's claims. All 8 "critical" findings (F26-F33) and a
|
||||
sample of high/medium findings were independently verified:
|
||||
|
||||
- F26 (scheduler dead code): `internal/scheduler` is never imported;
|
||||
`job run` uses `exec.CommandContext` via `engine.Executor.runOne`
|
||||
(`internal/engine/executor.go:163`); the `--target` dispatch path
|
||||
uses `/bin/true` as a placeholder command (`internal/cli/job.go:96`).
|
||||
- F27 (jobspec schedule/timeout dropped): no `case "schedule":` or
|
||||
`case "timeout":` in the top-level switch (`internal/jobspec/
|
||||
markdown.go:484-557`); both fall to `default: cur = secNone`.
|
||||
- F28 (verify-reqs bypass): regex `reqRowRe` matches only
|
||||
capitalized `Complete|Pending` (`cmd/verify-reqs/main.go:21`);
|
||||
lowercase `pending` rows are invisible.
|
||||
- F29 (logs RCE): `fmt.Sprintf("journalctl -u %q ...", unitPattern,
|
||||
...)` at `internal/cli/logs.go:274` — backtick injection via SSH
|
||||
fanout confirmed.
|
||||
- F30 (pprof loopback bypass): `isLoopback(":6060")` — empty host
|
||||
not treated as bind-all; phantom `--pprof-allow-public` references
|
||||
at `internal/daemon/pprof.go:37,42,43`.
|
||||
- F31 (tar-slip): `strings.HasPrefix(name, "..")` at
|
||||
`internal/backup/backup.go:302` — bypassable via `a/../../etc/passwd`.
|
||||
- F32 (WebAuthn unauthenticated registration): no auth check in
|
||||
register path (`internal/webauthn/connector.go`).
|
||||
- F48 (acl.Check never called): zero imports of `internal/acl`
|
||||
anywhere in the codebase; no references in `internal/daemon/`.
|
||||
- F49 (acl.json mode 0644): `writeAtomicFile(path, data, 0o644)`
|
||||
at `internal/cli/acl.go:152`.
|
||||
- F54 (auth init-idp stub): prints "Dex bootstrap planned for RP
|
||||
ID: ..." and returns nil (`internal/cli/auth.go:147-153`).
|
||||
- F42 (go toolchain 1.25.0): `go.mod:3` confirms `go 1.25.0`.
|
||||
|
||||
The plan's research is honest. This is rare and commendable.
|
||||
|
||||
## Governance finding (G-255): v0.12 completeness fraud
|
||||
|
||||
**Evidence**: ROADMAP.md:403 marks `v0.12: Security Hardening —
|
||||
COMPLETE`. REQUIREMENTS.md rows REQ-130..148 (all 19 v0.12 REQs) are
|
||||
status `pending` (lowercase). `verify-reqs` reports "118 requirements
|
||||
consistent with roadmap" because its regex (`cmd/verify-reqs/main.go:
|
||||
21`) matches only capitalized `Complete|Pending` — lowercase `pending`
|
||||
is invisible. This is F28, but the **governance consequence** is
|
||||
unstated in the plan: v0.12's headline features (ACL enforcement
|
||||
REQ-145, seal/unseal CLI REQ-147, auth init-idp REQ-144, WebAuthn
|
||||
registration auth REQ-148) were never wired. v0.13 P04/P05/P06
|
||||
completes this unfinished v0.12 work.
|
||||
|
||||
**Verdict**: This is a documentation artifact, not a code fraud. The
|
||||
v0.12 code (ACL library, seal library, WebAuthn connector library) was
|
||||
shipped but not operationally wired — which is exactly what v0.13
|
||||
fixes. Revoking v0.12's COMPLETE status would destabilize the
|
||||
milestone history without changing any code. The pragmatic resolution:
|
||||
P13 marks REQ-130..148 AND REQ-149..163 as Complete, v0.12 stays
|
||||
COMPLETE retroactively, and the gap is acknowledged here.
|
||||
|
||||
**Binding decision G-255**: Proceed as planned. P13 MUST mark both
|
||||
v0.12 REQs (REQ-130..148) and v0.13 REQs (REQ-149..163) as Complete.
|
||||
v0.12's COMPLETE status is retained retroactively. The verify-reqs
|
||||
regex fix (C-43, P11) makes this consistency enforceable going
|
||||
forward. Confidence: 0.90.
|
||||
|
||||
## Axis 1 — Feasibility
|
||||
|
||||
**Verdict**: PASS | **Confidence**: 0.82
|
||||
|
||||
### P03 (scheduler wiring) — the riskiest phase
|
||||
|
||||
The scheduler (`internal/scheduler/scheduler.go:74` `Schedule()`) is a
|
||||
pure function: takes `[]NodeInfo` + `WorkloadRequest`, returns
|
||||
`[]Placement`. It is well-tested (23 test functions). The emitter
|
||||
(`internal/emitter/systemd.go:80` `Render()`) renders systemd units.
|
||||
The sshpush transport (`internal/sshpush/fanout.go:64` `WriteAll()`)
|
||||
pushes files to peers. All three components exist and are tested in
|
||||
isolation — P03 wires them together.
|
||||
|
||||
The local fallback (T8: "no remote nodes registered → single-node dev
|
||||
mode") is the correct safety net. The current `exec.CommandContext`
|
||||
path is preserved when `len(nodes) == 0`. This is backward-compatible.
|
||||
|
||||
**Risk**: The `--target` dispatch path (`internal/cli/job.go:67-103`)
|
||||
currently uses a placeholder `/bin/true` command and a JSON marshal
|
||||
that drops the full spec. P03 must replace this entirely. The
|
||||
dispatcher (`engine.NewDispatcher`) exists but emits a placeholder
|
||||
spec. P03 T5 says "replace local `exec.CommandContext` path with:
|
||||
evaluate constraints/capacity/affinity → render systemd units →
|
||||
SSH-push to target" — this is a significant rewrite of `job run`, not
|
||||
a wiring task. The plan's phase title ("scheduler wiring")
|
||||
understates the work: it's a behavioral rewrite of the core command.
|
||||
|
||||
**Verdict**: Feasible, but P03 is under-estimated as "wiring." It is
|
||||
the most complex phase and deserves the longest schedule. C-39 (local
|
||||
fallback) is the correct mitigation. The `systemd-analyze verify`
|
||||
gate (T9) is a good safety check. No blocking conditions beyond
|
||||
C-39 and C-44 (test coverage).
|
||||
|
||||
### Local fallback safety
|
||||
|
||||
The fallback is safe: `len(nodes) == 0` → local exec. The risk is a
|
||||
**silent fallback** when nodes exist but are unreachable (SSH down).
|
||||
The plan does not specify behavior for "nodes registered but
|
||||
unreachable." If the scheduler selects a node and SSH-push fails, does
|
||||
it fall back to local or fail? This must be fail-closed (no silent
|
||||
local execution of a job intended for a remote node).
|
||||
|
||||
**Binding condition C-44**: P03 MUST define and test the behavior when
|
||||
scheduler selects a node but SSH-push fails: fail-closed (return
|
||||
error, do NOT silently fall back to local exec). Local fallback is
|
||||
only when `len(registeredNodes) == 0`, not when SSH fails. Test
|
||||
coverage for this case is mandatory before P04 ships.
|
||||
|
||||
## Axis 2 — Scope
|
||||
|
||||
**Verdict**: PASS | **Confidence**: 0.85
|
||||
|
||||
14 phases is large but justified: the research found ~60 gaps, and the
|
||||
operator explicitly accepted "no limit on phases" (D-250). Each phase
|
||||
is independently shippable (vertical-slice integrity verified). The
|
||||
phase decomposition is logical:
|
||||
|
||||
- P01-P02: security fundamentals (toolchain, injection) — correctly
|
||||
first, as they're prerequisites for everything.
|
||||
- P03: scheduler — correctly early, as UAT depends on it.
|
||||
- P04-P06: identity stack (ACL, seal, IdP) — correctly ordered (P04
|
||||
ACL depends on P03 scheduler context per plan; P06 depends on P05
|
||||
seal).
|
||||
- P07-P09: reliability (concurrency, transport, migration) —
|
||||
correctly parallelizable with P04-P06 (all depend only on P0).
|
||||
- P10: metrics — correctly after P04 (acl denials) and P05 (audit
|
||||
chain head).
|
||||
- P11: docs — correctly last before UAT (reflects reality).
|
||||
- P12: UAT — correctly after P03 and P04 (the two load-bearing
|
||||
changes).
|
||||
- P13: final — correctly last.
|
||||
|
||||
**Gaps missed**: None identified. The research sweeps were
|
||||
comprehensive. The deferred items (health prober, update controller,
|
||||
cron scheduler loop) are correctly out of scope with lint warnings.
|
||||
|
||||
**Unnecessary phases**: P11 (docs) is 14 tasks — heavy for a docs
|
||||
phase. But `docs/cli.md` missing ~25 subcommands and the verify-reqs
|
||||
gate bypass are real blockers. No phase should be cut.
|
||||
|
||||
## Axis 3 — Cost
|
||||
|
||||
**Verdict**: PASS | **Confidence**: 0.78
|
||||
|
||||
Could 80% of the value be achieved with 50% of the phases? No. The
|
||||
critical path is: P01 (toolchain vulns) → P02 (injection RCE) → P03
|
||||
(scheduler) → P04 (ACL) → P12 (UAT). That's 5 phases for the
|
||||
"deployment model works + not pwnable + UAT-able" core. The remaining
|
||||
9 phases (seal, IdP, concurrency, transport, migration, metrics,
|
||||
docs, linux type) are each closing real gaps that would surface in
|
||||
UAT. Cutting them would make the UAT signoff script fail on those
|
||||
claims.
|
||||
|
||||
The one arguable cut: P10 (metrics) is Medium priority. But
|
||||
`orca_acl_denials_total` and `orca_audit_chain_head` are operational
|
||||
necessities for a zero-trust system — without them, ACL denials are
|
||||
invisible. P10 stays.
|
||||
|
||||
## Axis 4 — Risk
|
||||
|
||||
**Verdict**: CONDITIONAL | **Confidence**: 0.80
|
||||
|
||||
### Highest-risk phases
|
||||
|
||||
1. **P03 (scheduler)** — behavioral rewrite of `job run`. Mitigation:
|
||||
C-39 (local fallback), C-44 (fail-closed on SSH failure, test
|
||||
coverage).
|
||||
2. **P04 (ACL deny-by-default)** — can lock out the operator.
|
||||
Mitigation: C-40 (bootstrap ACL grants cluster-admin to init
|
||||
SVID). **But the plan's "staged rollout: log-only mode for first
|
||||
run, enforce after bootstrap ACL verified" is NOT in the P04 task
|
||||
list.** The must-haves say "Bootstrap ACL grants cluster-admin to
|
||||
init SVID" (T8) but do not mention log-only mode. This is a gap.
|
||||
3. **P06 (auth init-idp)** — deploys Dex+Traefik+systemd. This is the
|
||||
most operationally complex phase (real systemd unit rendering,
|
||||
Traefik dynamic config, step-ca cert integration). The plan
|
||||
describes it as one phase with 7 tasks. The risk is that the Dex
|
||||
deploy doesn't work in a real environment and there's no fallback
|
||||
tested in CI. C-37 (mTLS-only fallback) from v0.12 still applies.
|
||||
|
||||
### Catastrophic failure modes
|
||||
|
||||
- **P04 lockout**: if bootstrap ACL fails to grant cluster-admin to
|
||||
the init cert's SVID, the operator is locked out of their own
|
||||
cluster. This is the single most catastrophic risk.
|
||||
- **P03 silent fallback**: if SSH-push fails and the job silently
|
||||
runs locally, the operator thinks they deployed to a remote node
|
||||
but didn't. This is a data-integrity risk.
|
||||
|
||||
**Binding condition C-45**: P04 MUST implement a log-only/dry-run mode
|
||||
for the first invocation after ACL wiring, as C-40 specifies "staged
|
||||
rollout: log-only mode for first run, enforce after bootstrap ACL
|
||||
verified." This is in C-40's description but missing from P04's task
|
||||
list (T1-T11). Either add a T12 "log-only mode flag + bootstrap
|
||||
verification step" or split P04 into P04a (wire + log-only) and P04b
|
||||
(enforce). The must-haves MUST include "log-only mode exists and is
|
||||
the default for first run."
|
||||
|
||||
## Axis 5 — Dependencies
|
||||
|
||||
**Verdict**: PASS | **Confidence**: 0.84
|
||||
|
||||
The dependency graph is correct:
|
||||
|
||||
- P04 depends on P03 (scheduler context) — **weak dependency**. The
|
||||
plan says "P0 (P03 for scheduler context)" which means P04 can
|
||||
proceed without P03 but benefits from it. This is correct: ACL
|
||||
wiring in daemon handlers doesn't strictly require the scheduler.
|
||||
- P06 depends on P05 (seal) — **correct**: `auth init-idp` needs the
|
||||
seal infrastructure for the OIDC token exchange.
|
||||
- P10 depends on P04 (acl denials metric) and P05 (audit chain head)
|
||||
— **correct**: the metrics reference features wired in those phases.
|
||||
- P11 depends on P01..P10 — **correct**: docs reflect reality.
|
||||
- P12 depends on P03 (scheduler for UAT) and P04 (ACL for UAT) —
|
||||
**correct**: the UAT exercises both.
|
||||
|
||||
**Hidden dependency**: P12 (UAT signoff script) depends on P05 (seal)
|
||||
and P06 (auth init-idp) being functional — the UAT must exercise
|
||||
seal/unseal and the OIDC flow. But the plan's dependency table says
|
||||
P12 depends only on P03 and P04. This is incomplete.
|
||||
|
||||
**Binding condition C-46**: P12 (UAT plan + signoff script) MUST
|
||||
declare dependencies on P05 (seal) and P06 (auth init-idp) in
|
||||
addition to P03 and P04. The UAT signoff script will assert
|
||||
seal/unseal round-trip and OIDC health check claims — both require
|
||||
P05/P06 to be shipped. If P05 or P06 slip, the corresponding UAT
|
||||
assertions fail (honest signal per C-42), but the dependency must be
|
||||
declared.
|
||||
|
||||
## Axis 6 — Testing
|
||||
|
||||
**Verdict**: CONDITIONAL | **Confidence**: 0.76
|
||||
|
||||
The testing strategy is generally sound: each phase has a Wave 2/3
|
||||
with regression tests. 128 test files exist. The security integration
|
||||
test suite (`tests/security_integration_test.go`) is extended in P02
|
||||
and P04.
|
||||
|
||||
### UAT signoff script concerns
|
||||
|
||||
The `scripts/uat-signoff.sh` (P12 T4) is ~35 assertions, idempotent,
|
||||
read-only. This is the v1.0 gate. Concerns:
|
||||
|
||||
1. **No assertion for F26 (scheduler actually deploys remotely)**:
|
||||
the plan says the UAT exercises "deploy full stack" but the
|
||||
signoff script's ~35 assertions are not enumerated. If the script
|
||||
doesn't assert "job ran on remote node, not local," the headline
|
||||
fix (F26) is not validated.
|
||||
2. **No assertion for F48 (ACL deny-by-default)**: the UAT must
|
||||
include a negative test (unauthorized identity denied). But the
|
||||
script is "read + non-mutating" — how does it test denial without
|
||||
attempting a mutation? It could check `acl.json` mode (0600) and
|
||||
the audit log for denial entries, but that's indirect.
|
||||
3. **`uat-smoke.sh` in CI**: the pure-CLI subset runs in `.coreci.yml`
|
||||
validate. This is good. But "version, acl file mode, doctor modes,
|
||||
no-password grep, metrics shape" is 5 assertions — the smoke test
|
||||
doesn't validate the core deployment model.
|
||||
|
||||
**Binding condition C-47**: P12 T4 (`uat-signoff.sh`) MUST include
|
||||
explicit assertions for: (a) job deployed to remote node (not local
|
||||
exec) — verify via `orca job list` showing node_id != localhost; (b)
|
||||
ACL deny-by-default — verify via audit log containing denial entries
|
||||
or a documented negative assertion; (c) seal/unseal round-trip; (d)
|
||||
OIDC health check (`doctor oidc`). The ~35 assertion count MUST
|
||||
include these 4 critical-path claims. The assertion list must be
|
||||
reviewable in `docs/uat.md` before the UAT is run.
|
||||
|
||||
## Axis 7 — Security
|
||||
|
||||
**Verdict**: PASS | **Confidence**: 0.86
|
||||
|
||||
The plan closes all critical/high/medium security findings (F26-F95).
|
||||
The 11 injection vectors (P02) are each small and independently
|
||||
testable. The ACL wiring (P04) is deny-by-default with bootstrap. The
|
||||
seal (P05) has Shamir recovery (C-35). Key zeroing (P05 T6) is
|
||||
defense-in-depth.
|
||||
|
||||
### New risks introduced by fixes
|
||||
|
||||
1. **P03 removes local exec path**: if the local fallback has a bug,
|
||||
`job run` breaks for all single-node users. Mitigation: C-44
|
||||
(fail-closed on SSH failure, test the fallback).
|
||||
2. **P04 ACL wiring**: deny-by-default could block legitimate traffic
|
||||
if the SVID extraction is wrong. Mitigation: C-45 (log-only mode
|
||||
first).
|
||||
3. **P05 seal**: if `orca cluster seal` is run accidentally, the
|
||||
cluster is sealed. Mitigation: Shamir shards are printed (operator
|
||||
must store them); `unseal` requires OIDC token or 3-of-5 shards.
|
||||
This is by design.
|
||||
4. **P06 Dex deploy**: introduces a new network service (Dex on
|
||||
Traefik). Mitigation: mTLS-only fallback (C-37), Traefik dynamic
|
||||
route is behind the orca CA.
|
||||
|
||||
No new risks are unmitigated. The 9 accepted residual risks are
|
||||
documented and reasonable.
|
||||
|
||||
## Axis 8 — Operability
|
||||
|
||||
**Verdict**: CONDITIONAL | **Confidence**: 0.72
|
||||
|
||||
### 3-host topology realism
|
||||
|
||||
The UAT topology (lead Ubuntu 22.04 + pve01 Proxmox VE 8/9 + worker01
|
||||
Ubuntu 22.04) is minimal and correct. It covers both node types
|
||||
(Proxmox + Linux) and migrate-between-hosts.
|
||||
|
||||
**Concern**: The UAT requires a real Proxmox VE host. This is not a
|
||||
CI-environment artifact — the operator must have a Proxmox server
|
||||
available. If the operator doesn't have one, the UAT cannot run. The
|
||||
plan does not address this prerequisite. `uat-smoke.sh` (CI subset)
|
||||
does NOT require Proxmox — it's pure-CLI — but the full
|
||||
`uat-signoff.sh` does.
|
||||
|
||||
**Binding condition C-48**: `docs/uat.md` (P12 T3) MUST document the
|
||||
hardware/host prerequisites explicitly: "You need a Proxmox VE 8/9
|
||||
host with SSH access and root credentials." If the operator cannot
|
||||
provision a Proxmox host, an alternative UAT path (3x Ubuntu hosts,
|
||||
`--type linux` only, Proxmox claims marked as "not exercised in this
|
||||
UAT") MUST be documented. The signoff script MUST report which claims
|
||||
were exercised vs. skipped, so a partial UAT is an honest signal, not
|
||||
a false pass.
|
||||
|
||||
### Operator ability to run the UAT
|
||||
|
||||
The UAT is operator-driven: `docs/uat.md` walks through the build,
|
||||
`uat-signoff.sh` asserts. The plan says "the operator runs it, pastes
|
||||
output back to the CI agent." This requires:
|
||||
|
||||
1. The operator has 3 hosts available (see C-48).
|
||||
2. The operator can follow `docs/uat.md` step-by-step (it must be
|
||||
complete and exact).
|
||||
3. `uat-signoff.sh` is truly idempotent and read-only (D-254).
|
||||
|
||||
These are achievable. The risk is that `docs/uat.md` is incomplete
|
||||
(missing a step) and the operator gets stuck. The plan's T3 says
|
||||
"step-by-step with exact commands" — this is the right intent.
|
||||
|
||||
## Axis 9 — Completeness
|
||||
|
||||
**Verdict**: CONDITIONAL | **Confidence**: 0.74
|
||||
|
||||
### Will this be the LAST round?
|
||||
|
||||
The research claims "this is the last hardening round" based on three
|
||||
deep sweeps. The 9 accepted residual risks are documented. But:
|
||||
|
||||
1. **UAT will surface new gaps**: the UAT signoff script exercises
|
||||
~35 claims against a real 3-host cluster. This is the first time
|
||||
the full stack is exercised end-to-end. It is virtually certain
|
||||
that the UAT will discover issues not found in code review (e.g.,
|
||||
systemd unit rendering on Proxmox, SSH-push to Ubuntu worker,
|
||||
Traefik route conflicts, drift event delivery across node types).
|
||||
The plan does not budget for a "UAT findings" follow-up.
|
||||
2. **P06 (Dex deploy) is untested in CI**: the plan's T5 is a
|
||||
"hermetic Dex+Traefik config render test" — this tests config
|
||||
rendering, not actual deployment. The first real Dex deploy will
|
||||
be in the UAT. If it fails, that's a round 3.
|
||||
3. **`--type linux` (P12 T1) is new code**: the first real Ubuntu
|
||||
worker onboarding will be in the UAT. If `internal/linux/bootstrap.go`
|
||||
has bugs, that's a round 3.
|
||||
|
||||
**Binding condition C-49**: The plan MUST acknowledge that v0.13 is
|
||||
"the last hardening round *before UAT*," not "the last hardening round
|
||||
*absolute*." The UAT will likely surface 3-7 issues requiring a
|
||||
follow-up patch round (v0.13.1 or a small v0.14). This is healthy and
|
||||
expected. The v1.0.0 tag is gated on UAT signoff passing — if UAT
|
||||
finds issues, v1.0.0 is deferred until they're fixed. The plan's
|
||||
"v1.0.0 NOT cut (deferred for UAT signoff)" in P13 is correct, but
|
||||
the narrative "this is the last hardening round" should be softened to
|
||||
"this is the last hardening round before UAT validation."
|
||||
|
||||
### What could force a round 3?
|
||||
|
||||
1. UAT discovers Dex deploy doesn't work on real Proxmox.
|
||||
2. UAT discovers `--type linux` bootstrap fails on real Ubuntu 22.04.
|
||||
3. UAT discovers scheduler bin-packing produces bad placements on
|
||||
heterogeneous nodes (Proxmox vs Linux worker).
|
||||
4. UAT discovers seal/unseal doesn't work with real OIDC tokens (not
|
||||
just test mocks).
|
||||
5. P03's local fallback has an edge case (e.g., job with `--target`
|
||||
but target node deregistered mid-flight).
|
||||
|
||||
Each of these is a single-fix patch, not a full round. The plan's
|
||||
per-phase tag structure (v0.12.x) supports patch releases.
|
||||
|
||||
## Summary Verdict
|
||||
|
||||
| Axis | Verdict | Confidence |
|
||||
|------|---------|-----------|
|
||||
| 1. Feasibility | PASS | 0.82 |
|
||||
| 2. Scope | PASS | 0.85 |
|
||||
| 3. Cost | PASS | 0.78 |
|
||||
| 4. Risk | CONDITIONAL | 0.80 |
|
||||
| 5. Dependencies | PASS | 0.84 |
|
||||
| 6. Testing | CONDITIONAL | 0.76 |
|
||||
| 7. Security | PASS | 0.86 |
|
||||
| 8. Operability | CONDITIONAL | 0.72 |
|
||||
| 9. Completeness | CONDITIONAL | 0.74 |
|
||||
|
||||
**Overall**: **CONDITIONAL PROCEED** | **Confidence**: 0.82
|
||||
|
||||
The plan is evidence-accurate, well-decomposed, and addresses real
|
||||
gaps. The binding conditions (C-44..C-49) are targeted fixes, not
|
||||
fundamental rework. No axis FAILs. The plan proceeds once the 6
|
||||
binding conditions are incorporated.
|
||||
|
||||
## Binding decisions (G-255..G-261)
|
||||
|
||||
| ID | Decision | Rationale | Confidence | Alternatives |
|
||||
|----|----------|-----------|------------|--------------|
|
||||
| G-255 | Proceed with v0.12 governance gap: P13 marks REQ-130..148 AND REQ-149..163 Complete; v0.12 stays COMPLETE retroactively | v0.12 code was shipped but not wired; v0.13 wires it; revoking COMPLETE destabilizes history without changing code; C-43 makes consistency enforceable | 0.90 | Revoke v0.12 COMPLETE (destabilizing); escalate (unnecessary at full autonomy) |
|
||||
| G-256 | P03 fail-closed on SSH failure (C-44) | Silent local fallback when SSH fails is a data-integrity risk; local fallback only when len(nodes)==0 | 0.88 | Silent fallback (unsafe); no fallback (breaks single-node) |
|
||||
| G-257 | P04 log-only mode for first run (C-45) | C-40 specifies staged rollout but P04 task list omits it; deny-by-default lockout is catastrophic | 0.85 | Enforce immediately (lockout risk); split P04 into P04a/P04b (acceptable alternative) |
|
||||
| G-258 | P12 declares dependency on P05+P06 (C-46) | UAT exercises seal/unseal and OIDC flow, which require P05/P06; undeclared dependency hides slip risk | 0.82 | Leave undeclared (C-42 honest signal covers it, but dependency should be explicit) |
|
||||
| G-259 | P12 signoff script includes 4 critical-path assertions (C-47) | F26 (remote deploy), F48 (ACL deny), seal round-trip, OIDC health are the headline claims; without asserting them the UAT is theater | 0.84 | Trust the ~35 count (insufficient); add more later (gate must be complete at ship) |
|
||||
| G-260 | P12 docs/uat.md documents Proxmox prerequisite + alternative path (C-48) | UAT requires real Proxmox host; if operator lacks one, partial UAT must be honest signal | 0.78 | Assume operator has Proxmox (may not); skip Proxmox claims silently (dishonest) |
|
||||
| G-261 | v0.13 is "last round before UAT," not "last round absolute" (C-49) | UAT will surface issues; narrative should reflect this; v1.0.0 deferred until UAT passes is correct | 0.80 | Claim "last round absolute" (likely false); pre-commit to v0.14 (premature) |
|
||||
|
||||
## Binding conditions (C-44..C-49)
|
||||
|
||||
| ID | Condition | Phase | Gates |
|
||||
|----|-----------|-------|-------|
|
||||
| C-44 | P03 MUST fail-closed when scheduler selects a node but SSH-push fails (return error, no silent local fallback). Local fallback only when len(registeredNodes)==0. Test case mandatory. | P03 | P04 ship |
|
||||
| C-45 | P04 MUST implement log-only/dry-run mode as default for first invocation after ACL wiring. Enforce mode enabled after bootstrap ACL verified. Add to P04 task list + must-haves. | P04 | P05 ship |
|
||||
| C-46 | P12 dependency table MUST include P05 (seal) and P06 (auth init-idp) in addition to P03 and P04. | P12 | P12 plan accuracy |
|
||||
| C-47 | P12 uat-signoff.sh MUST include explicit assertions for: (a) job deployed to remote node (node_id != localhost), (b) ACL deny-by-default (audit log denial entries or documented negative assertion), (c) seal/unseal round-trip, (d) OIDC health check. Assertion list reviewable in docs/uat.md. | P12 | v1.0.0 gate |
|
||||
| C-48 | P12 docs/uat.md MUST document hardware/host prerequisites (Proxmox VE 8/9 host required). Alternative UAT path (3x Ubuntu, --type linux only, Proxmox claims skipped) MUST be documented. Signoff script reports exercised vs. skipped claims. | P12 | UAT executability |
|
||||
| C-49 | Plan narrative MUST soften "last hardening round" to "last hardening round before UAT validation." UAT will likely surface 3-7 issues requiring patch release. v1.0.0 deferred until UAT passes. | P0/P13 | Expectation setting |
|
||||
|
||||
## Escalations
|
||||
|
||||
None. All axes resolved at confidence >= 0.72. The question tool
|
||||
infrastructure failed during the interactive grill (stack overflow on
|
||||
every invocation); given `autonomy.level=full` and
|
||||
`workflow.no_hitl=true`, the grill proceeded on evidence alone. All
|
||||
binding decisions are evidence-based and within the agent's autonomy
|
||||
threshold (0.60).
|
||||
|
||||
## What the auditor would flag
|
||||
|
||||
1. **v0.12 COMPLETE with 19 pending REQs** — documentation governance
|
||||
failure, now acknowledged and resolved (G-255).
|
||||
2. **P03 under-estimated as "wiring"** — it's a behavioral rewrite of
|
||||
`job run`. Schedule accordingly.
|
||||
3. **P04 staged rollout missing from task list** — C-40 describes it,
|
||||
P04 tasks omit it (C-45).
|
||||
4. **P12 dependencies incomplete** — P05/P06 not listed (C-46).
|
||||
5. **UAT signoff assertions not enumerated** — ~35 count without a
|
||||
reviewable list (C-47).
|
||||
6. **"Last round" narrative overclaims** — UAT will find issues
|
||||
(C-49).
|
||||
|
||||
## What the project is not doing that it should
|
||||
|
||||
1. **No end-to-end integration test in CI** — the UAT is the first
|
||||
E2E test. The `uat-smoke.sh` is CLI-only. A CI E2E test (mock SSH
|
||||
to localhost containers) would catch P03/P04 integration issues
|
||||
before UAT. This is deferred to v1.x and is acceptable.
|
||||
2. **No performance testing** — the plan doesn't address scheduler
|
||||
performance on large node counts. Acceptable for a 3-host UAT;
|
||||
relevant for v1.x.
|
||||
3. **No chaos testing** — SSH failure mid-deploy, node deregistration
|
||||
mid-flight, etc. C-44 covers the fail-closed case; broader chaos
|
||||
testing is v1.x.
|
||||
|
||||
## Simplest version delivering 80% of value
|
||||
|
||||
P01 (toolchain) + P02 (injection) + P03 (scheduler) + P04 (ACL) +
|
||||
P12 (UAT) = 5 phases. This makes the deployment model functional,
|
||||
closes the RCE vectors, wires zero-trust, and delivers the UAT gate.
|
||||
The remaining 9 phases (seal, IdP, concurrency, transport, migration,
|
||||
metrics, docs, linux type) each close real gaps but could defer to
|
||||
v1.0.1 patches. The operator chose comprehensiveness (D-250) —
|
||||
justified to avoid a round 3, but the 5-phase core is the minimum
|
||||
viable path.
|
||||
|
||||
## What must be true for success in 90 days
|
||||
|
||||
1. P03 ships with fail-closed SSH handling and local fallback (C-44).
|
||||
2. P04 ships with log-only mode and bootstrap ACL (C-45).
|
||||
3. P12 ships with enumerated assertions covering the 4 critical paths
|
||||
(C-47).
|
||||
4. The operator has a 3-host environment (or the alternative UAT path
|
||||
is documented, C-48).
|
||||
5. The UAT signoff script runs and either passes (-> v1.0.0) or fails
|
||||
honestly (-> patch round).
|
||||
|
||||
All five are achievable. The plan proceeds.
|
||||
Reference in New Issue
Block a user