---
name: define-config
description: >
  Writing the defineConfig() object for OpenPolicyConfig — privacy and cookie — including all field types, jurisdiction requirements, and preset constants from @openpolicy/sdk.
type: core
library: openpolicy
library_version: "0.0.19"
sources:
  - jamiedavenport/openpolicy:packages/core/src/types.ts
  - jamiedavenport/openpolicy:packages/sdk/src/constants.ts
---

# openpolicy/define-config

Write and maintain the `defineConfig()` call in `openpolicy.ts`. The function is an identity function used as a type marker — it accepts `OpenPolicyConfig` and returns it unchanged.

## Setup

Minimal config with privacy policy:

```ts
// openpolicy.ts
import { defineConfig, dataCollected, thirdParties } from "@openpolicy/sdk";

export default defineConfig({
  company: {
    name: "Acme",
    legalName: "Acme, Inc.",
    address: "123 Main St, San Francisco, CA 94105",
    contact: "privacy@acme.com",
  },
  effectiveDate: "2026-01-01",
  jurisdictions: ["us"],
  dataCollected: { ...dataCollected },
  legalBasis: "legitimate_interests",
  retention: { "Account Information": "Until account deletion" },
  thirdParties: [...thirdParties],
  cookies: { essential: true, analytics: false, marketing: false },
});
```

All policy fields live at the top level of `OpenPolicyConfig`. OpenPolicy auto-detects which policies to generate from the fields you provide: privacy-specific fields (like `dataCollected`, `legalBasis`, `retention`) produce a privacy policy, and cookie-specific fields (like `cookies`, `consentMechanism`) produce a cookie policy. `effectiveDate` and `jurisdictions` are shared across both.

User rights (access, erasure, portability, etc.) are **derived automatically** from `jurisdictions` — declare `eu` for the six GDPR rights, `ca` for the four CCPA rights, or both for the union. There is no `userRights` field on the public config.

## Core Patterns

### 1. Privacy config with GDPR

Use `Compliance.GDPR` to spread the required `jurisdictions` and `legalBasis` values in one step (rights are derived automatically from `jurisdictions`):

```ts
import {
  defineConfig,
  Compliance,
  DataCategories,
  Retention,
  Providers,
  dataCollected,
  thirdParties,
} from "@openpolicy/sdk";

export default defineConfig({
  company: {
    name: "Acme",
    legalName: "Acme, Inc.",
    address: "123 Main St, San Francisco, CA 94105",
    contact: "privacy@acme.com",
  },
  effectiveDate: "2026-01-01",
  ...Compliance.GDPR,
  dataCollected: {
    ...dataCollected,
    ...DataCategories.AccountInfo,
    ...DataCategories.UsageData,
  },
  retention: {
    "Account Information": Retention.UntilAccountDeletion,
    "Usage Data": Retention.NinetyDays,
  },
  thirdParties: [...thirdParties, Providers.Stripe, Providers.PostHog],
  children: { underAge: 13 },
  cookies: { essential: true, analytics: true, marketing: false },
});
```

`Compliance.GDPR` expands to `{ jurisdictions: ["eu"], legalBasis: ["legitimate_interests"] }`. The six GDPR user rights are derived automatically from `jurisdictions: ["eu"]`.

### 2. Using Compliance presets

`Compliance.GDPR` and `Compliance.CCPA` are objects safe to spread directly into `defineConfig()`:

```ts
import { Compliance, defineConfig } from "@openpolicy/sdk";

// GDPR only
defineConfig({ ...Compliance.GDPR, /* ... */ })

// Both — union the jurisdictions; user rights are derived automatically
defineConfig({
  ...Compliance.GDPR,
  jurisdictions: [...Compliance.GDPR.jurisdictions, ...Compliance.CCPA.jurisdictions],
  // ...
})
```

`Compliance.CCPA` does not include `legalBasis` — it provides only `jurisdictions: ["ca"]`. The four CCPA user rights are derived automatically.

Available preset groups from `@openpolicy/sdk`:

| Export | Content |
|---|---|
| `DataCategories` | Named `dataCollected` entries (AccountInfo, SessionData, PaymentInfo, UsageData, DeviceInfo, LocationData, Communications) |
| `Retention` | Retention period strings (UntilAccountDeletion, ThirtyDays, NinetyDays, OneYear, ThreeYears, AsRequiredByLaw, …) |
| `LegalBases` | `LegalBasis` string constants (Consent, Contract, LegitimateInterests, …) |
| `Compliance` | Preset bundles: `GDPR`, `CCPA` |
| `Providers` | Named third-party descriptors: Stripe, PostHog, Vercel, Sentry, Clerk, Resend, … |

### 3. Cookie config

```ts
export default defineConfig({
  company: { ... },
  effectiveDate: "2026-01-01",
  jurisdictions: ["eu", "us"],
  cookies: { essential: true, analytics: true, marketing: false },
  consentMechanism: {
    hasBanner: true,
    hasPreferencePanel: true,
    canWithdraw: true,
  },
  trackingTechnologies: ["localStorage", "sessionStorage", "cookies"],
  thirdParties: [Providers.GoogleAnalytics, Providers.Cloudflare],
});
```

The `cookies` field requires `essential: boolean` — all other keys are `boolean` and are treated as additional cookie categories. Presence of `cookies`, `consentMechanism`, or `trackingTechnologies` auto-detects a cookie policy.

## Common Mistakes

### HIGH — Using standalone PrivacyPolicyConfig instead of flat OpenPolicyConfig

Wrong:
```ts
// WRONG: standalone shape
import type { PrivacyPolicyConfig } from "@openpolicy/sdk";

const config: PrivacyPolicyConfig = {
  company: { name: "Acme", legalName: "Acme, Inc.", address: "...", contact: "..." },
  effectiveDate: "2026-01-01",
  dataCollected: {},
  legalBasis: "consent",
  retention: {},
  cookies: { essential: true, analytics: false, marketing: false },
  thirdParties: [],
  userRights: [],
  jurisdictions: [],
};
// userRights is a REQUIRED field on the internal PrivacyPolicyConfig,
// but this shape isn't what defineConfig() accepts.
```

Correct:
```ts
// correct: flat OpenPolicyConfig via defineConfig()
import { defineConfig } from "@openpolicy/sdk";

export default defineConfig({
  company: { name: "Acme", legalName: "Acme, Inc.", address: "...", contact: "privacy@acme.com" },
  effectiveDate: "2026-01-01",
  jurisdictions: [],
  dataCollected: {},
  legalBasis: "consent",
  retention: {},
  thirdParties: [],
  cookies: { essential: true, analytics: false, marketing: false },
});
```

React components and the autoCollect pipeline read from `OpenPolicyConfig`; the standalone policy types are internal shapes not consumed by the rendering layer.

Source: `packages/core/src/types.ts`

---

### MEDIUM — Not specifying jurisdictions — GDPR/CCPA sections silently absent

Wrong:
```ts
// WRONG: jurisdictions missing — legalBasis section and GDPR/CCPA content will not appear,
// and no user rights will be derived
defineConfig({
  company: { /* ... */ },
  legalBasis: "legitimate_interests",
  // jurisdictions omitted
})
```

Correct:
```ts
defineConfig({
  company: { /* ... */ },
  legalBasis: "legitimate_interests",
  jurisdictions: ["eu", "us"],
})
```

Section builders for GDPR (`eu`) and CCPA (`ca`) content check the top-level `jurisdictions` field before generating output, and the user rights list is derived from the same field. Omitting `jurisdictions` (or passing an empty array) causes those sections to be silently skipped and no rights to be listed. `Compliance.GDPR` and `Compliance.CCPA` include the correct `jurisdictions` values when spread.

Source: `packages/core/src/templates/privacy/`

## Reference

- [PrivacyPolicyConfig and CookiePolicyConfig field table](./references/privacy-config.md)
