Adds the `conformance/pii-declaration-must-be-complete` ESLint rule at
warn severity. The rule detects `custom: { pii: { ... } }` blocks in
Payload config files and warns when any of the four required sub-fields
(`category`, `purpose`, `exportable`, `restrictable`) is missing.
Incomplete PII declarations can produce incorrect audit reports —
sub-second editor feedback catches the gap before it reaches
compliance/data-map.yml.
- Rule + 7 RuleTester fixtures (complete passes, each missing field
warns, non-pii custom block is no-op, malformed custom.pii is no-op)
- Registered in plugin.js + base.js at "warn"
- Conformance rule count bumped 7 → 8 in CLAUDE.md +
conformance-quickref.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
58 lines
1.5 KiB
JavaScript
58 lines
1.5 KiB
JavaScript
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 },
|
|
});
|
|
}
|
|
}
|
|
},
|
|
};
|
|
},
|
|
};
|