{
  "schema_version": "1.0.0",
  "id": "aws-retail-store",
  "title": "AWS Retail Store Sample App",
  "summary": "A five-service retail application on Amazon ECS: Aurora, DynamoDB, OpenSearch, ElastiCache and Amazon MQ behind an Application Load Balancer. StackToIT read the ECS Terraform estate and wrote a STACKIT migration package.",
  "source": {
    "cloud": "AWS",
    "iac": "Terraform (OpenTofu-readable)",
    "project_name": "retail-store-sample-app",
    "maintainer": "AWS Containers (aws-containers)",
    "repository_url": "https://github.com/aws-containers/retail-store-sample-app",
    "commit": "d7a380b843e0759e58754f74188ea18252a51415",
    "commit_url": "https://github.com/aws-containers/retail-store-sample-app/tree/d7a380b843e0759e58754f74188ea18252a51415",
    "terraform_root": "terraform/ecs/default",
    "terraform_root_url": "https://github.com/aws-containers/retail-store-sample-app/tree/d7a380b843e0759e58754f74188ea18252a51415/terraform/ecs/default",
    "license": "MIT-0 (upstream LICENSE)",
    "registry_modules": "13 registry modules resolved by OpenTofu on 2026-10-26 (terraform-aws-modules, cloudposse)",
    "note": "The estate was assessed exactly as published upstream: nothing in it was edited. It ships no .terraform.lock.hcl. Because of that the source provider is UNPINNED and the OpenTofu validation of the source did not run, even with a provider mirror prepared beforehand: StackToIT validates a source only against the provider versions its lock file records, and will not pick one for it.",
    "description": "The retail-store-sample-app by AWS Containers is a sample retail application: five services (ui, catalog, carts, checkout, orders) on Amazon ECS behind an Application Load Balancer, with Aurora (catalog, orders), DynamoDB (carts), OpenSearch (catalog), ElastiCache (checkout) and Amazon MQ as managed dependencies in one VPC. The estate assessed is its terraform/ecs/default root module and the local terraform/lib modules it calls.",
    "attribution": "The source estate is the retail-store-sample-app published by AWS under MIT-0."
  },
  "target": {
    "cloud": "STACKIT",
    "provider": "stackitcloud/stackit 0.121.0"
  },
  "tool": {
    "name": "StackToIT",
    "version": "0.6.0-11562-g1966ddf116",
    "commit": "1966ddf116",
    "kb_version": "0.384.0",
    "kb_sha256": "fc24dfbd7370bd23bbae090adf2960acf5d9b4ac749be7362ac50053ceddc6d9",
    "assessment_schema": "0.24.0",
    "manifest_version": "0.4.0",
    "opentofu": "1.13.1"
  },
  "run": {
    "run_id": "f6267c3f-2848-4aa5-89df-5fee8b15b3b9",
    "generated_at": "2026-11-02T12:08:24Z",
    "date": "2026-11-02",
    "mode": "online (default options; a local OpenTofu provider mirror with hashicorp/aws 5.100.0 was prepared beforehand as the console suggests; prices from the local price cache retrieved 2026-10-26)",
    "command": "stacktoit assess terraform/ecs/default ./aws-retail-store --provider-mirror /path/to/mirror",
    "command_note": "Run from the vendored copy of the upstream repository. A local OpenTofu provider mirror (hashicorp/aws 5.100.0, the version the constraints resolve to) was prepared first with `tofu providers mirror`, as the first run's console suggested; the source validation still did not run because the source has no lock file. The output directory is this example's output/ folder, unchanged.",
    "verify_command": "stacktoit verify ./aws-retail-store",
    "verify_result": "VERIFIED — 143 files match manifest.json (size and SHA-256); 7 of 7 checks PASS",
    "source_digest": "sha256:812c5ae3f6cc8530163abbf5b6fbe305ed3b363c4886ec6b87623db857ea0c70"
  },
  "metrics": {
    "files_read": 105,
    "resources": 282,
    "units": 44,
    "plan_time_units": 8,
    "module_calls": 23,
    "module_calls_external": 13,
    "module_calls_local": 10,
    "source_status": "RUNTIME_TOPOLOGY_PARTIAL",
    "source_visibility": "Partial runtime topology — 8 units have a count/for_each decided only when OpenTofu plans",
    "by_class": {
      "DIRECT": 0,
      "RECONFIGURE": 34,
      "REPLATFORM": 9,
      "CONTAINERIZE": 0,
      "REDESIGN": 1,
      "MANUAL_REVIEW": 0,
      "BLOCKED": 0
    },
    "by_confidence": {
      "HIGH": 0,
      "MEDIUM": 35,
      "LOW": 9
    },
    "by_domain": {
      "network": 16,
      "identity": 15,
      "compute": 6,
      "data": 5,
      "observability": 1,
      "messaging": 1
    },
    "draft": {
      "units_considered": 52,
      "generated": 38,
      "no_resource_needed": 11,
      "manual": 3,
      "variables": 60,
      "terraform_only": 34,
      "hybrid": 4
    },
    "execution": {
      "package_state": "PARTIALLY_EXECUTABLE",
      "package_state_words": "Partially executable migration package",
      "plan_steps": 314,
      "automated_steps": 57,
      "automated_can_run_now": 48,
      "automated_wait_manual_prerequisite": 1,
      "automated_require_design_decision": 8,
      "automated_on_unconfirmed_default": 9,
      "automated_approved": 0,
      "terraform_steps": 49,
      "api_steps": 4,
      "api_steps_waiting_opt_in": 4,
      "manual_steps": 254,
      "manual_can_start_now": 114,
      "lifecycle_steps": 84,
      "refused_steps": 3,
      "steps_not_runnable_now": 147
    },
    "readiness": {
      "migration_ready": "NO",
      "approval": "NOT READY FOR APPROVAL",
      "automation_eligible_units": 0,
      "automation_eligible_after_open_items": 17,
      "cannot_be_automated_in_this_build": 27,
      "critical_settings_total": 319,
      "critical_settings_resolved": 36,
      "mapping_confidence_high": 0,
      "live_verification": "Never applied to STACKIT — no plan was run against a live project"
    },
    "decisions": {
      "records_open": 113,
      "decisions_to_make": 16,
      "defaults_to_confirm": 8,
      "defaults_to_confirm_note": "8 unanswered decisions rest on a draft default (public endpoint 5, size derived from the source 3); the register groups them in 2 records",
      "open_input_requests": 47,
      "input_requests_blocking_draft": 14,
      "first_required_action": "Allow the calls of STACKIT APIs that are not generally available (Secrets Manager v1) — Owner: Platform Architect"
    },
    "applications": {
      "total": 5,
      "ready": 0,
      "blocked": 1,
      "redesign": 2,
      "not_ready": 2,
      "list": [
        {
          "name": "carts",
          "state": "REDESIGN",
          "why": "DynamoDB table is a REDESIGN (MongoDB Flex, data-model change)"
        },
        {
          "name": "catalog",
          "state": "BLOCKED",
          "why": "OpenSearch engine downgrade 3.3 → 2 until tested or decided"
        },
        {
          "name": "checkout",
          "state": "REDESIGN",
          "why": "shares the DynamoDB redesign; TLS-only Valkey endpoint for ElastiCache clients"
        },
        {
          "name": "orders",
          "state": "NOT_READY",
          "why": "environment values required; workload identity undecided"
        },
        {
          "name": "ui",
          "state": "NOT_READY",
          "why": "workload identity undecided; functional check not run"
        }
      ]
    },
    "cost": {
      "comparison": "NOT AVAILABLE",
      "why": "Source region unknown (30 AWS lines wait for source.aws.region); 9 of 14 STACKIT lines have no price; 10 billable source resources are outside the model.",
      "stackit_partial_eur": "878.34",
      "stackit_lines_priced": "5 of 14",
      "source_lines_priced": "0 of 30",
      "price_source": "StackToIT price cache (STACKIT list prices retrieved 2026-10-26); AWS prices not fetched because the region is not stated in the source"
    },
    "validation": {
      "source_completeness": {
        "state": "PARTIAL",
        "detail": "source status RUNTIME_TOPOLOGY_PARTIAL: 8 unit(s) have a count/for_each that is not known statically; whether and how often they exist is decided at plan time"
      },
      "source_provider": {
        "state": "UNPINNED",
        "detail": "aws constraints ~> 5.0, tested against 5.100.0; No lock file entry pins this provider, so the version a plan would use is not proven; the knowledge base was checked against one version only. Until the exact version is pinned (commit .terraform.lock.hcl), the units of this provider are capped at MEDIUM confidence and are not automation eligible."
      },
      "source_opentofu": {
        "state": "NOT_RUN",
        "reason": "LOCK_FILE — the source has no dependency lock file (.terraform.lock.hcl), so provider identity and integrity cannot be verified; the validation never updates it (Provider dependency changes detected). No validation result exists; this is neither a pass nor a failure of the source."
      },
      "draft_generation": {
        "state": "GENERATED",
        "detail": "the draft is in terraform/"
      },
      "draft_checks": {
        "state": "PASSED",
        "detail": "100 checks, none found a violation"
      },
      "global_invariants": {
        "state": "PASSED",
        "detail": "12 of 12 invariants PASS"
      },
      "draft_opentofu": {
        "state": "PASSED",
        "detail": "tofu init -backend=false and tofu validate accepted the draft; tofu 1.13.1 — static validation of the draft against the pinned provider schema — not target behaviour, not approval"
      },
      "manifest": {
        "state": "VERIFIED",
        "detail": "143 files match manifest.json; EVIDENCE, SCHEMA, RUN_ID, BASIS, INPUTS_DIGEST, INVALIDATION_KEYS, EXECUTION_PLAN PASS"
      },
      "not_established": [
        {
          "id": "STACKIT_PLAN",
          "state": "NOT_RUN",
          "detail": "this build runs no plan against a STACKIT project"
        },
        {
          "id": "ARCHITECT_APPROVAL",
          "state": "NOT_PROVIDED",
          "detail": "no review decision is recorded for this run"
        },
        {
          "id": "SEMANTIC_EQUIVALENCE",
          "state": "NOT_ASSESSED",
          "detail": "this build has no measure for it"
        },
        {
          "id": "SAFE_TO_APPLY",
          "state": "NOT_ASSERTED",
          "detail": "StackToIT never asserts it"
        }
      ]
    },
    "confidence_note": "capped at MEDIUM: the source provider is unpinned"
  },
  "key_findings": [
    {
      "title": "Nothing is DIRECT",
      "text": "All 44 present units need at least a reconfiguration: 34 RECONFIGURE, 9 REPLATFORM (ECS → SKE, Aurora → MariaDB/PostgreSQL Flex, OpenSearch), 1 REDESIGN (DynamoDB has no STACKIT counterpart; MongoDB Flex or PostgreSQL JSONB are the named options)."
    },
    {
      "title": "The source provider is unpinned, so the source was not validated",
      "text": "The upstream estate commits no .terraform.lock.hcl. StackToIT caps every unit at MEDIUM confidence, marks none automation-eligible, and does not run OpenTofu validation on the source, with or without a provider mirror, because no lock file states which provider version to validate against. It names the two remedies (commit a lock file with aws 5.100.0, or raise the constraint to ~> 6.0 and lock 6.67.0); only a lock file and a source validation show that either works."
    },
    {
      "title": "Catalog is deployment-blocked",
      "text": "The catalog service depends on OpenSearch 3.3; the STACKIT region offers version 2. The draft stays blocked until a test shows the application works on that version or an architecture decision is recorded."
    },
    {
      "title": "Four STACKIT API steps wait for an opt-in",
      "text": "Secrets Manager steps call a pre-release STACKIT API. The plan does not make the calls until the customer allows them in the decisions file; this is the first required action of the run."
    },
    {
      "title": "No cost comparison is stated",
      "text": "The source does not name its AWS region, so no AWS price was fetched. 5 of 14 STACKIT lines are priced (878.34 EUR partial, list prices); the report refuses to call a one-sided subtotal a saving."
    }
  ],
  "report": {
    "entry": "index.html",
    "architecture_dir": "architecture",
    "terraform_dir": "terraform",
    "executive_brief": "executive/brief.md",
    "decisions": "executive/decisions.md",
    "execution_plan": "execution/README.md",
    "manual_actions": "execution/manual/actions.md",
    "roadmap": "migration/roadmap.md",
    "data_movement": "migration/data-movement.md",
    "manifest": "manifest.json",
    "console": "console.txt"
  },
  "publication": {
    "published_files": 147,
    "manifest_files": 142,
    "outside_manifest": [
      "manifest.json",
      "review/applications.yaml",
      "review/decisions.yaml",
      "review/inputs.yaml",
      "review/progress.yaml"
    ],
    "outside_manifest_note": "review/ is the customer's answer area the run writes beside its files; it is excluded from the manifest by design. manifest.json lists every other file.",
    "excluded": [],
    "modified": [],
    "statement": "The output folder is published exactly as StackToIT wrote it. No file was removed, edited or redacted; stacktoit verify passes on the published copy."
  },
  "case_study": {
    "lede": "Explore how StackToIT analyzed the AWS Retail Store Sample App and generated a structured migration assessment, proposed STACKIT infrastructure, architecture diagrams and a detailed migration plan."
  }
}
