Conversation
## Context Billing objects need to route themselves to one of a customer's connections. The table, the resolution cascade and the connection codes already shipped; nothing wrote the override rows yet. This adds the first write path, behind the multi_connection flag. ## Description The wallet endpoints and each nested recurring transaction rule accept a connections object keyed by category (payment, tax, accounting, crm). An entry either names a connection code, which pins it, or a behavior: skip never falls back, inherit drops the choice. An omitted category changes nothing. Inherit is never persisted, since resolution reads a missing row as inheritance. An unknown code is a validation error, and connections sent while the flag is off are refused rather than ignored. Validation and persistence are polymorphic in the owner, so the subscription and invoice surfaces can reuse them.
## Context ING-466 added the REST write path for wallet connections along with the shared validation and persistence services. This exposes the same routing to the UI, which drives wallets through GraphQL (dive-in T19-GQL). ## Description A new ConnectionsInput carries one optional choice per category — payment, tax, accounting and crm — each either a connection code or a behavior. The behavior enum is limited to inherit and skip, since specific is implied by supplying a code. The argument is added to the wallet create and update inputs and to both recurring-rule inputs, and the dumped schema is regenerated. No new service logic was needed: the mutations already forward their arguments to the same write path as REST, so validation, the multi_connection gate and persistence come with it. One fix was required. GraphQL passes nested inputs as an InputObject rather than a Hash, which the validator rejected outright, so both shared services now normalise at their boundary. The conversion applies only when the value is not already a Hash, because HashWithIndifferentAccess#to_hash returns string keys and silently broke the lookups on the recurring-rule path.
mariohd
marked this pull request as ready for review
September 11, 2026 17:09
Contributor
|
Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green HOLD — recurring-rule creation can silently accept an unresolvable connection.
|
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.
[> Stacked on #ING-466 — base this PR on
ing-466, notmain. It builds on the shared connection services introduced there, and amends two of them.Context
ING-467. The GraphQL counterpart of per-object connection routing for wallets (dive-in T19-GQL). ING-466 added the REST write path plus the shared validation and persistence services; the UI drives wallets through GraphQL, so it needs the same routing exposed there.
Description
A new
ConnectionsInputcarries one optional choice per category — payment, tax, accounting, crm — each either a connectioncodeor abehavior:specificis deliberately absent from the enum — it's implied by supplying a code. The argument is added toWallets::Create/UpdateInputand both recurring-rule inputs, andschema.graphql/schema.jsonare regenerated (both are spec-enforced). The existingpaymentMethodinput is untouched, and everything stays behind themulti_connectionflag.No new service logic. The mutations already forward their arguments to the same write path as REST, so validation, the flag gate and persistence came for free.
Reviewer note — why this touches two ING-466 files
GraphQL passes nested inputs as
GraphQL::Schema::InputObject, notHash, and the validator guards withis_a?(Hash)— so every GraphQL request would have been rejected asinvalid_connections. Both shared services now normalise at their boundary, converting only when the value isn't already a Hash:HashWithIndifferentAccess#to_hashreturns string keys, which silently brokechoice[:code]on the recurring-rule path. ING-462 and the future invoice surfaces share these services, so the fix benefits them too.Testing
9 new mutation examples — 4 on create, 5 on update, the latter covering
inheritclearing a row, the per-rule path throughRecurringTransactionRules::UpdateService, an unresolvable code, and the flag gate. Regression: 691 examples across the shared services, the wallet REST suites, both mutations and the schema-dump spec. All green, Rubocop clean.