feat(ADM-018): completed feature
This commit is contained in:
55
work/artifacts/F-014/architect.md
Normal file
55
work/artifacts/F-014/architect.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Architect — F-014 Storefront catalog pages (SSG/ISR)
|
||||
|
||||
## Decision
|
||||
Implement catalog pages in the existing `project/storefront/` Next.js App Router package. Keep the frontend isolated from backend internals and consume only public HTTP endpoints through `src/lib/api.ts`.
|
||||
|
||||
## Routes
|
||||
Add server-rendered catalog routes:
|
||||
- `app/productos/[slug]/page.tsx`: product detail at `/productos/<slug>`.
|
||||
- `app/categoria/[slug]/page.tsx`: category listing at `/categoria/<slug>`.
|
||||
- `app/marca/[slug]/page.tsx`: brand listing at `/marca/<slug>`.
|
||||
- `app/products/search/page.tsx`: search results page using `q`, `brandSlug`, `categorySlug`, `limit`, `offset` query params.
|
||||
|
||||
## Rendering model
|
||||
- Use React Server Components only for this slice.
|
||||
- Export `revalidate = 300` on catalog pages for ISR.
|
||||
- Do not generate static params from backend at build time yet; return `[]` from `generateStaticParams()` and allow dynamic ISR generation on first request.
|
||||
- Backend unavailable at build must not fail the build.
|
||||
|
||||
## On-demand revalidation
|
||||
Add `app/api/revalidate/route.ts`:
|
||||
- POST-only JSON body `{ "path": "/productos/foo" }`.
|
||||
- Require `REVALIDATE_SECRET`; request must send matching `x-revalidate-secret` header.
|
||||
- Validate path is local and belongs to supported public catalog routes.
|
||||
- Call `revalidatePath(path)` and return JSON.
|
||||
|
||||
## API client
|
||||
Extend `src/lib/api.ts`:
|
||||
- Add typed `CategoryDto` and `BrandDto`.
|
||||
- Add `getCategoryBySlug(slug)` and `getBrandBySlug(slug)`.
|
||||
- Extend `searchProducts` input with `categorySlug`.
|
||||
- Keep client `server-only`.
|
||||
|
||||
Backend support:
|
||||
- Add optional `categorySlug` filter to public product search so category pages can list products without importing backend internals.
|
||||
- Preserve existing `/products/search` API shape.
|
||||
|
||||
## Metadata and OpenGraph
|
||||
Each route must export `generateMetadata`:
|
||||
- Product: title/description from SEO fields or product name/description, canonical `/productos/<slug>`, OG title/description/url/images when product image exists.
|
||||
- Category: title/description from SEO fields or category name, canonical `/categoria/<slug>`.
|
||||
- Brand: title/description from SEO fields or brand name, canonical `/marca/<slug>`.
|
||||
- Search: title reflects the query when present and canonical `/products/search`.
|
||||
|
||||
## SEO/Lighthouse basics
|
||||
- Use semantic headings, descriptive links, visible text content, metadata and OG tags.
|
||||
- Avoid client JavaScript in this slice.
|
||||
- No cart, checkout UI, auth UI, or full structured-data module here.
|
||||
|
||||
## Quality evidence
|
||||
Required:
|
||||
- `cd project/storefront && npm run lint && npm run typecheck && npm run build && npm run lint`
|
||||
- `cd project && npm run lint && npm run typecheck && npm test`
|
||||
- `./scripts/verify.sh`
|
||||
|
||||
Lighthouse evidence can be structural/build evidence in this environment unless browser Lighthouse tooling is available.
|
||||
17
work/artifacts/F-014/documenter.md
Normal file
17
work/artifacts/F-014/documenter.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Documenter — F-014 Storefront catalog pages (SSG/ISR)
|
||||
|
||||
## Documentation updated
|
||||
- Updated `project/README.md` catalog section to document `categorySlug` search filtering.
|
||||
- Updated `project/README.md` storefront section to document:
|
||||
- Product detail pages at `/productos/<slug>`.
|
||||
- Category pages at `/categoria/<slug>`.
|
||||
- Brand pages at `/marca/<slug>`.
|
||||
- Search results at `/products/search`.
|
||||
- ISR settings for product/category/brand pages and search results.
|
||||
- Metadata, canonical URL and OpenGraph behavior.
|
||||
- On-demand revalidation via `POST /api/revalidate` with `REVALIDATE_SECRET` and `x-revalidate-secret`.
|
||||
- Cart and checkout UI remain out of scope.
|
||||
|
||||
## Evidence
|
||||
- `cd project && npm run lint` — PASS after README update.
|
||||
- `./scripts/verify.sh` — PASS after README update.
|
||||
47
work/artifacts/F-014/implementer.md
Normal file
47
work/artifacts/F-014/implementer.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Implementer — F-014 Storefront catalog pages (SSG/ISR)
|
||||
|
||||
## Summary
|
||||
Implemented storefront catalog pages for product detail, category listing, brand listing and search results using Next.js App Router server components, ISR, per-page metadata/OpenGraph, typed public API client functions and on-demand revalidation.
|
||||
|
||||
## Code changes
|
||||
- Extended backend public search filter:
|
||||
- `project/src/modules/catalog/domain/product.ts` adds `categorySlug` to search criteria.
|
||||
- `project/src/modules/catalog/application/product-use-cases.ts` forwards `categorySlug`.
|
||||
- `project/src/modules/catalog/api/catalog.routes.ts` accepts/logs `categorySlug` on `/products/search`.
|
||||
- `project/src/modules/catalog/infrastructure/pg-product-search-repository.ts` filters products by category slug through public catalog/category tables.
|
||||
- `project/src/modules/catalog/tests/product-use-cases.test.ts` covers forwarding `brandSlug` and `categorySlug` through the search port.
|
||||
- Extended storefront API client:
|
||||
- `project/storefront/src/lib/api.ts` adds `CategoryDto`, `BrandDto`, `getCategoryBySlug`, `getBrandBySlug`, `listCategoryTree`, and `categorySlug` search input.
|
||||
- `project/storefront/src/lib/seo.ts` centralizes site URL/title helpers.
|
||||
- Added catalog UI:
|
||||
- `project/storefront/src/components/product-card.tsx`.
|
||||
- `project/storefront/src/app/productos/[slug]/page.tsx` product detail route.
|
||||
- `project/storefront/src/app/categoria/[slug]/page.tsx` category listing route.
|
||||
- `project/storefront/src/app/marca/[slug]/page.tsx` brand listing route.
|
||||
- `project/storefront/src/app/products/search/page.tsx` search results route.
|
||||
- Added on-demand revalidation:
|
||||
- `project/storefront/src/app/api/revalidate/route.ts` validates `REVALIDATE_SECRET` with `timingSafeEqual`, accepts supported catalog paths only, and calls `revalidatePath`.
|
||||
|
||||
## Rendering/SEO behavior
|
||||
- Product/category/brand pages export `revalidate = 300` and `generateStaticParams() { return []; }`, allowing SSG/ISR generation without requiring a live backend at build time.
|
||||
- Search page exports `revalidate = 120`.
|
||||
- Search page bounds displayed/metadata query text to 200 characters before rendering or metadata generation.
|
||||
- Product/category/brand/search pages export `generateMetadata` with title, description, canonical URL and OpenGraph data.
|
||||
- Product page uses `/productos/<slug>` and never exposes internal ids in the URL.
|
||||
- All pages are server components; no client components added.
|
||||
|
||||
## Evidence
|
||||
- `cd project/storefront && npm run lint` — PASS.
|
||||
- `cd project/storefront && npm run typecheck` — PASS.
|
||||
- `cd project/storefront && npm run build` — PASS; Next output shows SSG routes for `/productos/[slug]`, `/categoria/[slug]`, `/marca/[slug]` and dynamic `/products/search` plus `/api/revalidate`.
|
||||
- `cd project/storefront && npm run lint` after build — PASS.
|
||||
- `cd project && npm run lint` — PASS.
|
||||
- `cd project && npm run typecheck` — PASS.
|
||||
- `cd project && npm test` — PASS: 17 files passed, 7 skipped; 64 passed, 33 skipped.
|
||||
- `./scripts/verify.sh` — PASS.
|
||||
- Internal review correction run: bounded search query text in search page, then storefront lint/typecheck/build/lint, backend lint/typecheck/test and verify all reran and passed.
|
||||
- Security correction run: revalidation secret comparison changed to timing-safe comparison, then storefront lint/typecheck/build/lint, backend lint/typecheck/test and verify all reran and passed.
|
||||
|
||||
## Notes
|
||||
- Lighthouse tooling is not installed; SEO score criterion is evidenced structurally: SSR/SSG pages, semantic content, metadata/OpenGraph, canonical URLs and no client JavaScript added for these pages.
|
||||
- No cart or checkout UI added.
|
||||
23
work/artifacts/F-014/leader-close.json
Normal file
23
work/artifacts/F-014/leader-close.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"feature_id": "F-014",
|
||||
"agent": "leader",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "F-014 closed with storefront catalog pages for products, categories, brands and search, ISR/SSG metadata, protected on-demand revalidation, backend categorySlug search support, documentation, and all gates approved.",
|
||||
"gates": {
|
||||
"reviewer": "APPROVED",
|
||||
"security": "APPROVED",
|
||||
"qa": "APPROVED"
|
||||
},
|
||||
"evidence": [
|
||||
"work/artifacts/F-014/architect.md",
|
||||
"work/artifacts/F-014/implementer.md",
|
||||
"work/artifacts/F-014/reviewer.json",
|
||||
"work/artifacts/F-014/security.json",
|
||||
"work/artifacts/F-014/qa.json",
|
||||
"work/artifacts/F-014/documenter.md",
|
||||
"cd project/storefront && npm run lint/typecheck/build/lint: PASS",
|
||||
"cd project && npm run lint/typecheck/test: PASS",
|
||||
"./scripts/verify.sh: PASS final close"
|
||||
],
|
||||
"closed_at": "2026-08-15T15:53:00Z"
|
||||
}
|
||||
16
work/artifacts/F-014/qa.json
Normal file
16
work/artifacts/F-014/qa.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"feature_id": "F-014",
|
||||
"agent": "qa",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "QA approved. Product/category/brand/search catalog pages exist with ISR metadata and OpenGraph, product URL remains /productos/<slug>, revalidation endpoint exists and is protected, and all configured checks are green. Lighthouse is evidenced structurally because browser Lighthouse tooling is not installed.",
|
||||
"evidence": [
|
||||
"Acceptance: Product page served at /productos/<slug> with no internal id -> project/storefront/src/app/productos/[slug]/page.tsx uses product.url and route slug; no id in URL",
|
||||
"Acceptance: Catalog update revalidation -> project/storefront/src/app/api/revalidate/route.ts accepts supported catalog paths and calls revalidatePath with REVALIDATE_SECRET protection",
|
||||
"Acceptance: Each page carries title/description/OpenGraph -> generateMetadata present on product/category/brand/search pages with canonical URL and OG fields",
|
||||
"Acceptance: Lighthouse SEO >= 90 -> structural evidence: server/SSG pages, semantic h1/nav/sections, metadata, canonical URLs, OpenGraph and no client components; Lighthouse binary not available in this environment",
|
||||
"cd project/storefront && npm run lint/typecheck/build/lint: PASS; build output shows SSG for product/category/brand routes",
|
||||
"cd project && npm run typecheck: PASS",
|
||||
"./scripts/verify.sh: PASS"
|
||||
],
|
||||
"timestamp": "2026-08-15T15:52:28Z"
|
||||
}
|
||||
19
work/artifacts/F-014/reviewer.json
Normal file
19
work/artifacts/F-014/reviewer.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"feature_id": "F-014",
|
||||
"agent": "reviewer",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "F-014 review approved. Storefront now has server-rendered product, category, brand and search pages with ISR/SSG configuration, metadata/OpenGraph, a protected revalidation endpoint, typed public API access, and backend categorySlug support without frontend backend-internal imports.",
|
||||
"evidence": [
|
||||
"Read work/current.md and work/artifacts/F-014/architect.md/implementer.md",
|
||||
"Inspected product/category/brand/search App Router pages and metadata generation",
|
||||
"Inspected /api/revalidate route: secret required, supported local catalog paths only, calls revalidatePath",
|
||||
"Inspected storefront API client extensions for category/brand/categorySlug and server-only boundary",
|
||||
"Inspected backend categorySlug search propagation through route/use case/repository/test",
|
||||
"Next build output shows SSG routes for /productos/[slug], /categoria/[slug], /marca/[slug], dynamic /products/search and /api/revalidate",
|
||||
"cd project/storefront && npm run lint/typecheck/build/lint: PASS",
|
||||
"cd project && npm run lint/typecheck/test: PASS",
|
||||
"./scripts/verify.sh: PASS",
|
||||
"gentle-ai review mode status: receipt-driven development off globally, ordinary gates used"
|
||||
],
|
||||
"timestamp": "2026-08-15T15:50:59Z"
|
||||
}
|
||||
16
work/artifacts/F-014/security.json
Normal file
16
work/artifacts/F-014/security.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"feature_id": "F-014",
|
||||
"agent": "security",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "Security approved. Public catalog pages use server-only API access, search/category inputs are bounded or slug-validated, backend SQL remains parameterized, and on-demand revalidation is protected by env secret, timing-safe comparison and strict local path allowlist.",
|
||||
"evidence": [
|
||||
"Checked /api/revalidate: REVALIDATE_SECRET required, x-revalidate-secret checked via timingSafeEqual, invalid/missing secret rejected, only /productos/<slug>, /categoria/<slug>, /marca/<slug>, /products/search paths allowed",
|
||||
"Checked storefront API client remains server-only and uses public HTTP endpoints only",
|
||||
"Checked search page bounds display/metadata query text and numeric pagination; backend route validates q/categorySlug/brandSlug with zod constraints",
|
||||
"Checked backend categorySlug filter uses parameterized SQL values and no frontend backend-internal imports are needed",
|
||||
"cd project/storefront && npm audit --audit-level=high --omit=dev: found 0 vulnerabilities",
|
||||
"rg secret patterns: only intentional env/header names and redaction pattern code findings; no committed credentials",
|
||||
"Post-hardening storefront lint/typecheck/build/lint, backend lint/typecheck/test and verify all passed in build evidence"
|
||||
],
|
||||
"timestamp": "2026-08-15T15:52:05Z"
|
||||
}
|
||||
Reference in New Issue
Block a user