# Source type enum enforced

- **Pattern:** `ab-000876` (`data-sourcing-provenance.source-management.source-type-enum`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000876
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000876)

## Why it matters

Unvalidated free-text source type fields let any string enter your database — 'scraped', 'Scraped', 'SCRAPER', and '' all become distinct values. Downstream deduplication queries, compliance lookups, and per-source quality analytics break silently when the field is inconsistent. CWE-20 (Improper Input Validation) and ISO 27001:2022 A.8.9 both require that data integrity controls are in place at the input boundary. Without a constrained enum, you cannot reliably segment contacts by acquisition method or demonstrate to a regulator that you know where each record came from.

## Severity rationale

High because an unconstrained source_type field silently corrupts every downstream provenance query and compliance report that groups or filters by source.

## Remediation

Add a constrained enum at the database level via a Prisma enum type or a SQL CHECK constraint. A free-text column with no constraint is not acceptable even if application code currently writes consistent values — future ingestion paths or admin tools may not.

```prisma
// schema.prisma
enum SourceType {
  SCRAPER
  API
  PURCHASED
  FORM
  REFERRAL
}

model Contact {
  id          String     @id @default(cuid())
  source_type SourceType
}
```

```sql
-- Migration for existing tables
ALTER TABLE contacts
  ADD COLUMN source_type TEXT NOT NULL
    CHECK (source_type IN ('scraper', 'api', 'purchased', 'form', 'referral'));
```

## Detection

- **ID:** `source-type-enum`
- **Severity:** `high`
- **What to look for:** Enumerate all values the `source_type` field accepts and count the total. Examine the database schema and contact model. Look for a `source_type` (or equivalent) field with constrained values — an enum type in Prisma, a CHECK constraint in SQL, or an application-level validation that rejects values outside the set. Expected values should cover at least 3 of the main ingestion paths: scraper, api, purchased, form, referral. Quote the actual enum or CHECK constraint found. An unvalidated free-text string does not count as pass.
- **Pass criteria:** A `source_type` field (or equivalent) exists on the contact record with at least 3 constrained values — either enforced at the database level (enum type, CHECK constraint) or at the application level via a Zod/Joi/ORM enum. Arbitrary values cannot be written. Report the count of enum values even on pass.
- **Fail criteria:** Source type is stored as an unvalidated free-text string, or there is no source type field at all on contact records.
- **Skip (N/A) when:** The system has only one data source and provenance is implied by the architecture (e.g., form-only signup with no other ingestion paths).
- **Cross-reference:** Check `data-sourcing-provenance.provenance-tracking.required-provenance-fields` — the source_type field must also be NOT NULL for complete provenance.
- **Detail on fail:** Describe what was found. Example: `"source_type stored as VARCHAR with no constraints — any string value accepted"` or `"No source_type field found on contacts table"`.
- **Remediation:** Add a constrained source type field:

  ```ts
  // Prisma
  enum SourceType {
    SCRAPER
    API
    PURCHASED
    FORM
    REFERRAL
  }

  model Contact {
    id         String     @id @default(cuid())
    source_type SourceType
    // ...
  }
  ```

  ```sql
  -- SQL migration
  ALTER TABLE contacts
    ADD COLUMN source_type TEXT NOT NULL
      CHECK (source_type IN ('scraper', 'api', 'purchased', 'form', 'referral'));
  ```

## External references

- cwe CWE-20
- iso-27001 A.8.9

Taxons: data-integrity

HTML version: https://auditbuffet.com/patterns/ab-000876
