> ## Documentation Index
> Fetch the complete documentation index at: https://docs.barndoor.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage Data Protection

> Define custom detection types, allow lists, and enforcement policies as code, with a dry-run-first rollout

This guide manages your organization's Data Control Center configuration in Terraform: the org-level switch, a custom detection type, allow-list entries that suppress false positives, and an enforcement policy rolled out safely with dry run.

<Note>
  **Estimated time**: 20–30 minutes. Complete [Getting Started](/terraform/getting-started) first. For the concepts, see the [Data Control Center overview](/how-tos/data-control-center/overview).
</Note>

## Before You Begin

* A configured `provider "barndoor"` block (see [Getting Started](/terraform/getting-started))
* At least one [Protection Profile](/how-tos/data-control-center/protection-profiles) — a named detection engine — configured in your organization. Enforcement policies can't be created until one exists, and its ID is what `detection_engine_ids` references.

## Step 1: Adopt the organization config

Data protection has one configuration object per organization, provisioned by the platform. The `barndoor_dlp_org_config` resource **adopts** that singleton rather than creating anything:

```hcl theme={null}
resource "barndoor_dlp_org_config" "this" {
  enabled = true

  # Observe-only mode: every policy records findings without acting.
  global_dry_run = false
}
```

Reference: [`barndoor_dlp_org_config`](https://registry.terraform.io/providers/barndoor-ai/barndoor/latest/docs/resources/dlp_org_config)

<Note>
  Because it's a singleton, `terraform destroy` doesn't delete anything — it resets both settings to the platform defaults (`enabled = true`, `global_dry_run = false`) and drops the resource from state.
</Note>

## Step 2: Define a custom detection type

Custom detection types extend the built-in detectors with organization-specific patterns — project codenames, internal ticket formats, customer ID shapes:

```hcl theme={null}
resource "barndoor_dlp_custom_detection_type" "codenames" {
  name        = "Project codenames"
  description = "Internal project codenames that must not leave the organization"

  patterns = [
    { pattern = "(?i)project\\s+aurora", pattern_type = "PATTERN_TYPE_REGEX" },
    { pattern = "AURORA-CLASSIFIED", pattern_type = "PATTERN_TYPE_LITERAL" },
  ]

  # Both default to *_MEDIUM when omitted.
  default_severity   = "DETECTION_SEVERITY_HIGH"
  default_confidence = "DETECTION_CONFIDENCE_HIGH"
}
```

Reference: [`barndoor_dlp_custom_detection_type`](https://registry.terraform.io/providers/barndoor-ai/barndoor/latest/docs/resources/dlp_custom_detection_type)

Patterns are evaluated in order. Regex patterns use Rust `regex` syntax and are validated by the API — a pattern that doesn't compile is rejected at apply time, not silently ignored.

The platform assigns the type's wire name (`DETECTION_TYPE_CUSTOM_…`), exposed as the `detection_type` attribute — that's the value other data protection resources reference.

## Step 3: Suppress false positives with allow-list entries

Allow-list entries stop known-safe values from being reported (and acted on) as findings:

```hcl theme={null}
# Scoped to specific detection types — including the custom one from Step 2.
resource "barndoor_dlp_allow_list_entry" "codename_docs_site" {
  pattern         = "aurora.docs.example.com"
  pattern_type    = "PATTERN_TYPE_LITERAL"
  detection_types = [barndoor_dlp_custom_detection_type.codenames.detection_type]
  reason          = "Public documentation host, not a leak"
}

# Omit detection_types to suppress matches for every detection type.
resource "barndoor_dlp_allow_list_entry" "support_mailbox" {
  pattern         = "support@example.com"
  pattern_type    = "PATTERN_TYPE_LITERAL"
  detection_types = ["DETECTION_TYPE_EMAIL"]
  reason          = "Shared support mailbox, not PII"
}
```

Reference: [`barndoor_dlp_allow_list_entry`](https://registry.terraform.io/providers/barndoor-ai/barndoor/latest/docs/resources/dlp_allow_list_entry)

<Note>
  The platform has no update operation for allow-list entries, so changing **any** attribute replaces the entry (delete + create). Plans will show this as a replacement — that's expected.
</Note>

## Step 4: Enforce with a policy — dry run first

Enforcement policies decide what happens when a detection engine reports a finding. A policy targets exactly one lane: **MCP traffic** (tool inputs/outputs) or **model-provider traffic** (prompts/responses).

Start in dry run — the policy evaluates and records findings in activity, but takes no action:

```hcl theme={null}
resource "barndoor_dlp_enforcement_policy" "block_secrets_in_prompts" {
  name          = "Block secrets in prompts"
  action        = "POLICY_ACTION_BLOCK"
  provider_ids  = ["openai"]
  runtime_stage = "RUNTIME_STAGE_PROMPT"

  # Roll out observing first; flip to false to enforce.
  dry_run = true

  detection_engine_ids = [var.detection_engine_id]
}

variable "detection_engine_id" {
  type        = string
  description = "The ID of a Protection Profile (detection engine) in the organization"
}
```

And an MCP-lane example — tokenize PII in tool traffic for one group:

```hcl theme={null}
resource "barndoor_dlp_enforcement_policy" "tokenize_mcp_pii" {
  name   = "Tokenize PII on MCP traffic"
  action = "POLICY_ACTION_TOKENIZE"

  mcp_targets = [
    { mcp_server_id = "*", direction = "BOTH" },
  ]

  principals = [
    { principal_type = "GROUP", principal_id = "engineering" },
  ]

  dry_run = true

  detection_engine_ids = [var.detection_engine_id]
}
```

Reference: [`barndoor_dlp_enforcement_policy`](https://registry.terraform.io/providers/barndoor-ai/barndoor/latest/docs/resources/dlp_enforcement_policy)

<Warning>
  **The two lanes don't mix.** `MCP_SERVER` policies use `mcp_targets` with the `RUNTIME_STAGE_TOOL_INPUT` / `RUNTIME_STAGE_TOOL_OUTPUT` stages and may not set `provider_ids` or `model_alias`; `MODEL_PROVIDER` policies are the reverse, with `RUNTIME_STAGE_PROMPT` / `RUNTIME_STAGE_RESPONSE`. The API rejects mixed shapes. It also rejects (with a 422) any detection engine that doesn't support the policy's `action`.
</Warning>

## Step 5: Flip to enforcement

Once dry-run findings in the activity view look right — expected matches, no false positives that an allow-list entry should cover — enforce by changing one line and re-applying:

```hcl theme={null}
  dry_run = false
```

This is the code-review moment the dry-run pattern exists for: the diff that turns on enforcement is one visible line in a pull request.

<Tip>
  There are two dry-run levers, and they compose: `global_dry_run` on the org config forces *every* policy to observe-only (useful during initial rollout of the whole system), while per-policy `dry_run` stages an individual policy. Enforcement happens only when both are off.
</Tip>

## Complete example

<Expandable title="Full configuration from this guide">
  ```hcl theme={null}
  resource "barndoor_dlp_org_config" "this" {
    enabled        = true
    global_dry_run = false
  }

  resource "barndoor_dlp_custom_detection_type" "codenames" {
    name        = "Project codenames"
    description = "Internal project codenames that must not leave the organization"

    patterns = [
      { pattern = "(?i)project\\s+aurora", pattern_type = "PATTERN_TYPE_REGEX" },
      { pattern = "AURORA-CLASSIFIED", pattern_type = "PATTERN_TYPE_LITERAL" },
    ]

    default_severity   = "DETECTION_SEVERITY_HIGH"
    default_confidence = "DETECTION_CONFIDENCE_HIGH"
  }

  resource "barndoor_dlp_allow_list_entry" "codename_docs_site" {
    pattern         = "aurora.docs.example.com"
    pattern_type    = "PATTERN_TYPE_LITERAL"
    detection_types = [barndoor_dlp_custom_detection_type.codenames.detection_type]
    reason          = "Public documentation host, not a leak"
  }

  resource "barndoor_dlp_enforcement_policy" "block_secrets_in_prompts" {
    name          = "Block secrets in prompts"
    action        = "POLICY_ACTION_BLOCK"
    provider_ids  = ["openai"]
    runtime_stage = "RUNTIME_STAGE_PROMPT"
    dry_run       = true

    detection_engine_ids = [var.detection_engine_id]
  }

  variable "detection_engine_id" {
    type        = string
    description = "The ID of a Protection Profile (detection engine) in the organization"
  }
  ```
</Expandable>
