Files
stack/docs/design/federation-architecture.md
Jason Woltje 82a09373e0 docs: add Federation Architecture design document
Captures:
- Peer-to-peer federation model (master/spoke)
- Agent Federation Protocol (CONNECT, QUERY, COMMAND, EVENT, DISCONNECT)
- Authentik integration for enterprise SSO and RBAC
- Data sovereignty principles (query, don't replicate)
- RBAC model with workspace/team hierarchy
- Implementation phases targeting 0.1.0 MVP
- Versioning policy (0.0.x dev, 0.1.0 MVP, 1.0.0 stable)
2026-01-29 17:25:57 -06:00

29 KiB

Federation Architecture

Version: 0.0.1
Status: Design Phase
Author: Mosaic Stack Team
Date: 2025-01-29

Table of Contents

  1. Problem Statement
  2. Architecture Overview
  3. Identity & Authentication
  4. Agent Federation Protocol
  5. RBAC Model
  6. Data Sovereignty
  7. Implementation Phases
  8. Versioning

Problem Statement

Use Cases

  1. Work/Personal Separation

    • Developer has personal projects at home and work projects at the office
    • Data must stay in its respective environment
    • Single pane of glass for unified visibility
  2. Enterprise Control

    • Organization runs their own Mosaic Stack instance
    • Teams within the org have isolated workspaces
    • IT controls access, audit, compliance
  3. Cross-Organization Collaboration

    • Partner companies need to share specific projects
    • Guest access with limited permissions
    • No data replication—query in place

Requirements

  • Data Sovereignty — Data stays where it's created, never crosses boundaries
  • Unified Control — Single interface to view/manage multiple instances
  • Clean Severance — Disconnect = lose access, no data to clean up
  • Enterprise Auth — SSO, RBAC, audit trails
  • Peer-to-Peer — Any instance can be both master and spoke

Architecture Overview

Peer-to-Peer Federation Model

Every Mosaic Stack instance is a peer that can simultaneously act as:

  • Master — Control and query downstream spokes
  • Spoke — Expose capabilities to upstream masters
                    ┌─────────────────┐
                    │   ENTERPRISE    │
                    │   (Corp HQ)     │
                    └────────┬────────┘
                             │ speaks to
              ┌──────────────┼──────────────┐
              ▼              ▼              ▼
       ┌──────────┐   ┌──────────┐   ┌──────────┐
       │ IT Dept  │   │ Dev Team │   │ HR Dept  │
       └────┬─────┘   └────┬─────┘   └──────────┘
            │              │
            ▼              ▼
     ┌──────────┐   ┌──────────┐
     │  Jason   │◄─►│  Mike    │  ← peer sharing
     │  (Work)  │   │  (Work)  │
     └────┬─────┘   └──────────┘
          │
          │ speaks to (personal master)
          ▼
     ┌──────────┐
     │  Jason   │◄─► [Future: Family instance?]
     │  (Home)  │◄─► [Future: Trusted collaborator?]
     └──────────┘

Component Architecture

┌─────────────────────────────────────────────────────────────────┐
│                      IDENTITY PLANE                             │
│                       (Authentik)                               │
├─────────────────────────────────────────────────────────────────┤
│  • Users (identities across instances)                          │
│  • Groups (teams, departments, roles)                           │
│  • Applications (Mosaic Stack instances)                        │
│  • Federation trust (OIDC/SAML between IdPs)                   │
└───────────────────────────┬─────────────────────────────────────┘
                            │ OIDC / SAML
        ┌───────────────────┼───────────────────┐
        ▼                   ▼                   ▼
┌───────────────┐   ┌───────────────┐   ┌───────────────┐
│ Instance A    │   │ Instance B    │   │ Instance C    │
│ (Home)        │   │ (Work)        │   │ (Partner)     │
├───────────────┤   ├───────────────┤   ├───────────────┤
│ Agent Layer   │   │ Agent Layer   │   │ Agent Layer   │
│ ┌───────────┐ │   │ ┌───────────┐ │   │ ┌───────────┐ │
│ │ Jarvis    │ │   │ │ Jarvis    │ │   │ │ Partner   │ │
│ │ Prime     │◄┼───┼─┤ Work      │ │   │ │ Agent     │ │
│ └───────────┘ │   │ └───────────┘ │   │ └───────────┘ │
├───────────────┤   ├───────────────┤   ├───────────────┤
│ Workspaces:   │   │ Workspaces:   │   │ Workspaces:   │
│ • Personal    │   │ • IT Ops      │   │ • Shared Proj │
│ • Side Proj   │   │ • Dev Team    │   │               │
└───────────────┘   └───────────────┘   └───────────────┘

Identity & Authentication

Authentik as Identity Provider

Authentik provides enterprise-grade identity management:

Feature Purpose
OIDC/SAML Single sign-on across instances
User Directory Centralized user management
Groups Team/department organization
RBAC Role-based access control
Audit Logs Compliance and security tracking
MFA Multi-factor authentication
Federation Trust between external IdPs

Auth Architecture

┌─────────────────────────────────────────────────────────────────┐
│                    Identity Provider (Authentik)                │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐ │
│  │   Users     │  │   Groups    │  │   Applications          │ │
│  ├─────────────┤  ├─────────────┤  ├─────────────────────────┤ │
│  │ jason       │  │ IT-Team     │  │ mosaic-home             │ │
│  │ mike        │  │ Dev-Team    │  │ mosaic-work-usc         │ │
│  │ sarah       │  │ Admins      │  │ mosaic-partner-acme     │ │
│  └─────────────┘  └─────────────┘  └─────────────────────────┘ │
│                                                                 │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │                    Policies & Flows                       │  │
│  │  • Login flow (password + MFA)                           │  │
│  │  • OAuth2/OIDC scopes (profile, email, groups)          │  │
│  │  • Conditional access (IP, device, time)                 │  │
│  │  • External IdP federation (Google, Azure AD)            │  │
│  └──────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘
                              │
          ┌───────────────────┼───────────────────┐
          │ OIDC              │ OIDC              │ OIDC
          ▼                   ▼                   ▼
   ┌─────────────┐     ┌─────────────┐     ┌─────────────┐
   │ Mosaic Home │     │ Mosaic Work │     │ Mosaic Ext  │
   └─────────────┘     └─────────────┘     └─────────────┘

OIDC Token Claims

Mosaic Stack expects these claims from the IdP:

{
  "sub": "user-uuid-123",
  "preferred_username": "jason",
  "email": "jason@example.com",
  "groups": ["IT-Team", "Dev-Team", "Admins"],
  "roles": ["workspace:ws-123:owner", "workspace:ws-456:member"],
  "aud": "mosaic-home",
  "iss": "https://auth.example.com"
}

Cross-Instance Identity

When federating between instances with different IdPs:

┌─────────────────┐                    ┌─────────────────┐
│  Authentik A    │◄── OIDC Trust ───►│  Authentik B    │
│  (Home IdP)     │                    │  (Work IdP)     │
└────────┬────────┘                    └────────┬────────┘
         │                                      │
         │                                      │
         ▼                                      ▼
┌─────────────────┐                    ┌─────────────────┐
│  Mosaic Home    │                    │  Mosaic Work    │
│                 │                    │                 │
│  User: jason    │◄── Federation ───►│  User: jason    │
│  (home identity)│    Protocol       │  (work identity)│
└─────────────────┘                    └─────────────────┘

Identity Mapping:

  • Same email = same person (by convention)
  • Explicit identity linking via federation protocol
  • No implicit access—must be granted per instance

Agent Federation Protocol

Connection Lifecycle

┌────────────┐                           ┌────────────┐
│   MASTER   │                           │   SPOKE    │
│  (Home)    │                           │  (Work)    │
└─────┬──────┘                           └─────┬──────┘
      │                                        │
      │  1. CONNECT (auth token + scopes)      │
      │───────────────────────────────────────►│
      │                                        │
      │  2. CAPABILITIES (available APIs)      │
      │◄───────────────────────────────────────│
      │                                        │
      │  3. QUERY / COMMAND (ongoing)          │
      │◄──────────────────────────────────────►│
      │                                        │
      │  4. EVENT (push notifications)         │
      │◄───────────────────────────────────────│
      │                                        │
      │  5. DISCONNECT (clean exit)            │
      │───────────────────────────────────────►│
      │                                        │

Message Types

1. CONNECT — Establish Federation Trust

{
  "type": "connect",
  "version": "0.0.1",
  "masterIdentity": {
    "instanceId": "mosaic-home-jason",
    "userId": "jason",
    "instanceUrl": "https://mosaic.home.local"
  },
  "authToken": "oidc-access-token-or-api-key",
  "requestedScopes": [
    "calendar.read",
    "calendar.write",
    "tasks.read",
    "tasks.write",
    "agents.query",
    "agents.command"
  ]
}

2. CAPABILITIES — Spoke Advertises Available APIs

{
  "type": "capabilities",
  "spokeIdentity": {
    "instanceId": "mosaic-work-usc",
    "instanceUrl": "https://mosaic.uscllc.com"
  },
  "grantedScopes": ["calendar.read", "tasks.read", "tasks.write"],
  "deniedScopes": ["calendar.write", "agents.command"],
  "availableCommands": [
    {
      "name": "tasks.list",
      "description": "List tasks in workspace",
      "params": { "workspaceId": "string", "status": "string?" }
    },
    {
      "name": "tasks.create",
      "description": "Create a new task",
      "params": { "title": "string", "description": "string?" }
    },
    {
      "name": "calendar.today",
      "description": "Get today's calendar events",
      "params": {}
    }
  ],
  "availableQueries": [
    {
      "name": "status",
      "description": "Get instance status",
      "returns": "InstanceStatus"
    },
    {
      "name": "workspaces.list",
      "description": "List accessible workspaces",
      "returns": "Workspace[]"
    }
  ],
  "eventSubscriptions": [
    "calendar.reminder",
    "tasks.assigned",
    "tasks.completed"
  ]
}

3. QUERY — Read-Only Data Fetch

{
  "type": "query",
  "id": "q-abc123",
  "name": "calendar.today",
  "params": { "includeAllDay": true }
}

Response:

{
  "type": "query.result",
  "id": "q-abc123",
  "success": true,
  "data": [
    { "title": "Standup", "time": "09:00", "duration": 30 },
    { "title": "1:1 with Mike", "time": "14:00", "duration": 60 }
  ],
  "provenance": {
    "instanceId": "mosaic-work-usc",
    "timestamp": "2025-01-29T14:30:00Z"
  }
}

4. COMMAND — Execute an Action

{
  "type": "command",
  "id": "c-def456",
  "name": "tasks.create",
  "params": {
    "title": "Review PR #421",
    "description": "Security review for auth changes",
    "priority": 8,
    "workspaceId": "ws-dev-team"
  }
}

Sync Response:

{
  "type": "command.result",
  "id": "c-def456",
  "success": true,
  "data": {
    "taskId": "task-789",
    "url": "https://mosaic.uscllc.com/tasks/task-789"
  },
  "provenance": {
    "instanceId": "mosaic-work-usc",
    "timestamp": "2025-01-29T14:31:00Z"
  }
}

Async Response (for long-running):

{
  "type": "command.accepted",
  "id": "c-def456",
  "status": "pending",
  "pollUrl": "/federation/status/c-def456",
  "estimatedCompletion": "30s"
}

5. EVENT — Push Notification from Spoke

{
  "type": "event",
  "name": "calendar.reminder",
  "data": {
    "title": "1:1 with Mike",
    "startsIn": "15m",
    "location": "Conference Room B"
  },
  "provenance": {
    "instanceId": "mosaic-work-usc",
    "timestamp": "2025-01-29T13:45:00Z"
  }
}

6. DISCONNECT — Clean Severance

{
  "type": "disconnect",
  "reason": "user-initiated",
  "revokeToken": true,
  "preserveHistory": false
}

Agent-to-Agent Communication

Masters can command spokes to execute agent tasks:

{
  "type": "command",
  "id": "c-agent-001",
  "name": "agents.spawn",
  "params": {
    "taskTitle": "Review today's tickets",
    "taskDescription": "Check GLPI for new high-priority tickets",
    "inputContext": {
      "priority": "high",
      "category": "network"
    },
    "callbackUrl": "https://mosaic.home.local/federation/callback/c-agent-001"
  }
}

The spoke agent executes the task and calls back with results:

{
  "type": "callback",
  "id": "c-agent-001",
  "success": true,
  "data": {
    "ticketsFound": 3,
    "tickets": [
      { "id": "GLPI-1234", "title": "Switch failure in Building A" },
      { "id": "GLPI-1235", "title": "VPN connectivity issues" },
      { "id": "GLPI-1236", "title": "Printer offline 3rd floor" }
    ]
  }
}

RBAC Model

Hierarchy

Instance
└── Workspace (like a Teams "Team")
    ├── Roles: owner, admin, member, viewer, guest
    ├── Teams (sub-groups within workspace)
    │   └── Roles: owner, admin, member
    ├── Projects / Channels
    │   └── Permissions (inherit or override)
    └── Members (users or groups from IdP)

Role Permissions Matrix

Permission Owner Admin Member Viewer Guest
View workspace ✓*
Create content
Edit content
Delete content
Manage members
Manage teams
Configure workspace
Delete workspace
Manage federation

*Guest: scoped to specific shared items only

Federation RBAC

Cross-instance access is always scoped and limited:

{
  "federation": {
    "trustedInstances": [
      {
        "instanceId": "mosaic-work-usc",
        "trustLevel": "verified",
        "maxRole": "member",
        "scopedWorkspaces": ["ws-shared-projects"],
        "allowedCapabilities": ["tasks.read", "tasks.write", "calendar.read"],
        "deniedCapabilities": ["admin.*", "federation.*"]
      }
    ]
  }
}

Key Constraints:

  • Federated users cannot exceed maxRole (e.g., member can't become admin)
  • Access limited to scopedWorkspaces only
  • Capabilities are explicitly allowlisted
  • Admin/federation capabilities always denied by default

Data Sovereignty

Core Principles

  1. Data Residency — Data lives where it's created, never crosses boundaries
  2. Query, Don't Replicate — Master queries spoke, doesn't store results
  3. Provenance Tagging — Every piece of data tagged with source instance
  4. Clean Exit — Disconnect = lose access, no cleanup needed

Data Flow

┌──────────────────────────────────────────────────────────────────┐
│                        MASTER (Home)                             │
│                                                                  │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │                   Aggregation Layer                          │ │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │ │
│  │  │ Home Data   │  │ Work Data   │  │ Partner Data        │  │ │
│  │  │ (stored)    │  │ (queried)   │  │ (queried)           │  │ │
│  │  │             │  │ ⚡ live      │  │ ⚡ live              │  │ │
│  │  └─────────────┘  └──────┬──────┘  └──────────┬──────────┘  │ │
│  │                          │                     │             │ │
│  └──────────────────────────┼─────────────────────┼─────────────┘ │
│                             │                     │               │
└─────────────────────────────┼─────────────────────┼───────────────┘
                              │                     │
                    ┌─────────▼─────────┐ ┌────────▼────────┐
                    │   SPOKE (Work)    │ │ SPOKE (Partner) │
                    │   Data stays here │ │ Data stays here │
                    └───────────────────┘ └─────────────────┘

What's Stored vs Queried

Data Type Home Instance Work Instance Notes
Personal tasks ✓ Stored Only at home
Work tasks Queried live ✓ Stored Never replicated
Personal calendar ✓ Stored Only at home
Work calendar Queried live ✓ Stored Never replicated
Federation metadata ✓ Stored ✓ Stored Connection config only
Query results cache Ephemeral (5m TTL) Optional, short-lived

Severance Procedure

When disconnecting from a spoke:

1. Master initiates DISCONNECT
2. Spoke revokes master's access token
3. Spoke removes master from trusted instances
4. Master removes spoke from connection list
5. All live queries fail immediately
6. No data cleanup needed—nothing was stored

Result:
- Master retains: its own data, federation config (marked disconnected)
- Spoke retains: its own data, audit log of the connection
- Neither has: the other's data

Implementation Phases

Phase 1: Foundation (v0.0.x)

Goal: Multi-instance awareness, basic federation protocol

Deliverables:

  • Instance identity model (instanceId, URL, public key)
  • Federation connection database schema
  • Basic CONNECT/DISCONNECT protocol
  • Manual connection setup (no auto-discovery)
  • Query/Command message handling (stub)

Testing:

  • Two local instances can connect
  • Connection persists across restarts
  • Disconnect cleans up properly

Phase 2: Authentik Integration (v0.0.x)

Goal: Enterprise SSO with RBAC

Deliverables:

  • Authentik OIDC provider setup guide
  • BetterAuth Authentik adapter
  • Group → Role mapping
  • Multi-workspace session handling
  • Audit logging for auth events

Testing:

  • Login via Authentik works
  • Groups map to roles correctly
  • Session isolation between workspaces

Phase 3: Federation Protocol (v0.0.x)

Goal: Full query/command capability

Deliverables:

  • QUERY message type with response streaming
  • COMMAND message type with async support
  • EVENT subscription and delivery
  • Capability negotiation
  • Error handling and retry logic

Testing:

  • Master can query spoke calendar
  • Master can create tasks on spoke
  • Events push from spoke to master
  • Errors handled gracefully

Phase 4: Single Pane of Glass (v0.1.0 MVP)

Goal: Unified dashboard showing all instances

Deliverables:

  • Connection manager UI
  • Aggregated calendar view
  • Aggregated task view
  • Instance status indicators
  • Visual provenance tagging (color/icon per instance)

Testing:

  • Dashboard shows data from multiple instances
  • Clear visual distinction between sources
  • Offline instance shows gracefully

Phase 5: Agent Federation (v0.1.x)

Goal: Cross-instance agent coordination

Deliverables:

  • Agent spawn command via federation
  • Callback mechanism for results
  • Agent status querying across instances
  • Cross-instance task assignment

Testing:

  • Home agent can spawn task on work instance
  • Results callback works
  • Agent health visible across instances

Phase 6: Enterprise Features (v0.2.x)

Goal: Production-ready for organizations

Deliverables:

  • Admin console for federation management
  • Compliance audit reports
  • Rate limiting and quotas
  • Webhook integration
  • Multi-region support

Versioning

Semantic Versioning Policy

Version Meaning
0.0.x Active development, breaking changes expected, internal use only
0.1.0 MVP — First user-testable release, core features working
0.x.y Pre-stable iteration, API may change with notice
1.0.0 Stable release, public API contract, breaking changes require major version

Version Milestones

Version Target Features
0.0.1 Design This document
0.0.5 Foundation Basic federation protocol
0.0.10 Auth Authentik integration
0.1.0 MVP Single pane of glass, basic federation
0.2.0 Agents Cross-instance agent coordination
0.3.0 Enterprise Admin console, compliance
1.0.0 Stable Production-ready, API frozen

Security Considerations

Transport Security

  • All federation traffic over TLS 1.3
  • Certificate pinning for known instances (optional)
  • mTLS for high-security deployments

Authentication

  • OIDC tokens with short expiry (1h)
  • Refresh tokens with longer expiry (7d)
  • API keys for service-to-service (no user context)

Authorization

  • Capability-based access control
  • Explicit allowlists (deny by default)
  • No implicit transitivity (A→B→C doesn't mean A→C)

Audit

  • All federation connections logged
  • All queries/commands logged with user identity
  • Retention configurable per compliance requirements

Secrets

  • Never log tokens or credentials
  • Encrypt sensitive federation config at rest
  • Rotate API keys periodically

API Endpoints

Federation Management

// List connected instances
GET /api/v1/federation/connections
Response: FederationConnection[]

// Initiate connection to spoke
POST /api/v1/federation/connect
{
  "spokeUrl": "https://mosaic.work.example.com",
  "authToken": "...",
  "requestedScopes": ["calendar.read", "tasks.*"]
}

// Disconnect from spoke
DELETE /api/v1/federation/connections/:instanceId

// Get connection status
GET /api/v1/federation/connections/:instanceId/status

// Update connection scopes
PATCH /api/v1/federation/connections/:instanceId
{
  "requestedScopes": ["calendar.*", "tasks.*"]
}

Federated Queries

// Query a spoke
POST /api/v1/federation/query
{
  "instanceId": "mosaic-work-usc",
  "query": "calendar.today",
  "params": { "includeAllDay": true }
}

// Execute command on spoke
POST /api/v1/federation/command
{
  "instanceId": "mosaic-work-usc",
  "command": "tasks.create",
  "params": { "title": "Review PR", "priority": 8 }
}

Spoke Configuration (for instances accepting connections)

// Get spoke settings
GET /api/v1/federation/spoke/settings

// Update spoke settings
PATCH /api/v1/federation/spoke/settings
{
  "acceptConnections": true,
  "allowedMasters": ["mosaic-home-jason"],
  "defaultScopes": ["calendar.read", "tasks.read"],
  "maxScopes": ["calendar.*", "tasks.*"]
}

// List connected masters
GET /api/v1/federation/spoke/masters

// Revoke master access
DELETE /api/v1/federation/spoke/masters/:instanceId

Glossary

Term Definition
Instance A single Mosaic Stack deployment
Master Instance that initiates connection and queries spoke
Spoke Instance that accepts connections and serves data
Peer An instance that can be both master and spoke
Federation Network of connected Mosaic Stack instances
Scope Permission to perform specific actions (e.g., calendar.read)
Capability API endpoint exposed by a spoke
Provenance Source attribution for data (which instance it came from)
Severance Clean disconnection with no data cleanup required
IdP Identity Provider (e.g., Authentik)

References


Open Questions

  1. Identity Linking: How do we link the same person across instances with different IdPs?
  2. Conflict Resolution: What happens if the same entity is modified on multiple instances?
  3. Offline Handling: How long to cache spoke data when offline?
  4. Rate Limiting: How to prevent spoke overload from aggressive masters?
  5. Discovery: Should instances be discoverable, or always manual connection?

Next Steps:

  1. Review and approve this design document
  2. Create GitHub issues for Phase 1 tasks
  3. Set up Authentik development instance
  4. Begin federation protocol implementation

Questions/Feedback: Open an issue in mosaic-stack repo with label federation.