Skip to content

fix(lint): the seven system-field exemption lists derive from the spec's declarations (#4330) - #4339

Merged
os-zhuang merged 1 commit into
mainfrom
claude/system-fields-lint-derive-3dsjuu
Jul 31, 2026
Merged

fix(lint): the seven system-field exemption lists derive from the spec's declarations (#4330)#4339
os-zhuang merged 1 commit into
mainfrom
claude/system-fields-lint-derive-3dsjuu

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Closes #4330.

What

Five rules in packages/lint each carried their own hand-copy of "registry-injected columns present on almost every object but absent from authored fields" — and by the time this lands there were seven: validate-translation-references had grown _id/name/space beyond the list the issue recorded, and #4305 added validate-hook-body-writes with 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 — exports SYSTEM_FIELDS, derived from the spec's two declarations: FIELD_GROUP_SYSTEM_FIELDS (@objectstack/spec/data) and SystemFieldName (@objectstack/spec/system). All seven field-resolving rules consume it; validate-searchable-fields' local derivation (feat(lint): catch a stale searchableFields entry 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

  1. The derived union is a superset of the hand-copies — accepted. widget-bindings, page-field-bindings and react-page-props now also exempt is_deleted; flow-template-paths now also exempts user_id. Both are the permissive direction the rules' own comments argue for: over-inclusion costs at worst a missed warning on a systemFields: false object, under-inclusion a false finding (ADR-0072 D1).
  2. name / owner / record_type (and legacy _id / space) stay rule-local. None is a system column in the spec's sense — name in 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" — validateFormLayout has no such set.

Verification

🤖 Generated with Claude Code

https://claude.ai/code/session_01D8QhQz2V6VH1SX5SQ1nAgk


Generated by Claude Code

…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
@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Jul 31, 2026 6:51am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/m labels Jul 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/lint.

2 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/automation/hook-bodies.mdx (via @objectstack/lint)
  • content/docs/permissions/authorization.mdx (via @objectstack/lint)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang marked this pull request as ready for review July 31, 2026 07:04
@os-zhuang
os-zhuang merged commit ade7be4 into main Jul 31, 2026
17 checks passed
@os-zhuang
os-zhuang deleted the claude/system-fields-lint-derive-3dsjuu branch July 31, 2026 07:05
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

lint: five hand-copied SYSTEM_FIELDS lists in packages/lint should derive from the spec's declarations

2 participants