# 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 `` 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.