proposal-system/infra/deploy-role/README.md
Adam Moussa 0f9d27fbf0
chore(infra): prep proposal-system for seahaven-prod deployment (#227)
* chore(infra): retarget prod to seahaven-prod account + OIDC deploy-role artifacts

Retarget the CDK prod env from mgmt (328440206208, now frozen for workloads) to the
dedicated seahaven-prod workload account (011934824531). proposal-system is the org's
first prod tenant. Hard-block env=staging (still targets frozen mgmt) in resolveConfig
until it is retargeted to seahaven-dev (710827005802). Add a WARN-only out-of-pipeline
deploy guard in bin/app.ts.

Add infra/deploy-role/: OIDC trust policy (sub scoped to
Sea-Haven-Industries/proposal-system:ref:refs/heads/main), least-privilege permissions
policy (AssumeRole on the verified cdk-hnb659fds bootstrap roles, deterministic site
bucket, account-scoped CloudFront invalidation), and an idempotent creation script.
Verified against live prod: bootstrap qualifier hnb659fds v32, OIDC provider present.
Passed GPT-4.1 cross-review (APPROVE) and workflow red-team (CLEAN). Role NOT yet created
— gated on /sh-security-review + the deploy go-ahead.

Docs: README + CLAUDE.md reflect the prod account and pipeline-only deploy.

* chore(infra): region-bound deploy-role DescribeStacks to us-east-1 (sh-security-review IAM-L2)

* feat(infra): Aurora prod backup retention 14d + window; prod-only CDK context

Bump Aurora automated-backup (PITR) retention 7->14d and set a preferred backup
window for the prod tenant. Dedicated AWS Backup vault + cross-account restore
test is a tracked follow-up (no org central-backup design exists yet). Prune the
stale mgmt-account AZ context; prod (011934824531) is the only deploy target.
2026-07-15 14:44:35 -04:00

64 lines
2.9 KiB
Markdown

# seahaven-prod OIDC deploy role — proposal-system
IAM artifacts for the GitHub Actions OIDC deploy role that lets the
`Sea-Haven-Industries/proposal-system` repo deploy the CDK stacks and sync the
frontend site bucket into **seahaven-prod**. Artifacts only — nothing here has
been applied to AWS.
## Resolved facts (Phase 0, read-only verification)
| Field | Value |
|---|---|
| Account | `011934824531` (seahaven-prod) |
| Region | `us-east-1` |
| CDK qualifier | `hnb659fds` (AWS CDK **default** — bootstrap v32; no custom synthesizer needed) |
| OIDC provider ARN | `arn:aws:iam::011934824531:oidc-provider/token.actions.githubusercontent.com` (EXISTS) |
| Role name | `githubdeploy-proposal-system` |
| Subject scope | `repo:Sea-Haven-Industries/proposal-system:ref:refs/heads/main` (exact, no wildcard) |
| Site bucket | `proposal-system-web-011934824531` (frontend-stack convention) |
## Files
- **trust-policy.json** — Web-identity trust policy. Federated principal is the
existing GitHub OIDC provider. `sts:AssumeRoleWithWebIdentity` gated by two
StringEquals conditions: `aud == sts.amazonaws.com` and an **exact** `sub`
match on the proposal-system repo's `main` branch (no `StringLike`, no
wildcard). Mirrors the structure of the existing
`githubdeploy-seahaven-org-baseline` role.
- **permissions-policy.json** — Least-privilege inline policy:
- `sts:AssumeRole` on the four CDK bootstrap roles (deploy, file-publishing,
lookup, image-publishing) scoped to qualifier `hnb659fds`, account, and
region. This is how a CDK deploy actually gains its power — no direct
service permissions are granted to the deploy role itself.
- `cloudformation:DescribeStacks` on `*` for the `cdk deploy` /
change-set health check.
- `s3:PutObject`/`DeleteObject`/`ListBucket` on the site bucket and its
objects for the frontend asset sync.
- `cloudfront:CreateInvalidation` on `*`, constrained by
`aws:ResourceAccount == 011934824531` (distribution ARNs aren't known at
author time; the account condition prevents cross-account use).
- **create-deploy-role.sh** — Idempotent bash (`aws --profile prod`). Verifies
the profile resolves to `011934824531`, then create-role (or
update-assume-role-policy if it exists) + put-role-policy. Safe to re-run.
**Gated:** do not execute until GPT-4.1 cross-review AND `/sh-security-review`
pass (IAM/trust change).
## Applying (after gates pass)
```bash
./create-deploy-role.sh
```
Then point the GitHub Actions workflow's `aws-actions/configure-aws-credentials`
step at the printed role ARN.
## Placeholders / follow-ups
- **None outstanding.** Qualifier resolved to the real value `hnb659fds`; no
`<QUALIFIER>` placeholder remains. OIDC provider exists, so no provider
creation prerequisite.
- CloudFront invalidation is scoped by account, not by distribution ARN — tighten
to the specific distribution ARN once frontend-stack is deployed if you want
per-resource least privilege.