feat(server): Entity Expose API — unified field, filter, sort & relation control#1237
Merged
viniciusdacal merged 6 commits intomainfrom Mar 14, 2026
Merged
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
…port Replace `relations` config on EntityConfig/EntityDefinition with a new `expose` API that unifies field exposure, relation config, filter/sort allowlists, and AccessRule descriptors into a fractal structure mirroring the DB query API shape (select, allowWhere, allowOrderBy, include). - Add ExposeConfig and RelationExposeConfig types with full generics - select values accept `true | AccessRule` for descriptor-guarded fields - include constrains to model relation keys with typed target table columns - Nested include supports recursive relation exposure - Update entity() factory, crud-pipeline, route-generator, vertzql-parser - Update extractAllowKeys() to handle object-shaped allowWhere/allowOrderBy - Comprehensive type-level tests in expose-types.test-d.ts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…vel allowWhere/allowOrderBy validation, POCs - Apply expose.select in crud-pipeline to restrict response fields (list, get, create, update) - Add entity-level allowWhere/allowOrderBy validation to validateVertzQL() - Wire expose config through route-generator to validateVertzQL() - Export ExposeValidationConfig from vertzql-parser - POC #1: allowWhere/allowOrderBy constrained to PublicColumnKeys at type level, subset-of-select enforced at runtime (fallback approach — avoids generic bloat) - POC #2: T | null typing for descriptor-guarded fields via conditional mapped type - Update design doc with POC results Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add expose-evaluator.ts with evaluateExposeDescriptors() that pre-evaluates AccessRule descriptors once per request, producing static field sets - Descriptor-guarded select fields return null when user lacks access - Descriptor-guarded allowWhere/allowOrderBy fields reject with "not filterable"/"not sortable" - Add nullGuardedFields() to field-filter for nulling descriptor-denied fields - Wire evaluation through route-generator for all CRUD handlers - Add EvaluatedExposeValidation to validateVertzQL() for dynamic field checks Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… (Phase 3) - New page guides/server/entity-exposure.mdx covering expose config: select, allowWhere, allowOrderBy, include, descriptors, null semantics - Add navigation entry in docs.json after entities - Add card and feature row in server overview - Cross-reference from entities.mdx to new guide Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…safe cast - Change applySelect to accept Record<string, unknown> (it only checks key presence, not values — the Record<string, true> type was a lie when expose.select contains AccessRule descriptors) - Remove exposeSelect cast to Record<string, true> in crud-pipeline - Remove duplicate EvaluatedExposeValidation type — import EvaluatedExpose from expose-evaluator instead Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cd31f74 to
9bda37b
Compare
This was referenced Mar 14, 2026
Merged
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.
Summary
relationsconfig on entities with a unifiedexposeconfig that controls the entire VertzQL query surfaceexpose.selectrestricts which fields appear in API responses (withAccessRuledescriptor support for conditional visibility)expose.allowWhere/expose.allowOrderByrestrict which fields clients can filter/sort onexpose.includecontrols relation exposure with fractal structure mirroring the DB query APInull(not field omission) — typed asT | nullin the SDKguides/server/entity-exposurePublic API Changes
Breaking (pre-v1)
EntityConfig.relations→ removed, replaced byEntityConfig.exposeEntityDefinition.relations→ removed, replaced byEntityDefinition.exposeAdditions
ExposeConfig<TTable, TModel>— top-level expose configuration typeRelationExposeConfig<R>— relation-level expose with fractal structureExposeValidationConfig— interface for VertzQL validationevaluateExposeDescriptors()— pre-evaluates AccessRule descriptors per requestnullGuardedFields()— sets descriptor-guarded fields tonullin responsesapplySelect()signature widened toRecord<string, unknown>Backwards compatible
exposecontinue to work as before (all non-hidden fields exposed)includeconfig shape ({ select: { field: true }, allowWhere, allowOrderBy }) works throughexpose.includePhases
ExposeConfig/RelationExposeConfigtypes, entity factory update,expose.selectenforcement in CRUD pipeline, entity-levelallowWhere/allowOrderByvalidation in VertzQL parserevaluateExposeDescriptors()engine,nullGuardedFields(), route-generator wiring for per-request descriptor evaluationentity-exposure.mdxguide covering select, filters, descriptors, null semantics, fractal structureKnown limitations
Test plan
ExposeConfiggeneric inference,PublicColumnKeys,allowWhere/allowOrderByfield validityexpose.selectrestricts fields across all CRUD operations (list, get, create, update)allowWhere/allowOrderByvalidation returns 400 for disallowed fieldsnullwhen descriptor failswhere/orderByexposeexpose all non-hidden fields🤖 Generated with Claude Code