Skip to content

0007. Derive admin access from system membership

Date: 2026-07-10 Status: Partially superseded by 0008 — the support-user eligibility criterion (first Decision bullet) is corrected there; the other two decisions below remain in effect. Extended by 0012 for sync rules, which the full/status-only split does not settle on its own.

Context

Two kinds of humans log into the Conflux admin panel: platform operators (internal staff running Conflux itself — unscoped SuperAdmin), and platform support (support staff of a consuming platform, e.g. User Platform, who need to open the tenant behind one of their clients to help them — scoped to the tenants connected to their platform). End customers (shop operators) never log into the admin panel; they self-serve inside their shop via the plugin and a per-connection token. Binding a person's reach to a data pipe is one of the things that made App awkward (ADR-0002); the admin access model is kept deliberately separate from the machine-auth model (ADR-0006).

Decision

  • Platform-support access is derived, never granted per tenant. A support user is made a member of one or more consuming Systems through a new system_user pivot, given the new PlatformSupport role. The tenants they may reach are then computed — every tenant that has a connection to one of their systems — with no per-tenant row created or maintained. Onboarding a tenant must not depend on a manual "assign this person to this tenant" step; membership is stated once, at platform level, and the tenant set follows the connection graph automatically. Only systems whose direction matrix includes PullOut may have support members — shop adapters never do.
  • Accessible tenants are the union of explicit and derived grants: accessibleTenants(user) = tenants granted directly via tenant_user tenants derived via system_user → connections, with SuperAdmin bypassing both. The derived source covers platform support with zero maintenance; the explicit source stays available for a one-off pin or a future end-customer portal. The two are additive, so neither limits the other. This supersedes the earlier plan for tenant_user to be the sole admin-access mechanism.
  • Own connections in full, sibling connections by status only. For a PlatformSupport user inside an accessible tenant: connections to a system they operate get full access (view + trigger resync, no credential read); any other connection is status-only (status, last_connected_at, health — never credentials or config); Customer/Order/Product rows are scoped to the connections they fully access; cross-system identity is the link view only, never a sibling's raw records. Support must be able to spot upstream breakage ("the shop stopped syncing") without gaining reach into a platform they have no relationship with.

Consequences

The exact status-only projection (which columns, which health signal) is an implementation detail, not specified by this decision. Roles & Permissions still describes the pre-Tenant (App-era) access model and will need a rewrite once this ships — it is intentionally left untouched until then.