fix(lint): the seven system-field exemption lists derive from the spec's declarations (#4330) - #4339
Merged
Merged
Conversation
…c's declarations (#4330) Five rules each carried their own hand-copy of "registry-injected columns present on almost every object but absent from authored fields", and they had already drifted — two more copies (validate-translation-references' extended list, validate-hook-body-writes' union) appeared while the issue was open. Same shape #3786 removed from the audit-provenance family. One module now owns the answer: system-fields.ts derives SYSTEM_FIELDS from FIELD_GROUP_SYSTEM_FIELDS (@objectstack/spec/data) + SystemFieldName (@objectstack/spec/system), and all seven field-resolving rules consume it. A pin test holds the boundary both ways: exactly the two declarations' union, and none of the rule-local exemptions. The two judgement calls the issue asked for, made deliberately: - The derived union is a superset of the four identical copies (adds is_deleted) and of flow-template-paths' set (adds user_id). Both are the permissive direction the rules' own comments argue for: over-inclusion costs at worst a missed warning, under-inclusion a false one. - name / owner / record_type (and the legacy physical spellings _id / space) are NOT spec system columns — name is an ordinary authored field on most objects — so they stay rule-local next to each rule's reason (IMPLICIT_FIELDS / IMPLICIT_HEADS extensions) instead of widening every field-existence rule in the package. Closes #4330 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D8QhQz2V6VH1SX5SQ1nAgk
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 2 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
marked this pull request as ready for review
July 31, 2026 07:04
xuyushun441-sys
pushed a commit
that referenced
this pull request
Jul 31, 2026
Conflict in validate-hook-body-writes.ts, resolved in main's favour and then some. #4339 replaced this rule's hand-copied `SYSTEM_FIELDS` list with `IMPLICIT_FIELDS` — derived from the spec via the package-shared `system-fields.ts` (#4330) — which supersedes the `BODY_WRITE_SYSTEM_FIELDS` rename this branch had introduced for the same reason. So the branch drops its rename and exports `IMPLICIT_FIELDS` instead: the action rule shares the derived set rather than the hand-copied one, which is strictly the outcome both changes were after.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #4330.
What
Five rules in
packages/linteach carried their own hand-copy of "registry-injected columns present on almost every object but absent from authoredfields" — and by the time this lands there were seven:validate-translation-referenceshad grown_id/name/spacebeyond the list the issue recorded, and #4305 addedvalidate-hook-body-writeswith its own union variant. Exactly the shape #3786 removed from the audit-provenance family.One module now owns the answer:
packages/lint/src/system-fields.ts— exportsSYSTEM_FIELDS, derived from the spec's two declarations:FIELD_GROUP_SYSTEM_FIELDS(@objectstack/spec/data) andSystemFieldName(@objectstack/spec/system). All seven field-resolving rules consume it;validate-searchable-fields' local derivation (feat(lint): catch a stalesearchableFieldsentry at authoring time (#4254 follow-up) #4328) moved here.system-fields.test.ts— pins the boundary in both directions: the set contains exactly the two declarations' union, and none of the rule-local exemptions (name,owner,record_type,_id,space).The two judgement calls the issue asked for
widget-bindings,page-field-bindingsandreact-page-propsnow also exemptis_deleted;flow-template-pathsnow also exemptsuser_id. Both are the permissive direction the rules' own comments argue for: over-inclusion costs at worst a missed warning on asystemFields: falseobject, under-inclusion a false finding (ADR-0072 D1).name/owner/record_type(and legacy_id/space) stay rule-local. None is a system column in the spec's sense —namein particular is an ordinary authored field on most objects, and exempting it package-wide would stop every field-existence rule from catching a reference to a genuinely missing field. The three rules that exempt any of them keep a local extension (IMPLICIT_FIELDS/IMPLICIT_HEADS) spreading the shared set, with the reason next to the names. The shared module's doc states this admission rule, and the pin test fails if one of them ever slips into the shared set.No exemption any rule previously had was removed — every conversion is behavior-preserving or strictly more permissive.
Also corrected in passing:
flow-template-paths' comment claimed to mirror "validateFormLayout's system-field set" —validateFormLayouthas no such set.Verification
pnpm testinpackages/lint: 40 files, 586 passed / 2 skippedpnpm typecheckinpackages/lint: clean@objectstack/lint(matches the fix(spec,plugin-approvals): the two approval vocabularies are derived, not hand-matched (#3786) #4295 / fix(hono,plugin-hono-server,runtime): one CORS source and one registry key — the last derivable copies from the #3786 sweep #4282 precedent for derive-not-copy fixes)🤖 Generated with Claude Code
https://claude.ai/code/session_01D8QhQz2V6VH1SX5SQ1nAgk
Generated by Claude Code