DC-084/085/089/090: Quick wins batch
CI / Test & Lint (push) Canceled after 0s
CI / Security audit (push) Canceled after 0s

DC-084: Add .dockerignore (excludes __tests__/, .git/, node_modules/, coverage/)
DC-085: Replace Math.random() with crypto.randomUUID()/crypto.randomBytes() for IDs
DC-089: Add dedicated rate limiter on POST /license/activate (10 attempts/15min)
DC-090: Pin Node.js to 20.11.1-alpine3.19 + add engines field to package.json

All 1539 tests pass. ESLint: 0 errors.
This commit is contained in:
Hermes
2026-08-12 02:24:28 -07:00
parent bb20f02cbf
commit 5c02bfba1d
6 changed files with 33 additions and 11 deletions
+14 -1
View File
@@ -1,7 +1,20 @@
const express = require('express');
const rateLimit = require('express-rate-limit');
const { success, error: errorResponse } = require('../src/utils/responses');
const { ValidationError } = require('../src/utilities/errors');
// Dedicated rate limiter for license activation — prevents brute-force key guessing.
// Pro keys follow a predictable format (DC-XXX-XXXXX-XXXXXX), so without rate
// limiting an attacker could enumerate valid keys.
const licenseActivateLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 10, // 10 attempts per window per IP
standardHeaders: true,
legacyHeaders: false,
message: { success: false, error: 'Too many license activation attempts. Please try again later.' },
skip: () => process.env.NODE_ENV === 'test',
});
/**
* License routes factory
* @param {Object} deps - Explicit dependencies
@@ -13,7 +26,7 @@ module.exports = function({ licenseManager, asyncHandler }) {
const router = express.Router();
// Activate a license code
router.post('/activate', asyncHandler(async (req, res) => {
router.post('/activate', licenseActivateLimiter, asyncHandler(async (req, res) => {
const { code } = req.body;
if (!code) {
throw new ValidationError('License code is required');