5.6 KiB
Frontend infrastructure and migration rehearsal
This CDK app describes the existing Sea Haven SHOC SPA hosting and an isolated,
production-shaped Terraform adoption rehearsal. It performs no content upload.
Content-only deployment is handled by scripts/deploy-web.sh.
Existing environments
Normal synthesis remains unchanged when the adoption flag is off:
- private, versioned S3 bucket with CDK auto-delete cleanup
- CloudFront distribution and origin access control
- viewer-request function that rewrites extensionless SPA routes
- optional Route 53 A and AAAA aliases
- GitHub Actions OIDC deploy role
Dev remains the default context in cdk.json. Staging uses explicit context
arguments. During migration, both content workflows are manual-only and use
fixed environment configuration rather than discovering deployment targets
from CloudFormation.
Terraform POC
The POC is isolated in account 396287094661, region us-east-1, and is
created only with -c tfPoc=true plus an explicit tfPocPhase. It uses three
ownership scopes:
shoc-frontend-tf-poc-shared: a dedicated public hosted zone forfrontend-tf-poc.seahaven.com.shoc-frontend-tf-poc-certificate: the DNS-validated ACM certificate.shoc-frontend-tf-poc: the private versioned bucket, CloudFront OAC, distribution, SPA function, A/AAAA aliases, and GitHub OIDC content deploy role.
Fixed application values:
- bucket:
seahaven-shoc-frontend-tf-poc - role:
githubdeploy-shoc-frontend-new-tf-poc - GitHub environment:
tf-poc - site:
https://frontend-tf-poc.seahaven.com - API:
https://api.tf-poc.seahaven.com/api
The shared stack is intentionally staged. The zone must exist and be delegated before ACM can validate a certificate inside it:
cd infra/cdk
npm ci
npm test
npm run synth:tf-poc-zone
npm run synth:tf-poc-environment
After approval, deploy only shoc-frontend-tf-poc-shared with
tfPocPhase=zone. Its outputs provide the child name servers. Create the
parent NS record as a separate approved change and verify public delegation.
Only then use tfPocPhase=environment to deploy the separate certificate and
site stacks. The zone stack never contains the certificate, so re-running the
zone phase cannot remove a certificate created by the environment phase.
Omitting tfPocPhase fails closed.
The stacks output the hosted zone ID, certificate ARN, delegation evidence, workspace tag, boundary ARN, and import IDs for the bucket, bucket policy, distribution, OAC, SPA function, A/AAAA records, deploy role, and inline role policy. They also emit the generated OAC name/description, deterministic origin ID, and inline policy name required by the tf-poc Terraform configuration.
Adoption retention
-c retainForTerraformAdoption=true is deliberately opt-in. Keep it enabled
from the reviewed retention deployment through CloudFormation ownership
detachment.
The emitted template applies both DeletionPolicy: Retain and
UpdateReplacePolicy: Retain to:
- site bucket and bucket policy
- distribution, OAC, and SPA rewrite function
- A and AAAA records
- GitHub deploy role and its inline policy
SiteBucket/AutoDeleteObjectsCustomResource
The bucket remains configured with autoDeleteObjects: true. The emitted
bucket and its matching custom resource are both retained, so deleting the
stack cannot invoke that custom resource to empty the versioned bucket.
Generated provider Lambda resources, provider IAM resources, provider logs,
and CDK metadata are intentionally excluded. Template tests enforce this exact
boundary.
In adoption mode, the deploy role also receives:
- tag
HcpTerraformWorkspace=shoc-frontend-new-{env} - permissions boundary
arn:aws:iam::<account>:policy/shoc-frontend-new-{env}-deploy-boundary - exact
StringEqualsOIDC subject matching; for dev this narrows the current no-wildcardStringLikesubject before Terraform import
These changes are absent when the flag is off.
Content deployment safeguards
scripts/deploy-web.sh requires explicit target and expectation variables:
SITE_BUCKETand matchingEXPECTED_SITE_BUCKETCLOUDFRONT_DISTRIBUTION_IDSITE_URLVITE_API_URLand matchingEXPECTED_API_URLDEPLOY_RELEASE_IDorGITHUB_SHA- optional comma-separated
FORBIDDEN_API_URLS - optional
API_SMOKE_URLandAPI_CORS_ORIGIN
The script verifies bucket versioning, builds the app, publishes immutable
assets and a no-cache index, records a release manifest, invalidates and waits,
then checks /, /login, an extensionless route, asset references, API URLs,
and cache headers. Optional API preflight checks verify CORS.
If verification fails after publishing the index, the previous index version is restored and invalidated. Pruning starts only after successful remote verification. Current versions needed by the latest two release manifests are kept; unreferenced object versions are deleted.
Manual workflows
.github/workflows/deploy.yml: dev content deployment.github/workflows/deploy-staging.yml: staging content deployment.github/workflows/deploy-tf-poc.yml: isolated POC content deployment
All are workflow_dispatch only. Staging and tf-poc retain their GitHub
environment protection and exact environment-scoped OIDC trust. Each dev and
staging distribution ID is pinned in its workflow. The tf-poc environment
must define its generated CLOUDFRONT_DISTRIBUTION_ID as a protected variable.
Each workflow pins its environment's Swagger URL for API CORS/preflight checks.
Infrastructure creation, parent-zone delegation, Terraform imports, and ownership detachment remain separate administrator actions. None of these workflows performs them.