@openpolicy/sdk
Version:
Public API for defining privacy policies with OpenPolicy
215 lines (173 loc) • 7.38 kB
Markdown
---
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)