Skip to content

002 harden checkout tenancy#81

Closed
rafiqul4 wants to merge 58 commits intomainfrom
002-harden-checkout-tenancy
Closed

002 harden checkout tenancy#81
rafiqul4 wants to merge 58 commits intomainfrom
002-harden-checkout-tenancy

Conversation

@rafiqul4
Copy link
Copy Markdown
Collaborator

Description

Why

Fixes #
Related to #

What

Type of Change

Please check the relevant option(s):

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📝 Documentation update
  • 🎨 Style/UI change
  • ♻️ Code refactoring (no functional changes)
  • ⚡ Performance improvement
  • ✅ Test addition or update
  • 🔧 Configuration change
  • 🏗️ Infrastructure change

Checklist

Please ensure your PR meets the following requirements:

Code Quality

  • Code follows the project's TypeScript and code style guidelines
  • Code is properly formatted (ran npm run format)
  • Code passes linting (ran npm run lint)
  • TypeScript compiles without errors (ran npm run type-check)
  • No any types used (except for documented third-party library interfaces)
  • File size limits respected (max 300 lines per file, 50 lines per function)

Testing

  • All existing tests pass (ran npm run test)
  • New tests have been added for new features or bug fixes
  • Test coverage meets requirements:
    • Business logic: minimum 80% coverage
    • Utility functions: 100% coverage
    • API routes: integration tests added
    • Critical paths: E2E tests added (if applicable)
  • Tests follow AAA pattern (Arrange, Act, Assert)

Security & Best Practices

  • Authentication checks are in place for protected routes
  • Multi-tenant isolation is enforced (storeId filtering)
  • Input validation is implemented using Zod schemas
  • No secrets or sensitive data in code (using environment variables)
  • SQL injection prevention (using Prisma, no raw SQL)
  • XSS prevention (proper input sanitization)

Documentation

  • Documentation has been updated (if applicable)
  • JSDoc comments added for complex functions
  • API documentation updated (if API changes were made)
  • README.md updated (if needed)
  • Specification documents updated (if architectural changes were made)

Database (if applicable)

  • Database migration created (if schema changes were made)
  • Migration tested on local database
  • Seed data updated (if needed)
  • Indexes added for new query patterns
  • Soft delete pattern followed for user-facing data

Accessibility (if UI changes were made)

  • Meets WCAG 2.1 Level AA standards
  • Keyboard navigation works properly
  • ARIA labels added where necessary
  • Color contrast ratios meet requirements (≥ 4.5:1)
  • Focus indicators are visible
  • Alt text provided for images
  • Tested with screen reader (if major UI changes)

Performance (if applicable)

  • Page load time within budget (< 2.0s LCP desktop, < 2.5s mobile)
  • API response time within budget (< 500ms p95)
  • Database queries optimized (no N+1 queries)
  • Images optimized (using Next.js Image component)
  • Bundle size within limits (< 200KB initial load)

Build & Deployment

  • Build succeeds locally (ran npm run build)
  • No console errors or warnings
  • Environment variables documented (if new ones added)
  • Works in both development and production modes

Screenshots (if applicable)

Before

After

Additional Context

Reviewer Notes


By submitting this pull request, I confirm that:

  • I have read and agree to follow the Code of Conduct
  • I have read the Contributing Guidelines
  • My contribution is original work or properly attributed
  • I agree to license my contribution under the project's MIT License

- Add 'type': 'module' to package.json for Vite 7.x ESM-only compatibility
- Add test:integration script to package.json
- Increase Node heap size to 4GB (--max-old-space-size=4096) to prevent OOM errors
- Update test scripts to use explicit vitest.mjs path with Node memory limit
- Update GitHub Actions workflows with NODE_OPTIONS for memory
- Exclude T037 mocked tests from integration suite (need conversion to true integration tests)
- Document T037 status in artifacts/T037-api-test-coverage-status.md

BREAKING CHANGE: package.json now has type: module (ESM-first)
Introduces a script to audit REST API routes for common violations and outputs a JSON report. Adds documentation and tests for payment intent validation robustness, including idempotency, retry logic, and timeout handling. Updates several API route handlers and tasks to support these features.
Added a detailed summary documenting the standardization of API response formats for five endpoints, removing non-standard success flags and aligning with the project-standard { data, error, meta } pattern. Includes migration guidance, testing impact, and next steps for production deployment.
Copilot AI review requested due to automatic review settings November 14, 2025 18:40
@github-actions
Copy link
Copy Markdown

👋 Thanks for opening your first pull request in StormCom!

A maintainer will review your PR soon. Please make sure:

  • Your PR follows our
    Contributing Guidelines
  • All CI checks pass
  • You've added appropriate tests
  • Documentation has been updated (if needed)

We appreciate your contribution to making StormCom better! 🚀

T042 deliverables:
- Automated audit script (scripts/audit-rest-api.ts)
- Comprehensive audit report (77 violations identified)
- Remediation plan with prioritization
- HIGH severity fixes (5 PUT endpoints with idempotency) - COMPLETE
- MEDIUM severity fixes (5 response format issues) - COMPLETE
- LOW severity fixes (67 OPTIONS handlers) - Optional Phase 4

All critical REST violations have been identified and remediated.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements comprehensive security and infrastructure hardening for the checkout flow, multi-tenant isolation, and newsletter functionality. The changes introduce server-side price recalculation to prevent client-side tampering, payment intent pre-validation, atomic transactions, audit logging, and a robust multi-tenant store resolution system.

Key Changes:

  • Checkout Security: Server-side price recalculation (FR-002), payment intent validation (T012), and atomic transactions (T013) to prevent fraudulent checkouts
  • Multi-Tenant Infrastructure: Store resolution from domain/subdomain with canonical redirects, request context propagation, and consistent storeId enforcement
  • API Standardization: Unified middleware pipeline (T027), standardized error responses (FR-008), idempotency handling for PUT/PATCH operations, and X-Request-Id header propagation

Reviewed Changes

Copilot reviewed 86 out of 178 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
tests/e2e/checkout-security.spec.ts E2E tests validating price tampering prevention, payment validation, and multi-tenant isolation
tests/integration/*/route.spec.ts Placeholder integration tests for analytics and attributes API routes
src/services/transaction.ts Transaction wrapper utilities for atomic multi-step operations with retry logic
src/services/pricing-service.ts Server-side pricing calculation service that recalculates all monetary values from database
src/services/payments/intent-validator.ts Payment intent pre-validator with retry logic, idempotency, and timeout handling
src/services/newsletter-service.ts Newsletter subscription service with consent recording and audit logging
src/services/export-service.ts Async CSV export service with job queue integration for large datasets
src/services/audit-service.ts Centralized audit logging service for checkout, payment, and order events
src/lib/store/resolve-store.ts Store resolution from domain/subdomain with custom domain support
src/lib/store/resolve-from-headers.ts Server-side helper to resolve store from request headers
src/lib/store/canonical-redirect.ts Canonical domain redirect for SEO optimization
src/lib/request-context.ts AsyncLocalStorage-based request context for correlation IDs and tenant isolation
src/lib/job-queue-stub.ts Lightweight job queue for development/testing with retry and exponential backoff
src/lib/idempotency.ts Idempotency handling for PUT/PATCH requests using Vercel KV or in-memory cache
src/lib/errors.ts Typed error class hierarchy with HTTP status mapping
src/lib/cache/tags.ts Cache tag registry for Next.js revalidateTag
src/lib/api-response.ts Standardized API response formatting with X-Request-Id headers
src/lib/api-middleware/index.ts Composable middleware pipeline for authentication, rate limiting, and validation
src/components/ConsentBanner.tsx GDPR-compliant newsletter consent banner with accessibility features
src/app/shop/newsletter/actions.ts Server actions for newsletter subscription with rate limiting
src/app/api/stores/[id]/theme/route.ts Idempotency support added to theme update endpoint
src/app/api/stores/[id]/route.ts Idempotency support added to store update endpoint
src/app/api/products/[id]/route.ts Idempotency support added to product update endpoint
src/app/api/orders/route.ts Migrated to middleware pipeline with standardized responses
src/app/api/orders/export/route.ts CSV export with streaming for ≤10k rows, async jobs for >10k
src/app/api/orders/[id]/status/route.ts Idempotency support added to order status updates
src/app/api/checkout/complete/route.ts Complete security overhaul with price recalculation, payment validation, and audit logging
src/app/(dashboard)/products/page.tsx Enforced storeId requirement with redirect for missing tenant context
src/app/(dashboard)/analytics/page.tsx Enforced storeId requirement with redirect for missing tenant context

}

// Multi-tenant: Get storeId from session (never trust client)
const storeId = (session.user as any).storeId;
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using as any bypasses TypeScript's type safety. The session.user type should be extended in next-auth.d.ts to include storeId and other custom fields. Create a type declaration file to properly type the session object instead of using type assertions.

Copilot uses AI. Check for mistakes.
}

const customerId = (session.user as any).id;
const userId = session.user.id;
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

customerId and userId are assigned the same value (session.user.id), which suggests duplicated logic. If these represent the same entity, use a single variable. If they represent different concepts, add a comment explaining the distinction.

Suggested change
const userId = session.user.id;

Copilot uses AI. Check for mistakes.
export function rateLimitMiddleware(): Middleware {
return async (context, next) => {
// Pass the actual Request object to checkSimpleRateLimit
const result = await checkSimpleRateLimit(context.request);
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The checkSimpleRateLimit function is called synchronously for every request in the middleware chain. Consider implementing distributed rate limiting with Vercel KV or Upstash Redis for production to avoid in-memory limitations and ensure consistent rate limiting across serverless function instances.

Copilot uses AI. Check for mistakes.
Comment on lines +263 to +264
// TODO: Integrate with actual Stripe SDK
// For now, check database payment records
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This TODO indicates incomplete payment validation logic. The current implementation only checks the database and validates payment intent ID format (pi_* prefix) but does not verify with Stripe API. This is a critical security gap that must be addressed before production use. Add a tracking issue reference or timeline for Stripe integration.

Copilot uses AI. Check for mistakes.
headers: headersList,
});

const rateLimitResult = checkSimpleRateLimit(request);
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checkSimpleRateLimit returns a Promise but is not being awaited. This will cause the rate limit check to be bypassed. Add await: const rateLimitResult = await checkSimpleRateLimit(request);

Suggested change
const rateLimitResult = checkSimpleRateLimit(request);
const rateLimitResult = await checkSimpleRateLimit(request);

Copilot uses AI. Check for mistakes.
payload: T,
scheduledFor?: Date
): Promise<string> {
const id = `${type}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Math.random() for ID generation can lead to collisions in high-concurrency scenarios. Use crypto.randomUUID() or a more robust ID generation library for production-grade uniqueness guarantees.

Copilot uses AI. Check for mistakes.
@rafiqul4 rafiqul4 closed this Nov 14, 2025
@rafiqul4 rafiqul4 review requested due to automatic review settings March 23, 2026 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants