Goal: AWS Infrastructure for Item Image Upload
Provision the AWS resources that support image storage and CDN delivery for the Item Image Upload feature. This is Phase 1 of the implementation phasing — it has no upstream dependencies and produces the foundation that all subsequent phases (backend, BFF, SPA) build on.
Context
Section titled “Context”The Item Image Upload project has completed system design. The
AWS specification defines the
specific S3 bucket, CloudFront distribution, IAM roles, and signing key
infrastructure required. The design
describes how the Storage sub-system fits into the overall architecture. This
project implements that specification as CDK constructs in the infrastructure
repository.
The infrastructure repository already contains a similar pattern: the
UploadBucket construct and UploadPreSigningRole in
public-upload-bucket.ts provide ephemeral S3 storage for CSV uploads with
presigned PUT credentials. This project follows the same structural patterns
but differs in key ways: persistent storage (no TTL expiration), versioning
enabled, CloudFront CDN with OAC origin access, and signed cookie access
control for tenant-isolated image delivery.
Repository
Section titled “Repository”infrastructure (Arda-cards/infrastructure)
In Scope
Section titled “In Scope”DNS and Certificate Foundation (PD-02):
assets.arda.cardshosted zone in the Root Account — new parent zone for static asset delivery, alongside the existingio,app, andauthzones inRootConfigurationStack.<infra>.assets.arda.cardssubdomain zone per infrastructure account — subdomain zone with NS delegation to the root zone and a wildcard ACM certificate (*.<infra>.assets.arda.cards), added toInfrastructureIngress.deploy-root.shscript — minimal root account deployment automation (PD-03).
Partition-Level Constructs:
ImageAssetBucketCDK construct — persistent S3 bucket with versioning, SSE-S3 encryption, CORS configuration for browser uploads, lifecycle rule to abort incomplete multipart uploads after 1 day,RETAINremoval policy, and an embedded presigning IAM role for presigned POST form generation (s3:PutObject+s3:GetObject, HTTPS required, SSE-S3 required). Follows theUploadBucketpattern where the presigning role is part of the bucket construct.ImageAssetCdnCDK construct — CloudFront distribution with OAC origin to the image asset bucket, custom domain (<partition>.<infra>.assets.arda.cards), HTTPS-only,PriceClass_100,CachingOptimizedpolicy, trusted key groups for signed cookie validation.CloudFrontSigningKeyGroupCDK construct — RSA key pair generation, public key uploaded to CloudFront trusted key group, private key stored in Secrets Manager for BFF consumption. Supports multiple active keys for zero-downtime rotation.- Cross-stack exports (6 values):
${Infra}-${Purpose}-API-ImageAssetBucketArn${Infra}-${Purpose}-API-ImageAssetBucketName${Infra}-${Purpose}-API-ImagePresignRoleArn${Infra}-${Purpose}-API-ImageCdnDomain${Infra}-${Purpose}-API-ImageCdnSigningKeyId${Infra}-${Purpose}-API-ImageCdnSigningKeySecretArn
- Stack integration —
ImageAssetBucket,ImageAssetCdn, andCloudFrontSigningKeyGroupco-located in a newImageStorageStack(PD-01, PD-04).BulkStoresStackis unchanged. - Verification script —
infrastructure/tools/verify-image-cdn.tsthat validates the deployed infrastructure end-to-end: assume presigning role, upload test JPEG, verify CloudFront 403 without cookies, verify 200 with correctly scoped signed cookies, verify tenant isolation, and clean up.
Out of Scope
Section titled “Out of Scope”- Backend code (
common-module,operations) — Phase 2. - BFF routes and cookie signing logic — Phase 3.
- SPA components and upload orchestration — Phase 4.
- Operations CloudFormation changes (
pre-install.cfn.ymlIAM additions) — Phase 2b, when the backend imports infrastructure exports. - CI/CD automation for root account (GitHub Actions OIDC role for root) — separate infrastructure concern.
Constraints
Section titled “Constraints”- Partition integration: The new constructs must be wired into the
partition composition (
apps/Al1x/partition.ts) so that every partition receives image storage and CDN resources when deployed throughamm.sh. The bucket, CDN distribution, and signing key group are co-located in the newImageStorageStack(PD-04).BulkStoresStackis unchanged. A partition deployed without image storage resources is incomplete. - Pattern alignment: Follow the existing
UploadBucket/UploadPreSigningRolepatterns for naming, parameterization, and IAM policy structure. Deviate only where the specification requires it (e.g., persistent storage, versioning, OAC). - No public access: The S3 bucket must block all public access. Only CloudFront (via OAC) and the presigning role have access.
- Tenant isolation at CDN layer: CloudFront signed cookies must scope
access to a single tenant’s key prefix (
/<tenantId>/*). This is the primary security boundary for image access. - Secrets Manager for private key: The CloudFront signing private key must be stored in Secrets Manager, not in environment variables or SSM Parameter Store. The BFF retrieves it at runtime.
- CDK synth must succeed without deployment: Phase 2a (common-module) can
start as soon as
cdk synthproduces valid templates — it only needs the key format and CDN domain pattern, not live infrastructure.
Deliverables
Section titled “Deliverables”| # | Deliverable | Location |
|---|---|---|
| 1 | assets.arda.cards root hosted zone | stacks/root/root-configuration-stack.ts (modify) |
| 2 | <infra>.assets.arda.cards subdomain zone + ACM cert | stacks/infrastructure/ingress-stack.ts (modify) |
| 3 | Import assets zone + cert in ImportingStack | apps/Al1x/util.ts (modify) |
| 4 | deploy-root.sh script | infrastructure/deploy-root.sh (new) |
| 5 | ImageAssetBucket construct (includes presigning role) | constructs/storage/image-asset-bucket.ts (new) |
| 6 | ImageAssetCdn construct | constructs/xgress/image-asset-cdn.ts (new) |
| 7 | CloudFrontSigningKeyGroup construct | constructs/xgress/cloudfront-signing-key-group.ts (new) |
| 8 | ImageStorageStack (bucket + CDN + signing keys) | stacks/purpose/image-storage.ts (new) |
| 9 | Partition wiring | apps/Al1x/partition.ts (modify) |
| 10 | Assets domain convention | platform/ari-configuration.ts (modify) |
| 11 | Cross-stack exports (6 partition values) | Within stack files |
| 12 | Verification script | tools/verify-image-cdn.ts (new) |
Success Criteria
Section titled “Success Criteria”cdk synthproduces valid CloudFormation templates with all 3 constructs and 6 cross-stack exports.- Stack deploys to dev environment without errors.
- Presigning role can be assumed via
sts:AssumeRole. - Test image uploaded to S3 via presigned POST and verified via
HeadObject. - CloudFront rejects unauthenticated requests with 403.
- Signed cookies (generated from the private key in Secrets Manager) grant CDN access to the uploaded image.
- Signed cookies scoped to Tenant A do not grant access to Tenant B’s path prefix (tenant isolation verified).
verify-image-cdn.tsscript executes criteria 3-7 automatically and passes.
Reference Documents
Section titled “Reference Documents”- AWS Specification — primary specification for this project
- System Design — structural overview of all sub-systems
- Phasing — Phase 1 definition, entry and exit criteria
- CDN Access Control — signed cookie design and tenant isolation model
- Requirements — FR and NFR traceability
- Project Decision Log — TD-06 (direct transfer), TD-07 (black box abstraction), TD-08 (presigned POST), TD-11 (signed cookies)
Copyright: (c) Arda Systems 2025-2026, All rights reserved
Copyright: © Arda Systems 2025-2026, All rights reserved