fix(core): validate multi-column fields before splitting into physical columns#794
Conversation
…l columns Move the splitColumns step (storage image()/file() in Keystone-parity mode) to run AFTER validateFieldRules instead of inline inside executeFieldResolveInputHooks. Previously an unrecognised value from a field's resolveInput fallback bypassed validation entirely, since it was split into null/undefined physical columns before the field's Zod schema ever saw it. Updated in lockstep across the top-level Hook Pipeline and both nested create/update write paths. Closes #789 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QPX69aoqSuBMAwD3bDCSWk
🦋 Changeset detectedLatest commit: 0cd584b The changes in this PR will be included in the next version bump. This PR includes changesets to release 9 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Self-reviewOverviewMoves the Correctness
Minor (non-blocking) observation
Test coverage
SecurityNo change to the access-control surface — the field-level write-access gate around the split is identical to before, just relocated. No new undeclared-key or bypass paths introduced ( No blocking issues found. Generated by Claude Code |
Coverage Report for Core Package Coverage (./packages/core)
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||
Coverage Report for UI Package Coverage (./packages/ui)
File CoverageNo changed files found. |
Coverage Report for CLI Package Coverage (./packages/cli)
File CoverageNo changed files found. |
Coverage Report for Auth Package Coverage (./packages/auth)
File CoverageNo changed files found. |
Coverage Report for Storage Package Coverage (./packages/storage)
File CoverageNo changed files found. |
Coverage Report for RAG Package Coverage (./packages/rag)
File CoverageNo changed files found. |
Coverage Report for Storage S3 Package Coverage (./packages/storage-s3)
File CoverageNo changed files found. |
Coverage Report for Storage Vercel Package Coverage (./packages/storage-vercel)
File CoverageNo changed files found. |
Summary
splitColumnsstep for multi-column fields (currently only@opensaas/stack-storage'simage()/file()indb.columns: 'keystone'mode) so it runs aftervalidateFieldRulesinstead of inline insideexecuteFieldResolveInputHooks(Hook Pipeline Phase 1.5, before validation).resolveInput"let validation catch it" fallback was split intonull/undefinedphysical columns and written silently —validateFieldRulesnever saw the logical field because it had already been deleted fromresolvedData.executeFieldResolveInputHooks(packages/core/src/hooks/index.ts) now only resolves each field's value under its logical key — no split. A newsplitMultiColumnFieldsfunction performs the split, gated by the exact same field-level write-access check (checkFieldAccess) that previously ran inline, so a denied field still drops its logical key and contributes none of its per-part columns (sudo still bypasses).resolveInput → validate → validateFieldRules → filterWritableFieldssequence:packages/core/src/context/hook-pipeline.ts(top-level Write Pipeline) — added as Phase 4, after Phase 3 (validateFieldRules).packages/core/src/context/nested-operations.ts—processNestedCreateandprocessNestedUpdate(nested relationship writes).CONTEXT.md's Hook Pipeline glossary entry and comments infield-access.tsthat referenced the old gate location.Test plan
packages/core/src/access/multi-column-read-write.test.tsretargeted: the split-behavior tests now drive the newsplitMultiColumnFieldsfunction directly (access-gate and null-split coverage preserved unweakened); added a new describe block provingexecuteFieldResolveInputHooksno longer splits and passes unrecognised values through unsplit under the logical key.packages/core/tests/multi-column-validation-ordering.test.ts— fullcontext.dbintegration tests proving:create/updatewith an unrecognised multi-column value throwsValidationErrorand never reaches the DB;createandupdate;null/undefined, a valid shaped object) continue to split and persist identically to before.pnpm testpasses inpackages/core(44 files / 898 tests) andpackages/storage(7 files / 148 tests, unaffected).pnpm build(core),pnpm lint,pnpm manypkg fix,pnpm formatall clean.Closes #789
Generated by Claude Code