feat(cli): §3 M3 — per-env approval gating ([project.environments])

A `[project.environments]` block maps an env name to `{ confirm = bool }`
(`ManifestProject.environments`, client-side only — `skip_serializing`).
`pic apply --env <e>` is refused before any request when `<e>` is
confirm-required unless it is explicitly `--approve <e>`d; a blanket `--yes`
does NOT cover a gated env (§4.2 "CI must opt in per environment"); an unlisted
or `confirm = false` env applies freely. `require_env_approval` gates both the
single (`run`) and tree (`run_tree`) apply paths; `--approve <env>` is a
repeatable flag. Per-env value overlays (`picloud.<env>.toml`) already merge
client-side, so this is the confirm-policy gate only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-07-07 20:28:28 +02:00
parent b8eced9d91
commit 62710b5d81
3 changed files with 53 additions and 1 deletions

View File

@@ -269,6 +269,10 @@ struct ApplyArgs {
/// divergence and reconcile content in place (no reparent).
#[arg(long)]
adopt_server_structure: bool,
/// §3 M3: approve applying to a confirm-required environment
/// (`[project.environments]`). Repeatable; each must match the `--env`.
#[arg(long = "approve")]
approve: Vec<String>,
}
#[derive(Args)]
@@ -1455,6 +1459,7 @@ async fn main() -> ExitCode {
args.force,
args.takeover,
structure_mode,
&args.approve,
args.env.as_deref(),
mode,
)
@@ -1468,6 +1473,7 @@ async fn main() -> ExitCode {
args.yes,
args.force,
args.takeover,
&args.approve,
mode,
)
.await