Defined by token is rejected on integer-typed config keys by PrimitiveType validation

Problem/Motivation

Four config keys offer the _eca_token ("Defined by token") option in the UI but are declared type: integer in their schema. For these, the sentinel is rejected by primitive type validation, before the Choice constraint is ever consulted: PrimitiveTypeConstraintValidator evaluates filter_var('_eca_token', FILTER_VALIDATE_INT), which returns FALSE, and a violation is raised regardless of what the choice list contains.

Affected keys:

  • eca_route_match.request (modules/miscellaneous/src/Plugin/RouteTrait.php:67)
  • eca_token_load_route_param.request (same trait)
  • eca_write_log_message.severity
  • eca_enqueue_task_delayed.delay_unit

Steps to reproduce

  1. Add one of the four actions/conditions above to an ECA model.
  2. Set the affected field to "Defined by token".
  3. Validate the resulting eca.eca.* config against its typed schema.

Result: a PrimitiveType violation — the value is not a valid integer. Expected: no violation; the model is correct and works at runtime.

Proposed resolution

Not obvious, which is why this is filed separately rather than folded into #3590375 (closed).

The naive fix — changing type: integer to type: string — is not safe as things stand:

  • SchemaCheckTrait is strict about the PHP type of the stored value versus the schema class, so existing integer-stored values would start failing.
  • tests/modules/logging/config/install/eca.eca.eca_test_0006.yml stores severity: 6 as an integer, and would break.
  • Conversely, string-ifying the choice list would invalidate every existing integer-stored value in the wild.

Options worth evaluating:

  1. A dedicated schema type that accepts an integer or the sentinel.
  2. Migrating stored values to strings, with an update hook — larger blast radius, but removes the type conflict permanently.
  3. Not offering "Defined by token" on integer-typed keys at all, if the option is not genuinely useful there.

An audit of which of the four actually need the option would usefully narrow this.

Remaining tasks

  • Decide which of the four keys should keep the "Defined by token" option
  • Choose a representation that accommodates both integers and the sentinel
  • Add test coverage, including existing integer-stored values

User interface changes

None intended.

Data model changes

Possibly — depends on the option chosen above.


Related: this is the third distinct mechanism by which the "Defined by token" sentinel fails typed-config validation. #3590375 (closed) covers Choice constraints (the large majority, 69 keys) and #3590374 (closed) covers machine_name pattern validation. This issue covers PrimitiveType validation on integer-typed keys. All three reject a value the UI offers and the plugins implement.

Found while implementing #3590375 (closed).

AI-Generated: Yes (Used OpenCode to audit the _eca_token sentinel surface across ECA while implementing #3590375 (closed); these four keys were identified as unfixable by that issue's approach, and all file and line references were verified against the 3.1.x source.)

Change record: #3616767

Edited by drupalbot