Skip to content

bug(flow-engine): nested user-schema fields are unusable #771

Description

@vitorbari

Summary

The storage layer already handles nested user-schema objects — CreateAttributesFromMap writes
dotted EAV keys (address.street) and honours x-unique on nested leaves, and
docs/design/flowengine/user-schema.md:125 documents this as supported. The flow engine's field
resolver sees only top-level scalars, so a nested property cannot be collected by any spelling.

Repro

User schema (accepted today by POST /schemas):

{
  "type": "object",
  "required": ["email", "address"],
  "properties": {
    "email": { "type": "string", "format": "email" },
    "address": {
      "type": "object",
      "required": ["street"],
      "properties": { "street": { "type": "string" } }
    }
  }
}

Every possible flow definition for it:

fields Result
["email", "address.street"] rejected: flow field: not a property in the user schema: "address.street"
["email", "address"] saves, renders a text box, then fails at the last step of registration with a non-field-specific ErrUserInvalid
["email"] rejected: required fields [address] in user schema are missing in the flow definition steps

There is no fourth option. The middle row is the worst: a definition-time type error deferred into
a live signup, after the user has already entered credentials.

Root cause

Three places, all in the resolver:

  • flow_field_resolver_schema.go:86-90 — exact properties[field] lookup, no path walk.
  • flow_field_resolver_schema.go:148-168 — no object/array case, so they fall through to
    FlowFieldTypeText.
  • flow_definition_validator.go:118,182-204 — required coverage compares the schema's root
    required array against whole field names.

packages/config/src/validate.ts mirrors this validator for zitadel plan and carries the same
three defects.

Expected

  • fields: ["address.street"] resolves to a scalar field, with the leaf's own validation
    keywords and x-unique.
  • Object- and array-typed properties are rejected at save time, never rendered as text.
  • Required coverage walks nested required; a leaf is required iff every ancestor is too.
  • Submitted flat keys un-flatten into the nested document the schema validates.

Metadata

Metadata

Assignees

No one assigned

    Labels

    goPull requests that update go code

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    Status
    In progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions