# PolicyStack SDK reference (llms.txt) > Generated from `@policystack/sdk` types — do not edit by hand. Feed this file > to a coding agent so it can write a correct `policystack.ts`. One typed > `defineConfig()` call is the single source of truth: it produces the privacy > policy, the cookie policy, and — via the §4.1 bridge — the consent runtime. ## Entry point ```ts import { defineConfig } from "@policystack/sdk"; import * as scanned from "./policystack.gen"; // generated by the policyStack() Vite plugin export default defineConfig({ /* PolicyStackConfig */ }, scanned); ``` Pass the generated module as the second argument — its scanned data categories, cookies and third parties are merged in, so never spread `...dataCollected` / `cookies` / `thirdParties` by hand. Omit the second argument (and its import) when there is no generated module yet. `defineConfig(config, scanned?)` returns a normalized config: `privacyVersion`/`cookieVersion` are filled in (stable content hashes) unless you set them, `consentMechanism` is derived from the cookie posture, and `company.{name,url,contact.email}` are seeded from the host `package.json` when omitted. Output only a single `policystack.ts` — no explanations. ## PolicyStackConfig shape Required: - `company`: `{ name?, legalName, address, url?, contact: { email?, phone? }, dpo?, euRepresentative? }` — `name`, `url` and `contact.email` default from the host `package.json` (`name`/`homepage`/`author.email`) when omitted; `legalName`/`address` are required - `effectiveDate`: `"YYYY-MM-DD"` - `jurisdictions`: non-empty array of jurisdiction ids (see below) - `data`: `{ collected, context }` — the data posture (an empty `collected` is valid for a brochure site but emits a `data-collected-empty` warning) Optional: - `locale`: one of `de`, `en`, `es`, `fr`, `nl` (default `"en"`) — governs only PolicyStack-emitted boilerplate; your own strings pass through untouched - `children`: `{ underAge: number, noticeUrl? }` - `thirdParties`: `{ name, purpose, policyUrl? }[]` - `automatedDecisionMaking`: `{ name, logic, significance }[]` (GDPR Art. 22) - `cookies`: `{ used?, context }` — see "Cookies & consent" below; scanned cookie categories are merged in from the second `defineConfig` argument - `trackingTechnologies`: `string[]` - `consent`: runtime-only knobs for the consent banner — `{ adapter?, jurisdictionResolver?, gpc?, initialRoute?, triggers?, onUnknownCategory?, request? }`. The category data (categories, policyVersion, locale, canWithdraw) is **derived** from `cookies`/`locale`, NOT authored here. - `policies`: explicit `("privacy" | "cookie")[]` opt-out of auto-detection - `privacyVersion` / `cookieVersion`: override the auto-computed hash `userRights` is **not** authored — it is derived from `jurisdictions`. ## data.collected & data.context (symmetric per-key) `data.collected` maps a human category label to the list of fields collected. Every category key must have a matching `data.context` entry: ```ts data: { collected: { "Account Information": ["Name", "Email address"] }, context: { "Account Information": { purpose: "Operate your account", lawfulBasis: "contract", // a lawful basis (see below) retention: "Until account deletion", provision: Contractual("You cannot create an account without it."), }, }, } ``` `provision` is built with one of the helpers (GDPR Art. 13(2)(e)): `Statutory(consequences)`, `Contractual(consequences)`, `ContractPrerequisite(consequences)`, `Voluntary(consequences)`. ## Jurisdiction ids (frozen at 1.0) Pick the codes that apply; the `us-${state}` tail not listed falls back to `us`. Posture and policy-text tier are read straight from the canonical table: - `br` — opt-in, equivalent policy text - `ca` — opt-in, equivalent policy text - `ch` — opt-in, equivalent policy text - `eea` — opt-in, specific policy text - `row` — opt-in, equivalent policy text - `uk` — opt-in, specific policy text - `us` — opt-out, equivalent policy text - `us-ca` — opt-out, specific policy text, inherits `us`, GPC legally binding - `us-co` — opt-out, equivalent policy text, inherits `us`, GPC legally binding - `us-ct` — opt-out, equivalent policy text, inherits `us`, GPC legally binding - `us-va` — opt-out, equivalent policy text, inherits `us`, GPC legally binding ## Lawful bases Used by `data.context[*].lawfulBasis` and `cookies.context[*].lawfulBasis`. The consent gating is an explicit, exhaustive table (§4.1) — only `consent` is gated: - `consent` — consent-gated (toggleable in the banner) - `contract` — standing legal ground (category renders locked-on) - `legal_obligation` — standing legal ground (category renders locked-on) - `legitimate_interests` — standing legal ground (category renders locked-on) - `public_task` — standing legal ground (category renders locked-on) - `vital_interests` — standing legal ground (category renders locked-on) ## Cookies & consent (the merged surface) `cookies.used` is a flat map; `essential` is always `true`. Every enabled key needs a `cookies.context[key].lawfulBasis`: ```ts cookies: { used: { essential: true, analytics: true, marketing: true }, context: { essential: { lawfulBasis: "legal_obligation" }, analytics: { lawfulBasis: "consent" }, marketing: { lawfulBasis: "consent" }, }, } ``` The consent category data is **derived** from this one config, never authored separately: - each truthy `cookies.used` key → a consent `Category` - `lawfulBasis === "consent"` → toggleable; any other basis → `locked: true` (a missing basis stays gated and `validate()` hard-errors it) - `cookieVersion` → `policyVersion`; a changed hash re-prompts automatically - the derived consent mechanism (any consent-gated category ⇒ `canWithdraw`) → the preferences-route affordance - `config.locale` → the consent UI locale (policy text and banner agree) Authoring: put runtime-only wiring (storage adapter, jurisdiction resolver, GPC, …) in the optional `consent` block, then pass the whole config to the single provider — `` from `@policystack/react/provider` (and the same-named provider in `@policystack/vue`/`@policystack/solid`). It supplies both the policy context and the consent store from one context; ``/ `` (from `@policystack/react/policy`) and `useConsent`/ `ConsentGate` (from `@policystack/react/consent`) all read from it. The cookies → consent-categories derivation happens inside `createConsentStore` (`@policystack/core/consent`) when given the whole config — there is no separate user-facing conversion step. ## Helper exports (from `@policystack/sdk`) Static-analysis markers (return their value unchanged; scanned at build time): - `collecting(category, value, labels)` — declare data at the point of storage; use `Ignore` as a label to exclude a field - `sharing(key, recipient, value)` — record a data-egress edge (the CCPA sell/share signal), wrap the outbound payload - `thirdParty(name, purpose, policyUrl?)` — declare a vendor exists - `defineCookie(category)` — declare a consent category at its use site Presets (optional convenience — plain objects/strings, spread or reference): - Data categories: `DataCategories.AccountInfo`, `DataCategories.Communications`, `DataCategories.DeviceInfo`, `DataCategories.LocationData`, `DataCategories.PaymentInfo`, `DataCategories.SessionData`, `DataCategories.UsageData` - Lawful bases: `LegalBases.Consent` (`"consent"`), `LegalBases.Contract` (`"contract"`), `LegalBases.LegalObligation` (`"legal_obligation"`), `LegalBases.LegitimateInterests` (`"legitimate_interests"`), `LegalBases.PublicTask` (`"public_task"`), `LegalBases.VitalInterests` (`"vital_interests"`) - Retention: `Retention.AsRequiredByLaw` (`"As required by applicable law"`), `Retention.NinetyDays` (`"90 days"`), `Retention.OneYear` (`"1 year"`), `Retention.ThirtyDays` (`"30 days"`), `Retention.ThreeYears` (`"3 years"`), `Retention.UntilAccountDeletion` (`"Until account deletion"`), `Retention.UntilSessionExpiry` (`"Until session expiry"`) - Providers: `Providers.AWS`, `Providers.Auth0`, `Providers.Clerk`, `Providers.Cloudflare`, `Providers.Datadog`, `Providers.GoogleAnalytics`, `Providers.LemonSqueezy`, `Providers.Loops`, `Providers.Mixpanel`, `Providers.Paddle`, `Providers.PayPal`, `Providers.Plausible`, `Providers.PostHog`, `Providers.Postmark`, `Providers.Resend`, `Providers.SendGrid`, `Providers.Sentry`, `Providers.Stripe`, `Providers.Vercel` - Compliance bundles: `Compliance.CCPA`, `Compliance.GDPR`, `Compliance.UK_GDPR` ## Rules - Output a single `policystack.ts` calling `defineConfig()`. No prose. - Do not author `userRights`, `privacyVersion`, `cookieVersion`, or `consentMechanism` — all derived. Pass scanned data via the second `defineConfig` argument, never by spreading the generated module. - Every `data.collected` / `cookies.used` key needs a matching `context` entry. - PolicyStack generates documents; it is not legal advice — a lawyer should review the output before publication.