Architecture: How should JWT tokens carry multi-tenant claims without brea...

Documentation for Sessions

🏗️ Architecture: How should JWT tokens carry multi-tenant claims without brea...

Date: 2026-02-05
Time: 23:03:07 UTC
Session: editor2-92.20
Agent: backend
Confidence: 93%
Status: ✅ Documented


📋 Decision Context

Question:

How should JWT tokens carry multi-tenant claims without breaking existing clients?

Task: Session 93: JWT enrichment with multi-tenant claims


🎯 Decision Made

Chosen:

Additive JWT claims: existing payload {sub, email, roles} is preserved. New optional fields added: userType ('developer'|'space_builder'|'platform_user'), mcpTier (from user_hierarchy.subscriptionTier or User.subscriptionTier fallback), spaceId (from hierarchy or User.defaultSpaceId fallback). Hierarchy lookup is non-blocking — failure falls back to User document fields. Platform Users (T3) get a separate JWT with required fields: userType='platform_user', mcpTier='free', spaceId, universeId, ownerId.

Options Considered:

  1. Break existing JWT and force all clients to update
  2. Additive optional claims with fallbacks
  3. Separate token types per tier
  4. Claims in a separate header instead of JWT

💭 Reasoning

Backward compatibility is critical — existing Cursor extension, VSCode extension, and Claude Desktop clients must continue working with their current tokens. Making new claims optional means old tokens without userType/mcpTier/spaceId are still valid. The @Optional() decorator on UserHierarchy model injection ensures auth doesn't break if hierarchy schema isn't registered in some module. Hierarchy lookup failure logs a warning but doesn't block authentication. T3 JWT is separate because Platform Users authenticate through a different endpoint (POST /api/platform/:universeSlug/auth/login) and need universeId+ownerId claims that T1/T2 don't have.


📁 Files Involved


🔗 Related


Auto-generated by MCP Smart Consolidation