name: policystack-audit
description: Audit a policystack.ts config: run policystack validate --json, explain each issue code, propose a minimal config fix, then re-validate until clean. Use when a PolicyStack config has validation errors or warnings.
policystack-audit
Close the validate → explain → fix → re-validate loop on a PolicyStack config.
1. Validate
npx @policystack/cli@latest validate --json
--json writes exactly one object to stdout and nothing else:
type ValidateResult = {
ok: boolean;
config: string;
issues: { code: string; level: "error" | "warning"; message: string }[];
errorCount: number;
warningCount: number;
loadError: string | null;
};
Branch on the exit code (or ok). loadError (missing file, TS syntax
error, no default export) is always ok: false and means fix the load
error first — there are no issues to triage yet. Pass a path or
--cwd if the config is not at the default location.
2. Explain each code
level is what validate() emits; the @policystack/vite plugin may
promote/suppress downstream, but errors block a valid config. Every code and
its durable meaning (the frozen 1.0 diagnostic surface — §6):
automated-decision-making — warning — Under GDPR/UK-GDPR automatedDecisionMaking is not declared (Art. 13(2)(f) / Art. 22) — set [] for none or list each activity.
children-under-age-invalid — error — children.underAge must be a positive number.
company-address-required — error — company.address is required.
company-contact-phone-recommended — warning — With a California (us-ca) jurisdiction, company.contact.phone is absent — CCPA §1798.130(a)(1) expects a toll-free number unless you operate exclusively online.
company-contact-required — error — company.contact.email is required.
company-dpo-undeclared — warning — Under GDPR/UK-GDPR company.dpo is not declared (Art. 13(1)(b)) — set it, or { required: false } to declare none.
company-legal-name-required — error — company.legalName is required.
company-name-required — error — company.name is required.
consent-banner-required — warning — A cookie category is consent-gated but consentMechanism.hasBanner is false — a banner is needed to collect affirmative consent.
consent-mechanism-undeclared — warning — No enabled cookie category is consent-gated, so no consent mechanism is generated (correct for strictly-necessary cookies only).
consent-preference-panel-required — warning — consentMechanism.canWithdraw is true but hasPreferencePanel is false — withdrawal has no preference panel in the wired runtime.
consent-withdrawal-required — warning — Under GDPR/UK-GDPR users must be able to withdraw cookie consent — set consentMechanism.canWithdraw.
cookie-lawful-basis-missing — error — An enabled cookie category is missing its Article 6 lawfulBasis in cookies.context.
cookies-empty — error — No cookie category is enabled in cookies.used.
data-collected-empty — warning — data.collected has no entries — the privacy policy will state that no personal data is collected.
data-context-missing — error — A collected category has no matching data.context entry (purpose, lawful basis, retention, provision).
data-context-orphan — error — A data.context entry has no matching category in data.collected.
data-missing — error — data is required when a privacy policy is emitted — use an empty data.collected for a site that collects nothing.
data-purpose-empty — error — A data.context purpose is present but blank.
data-purpose-missing — error — A data.context entry is missing its processing purpose (GDPR Art. 13(1)(c)).
effective-date-required — error — effectiveDate is required.
jurisdiction-generic-policy-text — warning — A declared jurisdiction is supported only at the "equivalent" tier (posture-correct + parent text), not hand-authored "specific" text.
jurisdiction-unknown — error — A declared jurisdiction code is not a recognised JurisdictionId.
jurisdictions-required — error — jurisdictions must list at least one jurisdiction id.
lawful-basis-incomplete — error — Under GDPR/UK-GDPR a collected category is missing its Article 6 lawfulBasis (Art. 13(1)(c)).
locale-unknown — error — locale is not one of the supported LOCALES.
policy-cookie-empty — error — policies includes "cookie" but no cookies block is set.
policy-empty — error — The config produces no policy — add data-handling fields (data, children) or a cookies block.
retention-incomplete — error — A collected category is missing a retention period.
statutory-contractual-obligation — error — Under GDPR/UK-GDPR a category is missing the Art. 13(2)(e) provision (statutory / contractual / contract-prerequisite / voluntary) or its consequences.
3. Propose a minimal fix
For each issue, change only what the code requires in policystack.ts — do
not restyle or expand the config. errors must be resolved; warnings
should be resolved or consciously accepted (e.g. data-collected-empty is
correct for a brochure site). Never invent compliance facts (a lawful basis, a
DPO) — surface the decision to the user. Many data/cookie issues are better
fixed at the source with policystack-instrument than hand-written.
4. Re-validate
Re-run step 1. Repeat until ok: true (exit 0). Report the remaining
accepted warnings, if any.