Verification: AWS Infrastructure for Item Image Upload
Verification criteria for the AWS Infrastructure project. Each criterion maps to a deliverable in specification.md and a success criterion in goal.md. Criteria are grouped by phase (Phase 0: DNS Foundation, Phase 1: Partition Resources).
Phase 0: DNS Foundation
Section titled “Phase 0: DNS Foundation”V-001: Root Zone Deployment
Section titled “V-001: Root Zone Deployment”Deliverable: assets.arda.cards hosted zone in Root Account
(specification.md section 2.4).
Verification steps:
- Run
deploy-root.shagainst the root account. cdk synthfor root configuration includes the newassetsZoneexport.- After deploy, verify the hosted zone exists:
Expected: one zone with
Terminal window aws route53 list-hosted-zones-by-name \--dns-name assets.arda.cards \--max-items 1Name: assets.arda.cards. - Verify the zone ID is exported:
Expected: non-empty zone ID.
Terminal window aws cloudformation list-exports \--query "Exports[?Name=='arda-assets-zone'].Value"
Pass criteria: Zone exists in root account, export is available.
V-002: Infrastructure Subdomain Zone and Certificate
Section titled “V-002: Infrastructure Subdomain Zone and Certificate”Deliverable: <infra>.assets.arda.cards subdomain zone + ACM cert
(specification.md section 2.4).
Verification steps:
- Run
amm.sh <infrastructure> <partition>(e.g.,amm.sh Alpha002 dev). - Verify the subdomain zone exists:
Terminal window aws route53 list-hosted-zones-by-name \--dns-name alpha002.assets.arda.cards \--max-items 1 - Verify NS delegation — the root
assets.arda.cardszone contains NS records for the subdomain:Expected: returns name servers matching the subdomain zone.Terminal window dig NS alpha002.assets.arda.cards - Verify the ACM certificate:
Expected: one certificate with
Terminal window aws acm list-certificates \--query "CertificateSummaryList[?DomainName=='*.alpha002.assets.arda.cards']"Status: ISSUED. - Verify CloudFormation exports include the new assets entries:
Terminal window aws cloudformation list-exports \--query "Exports[?contains(Name, 'AssetsDomainName')]"
Pass criteria: Subdomain zone resolves, NS delegation works, ACM cert
is ISSUED, exports are available.
V-003: CDK Synth Regression
Section titled “V-003: CDK Synth Regression”Deliverable: No regressions to existing stacks.
Verification steps:
- Run
npm run ci-check(synthesizes all infrastructure and partition targets). - All targets produce valid CloudFormation templates.
- No existing exports are removed or renamed.
Pass criteria: ci-check passes with zero errors.
V-004: deploy-root.sh Script
Section titled “V-004: deploy-root.sh Script”Deliverable: deploy-root.sh (specification.md section 2.4).
Verification steps:
- Script exists at
infrastructure/deploy-root.sh. - Script is executable (
chmod +x). - Script bootstraps CDK and deploys
r53-zones.tsto the root account. - Idempotent: running twice produces no errors and no changes on second run.
Pass criteria: Script deploys root configuration successfully.
Phase 1: Partition Resources
Section titled “Phase 1: Partition Resources”V-101: CDK Synth
Section titled “V-101: CDK Synth”Deliverable: All new constructs and stack modifications (specification.md sections 1 and 2).
Maps to: Goal SC-1.
Verification steps:
- Run
npm run ci-check. - Verify the synthesized templates include:
ImageAssetBucketS3 bucket resource with versioning enabled, SSE-S3, RETAIN removal policy.ImageUploadPresigningRoleIAM role withs3:PutObject,s3:GetObject, multipart actions.ImageStorageStackwith CloudFront distribution, OAC, trusted key groups.CloudFrontSigningKeyGroupwith public key and Secrets Manager secret.
- Verify 6 new cross-stack exports are present in the synthesized templates.
Pass criteria: ci-check passes; templates contain all expected
resources and exports.
V-102: Stack Deployment
Section titled “V-102: Stack Deployment”Deliverable: Stacks deploy without errors.
Maps to: Goal SC-2.
Verification steps:
- Run
amm.sh <infrastructure> <partition>against dev environment. - All stacks (including new
ImageStorageStack) deploy successfully. - No rollbacks.
Pass criteria: All stacks reach CREATE_COMPLETE or
UPDATE_COMPLETE.
V-103: Presigning Role Assumption
Section titled “V-103: Presigning Role Assumption”Deliverable: ImageUploadPresigningRole
(specification.md section 1.1).
Maps to: Goal SC-3.
Verification steps:
- From the EKS pod role (or equivalent test credentials), call
sts:AssumeRoleon the presigning role ARN. - Temporary credentials are returned.
Pass criteria: AssumeRole succeeds; credentials are valid.
Automated by: verify-image-cdn.ts step 1.
V-104: S3 Upload via Presigned POST
Section titled “V-104: S3 Upload via Presigned POST”Deliverable: ImageAssetBucket with presigning role
(specification.md section 1.1).
Maps to: Goal SC-4.
Verification steps:
- Using assumed-role credentials, generate a presigned POST form for key
<tenantId>/images/test-<uuid>.jpg. - POST a test JPEG to S3 using the presigned form fields.
HeadObjecton the uploaded key returns metadata matching the policy conditions (x-amz-meta-tenant-id,Content-Type: image/jpeg, SSE-S3).
Pass criteria: Upload succeeds (HTTP 204); HeadObject confirms object exists with correct metadata.
Automated by: verify-image-cdn.ts steps 2-4.
V-105: CloudFront Unauthenticated Rejection
Section titled “V-105: CloudFront Unauthenticated Rejection”Deliverable: ImageAssetCdn with trusted key groups
(specification.md section 1.2).
Maps to: Goal SC-5.
Verification steps:
- GET the uploaded image URL from CloudFront without any cookies.
- Response is HTTP 403 Forbidden.
Pass criteria: Unauthenticated request returns 403.
Automated by: verify-image-cdn.ts step 5.
V-106: CloudFront Signed Cookie Access
Section titled “V-106: CloudFront Signed Cookie Access”Deliverable: CloudFrontSigningKeyGroup + ImageAssetCdn
(specification.md sections 1.2 and 1.3).
Maps to: Goal SC-6.
Verification steps:
- Retrieve the signing private key from Secrets Manager.
- Generate CloudFront signed cookies with a custom policy scoped to
https://<cdn-domain>/<tenantId>/*. - GET the uploaded image URL with the three signed cookies
(
CloudFront-Policy,CloudFront-Signature,CloudFront-Key-Pair-Id). - Response is HTTP 200 with image content.
Pass criteria: Authenticated request with valid cookies returns 200.
Automated by: verify-image-cdn.ts steps 6-8.
V-107: Tenant Isolation
Section titled “V-107: Tenant Isolation”Deliverable: Signed cookie tenant scoping (specification.md section 1.2).
Maps to: Goal SC-7.
Verification steps:
- Generate signed cookies scoped to a different tenant ID (Tenant B).
- GET the original image (uploaded under Tenant A) with Tenant B’s cookies.
- Response is HTTP 403 Forbidden.
Pass criteria: Wrong-tenant cookies are rejected.
Automated by: verify-image-cdn.ts steps 9-10.
V-108: Verification Script
Section titled “V-108: Verification Script”Deliverable: tools/verify-image-cdn.ts
(specification.md section 3).
Maps to: Goal SC-8.
Verification steps:
- Script exists and compiles (
npx ts-node tools/verify-image-cdn.ts --help). - Run the script with valid parameters against the deployed dev environment.
- All steps (V-103 through V-107) pass.
- Test object is cleaned up from S3 after the run.
Pass criteria: Script exits with code 0; no test artifacts remain.
V-109: Partition Integration
Section titled “V-109: Partition Integration”Deliverable: partition.ts wiring
(specification.md section 2.3).
Verification steps:
- Deploy a second partition in the same infrastructure (e.g.,
stageafterdev). - The new partition receives its own image bucket, CDN distribution, presigning role, and signing key group.
- CDN domains are distinct per partition
(
dev.<infra>.assets.arda.cardsvs.stage.<infra>.assets.arda.cards). - S3 bucket names are distinct per partition.
Pass criteria: Multiple partitions coexist with independent image infrastructure.
V-110: No Regressions
Section titled “V-110: No Regressions”Deliverable: Existing stacks unaffected.
Verification steps:
- After deploying Phase 1, verify existing resources are unchanged:
- Upload bucket (CSV) still works.
- API Gateway still serves requests.
- Cognito authentication still works.
- Aurora database still accessible.
- All existing CloudFormation exports are present and unchanged.
Pass criteria: No existing functionality is broken.
V-111: Unit Tests Pass
Section titled “V-111: Unit Tests Pass”Deliverable: Test infrastructure and construct tests (specification.md section 5).
Verification steps:
npm testruns successfully.- Unit tests for
ImageAssetBucketverify: naming, versioning, RETAIN policy, SSE-S3, BlockPublicAccess, no expiration lifecycle, CORS POST-only, presigning role conditions, validation. - Unit tests for
ImageAssetCdnverify: OAC origin, HTTPS-only, GET/HEAD only, CachingOptimized, PriceClass_100, trusted key groups, custom domain, Route53 record, validation. - Unit tests for
CloudFrontSigningKeyGroupverify: public key, key group, Secrets Manager secret, RETAIN policies. - Snapshot tests for
ImageStorageStackcapture the full template with all 6 exports.
Pass criteria: npm test exits with code 0; all assertions pass.
V-112: cdk-nag Compliance
Section titled “V-112: cdk-nag Compliance”Deliverable: AwsSolutions compliance (specification.md section 5).
Verification steps:
cdk synthwithAwsSolutionsChecksaspect applied.- No unsuppressed findings for new constructs.
- All suppressions have documented reasons.
Pass criteria: Synth succeeds; no unaddressed cdk-nag findings.
V-113: CI Gates PRs with Tests
Section titled “V-113: CI Gates PRs with Tests”Deliverable: .github/workflows/ci.yaml updated
(specification.md section 5).
Verification steps:
- Open a PR in the
infrastructurerepo with a deliberate test failure (e.g., wrong bucket name assertion). - The
buildjob inci.yamlrunsnpm testand fails. - PR cannot merge while the
buildjob is failing. - Fix the test, push —
buildjob passes, PR is mergeable.
Pass criteria: npm test is a required step in the build job; a
failing test blocks PR merge.
Verification Summary
Section titled “Verification Summary”| ID | Phase | Criterion | Automated | Goal SC |
|---|---|---|---|---|
| V-001 | 0 | Root zone deployment | Manual | — |
| V-002 | 0 | Infra subdomain zone + cert | Manual | — |
| V-003 | 0 | CDK synth regression | ci-check | — |
| V-004 | 0 | deploy-root.sh script | Manual | — |
| V-101 | 1 | CDK synth | ci-check | SC-1 |
| V-102 | 1 | Stack deployment | amm.sh | SC-2 |
| V-103 | 1 | Presigning role assumption | verify-image-cdn.ts | SC-3 |
| V-104 | 1 | S3 upload via presigned POST | verify-image-cdn.ts | SC-4 |
| V-105 | 1 | CloudFront unauthenticated rejection | verify-image-cdn.ts | SC-5 |
| V-106 | 1 | CloudFront signed cookie access | verify-image-cdn.ts | SC-6 |
| V-107 | 1 | Tenant isolation | verify-image-cdn.ts | SC-7 |
| V-108 | 1 | Verification script | Manual + script | SC-8 |
| V-109 | 1 | Partition integration | Manual | — |
| V-110 | 1 | No regressions | ci-check + manual | — |
| V-111 | 1 | Unit tests pass | npm test | — |
| V-112 | 1 | cdk-nag compliance | cdk synth | — |
| V-113 | 1 | CI gates PRs with tests | ci.yaml | — |
Copyright: (c) Arda Systems 2025-2026, All rights reserved
Copyright: © Arda Systems 2025-2026, All rights reserved