AWS Runtime Configuration

This page owns AWS secret flow and external-source configuration. First deployment, routine rollout, rollback and status commands remain in AWS Application Deployment.

Secrets and external API keys

PackyTrace keeps no production secrets in Git or container images. Committed realm, fixture and development credential files are demonstration configuration and must not be reused as production secrets. AWS values live encrypted in SSM Parameter Store:

Terraform variable
  -> SSM Parameter Store         (SecureString under /<project>/secret/*)
  -> render-config.sh            (writes /opt/packytrace/.env on the box)
  -> Docker Compose              (passes values to containers)
  -> service environment

render-config.sh converts a parameter's leaf name to UPPER_SNAKE; for example, …/secret/edamam_app_key becomes EDAMAM_APP_KEY. Adding a secret therefore requires a Terraform SSM parameter and a check that the rendered environment contains the expected variable. Database, Keycloak, GHCR, Grafana and Prometheus credentials follow this path. The Prometheus password also has a pre-hashed prometheus_basicauth_hash parameter for the generated Caddyfile.

Local deployment/.env is not an AWS configuration source. AWS uses SSM and render-config.sh only.

Recipe provider

The Recipes section uses the RecipeSource port, and provider failure degrades only that section. The default demonstration adapter calls TheMealDB with its public test key 1 embedded in the URL, so PackyTrace stores no credential for that adapter. The provider permits that key for development or educational use; verify current terms and obtain an appropriate key before a public commercial release (TheMealDB API documentation, verified 2026-08-01).

Edamam is optional. To select it without writing credentials to a file:

cd deployment/aws/terraform
export TF_VAR_recipe_provider="edamam"
export TF_VAR_edamam_app_id="your_app_id"
export TF_VAR_edamam_app_key="your_app_key"
terraform apply

terraform.tfvars is gitignored and may be used instead, but environment variables reduce the risk of persisting the credentials. After the plan is approved, return to the repository root and deploy the updated configuration:

make aws-deploy

Confirm the selected provider inside the running container, then submit a known-product scan. Replace '' with the configured domain:

sudo docker compose -f /opt/packytrace/docker-compose.yml \
  exec passport-service printenv RECIPE_PROVIDER

curl --fail-with-body "https://<domain>/api/v1/scans" \
  -H 'Content-Type: application/json' \
  -H 'X-Visitor-Id: 00000000-0000-4000-8000-000000000001' \
  --data '{"gtin":"07310070017284"}' \
  | jq -e '.recipes.state == "loaded" and (.recipes.data.items | length > 0)'

The first command must print edamam; the second must exit successfully. Current metrics distinguish recipe-section success from failure but do not label the provider, so they are supporting evidence rather than provider proof. Provider quotas, caching terms and credentials must be rechecked before rollout. Quota exhaustion must not fail the complete scan.

Producer catalogs

Producer-owned Brand products are not seeded in Postgres. Migration 0010 removed the former demo Brand rows because the producer APIs are authoritative. The AWS demonstration runs four instances of mock-brand-service: granrolo, muttini, de-cello and fabbrino, and Passport synchronizes their snapshots through BRAND_PROVIDER_URLS.

If the simulators are unavailable, Brand GTINs resolve as unknown while community-source and other application flows continue. The mock-brand-service image is part of the deploy-images.yml matrix. Fixtures are baked into '/fixtures/.json' in that image and selected by BRAND_DATA_FILE; changing a product requires republishing the image and running make aws-deploy. Passport refreshes within BRAND_SYNC_INTERVAL* (30 seconds in this deployment).

On the box, verify all producer containers are running:

sudo docker compose -f /opt/packytrace/docker-compose.yml ps \
  | grep -E 'granrolo|muttini|de-cello|fabbrino'