SmartStore AI — Phase 12 Implementation Guide
Production Hardening & AWS
What got built
backend/app/secrets_aws.py — Secrets Manager integration
backend/tests/test_secrets_aws.py
infra/ecs-task-definition.json — ECS Fargate task definition, secrets wired via Secrets Manager
Key design decisions
Tested against moto's mocked AWS, not a hand-rolled fake boto3 client. Every other phase's tests inject a fake client matching some SDK's shape by hand. For AWS specifically, moto provides an actual simulated backend that real boto3 code talks to over its real request/response machinery — test_get_secret_retrieves_real_value_from_mocked_aws is a genuine boto3 create_secret + get_secret_value round-trip, not an assertion about what a hand-written fake returns. This is meaningfully more trustworthy for AWS-specific code, where the SDK's actual request signing/serialization behavior is exactly the kind of thing worth not having to assume.
load_secrets_into_environment sets real environment variables, then app.config.Settings() picks them up exactly like a local .env file. This is the actual point of Volume 4, Chapter 5: application code (config.py) never needs to know or care whether a value came from a .env file or AWS Secrets Manager — that distinction lives entirely in a startup script, called once before the app initializes.
The ECS task definition references individual JSON keys within ONE secret (smartstore-ai/production:DATABASE_URL:: syntax), not six separate secrets. This matches a single secret holding the whole .env-equivalent payload as JSON, consistent with how secrets_aws.py reads it — six separate AWS secrets would work too, but would mean six separate places to rotate and manage instead of one.
Verified test results
tests/test_secrets_aws.py::test_get_secret_retrieves_real_value_from_mocked_aws PASSED
tests/test_secrets_aws.py::test_load_secrets_into_environment_sets_real_env_vars PASSED
tests/test_secrets_aws.py::test_get_secret_raises_clear_error_for_missing_secret PASSED
ecs-task-definition.json: valid JSON, all 6 secrets correctly wired (verified by parsing it directly)
Full suite: 42 passed
Honest limitation
No real AWS account exists in this sandbox — RDS, ElastiCache, ECS Fargate, the actual IAM roles referenced in the task definition (ACCOUNT_ID is a placeholder), and an actual deployed container were not, and could not be, created or tested here. What was verified: the Secrets Manager integration code's actual logic (via moto), and that the task definition JSON is syntactically valid and internally consistent (the same secret name format secrets_aws.py expects).
Setting this up for real
- Create the secret:
aws secretsmanager create-secret --name smartstore-ai/production --secret-string file://prod-secrets.json - Create an RDS Postgres instance, an ElastiCache Redis instance, and run Phase 1's migrations plus Phase 6's
smartstore_approle setup against RDS - Push the backend Docker image to ECR
- Create the IAM execution/task roles referenced in
ecs-task-definition.json, scoped to read only the one secret (Volume 4, Ch.5's least-privilege principle) - Register the task definition and create an ECS Fargate service behind an Application Load Balancer
What's next
Phase 13 — Launch, Governance & Iteration closes the loop: governance documentation, the PostHog review process, and continuous evaluation running against real production traffic.