1334 lines
43 KiB
Markdown
1334 lines
43 KiB
Markdown
# ColaFlow M1.2 Feature List - Enterprise Multi-Tenant Architecture
|
||
|
||
**Document Type:** Feature Requirements & Acceptance Criteria
|
||
**Milestone:** M1.2 (Enterprise Multi-Tenant Architecture)
|
||
**Version:** 1.0
|
||
**Date:** 2025-11-03
|
||
**Owner:** Product Manager
|
||
**Status:** Approved for Development
|
||
|
||
---
|
||
|
||
## Document Overview
|
||
|
||
This document defines the complete feature set for ColaFlow M1.2, the Enterprise Multi-Tenant Architecture milestone. It includes functional requirements, non-functional requirements, acceptance criteria, technical requirements, and security requirements for all features.
|
||
|
||
**M1.2 Scope:** Transform ColaFlow from single-tenant to enterprise-ready multi-tenant SaaS platform with SSO and AI agent authentication.
|
||
|
||
---
|
||
|
||
## Table of Contents
|
||
|
||
1. [Feature Overview](#feature-overview)
|
||
2. [Feature Categories](#feature-categories)
|
||
3. [Detailed Feature Specifications](#detailed-feature-specifications)
|
||
4. [Non-Functional Requirements](#non-functional-requirements)
|
||
5. [Technical Requirements](#technical-requirements)
|
||
6. [Security Requirements](#security-requirements)
|
||
7. [Acceptance Criteria Matrix](#acceptance-criteria-matrix)
|
||
|
||
---
|
||
|
||
## Feature Overview
|
||
|
||
### M1.2 Goals
|
||
|
||
1. **Multi-Tenancy:** Support multiple companies (tenants) on shared infrastructure
|
||
2. **SSO Integration:** Enable enterprise SSO (Azure AD, Google, Okta, SAML 2.0)
|
||
3. **MCP Authentication:** Secure AI agent access via MCP tokens
|
||
4. **Tenant Management:** Self-service tenant registration and administration
|
||
5. **Data Isolation:** Ensure complete data separation between tenants
|
||
|
||
### Feature Summary
|
||
|
||
| Feature Category | Features Count | Priority | Status |
|
||
|------------------|----------------|----------|--------|
|
||
| **Multi-Tenancy** | 6 | P0 (Must Have) | In Development |
|
||
| **Authentication** | 4 | P0 (Must Have) | Planned |
|
||
| **SSO Integration** | 5 | P1 (Should Have) | Planned |
|
||
| **MCP Tokens** | 5 | P1 (Should Have) | Planned |
|
||
| **Tenant Management** | 4 | P0 (Must Have) | Planned |
|
||
| **Total** | **24 features** | - | Day 1/10 Complete |
|
||
|
||
---
|
||
|
||
## Feature Categories
|
||
|
||
### Category 1: Multi-Tenancy Foundation (P0)
|
||
|
||
**Business Value:** Enable SaaS business model, serve multiple customers on shared infrastructure
|
||
|
||
| Feature ID | Feature Name | Description | Priority |
|
||
|------------|--------------|-------------|----------|
|
||
| MT-001 | Tenant Data Model | Tenant entity with subscription, limits, status | P0 |
|
||
| MT-002 | Tenant Identification | JWT-based tenant resolution | P0 |
|
||
| MT-003 | Data Isolation | Global Query Filter for automatic tenant filtering | P0 |
|
||
| MT-004 | Tenant-Scoped Queries | All database queries filter by tenant_id | P0 |
|
||
| MT-005 | Cross-Tenant Protection | Prevent access to other tenant's data | P0 |
|
||
| MT-006 | Tenant Subdomain | Tenant-specific URLs (acme.colaflow.com) | P0 |
|
||
|
||
### Category 2: Authentication & Authorization (P0)
|
||
|
||
**Business Value:** Secure access control, support enterprise identity providers
|
||
|
||
| Feature ID | Feature Name | Description | Priority |
|
||
|------------|--------------|-------------|----------|
|
||
| AUTH-001 | JWT Authentication | JWT tokens with tenant claims | P0 |
|
||
| AUTH-002 | Local Login | Email + password authentication | P0 |
|
||
| AUTH-003 | Token Refresh | Automatic token refresh mechanism | P0 |
|
||
| AUTH-004 | Logout | Clear authentication state | P0 |
|
||
|
||
### Category 3: SSO Integration (P1)
|
||
|
||
**Business Value:** Enterprise requirement, reduces friction, improves security
|
||
|
||
| Feature ID | Feature Name | Description | Priority |
|
||
|------------|--------------|-------------|----------|
|
||
| SSO-001 | OIDC Integration | Azure AD, Google, Okta support | P1 |
|
||
| SSO-002 | SAML 2.0 Integration | Generic enterprise IdP support | P1 |
|
||
| SSO-003 | User Auto-Provisioning | Create users on first SSO login | P1 |
|
||
| SSO-004 | Domain Restrictions | Allow only specific email domains | P1 |
|
||
| SSO-005 | SSO Configuration UI | Admin interface to configure SSO | P1 |
|
||
|
||
### Category 4: MCP Token Management (P1)
|
||
|
||
**Business Value:** Enable AI agent integration, differentiate from competitors
|
||
|
||
| Feature ID | Feature Name | Description | Priority |
|
||
|------------|--------------|-------------|----------|
|
||
| MCP-001 | Token Generation | Generate secure MCP tokens | P1 |
|
||
| MCP-002 | Fine-Grained Permissions | Resource + operation level permissions | P1 |
|
||
| MCP-003 | Token Revocation | Instant token revocation | P1 |
|
||
| MCP-004 | Token Audit Logs | Complete audit trail of token usage | P1 |
|
||
| MCP-005 | Token Management UI | UI to create, view, revoke tokens | P1 |
|
||
|
||
### Category 5: Tenant Management (P0)
|
||
|
||
**Business Value:** Self-service onboarding, reduce support burden
|
||
|
||
| Feature ID | Feature Name | Description | Priority |
|
||
|------------|--------------|-------------|----------|
|
||
| TM-001 | Tenant Registration | 3-step registration wizard | P0 |
|
||
| TM-002 | Slug Validation | Real-time slug availability check | P0 |
|
||
| TM-003 | Subscription Plans | Free, Starter, Pro, Enterprise plans | P0 |
|
||
| TM-004 | Tenant Settings | Admin interface for tenant configuration | P0 |
|
||
|
||
---
|
||
|
||
## Detailed Feature Specifications
|
||
|
||
### MT-001: Tenant Data Model
|
||
|
||
**Description:** Core tenant entity with all necessary attributes for multi-tenant operation
|
||
|
||
**Functional Requirements:**
|
||
- Tenant has unique ID (UUID)
|
||
- Tenant has unique slug (URL-safe, 3-50 characters, lowercase, alphanumeric + hyphens)
|
||
- Tenant has name (2-100 characters)
|
||
- Tenant has status (Active, Suspended, Cancelled)
|
||
- Tenant has subscription plan (Free, Starter, Professional, Enterprise)
|
||
- Tenant has resource limits (max_users, max_projects, max_storage_gb)
|
||
- Tenant has SSO configuration (JSONB, nullable)
|
||
- Tenant has timestamps (created_at, updated_at, suspended_at)
|
||
- Tenant has suspension reason (text, nullable)
|
||
|
||
**Domain Model:**
|
||
```csharp
|
||
public sealed class Tenant : AggregateRoot<TenantId>
|
||
{
|
||
public TenantId Id { get; private set; }
|
||
public TenantName Name { get; private set; }
|
||
public TenantSlug Slug { get; private set; }
|
||
public TenantStatus Status { get; private set; }
|
||
public SubscriptionPlan Plan { get; private set; }
|
||
public SsoConfiguration? SsoConfig { get; private set; }
|
||
|
||
// Resource limits
|
||
public int MaxUsers { get; private set; }
|
||
public int MaxProjects { get; private set; }
|
||
public int MaxStorageGb { get; private set; }
|
||
|
||
// Methods
|
||
public static Tenant Create(TenantName name, TenantSlug slug, SubscriptionPlan plan);
|
||
public void Activate();
|
||
public void Suspend(string reason);
|
||
public void Cancel();
|
||
public void ConfigureSso(SsoConfiguration config);
|
||
public void DisableSso();
|
||
public void UpgradePlan(SubscriptionPlan newPlan);
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Tenant entity follows DDD aggregate root pattern
|
||
- [ ] All business rules enforced at domain level
|
||
- [ ] Value objects used for name, slug, SSO config
|
||
- [ ] Domain events raised for all state changes
|
||
- [ ] Unit tests cover all business logic (100% coverage)
|
||
|
||
**Status:** COMPLETE (Day 1)
|
||
|
||
---
|
||
|
||
### MT-002: Tenant Identification
|
||
|
||
**Description:** Resolve current tenant from JWT claims for all API requests
|
||
|
||
**Functional Requirements:**
|
||
- JWT access token contains tenant_id and tenant_slug claims
|
||
- Middleware extracts tenant from JWT on every request
|
||
- TenantContext service provides current tenant to application
|
||
- Invalid or missing tenant results in 401 Unauthorized
|
||
- Tenant status checked (suspended tenants cannot access API)
|
||
|
||
**Technical Implementation:**
|
||
```csharp
|
||
// JWT Claims
|
||
{
|
||
"sub": "user-id",
|
||
"email": "john@acme.com",
|
||
"tenant_id": "tenant-uuid",
|
||
"tenant_slug": "acme",
|
||
"tenant_plan": "Enterprise"
|
||
}
|
||
|
||
// TenantContext Service
|
||
public class TenantContext
|
||
{
|
||
public TenantId CurrentTenantId { get; }
|
||
public string CurrentTenantSlug { get; }
|
||
public SubscriptionPlan CurrentTenantPlan { get; }
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] JWT contains tenant_id, tenant_slug, tenant_plan claims
|
||
- [ ] Middleware extracts tenant from JWT successfully
|
||
- [ ] TenantContext injected into all services
|
||
- [ ] Missing tenant results in 401 error
|
||
- [ ] Suspended tenant results in 403 error
|
||
- [ ] Performance: <5ms overhead per request
|
||
|
||
**Status:** PLANNED (Day 2)
|
||
|
||
---
|
||
|
||
### MT-003: Data Isolation
|
||
|
||
**Description:** Automatic tenant filtering for all database queries using EF Core Global Query Filter
|
||
|
||
**Functional Requirements:**
|
||
- All entities have tenant_id column
|
||
- EF Core Global Query Filter automatically adds `WHERE tenant_id = current_tenant`
|
||
- Queries return only current tenant's data
|
||
- Bypass requires explicit `.IgnoreQueryFilters()` (rare cases only)
|
||
- Cross-tenant queries prevented at database level
|
||
|
||
**Technical Implementation:**
|
||
```csharp
|
||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||
{
|
||
// Apply to all IHasTenant entities
|
||
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
||
{
|
||
if (typeof(IHasTenant).IsAssignableFrom(entityType.ClrType))
|
||
{
|
||
modelBuilder.Entity(entityType.ClrType)
|
||
.HasQueryFilter(BuildTenantFilter(entityType.ClrType));
|
||
}
|
||
}
|
||
}
|
||
|
||
private LambdaExpression BuildTenantFilter(Type entityType)
|
||
{
|
||
var param = Expression.Parameter(entityType, "e");
|
||
var tenantIdProperty = Expression.Property(param, nameof(IHasTenant.TenantId));
|
||
var currentTenantId = Expression.Constant(_tenantContext.CurrentTenantId);
|
||
var equals = Expression.Equal(tenantIdProperty, currentTenantId);
|
||
return Expression.Lambda(equals, param);
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Global Query Filter applied to all entities
|
||
- [ ] All queries automatically filter by tenant
|
||
- [ ] Cross-tenant queries return empty results
|
||
- [ ] Integration tests verify tenant isolation
|
||
- [ ] No database queries missing tenant filter (verified via logging)
|
||
- [ ] Performance: Queries complete in <50ms with proper indexes
|
||
|
||
**Status:** PLANNED (Day 2)
|
||
|
||
---
|
||
|
||
### MT-004: Tenant-Scoped Queries
|
||
|
||
**Description:** Ensure all database queries respect tenant boundaries
|
||
|
||
**Functional Requirements:**
|
||
- All SELECT queries include `WHERE tenant_id = ?`
|
||
- All INSERT queries include tenant_id column
|
||
- All UPDATE/DELETE queries filter by tenant_id
|
||
- Composite indexes on (tenant_id, other_columns) for performance
|
||
- Unique constraints scoped to tenant (e.g., email unique per tenant)
|
||
|
||
**Database Schema:**
|
||
```sql
|
||
-- Example: Projects table
|
||
CREATE TABLE projects (
|
||
id UUID PRIMARY KEY,
|
||
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
||
name VARCHAR(200) NOT NULL,
|
||
key VARCHAR(20) NOT NULL,
|
||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
CONSTRAINT uq_projects_tenant_key UNIQUE (tenant_id, key)
|
||
);
|
||
|
||
CREATE INDEX idx_projects_tenant_id ON projects(tenant_id);
|
||
CREATE INDEX idx_projects_tenant_key ON projects(tenant_id, key);
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] All tables have tenant_id column (NOT NULL)
|
||
- [ ] All queries include tenant_id filter
|
||
- [ ] Composite indexes exist for all tenant-filtered queries
|
||
- [ ] Unique constraints scoped to tenant
|
||
- [ ] EXPLAIN ANALYZE shows index scans (not sequential scans)
|
||
- [ ] Performance: Query time <50ms p95
|
||
|
||
**Status:** PLANNED (Day 2-4)
|
||
|
||
---
|
||
|
||
### MT-005: Cross-Tenant Protection
|
||
|
||
**Description:** Prevent any cross-tenant data access (security feature)
|
||
|
||
**Functional Requirements:**
|
||
- Attempt to access other tenant's data returns 403 Forbidden
|
||
- API validates tenant ownership before operations
|
||
- Database constraints enforce tenant isolation
|
||
- Integration tests verify cross-tenant protection
|
||
- Audit logs track cross-tenant access attempts
|
||
|
||
**Security Tests:**
|
||
```csharp
|
||
[Fact]
|
||
public async Task GetProject_WhenProjectBelongsToOtherTenant_Returns403()
|
||
{
|
||
// Arrange
|
||
var tenantA = await CreateTenantAsync("acme");
|
||
var tenantB = await CreateTenantAsync("beta");
|
||
var projectInTenantA = await CreateProjectAsync(tenantA, "Project A");
|
||
|
||
// Act: Login as Tenant B, try to access Tenant A's project
|
||
AuthenticateAs(tenantB);
|
||
var response = await _client.GetAsync($"/api/projects/{projectInTenantA.Id}");
|
||
|
||
// Assert
|
||
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Cross-tenant GET requests return 403 Forbidden
|
||
- [ ] Cross-tenant POST/PUT/DELETE requests return 403 Forbidden
|
||
- [ ] Global Query Filter prevents cross-tenant reads
|
||
- [ ] Repository methods validate tenant ownership
|
||
- [ ] Security tests verify protection (10+ test cases)
|
||
- [ ] Audit logs record cross-tenant attempts
|
||
|
||
**Status:** PLANNED (Day 3-4, Day 8 security testing)
|
||
|
||
---
|
||
|
||
### MT-006: Tenant Subdomain
|
||
|
||
**Description:** Each tenant has a unique subdomain (e.g., acme.colaflow.com)
|
||
|
||
**Functional Requirements:**
|
||
- Tenant slug used as subdomain (acme.colaflow.com)
|
||
- Subdomain used for tenant resolution on login page
|
||
- Subdomain displayed in tenant registration wizard
|
||
- Subdomain availability checked in real-time
|
||
- Reserved subdomains (www, api, admin, app, docs, etc.) prevented
|
||
|
||
**User Experience:**
|
||
```
|
||
User visits: acme.colaflow.com/login
|
||
↓
|
||
System resolves tenant from subdomain ("acme")
|
||
↓
|
||
Login page displays: "Welcome to Acme Corp"
|
||
↓
|
||
User enters credentials
|
||
↓
|
||
JWT includes tenant_id and tenant_slug
|
||
↓
|
||
User redirected to: acme.colaflow.com/dashboard
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Subdomain resolves to tenant on login page
|
||
- [ ] Tenant slug displayed in UI (e.g., "acme.colaflow.com")
|
||
- [ ] Reserved subdomains rejected (www, api, admin, etc.)
|
||
- [ ] Slug validation prevents invalid characters
|
||
- [ ] Slug availability checked in real-time (debounced 500ms)
|
||
|
||
**Status:** PLANNED (Day 5-6 frontend)
|
||
|
||
---
|
||
|
||
### AUTH-001: JWT Authentication
|
||
|
||
**Description:** JWT-based stateless authentication with tenant claims
|
||
|
||
**Functional Requirements:**
|
||
- JWT access token: short-lived (60 minutes), contains user + tenant claims
|
||
- JWT refresh token: long-lived (7 days), stored in httpOnly cookie
|
||
- Access token used for API authentication (Authorization: Bearer header)
|
||
- Refresh token used to obtain new access token
|
||
- JWT signature validated on every request
|
||
|
||
**JWT Structure:**
|
||
```json
|
||
{
|
||
"sub": "user-id-123",
|
||
"email": "john@acme.com",
|
||
"full_name": "John Doe",
|
||
"tenant_id": "tenant-uuid-456",
|
||
"tenant_slug": "acme",
|
||
"tenant_plan": "Enterprise",
|
||
"auth_provider": "Local",
|
||
"role": "User",
|
||
"exp": 1730678400,
|
||
"iat": 1730674800,
|
||
"iss": "colaflow-api",
|
||
"aud": "colaflow-web"
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] JWT generated on successful login
|
||
- [ ] Access token expires in 60 minutes
|
||
- [ ] Refresh token expires in 7 days
|
||
- [ ] JWT signature validated (HMAC SHA256)
|
||
- [ ] Invalid JWT returns 401 Unauthorized
|
||
- [ ] Expired JWT triggers automatic refresh
|
||
- [ ] Middleware validates JWT on every request
|
||
|
||
**Status:** PLANNED (Day 2-3)
|
||
|
||
---
|
||
|
||
### AUTH-002: Local Login
|
||
|
||
**Description:** Email + password authentication (traditional login)
|
||
|
||
**Functional Requirements:**
|
||
- User enters email and password
|
||
- System validates credentials
|
||
- Password hashed with BCrypt (cost factor 12)
|
||
- Failed login attempts throttled (max 5 attempts per 15 minutes)
|
||
- Successful login generates JWT tokens
|
||
- Login response includes user, tenant, and access token
|
||
|
||
**API Contract:**
|
||
```
|
||
POST /api/auth/login
|
||
Content-Type: application/json
|
||
|
||
Request:
|
||
{
|
||
"email": "john@acme.com",
|
||
"password": "SecurePassword123!"
|
||
}
|
||
|
||
Response (200 OK):
|
||
{
|
||
"user": {
|
||
"id": "user-id",
|
||
"email": "john@acme.com",
|
||
"fullName": "John Doe"
|
||
},
|
||
"tenant": {
|
||
"id": "tenant-id",
|
||
"slug": "acme",
|
||
"name": "Acme Corp"
|
||
},
|
||
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||
}
|
||
|
||
Set-Cookie: refreshToken=...; HttpOnly; Secure; SameSite=Strict; Max-Age=604800
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Valid credentials return 200 OK with JWT
|
||
- [ ] Invalid credentials return 401 Unauthorized
|
||
- [ ] Password hashed with BCrypt (cost 12)
|
||
- [ ] Failed login attempts throttled (max 5/15min)
|
||
- [ ] Refresh token set in httpOnly cookie
|
||
- [ ] Access token returned in response body
|
||
|
||
**Status:** PLANNED (Day 3 backend, Day 5 frontend)
|
||
|
||
---
|
||
|
||
### AUTH-003: Token Refresh
|
||
|
||
**Description:** Automatic token refresh mechanism to maintain user session
|
||
|
||
**Functional Requirements:**
|
||
- Frontend detects 401 error → calls refresh endpoint
|
||
- Refresh endpoint validates refresh token (httpOnly cookie)
|
||
- New access token generated and returned
|
||
- Original request retried with new access token
|
||
- Only one refresh in flight at a time (queue other requests)
|
||
- Failed refresh → logout user
|
||
|
||
**Flow:**
|
||
```
|
||
API Request with expired access token
|
||
↓ 401 Unauthorized
|
||
Frontend intercepts error
|
||
↓
|
||
POST /api/auth/refresh (refresh token in cookie)
|
||
↓ 200 OK (new access token)
|
||
Update Auth Store with new token
|
||
↓
|
||
Retry original request with new token
|
||
↓ 200 OK
|
||
Return response to user
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] 401 errors trigger automatic refresh
|
||
- [ ] Refresh endpoint validates refresh token
|
||
- [ ] New access token generated successfully
|
||
- [ ] Original request retried with new token
|
||
- [ ] Only one refresh call in flight (concurrent requests queued)
|
||
- [ ] Failed refresh logs out user
|
||
- [ ] Performance: Refresh completes in <500ms
|
||
|
||
**Status:** PLANNED (Day 5 frontend API client)
|
||
|
||
---
|
||
|
||
### AUTH-004: Logout
|
||
|
||
**Description:** Clear authentication state and invalidate tokens
|
||
|
||
**Functional Requirements:**
|
||
- User clicks logout button
|
||
- Frontend clears Auth Store (user, tenant, accessToken)
|
||
- Frontend calls logout endpoint (invalidates refresh token)
|
||
- Backend clears refresh token cookie
|
||
- User redirected to login page
|
||
|
||
**API Contract:**
|
||
```
|
||
POST /api/auth/logout
|
||
|
||
Response (200 OK):
|
||
{
|
||
"message": "Logged out successfully"
|
||
}
|
||
|
||
Set-Cookie: refreshToken=; HttpOnly; Secure; SameSite=Strict; Max-Age=0 (clear cookie)
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Logout clears frontend Auth Store
|
||
- [ ] Logout clears refresh token cookie
|
||
- [ ] User redirected to login page
|
||
- [ ] Cross-tab logout (using storage events)
|
||
- [ ] Subsequent API calls return 401 (no valid token)
|
||
|
||
**Status:** PLANNED (Day 3 backend, Day 5 frontend)
|
||
|
||
---
|
||
|
||
### SSO-001: OIDC Integration
|
||
|
||
**Description:** OpenID Connect (OIDC) integration for Azure AD, Google, Okta
|
||
|
||
**Functional Requirements:**
|
||
- Support Azure AD / Microsoft Entra
|
||
- Support Google Workspace
|
||
- Support Okta
|
||
- Tenant admin configures SSO (Authority URL, Client ID, Client Secret)
|
||
- OIDC discovery via .well-known/openid-configuration
|
||
- State parameter for CSRF protection
|
||
- User auto-provisioned on first SSO login
|
||
|
||
**SSO Flow:**
|
||
```
|
||
User clicks "Sign in with Microsoft"
|
||
↓
|
||
Frontend calls: POST /api/auth/sso/initiate (provider: AzureAD)
|
||
↓
|
||
Backend generates state token (CSRF protection)
|
||
Backend loads tenant's SSO config
|
||
Backend builds authorization URL
|
||
↓
|
||
Redirect user to: https://login.microsoftonline.com/authorize?...
|
||
↓
|
||
User authenticates with Microsoft
|
||
↓
|
||
Microsoft redirects back to: /api/auth/sso/callback?code=xxx&state=yyy
|
||
↓
|
||
Backend validates state (CSRF check)
|
||
Backend exchanges code for tokens (ID token + access token)
|
||
Backend validates ID token signature
|
||
↓
|
||
Backend creates or updates user (auto-provision)
|
||
Backend generates JWT with tenant claims
|
||
↓
|
||
Redirect user to: frontend/auth/callback?token=jwt
|
||
↓
|
||
Frontend stores JWT and redirects to dashboard
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] OIDC login works with Azure AD
|
||
- [ ] OIDC login works with Google
|
||
- [ ] OIDC login works with Okta
|
||
- [ ] State parameter validated (CSRF protection)
|
||
- [ ] ID token signature validated
|
||
- [ ] User auto-provisioned on first login
|
||
- [ ] User profile updated from IdP claims
|
||
- [ ] SSO errors handled gracefully (user-friendly messages)
|
||
|
||
**Status:** PLANNED (Day 3-4 backend, Day 6 frontend)
|
||
|
||
---
|
||
|
||
### SSO-002: SAML 2.0 Integration
|
||
|
||
**Description:** SAML 2.0 integration for generic enterprise IdPs
|
||
|
||
**Functional Requirements:**
|
||
- Support any SAML 2.0 compliant IdP
|
||
- Tenant admin configures SAML (Entity ID, SSO URL, X.509 Certificate)
|
||
- SAML assertion signature validated
|
||
- SAML metadata endpoint for SP (Service Provider)
|
||
- User auto-provisioned from SAML attributes
|
||
|
||
**SAML Configuration:**
|
||
```json
|
||
{
|
||
"provider": "SAML",
|
||
"entityId": "https://idp.acme.com/saml",
|
||
"ssoUrl": "https://idp.acme.com/sso",
|
||
"certificate": "-----BEGIN CERTIFICATE-----\nMIID...\n-----END CERTIFICATE-----",
|
||
"metadataUrl": "https://idp.acme.com/metadata.xml"
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] SAML login works with generic IdP
|
||
- [ ] SAML assertion signature validated
|
||
- [ ] X.509 certificate validated
|
||
- [ ] User auto-provisioned from SAML attributes (NameID, email, name)
|
||
- [ ] SAML metadata endpoint exposed for SP
|
||
- [ ] SAML errors handled gracefully
|
||
|
||
**Status:** PLANNED (Day 4 backend, Day 6 frontend)
|
||
|
||
---
|
||
|
||
### SSO-003: User Auto-Provisioning
|
||
|
||
**Description:** Automatically create user accounts on first SSO login
|
||
|
||
**Functional Requirements:**
|
||
- User does not exist in database → create new user
|
||
- User attributes populated from IdP (email, name, avatar)
|
||
- User linked to tenant based on SSO config
|
||
- User marked as SSO user (auth_provider = AzureAD/Google/Okta/SAML)
|
||
- External user ID stored (for future logins)
|
||
|
||
**Auto-Provisioning Logic:**
|
||
```csharp
|
||
public async Task<User> AutoProvisionUserFromSsoAsync(
|
||
TenantId tenantId,
|
||
string externalUserId,
|
||
string email,
|
||
string fullName,
|
||
AuthenticationProvider provider)
|
||
{
|
||
// Check if user already exists (by external_user_id)
|
||
var existingUser = await _userRepository.GetByExternalUserIdAsync(
|
||
tenantId, provider, externalUserId);
|
||
|
||
if (existingUser != null)
|
||
{
|
||
// Update profile from IdP
|
||
existingUser.UpdateProfile(email, fullName);
|
||
return existingUser;
|
||
}
|
||
|
||
// Create new user
|
||
var user = User.CreateFromSso(
|
||
tenantId,
|
||
Email.Create(email),
|
||
FullName.Create(fullName),
|
||
provider,
|
||
externalUserId
|
||
);
|
||
|
||
await _userRepository.AddAsync(user);
|
||
return user;
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] New users created automatically on first SSO login
|
||
- [ ] User email, name populated from IdP claims
|
||
- [ ] User linked to correct tenant
|
||
- [ ] External user ID stored for future logins
|
||
- [ ] Existing users updated (profile sync)
|
||
- [ ] Domain restrictions enforced (if configured)
|
||
|
||
**Status:** PLANNED (Day 3-4 backend)
|
||
|
||
---
|
||
|
||
### SSO-004: Domain Restrictions
|
||
|
||
**Description:** Restrict SSO login to specific email domains
|
||
|
||
**Functional Requirements:**
|
||
- Tenant admin can specify allowed email domains (e.g., @acme.com, @acme.co.uk)
|
||
- SSO login checks user's email domain against allowed list
|
||
- Unauthorized domain → login rejected with error message
|
||
- Empty allowed domains list → all domains allowed
|
||
|
||
**Configuration:**
|
||
```json
|
||
{
|
||
"provider": "AzureAD",
|
||
"allowedDomains": ["acme.com", "acme.co.uk"],
|
||
"autoProvision": true
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Email domain validated against allowed list
|
||
- [ ] Unauthorized domain returns error: "Your email domain is not allowed for SSO"
|
||
- [ ] Empty allowed list allows all domains
|
||
- [ ] Multiple domains supported
|
||
- [ ] Case-insensitive domain matching
|
||
|
||
**Status:** PLANNED (Day 3-4 backend, Day 6 frontend)
|
||
|
||
---
|
||
|
||
### SSO-005: SSO Configuration UI
|
||
|
||
**Description:** Admin interface to configure SSO for tenant
|
||
|
||
**Functional Requirements:**
|
||
- Provider selection: Azure AD, Google, Okta, SAML 2.0
|
||
- Dynamic form fields based on provider:
|
||
- OIDC: Authority URL, Client ID, Client Secret, Metadata URL
|
||
- SAML: Entity ID, SSO URL, X.509 Certificate, Metadata URL
|
||
- Auto-provision users toggle
|
||
- Allowed email domains input (TagInput)
|
||
- Test connection button (validates config)
|
||
- Save configuration button
|
||
- Display callback URL (for IdP configuration)
|
||
|
||
**UI Screenshots:** See `docs/design/multi-tenant-ux-flows.md#sso-configuration-form`
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Provider selection changes form fields
|
||
- [ ] All fields validate correctly (required, format)
|
||
- [ ] Test connection validates config (success/error with details)
|
||
- [ ] Save configuration updates tenant SSO config
|
||
- [ ] Callback URL displayed and copyable
|
||
- [ ] Form accessible only to Admin users
|
||
- [ ] Mobile responsive
|
||
|
||
**Status:** PLANNED (Day 6 frontend)
|
||
|
||
---
|
||
|
||
### MCP-001: Token Generation
|
||
|
||
**Description:** Generate secure MCP tokens for AI agents
|
||
|
||
**Functional Requirements:**
|
||
- Token format: `mcp_<tenant_slug>_<random_32_hex>`
|
||
- Token generated using CSPRNG (cryptographically secure random)
|
||
- Token hashed with SHA256 before storage (never stored plain-text)
|
||
- Token metadata: name, description, permissions, expiration
|
||
- Token displayed only once after creation (security)
|
||
|
||
**Token Generation:**
|
||
```csharp
|
||
public string GenerateToken(string tenantSlug)
|
||
{
|
||
var randomBytes = new byte[16]; // 128 bits
|
||
using var rng = RandomNumberGenerator.Create();
|
||
rng.GetBytes(randomBytes);
|
||
var randomHex = Convert.ToHexString(randomBytes).ToLowerInvariant();
|
||
return $"mcp_{tenantSlug}_{randomHex}";
|
||
}
|
||
|
||
public string HashToken(string token)
|
||
{
|
||
using var sha256 = SHA256.Create();
|
||
var hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(token));
|
||
return Convert.ToBase64String(hashBytes);
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Token format correct: `mcp_<slug>_<32_hex>`
|
||
- [ ] Token generated with CSPRNG (secure random)
|
||
- [ ] Token hashed with SHA256 before storage
|
||
- [ ] Token displayed only once (with warning)
|
||
- [ ] Token metadata stored (name, permissions, expiration)
|
||
- [ ] Copy and download options provided
|
||
|
||
**Status:** PLANNED (Day 3-4 backend, Day 7 frontend)
|
||
|
||
---
|
||
|
||
### MCP-002: Fine-Grained Permissions
|
||
|
||
**Description:** Resource-level + operation-level permissions for MCP tokens
|
||
|
||
**Functional Requirements:**
|
||
- Permissions stored as JSONB in database
|
||
- Resources: Projects, Issues, Documents, Reports, Sprints, Comments
|
||
- Operations: Read, Create, Update, Delete, Search
|
||
- Permission checked on every API call
|
||
- Unauthorized operation returns 403 Forbidden
|
||
|
||
**Permission Structure:**
|
||
```json
|
||
{
|
||
"projects": ["read", "search"],
|
||
"issues": ["read", "create", "update", "search"],
|
||
"documents": ["read", "create", "search"],
|
||
"reports": ["read"],
|
||
"sprints": ["read", "search"],
|
||
"comments": ["read", "create"]
|
||
}
|
||
```
|
||
|
||
**Permission Check:**
|
||
```csharp
|
||
public bool HasPermission(string resource, string operation)
|
||
{
|
||
if (!_permissions.ContainsKey(resource))
|
||
return false;
|
||
|
||
return _permissions[resource].Contains(operation);
|
||
}
|
||
|
||
// Example usage
|
||
if (!token.HasPermission("issues", "create"))
|
||
{
|
||
return Forbid("Token does not have permission to create issues");
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Permissions stored in JSONB format
|
||
- [ ] All 6 resources supported
|
||
- [ ] All 5 operations supported
|
||
- [ ] Permission checked on every MCP API call
|
||
- [ ] Unauthorized operation returns 403 Forbidden
|
||
- [ ] Audit log records permission violations
|
||
|
||
**Status:** PLANNED (Day 3-4 backend, Day 7 frontend)
|
||
|
||
---
|
||
|
||
### MCP-003: Token Revocation
|
||
|
||
**Description:** Instant token revocation for security
|
||
|
||
**Functional Requirements:**
|
||
- Admin can revoke token at any time
|
||
- Revoke updates token status to "Revoked"
|
||
- Revoked token cannot be used (returns 401 Unauthorized)
|
||
- Revocation reason recorded (optional)
|
||
- Revocation timestamp recorded
|
||
- Audit log entry created
|
||
|
||
**Revocation Logic:**
|
||
```csharp
|
||
public void Revoke(string reason)
|
||
{
|
||
if (Status == McpTokenStatus.Revoked)
|
||
throw new DomainException("Token is already revoked");
|
||
|
||
Status = McpTokenStatus.Revoked;
|
||
RevokedAt = DateTime.UtcNow;
|
||
RevocationReason = reason;
|
||
|
||
AddDomainEvent(new McpTokenRevokedEvent(Id, reason));
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Revoke button available on token details page
|
||
- [ ] Revoke confirmation dialog shown
|
||
- [ ] Revocation reason optional (text input)
|
||
- [ ] Revoked token status updated immediately
|
||
- [ ] Revoked token cannot be used (401 Unauthorized)
|
||
- [ ] Audit log entry created
|
||
- [ ] UI shows "Revoked" badge (red)
|
||
|
||
**Status:** PLANNED (Day 3-4 backend, Day 7 frontend)
|
||
|
||
---
|
||
|
||
### MCP-004: Token Audit Logs
|
||
|
||
**Description:** Complete audit trail of all MCP token operations
|
||
|
||
**Functional Requirements:**
|
||
- Every API call with MCP token logged
|
||
- Audit log includes: timestamp, HTTP method, endpoint, request body, response status, duration, IP address, user agent
|
||
- Audit logs stored in separate table (mcp_audit_logs)
|
||
- Audit logs displayed on token details page
|
||
- Audit logs filterable (date range, status code)
|
||
- Audit logs exportable (CSV)
|
||
|
||
**Audit Log Schema:**
|
||
```sql
|
||
CREATE TABLE mcp_audit_logs (
|
||
id UUID PRIMARY KEY,
|
||
tenant_id UUID NOT NULL,
|
||
token_id UUID NOT NULL,
|
||
user_id UUID NULL,
|
||
|
||
http_method VARCHAR(10) NOT NULL,
|
||
endpoint VARCHAR(500) NOT NULL,
|
||
request_body TEXT NULL,
|
||
status_code INT NOT NULL,
|
||
response_body TEXT NULL,
|
||
|
||
ip_address VARCHAR(50) NOT NULL,
|
||
user_agent VARCHAR(500) NULL,
|
||
|
||
timestamp TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
duration_ms INT NOT NULL,
|
||
error_message TEXT NULL
|
||
);
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Every MCP API call logged
|
||
- [ ] Audit log includes all required fields
|
||
- [ ] Audit logs displayed on token details page
|
||
- [ ] Pagination (50 logs per page)
|
||
- [ ] Date range filter works
|
||
- [ ] Status code filter works (200, 401, 403, 500)
|
||
- [ ] Export to CSV works
|
||
|
||
**Status:** PLANNED (Day 3-4 backend, Day 7 frontend)
|
||
|
||
---
|
||
|
||
### MCP-005: Token Management UI
|
||
|
||
**Description:** User interface to create, view, and revoke MCP tokens
|
||
|
||
**Functional Requirements:**
|
||
- Token list page (table view)
|
||
- Generate token button (opens 3-step wizard)
|
||
- Token creation wizard:
|
||
- Step 1: Token info (name, description, expiration)
|
||
- Step 2: Permissions (matrix UI or templates)
|
||
- Step 3: Review & create
|
||
- Token display modal (one-time, with copy/download)
|
||
- Token details page (metadata + audit logs)
|
||
- Revoke token action (with confirmation)
|
||
|
||
**UI Mockups:** See `docs/design/multi-tenant-ux-flows.md#mcp-token-management-flow`
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Token list loads and displays all tokens
|
||
- [ ] Generate token wizard works (3 steps)
|
||
- [ ] Permission matrix or templates easy to use
|
||
- [ ] Generated token displayed only once
|
||
- [ ] Copy button works (toast notification)
|
||
- [ ] Download button works (.env file)
|
||
- [ ] Token details page shows metadata + audit logs
|
||
- [ ] Revoke button works (with confirmation)
|
||
- [ ] Mobile responsive
|
||
|
||
**Status:** PLANNED (Day 7 frontend)
|
||
|
||
---
|
||
|
||
### TM-001: Tenant Registration
|
||
|
||
**Description:** Self-service tenant registration with 3-step wizard
|
||
|
||
**Functional Requirements:**
|
||
- Step 1: Company information (name, slug)
|
||
- Step 2: Administrator account (name, email, password)
|
||
- Step 3: Subscription plan selection
|
||
- Real-time slug validation (debounced 500ms)
|
||
- Password strength indicator (weak/medium/strong)
|
||
- Email verification (send email after registration)
|
||
- Terms of service acceptance (checkbox)
|
||
|
||
**Registration Flow:** See `docs/design/multi-tenant-ux-flows.md#tenant-registration-flow`
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] 3-step wizard navigates correctly
|
||
- [ ] Step 1: Company name and slug validated
|
||
- [ ] Slug availability checked in real-time
|
||
- [ ] Slug suggestions shown if taken
|
||
- [ ] Step 2: Email, password, name validated
|
||
- [ ] Password strength indicator works
|
||
- [ ] Step 3: Plan selection works
|
||
- [ ] Registration creates tenant + admin user
|
||
- [ ] User automatically logged in after registration
|
||
- [ ] Welcome email sent
|
||
- [ ] Mobile responsive
|
||
|
||
**Status:** PLANNED (Day 3 backend, Day 5 frontend)
|
||
|
||
---
|
||
|
||
### TM-002: Slug Validation
|
||
|
||
**Description:** Real-time slug availability check with suggestions
|
||
|
||
**Functional Requirements:**
|
||
- Slug validated on blur and debounced on typing (500ms)
|
||
- Slug format: 3-50 characters, lowercase, alphanumeric + hyphens
|
||
- Reserved slugs prevented (www, api, admin, app, dashboard, docs, blog, support, etc.)
|
||
- Taken slugs show "Taken" message with suggestions
|
||
- Available slugs show green checkmark
|
||
|
||
**Validation Rules:**
|
||
```typescript
|
||
// Format validation
|
||
const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
||
|
||
// Reserved slugs
|
||
const reservedSlugs = [
|
||
'www', 'api', 'admin', 'app', 'dashboard',
|
||
'docs', 'blog', 'support', 'status', 'legal'
|
||
];
|
||
|
||
// Suggestions if taken
|
||
function suggestAlternatives(slug: string): string[] {
|
||
return [
|
||
`${slug}-corp`,
|
||
`${slug}-team`,
|
||
`${slug}2`
|
||
];
|
||
}
|
||
```
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Slug format validated (regex)
|
||
- [ ] Reserved slugs rejected
|
||
- [ ] Availability checked via API
|
||
- [ ] Real-time validation (debounced 500ms)
|
||
- [ ] Green checkmark for available slug
|
||
- [ ] Red X for taken slug with suggestions
|
||
- [ ] Preview shows full domain (acme.colaflow.com)
|
||
|
||
**Status:** PLANNED (Day 3 backend API, Day 5 frontend component)
|
||
|
||
---
|
||
|
||
### TM-003: Subscription Plans
|
||
|
||
**Description:** Multiple subscription tiers with resource limits
|
||
|
||
**Functional Requirements:**
|
||
- 4 plans: Free, Starter, Professional, Enterprise
|
||
- Each plan has limits: max_users, max_projects, max_storage_gb
|
||
- Each plan has features (SSO, MCP tokens, support level)
|
||
- Plan selection during registration (Step 3)
|
||
- Plan upgrade/downgrade after registration (Settings page)
|
||
|
||
**Plan Comparison:**
|
||
|
||
| Feature | Free | Starter | Professional | Enterprise |
|
||
|---------|------|---------|--------------|------------|
|
||
| **Price** | $0/month | $19/month | $49/month | Custom |
|
||
| **Users** | 5 | 15 | 50 | Unlimited |
|
||
| **Projects** | 3 | 20 | 100 | Unlimited |
|
||
| **Storage** | 2 GB | 10 GB | 100 GB | 1 TB+ |
|
||
| **SSO** | No | No | Yes | Yes |
|
||
| **MCP Tokens** | 3 | 10 | 50 | Unlimited |
|
||
| **Support** | Community | Email | Priority | Dedicated |
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] 4 plans defined with limits
|
||
- [ ] Plan selection UI during registration
|
||
- [ ] Plan limits enforced (cannot exceed max_users, etc.)
|
||
- [ ] Plan upgrade increases limits
|
||
- [ ] Plan downgrade warns if limits exceeded
|
||
- [ ] Free trial available for paid plans (14 days)
|
||
|
||
**Status:** PLANNED (Day 1 domain model COMPLETE, Day 3 backend, Day 5 frontend)
|
||
|
||
---
|
||
|
||
### TM-004: Tenant Settings
|
||
|
||
**Description:** Admin interface to manage tenant configuration
|
||
|
||
**Functional Requirements:**
|
||
- General settings: Name, slug (read-only), logo
|
||
- SSO settings: Configure SSO (separate page)
|
||
- Billing settings: Plan, payment method, invoices
|
||
- Usage stats: Current users, projects, storage
|
||
- Danger zone: Suspend tenant, cancel subscription
|
||
|
||
**Settings Tabs:**
|
||
- General
|
||
- SSO (see SSO-005)
|
||
- Billing
|
||
- Usage
|
||
|
||
**Acceptance Criteria:**
|
||
- [ ] Settings page accessible to Admin users only
|
||
- [ ] Tenant name editable
|
||
- [ ] Logo upload works
|
||
- [ ] Usage stats displayed correctly
|
||
- [ ] Plan upgrade/downgrade works
|
||
- [ ] Suspend tenant button works (with confirmation)
|
||
- [ ] Cancel subscription works (with confirmation)
|
||
|
||
**Status:** PLANNED (Day 3 backend, Day 6 frontend)
|
||
|
||
---
|
||
|
||
## Non-Functional Requirements
|
||
|
||
### Performance
|
||
|
||
| Requirement | Target | Measurement |
|
||
|-------------|--------|-------------|
|
||
| **API Response Time** | <100ms (p95) | APM monitoring |
|
||
| **Database Query Time** | <50ms (p95) | pg_stat_statements |
|
||
| **Frontend Render Time** | <16ms (60fps) | React DevTools Profiler |
|
||
| **Token Validation Time** | <10ms | Custom instrumentation |
|
||
| **Page Load Time** | <1.5s | Lighthouse |
|
||
| **Time to Interactive** | <3s | Lighthouse |
|
||
|
||
### Scalability
|
||
|
||
| Requirement | Target | Notes |
|
||
|-------------|--------|-------|
|
||
| **Concurrent Users** | 10,000+ | Load testing with k6 |
|
||
| **Tenants** | 10,000+ | Shared database model |
|
||
| **API Requests** | 10,000/second | Horizontal scaling |
|
||
| **Database Size** | 100+ GB | PostgreSQL with partitioning |
|
||
| **Storage** | 10+ TB | S3 or equivalent |
|
||
|
||
### Reliability
|
||
|
||
| Requirement | Target | SLA |
|
||
|-------------|--------|-----|
|
||
| **Uptime** | 99.9% | ~8 hours downtime/year |
|
||
| **Error Rate** | <1% | Sentry monitoring |
|
||
| **Data Loss** | 0% | Daily backups, replication |
|
||
| **Recovery Time (RTO)** | <1 hour | Disaster recovery plan |
|
||
| **Recovery Point (RPO)** | <5 minutes | Continuous replication |
|
||
|
||
### Security
|
||
|
||
| Requirement | Standard | Verification |
|
||
|-------------|----------|--------------|
|
||
| **Authentication** | JWT + SSO | Security audit |
|
||
| **Authorization** | RBAC + tenant isolation | Penetration testing |
|
||
| **Data Encryption (Transit)** | TLS 1.3 | SSL Labs scan |
|
||
| **Data Encryption (Rest)** | AES-256 | Database encryption |
|
||
| **Password Hashing** | BCrypt (cost 12) | Code review |
|
||
| **OWASP Top 10** | Compliant | Security testing |
|
||
| **GDPR** | Compliant | Legal review |
|
||
|
||
---
|
||
|
||
## Technical Requirements
|
||
|
||
### Backend
|
||
|
||
| Component | Technology | Version | Rationale |
|
||
|-----------|------------|---------|-----------|
|
||
| **Runtime** | .NET | 9.0 | Latest LTS |
|
||
| **Language** | C# | 13.0 | Latest features |
|
||
| **Database** | PostgreSQL | 16+ | JSON support, performance |
|
||
| **ORM** | EF Core | 9.0 | Type-safe, migrations |
|
||
| **API** | ASP.NET Core | 9.0 | Modern, fast |
|
||
| **Auth** | ASP.NET Identity | 9.0 | Built-in SSO support |
|
||
| **Validation** | FluentValidation | 11+ | Expressive validation |
|
||
| **Testing** | xUnit | 2.6+ | Industry standard |
|
||
|
||
### Frontend
|
||
|
||
| Component | Technology | Version | Rationale |
|
||
|-----------|------------|---------|-----------|
|
||
| **Framework** | Next.js | 16+ | App Router, SSR |
|
||
| **Runtime** | React | 19+ | Latest features |
|
||
| **Language** | TypeScript | 5.6+ | Type safety |
|
||
| **State (Client)** | Zustand | 5+ | Lightweight, TypeScript-first |
|
||
| **State (Server)** | TanStack Query | 5+ | Caching, mutations |
|
||
| **Forms** | React Hook Form | 7+ | Performance, DX |
|
||
| **Validation** | Zod | 3+ | TypeScript schemas |
|
||
| **UI Components** | shadcn/ui | Latest | Accessible, customizable |
|
||
| **Styling** | Tailwind CSS | 4+ | Utility-first |
|
||
| **Testing** | Vitest | 2+ | Fast, Vite-based |
|
||
|
||
### Infrastructure
|
||
|
||
| Component | Technology | Notes |
|
||
|-----------|------------|-------|
|
||
| **Hosting** | Vercel / AWS | Cloud-native |
|
||
| **Database** | RDS PostgreSQL | Managed service |
|
||
| **Storage** | S3 | Scalable, cheap |
|
||
| **CDN** | CloudFront | Global distribution |
|
||
| **Monitoring** | Sentry + DataDog | Error tracking + APM |
|
||
| **CI/CD** | GitHub Actions | Automated deployments |
|
||
|
||
---
|
||
|
||
## Security Requirements
|
||
|
||
### Authentication Security
|
||
|
||
- [ ] Passwords hashed with BCrypt (cost factor 12)
|
||
- [ ] Failed login attempts throttled (max 5 per 15 minutes)
|
||
- [ ] JWT tokens signed with HMAC SHA256 (512-bit secret)
|
||
- [ ] Access tokens short-lived (60 minutes)
|
||
- [ ] Refresh tokens long-lived (7 days) in httpOnly cookies
|
||
- [ ] Token refresh requires valid refresh token
|
||
- [ ] Logout invalidates refresh token
|
||
|
||
### Authorization Security
|
||
|
||
- [ ] All API endpoints require authentication (except login, registration)
|
||
- [ ] Tenant isolation enforced at database level (Global Query Filter)
|
||
- [ ] Cross-tenant access attempts logged and blocked (403 Forbidden)
|
||
- [ ] Admin-only endpoints check user role
|
||
- [ ] MCP token permissions checked on every operation
|
||
- [ ] Permission violations logged in audit log
|
||
|
||
### Data Security
|
||
|
||
- [ ] All data encrypted in transit (TLS 1.3)
|
||
- [ ] All data encrypted at rest (AES-256)
|
||
- [ ] Database backups encrypted
|
||
- [ ] Sensitive fields (passwords, tokens) never logged
|
||
- [ ] PII (personally identifiable information) minimized
|
||
- [ ] GDPR compliance (data export, deletion)
|
||
|
||
### SSO Security
|
||
|
||
- [ ] State parameter used for CSRF protection (OIDC)
|
||
- [ ] SAML assertion signature validated
|
||
- [ ] X.509 certificate validated (SAML)
|
||
- [ ] ID token signature validated (OIDC)
|
||
- [ ] SSO configuration stored encrypted (Client Secret)
|
||
- [ ] Email domain restrictions enforced
|
||
|
||
### MCP Token Security
|
||
|
||
- [ ] Tokens generated with CSPRNG (cryptographically secure random)
|
||
- [ ] Tokens hashed with SHA256 before storage
|
||
- [ ] Tokens never stored plain-text
|
||
- [ ] Tokens displayed only once (after creation)
|
||
- [ ] Revoked tokens invalid immediately
|
||
- [ ] Token usage logged in audit trail
|
||
- [ ] Rate limiting applied to MCP endpoints
|
||
|
||
### OWASP Top 10 Compliance
|
||
|
||
- [ ] **A01:2021 – Broken Access Control:** Tenant isolation + RBAC enforced
|
||
- [ ] **A02:2021 – Cryptographic Failures:** TLS 1.3 + AES-256 encryption
|
||
- [ ] **A03:2021 – Injection:** Parameterized queries (EF Core)
|
||
- [ ] **A04:2021 – Insecure Design:** Security-first architecture
|
||
- [ ] **A05:2021 – Security Misconfiguration:** Secure defaults, config reviews
|
||
- [ ] **A06:2021 – Vulnerable Components:** Dependency scanning (Dependabot)
|
||
- [ ] **A07:2021 – Auth Failures:** JWT + SSO + MFA (future)
|
||
- [ ] **A08:2021 – Software Integrity:** Code signing, SRI
|
||
- [ ] **A09:2021 – Logging Failures:** Comprehensive audit logs
|
||
- [ ] **A10:2021 – SSRF:** Input validation, URL whitelisting
|
||
|
||
---
|
||
|
||
## Acceptance Criteria Matrix
|
||
|
||
### Feature Completion Checklist
|
||
|
||
| Feature ID | Feature Name | Backend | Frontend | Tests | Docs | Status |
|
||
|------------|--------------|---------|----------|-------|------|--------|
|
||
| MT-001 | Tenant Data Model | DONE | N/A | DONE | DONE | COMPLETE |
|
||
| MT-002 | Tenant Identification | Planned | Planned | Planned | Planned | Pending |
|
||
| MT-003 | Data Isolation | Planned | N/A | Planned | Planned | Pending |
|
||
| MT-004 | Tenant-Scoped Queries | Planned | N/A | Planned | Planned | Pending |
|
||
| MT-005 | Cross-Tenant Protection | Planned | N/A | Planned | Planned | Pending |
|
||
| MT-006 | Tenant Subdomain | Planned | Planned | Planned | Planned | Pending |
|
||
| AUTH-001 | JWT Authentication | Planned | Planned | Planned | Planned | Pending |
|
||
| AUTH-002 | Local Login | Planned | Planned | Planned | Planned | Pending |
|
||
| AUTH-003 | Token Refresh | Planned | Planned | Planned | Planned | Pending |
|
||
| AUTH-004 | Logout | Planned | Planned | Planned | Planned | Pending |
|
||
| SSO-001 | OIDC Integration | Planned | Planned | Planned | Planned | Pending |
|
||
| SSO-002 | SAML 2.0 Integration | Planned | Planned | Planned | Planned | Pending |
|
||
| SSO-003 | User Auto-Provisioning | Planned | N/A | Planned | Planned | Pending |
|
||
| SSO-004 | Domain Restrictions | Planned | Planned | Planned | Planned | Pending |
|
||
| SSO-005 | SSO Configuration UI | N/A | Planned | Planned | Planned | Pending |
|
||
| MCP-001 | Token Generation | Planned | Planned | Planned | Planned | Pending |
|
||
| MCP-002 | Fine-Grained Permissions | Planned | Planned | Planned | Planned | Pending |
|
||
| MCP-003 | Token Revocation | Planned | Planned | Planned | Planned | Pending |
|
||
| MCP-004 | Token Audit Logs | Planned | Planned | Planned | Planned | Pending |
|
||
| MCP-005 | Token Management UI | N/A | Planned | Planned | Planned | Pending |
|
||
| TM-001 | Tenant Registration | Planned | Planned | Planned | Planned | Pending |
|
||
| TM-002 | Slug Validation | Planned | Planned | Planned | Planned | Pending |
|
||
| TM-003 | Subscription Plans | DONE | Planned | DONE | Planned | Partial |
|
||
| TM-004 | Tenant Settings | Planned | Planned | Planned | Planned | Pending |
|
||
|
||
**Overall Progress:** 1/24 features complete (4.2%)
|
||
**Day 1 Progress:** 10% of backend foundation complete
|
||
|
||
---
|
||
|
||
## Appendix: Related Documentation
|
||
|
||
### Architecture Documents
|
||
- `docs/architecture/multi-tenancy-architecture.md` - Multi-tenant design
|
||
- `docs/architecture/sso-integration-architecture.md` - SSO implementation
|
||
- `docs/architecture/mcp-authentication-architecture.md` - MCP token system
|
||
- `docs/architecture/jwt-authentication-architecture.md` - JWT with tenant claims
|
||
- `docs/architecture/migration-strategy.md` - Database migration plan
|
||
|
||
### Design Documents
|
||
- `docs/design/multi-tenant-ux-flows.md` - Complete user flows
|
||
- `docs/design/ui-component-specs.md` - 16 component specifications
|
||
- `docs/design/responsive-design-guide.md` - Responsive breakpoints
|
||
- `docs/design/design-tokens.md` - Design system tokens
|
||
|
||
### Implementation Documents
|
||
- `docs/frontend/implementation-plan.md` - 4-day development plan
|
||
- `docs/frontend/api-integration-guide.md` - API client + endpoints
|
||
- `docs/frontend/state-management-guide.md` - Zustand + TanStack Query
|
||
- `docs/frontend/component-library.md` - Component implementations
|
||
|
||
---
|
||
|
||
**Document Status:** Approved for Development
|
||
**Next Review:** Day 4 (2025-11-06) - Post Backend Completion Review
|
||
**Owner:** Product Manager
|
||
**Approval Date:** 2025-11-03
|
||
|
||
---
|
||
|
||
**End of M1.2 Feature List**
|