audit: Tier 1/3/6/7 batch — PII redaction, mobile safe-area, perf, build hardening

Tier 1.4: error_events.request_body_excerpt sanitizer now redacts
GDPR-relevant fields (email, phone, dob, address, fullName, firstName,
lastName, postcode, nationalId, etc.) on top of the existing
credential list. A 5xx in /api/v1/clients no longer lands full client
PII in the super-admin inspector.

Tier 3.10: ScanShell <main> now adds pb-[max(1.5rem, env(safe-area-
inset-bottom))]. Mobile-pwa audit caught the Save expense button sitting
flush against the iPhone 14/15 home indicator in standalone PWA mode.

Tier 6.2: dashboard widget-registry now dynamic-imports every
recharts-backed chart widget (berth status, lead source, occupancy
timeline, pipeline funnel, revenue breakdown, source conversion).
~80-150KB initial-bundle savings when reps have charts disabled.
ssr:false because recharts needs window.

Tier 6.3: DataTable wraps the assembled columns in useMemo keyed on
(columns, hasBulkActions). TanStack docs explicitly warn that
rebuilding columns every render resets the table's internal state.

Tier 7.1: Added .dockerignore (was missing — 7.6 GB context with
.env reachable via COPY . .). Excludes git, env files, node_modules,
build artefacts, IDE config, test artefacts, audit docs.

Tier 7.4: Dockerfile.dev now runs as the node user (uid 1000) — was
root. Working dir moves to /home/node/app.

Tier 7.5: docker-compose.prod.yml adds memory limits (2g postgres,
512m redis, 1g crm-app, 1g crm-worker) and json-file log rotation
(max-size, max-file) to every service.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-12 17:18:35 +02:00
parent 50f48a8b6a
commit ad74e4a174
9 changed files with 435 additions and 45 deletions

View File

@@ -21,7 +21,13 @@ const STACK_MAX_BYTES = 4 * 1024;
const BODY_MAX_BYTES = 1 * 1024;
/** Keys whose values are never persisted to the body excerpt. */
// gdpr-auditor HIGH H2: the previous list only covered credentials.
// A 5xx in /api/v1/clients (create / update) was landing full client
// PII (full name, DOB, address, phone, nationality, email) in
// error_events.request_body_excerpt for the super-admin inspector.
// Extend to cover GDPR-relevant fields too.
const SENSITIVE_KEYS = new Set([
// Credentials
'password',
'newPassword',
'oldPassword',
@@ -35,6 +41,26 @@ const SENSITIVE_KEYS = new Set([
'cvv',
'ssn',
'authorization',
// PII
'email',
'emails',
'phone',
'phoneNumber',
'mobile',
'whatsapp',
'dob',
'dateOfBirth',
'birthdate',
'address',
'street',
'postcode',
'zip',
'nationalId',
'passport',
'taxId',
'fullName',
'firstName',
'lastName',
]);
/** Drop sensitive keys + cap the JSON length. */