@openpolicy/sdk
Version:
Public API for defining privacy policies with OpenPolicy
226 lines (166 loc) • 8.8 kB
Markdown
---
name: annotate-third-parties
description: >
Mark third-party service dependencies in source code using thirdParty() so
the autoCollect() Vite plugin can populate the thirdParties sentinel for the
privacy policy config. Covers manual annotation, usePackageJson auto-detection
from the KNOWN_PACKAGES registry, combining both approaches, and the Providers
preset as a static alternative.
type: core
library: openpolicy
library_version: "0.0.19"
requires:
- openpolicy/vite-setup
sources:
- jamiedavenport/openpolicy:packages/sdk/src/third-parties.ts
- jamiedavenport/openpolicy:packages/vite-auto-collect/src/known-packages.ts
---
This skill builds on openpolicy/vite-setup. Read it first.
## How It Works
`thirdParty()` is a **runtime no-op**. It is a build-time marker — `autoCollect()` scans source files statically via `oxc-parser` and extracts the three string literal arguments. The plugin then populates the `thirdParties` sentinel exported from `@openpolicy/sdk`. Without the plugin, `thirdParty()` calls have no effect whatsoever.
The populated sentinel must be spread into the top-level `thirdParties` field in the config file. Without the spread, the plugin output is discarded and the policy renders with no third parties listed.
## Setup
Three moving parts must all be in place:
**1. `vite.config.ts` — enable the plugin**
```ts
import { defineConfig } from "vite";
import { autoCollect } from "@openpolicy/vite-auto-collect";
export default defineConfig({
plugins: [
autoCollect({
thirdParties: { usePackageJson: true }, // optional — see below
}),
],
});
```
**2. Source file — annotate next to the usage**
```ts
import { thirdParty } from "@openpolicy/sdk";
// Place next to where you initialise or use the third-party SDK
thirdParty("Stripe", "Payment processing", "https://stripe.com/privacy");
// ... rest of your Stripe integration
```
**3. `openpolicy.ts` — spread the sentinel into config**
```ts
import { defineConfig, 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",
thirdParties: [...thirdParties],
});
```
Call `thirdParty(name, purpose, policyUrl)` with three string literals next to wherever you initialise the third-party integration. All three arguments must be string literals — dynamic values are silently skipped by the static analyser.
```ts
import { thirdParty } from "@openpolicy/sdk";
// Correct: all string literals
thirdParty("Intercom", "Customer messaging", "https://www.intercom.com/legal/privacy");
// Wrong: variable — silently skipped at build time
const name = "Intercom";
thirdParty(name, "Customer messaging", "https://www.intercom.com/legal/privacy");
```
Deduplication is by `name` — the first occurrence wins when files are walked in sorted alphabetical order. Calling `thirdParty()` with the same name from multiple files is safe.
`autoCollect({ thirdParties: { usePackageJson: true } })` reads `package.json` at build time and cross-references every entry in `dependencies` and `devDependencies` against the built-in KNOWN_PACKAGES registry. Matched packages are merged into `thirdParties` automatically, with deduplication by service name.
This is the fastest way to cover common services (Stripe, Sentry, PostHog, Vercel, etc.) without any source annotations.
```ts
// vite.config.ts
autoCollect({ thirdParties: { usePackageJson: true } })
```
See [references/known-packages.md](references/known-packages.md) for the full list of ~30 auto-detected packages.
### 3. Combining both approaches
`thirdParty()` annotations and `usePackageJson` are merged at build time. The plugin deduplicates by service name — `thirdParty()` entries from source files are added first (sorted file order), then package.json detections fill in any remaining services not already seen.
Use this combination when:
- Most services are covered by the KNOWN_PACKAGES registry (`usePackageJson: true`)
- A few services are not in the registry and need explicit `thirdParty()` calls
```ts
// vite.config.ts
autoCollect({ thirdParties: { usePackageJson: true } })
// src/lib/custom-analytics.ts
import { thirdParty } from "@openpolicy/sdk";
thirdParty("Fathom Analytics", "Privacy-friendly web analytics", "https://usefathom.com/privacy");
```
```ts
// openpolicy.ts — one spread covers both sources
import { defineConfig, thirdParties } from "@openpolicy/sdk";
export default defineConfig({
thirdParties: [...thirdParties],
});
```
`Providers` from `@openpolicy/sdk` is a collection of pre-filled third-party objects for common services. Use this when you want to declare third parties statically in `openpolicy.ts` without any source annotations or plugin scanning.
```ts
import { defineConfig, Providers } from "@openpolicy/sdk";
export default defineConfig({
thirdParties: [
Providers.Stripe,
Providers.Sentry,
Providers.Vercel,
{ name: "Custom Service", purpose: "Internal logging", policyUrl: "https://example.com/privacy" },
],
});
```
Available presets: `Stripe`, `Paddle`, `LemonSqueezy`, `PayPal`, `GoogleAnalytics`, `PostHog`, `Plausible`, `Mixpanel`, `Vercel`, `Cloudflare`, `AWS`, `Auth0`, `Clerk`, `Resend`, `Postmark`, `SendGrid`, `Loops`, `Sentry`, `Datadog`.
Note: when using `Providers` statically, you can still spread `thirdParties` alongside it to capture any additional auto-collected services:
```ts
thirdParties: [...thirdParties, Providers.Cloudflare],
```
`thirdParty()` is defined as a no-op function that immediately returns `undefined`. It has no runtime behaviour. The only way it produces output in the policy is when `autoCollect()` is present in `vite.config.ts` and scans the file at build time.
```ts
// WRONG: calling thirdParty() and expecting it to affect the policy at runtime
import { thirdParty } from "@openpolicy/sdk";
thirdParty("Stripe", "Payment processing", "https://stripe.com/privacy");
// Without autoCollect() in vite.config.ts, this does nothing
```
```ts
// Correct: autoCollect() in vite.config.ts is the required prerequisite
// vite.config.ts
import { autoCollect } from "@openpolicy/vite-auto-collect";
export default defineConfig({ plugins: [autoCollect()] });
// src/lib/stripe.ts — scanned at build time by the plugin
import { thirdParty } from "@openpolicy/sdk";
thirdParty("Stripe", "Payment processing", "https://stripe.com/privacy");
```
Even when `autoCollect()` scans the source and populates the sentinel, the populated value is discarded unless it is imported and spread into the top-level `thirdParties` field in the config. The privacy policy then renders with an empty third-party section, which may be legally invalid.
```ts
// WRONG: thirdParties not imported or spread
export default defineConfig({
thirdParties: [], // static empty array, discards plugin output
});
```
```ts
// Correct
import { defineConfig, thirdParties } from "@openpolicy/sdk";
export default defineConfig({
thirdParties: [...thirdParties],
// or combine with static entries:
// thirdParties: [...thirdParties, Providers.Cloudflare],
});
```
The KNOWN_PACKAGES registry covers ~30 common npm packages. Without `usePackageJson: true`, packages like `@sentry/browser`, `posthog-js`, or `@stripe/stripe-js` are not auto-detected and must each be annotated manually with `thirdParty()`. Enabling the option costs nothing and eliminates this annotation burden for any covered package.
```ts
// WRONG: usePackageJson not enabled — known packages not auto-detected
autoCollect()
```
```ts
// Correct
autoCollect({ thirdParties: { usePackageJson: true } })
```
- [Known packages registry](references/known-packages.md) — full table of npm packages auto-detected by `usePackageJson: true`
- `packages/sdk/src/third-parties.ts` — thirdParty() implementation (runtime no-op)
- `packages/sdk/src/providers.ts` — Providers preset objects
- `packages/sdk/src/auto-collected.ts` — thirdParties sentinel definition
- `packages/vite-auto-collect/src/index.ts` — autoCollect() plugin, AutoCollectOptions type
- `packages/vite-auto-collect/src/analyse.ts` — static AST extraction logic
- `packages/vite-auto-collect/src/known-packages.ts` — KNOWN_PACKAGES registry source