API Security Standards¶
| Owner | Joshua Curci - CTO |
| Applies to | All engineers building or modifying the Trove API |
| Last reviewed | April 2026 |
| Review cycle | Annually |
Purpose¶
This document defines the security standards that apply to the Trove REST API. It is a technical companion to the Secure Development Policy and provides specific, implementation-level guidance for engineers working on the API.
Stack Reference¶
| Layer | Technology |
|---|---|
| Framework | NestJS 11 |
| HTTP adapter | Fastify |
| Authentication | Auth0 + JWT |
| Database | MySQL 8 via MikroORM |
| Error monitoring | Sentry |
| Documentation | Swagger (OpenAPI) at /api/docs |
Authentication¶
All API endpoints must require authentication unless explicitly designed to be public. Authentication is handled via Auth0-issued JWTs validated on every request using NestJS guards.
Requirements¶
- Every protected endpoint must have an
@UseGuards()decorator applying the appropriate auth guard - Tokens must be validated for signature, expiry, issuer, and audience on every request
- The five token types in use must only be accepted on the endpoints they are intended for - vendor tokens must not be accepted on recipient endpoints and vice versa
- Token payloads must not be trusted without validation - always verify via the Auth0 JWKS endpoint or equivalent
- Tokens must be transmitted via the
Authorization: Bearer <token>header only - never via query parameters or request bodies
Token Types¶
| Token | Intended Scope |
|---|---|
| Vendor | Admin Portal endpoints for brand management |
| Recipient | Storefront and gift redemption endpoints |
| Admin | Internal platform administration endpoints |
| Shopify OAuth | Shopify integration authorisation flow only |
| Xero OAuth | Xero integration authorisation flow only |
Authorisation¶
Authentication confirms who a user is. Authorisation controls what they can access. Both must be enforced independently.
Requirements¶
- Every endpoint must enforce role-based access using the
UserRoleenum (ADMINISTRATOR,VENDOR,CUSTOMER) - Vendor-scoped endpoints must verify that the authenticated vendor can only access their own data - a vendor must never be able to read or modify another vendor's storefronts, orders, products, or settings
- Recipient-scoped endpoints must verify that the recipient token corresponds to the correct order and storefront
- Administrator endpoints must only be accessible to users with the
ADMINISTRATORrole - Do not rely on the frontend to enforce access controls - all access decisions must be made server-side
- Authorisation checks must be applied at the service layer, not only at the controller layer
Input Validation¶
All input received by the API must be validated before use, regardless of the source.
Requirements¶
- Use NestJS
ValidationPipewithclass-validatorDTOs for all request bodies, query parameters, and route parameters - Enable
whitelist: trueon the globalValidationPipeto strip unknown properties - Enable
forbidNonWhitelisted: trueto reject requests with unknown properties rather than silently ignoring them - Validate all data types, lengths, formats, and allowed values explicitly in DTOs
- File uploads must be validated for type, size, and content before processing
- Do not perform business logic on input that has not been validated
Injection Prevention¶
- All database queries must use MikroORM's query builder or repository methods - raw SQL is not permitted without explicit CTO approval and thorough review
- All user-supplied values passed to external services (Shopify, Stripe, Xero) must be sanitised before use
- Shell commands must never be constructed from user input
Rate Limiting¶
The API enforces a global rate limit of 30 requests per second per client.
Requirements¶
- The global rate limit must remain in place on all endpoints
- Additional endpoint-level rate limiting should be applied to sensitive operations including:
- Authentication and token refresh endpoints
- Password reset and account activation flows
- Payment initiation endpoints
- Any endpoint that triggers an external service call or background job
- Rate limit responses must return HTTP
429 Too Many Requestswith aRetry-Afterheader - Rate limit configuration must not be disabled in any environment including development
Transport Security¶
- All API traffic must be served over HTTPS with TLS 1.2 or higher
- HTTP requests must be redirected to HTTPS - unencrypted connections are not accepted
- HTTP Strict Transport Security (HSTS) headers must be set on all responses
- Certificate management is handled at the infrastructure level via DuploCloud and AWS
Response Security Headers¶
The API must set the following security headers on all responses:
| Header | Value |
|---|---|
Strict-Transport-Security |
max-age=31536000; includeSubDomains |
X-Content-Type-Options |
nosniff |
X-Frame-Options |
DENY |
Content-Security-Policy |
Appropriate policy for the endpoint context |
Referrer-Policy |
strict-origin-when-cross-origin |
CORS¶
Cross-Origin Resource Sharing (CORS) must be explicitly configured.
Requirements¶
- CORS must only permit requests from known, approved origins (Admin Portal, Customer Frontend domains)
- Wildcard origins (
*) are not permitted in production - Allowed methods and headers must be explicitly defined - do not use blanket permissive configuration
- CORS configuration must be reviewed when new frontend origins are added
Error Handling¶
Errors returned to API consumers must not expose internal implementation details.
Requirements¶
- Error responses must return generic messages to clients (e.g.
"An error occurred","Not found","Unauthorised") - Stack traces, database error messages, and internal service details must never be included in API responses
- Detailed error context must be captured internally via Sentry for debugging
- Validation errors may return field-level detail (e.g. which fields failed and why) as this is expected behaviour
500 Internal Server Errorresponses must not include any implementation detail beyond a request ID or correlation reference if applicable- Authentication failures must return
401 Unauthorised- do not return404to obscure endpoint existence for public-facing sensitive endpoints - Authorisation failures must return
403 Forbidden
Webhook Security¶
Trove receives webhooks from Stripe and Shopify. All incoming webhook payloads must be verified before processing.
Requirements¶
- Shopify: Validate the
X-Shopify-Hmac-Sha256header against a HMAC-SHA256 digest of the raw request body using the shared secret before processing any webhook payload - Stripe: Validate the
Stripe-Signatureheader using Stripe's webhook signature verification before processing any webhook payload - Webhooks that fail signature verification must be rejected with
400 Bad Requestand logged - Raw request bodies must be preserved for signature verification - do not parse the body before verifying the signature
- Webhook handlers must be idempotent where possible to safely handle duplicate deliveries
- Webhook processing is handled asynchronously via the Worker Service - the API should acknowledge receipt quickly and enqueue the job rather than processing inline
Sensitive Data Handling¶
- Passwords must never be returned in API responses
- Payment card numbers, CVVs, and full bank account details must never be stored or returned - Stripe handles payment data directly
- PII in API responses must be scoped to what the authenticated user is entitled to see - vendor users must not receive recipient PII beyond what is necessary for order management
- API responses must not include internal database IDs or implementation details that could aid enumeration attacks where UUIDs or slugs can be used instead
- File download URLs must use pre-signed S3 URLs with short expiry times rather than permanent public URLs for sensitive content
Swagger / API Documentation¶
The Swagger UI is available at /api/docs when the server is running.
Requirements¶
- Swagger must be disabled or access-restricted in production - it should not be publicly accessible
- All endpoints must be documented with accurate request and response schemas
- Authentication requirements must be documented on each endpoint
- Sensitive example values (real API keys, tokens, PII) must not appear in Swagger documentation
Dependency Security¶
- All npm dependencies must be kept up to date - run
pnpm auditregularly and before releases - Critical or high severity vulnerabilities in dependencies must be patched promptly in line with the Information Security Policy
- New dependencies must be evaluated before introduction - consider the package's maintenance status, popularity, and whether it introduces unnecessary attack surface
Logging and Monitoring¶
- All unhandled exceptions must be captured by Sentry with full context
- Authentication failures, authorisation failures, and rate limit breaches should be logged for monitoring
- Logs must not contain plaintext passwords, full payment details, or other sensitive credentials
- AWS CloudWatch is used for infrastructure-level monitoring and should alert on anomalous API error rates or traffic patterns
Security Review Checklist¶
Before merging any pull request that adds or modifies API endpoints, the reviewer should confirm:
- Authentication is enforced on all non-public endpoints
- Authorisation checks verify the correct role and data ownership
- All input is validated via DTOs with
class-validator - Database queries use MikroORM methods, not raw SQL
- Error responses do not expose internal detail
- Sensitive data is not returned unnecessarily in responses
- Any new webhook endpoints validate the incoming signature
- Rate limiting applies to the new endpoint
- CORS is not widened beyond existing approved origins