0008. Derive support-user eligibility from the adapter driver, not the direction matrix¶
Date: 2026-07-21 Status: Accepted
Context¶
ADR-0007 ties system_user membership
eligibility to whether a System's direction_matrix includes PullOut. The direction matrix is
a per-instance sync configuration (ADR-0004)
describing what data currently flows and in which direction — an operational setting, not an
organisational one. Whether a consuming platform's staff can ever act as platform support for a
given adapter type is fixed by what kind of adapter it is (a shop a tenant plugs in vs. a platform
that itself consumes Conflux), not by which sync directions happen to be configured on one
instance of it at a given moment. Gating membership on direction_matrix also couples an
authorization decision to a field that ADR-0004 already expects to become a domain-keyed map
rather than a flat list — a "does the flat list contain PullOut" check would not survive that
change.
Decision¶
Support-user eligibility is a static property of the adapter type, not of any one System row's
sync configuration: SystemDriver::canHaveSupportUsers() is the single source of truth (shop
adapters — WooCommerce, PrestaShop, Shopify, Shopware — return false; the internal consuming
platforms — RapidMail, UserPlatform — return true). System::scopeCanHaveSupportUsers() reads
this per-driver classification, and every place that previously inspected direction_matrix for
this purpose reads it instead: the system_user pivot's assignment guard, Tenant::scopeAccessibleBy(),
and SystemConnection::scopeFullyAccessibleBy().
This corrects only the eligibility criterion in ADR-0007; its other two decisions — the accessible-tenants union and the own-connections-full / sibling-connections-status-only split — are unaffected and remain in effect.
Consequences¶
A System's direction_matrix no longer has any bearing on whether it may have support members;
reclassifying an adapter's eligibility now means changing SystemDriver::canHaveSupportUsers() (a
code change, reviewed like any other), not editing per-row configuration data. The system_user
pivot's creating guard (App\Models\SystemUser) throws SystemCannotHaveSupportUsersException
at assignment time based on this same classification; if a driver is later reclassified from
eligible to ineligible, existing pivot rows are not retroactively removed — Tenant::scopeAccessibleBy()
and SystemConnection::scopeFullyAccessibleBy() re-check canHaveSupportUsers() on every query,
so access is still cut off for stale assignments even though the pivot row itself lingers.