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"; import { ShocFrontendResources } from "./terraform-substrate/shoc-frontend-resources"; 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; /** * Enable the two SHOC backend tf-poc HCP roles. Defaults false so the * external-dev base-stack create is role-free. */ enableShocBackendPocRoles?: boolean; /** * Enable the four existing SHOC backend dev/staging HCP roles. Defaults * false because these names must enter the stack through CloudFormation * resource import, never a normal create/update. */ enableShocBackendLiveRoles?: boolean; /** * Enable the SHOC frontend tf-poc HCP roles after its exact CloudFront * identifiers and deploy-role guardrails have been reconciled. */ enableShocFrontendPocRoles?: boolean; /** * Enable the SHOC frontend dev/staging HCP roles after the existing GitHub * deploy roles have their exact boundaries and manager tags. */ enableShocFrontendLiveRoles?: boolean; /** Exact tf-poc site identifiers; empty values keep its roles disabled. */ shocFrontendPocDistributionId?: string; shocFrontendPocOriginAccessControlId?: string; shocFrontendPocFunctionName?: string; shocFrontendPocHostedZoneId?: string; shocFrontendPocCertificateArn?: string; } /** * Per-account HCP Terraform deploy substrate: the conditional * app.terraform.io OIDC provider, the prod/dev shared boundary-gated IAM * manager, and reviewed per-workspace role pairs. External-dev conditions out * the shared manager and uses exact inline policies for its SHOC import roles. * * 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); const substrate = new cfninc.CfnInclude(this, "Substrate", { templateFile: path.join( __dirname, "terraform-substrate", "terraform-substrate.template.yaml", ), parameters: { CreateOIDCProvider: props?.createOidcProvider === false ? "false" : "true", EnableShocBackendPocRoles: props?.enableShocBackendPocRoles === true ? "true" : "false", EnableShocBackendLiveRoles: props?.enableShocBackendLiveRoles === true ? "true" : "false", }, }); if (props?.env?.account === "396287094661") { new ShocFrontendResources(this, "ShocFrontend", { template: substrate, enablePocRoles: props?.enableShocFrontendPocRoles === true, enableLiveRoles: props?.enableShocFrontendLiveRoles === true, pocDistributionId: props?.shocFrontendPocDistributionId ?? "", pocOriginAccessControlId: props?.shocFrontendPocOriginAccessControlId ?? "", pocFunctionName: props?.shocFrontendPocFunctionName ?? "", pocHostedZoneId: props?.shocFrontendPocHostedZoneId ?? "", pocCertificateArn: props?.shocFrontendPocCertificateArn ?? "", }); } cdk.Tags.of(this).add("Project", "account-baseline"); cdk.Tags.of(this).add("Owner", "adam@seahavenind.com"); cdk.Tags.of(this).add("ManagedBy", "cdk"); } }