import * as cdk from "aws-cdk-lib"; import * as cfninc from "aws-cdk-lib/cloudformation-include"; import * as path from "path"; import { Construct } from "constructs"; export interface TerraformSubstrateStackProps extends cdk.StackProps { /** * Create the app.terraform.io OIDC identity provider in this account. * Defaults to true - Phase-0 checks (2026-07-30) confirmed neither prod nor * dev has one. Set false for an account that already has the provider: an * account holds exactly ONE provider per URL, so a duplicate create fails. * * This flag also makes a first-create rollback recoverable. The provider is * Retain, so if any other resource in this stack fails on FIRST create the * provider survives as an orphan while the stack lands in ROLLBACK_COMPLETE * (which cannot be updated). Recovery is to delete the stack and either * remove the orphaned provider or redeploy with this false. */ createOidcProvider?: boolean; } /** * Per-account HCP Terraform deploy substrate: the shared account-level * resources every Terraform workspace pipeline needs - * - app.terraform.io OIDC identity provider (conditional, see props), and * - `seahaven-hcptf-iam-management`, the shared boundary-gated IAM * guardrail policy every per-workspace APPLY role attaches. * * Deliberately NOT here: per-workspace hcptf- / hcptf--plan * roles. Those are appended to the template at each stack's migration time * (accumulator pattern, parallel to per-repo githubdeploy-* roles) so an * account never accumulates trust for workspaces that do not deploy to it. * * The IAM guardrail statements DERIVE FROM seahaven-cfn-exec-iam-management in * lib/deploy-substrate/deploy-substrate.template.yaml but are deliberately * STRICTER (role writes and PassRole confined to the tf-managed path, wider * DenySelfMutation) - the SAM copy's Resource "*" grants were confirmed a * critical escalation primitive by the 2026-07-30 security review, and its * justification for them does not transfer to Terraform. See the provenance * header in lib/terraform-substrate/terraform-substrate.template.yaml for the * full divergence list, and for the boundary-ARN coupling to the * seahaven-deploy-substrate stack (bin/app.ts carries the explicit * addStackDependency; the ARN reference alone creates no CFN edge). */ export class TerraformSubstrateStack extends cdk.Stack { constructor( scope: Construct, id: string, props?: TerraformSubstrateStackProps, ) { super(scope, id, props); new cfninc.CfnInclude(this, "Substrate", { templateFile: path.join( __dirname, "terraform-substrate", "terraform-substrate.template.yaml", ), parameters: { CreateOIDCProvider: props?.createOidcProvider === false ? "false" : "true", }, }); cdk.Tags.of(this).add("Project", "account-baseline"); cdk.Tags.of(this).add("Owner", "adam@seahavenind.com"); cdk.Tags.of(this).add("ManagedBy", "cdk"); } }