Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"extends": [
"next/core-web-vitals",
"next/typescript"
"next/typescript",
"plugin:jsx-a11y/recommended"
],
"rules": {
"@typescript-eslint/no-unused-vars": [
Expand Down
42 changes: 42 additions & 0 deletions docs/MARKETPLACE_LISTING_PAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Marketplace Listing Detail Page

This document describes the new deep-linkable marketplace listing detail page at `src/app/marketplace/[id]/page.tsx`.

## Purpose

The listing detail page provides a durable, shareable route for marketplace listings that is independent of the existing `CommitmentDetailsModal` quick-view UI.

## Routes

- `GET /marketplace/:id` — renders the new marketplace listing detail page.
- `GET /api/marketplace/listings/:id` — returns the listing payload used by the page and other marketplace clients.

## Features

- Server-rendered listing details for marketplace listings
- Trust and risk signals using `TrustBadge` and `ReputationDisplay`
- Purchase flow wiring via `/api/marketplace/listings/:id/preflight` and `/api/marketplace/listings/:id/purchase`
- Loading fallback via `src/app/marketplace/[id]/loading.tsx`
- Error boundary via `src/app/marketplace/[id]/error.tsx`
- Deep-linkable metadata for sharing and social previews

## Implementation

- `src/app/marketplace/[id]/page.tsx`
- loads the listing server-side from `marketplaceService.getPublicListing`
- returns `notFound()` when the listing does not exist
- renders the marketplace detail component and purchase panel

- `src/components/MarketplaceListingDetail.tsx`
- renders marketplace listing fields, risk indicators, and trust signals

- `src/components/MarketplaceListingPurchase.tsx`
- client-side purchase CTA with preflight and purchase request handling

- `src/app/api/marketplace/listings/[id]/route.ts`
- adds a public `GET` route for listing retrieval
- retains `DELETE` for listing cancellation

## Notes

This page is intentionally separate from the quick-view modal so listings can be shared directly, bookmarked, and indexed by client-side navigation.
39 changes: 39 additions & 0 deletions docs/PR_BACKEND_CSRF.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# PR Documentation: Backend CSRF Coverage

## Summary

This PR strengthens the backend CSRF test suite for browser-session mutation endpoints.
It adds focused coverage around the double-submit cookie flow implemented in `src/lib/backend/csrf.ts`, with emphasis on token freshness, session binding, rotation, and origin validation.

## What changed

- Expanded `src/lib/backend/csrf.test.ts` to cover:
- fresh CSRF token verification for the same browser session
- rejection of empty or missing CSRF headers
- rejection when the header token belongs to a different session
- token rotation behavior where the old token is rejected and the new token is accepted
- same-origin enforcement for `assertSameOriginForCookieSession`
- Verified the behavior with:
- `./node_modules/.bin/vitest run src/lib/backend/csrf.test.ts`

## Why this matters

- Protects cookie-authenticated write routes from forged cross-site requests.
- Ensures stale or tampered CSRF tokens cannot be replayed with a valid session cookie.
- Confirms the helper continues to reject mismatched, empty, and cross-session token values.
- Makes the intended security behavior explicit and regression-resistant.

## Testing

1. Run the focused CSRF unit tests:
- `./node_modules/.bin/vitest run src/lib/backend/csrf.test.ts`
2. Confirm the result:
- `17 tests passed`
3. Optionally run the wider suite for regression coverage:
- `pnpm test`

## Notes

- No production behavior was changed; this PR is test coverage focused.
- The existing CSRF helper already enforces same-origin checks and avoids enforcement for bearer-token API clients.
- These additions make the security contract easier to audit and maintain over time.
36 changes: 36 additions & 0 deletions docs/PR_JSX_A11Y.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# PR Documentation: JSX Accessibility Linting

## Summary

This PR enables the recommended `jsx-a11y` ESLint rules across the frontend and fixes the accessibility issues they surface.
The goal is to make accessibility checks part of the normal development workflow and reduce regressions in interactive UI components.

## What changed

- Enabled the recommended `jsx-a11y` rules in `.eslintrc.json`.
- Fixed accessibility violations in affected components and route views, including:
- keyboard-accessible interactive controls
- proper label associations for form-like controls
- valid link semantics and navigable anchors
- safer interactive patterns in dialogs and menus
- Added documentation for the linting setup and local validation steps in `docs/accessibility/LINTING.md`.

## Why this matters

- Helps prevent common accessibility regressions in buttons, links, forms, and dialogs.
- Improves support for keyboard and assistive-technology users.
- Makes accessibility enforcement part of the regular frontend workflow rather than a one-off review task.

## Testing

1. Run the targeted lint check for updated UI files:
- `./node_modules/.bin/eslint "src/components/**/*.{ts,tsx}" "src/app/**/*.{ts,tsx}" --ext .ts,.tsx`
2. Confirm the updated `jsx-a11y` issues are resolved.
3. Optionally run the broader repo lint command:
- `corepack pnpm lint`

## Notes

- This PR focuses on enabling and remediating the accessibility issues surfaced by `jsx-a11y`.
- Some unrelated repository-wide lint issues remain outside the scope of this change.
- The new documentation provides a repeatable local validation path for future contributors.
40 changes: 40 additions & 0 deletions docs/PR_MARKETPLACE_LISTING_DETAIL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# PR Documentation: Marketplace Listing Detail Page

## Summary

This PR adds a deep-linkable marketplace listing detail page at `/marketplace/[id]`.
The page renders server-side listing data, supports rich metadata, and wires the purchase flow through the public marketplace API.

## What changed

- Added server route: `src/app/marketplace/[id]/page.tsx`
- Added route-level loading fallback: `src/app/marketplace/[id]/loading.tsx`
- Added route-level error boundary: `src/app/marketplace/[id]/error.tsx`
- Added marketplace listing detail component: `src/components/MarketplaceListingDetail.tsx`
- Added client-side purchase widget: `src/components/MarketplaceListingPurchase.tsx`
- Added public GET API route for listings: `src/app/api/marketplace/listings/[id]/route.ts`
- Expanded marketplace service: `src/lib/backend/services/marketplace.ts`
- Added listing detail page documentation: `docs/MARKETPLACE_LISTING_PAGE.md`
- Added API docs update: `docs/backend-api-reference.md`
- Added CORS policy update: `docs/backend-cors-policy.md`

## Why this matters

- Users can now share and bookmark individual marketplace listings.
- The page is server-rendered for better SEO and metadata previews.
- The purchase flow is wired consistently with existing marketplace endpoints.
- The new public GET endpoint enables marketplace clients to fetch a single listing by ID.

## How to verify

1. Run the new page test file:
- `./node_modules/.bin/vitest run src/app/marketplace/[id]/page.test.tsx`
2. Confirm the test output includes:
- `4 tests passed`
3. Review the new docs and API reference changes.

## Notes

- No backend breaking contract changes were introduced beyond the addition of a new public GET endpoint.
- The listing detail page uses existing marketplace models and service lookup logic.
- The purchase panel depends on wallet connection and `/api/marketplace/listings/[id]/preflight`.
29 changes: 29 additions & 0 deletions docs/accessibility/LINTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Accessibility Linting

## Overview

The frontend now enables the recommended `jsx-a11y` ESLint rules to catch common accessibility issues during development and CI.

## Enabled rule set

The repository extends the recommended `jsx-a11y` configuration in `.eslintrc.json`.

This helps enforce:

- meaningful alt text and accessible images
- keyboard-accessible links and buttons
- proper form labels and associations
- safe interactive element patterns for modal and menu UI

## Local validation

Run the accessibility lint check locally with:

```bash
./node_modules/.bin/eslint "src/components/**/*.{ts,tsx}" "src/app/**/*.{ts,tsx}" --ext .ts,.tsx
```

## Notes

- Inline eslint suppressions are only used when a UI pattern genuinely requires a targeted exception and the reason is documented in the code.
- The goal is to keep the app accessible for keyboard, screen-reader, and assistive-technology users while preventing regressions in reusable UI components.
38 changes: 38 additions & 0 deletions docs/backend-api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,44 @@ Clients should wait the indicated seconds before retrying. See [error-handling.m

---

## `GET /api/marketplace/listings/[id]`

Fetches a single marketplace listing by its listing ID. This endpoint is used by
`/marketplace/[id]` to render deep-linkable listing detail pages.

- **Authentication**: none
- **Path parameter**: `id` — the marketplace listing ID
- **Response**:
- `200 OK`: Listing returned.
- `404 Not Found`: Listing does not exist.

### Example

```bash
curl -X GET http://localhost:3000/api/marketplace/listings/LST-001
```

```json
{
"success": true,
"data": {
"listing": {
"listingId": "LST-001",
"commitmentId": "CMT-001",
"type": "Safe",
"amount": 50000,
"remainingDays": 25,
"maxLoss": 2,
"currentYield": 5.2,
"complianceScore": 95,
"price": 52000
}
}
}
```

---

## `POST /api/marketplace/listings/[id]/purchase`

Purchases a marketplace listing. Requires an active session cookie. Runs
Expand Down
1 change: 1 addition & 0 deletions docs/backend-cors-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Public browser routes:
- `GET /api/ready`
- `GET /api/marketplace`
- `GET /api/marketplace/listings`
- `GET /api/marketplace/listings/[id]`
- `GET /api/attestations`

First-party browser routes:
Expand Down
Loading