Skip to content

feat: add FieldType/FieldDefault AST validators with schema-aware allowlists#1153

Merged
pyramation merged 1 commit into
mainfrom
devin/1778713957-field-type-ast-validator
May 14, 2026
Merged

feat: add FieldType/FieldDefault AST validators with schema-aware allowlists#1153
pyramation merged 1 commit into
mainfrom
devin/1778713957-field-type-ast-validator

Conversation

@pyramation
Copy link
Copy Markdown
Contributor

Summary

Adds a new field-types module to graphile-sql-expression-validator that validates structured FieldType/FieldDefault JSONB models — the precursor to migrating the metaschema API from raw SQL strings to safe, structured objects (tracked in constructive-planning#786).

New module (src/field-types.ts):

  • FieldType / FieldDefault TypeScript interfaces matching the JSONB model design
  • Converters: object → pgsql-parser AST (fieldTypeToAst, fieldDefaultToAst)
  • Converters: object → canonical SQL text (fieldTypeToSql, fieldDefaultToSql)
  • validateFieldType() — structural checks, forbidden OID-alias type rejection, schema allowlists, interval range validation
  • validateFieldDefault() — structural checks → AST conversion → full expression validation via existing validateAst() machinery (function/schema allowlists, forbidden type casts, recursive depth limiting)
  • allowedSchemaFunctions option for per-schema function allowlists (e.g. { jwt_public: ['current_user_id', 'current_origin'] })

Bug fix (src/validator.ts):

  • Added 'isnull' to ALLOWED_NODE_TYPES — was missing alongside ival, sval, fval, boolval, bsval, causing NULL literals ({ A_Const: { isnull: true } }) to be rejected by the existing validator.

Test suite (__tests__/field-types.test.ts):

  • 155 new tests covering all type categories, real-world defaults from constructive-db generators, SQL injection prevention, forbidden types, and invalid structure rejection. All 271 tests pass (155 new + 116 existing).

Review & Testing Checklist for Human

  • allowedSchemaFunctions merging logic (security-critical): Functions from the schema map are merged into the flat allowedFunctions list before passing to validateAst(). This means e.g. current_user_id becomes globally allowed by function name — the schema gate in validateAst provides the second check, but verify this can't create unintended cross-schema allowances.
  • isnull addition to ALLOWED_NODE_TYPES: Confirm isnull only appears as a property inside A_Const nodes in pgsql-parser and cannot be used as a standalone node type to bypass validation.
  • Hand-built AST format correctness: The converters construct pgsql-parser AST nodes manually (TypeName, FuncCall, A_Const, TypeCast). Spot-check a few complex cases (e.g. geometry(Point, 4326), encode(gen_random_bytes(16), 'hex'), '{}'::jsonb) against actual pgsql-parser output to verify structural match.
  • IDENTIFIER_PATTERN (/^[a-zA-Z_][a-zA-Z0-9_]*$/): Verify this isn't too restrictive for legitimate type/function identifiers (e.g. hyphenated names, unicode) or too permissive for security purposes.

Suggested test plan: Run npx jest --no-coverage in graphile/graphile-sql-expression-validator/ and review the real-world defaults test block to confirm coverage of all patterns from constructive-db generators.

Notes

  • This is a validator-only PR — no API changes, no generator updates, no database schema changes. The intent is to have the validator solid and tested before proceeding to API integration.
  • Related planning: constructive-planning#786

Link to Devin session: https://app.devin.ai/sessions/1c5e3fccccaa40f1b327a07423ab947d
Requested by: @pyramation

…owlists

- Add FieldType and FieldDefault TypeScript types for structured JSONB models
- Add converters: FieldType → TypeName AST, FieldDefault → expression AST
- Add fieldTypeToSql/fieldDefaultToSql for canonical SQL text output
- Add validateFieldType with identifier checks, forbidden types, schema allowlists
- Add validateFieldDefault with recursive validation, schema-function maps,
  depth limits, and full expression AST validation via existing validator
- Add allowedSchemaFunctions option for per-schema function allowlists
- Fix: add missing 'isnull' to ALLOWED_NODE_TYPES (NULL literal support)
- 155 new tests covering all type categories, real-world defaults,
  SQL injection prevention, and invalid structure rejection
@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@pyramation pyramation merged commit ff34141 into main May 14, 2026
37 checks passed
@pyramation pyramation deleted the devin/1778713957-field-type-ast-validator branch May 14, 2026 00:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant