Skip to main content

ADR-011: API Security Mode Selection β€” mTLS / OAuth2 / Hybrid

Metadata​

FieldValue
Statusβœ… Accepted
Date11 January 2026
LinearCAB-410

Context​

STOA Gateway must support multiple API security modes depending on usage contexts. Rather than letting teams guess, we formalize a Decision Tree that automatically recommends the right mode.

Options Considered​

OptionDescriptionVerdict
mTLS onlyClient certificate authenticationβœ… For CORE internal APIs
OAuth2 onlyJWT tokens with scopesβœ… For SELF-SERVICE APIs
mTLS + OAuth2Dual authenticationβœ… For critical exposed APIs
API Key onlyStatic secret⚠️ Community tier only

Decision​

Implement an automated Decision Tree to recommend the optimal API security mode.

Decision Tree​

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Consumer type? β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚
[Internal] [External]
β”‚ β”‚
β–Ό β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Flow type? β”‚ β”‚ OAuth2 requiredβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ β–Ό
[A2A] [User] β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚ β”‚ Critical domain?β”‚
β”‚ β–Ό β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ OAuth2 required β”‚
β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚Critical domain? β”‚ [Yes] [No]
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β–Ό β–Ό
β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚ β”‚ mTLS + OAuth2β”‚ β”‚ OAuth2 only β”‚
[Yes] [No] β”‚ (HYBRID) β”‚ β”‚(SELF-SERVICE)β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β–Ό β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ mTLS β”‚ β”‚ OAuth2 or β”‚
β”‚ (CORE) β”‚ β”‚ mTLS per β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ governance β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Decision Rules​

CaseConditionsRecommended Mode
🟒 COREInternal + A2A + Critical + Stable rightsmTLS
πŸ”΅ SELF-SERVICEExternal + User/BFF + DX priorityOAuth2
🟣 HYBRIDCritical + External + Strong governancemTLS + OAuth2

Consequences​

Positive​

  • Automatic and consistent recommendation
  • Reduced security configuration errors
  • Documented decisions for audit

Negative​

  • Additional tooling complexity
  • Learning curve for teams

Neutral​

  • Teams can deviate with documented justification

MCP Tool: security-advisor​

// Input
{
"consumer_type": "internal | external",
"flow_type": "a2a | user",
"rights_variability": "static | dynamic",
"domain_criticality": "low | high",
"governance_level": "basic | strong"
}

// Output
{
"recommended_security_mode": "mTLS | OAuth2 | mTLS+OAuth2",
"justification": ["Critical domain", "Internal A2A flow"],
"risk_level": "low | medium | high",
"implementation_notes": ["Short-lived client cert", "ABAC policy"]
}

References​