# Exercise 2: Design the CloudFront Distribution for a SPA + API

`ShopCo` serves:

- a React SPA (`index.html` + hashed assets in `/assets/*`) from an S3 bucket,
- product images in `/images/*` (S3, rarely change, overwritten in place when a merchant updates a photo),
- a JSON API at `/api/*` behind the ALB from Exercise 1. Some API GETs are public and cacheable (`/api/v1/catalog/*`, varies by `?page=` and `Accept-Language`); everything else is per-user (`Authorization: Bearer …`) and must never be cached.

## Deliverables

1. **Behaviors table**: path pattern | origin | allowed methods | cache key (headers/cookies/query strings) | TTLs | viewer protocol | origin request policy. Cover `/assets/*`, `/images/*`, `/api/v1/catalog/*`, `/api/*`, and the default `/*` (SPA fallback).
2. **S3 access**: configure OAC and write the bucket policy statement allowing only this distribution to `s3:GetObject`.
3. **ALB lockdown**: describe the two mechanisms that make the ALB reject traffic not coming through CloudFront.
4. **SPA routing**: how deep links like `/orders/42` serve `index.html` without breaking real 404s for missing assets.
5. **Invalidation plan**: what you invalidate on each frontend deploy, and how image updates (overwritten in place) become visible quickly. Propose a better naming scheme.
6. **Security**: where WAF attaches, and which managed rule groups/rate limits you'd enable for `/api/*`.

## Requirements Checklist

- [ ] `/assets/*` cached ~1 year (immutable, hashed names), no cookies/headers in the key; `/` and `index.html` short TTL or no-cache.
- [ ] `/api/*` uses `CachingDisabled` and forwards `Authorization`, query strings and needed headers via an origin request policy; `/api/v1/catalog/*` caches with key = path + `page` + `Accept-Language` only — never `Authorization`.
- [ ] Bucket policy grants `s3:GetObject` to `cloudfront.amazonaws.com` with a `AWS:SourceArn` condition for the distribution; the bucket blocks public access.
- [ ] ALB SG allows only the CloudFront origin-facing managed prefix list, plus a secret custom origin header checked by an ALB rule.
- [ ] SPA fallback via a CloudFront Function (rewrite extension-less paths to `/index.html`) rather than converting all 403/404 to 200.
- [ ] Images: versioned keys (content hash or version in the path) instead of in-place overwrites; otherwise targeted invalidations.
- [ ] WAF on the distribution with AWS managed rule groups (common, known bad inputs, IP reputation) and a rate-based rule on `/api/*`.
