@intentius/chant-lexicon-terraform 0.62.0 → 0.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -56,11 +56,21 @@
56
56
  *
57
57
  * A gate is a fact on the gate ledger, not a wait (#2119). Reaching one,
58
58
  * `chant run` consults the ledger (`packages/core/src/op/gate.ts`): a
59
- * resolution newer than the gate's newest pending fact lets the run walk
60
- * through, and anything else records the pending fact and ends the run with
61
- * status `gated` and exit 3. `chant approve <op> <gate>` writes the
62
- * resolution, and the next run reads it. `gate: "never"` drops the Gate phase
63
- * entirely, so a run never stops.
59
+ * resolution recorded for this run's own plan lets the run walk through, and
60
+ * anything else records the pending fact and ends the run with status `gated`
61
+ * and exit 3. `chant approve <op> <gate>` writes the resolution, and the next
62
+ * run reads it. `gate: "never"` drops the Gate phase entirely, so a run never
63
+ * stops.
64
+ *
65
+ * **The gate binds the plan** (#2300). The Plan step publishes
66
+ * `planDigest` — its `terraform show -json` change set, hashed — and the Gate
67
+ * step references it, so the resolution names the plan it approves. That
68
+ * closes the window the exit-3 refusal above does not: exit 3 compares the
69
+ * Apply step's fresh plan against the *file* it was handed inside one run,
70
+ * and this compares a later run's fresh plan against what a human actually
71
+ * approved. INTENTIUS/choudoufu#1026 measured the gap by approving, renaming
72
+ * a resource, and re-running: the second run applied without complaint. It
73
+ * now stops, naming the approved digest and the planned one.
64
74
  *
65
75
  * @example
66
76
  * ```typescript
@@ -1 +1 @@
1
- {"version":3,"file":"terraform-apply-op.d.ts","sourceRoot":"","sources":["../../src/composites/terraform-apply-op.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsEG;AAEH,OAAO,EAA6B,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAW5E;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElE,MAAM,WAAW,sBAAsB;IACrC,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,+GAA+G;IAC/G,IAAI,EAAE,MAAM,CAAC;IACb,0GAA0G;IAC1G,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qGAAqG;IACrG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED,MAAM,WAAW,yBAAyB;IACxC,mEAAmE;IACnE,EAAE,EAAE,YAAY,CAAC,OAAO,UAAU,CAAC,CAAC;CACrC;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,yBAAyB,CA2G1F"}
1
+ {"version":3,"file":"terraform-apply-op.d.ts","sourceRoot":"","sources":["../../src/composites/terraform-apply-op.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AAEH,OAAO,EAA6B,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAW5E;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElE,MAAM,WAAW,sBAAsB;IACrC,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,+GAA+G;IAC/G,IAAI,EAAE,MAAM,CAAC;IACb,0GAA0G;IAC1G,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qGAAqG;IACrG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED,MAAM,WAAW,yBAAyB;IACxC,mEAAmE;IACnE,EAAE,EAAE,YAAY,CAAC,OAAO,UAAU,CAAC,CAAC;CACrC;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,yBAAyB,CAgH1F"}
@@ -1 +1 @@
1
- {"version":3,"file":"terraform-watch-op.d.ts","sourceRoot":"","sources":["../../src/composites/terraform-watch-op.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6GG;AAEH,OAAO,EAAa,UAAU,EAAqB,MAAM,qBAAqB,CAAC;AAS/E;;;;;;;;;;GAUG;AACH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,cAAc,CAAC;AAEnF,MAAM,WAAW,sBAAsB;IACrC,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,+GAA+G;IAC/G,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC;;;;;;;;;;;;;;;;OAgBG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,yBAAyB;IACxC,4DAA4D;IAC5D,EAAE,EAAE,YAAY,CAAC,OAAO,UAAU,CAAC,CAAC;CACrC;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,yBAAyB,CA8G1F"}
1
+ {"version":3,"file":"terraform-watch-op.d.ts","sourceRoot":"","sources":["../../src/composites/terraform-watch-op.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6GG;AAEH,OAAO,EAAa,UAAU,EAAqB,MAAM,qBAAqB,CAAC;AAS/E;;;;;;;;;;GAUG;AACH,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,cAAc,CAAC;AAEnF,MAAM,WAAW,sBAAsB;IACrC,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,+GAA+G;IAC/G,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC;;;;;;;;;;;;;;;;OAgBG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,yBAAyB;IACxC,4DAA4D;IAC5D,EAAE,EAAE,YAAY,CAAC,OAAO,UAAU,CAAC,CAAC;CACrC;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,yBAAyB,CAwH1F"}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "algorithm": "sha256",
3
3
  "artifacts": {
4
- "manifest.json": "68a63fa7e36966979057c179df4393ea7af5ebaa3d4c4126b972fdb260a8c3d4",
4
+ "manifest.json": "088433e81a7727eff653974246daa38fd4bd226f7eebfcb1bad01bba65a0f77e",
5
5
  "meta.json": "ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356",
6
6
  "types/index.d.ts": "022927e6a7b351cc4cf52d5f973f60ccd140e5810e17b32fb8868965aa1db161",
7
7
  "rules/plan-before-apply.ts": "31b1b3176799fd365b2583fe3947edd187c2a863e3dc0094ed9e91ece2464c99",
@@ -37,5 +37,5 @@
37
37
  "rules/tf028.ts": "81ef95659c40ad1774c83e663473ed769143d894a4ba0517c3defa31f00ba723",
38
38
  "skills/chant-terraform.md": "d9ca7b7c28aed0038ce775a3491150298492eed2858fd3651ed9bfca0e577ae8"
39
39
  },
40
- "composite": "bce1d6bc7353146056d897096ba518203b0b588cb4b4546b420e6d93169b77c4"
40
+ "composite": "0f2f07cf1272dabb45bddb3a6a6c99b44cdbbcebb426ea2c94ce3c2c41db8abb"
41
41
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "terraform",
3
- "version": "0.62.0",
3
+ "version": "0.64.0",
4
4
  "chantVersion": ">=0.1.0",
5
5
  "namespace": "Terraform"
6
6
  }
@@ -203,6 +203,56 @@ export interface PlanChangeCounts {
203
203
  /** Resources to destroy. This is the number an approval gate exists for. */
204
204
  destroys: number;
205
205
  }
206
+ /**
207
+ * One resource's proposed change, as a plan digest sees it (#2300) — the
208
+ * projection of a `terraform show -json` `resource_changes` entry that
209
+ * survives into {@link terraformPlanDigest}.
210
+ */
211
+ export interface TerraformPlannedChange {
212
+ address: unknown;
213
+ mode: unknown;
214
+ type: unknown;
215
+ name: unknown;
216
+ index: unknown;
217
+ provider_name: unknown;
218
+ deposed: unknown;
219
+ actions: unknown;
220
+ before: unknown;
221
+ after: unknown;
222
+ after_unknown: unknown;
223
+ replace_paths: unknown;
224
+ importing: unknown;
225
+ }
226
+ /**
227
+ * The change set a `terraform show -json` plan describes, canonicalised
228
+ * (#2300): every proposed change, at its address, with the values that would
229
+ * be written, sorted so two renderings of the same plan project identically.
230
+ *
231
+ * Everything else in the document is dropped, and the drops are the point —
232
+ * see `packages/core/src/lifecycle/plan-digest.ts` for the general rule. Here
233
+ * that means `timestamp` and `terraform_version` (when the plan was taken and
234
+ * by which binary), `format_version` (how it was rendered), `prior_state` and
235
+ * `planned_values` (restatements of the same change set from another angle),
236
+ * `configuration` (the source that produced it, which can be refactored
237
+ * without changing a single proposed action) and `checks` / `relevant_
238
+ * attributes` (diagnostics about the plan, not the plan). What is left is
239
+ * what applying it would do.
240
+ */
241
+ export declare function terraformPlanChangeSet(planJson: unknown): {
242
+ resourceChanges: TerraformPlannedChange[];
243
+ outputChanges: unknown;
244
+ };
245
+ /**
246
+ * The identity of a terraform plan (#2300): {@link terraformPlanChangeSet}
247
+ * hashed. This is what a `TerraformApplyOp` gate binds its approval to, and
248
+ * what a later run recomputes and compares.
249
+ *
250
+ * Taken over the `show -json` rendering rather than the plan file's bytes on
251
+ * purpose: the file is an opaque, version-stamped archive, and two runs of
252
+ * `plan -out` over an unchanged root produce different bytes. The rendering
253
+ * is the same plan both times.
254
+ */
255
+ export declare function terraformPlanDigest(planJson: unknown): string;
206
256
  /** What {@link terraformPlan} resolved. Carries the plan itself, so no later step re-plans. */
207
257
  export interface TerraformPlanResult extends PlanChangeCounts {
208
258
  /** `true` when terraform reported exit 2 under `-detailed-exitcode`: the plan proposes changes. */
@@ -215,6 +265,13 @@ export interface TerraformPlanResult extends PlanChangeCounts {
215
265
  json: unknown;
216
266
  /** `terraform show -no-color <planFile>` — the human-readable plan. */
217
267
  text: string;
268
+ /**
269
+ * This plan's identity (#2300) — {@link terraformPlanDigest} over
270
+ * {@link TerraformPlanResult.json}. Hand it to a gate step's `plan` so the
271
+ * approval binds to this plan and not to the next run: `gate(name, { plan:
272
+ * plan.out.planDigest })`.
273
+ */
274
+ planDigest: string;
218
275
  }
219
276
  /**
220
277
  * Why a live apply refused the approval artifact it was handed. Both are
@@ -1 +1 @@
1
- {"version":3,"file":"terraform.d.ts","sourceRoot":"","sources":["../../../src/op/activities/terraform.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"terraform.d.ts","sourceRoot":"","sources":["../../../src/op/activities/terraform.ts"],"names":[],"mappings":"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"}
@@ -49,6 +49,7 @@ export declare const terraformPlanContract: import("@intentius/chant/op").Activi
49
49
  dir: string;
50
50
  json: unknown;
51
51
  text: string;
52
+ planDigest: string;
52
53
  adds: number;
53
54
  changes: number;
54
55
  destroys: number;
@@ -1 +1 @@
1
- {"version":3,"file":"activity-contracts.d.ts","sourceRoot":"","sources":["../../src/op/activity-contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AA+BH,eAAO,MAAM,qBAAqB;;;;;;;;EASjC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;EAgBjC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;EAWlC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;EAYjC,CAAC;AAEF,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;EAwBrC,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;;;;;;;EASnC,CAAC;AAEF,eAAO,MAAM,0BAA0B;;;;;;;;EAKtC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;EAgBlC,CAAC"}
1
+ {"version":3,"file":"activity-contracts.d.ts","sourceRoot":"","sources":["../../src/op/activity-contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AA+BH,eAAO,MAAM,qBAAqB;;;;;;;;EASjC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;EAiBjC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;EAWlC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;EAYjC,CAAC;AAEF,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;EAwBrC,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;;;;;;;EASnC,CAAC;AAEF,eAAO,MAAM,0BAA0B;;;;;;;;EAKtC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;EAgBlC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant-lexicon-terraform",
3
- "version": "0.62.0",
3
+ "version": "0.64.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src/",
@@ -56,7 +56,7 @@
56
56
  },
57
57
  "peerDependencies": {
58
58
  "zod": "^4.3.6",
59
- "@intentius/chant": "^0.62.0",
59
+ "@intentius/chant": "^0.64.0",
60
60
  "typescript": "^5.9.3"
61
61
  },
62
62
  "description": "terraform lexicon for chant, existing Terraform root modules as declarable entities",
@@ -351,3 +351,35 @@ describe("TerraformApplyOp on a live root (#2106 follow-up)", () => {
351
351
  expect(fns).toEqual(["terraformInit", "terraformPlan", "terraformApply"]);
352
352
  });
353
353
  });
354
+
355
+ /**
356
+ * #2300 — the gate binds the plan. The Plan step publishes `planDigest` and
357
+ * the Gate step references it, so the resolution `chant approve` writes names
358
+ * the plan it approves. Before this, INTENTIUS/choudoufu#1026 approved,
359
+ * renamed a resource in the root, re-ran, and watched the apply proceed.
360
+ */
361
+ describe("TerraformApplyOp binds the gate to the plan (#2300)", () => {
362
+ test("the gate step references the Plan step's own digest", () => {
363
+ const op = props({ name: "app-apply", root: "app" });
364
+ const gate = op.phases.find((p) => p.name === "Gate")!.steps.find(isGate)!;
365
+ expect(isStepOutputRef(gate.plan)).toBe(true);
366
+ expect(gate.plan).toMatchObject({ step: "plan", path: "planDigest" });
367
+ });
368
+
369
+ test("a run records the plan on the pending fact it leaves behind", async () => {
370
+ const op = props({ name: "prod-apply", root: "app" });
371
+ const digest = `sha256:${"c".repeat(64)}`;
372
+ const activities = new Map<string, (args: Record<string, unknown>) => Promise<unknown>>([
373
+ ["terraformInit", async () => ({})],
374
+ ["terraformPlan", async () => ({ planFile: "chant.tfplan", planDigest: digest })],
375
+ ["terraformShow", async () => ({})],
376
+ ["terraformApply", async () => ({})],
377
+ ]);
378
+ const gates = memoryGateLedgerPort();
379
+ const result = await runOpLocally(op, activities, {}, undefined, { gates, now: "2026-09-09T12:00:00.000Z" });
380
+
381
+ expect(result.status).toBe("gated");
382
+ expect(result.gate?.planDigest).toBe(digest);
383
+ expect(gates.appended[0].planDigest).toBe(digest);
384
+ });
385
+ });
@@ -56,11 +56,21 @@
56
56
  *
57
57
  * A gate is a fact on the gate ledger, not a wait (#2119). Reaching one,
58
58
  * `chant run` consults the ledger (`packages/core/src/op/gate.ts`): a
59
- * resolution newer than the gate's newest pending fact lets the run walk
60
- * through, and anything else records the pending fact and ends the run with
61
- * status `gated` and exit 3. `chant approve <op> <gate>` writes the
62
- * resolution, and the next run reads it. `gate: "never"` drops the Gate phase
63
- * entirely, so a run never stops.
59
+ * resolution recorded for this run's own plan lets the run walk through, and
60
+ * anything else records the pending fact and ends the run with status `gated`
61
+ * and exit 3. `chant approve <op> <gate>` writes the resolution, and the next
62
+ * run reads it. `gate: "never"` drops the Gate phase entirely, so a run never
63
+ * stops.
64
+ *
65
+ * **The gate binds the plan** (#2300). The Plan step publishes
66
+ * `planDigest` — its `terraform show -json` change set, hashed — and the Gate
67
+ * step references it, so the resolution names the plan it approves. That
68
+ * closes the window the exit-3 refusal above does not: exit 3 compares the
69
+ * Apply step's fresh plan against the *file* it was handed inside one run,
70
+ * and this compares a later run's fresh plan against what a human actually
71
+ * approved. INTENTIUS/choudoufu#1026 measured the gap by approving, renaming
72
+ * a resource, and re-running: the second run applied without complaint. It
73
+ * now stops, naming the approved digest and the planned one.
64
74
  *
65
75
  * @example
66
76
  * ```typescript
@@ -226,6 +236,11 @@ export function TerraformApplyOp(config: TerraformApplyOpConfig): TerraformApply
226
236
  show,
227
237
  gate(config.gateName ?? config.signalName ?? `approve-${config.name}`, {
228
238
  ...(config.gateTimeout ? { timeout: config.gateTimeout } : {}),
239
+ // #2300: the approval is for this plan, not for the next run. The
240
+ // Plan step's digest rides onto the pending fact, `chant approve`
241
+ // copies it onto the resolution, and a later run whose fresh plan
242
+ // digests differently is refused with both digests named.
243
+ plan: plan.out.planDigest,
229
244
  description:
230
245
  config.gateDescription ??
231
246
  `Approve terraform apply of ${live ? "live " : ""}root "${config.root}" (gate: ${gateMode}). ` +
@@ -103,6 +103,20 @@ describe("TerraformWatchOp finding modes (#2087)", () => {
103
103
  expect(step.outcomeAttribute).toEqual({ name: "Comment", from: "commentUrl" });
104
104
  });
105
105
 
106
+ test("the finding step names its Op, so two watches over one root cannot collide (#2319)", () => {
107
+ // The pairing #2319 names: a stock drift watch and a `live: true` one over
108
+ // the same root is what this composite is built for, and both pass the
109
+ // root as `env`. Before #2319 that was the whole marker, so each nightly
110
+ // run PATCHed the title and body of the other Op's issue.
111
+ expect(findingStep("issue").args?.op).toBe("app-watch");
112
+ const stock = props({ name: "app-drift", root: "app", findingMode: "issue" });
113
+ const paired = props({ name: "app-drift-nightly", root: "app", findingMode: "issue" });
114
+ const a = stock.phases[2].steps[0] as ActivityStep;
115
+ const b = paired.phases[2].steps[0] as ActivityStep;
116
+ expect(a.args?.env).toBe(b.args?.env);
117
+ expect(a.args?.op).not.toBe(b.args?.op);
118
+ });
119
+
106
120
  test("the finding step derives no plan of its own", () => {
107
121
  // `entries: []` is what stops reconcilePr shelling to `chant lifecycle
108
122
  // plan --json`: the finding is already written by the time it runs.
@@ -269,11 +269,21 @@ export function TerraformWatchOp(config: TerraformWatchOpConfig): TerraformWatch
269
269
  // terraform that is the root, which with its workspace is the deployment
270
270
  // target. `entries: []` and `body` together mean the activity opens what
271
271
  // it is given rather than running `chant lifecycle plan` to find out.
272
+ //
273
+ // `op` is what keeps the sticky issue this Op's own (#2319). The root
274
+ // alone does not: a stock drift watch and a `live: true` watch over one
275
+ // root is the pairing this composite is built for, and before #2319 both
276
+ // resolved to one env-keyed marker, so each nightly run rewrote the
277
+ // other's issue title and body. Two Ops in a project do not share a raw
278
+ // name — it names the Op's output directory — though the marker carries
279
+ // the slug rather than the raw name, and the slug is not injective; see
280
+ // `issueMarker` for what that leaves and why it is accepted.
272
281
  const report: ActivityStep = {
273
282
  kind: "activity",
274
283
  fn: "reconcilePr",
275
284
  args: {
276
285
  env: config.root,
286
+ op: config.name,
277
287
  mode: findingMode,
278
288
  entries: [],
279
289
  title: config.title ?? `Terraform drift in root "${config.root}"`,
@@ -29,6 +29,8 @@ import {
29
29
  terraformEnvironment,
30
30
  terraformBinary,
31
31
  countPlanChanges,
32
+ terraformPlanChangeSet,
33
+ terraformPlanDigest,
32
34
  quoteArg,
33
35
  DEFAULT_PLAN_FILE,
34
36
  } from "./terraform";
@@ -253,6 +255,79 @@ describe("countPlanChanges (#2086)", () => {
253
255
  });
254
256
  });
255
257
 
258
+ /**
259
+ * #2300. The digest is what a `TerraformApplyOp` gate binds its approval to,
260
+ * so what it covers and what it ignores is the contract an approver is
261
+ * relying on. Taken over the `show -json` rendering rather than the plan
262
+ * file's bytes: two `plan -out` runs over an unchanged root write different
263
+ * bytes and the same plan.
264
+ */
265
+ describe("terraformPlanDigest (#2300)", () => {
266
+ test("the same change set digests the same across renderings that differ only in noise", () => {
267
+ const a = JSON.parse(PLAN_JSON) as Record<string, unknown>;
268
+ const b = {
269
+ ...JSON.parse(PLAN_JSON) as Record<string, unknown>,
270
+ format_version: "1.3",
271
+ terraform_version: "1.9.0",
272
+ timestamp: "2026-09-09T12:00:00Z",
273
+ prior_state: { anything: true },
274
+ configuration: { root_module: { resources: ["moved around"] } },
275
+ checks: [],
276
+ };
277
+ expect(terraformPlanDigest(b)).toBe(terraformPlanDigest(a));
278
+ });
279
+
280
+ test("a renamed resource changes it — the exact edit choudoufu#1026 made between approve and re-run", () => {
281
+ const before = JSON.parse(PLAN_JSON) as { resource_changes: { address: string }[] };
282
+ const after = JSON.parse(PLAN_JSON) as { resource_changes: { address: string }[] };
283
+ after.resource_changes[0].address = "null_resource.renamed";
284
+ expect(terraformPlanDigest(after)).not.toBe(terraformPlanDigest(before));
285
+ });
286
+
287
+ test("a changed planned value changes it, even at the same addresses and actions", () => {
288
+ const before = { resource_changes: [{ address: "null_resource.a", change: { actions: ["create"], after: { triggers: { v: "1" } } } }] };
289
+ const after = { resource_changes: [{ address: "null_resource.a", change: { actions: ["create"], after: { triggers: { v: "2" } } } }] };
290
+ expect(terraformPlanDigest(after)).not.toBe(terraformPlanDigest(before));
291
+ });
292
+
293
+ test("a changed action changes it — create is not destroy", () => {
294
+ const create = { resource_changes: [{ address: "null_resource.a", change: { actions: ["create"] } }] };
295
+ const destroy = { resource_changes: [{ address: "null_resource.a", change: { actions: ["delete"] } }] };
296
+ expect(terraformPlanDigest(destroy)).not.toBe(terraformPlanDigest(create));
297
+ });
298
+
299
+ test("output changes are part of the plan", () => {
300
+ const withOutput = { resource_changes: [], output_changes: { url: { actions: ["create"], after: "https://a" } } };
301
+ const withOther = { resource_changes: [], output_changes: { url: { actions: ["create"], after: "https://b" } } };
302
+ expect(terraformPlanDigest(withOther)).not.toBe(terraformPlanDigest(withOutput));
303
+ });
304
+
305
+ test("the emitter's iteration order does not change the answer", () => {
306
+ const one = { resource_changes: [{ address: "b", change: { actions: ["create"] } }, { address: "a", change: { actions: ["create"] } }] };
307
+ const two = { resource_changes: [{ address: "a", change: { actions: ["create"] } }, { address: "b", change: { actions: ["create"] } }] };
308
+ expect(terraformPlanDigest(one)).toBe(terraformPlanDigest(two));
309
+ });
310
+
311
+ test("a plan with no resource_changes still digests, rather than throwing", () => {
312
+ expect(terraformPlanDigest({ format_version: "1.2" })).toMatch(/^sha256:[0-9a-f]{64}$/);
313
+ expect(terraformPlanDigest(null)).toMatch(/^sha256:[0-9a-f]{64}$/);
314
+ });
315
+
316
+ test("the change set keeps the fields an approver reads and drops the rest", () => {
317
+ const { resourceChanges } = terraformPlanChangeSet({
318
+ timestamp: "2026-09-09T12:00:00Z",
319
+ resource_changes: [{
320
+ address: "null_resource.a", mode: "managed", type: "null_resource", name: "a",
321
+ provider_name: "registry.terraform.io/hashicorp/null",
322
+ change: { actions: ["create"], before: null, after: { x: 1 }, after_unknown: {}, before_sensitive: false },
323
+ }],
324
+ });
325
+ expect(resourceChanges[0]).toMatchObject({ address: "null_resource.a", actions: ["create"], after: { x: 1 } });
326
+ expect(resourceChanges[0]).not.toHaveProperty("before_sensitive");
327
+ expect(resourceChanges[0]).not.toHaveProperty("change");
328
+ });
329
+ });
330
+
256
331
  // ── Root resolution ─────────────────────────────────────────────────────────
257
332
 
258
333
  describe("root resolution against terraform.roots (#2086)", () => {
@@ -323,6 +398,16 @@ describe("terraformPlan — the -detailed-exitcode mapping (#2086)", () => {
323
398
  ]);
324
399
  });
325
400
 
401
+ // #2300 — the Plan phase is where the plan gets its identity, so the
402
+ // activity's own result carries it and the Gate step references it from
403
+ // there rather than re-reading the file.
404
+ test("the result carries the plan's digest, taken off the show -json rendering", async () => {
405
+ const dir = project({ roots: { app: { dir: "./infra" } } });
406
+ showReplies();
407
+ const result = await terraformPlan({ root: "app", cwd: dir });
408
+ expect(result.planDigest).toBe(terraformPlanDigest(JSON.parse(PLAN_JSON)));
409
+ });
410
+
326
411
  test("exit 2: changed, and the plan is still shown", async () => {
327
412
  const dir = project({ roots: { app: { dir: "./infra" } } });
328
413
  replies.push({ match: "plan ", reply: execError(2, "", "Plan: 2 to add...\n") });
@@ -44,6 +44,7 @@ import { writeFileSync } from "node:fs";
44
44
  import { promisify } from "node:util";
45
45
  import { resolve, dirname, join } from "node:path";
46
46
  import { loadChantConfigUpward } from "@intentius/chant/config";
47
+ import { computePlanDigest } from "@intentius/chant/op";
47
48
  import type { TerraformConfig, TerraformRootConfig } from "../../config";
48
49
  import { detectLiveEstate } from "./live-detect";
49
50
  import {
@@ -247,6 +248,92 @@ export interface PlanChangeCounts {
247
248
  destroys: number;
248
249
  }
249
250
 
251
+ /**
252
+ * One resource's proposed change, as a plan digest sees it (#2300) — the
253
+ * projection of a `terraform show -json` `resource_changes` entry that
254
+ * survives into {@link terraformPlanDigest}.
255
+ */
256
+ export interface TerraformPlannedChange {
257
+ address: unknown;
258
+ mode: unknown;
259
+ type: unknown;
260
+ name: unknown;
261
+ index: unknown;
262
+ provider_name: unknown;
263
+ deposed: unknown;
264
+ actions: unknown;
265
+ before: unknown;
266
+ after: unknown;
267
+ after_unknown: unknown;
268
+ replace_paths: unknown;
269
+ importing: unknown;
270
+ }
271
+
272
+ /**
273
+ * The change set a `terraform show -json` plan describes, canonicalised
274
+ * (#2300): every proposed change, at its address, with the values that would
275
+ * be written, sorted so two renderings of the same plan project identically.
276
+ *
277
+ * Everything else in the document is dropped, and the drops are the point —
278
+ * see `packages/core/src/lifecycle/plan-digest.ts` for the general rule. Here
279
+ * that means `timestamp` and `terraform_version` (when the plan was taken and
280
+ * by which binary), `format_version` (how it was rendered), `prior_state` and
281
+ * `planned_values` (restatements of the same change set from another angle),
282
+ * `configuration` (the source that produced it, which can be refactored
283
+ * without changing a single proposed action) and `checks` / `relevant_
284
+ * attributes` (diagnostics about the plan, not the plan). What is left is
285
+ * what applying it would do.
286
+ */
287
+ export function terraformPlanChangeSet(planJson: unknown): {
288
+ resourceChanges: TerraformPlannedChange[];
289
+ outputChanges: unknown;
290
+ } {
291
+ const doc = planJson as { resource_changes?: unknown; output_changes?: unknown } | null | undefined;
292
+ const raw = Array.isArray(doc?.resource_changes) ? doc.resource_changes : [];
293
+ const resourceChanges = raw.map((entry): TerraformPlannedChange => {
294
+ const e = (entry ?? {}) as Record<string, unknown>;
295
+ const change = (e.change ?? {}) as Record<string, unknown>;
296
+ return {
297
+ address: e.address,
298
+ mode: e.mode,
299
+ type: e.type,
300
+ name: e.name,
301
+ index: e.index,
302
+ provider_name: e.provider_name,
303
+ deposed: e.deposed,
304
+ actions: change.actions,
305
+ before: change.before,
306
+ after: change.after,
307
+ after_unknown: change.after_unknown,
308
+ replace_paths: change.replace_paths,
309
+ importing: change.importing,
310
+ };
311
+ });
312
+ // terraform already emits these in address order, but nothing in the format
313
+ // promises it, and a digest that depends on the emitter's iteration order
314
+ // would refuse a plan that is identical in every way that matters.
315
+ resourceChanges.sort((a, b) =>
316
+ `${String(a.address)}\u0000${String(a.deposed ?? "")}`.localeCompare(
317
+ `${String(b.address)}\u0000${String(b.deposed ?? "")}`,
318
+ ),
319
+ );
320
+ return { resourceChanges, outputChanges: doc?.output_changes ?? {} };
321
+ }
322
+
323
+ /**
324
+ * The identity of a terraform plan (#2300): {@link terraformPlanChangeSet}
325
+ * hashed. This is what a `TerraformApplyOp` gate binds its approval to, and
326
+ * what a later run recomputes and compares.
327
+ *
328
+ * Taken over the `show -json` rendering rather than the plan file's bytes on
329
+ * purpose: the file is an opaque, version-stamped archive, and two runs of
330
+ * `plan -out` over an unchanged root produce different bytes. The rendering
331
+ * is the same plan both times.
332
+ */
333
+ export function terraformPlanDigest(planJson: unknown): string {
334
+ return computePlanDigest("terraform-plan", terraformPlanChangeSet(planJson));
335
+ }
336
+
250
337
  /** What {@link terraformPlan} resolved. Carries the plan itself, so no later step re-plans. */
251
338
  export interface TerraformPlanResult extends PlanChangeCounts {
252
339
  /** `true` when terraform reported exit 2 under `-detailed-exitcode`: the plan proposes changes. */
@@ -259,6 +346,13 @@ export interface TerraformPlanResult extends PlanChangeCounts {
259
346
  json: unknown;
260
347
  /** `terraform show -no-color <planFile>` — the human-readable plan. */
261
348
  text: string;
349
+ /**
350
+ * This plan's identity (#2300) — {@link terraformPlanDigest} over
351
+ * {@link TerraformPlanResult.json}. Hand it to a gate step's `plan` so the
352
+ * approval binds to this plan and not to the next run: `gate(name, { plan:
353
+ * plan.out.planDigest })`.
354
+ */
355
+ planDigest: string;
262
356
  }
263
357
 
264
358
  /**
@@ -858,7 +952,15 @@ export async function terraformPlan(
858
952
  const textRun = await run(terraformShowCommand({ binary, json: false, planFile }), dir, env, signal);
859
953
  const json: unknown = JSON.parse(jsonRun.stdout);
860
954
 
861
- return { changed, planFile, dir, json, text: textRun.stdout, ...countPlanChanges(json) };
955
+ return {
956
+ changed,
957
+ planFile,
958
+ dir,
959
+ json,
960
+ text: textRun.stdout,
961
+ planDigest: terraformPlanDigest(json),
962
+ ...countPlanChanges(json),
963
+ };
862
964
  }
863
965
 
864
966
  /**
@@ -84,6 +84,7 @@ export const terraformPlanContract = activityContract(
84
84
  dir: z.string(),
85
85
  json: z.unknown(),
86
86
  text: z.string(),
87
+ planDigest: z.string(),
87
88
  }),
88
89
  rootEntity,
89
90
  );