Task Plan: BFF Stream
Author: Miguel Pinilla Date: 2026-05-07 Status: Planning
Summary
Section titled “Summary”Implement the new /api/amazon/import BFF route in arda-frontend-app, the Creators API client (wrapping the amazon-creators-api@1.2.2 npm package), the Shared utility module (ASIN extractor, affiliate-URL builder, DTO types, MARKETPLACE constant), the src/lib/env.ts additions for the four AMAZON_* env vars, and the amplify.yml allowlist additions. The route accepts an ASIN or canonical Amazon product URL and returns the v1 DTO defined in goal.md.
This stream is independent of the other three streams at the code level. It depends on infrastructure only at deployment time (env vars must exist in the Amplify app before the route can be invoked usefully).
Scope (cite of goal.md)
Section titled “Scope (cite of goal.md)”- Goal §“Repositories” —
arda-frontend-approw. - Goal §“Success Criteria” — items 2, 3, 4, 5, 8.
- Goal §“Scope > In Scope” — all bullets concerning
arda-frontend-app, the BFF route, ASIN extractor, affiliate-URL builder, Creators API client, JWT verification,src/lib/env.ts,amplify.ymlallowlist. - Goal §“Constraints” — all of 1, 2, 3, 5, 7, 8, 11, 12.
- Context §“SDK Choice” — pin
amazon-creators-api@1.2.2, exact version (no caret). - Context §“Configuration & Env-Var Convention” — variable names, source-of-truth, src/lib/env.ts pattern.
- Context §“Affiliate-Tag Canonicalisation Rule” —
productUrlisdetailPageURLfrom the response, not rebuilt. - Context §“v1 BFF DTO ← Creators API field mapping” — the upstream-to-DTO field-path mapping table.
- Context §“Error Model — Verbatim from Amazon” — error mapping table.
Repository
Section titled “Repository”| Repository | Branch | Worktree |
|---|---|---|
Arda-cards/arda-frontend-app | jmpicnic/amazon-client-integration (existing) | /Users/jmp/code/arda/projects/amazon-item-import-worktrees/arda-frontend-app (existing) |
Single worktree, single PR. Single-agent execution recommended.
| # | Task | Depends on | Notes |
|---|---|---|---|
| 1 | Add amazon-creators-api to package.json dependencies with exact version "1.2.2" (no caret, no tilde). Run GITHUB_TOKEN=$(gh auth token) npm install to update package-lock.json with integrity hashes. Commit both files. | — | Per workspace memory: npm install requires GITHUB_TOKEN for @arda-cards/* packages. |
| 2 | Create src/lib/shared/amazon/types.ts exporting the v1 DTO type. Inline field shape (per goal.md Success Criterion 2): name: string, image: { url: string; width: number; height: number }, price: { amount: number; currency: string; displayAmount: string }, unitCount: number | null, unit: string | null, upc: string | null, asin: string, productUrl: string. | — | TypeScript-strict; nullability per context-exploration.md § “v1 BFF DTO ← Creators API field mapping” — unitCount/unit/upc are nullable (typically null for digital goods like Kindle); the rest are required. |
| 3 | Create src/lib/shared/amazon/constants.ts exporting MARKETPLACE = "www.amazon.com" as const. | — | True invariant per Constraint 6. |
| 4 | Create src/lib/shared/amazon/asin.ts with `extractAsin(input: string): { ok: true; asin: string } | { ok: false; code: ErrorCode }. Recognise the URL forms enumerated in context-exploration.md § "URL Forms". Reject short links (UNSUPPORTED_SHORT_LINK), non-US hosts (UNSUPPORTED_AMAZON_LOCALE), unparseable (UNRECOGNIZED_AMAZON_URL`). | 2 |
| 5 | Unit tests for the ASIN extractor covering every accepted form, every rejected form (with the expected error code), arbitrary query-param stripping, edge cases (empty string, whitespace, trailing slash). | 4 | Use the table in context-exploration.md § “URL Forms” as the source of truth for the test matrix. |
| 6 | Create src/lib/shared/amazon/affiliate-url.ts with buildAffiliateUrl(asin: string, tag: string): string returning https://www.amazon.com/dp/<asin>?tag=<tag>. Provided as a Shared fallback utility (PDEV-429 cart-link work). Not used by v1’s productUrl. | 2 | Pure function. |
| 7 | Unit tests for the affiliate-URL builder. | 6 | Trivial. |
| 8 | Add the four env-var entries to src/lib/env.ts (AMAZON_CREATORS_CREDENTIAL_ID, AMAZON_CREATORS_CREDENTIAL_SECRET, AMAZON_CREATORS_CREDENTIAL_VERSION, AMAZON_ASSOCIATE_TAG). Match the existing requiredEnv() pattern with mock-mode fallbacks (so unit tests / mock-mode dev don’t crash on missing values). | — | Verbatim names per Constraint 12. |
| 9 | Create src/server/lib/amazon/creators-client.ts that imports ApiClient, TypedDefaultApi, GetItemsRequestContent, GetItemsResource from amazon-creators-api. Initialise with the credential triple from env. Expose a single typed method that takes asins: string[] and a resources: string[] set (default = the v1 minimum useful set per context-exploration.md § “Creators API GetItems — v1 Request and Resource Set”). Token cache + retry handled by the SDK. | 1, 8 | Pinned at amazon-creators-api@1.2.2. |
| 10 | Unit tests for the Creators API client: stub the SDK class, assert the request payload includes partnerTag, the v1 resource set, marketplace = "www.amazon.com", itemIdType = "ASIN". Mock-mode: assert the client is not constructed. | 9 | Stubbed at the SDK boundary, not the HTTP boundary. |
| 11 | Create src/server/routes/amazon/import.ts with the orchestration: extractAsin → creatorsClient.getItems → DTO mapping (per context-exploration.md § “v1 BFF DTO ← Creators API field mapping” table) → return DTO including productUrl = item.detailPageURL verbatim — do not rebuild, modify, or strip query parameters. Error mapping per context-exploration.md § “Error Model — Verbatim from Amazon”. | 4, 9, 2 | Verbatim pass-through is required by goal.md Constraint 3 and grounded in Amazon’s Associates Program IP License (verbatim quote in context-exploration.md § “Affiliate-Tag Canonicalisation Rule”): “Do not edit any of the URL parameters.” Rebuilding the URL — even just to substitute the affiliate tag — violates the IP License and risks Associates account termination. One ASIN per call in v1 (the SDK list signature is preserved for future bulk). |
| 12 | Unit tests for the route logic with a mocked client. Cover: happy path (DTO populated correctly from a fixture response); short-link rejection; non-US-host rejection; unparseable rejection; HTTP 404 → AMAZON_ITEM_NOT_ACCESSIBLE; HTTP 429 → AMAZON_API_THROTTLED; HTTP 5xx → AMAZON_API_UNAVAILABLE; missing env vars → clean AMAZON_API_UNAVAILABLE. | 11 | The full error matrix per the contract. |
| 13 | Create src/app/api/amazon/import/route.ts (Next.js Route Handler) — thin wrapper: extract JWT, call into import.ts, return JSON. Tenant-scoped per Constraint 8. | 11 | Match the existing /api/arda/* route pattern — concrete reference: src/app/api/arda/items/route.ts (POST handler with JWT extraction, tenant scoping, and JSON response). The new handler should use the same JWT-extraction utility and error-shape conventions. |
| 14 | Integration tests for the route handler: run through MSW, assert request → response shape end-to-end. | 13 | Match the existing MSW pattern under src/mocks/handlers/. |
| 15 | Add the four AMAZON_* names to the `env | grepallowlist inarda-frontend-app/amplify.yml. No CLI propagation required — the infrastructurestream's Task 8b clears the inlineBuildSpecon every Amplify app, making the in-repoamplify.yml` the single source of truth on every build. | — |
| 16 | Author the BFF API reference page at documentation/src/content/docs/current-system/functional/reference-data/item/amazon-bff-api.md. Sections: Purpose; Authentication (tenant-scoped JWT); Input shape; Output DTO shape (referenced from the TypeScript type in arda-frontend-app/src/lib/shared/amazon/types.ts); Error codes (the full matrix from Constraint 7); Configuration touchpoints (the four env vars + MARKETPLACE constant). | 2, 11 | Lives in the documentation repo, on the existing project branch. |
| 17 | CHANGELOG entry in arda-frontend-app/CHANGELOG.md under Added (minor bump). Cite PDEV-446. | — | Required for CI gate. |
| 18 | Pre-push: run make check in the worktree (lint + typecheck + build + Jest unit tests + Chromium e2e). All green. | 1–17 | Per workspace feedback_always_run_checks rule. |
| 19 | Open the PR; run /pr-steward. | 18 | Standard. |
Acceptance criteria
Section titled “Acceptance criteria”make checkis green locally.- CI is green on the PR.
- Unit tests cover the matrix in tasks #5, #7, #10, #12, #14.
- The BFF API reference page is committed to the documentation worktree on the same branch.
- The four
AMAZON_*env vars are insrc/lib/env.tsANDamplify.yml. package.jsonpinsamazon-creators-apito1.2.2exactly (no^, no~).package-lock.jsonis committed alongside, with integrity hashes.
Merge gate
Section titled “Merge gate”- CI green on the PR.
- No code-level dependency on the other streams. Can merge before or after
item-module,infrastructure,operator. - Operationally: the route is non-functional in production until
infrastructuredeploys the env vars. Acceptable because no caller exists in v1 (the SPA UI is a follow-up project).
Files to be created or modified
Section titled “Files to be created or modified”New files:
src/lib/shared/amazon/{types.ts, constants.ts, asin.ts, affiliate-url.ts}plus their*.test.tssiblings.src/server/lib/amazon/creators-client.ts(+ test).src/server/routes/amazon/import.ts(+ test).src/app/api/amazon/import/route.ts(+ test).documentation/src/content/docs/current-system/functional/reference-data/item/amazon-bff-api.md.
Modified files:
package.json,package-lock.json(addamazon-creators-api@1.2.2).src/lib/env.ts(four new entries).amplify.yml(four names appended to theenv | grepallowlist).CHANGELOG.md(Added entry).
References
Section titled “References”../../goal.md— project goal.../../context-exploration.md— decision backing for SDK choice, env-var convention, DTO mapping, error model, URL forms.../../phases.md— overall stream structure.../../3-deployment/deployment-plan.md— choreography for rollout.
Copyright: (c) Arda Systems 2025-2026, All rights reserved
Copyright: © Arda Systems 2025-2026, All rights reserved