const REQUIRED_FIELDS = ["category", "purpose", "exportable", "restrictable"]; /** @type {import("eslint").Rule.RuleModule} */ export default { meta: { type: "problem", docs: { description: "custom.pii blocks in Payload config files must declare all required sub-fields: category, purpose, exportable, restrictable.", }, schema: [], messages: { missingField: "custom.pii block is missing required field '{{field}}'. Incomplete PII declarations can produce incorrect audit reports.", }, }, create(context) { return { Property(node) { if ( node.key.type !== "Identifier" || node.key.name !== "custom" || node.value.type !== "ObjectExpression" ) { return; } const piiProp = node.value.properties.find( (p) => p.type === "Property" && p.key.type === "Identifier" && p.key.name === "pii", ); if (!piiProp || piiProp.value.type !== "ObjectExpression") { return; } const presentFields = new Set( piiProp.value.properties .filter((p) => p.type === "Property" && p.key.type === "Identifier") .map((p) => p.key.name), ); for (const field of REQUIRED_FIELDS) { if (!presentFields.has(field)) { context.report({ node: piiProp, messageId: "missingField", data: { field }, }); } } }, }; }, };