Skip to content

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.

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.

infrastructure (Arda-cards/infrastructure)

DNS and Certificate Foundation (PD-02):

  • assets.arda.cards hosted zone in the Root Account — new parent zone for static asset delivery, alongside the existing io, app, and auth zones in RootConfigurationStack.
  • <infra>.assets.arda.cards subdomain zone per infrastructure account — subdomain zone with NS delegation to the root zone and a wildcard ACM certificate (*.<infra>.assets.arda.cards), added to InfrastructureIngress.
  • deploy-root.sh script — minimal root account deployment automation (PD-03).

Partition-Level Constructs:

  • ImageAssetBucket CDK construct — persistent S3 bucket with versioning, SSE-S3 encryption, CORS configuration for browser uploads, lifecycle rule to abort incomplete multipart uploads after 1 day, RETAIN removal policy, and an embedded presigning IAM role for presigned POST form generation (s3:PutObject + s3:GetObject, HTTPS required, SSE-S3 required). Follows the UploadBucket pattern where the presigning role is part of the bucket construct.
  • ImageAssetCdn CDK construct — CloudFront distribution with OAC origin to the image asset bucket, custom domain (<partition>.<infra>.assets.arda.cards), HTTPS-only, PriceClass_100, CachingOptimized policy, trusted key groups for signed cookie validation.
  • CloudFrontSigningKeyGroup CDK 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 integrationImageAssetBucket, ImageAssetCdn, and CloudFrontSigningKeyGroup co-located in a new ImageStorageStack (PD-01, PD-04). BulkStoresStack is unchanged.
  • Verification scriptinfrastructure/tools/verify-image-cdn.ts that 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.
  • 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.yml IAM additions) — Phase 2b, when the backend imports infrastructure exports.
  • CI/CD automation for root account (GitHub Actions OIDC role for root) — separate infrastructure concern.
  1. 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 through amm.sh. The bucket, CDN distribution, and signing key group are co-located in the new ImageStorageStack (PD-04). BulkStoresStack is unchanged. A partition deployed without image storage resources is incomplete.
  2. Pattern alignment: Follow the existing UploadBucket / UploadPreSigningRole patterns for naming, parameterization, and IAM policy structure. Deviate only where the specification requires it (e.g., persistent storage, versioning, OAC).
  3. No public access: The S3 bucket must block all public access. Only CloudFront (via OAC) and the presigning role have access.
  4. 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.
  5. 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.
  6. CDK synth must succeed without deployment: Phase 2a (common-module) can start as soon as cdk synth produces valid templates — it only needs the key format and CDN domain pattern, not live infrastructure.
#DeliverableLocation
1assets.arda.cards root hosted zonestacks/root/root-configuration-stack.ts (modify)
2<infra>.assets.arda.cards subdomain zone + ACM certstacks/infrastructure/ingress-stack.ts (modify)
3Import assets zone + cert in ImportingStackapps/Al1x/util.ts (modify)
4deploy-root.sh scriptinfrastructure/deploy-root.sh (new)
5ImageAssetBucket construct (includes presigning role)constructs/storage/image-asset-bucket.ts (new)
6ImageAssetCdn constructconstructs/xgress/image-asset-cdn.ts (new)
7CloudFrontSigningKeyGroup constructconstructs/xgress/cloudfront-signing-key-group.ts (new)
8ImageStorageStack (bucket + CDN + signing keys)stacks/purpose/image-storage.ts (new)
9Partition wiringapps/Al1x/partition.ts (modify)
10Assets domain conventionplatform/ari-configuration.ts (modify)
11Cross-stack exports (6 partition values)Within stack files
12Verification scripttools/verify-image-cdn.ts (new)
  1. cdk synth produces valid CloudFormation templates with all 3 constructs and 6 cross-stack exports.
  2. Stack deploys to dev environment without errors.
  3. Presigning role can be assumed via sts:AssumeRole.
  4. Test image uploaded to S3 via presigned POST and verified via HeadObject.
  5. CloudFront rejects unauthenticated requests with 403.
  6. Signed cookies (generated from the private key in Secrets Manager) grant CDN access to the uploaded image.
  7. Signed cookies scoped to Tenant A do not grant access to Tenant B’s path prefix (tenant isolation verified).
  8. verify-image-cdn.ts script executes criteria 3-7 automatically and passes.

Copyright: (c) Arda Systems 2025-2026, All rights reserved