feat(spec,lint): reject userFilters on object list views (ADR-0053 phase 4)#2583
Merged
Conversation
…ase 4)
ADR-0053 reserves userFilters/quickFilters for page lists ("filters" mode); on
an object list view ("views" mode, where the ViewTabBar is the only nav
control) they are silently dropped. Land the phase-4 guardrail as a layered
defence so the wrong-context authoring mistake is caught without breaking
existing metadata:
- Type (author time): new ObjectListViewSchema = ListViewSchema minus
userFilters. Object built-in listViews + defineView list/listViews use it, so
userFilters on an object list view is a tsc error. Full ListViewSchema (page
filters mode) untouched.
- Runtime (back-compat): field STRIPPED at parse (default strip, no throw) —
existing metadata keeps loading; ObjectSchema.parse never fails on a stray
userFilters.
- Author/CI (actionable): new @objectstack/lint validateListViewMode, wired
into `os validate`, reports the wrong-context field PRE-parse (before the
schema strips it) with a fix hint.
Verified: spec 6673 tests + lint 122 tests green, turbo build (54 pkgs, tsc
typecheck) green, e2e normalize+lint chain catches both array/map forms.
Closes the schema half of objectui #2219; supersedes the interim runtime warn
in objectui #2220.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 93 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
New export from the ADR-0053 phase-4 guardrail; the api-surface check flagged it as 1 added / 0 breaking. Regenerated the snapshot via `pnpm --filter @objectstack/spec gen:api-surface`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Lands the ADR-0053 phase-4 guardrail:
userFilters/quickFiltersare reserved for page lists (InterfaceListPage, "filters" mode). On an object list view ("views" mode — where theViewTabBaris the only nav control) they were silently dropped at every layer. The runtime suppression is correct, but the schema still accepted the field, so an author (human or AI) got a valid schema, a passing build, and a toolbar with nothing where the filter controls should be.This is the framework/schema half of the fix. objectui #2219 tracks the issue; objectui #2220 shipped the interim runtime
console.warnthat this guardrail supersedes.Design — layered defence (no runtime break)
The hard constraint from ADR-0053 is no
modediscriminator: the mode is decided by context (object list → views; page list → filters), so a single schema can't tell which context it's in. The fix splits across three layers:ObjectListViewSchema = ListViewSchema.omit({ userFilters }); object built-inlistViews+defineViewlist/listViewsuse ituserFilterson an object list view is atscerror — the primary defence for AI-authored.ts.strict), so a strayuserFiltersis dropped at parseObjectSchema.parsenever throws — existing metadata keeps loading, no line-side break@objectstack/lintvalidateListViewMode, wired intoos validateThe full
ListViewSchemaused by page lists ("filters" mode) is untouched — pageuserFiltersstays valid.Why lint runs pre-parse
ObjectStackDefinitionSchema.objectsdeep-parses throughObjectSchema, so once the schema stripsuserFilters, a post-parse stack no longer has it. The rule therefore runs on thenormalizeStackInputoutput (pre-parse), where the field is still present. ConfirmednormalizeStackInputpreserves it.Changes
spec/src/ui/view.zod.ts— newObjectListViewSchema;ViewSchema.list/listViewsuse it.spec/src/data/object.zod.ts— object built-inlistViewsuses it.lint/src/validate-list-view-mode.ts(+ export) — new rule, scansobjects[*].listViews,views[*].list,views[*].listViews.cli/src/commands/validate.ts— wires the rule intoos validate(onnormalized, pre-parse).Testing
userFilters, page schema still accepts it). Zero regressions, so nothing depended on objectlistViewskeepinguserFilters.turbo run build --filter=@objectstack/cli...— 54 pkgs,tsctypecheck green.normalizeStackInput→validateListViewModecatches both array (objects) and map (views) forms.Rollout
Needs a
@objectstack/specrelease before objectui can bump and consume the tightened schema; objectui's runtime warn (#2220) already covers the gap in the meantime. objectui's hand-written mirror (packages/types) is intentionally not switched to import spec here — the twoListViewSchemacopies have drifted and that's a separate migration.🤖 Generated with Claude Code