Noticed while adding searchable-field-unknown (#4328).
Five rules in packages/lint each carry their own copy of "registry-injected columns present on almost every object but absent from authored fields", and they have already drifted from one another:
| file |
contents |
validate-widget-bindings.ts:238 |
id, 4 audit, owner_id, organization_id, tenant_id, user_id, deleted_at |
validate-page-field-bindings.ts:72 |
same list, comment says "Copied verbatim from validate-widget-bindings" |
validate-translation-references.ts:173 |
same list |
validate-react-page-props.ts:214 |
same list |
validate-flow-template-paths.ts:93 |
different — adds name, owner, is_deleted, record_type; its comment says it "mirrors validateFormLayout's system-field set plus the audit/tenant columns from FIELD_GROUP_SYSTEM_FIELDS" — i.e. it names the canonical source and then hand-copies anyway |
This is exactly the shape #3786 fixed for the audit-provenance family: a four-name list hand-copied four times across two repos, each under a comment asking to be kept in sync with one of the others. The spec now owns two declarations that between them cover the whole set:
FIELD_GROUP_SYSTEM_FIELDS (@objectstack/spec/data) — audit provenance + organization_id / tenant_id / is_deleted / deleted_at
SystemFieldName (@objectstack/spec/system) — id, created_at, updated_at, owner_id, tenant_id, user_id, deleted_at
validate-searchable-fields.ts (#4328) derives from both rather than adding a sixth copy:
const SYSTEM_FIELDS: ReadonlySet<string> = new Set<string>([
...FIELD_GROUP_SYSTEM_FIELDS,
...Object.values(SystemFieldName),
]);
Suggested fix: lift that into one module-local export in packages/lint (e.g. system-fields.ts) and point the five existing rules at it. Two judgement calls the conversion has to make deliberately rather than by accident:
- The derived union is a superset of the four identical copies (it adds
is_deleted), which only makes those rules more permissive — safe, and the direction the comments already argue for ("deliberately generous: over-inclusion costs at worst a missed warning; under-inclusion costs a false one").
validate-flow-template-paths additionally exempts name, owner and record_type, which are not system columns in the same sense — name in particular is an ordinary authored field on most objects. Whether those belong in the shared set or stay local to that rule needs a decision, not a mechanical merge.
Not folded into #4328 to keep a new gating rule's diff reviewable.
Noticed while adding
searchable-field-unknown(#4328).Five rules in
packages/linteach carry their own copy of "registry-injected columns present on almost every object but absent from authoredfields", and they have already drifted from one another:validate-widget-bindings.ts:238id, 4 audit,owner_id,organization_id,tenant_id,user_id,deleted_atvalidate-page-field-bindings.ts:72validate-widget-bindings"validate-translation-references.ts:173validate-react-page-props.ts:214validate-flow-template-paths.ts:93name,owner,is_deleted,record_type; its comment says it "mirrorsvalidateFormLayout's system-field set plus the audit/tenant columns fromFIELD_GROUP_SYSTEM_FIELDS" — i.e. it names the canonical source and then hand-copies anywayThis is exactly the shape #3786 fixed for the audit-provenance family: a four-name list hand-copied four times across two repos, each under a comment asking to be kept in sync with one of the others. The spec now owns two declarations that between them cover the whole set:
FIELD_GROUP_SYSTEM_FIELDS(@objectstack/spec/data) — audit provenance +organization_id/tenant_id/is_deleted/deleted_atSystemFieldName(@objectstack/spec/system) —id,created_at,updated_at,owner_id,tenant_id,user_id,deleted_atvalidate-searchable-fields.ts(#4328) derives from both rather than adding a sixth copy:Suggested fix: lift that into one module-local export in
packages/lint(e.g.system-fields.ts) and point the five existing rules at it. Two judgement calls the conversion has to make deliberately rather than by accident:is_deleted), which only makes those rules more permissive — safe, and the direction the comments already argue for ("deliberately generous: over-inclusion costs at worst a missed warning; under-inclusion costs a false one").validate-flow-template-pathsadditionally exemptsname,ownerandrecord_type, which are not system columns in the same sense —namein particular is an ordinary authored field on most objects. Whether those belong in the shared set or stay local to that rule needs a decision, not a mechanical merge.Not folded into #4328 to keep a new gating rule's diff reviewable.