AWS Deploy
Infrastructure is AWS CDK under upstream infra/. The app stack is API Gateway + Lambda + Cognito + DynamoDB (-c enableDynamo=true) + Amplify app/branch. It does not define product S3 buckets. The SPA artifact is zip-deployed
SPA hosting path: CDK creates Amplify app/branch with auto-build off; a separate job zip-uploads the Vite build — no GitHub↔Amplify Git connection. separately after CDK — not via a GitHub↔Amplify Git connection.
Lambda defaults: Node.js 24.x, 90s timeout, 512 MB; Bedrock invoke/converse IAM scoped to Nova Lite + Haiku 4.5 ARNs (not *).
Credentials
Section titled “Credentials”Use one account/region for the session. Export once; do not pass --profile on every later command:
aws sso login --profile sandboxexport AWS_PROFILE=sandboxexport AWS_REGION=ap-southeast-2export CDK_DEFAULT_ACCOUNT=$(aws sts get-caller-identity --query Account --output text)export CDK_DEFAULT_REGION=$AWS_REGIONaws sts get-caller-identityAlso needed: Bedrock usable in that region (below). For GitHub deploy / PR analysis, configure OIDC and PR comment secrets — do not put AWS keys or the API key value in the repo.
Required Bedrock models
Section titled “Required Bedrock models”Demo targets ap-southeast-2. Model availability is not global — invoke in the same region as AWS_REGION / Lambda. See model regional availability and model access.
The Bedrock Model access console page is retired. Serverless foundation models are intended to enable on first invoke (Marketplace subscribe for 3P models; Anthropic may need a one-time use-case form). Amazon models (e.g. Nova) are not Marketplace agreement products. IAM or SCPs can still deny invoke.
| Agent | Model | Bedrock model ID |
|---|---|---|
| Diff Analyst | Amazon Nova Lite | amazon.nova-lite-v1:0 |
| Risk Reviewer | Amazon Nova Lite | amazon.nova-lite-v1:0 |
| Ship Coach | Claude Haiku 4.5 (AU inference profile) | au.anthropic.claude-haiku-4-5-20251001-v1:0 |
Smoke Nova Lite (same profile/region as deploy):
aws bedrock get-foundation-model-availability --model-id amazon.nova-lite-v1:0aws bedrock-runtime converse \ --model-id amazon.nova-lite-v1:0 \ --messages '[{"role":"user","content":[{"text":"Hi"}]}]' \ --inference-config '{"maxTokens":16}'Expect authorizationStatus: AUTHORIZED and a normal Converse reply. If you see ValidationException: Operation not allowed with authorizationStatus: NOT_AUTHORIZED, check Bedrock Quotas for Nova (TPM/RPM). Applied 0 with on-demand increase “Not supported” means the account cannot run inference until AWS grants default capacity — separate from IAM Admin.
Also smoke Ship Coach:
aws bedrock-runtime converse \ --model-id au.anthropic.claude-haiku-4-5-20251001-v1:0 \ --messages '[{"role":"user","content":[{"text":"Hi"}]}]' \ --inference-config '{"maxTokens":16}'Alternatives (override via env):
- US regions: Claude 3.5 Haiku
anthropic.claude-3-5-haiku-20241022-v1:0(orus.anthropic.claude-3-5-haiku-20241022-v1:0) viaCLAUDE_MODEL_ID/SHIP_COACH_MODEL_ID - Global Haiku 4.5 profile:
global.anthropic.claude-haiku-4-5-20251001-v1:0 - Do not default to Claude 3 Haiku (
anthropic.claude-3-haiku-20240307-v1:0) — it is LEGACY - Claude unavailable: set
SHIP_COACH_MODEL_IDorCLAUDE_MODEL_IDtoamazon.nova-lite-v1:0 - Cross-region Nova (if on-demand stays at 0):
NOVA_MODEL_ID=apac.amazon.nova-lite-v1:0
Override vars: NOVA_MODEL_ID, CLAUDE_MODEL_ID, or per-agent DIFF_ANALYST_MODEL_ID, RISK_REVIEWER_MODEL_ID, SHIP_COACH_MODEL_ID.
Bootstrap
Section titled “Bootstrap”Before the first cdk deploy, bootstrap once. CDK creates toolkit stack CDKToolkit with assets bucket cdk-hnb659fds-assets-<account>-<region>, IAM publish/deploy roles, and SSM /cdk-bootstrap/hnb659fds/version. That bucket is CDK plumbing — not part of the Coach product — but remains and is reused on later deploys.
npx cdk bootstrap aws://$CDK_DEFAULT_ACCOUNT/$CDK_DEFAULT_REGIONIf a hardened account denies s3:PutBucketPublicAccessBlock, retry with --public-access-block-configuration false. That flag only skips CDK attaching BPA via that API call — it does not make the assets bucket public.
Deploy
Section titled “Deploy”npm installnpm run buildnpx cdk synth -c enableDynamo=trueexport PR_READY_OWNER_EMAIL=you@example.comnpx cdk deploy --require-approval never -c enableDynamo=true -c ownerEmail="$PR_READY_OWNER_EMAIL"Or: npm run deploy (passes -c enableDynamo=true). GitHub Deploy always enables DynamoDB. After CDK, run npm run deploy:amplify (or wait for GHA job deploy-amplify) so AppUrl serves the SPA — see Owner UI.
Stack outputs
Section titled “Stack outputs”| Output | Notes |
|---|---|
ApiUrl | Base URL before analyze |
ApiKeyId | Use to retrieve the key value once — value is never a stack output |
| Cognito IDs / region | For the SPA |
AmplifyAppId / AmplifyBranchName / AppUrl | Zip deploy + hosted UI |
aws apigateway get-api-key --api-key "$(aws cloudformation describe-stacks \ --stack-name PrReadinessCoachStack \ --query "Stacks[0].Outputs[?OutputKey=='ApiKeyId'].OutputValue" --output text)" \ --include-value --query value --output textStore PR_READY_API_KEY and PR_READY_API_URL as GitHub secrets for PR comments. Do not put the API key in Amplify / Vite env — the browser uses Cognito JWTs only.
Dual auth
Section titled “Dual auth”| Client | Credential | Routes |
|---|---|---|
| GitHub Actions / CLI | API key (x-api-key) | POST /analyze |
| Amplify SPA | Cognito JWT Authorization: Bearer | GET /runs, GET /runs/{runId}, POST /ui/analyze |
Pitfalls
Section titled “Pitfalls”- IAM Admin ≠ inference if Bedrock quotas are 0 /
NOT_AUTHORIZED - Vite
VITE_*are bake-time — re-rundeploy-amplifywhen API/Cognito outputs change - Prefer the minimum deploy IAM policy over
AdministratorAccess; bootstrap stays a one-time wider admin step - OIDC trust too broad (
repo:OWNER/REPO:*or*) weakens a public repo — lock deploy tomain(see GitHub OIDC) - Fork PRs do not receive Actions secrets
- Full-mode AI can over-flag docs; heuristics +
docsPathAllowlistremain the reproducible baseline