Skip to content

Task Plan: BFF Stream

Author: Miguel Pinilla Date: 2026-05-07 Status: Planning

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).

  • Goal §“Repositories”arda-frontend-app row.
  • 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.yml allowlist.
  • 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”productUrl is detailPageURL from 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.
RepositoryBranchWorktree
Arda-cards/arda-frontend-appjmpicnic/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.

#TaskDepends onNotes
1Add 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.
2Create 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.
3Create src/lib/shared/amazon/constants.ts exporting MARKETPLACE = "www.amazon.com" as const.True invariant per Constraint 6.
4Create 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
5Unit 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).4Use the table in context-exploration.md § “URL Forms” as the source of truth for the test matrix.
6Create 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.2Pure function.
7Unit tests for the affiliate-URL builder.6Trivial.
8Add 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.
9Create 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, 8Pinned at amazon-creators-api@1.2.2.
10Unit 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.9Stubbed at the SDK boundary, not the HTTP boundary.
11Create src/server/routes/amazon/import.ts with the orchestration: extractAsincreatorsClient.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, 2Verbatim 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).
12Unit 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.11The full error matrix per the contract.
13Create 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.11Match 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.
14Integration tests for the route handler: run through MSW, assert request → response shape end-to-end.13Match the existing MSW pattern under src/mocks/handlers/.
15Add the four AMAZON_* names to the `envgrepallowlist 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.
16Author 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, 11Lives in the documentation repo, on the existing project branch.
17CHANGELOG entry in arda-frontend-app/CHANGELOG.md under Added (minor bump). Cite PDEV-446.Required for CI gate.
18Pre-push: run make check in the worktree (lint + typecheck + build + Jest unit tests + Chromium e2e). All green.1–17Per workspace feedback_always_run_checks rule.
19Open the PR; run /pr-steward.18Standard.
  1. make check is green locally.
  2. CI is green on the PR.
  3. Unit tests cover the matrix in tasks #5, #7, #10, #12, #14.
  4. The BFF API reference page is committed to the documentation worktree on the same branch.
  5. The four AMAZON_* env vars are in src/lib/env.ts AND amplify.yml.
  6. package.json pins amazon-creators-api to 1.2.2 exactly (no ^, no ~).
  7. package-lock.json is committed alongside, with integrity hashes.
  • 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 infrastructure deploys the env vars. Acceptable because no caller exists in v1 (the SPA UI is a follow-up project).

New files:

  • src/lib/shared/amazon/{types.ts, constants.ts, asin.ts, affiliate-url.ts} plus their *.test.ts siblings.
  • 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 (add amazon-creators-api@1.2.2).
  • src/lib/env.ts (four new entries).
  • amplify.yml (four names appended to the env | grep allowlist).
  • CHANGELOG.md (Added entry).
  • ../../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