Skip to content

Task Plan: Infrastructure Stream

Author: Miguel Pinilla Date: 2026-05-07 Status: Planning

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”infrastructure row (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:prod us-east-2 region anomaly, the file-by-file change list under “Concrete infrastructure PR — file-by-file changes”.
RepositoryBranchWorktree
Arda-cards/infrastructurejmpicnic/amazon-client-integration (existing)/Users/jmp/code/arda/projects/amazon-item-import-worktrees/infrastructure (existing)

Single worktree, single PR.

#TaskDepends onNotes
1In 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.
2In 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.).1Single multi-field secret per partition (per the v1 settled decision).
3In the same template: add an AmazonCreatorsApiArn output exporting the secret ARN as ${Infrastructure}-${Partition}-I-AmazonCreatorsApiArn.2Cross-stack export name follows the existing -I- convention for partition-internal exports.
4In 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.3This template applies only to full-IaC partitions (Alpha001:demo is the only one in scope; SandboxKyle002:kyle is no longer in service).
5In 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.
5bFix 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.5Pre-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.
6In amm.sh: assemble the four op read outputs into a single JSON string {"credentialId":"…","credentialSecret":"…","version":"…","associateTag":"…"}.5Use jq -n --arg. Validate non-empty before passing.
7In amm.sh: pass AmazonCreatorsApi=${json} as a --parameter-overrides entry on the existing partitionSecrets aws cloudformation deploy invocation (around amm.sh:506).6, 1Adds one \ line to the existing parameter-override block.
8In 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.7Mirrors the existing CLOUDFRONT_KEY_PAIR_ID conditional injection at the same location.
8bOne-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.
8camm.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 texttr -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
9No 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.
10No 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.
11CHANGELOG entry in infrastructure/CHANGELOG.md under Added (new feature). Cite PDEV-446.
12Pre-push: npm run build (CDK synth) green; npm test green if applicable.1–11The CFN templates are deployable artefacts; CDK synth catches schema errors.
13Vault-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>&1head -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
14Open the PR; run /pr-steward. Record the verification command output (Task 13) in the PR body for auditability.12, 13
  1. CDK synth + tests green locally and in CI.
  2. The four 1Password vaults contain a populated Amazon Creators API entry at merge time (verified by Task 13).
  3. CFN templates pass cfn-lint (or equivalent in this repo’s CI).
  4. 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 no gh-oidc-provider.ts change was needed.
  5. After deploy, every target Amplify app has app.buildSpec returning null/whitespace; amm.sh’s Task 8c drift check passes on subsequent runs.

The four partition vaults — Arda-DevOAM, Arda-StageOAM, Arda-DemoOAM, Arda-ProdOAM — must each contain a populated Amazon Creators API entry before this PR merges. (Arda-SystemsOAM is a separate, workspace-wide vault for system-level secrets and is not used here.)

If the gate is not met:

  • op read for the missing entry will fail (set -eu in amm.sh aborts the run).
  • Every subsequent amm.sh execution 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.

Modified:

  • src/main/cfn/partitionSecrets.cfn.yaml (parameter, secret resource, output).
  • src/main/cfn/amplify.cfn.yaml (four EnvironmentVariables entries — full-IaC partitions only, currently Alpha001:demo).
  • amm.sh (op-read additions, CFN parameter-override addition, partial-IaC jq-merge extension, inline-BuildSpec drift check at top per Task 8c, fix PARTITION_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.
  • ../../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