Skip to content

feat(plugins): Register the standard matching rules and generators as core plugin capabilities - #548

Merged
rholshausen merged 1 commit into
masterfrom
feat/host-provided-core-matching
Aug 7, 2026
Merged

feat(plugins): Register the standard matching rules and generators as core plugin capabilities#548
rholshausen merged 1 commit into
masterfrom
feat/host-provided-core-matching

Conversation

@rholshausen

Copy link
Copy Markdown
Contributor

Proposal 009: let a plugin delegate a standard Pact rule to the host it is running under, instead of reimplementing it. The mechanism has been in the plugin driver since 006; nothing registered anything behind it, so a plugin naming a standard rule resolved the catalogue entry and then failed with "No core field matcher registered for 'type'".

Catalogue entries:

  • the matcher entries are re-keyed by the name the rule carries in a request (MatchingRule::name(), the same string the driver puts in MatchFieldRequest.rule.type) rather than the specification version prefixed to the name, which moves to a spec-version value on the entry;
  • generator entries are added - there were none at all, so find_field_ generator("Uuid") failed at the catalogue step and no generator/* capability was ever advertised;
  • both lists are now exactly the rules and generators this crate implements, pinned by a test that compares them against the enum variants, with an exhaustive match so a new variant fails to compile until it has an entry.

Handlers:

  • CoreFieldRuleMatcher answers for the 16 rules that act on a single value, and CoreFieldValueGenerator for the 12 generators that are a pure function of their configuration and the test context;
  • the collection-wide rules (min-type, values, array-contains, each-key/each-value) and the ArrayContains generator are registered too, but answer with why they can not be applied one value at a time - they stay host-only per 006's non-goals, and a plugin naming one should be told that rather than that nothing is registered;
  • a rule or generator name this crate does not provide is an error, not a call back out: an unrecognised name parses into the Plugin carrier variant, which would send the callback straight back to a plugin.

Two bugs this turned up:

  • MatchingRule::Equality on &Bytes built its mismatch message with split_at(10), which panics for any value shorter than 10 bytes;
  • rule and generator configuration crosses the plugin interface as a google.protobuf.Struct, which has one number type, so a plugin's min: 2 arrives as 2.0 and the integer accessors reading it fall back to the attribute's default - a RandomInt(5, 5) from a plugin generated from 0..10. Whole floats are put back to integers on the way in.

… core plugin capabilities

Proposal 009: let a plugin delegate a standard Pact rule to the host it is
running under, instead of reimplementing it. The mechanism has been in the
plugin driver since 006; nothing registered anything behind it, so a plugin
naming a standard rule resolved the catalogue entry and then failed with
"No core field matcher registered for 'type'".

Catalogue entries:

- the matcher entries are re-keyed by the name the rule carries in a
  request (`MatchingRule::name()`, the same string the driver puts in
  `MatchFieldRequest.rule.type`) rather than the specification version
  prefixed to the name, which moves to a `spec-version` value on the entry;
- generator entries are added - there were none at all, so `find_field_
  generator("Uuid")` failed at the catalogue step and no `generator/*`
  capability was ever advertised;
- both lists are now exactly the rules and generators this crate
  implements, pinned by a test that compares them against the enum
  variants, with an exhaustive match so a new variant fails to compile
  until it has an entry.

Handlers:

- `CoreFieldRuleMatcher` answers for the 16 rules that act on a single
  value, and `CoreFieldValueGenerator` for the 12 generators that are a
  pure function of their configuration and the test context;
- the collection-wide rules (`min-type`, `values`, `array-contains`,
  `each-key`/`each-value`) and the `ArrayContains` generator are
  registered too, but answer with why they can not be applied one value at
  a time - they stay host-only per 006's non-goals, and a plugin naming one
  should be told that rather than that nothing is registered;
- a rule or generator name this crate does not provide is an error, not a
  call back out: an unrecognised name parses into the `Plugin` carrier
  variant, which would send the callback straight back to a plugin.

Two bugs this turned up:

- `MatchingRule::Equality` on `&Bytes` built its mismatch message with
  `split_at(10)`, which panics for any value shorter than 10 bytes;
- rule and generator configuration crosses the plugin interface as a
  `google.protobuf.Struct`, which has one number type, so a plugin's
  `min: 2` arrives as `2.0` and the integer accessors reading it fall back
  to the attribute's default - a `RandomInt(5, 5)` from a plugin generated
  from `0..10`. Whole floats are put back to integers on the way in.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@rholshausen
rholshausen merged commit 251d86b into master Aug 7, 2026
25 checks passed
@rholshausen
rholshausen deleted the feat/host-provided-core-matching branch August 7, 2026 06:34
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