Route store integrations using trusted configuration

Select integration providers from server-owned store configuration and keep caller input from choosing external destinations or handlers.

Znode 10PatternAdvancedGCG engineering guide
In this guide
Authorized business object Trusted store Owned route policy Registered handler Bounded transport
Business context selects an approved provider through server-owned configuration.

Two stores, one integration boundary

A commerce platform serves two stores that submit orders to different operational systems. Reusing the integration boundary is sensible. Allowing a request to name the destination URL is not. A caller who can change routing can send a valid order to the wrong business system even when the payload itself passes validation.

Make store context authoritative and routing configuration server-owned. The request describes the business operation. The application determines where that operation is allowed to go. Keep those responsibilities separate from the first adapter method through the eventual provider transport.

Resolve the store from the business object

For an order operation, resolve the stored order through an authorized supported API and derive its store from that record. Do not assume the current browser store is the order's store. Background processing may have no browser context at all, and an operator may work across several stores.

For other operations, document the trusted source of store identity in the target contract. If the source is missing or ambiguous, stop rather than selecting a convenient default. Mixed-store batches need to be rejected or partitioned deliberately before provider dispatch, with each item retaining its own authorized context.

Resolve a finite registered provider

StoreRoutePolicy.cs walks an ordered set of trusted settings and resolves only an exact registered provider/operation pair. Explicit Disabled stops routing, while missing configuration and unsupported operations raise distinct errors.

Build orderedSettings from the Store's operation, family, and default settings, and use an ordinal HashSet for registeredProviderOperations. Derive the Store from the authorized business object before reading those settings. Attach this policy to your configured legacy connector's touchpoint handler; a Data Exchange processor has a separate invocation contract.

Routing/StoreRoutePolicy.cs csharp

using System;
using System.Collections.Generic;
namespace Gcg.DeveloperExamples.Routing
{
public sealed class RouteResult
{
public string Provider { get; }
public bool Disabled { get; }
public RouteResult(string provider, bool disabled)
{ Provider = provider; Disabled = disabled; }
}
public static class StoreRoutePolicy
{
public static RouteResult Resolve(string operation, IEnumerable<string> orderedSettings,
ISet<string> registeredProviderOperations)
{
if (string.IsNullOrWhiteSpace(operation)) throw new ArgumentException("Operation required.");
foreach (var setting in orderedSettings)
{
if (string.IsNullOrWhiteSpace(setting)) continue;
if (string.Equals(setting, "Disabled", StringComparison.Ordinal))
return new RouteResult(null, true);
if (!registeredProviderOperations.Contains(setting + ":" + operation))
throw new InvalidOperationException("Provider does not support this operation.");
return new RouteResult(setting, false);
}
throw new InvalidOperationException("No integration route is configured.");
}
}
}
// Example server-owned configuration:
// Resolve("orders.create", new[] { null, "North", "Fallback" },
//         new HashSet<string>(StringComparer.Ordinal) { "North:orders.create" });
// Read settings for the store resolved from the authorized order, never request fields.

Separate routing from delivery mechanics

A route determines the provider for a command. A durable delivery system determines how that command is attempted and reconciled. Persist enough trusted context with the delivery to explain the original decision. Decide explicitly whether a replay uses the original route or a reviewed replacement.

Legacy ERP connector hooks and Data Exchanges custom processors are distinct Znode integration mechanisms. A custom router behind one does not automatically implement the other. Verify the actual trigger and supported request model for the selected mechanism, and avoid widening a gateway route into a generic proxy just to reuse dispatch code.

Test the negative configuration cases

Create two fake providers that record only sanitized metadata. Send equivalent operations for two fictional stores and verify the intended provider receives each. Attempt to override the provider through a request body field, header, or query parameter; the route must remain server-owned.

Then test explicit Disabled, no configuration, unknown provider, unsupported operation, a cross-store order lookup, and an unavailable configuration source. Exercise a mixed-store batch if it is supported. Record the expected outcome for every case, including whether work is rejected before enqueueing or held for an operational correction.

  • Bound configuration reads and response sizes.
  • Cache successful configuration only under a documented freshness policy.
  • Never put credentials in store attributes or public diagnostics.

Make route changes reviewable

Expose a safe operational summary of store, operation, configured provider identifier, and enabled state. Keep actual destinations and secrets restricted. Log a correlation reference and sanitized routing failure category so support can identify a configuration problem without reading the order payload.

A store-aware integration becomes maintainable when its decisions are deterministic and explainable. The strongest design has few route levels, exact provider registration, and a deliberate answer for missing or disabled configuration. That prevents a helpful-looking fallback from turning into a shipment, invoice, or order in the wrong system.

References and further reading

Bring your next engineering question.

Design a multi-store integration

Explore how GCG can help

Independent guidance from GCG. Znode is a trademark of its owner. Examples use fictional data and are not official platform documentation. Suggest a correction.