# Test — Production Image, nginx Routes & Edge-host RAM

**Task**: AZ-480_test_prod_image_nginx_ram
**Name**: nginx:alpine no-Node + 500M cap + 9 routes + prefix-strip + edge-host RAM
**Description**: Implement the 5 blackbox tests pinning the production container surface: nginx:alpine image with no Node runtime (NFT-RES-LIM-03), `client_max_body_size 500M` (NFT-RES-LIM-02), exactly 9 location blocks for the suite services (NFT-RES-LIM-09), each route strips its `/api/<service>/` prefix (NFT-RES-LIM-10), and steady-state RAM on the edge image (NFT-RES-LIM-08).
**Complexity**: 3 points
**Dependencies**: AZ-456_test_infrastructure
**Component**: 00_foundation (build + image) (Blackbox Tests)
**Tracker**: AZ-480
**Epic**: AZ-455

## Problem

The production image MUST be `nginx:alpine` (no Node — defence against "I'll just add a tiny Node helper" regressions), enforce a 500 MB body cap (matches NFT-PERF / upload cap), expose exactly 9 nginx routes (one per suite service), strip the route prefix (so upstream services see the canonical path), and keep RAM bounded at steady state. These are five contract pins on the runtime surface that have no source-code home — they live in the image / nginx config and CI build.

## Outcome

- 5 scenarios pass.

## Scope

### Included

| Scenario | Profile | Source file |
|----------|---------|-------------|
| NFT-RES-LIM-02 — nginx `client_max_body_size 500M` | static | resource-limit-tests.md |
| NFT-RES-LIM-03 — Production image is `nginx:alpine` and carries no Node.js | static + e2e | resource-limit-tests.md |
| NFT-RES-LIM-08 — Edge-host RAM profile of the UI image at steady state | e2e | resource-limit-tests.md |
| NFT-RES-LIM-09 — nginx routes — exactly 9 location blocks for the suite services | static | resource-limit-tests.md |
| NFT-RES-LIM-10 — nginx — each route strips its `/api/<service>/` prefix | static + e2e | resource-limit-tests.md |

### Excluded

- CI image-tag scheme + OCI labels (covered in 26_test_ci_image_labels).
- Bundle exclusions (covered in 24_test_bundle_fcp_soak).

## Acceptance Criteria

**AC-1: nginx config — 500 MB cap**
NFT-RES-LIM-02 — `grep -E 'client_max_body_size\s+500M'` against `nginx/conf.d/*.conf` returns exactly one hit (in the SPA server block).

**AC-2: nginx:alpine, no Node**
NFT-RES-LIM-03 — `Dockerfile` base image is `nginx:alpine` (or a versioned variant thereof); the produced image, run with `docker run --rm $IMAGE which node`, returns non-zero. E2e probes the running container.

**AC-3: Steady-state RAM**
NFT-RES-LIM-08 — boot the production image with the suite test stack; after 5 min of idle traffic, `docker stats $CONTAINER --no-stream --format '{{.MemUsage}}'` reports usage ≤ the published edge budget (per `_docs/02_document/tests/environment.md`).

**AC-4: 9 routes**
NFT-RES-LIM-09 — `grep -cE '^\s*location\s+/api/'` against `nginx/conf.d/*.conf` returns exactly 9.

**AC-5: Prefix strip**
NFT-RES-LIM-10 — for each suite service `S`, a request to `/api/<S>/probe` reaches `S` with the path `/probe` (asserted via the suite's echo endpoints). Static check additionally verifies `rewrite ^/api/<S>/(.*)$ /$1 break;` or equivalent for each route.

## System Under Test Boundary

- System under test: `Dockerfile`, `nginx/conf.d/*.conf` (or equivalent), and the built image.
- Allowed stubs: suite echo endpoints for the prefix-strip e2e assertion.
- Disallowed: stubbing nginx itself.

## Constraints

- E2E tests (AC-2, AC-3, AC-5) run against the suite docker-compose stack; tagged `@requires-docker`.
