---
name: policystack-instrument
description: Find un-annotated data collection and data egress in a codebase and add PolicyStack `collecting()` / `sharing()` / `thirdParty()` / `defineCookie()` call sites so the generated policy reflects what the code actually does.
---

<!-- Generated by @policystack/sdk renderSkillPack() — do not edit by hand. Run `vp run gen`. -->

# policystack-instrument

Make the policy reflect reality: annotate real data flows at their call sites
so the `@policystack/vite` build scans them into the config. The markers are
identity functions — they return their value unchanged and have **no runtime
effect**; the build reads them statically.

## The markers (from `@policystack/sdk`)

- `collecting(category, value, labels)` — wrap a value at the point it is
  stored. `labels` maps each field to a human label, or `Ignore` to
  exclude it (e.g. `password: Ignore`).
- `sharing(key, recipient, value)` — wrap an outbound payload at a data
  egress edge (the CCPA sell/share signal).
- `thirdParty(name, purpose, policyUrl?)` — declare a vendor exists; place
  next to its initialisation.
- `defineCookie(category)` — declare a consent category at its use site.

**Constraint:** `category`, `key`, `recipient`, `name` and the label
map must be **string / object literals**. Non-literal arguments are skipped by
the static scanner (it emits a build diagnostic — they are not silently lost,
but no annotation is produced). Never pass a variable.

## What counts as an un-annotated flow

The scanner already recognises common cookie/vendor surfaces (`document.cookie`,
`js-cookie`, `cookies-next`, `react-cookie`, server `set-cookie`, and
~30 known vendor imports) and flags any that are **not** gated by
`<ConsentGate>`, a `consent.has(...)` check, or an accept/set helper. Look
for, in priority order:

1. Persisted user input / DB writes with no nearby `collecting()`.
2. Outbound requests carrying user data (analytics, CRM, webhooks) with no
   `sharing()` and no `thirdParty()`.
3. Cookie / `localStorage` writes and tracker `<script>`/SDK init with no
   `defineCookie()` and not consent-gated.

## Procedure

1. Grep the data layer and network calls; list candidate flows.
2. Add the smallest correct marker at each call site, reusing presets where
   they fit so labels stay consistent:
   - Data categories: `DataCategories.AccountInfo`, `DataCategories.Communications`, `DataCategories.DeviceInfo`, `DataCategories.LocationData`, `DataCategories.PaymentInfo`, `DataCategories.SessionData`, `DataCategories.UsageData`
   - Lawful bases: `LegalBases.Consent`, `LegalBases.Contract`, `LegalBases.LegalObligation`, `LegalBases.LegitimateInterests`, `LegalBases.PublicTask`, `LegalBases.VitalInterests`
   - Retention: `Retention.AsRequiredByLaw`, `Retention.NinetyDays`, `Retention.OneYear`, `Retention.ThirtyDays`, `Retention.ThreeYears`, `Retention.UntilAccountDeletion`, `Retention.UntilSessionExpiry`
   - Vendors: `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`
3. Ensure every newly scanned category has a matching `data.context` /
   `cookies.context` entry in `policystack.ts` (the typed config enforces
   this).
4. Run `policystack-audit` to confirm the config still validates.
