refactor(apply): split reconcile_group_structure_tx create/reparent branches
Some checks failed
CI / Rust — fmt, clippy, test (push) Failing after 19m24s
CI / Dashboard — check (push) Successful in 9m46s

Review #4 (LOW, cleanup). `reconcile_group_structure_tx` carried a
`#[allow(clippy::too_many_lines)]` over a ~145-line body doing create +
reparent + attach/RBAC/lock in one loop. Extract the create branch
(`create_group_node_tx`) and the divergence-resolution branch
(`reparent_diverged_group_tx`) into helper methods, threading the shared
attach-ceiling / principal / mode context through a small `ReconcileCtx` — the
loop is now thin enough to drop the allow. Also improve the child-before-parent
error in `resolve_declared_parent` to hint that group nodes must be ordered
parents-first (only a hand-rolled bundle hits it; the CLI already sorts).

No behavior change. Documents the Tier-1 review follow-ups in the design doc.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-07-07 21:49:18 +02:00
parent 6ec034fb1d
commit 87292fc4e9
2 changed files with 174 additions and 91 deletions

View File

@@ -838,6 +838,20 @@ environment"); an unlisted / `confirm = false` env applies freely. `require_env_
**§6/§3 group-tree Tier 1 (M1 create · M2 divergence/reparent · M3 per-env approval) is COMPLETE.**
**Review follow-ups (post-Tier-1 hardening).** A code review of the Tier-1 branch surfaced four fixes: (1)
M1's `authz_tree` skip for a to-create group opened a race window (a group created by a racer between the
API-layer authz check and the in-tx reconcile could have its content written unauthorized) — closed by an
in-tx content-write re-check in `apply_tree` for every group NOT structurally created/reparented by that apply
(`require_group_node_writes` moved from `apply_api` onto `ApplyService`; a group WE create is covered by
create-RBAC and its uncommitted row is invisible to the authz cascade, so it's skipped). (2) The M3 approval
gate could silently fail open — now `EnvPolicy.confirm` is a REQUIRED field (an empty `prod = {}` is a load
error, not a silent no-gate), a single-file `pic apply --file <leaf>` discovers the governing `[project]` by
walking up the directory tree, and a non-root `[project].environments` is dropped with an explicit warning.
(3) Divergence detection is unified — the plan-path `divergence_preview` reuses the already-loaded group rows
(no per-node re-fetch) and compares parent slugs case-insensitively so it can't disagree with the apply path's
id-based check. (4) `reconcile_group_structure_tx`'s create/reparent branches are extracted into helpers.
Pinned by new cases in `tests/group_create.rs` + `tests/env_approval.rs`.
---
## 8. Diagrams