Task Plan: Infrastructure Stream
Author: Miguel Pinilla Date: 2026-05-07 Status: Planning
Summary
Section titled “Summary”Add the four AMAZON_* runtime values to the existing 1Password → AWS Secrets Manager → Amplify env-var pipeline used by arda-frontend-app. Concrete edits to three files: partitionSecrets.cfn.yaml (add a multi-field secret), amplify.cfn.yaml (add four entries to the EnvironmentVariables block — full-IaC partitions only), and amm.sh (read the four fields from each partition’s 1Password vault, pass as a CFN parameter, and extend the partial-IaC jq-merge block to inject the values via aws amplify update-app --environment-variables).
This stream is independent of the other three streams at the code level. It has a hard merge gate on the operator action: all four 1Password vaults must contain the Amazon Creators API entry before this PR merges.
Scope (cite of goal.md and context-exploration.md)
Section titled “Scope (cite of goal.md and context-exploration.md)”- Goal §“Repositories” —
infrastructurerow (the file-by-file plan is in the row’s body). - Goal §“Open Items” — “Amplify env-var IaC pipeline” item (the pipeline diagram).
- Context §“Configuration & Env-Var Convention” — env-var naming, source-of-truth, delivery pipeline.
- Context §“IaC Compliance per Partition” — full-IaC vs partial-IaC partition split, the
Alpha001:produs-east-2region anomaly, the file-by-file change list under “ConcreteinfrastructurePR — file-by-file changes”.
Repository
Section titled “Repository”| Repository | Branch | Worktree |
|---|---|---|
Arda-cards/infrastructure | jmpicnic/amazon-client-integration (existing) | /Users/jmp/code/arda/projects/amazon-item-import-worktrees/infrastructure (existing) |
Single worktree, single PR.
| # | Task | Depends on | Notes |
|---|---|---|---|
| 1 | In src/main/cfn/partitionSecrets.cfn.yaml: add a new AmazonCreatorsApi parameter — Type: String, MinLength: 1, ConstraintDescription: "Cannot be empty", NoEcho: true, Description describing it as a JSON-shaped string with four keys (credentialId, credentialSecret, version, associateTag). | — | Hard MinLength:1 is the project’s chosen hard gate; amm.sh is responsible for validating that the JSON is well-formed before passing it. |
| 2 | In the same template: add an AmazonCreatorsApiSecret resource (AWS::SecretsManager::Secret, Name: !Sub "${Infrastructure}-${Partition}-AmazonCreatorsApi", SecretString: !Ref AmazonCreatorsApi, DeletionPolicy: Delete, UpdateReplacePolicy: Delete — match the conventions of ArdaApiKeySecret etc.). | 1 | Single multi-field secret per partition (per the v1 settled decision). |
| 3 | In the same template: add an AmazonCreatorsApiArn output exporting the secret ARN as ${Infrastructure}-${Partition}-I-AmazonCreatorsApiArn. | 2 | Cross-stack export name follows the existing -I- convention for partition-internal exports. |
| 4 | In src/main/cfn/amplify.cfn.yaml: in the AmplifyApp resource’s EnvironmentVariables block, add four entries — AMAZON_CREATORS_CREDENTIAL_ID, AMAZON_CREATORS_CREDENTIAL_SECRET, AMAZON_CREATORS_CREDENTIAL_VERSION, AMAZON_ASSOCIATE_TAG — each resolving via !Sub - "{{resolve:secretsmanager:${SecretArn}:SecretString:<key>::}}" - SecretArn: !ImportValue "Fn::Sub": "${Infrastructure}-${Partition}-I-AmazonCreatorsApiArn". The <key> for each is credentialId, credentialSecret, version, associateTag respectively. | 3 | This template applies only to full-IaC partitions (Alpha001:demo is the only one in scope; SandboxKyle002:kyle is no longer in service). |
| 5 | In amm.sh: read the four fields from each partition’s 1Password vault. Concretely, define PARTITION_AMAZON_VAULT lookups (or extend the existing PARTITION_VAULT_MAP) so each partition’s deploy reads op://Arda-${Vault}/Amazon Creators API/{credentialId,credentialSecret,version,associateTag}. Partition → vault map: dev→DevOAM, stage→StageOAM, demo→DemoOAM, prod→ProdOAM — one env-named vault per partition, following the Arda-{Env}OAM convention. | — | Arda-SystemsOAM is a separate workspace-wide vault for system-level secrets (e.g. the 1Password service account token used by CI); it is not used for partition-scoped runtime credentials. |
| 5b | Fix amm.sh:170 PARTITION_VAULT_MAP[prod]. The existing map currently sets prod to SystemsOAM, which conflates the system-wide vault with prod’s partition-scoped vault. Update to prod=ProdOAM so prod’s op read lookups (Amazon credentials and any other partition-scoped fields) target Arda-ProdOAM. Before flipping: enumerate every field that amm.sh currently reads from the prod vault and confirm with the Account Holder that each is present in (or migrated to) Arda-ProdOAM. | 5 | Pre-existing inconsistency surfaced by this project. Fix is in scope because this PR is the one introducing new prod-vault reads; leaving the map pointed at SystemsOAM would split Amazon credentials from the rest of prod’s secrets across two vaults, which is exactly what the Arda-{Env}OAM convention is meant to avoid. |
| 6 | In amm.sh: assemble the four op read outputs into a single JSON string {"credentialId":"…","credentialSecret":"…","version":"…","associateTag":"…"}. | 5 | Use jq -n --arg. Validate non-empty before passing. |
| 7 | In amm.sh: pass AmazonCreatorsApi=${json} as a --parameter-overrides entry on the existing partitionSecrets aws cloudformation deploy invocation (around amm.sh:506). | 6, 1 | Adds one \ line to the existing parameter-override block. |
| 8 | In amm.sh: extend the partial-IaC else branch’s jq-merge block (around amm.sh:628-660). Steps: (a) fetch the secret value via aws secretsmanager get-secret-value --secret-id "${infrastructure}-${partition}-AmazonCreatorsApi"; (b) jq the four fields out of the SecretString; (c) extend the existing JQ_EXPR to include AMAZON_CREATORS_CREDENTIAL_ID, AMAZON_CREATORS_CREDENTIAL_SECRET, AMAZON_CREATORS_CREDENTIAL_VERSION, AMAZON_ASSOCIATE_TAG keys; (d) extend JQ_ARGS to pass them in. | 7 | Mirrors the existing CLOUDFRONT_KEY_PAIR_ID conditional injection at the same location. |
| 8b | One-time inline BuildSpec clear (Option A). For each Amplify app (Alpha002/dev, Alpha002/stage, Alpha001/demo, Alpha001/prod), clear the inline BuildSpec so the in-repo amplify.yml becomes the single source of truth on every build: aws amplify update-app --app-id <id> --build-spec ' ' (single-space; the API rejects empty string). Verify per-app with aws amplify get-app --app-id <id> --query 'app.buildSpec' returning null/whitespace. Record before/after output in the PR body. | — | Safe because (a) Arda triggers builds via aws amplify start-job against the connected branch, never start-deployment; (b) AWS docs: “Amplify Hosting does not support manual deploys for server-side rendered (SSR) apps” — arda-frontend-app is Next.js SSR, so the only available trigger path reads amplify.yml from the branch checkout. After this, future amplify.yml changes (this project’s BFF stream and beyond) take effect on the next Amplify build with no CLI propagation step. |
| 8c | amm.sh drift check for inline BuildSpec. Add an early assertion (top of amm.sh, after partition resolution) that fails the deploy if any target Amplify app has a non-empty inline BuildSpec: `if [[ -n ”$(aws amplify get-app —app-id ”${app_id}” —query ‘app.buildSpec’ —output text | tr -d ’[:space:]’)” ]]; then echo “ERROR: inline BuildSpec is set on ${app_id}; clear it via ‘aws amplify update-app —app-id ${app_id} —build-spec ” ”’ before re-running”; exit 1; fi`. | 8b |
| 9 | No change to gh-oidc-provider.ts. The existing amplify:GetApp / amplify:UpdateApp IAM grants on arn:aws:amplify:*:apps/* already cover both us-east-1 and us-east-2 (verbatim comment at gh-oidc-provider.ts:375-376 carries the historical anomaly note for Alpha001:prod). Verify in code review; no edit needed. amplify:GetApp is also the grant that backs Task 8c’s drift check — confirm it remains in the policy. | — | Negative confirmation; record in PR description. |
| 10 | No change to .github/workflows/amm.yml unless the workflow needs to source the credential triple from GitHub Org secrets. The current amm.yml (amm.yml) reads via op read at job time, so 1Password is the only secret-source. Verify by re-reading the workflow at PR-prep time. | — | If a change is needed, add to this task plan; otherwise skip. |
| 11 | CHANGELOG entry in infrastructure/CHANGELOG.md under Added (new feature). Cite PDEV-446. | — | |
| 12 | Pre-push: npm run build (CDK synth) green; npm test green if applicable. | 1–11 | The CFN templates are deployable artefacts; CDK synth catches schema errors. |
| 13 | Vault-population verification immediately before merge. Run `for v in DevOAM StageOAM DemoOAM ProdOAM; do op item get “Amazon Creators API” —vault “Arda-${v}” —fields credentialId 2>&1 | head -1; done`. All four must return a non-empty Credential ID. If any returns an error, the PR cannot merge until the operator populates the missing vault. | 5b |
| 14 | Open the PR; run /pr-steward. Record the verification command output (Task 13) in the PR body for auditability. | 12, 13 |
Acceptance criteria
Section titled “Acceptance criteria”- CDK synth + tests green locally and in CI.
- The four 1Password vaults contain a populated
Amazon Creators APIentry at merge time (verified by Task 13). - CFN templates pass
cfn-lint(or equivalent in this repo’s CI). - Recorded in the PR description: the result of Task 13’s verification, the before/after
aws amplify get-app ... --query 'app.buildSpec'output for all four apps (Task 8b), and a one-line confirmation that nogh-oidc-provider.tschange was needed. - After deploy, every target Amplify app has
app.buildSpecreturning null/whitespace;amm.sh’s Task 8c drift check passes on subsequent runs.
Merge gate (the hard gate)
Section titled “Merge gate (the hard gate)”The four partition vaults —
Arda-DevOAM,Arda-StageOAM,Arda-DemoOAM,Arda-ProdOAM— must each contain a populatedAmazon Creators APIentry before this PR merges. (Arda-SystemsOAMis a separate, workspace-wide vault for system-level secrets and is not used here.)
If the gate is not met:
op readfor the missing entry will fail (set -euinamm.shaborts the run).- Every subsequent
amm.shexecution for that partition fails — including infra changes unrelated to this project that happen to land on the partition during the rollout window. - The blast radius is “all infra deploys for that partition”; not just our project.
This gate is documented in phases.md and 3-deployment/deployment-plan.md. The operator stream’s runbook is the artefact that drives it.
Files to be created or modified
Section titled “Files to be created or modified”Modified:
src/main/cfn/partitionSecrets.cfn.yaml(parameter, secret resource, output).src/main/cfn/amplify.cfn.yaml(fourEnvironmentVariablesentries — full-IaC partitions only, currentlyAlpha001:demo).amm.sh(op-read additions, CFN parameter-override addition, partial-IaCjq-merge extension, inline-BuildSpecdrift check at top per Task 8c, fixPARTITION_VAULT_MAP[prod]per Task 5b).CHANGELOG.md(Added entry).
Out-of-band one-time action (no PR diff, recorded in PR body):
aws amplify update-app --build-spec ' 'against each of the four Amplify apps (Task 8b).
Possibly modified (settled at PR-prep):
.github/workflows/amm.yml— only if the workflow needs an env-var added (Task 10).
No change:
src/main/cdk/constructs/oam/gh-oidc-provider.ts— existing IAM grants already cover both regions.
References
Section titled “References”../../goal.md— project goal.../../context-exploration.md§ “Configuration & Env-Var Convention”, § “IaC Compliance per Partition” (the file-by-file plan).../../phases.md— stream structure and the hard ordering constraint.../operator/task-plan.md— produces the four 1Password vault entries this stream consumes at deploy time.../../3-deployment/deployment-plan.md— overall choreography, smoke test, rollback.
Copyright: (c) Arda Systems 2025-2026, All rights reserved
Copyright: © Arda Systems 2025-2026, All rights reserved