Skip to content

ADR-0009: Portal x Chain Matrix as Access Control Model

Status: ACCEPTED Date: 2026-03-22 Supersedes: N/A Superseded by: N/A

Context

The platform serves four distinct portal types (SYSTEM, TENANT, PARTNER, CONSUMER) with two request chains (WEB for browser-based sessions, API for programmatic access). Each combination has different endpoints, authentication flows, and permission models. A unified model was needed to classify and control endpoint access.

Source: DevPortal design spec (Portal x Chain Matrix), slaunchx-infra-gateway/docs/MODULE-SPEC.md, slaunchx-app-prometheus/docs/domain/gateway/DESIGN-gateway-validation-chain.md

Decision

Access control is modeled as a Portal x Chain matrix. Each controller declares its portal scope via @GatewayValidation(portals = {...}) and its chain type via chainType. The WEB chain uses JWT + RBAC permissions; the API chain uses API Key + HMAC-SHA256 + scope-based authorization (@ApiScope). The gateway framework assembles a different validation chain per chain type, with portal-specific handlers executing in a defined priority order.

Current matrix:

  • SYSTEM (10010101): WEB chain only (206 endpoints)
  • TENANT (10010102): WEB chain only (209 endpoints)
  • PARTNER (10010103): WEB chain only (103 endpoints)
  • CONSUMER (10010104): WEB + API chain (87 WEB + API endpoints with scopes)

Consequences

  • Clean separation of concerns: portal identity and chain type are orthogonal dimensions.
  • API chain extensibility: any portal can add API endpoints by annotating controllers with @ApiScope.
  • Per-portal controller isolation (ADR-0011) becomes natural: each portal gets its own controller package.
  • The matrix is the definitive reference for documentation generation (DevPortal parser uses it directly).

Alternatives Considered

  • Single chain with role-based differentiation: Rejected because WEB (session-based) and API (key-based) authentication are fundamentally different protocols that cannot be unified without compromising security.
  • Portal-agnostic endpoints with runtime portal filtering: Rejected because it hides the portal scope from the source code, making audits unreliable.

Internal Handbook