diff --git a/docs/design/README.md b/docs/design/README.md index 25ee358..d500af4 100644 --- a/docs/design/README.md +++ b/docs/design/README.md @@ -70,4 +70,44 @@ When creating a new design document: --- +### [Federation Architecture](./federation-architecture.md) + +**Status:** Design Phase +**Version:** 0.0.1 +**Date:** 2025-01-29 + +Multi-instance federation enabling cross-organization collaboration, work/personal separation, and enterprise control with data sovereignty. + +**Key Features:** +- Peer-to-peer federation (every instance can be master and/or spoke) +- Authentik integration for enterprise SSO and RBAC +- Agent Federation Protocol for cross-instance queries and commands +- Data sovereignty (query in place, never replicate) +- Single pane of glass aggregating multiple instances + +--- + +### [Multi-Tenant RLS](./multi-tenant-rls.md) + +**Status:** Implemented +**Version:** 1.0 +**Date:** 2025-01-29 + +PostgreSQL Row-Level Security for workspace isolation and defense-in-depth multi-tenancy. + +--- + +## Contributing + +When creating a new design document: + +1. Copy the structure from an existing document +2. Use ASCII diagrams for architecture (keep them simple) +3. Include code examples in TypeScript +4. Specify database schema in SQL (PostgreSQL dialect) +5. Add implementation phases with clear milestones +6. Update this README with a summary + +--- + **Last Updated:** 2025-01-29 diff --git a/docs/design/federation-architecture.md b/docs/design/federation-architecture.md new file mode 100644 index 0000000..5acfe45 --- /dev/null +++ b/docs/design/federation-architecture.md @@ -0,0 +1,848 @@ +# Federation Architecture + +**Version:** 0.0.1 +**Status:** Design Phase +**Author:** Mosaic Stack Team +**Date:** 2025-01-29 + +## Table of Contents + +1. [Problem Statement](#problem-statement) +2. [Architecture Overview](#architecture-overview) +3. [Identity & Authentication](#identity--authentication) +4. [Agent Federation Protocol](#agent-federation-protocol) +5. [RBAC Model](#rbac-model) +6. [Data Sovereignty](#data-sovereignty) +7. [Implementation Phases](#implementation-phases) +8. [Versioning](#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: + +```json +{ + "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 + +```json +{ + "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 + +```json +{ + "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 + +```json +{ + "type": "query", + "id": "q-abc123", + "name": "calendar.today", + "params": { "includeAllDay": true } +} +``` + +**Response:** + +```json +{ + "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 + +```json +{ + "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:** + +```json +{ + "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):** + +```json +{ + "type": "command.accepted", + "id": "c-def456", + "status": "pending", + "pollUrl": "/federation/status/c-def456", + "estimatedCompletion": "30s" +} +``` + +#### 5. `EVENT` — Push Notification from Spoke + +```json +{ + "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 + +```json +{ + "type": "disconnect", + "reason": "user-initiated", + "revokeToken": true, + "preserveHistory": false +} +``` + +### Agent-to-Agent Communication + +Masters can command spokes to execute agent tasks: + +```json +{ + "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: + +```json +{ + "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: + +```json +{ + "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 + +```typescript +// 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 + +```typescript +// 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) + +```typescript +// 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 + +- [Authentik Documentation](https://goauthentik.io/docs/) +- [OIDC Specification](https://openid.net/specs/openid-connect-core-1_0.html) +- [Multi-Tenant RLS Design](./multi-tenant-rls.md) +- [Agent Orchestration Design](./agent-orchestration.md) +- [Architecture Decisions](./architecture-decisions.md) + +--- + +## 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`.