Skip to content

Latest commit

 

History

History
231 lines (191 loc) · 6.46 KB

File metadata and controls

231 lines (191 loc) · 6.46 KB

Implementation Summary - Issue #770: /api/exports Endpoint for GrantFox FWC26 Campaign

Overview

This implementation adds the /api/exports endpoint for the GrantFox FWC26 (Stellar Wave) campaign, providing access to materialized export artifacts with signed download URLs.

Changes Made

1. New Route: src/routes/exports.ts

  • Created a new Express router for the /api/exports endpoint
  • Implements GET /api/exports with the following features:
    • Authentication required (bearer token)
    • Input validation using Zod schema
    • Pagination support (limit: 1-100, offset: >=0)
    • Format filtering (csv or json)
    • Developer profile verification
    • Signed download URL generation with configurable TTL
    • Standardized error envelope

Key Features:

  • Returns paginated list of export artifacts for the authenticated developer
  • Each export includes: id, developerId, format, exportedAt, expiresAt, downloadUrl
  • Download URLs are signed and expire per EXPORT_SIGNED_URL_TTL_SECONDS (default: 900s / 15 minutes)
  • Non-admin users can only access their own exports
  • Proper error handling with standardized error codes

2. Router Integration: src/routes/index.ts

  • Added import for createExportsRouter from ./exports.js
  • Added ReportExporterService to ApiRouterDeps interface
  • Mounted /api/exports router when both reportExporterService and developerRepository dependencies are available
  • Registered after /api/exports/schedules to ensure proper route matching order

3. OpenAPI Specification: docs/openapi.json

  • Added /api/exports endpoint definition with:
    • Comprehensive request/response schemas
    • Example request and response bodies
    • Security requirements (bearerAuth)
    • Query parameter definitions
    • Error response definitions
    • References to existing ErrorResponse schema

Endpoint Specification:

GET /api/exports
Query Parameters:
- limit (optional, default: 20, max: 100): Maximum records to return
- offset (optional, default: 0): Pagination offset
- developerId (optional): Filter by developer ID (admin-only)
- format (optional): Filter by format ('csv' or 'json')

Response:
{
  "data": [
    {
      "id": "uuid",
      "developerId": "string",
      "format": "csv" | "json",
      "exportedAt": "ISO-8601 timestamp",
      "expiresAt": "ISO-8601 timestamp",
      "downloadUrl": "signed URL"
    }
  ],
  "pagination": {
    "limit": number,
    "offset": number,
    "total": number
  }
}

4. Test Suite: src/routes/exports.test.ts

  • Created comprehensive test suite with 7 test cases:
    1. Returns 401 when not authenticated
    2. Returns 403 when user has no developer profile
    3. Returns 200 with empty data when no exports exist
    4. Returns 200 with export records when they exist
    5. Filters by format when specified
    6. Respects pagination parameters
    7. Has standardized error envelope

Test Coverage:

  • Authentication and authorization validation
  • Developer profile verification
  • Empty state handling
  • Data retrieval and transformation
  • Format filtering
  • Pagination
  • Error response structure

Security Considerations

Authentication & Authorization

  • Requires valid bearer token (via requireAuth middleware)
  • Verifies developer profile exists for authenticated user
  • Non-admin users can only access their own exports
  • Uses standardized error codes (UNAUTHORIZED, DEVELOPER_NOT_FOUND)

Data Protection

  • S3 credentials are never returned in responses
  • Download URLs are signed with limited TTL (configurable via EXPORT_SIGNED_URL_TTL_SECONDS)
  • Sensitive data is properly redacted

Input Validation

  • All query parameters are validated using Zod schema
  • Limit is constrained to 1-100 range
  • Offset must be >= 0
  • Format must be 'csv' or 'json'

API Documentation

Request Examples

Basic Request:

curl -X GET \
  https://api.callora.dev/api/exports \
  -H 'Authorization: Bearer YOUR_TOKEN'

With Pagination:

curl -X GET \
  'https://api.callora.dev/api/exports?limit=10&offset=0' \
  -H 'Authorization: Bearer YOUR_TOKEN'

Filter by Format:

curl -X GET \
  'https://api.callora.dev/api/exports?format=csv' \
  -H 'Authorization: Bearer YOUR_TOKEN'

Response Examples

Success (200 OK):

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "developerId": "dev-123",
      "format": "csv",
      "exportedAt": "2026-06-01T00:00:00.000Z",
      "expiresAt": "2026-06-08T00:00:00.000Z",
      "downloadUrl": "https://s3.example.com/exports/dev-123/2026-06-01.csv?expires=1234567890&signature=abc123"
    }
  ],
  "pagination": {
    "limit": 20,
    "offset": 0,
    "total": 1
  }
}

Error (401 Unauthorized):

{
  "code": "UNAUTHORIZED",
  "message": "Authentication required",
  "requestId": "req-abc123def456"
}

Error (403 Forbidden):

{
  "code": "DEVELOPER_NOT_FOUND",
  "message": "No developer profile found for this account",
  "requestId": "req-abc123def456"
}

Configuration

The endpoint respects the following environment variables:

  • EXPORT_SIGNED_URL_TTL_SECONDS: TTL for signed download URLs (default: 900 / 15 minutes)

Dependencies

The endpoint requires the following services to be configured:

  • ReportExporterService: For listing exports and generating signed URLs
  • DeveloperRepository: For verifying developer profiles

Compliance

Security:

  • Input validation at boundary
  • Standardized error envelope
  • Signed URLs with limited TTL
  • No credential exposure

Testing:

  • Focused test suite with 7 test cases
  • Covers all major code paths
  • Validates error handling

Documentation:

  • OpenAPI specification with examples
  • Inline code comments
  • Clear request/response examples

Code Quality:

  • Follows existing code patterns
  • Type-safe with TypeScript
  • Proper error handling
  • Structured logging ready (uses requestId)

Files Modified

  1. src/routes/exports.ts (NEW)
  2. src/routes/exports.test.ts (NEW)
  3. src/routes/index.ts (MODIFIED)
  4. docs/openapi.json (MODIFIED)

Files Created

  1. IMPLEMENTATION_SUMMARY_ISSUE_770.md (THIS FILE)

Next Steps

To fully enable this endpoint in production:

  1. Ensure ReportExporterService is instantiated and passed to createApiRouter
  2. Configure EXPORT_SIGNED_URL_TTL_SECONDS as needed
  3. Verify object storage credentials are properly configured
  4. Run the daily export worker to generate export artifacts

Related Issues

  • Closes #770
  • Related to #398 (scheduled developer report exports)