Terraform and OpenTofu plan approval workflow
A pull-request approval proves that someone reviewed source changes. It does not always prove that the final plan executed against the target is the same plan they saw. Inputs, state, provider behavior, credentials, or the target itself can change between review and apply.
Forgeplane uses a separate plan-to-apply approval boundary. A successful plan remains immutable. Promotion creates a linked apply intent, and the approval record controls whether that intent can enter the queue.
Forgeplane is in private beta. Request access before planning a deployment around this workflow.
Source review and apply review are different
Section titled “Source review and apply review are different”| Review | Main question | Evidence |
|---|---|---|
| Pull-request review | Should this source change merge? | Repository diff, tests, and source history |
| Plan review | What does the tool propose against this target now? | Resolved inputs, target context, plan output, and artifact digest |
| Apply approval | May this exact reviewed execution intent proceed? | Requester, reviewer, decision, source plan, promoted run, and verified artifact |
A strong delivery process can use all three. Forgeplane does not replace repository review or claim a built-in VCS policy engine.
Forgeplane approval sequence
Section titled “Forgeplane approval sequence”- A Terraform or OpenTofu
planrun succeeds and stores a plan artifact. - Promotion creates a new linked apply intent. The source plan remains
succeeded. - If the environment requires review, the apply intent enters
pending_approval. - Forgeplane creates a separate approval record.
- An authorized reviewer approves or rejects the request.
- Approval queues the apply intent.
- Before execution, Forgeplane verifies the plan artifact’s SHA-256 digest.
- The source plan, approval, apply run, logs, status, and result remain linked.
The requester needs run:create; the approver needs run:approve. Self-approval is disabled by default. An explicit project feature assignment overrides the system default; without a project assignment, the system setting is the fallback. Treat any effective policy that enables self-approval as an explicit risk decision. To approve, the submitted confirmation must contain a reason, the matching pending-run ID, and acknowledgement of irreversible impact. The web form pre-populates that run ID; the backend still rejects a mismatch. A rejection message is optional. When it is omitted, Forgeplane records the fallback reason rejected.
See Approval workflows for the detailed record and permission contract.
Failure modes the gate must stop
Section titled “Failure modes the gate must stop”A different artifact reaches apply
Section titled “A different artifact reaches apply”The promoted run references the reviewed plan artifact. A digest mismatch fails closed instead of applying substituted content.
The final execution context is no longer valid
Section titled “The final execution context is no longer valid”Approval is not a bypass for authorization, feature gates, worker eligibility, state-generation checks, or other admission rules. If the operation can no longer execute safely, it must fail rather than treat an old approval as permission to ignore current constraints.
The requester approves their own change
Section titled “The requester approves their own change”Forgeplane separates run:create and run:approve. It rejects self-approval unless the effective policy allows it: an explicit project assignment takes precedence, and the system setting is used only as the fallback. The high-friction confirmation must also succeed. Organization membership, team scope, resource ownership, and other policy still apply. Keep self-approval disabled for production separation-of-duty controls.
A rejected request is reused
Section titled “A rejected request is reused”Rejection does not change the successful source plan or queue the apply intent. Change the inputs or definition, produce new evidence, and create a new promotion when appropriate.
Example policy by environment
Section titled “Example policy by environment”| Environment | Example review boundary |
|---|---|
| Development | Allow rapid plans and applies when policy and risk permit. |
| Staging | Require a reviewer before a promoted apply can execute. |
| Production | Require separate requester/reviewer roles, restricted worker credentials, and approval of the exact plan artifact. |
These are design examples, not built-in role templates. Configure the actual feature gates, permissions, memberships, and worker access for your deployment.
Trigger from CI or another system
Section titled “Trigger from CI or another system”CI can remain the source-build and test boundary while Forgeplane owns the execution record. An automation identity with an expiring API key and the required scopes can call the Coordinator API to create the run or promotion request.
Keep the service account narrowly scoped. Do not place a human API key in CI. Preserve the returned request and correlation IDs so the external job can be traced to the Forgeplane run and audit records.
Use Service accounts and the Coordinator API reference for the current authentication and request contract.
Tool boundaries
Section titled “Tool boundaries”Plan promotion and apply approval apply to Terraform and OpenTofu. Ansible uses an execute run and does not have Terraform-style plan/apply promotion. Other gated operations can use approval records while retaining their own evidence and lifecycle rules.
Before production
Section titled “Before production”- Verify who can create runs and who can approve them.
- Confirm the explicit project self-approval assignment when one exists, and the system fallback when it does not; keep the effective policy disabled when separation of duties is required.
- Test approval with the required reason, matching pre-populated pending-run ID, and irreversible-impact acknowledgement.
- Test rejection with and without its optional message, plus stale or missing artifacts, digest mismatch, worker unavailability, and state-generation conflicts.
- Keep production worker credentials separate from development credentials.
- Confirm audit records link the requester, reviewer, source plan, apply intent, and result.
- Test the recovery path when a plan must be replaced rather than reused.
Continue with Run operations, Permissions and roles, and Managed state.