All Docs
FeaturesCalmony Sanctions MonitorUpdated March 11, 2026

HIPAA-10: Minimum Necessary Access — Compliance Finding & Remediation Guide

HIPAA-10: Minimum Necessary Access

Compliance Framework: HIPAA
Control: HIPAA-10 — Minimum Necessary Access
Release: v0.1.21
Affected File: src/app/api/people/[id]/route.ts


Overview

The minimum necessary access principle requires that API endpoints and data queries return only the information needed to fulfil a specific request — no more. Returning full database records to clients, including internal metadata, is a HIPAA compliance violation and an unnecessary data exposure risk.

This finding was identified during a HIPAA compliance review of the sanctions screening platform's people API.


The Problem

Full Records Returned by Default

Drizzle ORM queries were written using .select() without column projection, meaning every column in the people table was fetched from the database and forwarded directly to the API response:

// ❌ Non-compliant — returns all columns including internal metadata
const result = await db.select().from(people).where(eq(people.id, id));

GET /api/people/[id] returned all fields, including:

  • userId (internal foreign key)
  • Internal metadata columns not relevant to the caller

No Field-Level Restrictions for Admin Users

Admin users received the same broad, unfiltered record set as all other callers. There were no field-level access controls applied at the query or response layer to further restrict what admins could see beyond their role-based access.


Remediation

1. Use Column Projection in Drizzle Queries

Replace open-ended .select() calls with explicit column projection. Only select the fields actually required by the calling operation:

// ✅ Compliant — projects only required fields
const result = await db
  .select({
    id: people.id,
    fullName: people.fullName,
    status: people.status,
  })
  .from(people)
  .where(eq(people.id, id));

2. Define DTO Types for Each Response Shape

Define explicit Data Transfer Object (DTO) interfaces for every API response. These types should never include internal fields:

// ✅ DTO — safe for client responses
type PersonDTO = {
  id: string;
  fullName: string;
  status: string;
};

Fields to exclude from all client-facing DTOs:

  • userId
  • Internal metadata columns (timestamps used only for audit, system flags, etc.)

3. Apply Field-Level Controls for Admin Endpoints

Where admin users require access to additional fields, define a separate, explicitly scoped admin DTO rather than returning the full database record. This ensures even privileged access is bounded.


Checklist

  • Replace all .select() (no projection) Drizzle queries in API routes with explicit column projections
  • Define a DTO type for every API response shape
  • Ensure userId and internal metadata are excluded from all DTOs
  • Audit admin-facing endpoints to apply appropriate field-level scoping
  • Add response shape validation (e.g. with Zod) to prevent accidental field leakage as the schema evolves

Why This Matters

Returning excess data:

  • Violates the HIPAA minimum necessary standard (45 CFR §164.514(d))
  • Increases the blast radius of any API-level data breach
  • Exposes internal system architecture (field names, foreign keys, metadata) to clients unnecessarily
  • Makes compliance audits harder, as the API contract is implicitly the full database schema rather than a controlled surface

Related