SeriesPart 59 of Building a property procurement platform on MedusaView the cluster →
Medusa & ArchitectureArticle

Your sales rep owns the Northeast. Why can they still open a Texas order?

How we turned supplier roles, geographic territories and customer portfolios into enforceable property-scoped access across a Medusa marketplace.

We Are Souk article cover: Your sales rep owns the Northeast. Why can they still open a Texas order?
Souk EngineeringCommerce architectureAug 2026·11 min read
Key takeaways
  • A supplier adds a second Account Manager to its marketplace team.
  • One person covers the Northeast.
  • Most commerce platforms understand an authenticated team member and a list of permissions.
  • For a B2B marketplace built on Medusa, we turned that commercial idea into an application rule.

The client problem

A supplier adds a second Account Manager to its marketplace team.

One person covers the Northeast. Another looks after a portfolio of national accounts. The supplier expects each rep to see their customers, answer their quote requests and follow their orders. It does not expect either person to browse the other rep's commercial pipeline by changing a URL.

Most commerce platforms understand an authenticated team member and a list of permissions. They do not automatically understand a supplier's sales territory, nor how that territory should constrain an order, return, quote, property or performance dashboard.

For a B2B marketplace built on Medusa, we turned that commercial idea into an application rule. A role defines what an Account Manager may do. A separate scope defines which customer properties they may do it for. Geographic zones or named customer groups resolve into one property set, and the backend applies that same set to lists and direct resource access.

The territory stopped being a label on a profile. It became part of the marketplace's permission model.

The client problem: delegation without opening the whole supplier account

A supplier administrator needs to delegate daily commercial work.

Account Managers should be able to read the orders relevant to them, respond to quotes, understand customer activity and follow operational issues. They do not need authority over the supplier's pricing policy, shipping configuration, inventory mutations or team administration.

Even the permitted work needs a perimeter. A rep covering New York and New Jersey should not see an unrelated order in California. A key-account rep may serve a named group of organisations regardless of geography. A Store Owner responsible for warehouses has a different perimeter again: stock locations, not customer territories.

A single “sales rep” boolean cannot express those distinctions.

Nor can the frontend solve them alone. Hiding a navigation item makes the interface cleaner, but a user can still call an API endpoint or open a bookmarked resource. The backend needs enough business context to decide whether the authenticated person may perform this action on this specific record.

The design therefore separates capability from commercial scope.

First answer what the person may do

The vendor team uses three operational roles.

An Admin owns the supplier account and its strategic settings. A Store Owner operates assigned stock locations. An Account Manager handles customer-facing commercial work inside an assigned market.

For the Account Manager, the capability matrix permits reading orders, products, inventory and customers, reading analytics and handling quotes. It withholds inventory writes, pricing, shipping settings and team administration.

That matrix is intentionally expressed in business capabilities rather than pages. “Can handle quotes” remains meaningful if the interface moves a quote action from one screen to another. “Can visit /quotes” would tie security to today's navigation.

The role check answers the first question: is this type of action part of the person's job?

It does not answer the second: does this particular customer, quote or order belong to the person's remit? That is the scope layer.

Represent a commercial territory as business data

A geographic territory belongs to one supplier.

It has a name that the team recognises and a collection of geographic zones. A zone can cover a country, a province or state, a city, or a set of postal-code patterns. The model also supports the information required for radius-based definitions.

Those zones are not attached directly to orders. They describe the supplier's sales organisation. The platform compares them with the structured geography of customer properties and resolves the properties currently inside the territory.

That indirection is valuable. If a new property opens in an existing covered state, the commercial perimeter can include it from the same territory rule. If the supplier redraws a territory, the definition changes in one place instead of rewriting permissions on every historical customer record.

The administration interface can show and edit the commercial map. The backend remains responsible for interpreting it.

Support named customer portfolios as well as geography

Not every sales organisation divides work by map.

A supplier may have one Account Manager for a strategic property group, a national customer or a collection of organisations with negotiated commercial terms. Those properties can span several states.

We introduced an Account Manager scope as a small polymorphic record. A geographic scope points to a territory. A customer-group scope points to a property group. In both cases, the result is the same kind of value for downstream commerce: a set of property IDs.

For a geographic scope, the resolver matches the territory's zones against property addresses. For a customer-group scope, it combines the properties attached directly to the group with properties belonging to its included organisations.

The rest of the permission system does not need separate order logic for “Northeast” and “National Accounts”. It asks one question: which properties are in this Account Manager's effective scope?

That common output is what makes the model reusable.

Resolve every commerce resource back to a property

Orders and quotes do not contain a sales-territory field, and they should not need one.

The marketplace already knows which property a purchase serves. The permission layer resolves each resource back to that business anchor.

An order or purchase order follows its property link. A return follows its order. A quote carries its property. A reservation follows its line item and order. A property identifies itself. An organisation resolves to the properties it owns.

The guard then intersects those properties with the Account Manager's effective property set. Any match grants access for that resource, subject to the role's capability. No match denies it.

This creates a comprehensible chain:

Account Manager → commercial scope → allowed properties
resource → owning property → access decision

The salesperson thinks in territories and accounts. The commerce engine thinks in durable resource relationships. The property connects the two.

Apply the same rule to lists and direct URLs

Permission bugs often appear when a system protects one route shape but not another.

Filtering the orders table is insufficient if /orders/:id returns any seller order. Protecting order detail is insufficient if analytics aggregate the entire supplier account. A quote comment endpoint can expose or mutate a resource even when the quote list is correct.

The project applies scope in both directions.

Collection routes for orders, quotes, properties, organisations, reservations and named statistics resolve the Account Manager's property IDs and constrain their queries. Resource routes use reusable guards for orders, returns, purchase orders, quotes, properties, organisations and reservations. Contextual actions such as creating a reservation or posting on a quote perform their own scope check.

The same business rule therefore survives different interface paths.

If a resource is outside the scope, the API responds as though it were not found. That avoids confirming that another rep's order or quote exists. If a scope record is stale or malformed, the resolver fails closed rather than interpreting missing context as unrestricted access.

Do not confuse seller ownership with Account Manager scope

Every territory and customer-group scope also belongs to a seller.

That boundary prevents a supplier administrator from linking an Account Manager to another supplier's commercial definition. Invitation and role-update paths verify ownership before creating the assignment.

The final decision has three layers:

  1. the authenticated member belongs to the supplier;
  2. their role permits this capability;
  3. their scope contains the property behind this resource.

Removing any layer produces a different bug. Seller ownership alone would expose every customer record inside the account. Scope alone could cross tenants if a foreign territory identifier were accepted. Role alone would allow an Account Manager to change strategic settings.

Together, the three layers mirror how the supplier actually delegates responsibility.

Make the scope part of the invitation

Access should be correct before the new colleague accepts an invitation.

When an Admin invites an Account Manager, the request includes the intended scope: either a geographic territory or a customer group. The system validates that definition against the same seller and links the pending invite to the scope.

The territory view can therefore distinguish an active member from a pending invite without losing the intended assignment.

A Store Owner is allowed to invite an Account Manager for operational continuity, but cannot use that delegation to create another Admin or redefine strategic roles. The backend validates the caller and the target role; the frontend merely presents the permitted options.

The scope model also prevents one exclusive territory or property group from being silently assigned to two people. Database uniqueness provides a concurrency safety net, while application checks return a useful conflict before creating a duplicate live member or invite link.

The team sees a clear ownership decision rather than a race-dependent permission state.

Replace access when a role changes

People move between responsibilities.

A Store Owner may become an Account Manager. An Account Manager may become an Admin. Simply updating the role string would leave old stock-location or territory links behind, ready to reappear in an unexpected code path.

The role-change workflow validates the target assignment first. It records the previous state, removes the old stock-location and Account Manager links, and creates only the links required by the new role. Compensation data allows the previous relationship to be restored if the transition fails midway.

That gives role changes replacement semantics: the new access model supersedes the old one.

It also keeps the request explicit. A Store Owner assignment requires stock locations. An Account Manager assignment requires a scope. The system refuses an incomplete transition instead of guessing a default territory or silently granting a seller-wide view.

This lifecycle detail is where many apparently sound permission models deteriorate. Creation is easy; safe mutation is the real test.

Keep operational users out of strategic settings

Territory scope does not make an Account Manager a smaller Admin.

The Account Manager may handle the quotes and orders in their portfolio, but cannot change the price lists, shipping configuration, inventory or team model that determine the supplier's wider commercial policy.

Likewise, a Store Owner has operational write access to assigned locations but not pricing or supplier settings. Their ability to invite an Account Manager does not expand their own permissions.

This produces deliberate delegation:

  • strategic controls remain with the supplier Admin;
  • location operations belong to Store Owners within assigned warehouses;
  • customer operations belong to Account Managers within assigned properties.

The model follows responsibilities rather than an abstract ladder where every higher-looking role inherits everything below it.

Test the permission algebra, not only the happy screen

We test the components that turn the commercial model into access decisions.

Geo matching covers country, province, city and postal rules. Scope resolution covers geographic and customer-group dispatch. Resource resolution covers the path from orders, returns, quotes, organisations and reservations back to properties. Guards cover allowed, out-of-scope, missing and malformed cases. Cross-tenant tests pin fail-closed behaviour. Link tests protect exclusive live assignments.

These tests matter because the visible interface is the least adversarial path. The dangerous cases are a direct resource ID, a stale link, an empty territory, a role change halfway through, or a scope identifier owned by another seller.

The useful unit of verification is not “the Account Manager page loads”. It is “for this identity, capability, scope and resource relationship, the server returns the correct decision”.

A practical territory-permission checklist

Before turning a sales territory into marketplace access, ask:

  1. Is the territory owned by exactly one supplier?
  2. Can the business define it by geography and by named customer portfolio?
  3. What durable entity anchors scope decisions: customer, organisation or property?
  4. Does the role matrix describe capabilities rather than pages?
  5. Do list queries constrain results to the same effective scope?
  6. Do detail and mutation routes resolve resources back to that anchor?
  7. Do returns and reservations inherit the property through their parent resource?
  8. Does an empty or stale scope fail closed?
  9. Do out-of-scope responses avoid revealing resource existence?
  10. Is seller ownership verified before a scope is linked?
  11. Does an invitation carry the intended role and perimeter?
  12. Can a delegated inviter create only permitted subordinate roles?
  13. Can one exclusive territory be assigned twice under concurrency?
  14. Does a role change remove previous assignments before installing new ones?
  15. Are analytics constrained as well as operational lists?

If those answers differ by route, the territory is still presentation data rather than a permission contract.

The broader lesson

Medusa provides the commerce resources and workflow primitives needed to build a vendor operation. It does not prescribe how a supplier divides its sales organisation.

That is precisely where an extensible commerce engine earns its place. We added the client's commercial model without reducing it to a profile field: roles for responsibilities, scopes for customer perimeter, properties as the common business anchor, and server-side guards for every evidenced access path.

The supplier can delegate meaningful work without opening the entire account. Account Managers see the opportunities and operations they own. Store Owners retain their location responsibilities. Admins keep strategic control.

A territory on a map explains the business. A territory enforced on every relevant resource makes the business safe to operate.

Read next
Keep the useful ideas coming

One practical commerce field note at a time.

Join the WeAreSouk journal for grounded stories about Medusa, Shopify, AI, integrations and the systems behind serious commerce.

Working on a similar problem?Bring us the business constraint. We’ll help map the system behind it.Talk to Souk →
Souk AI · online now

Turn the article into an implementation plan.

Ask how this applies to your store, your stack, or your current bottleneck.

01 Describe your current setup.02 Name the workflow or signal that feels unreliable.03 Get a practical first architecture back.
I can help map this article to your stack. Tell me what you sell, what platform you use, and where the medusa & architecture question hurts.
Continue the cluster

Building a property procurement platform on Medusa

Start a conversation

Tell us what commerce needs to do for your business.

No scheduling maze. Send the context, the constraint or the idea. We will read it and come back to you directly.