feat(apply): reconcile app-owned vars in the declarative engine
Extends the Phase-1 apply engine to manage app `vars` declaratively, alongside scripts/routes/triggers/secrets. The `Bundle` gains a `vars` map (key → JSON value; values are non-secret, so they live inline, unlike secret names). `diff_vars` is value-sensitive: a changed value is an Update, a live var the manifest dropped is a Delete (applied only under `--prune` — vars are prunable config, unlike never-pruned secrets). Writes go through `set_app_var_tx`/`delete_app_var_tx` inside the apply transaction (mirroring `PostgresVarsRepo::set` for `VarOwner::App`, scope `*`), so they commit atomically with the rest of the apply and roll back together on failure. `CurrentState` loads the app's OWN scope-`*`, non-tombstone vars (inherited group vars and tombstones are out of scope for the manifest); `state_token` folds them in so the bound-plan check catches an out-of-band `pic vars set` between plan and apply. Keys are validated against the same kebab rule as the vars admin API, and the apply handler now requires `AppVarsWrite` when vars are touched or `--prune` is set. Scope: app-owned vars at scope `*` (an app *is* an environment). Group vars via manifest and tombstone-via-manifest wait for the nested-manifest model. Unit tests cover the create/update/noop/delete diff and the state-token value sensitivity. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -81,6 +81,15 @@ async fn apply_handler(
|
||||
.await
|
||||
.map_err(map_authz)?;
|
||||
}
|
||||
if req.prune || !req.bundle.vars.is_empty() {
|
||||
require(
|
||||
svc.authz.as_ref(),
|
||||
&principal,
|
||||
Capability::AppVarsWrite(app_id),
|
||||
)
|
||||
.await
|
||||
.map_err(map_authz)?;
|
||||
}
|
||||
// Email triggers resolve and decrypt a stored secret by name server-side,
|
||||
// which the secrets API guards with `AppSecretsRead`. Require it here too
|
||||
// so apply can't bind a secret a principal couldn't otherwise read — the
|
||||
|
||||
Reference in New Issue
Block a user