# Admin Dashboard Implementation Plan

**Created**: October 3, 2025
**Updated**: October 6, 2025 - Separate microservice architecture
**Status**: Planning Phase
**Priority**: High - Multi-tenancy & Administration
**Estimated Effort**: 6-8 weeks (120-160 hours)

---

## 📋 Executive Summary

### Overview
Create a comprehensive **standalone admin service** for managing ParentFlow applications across multiple platforms (web, iOS, Android) with role-based access control (RBAC), user management, system monitoring, and configuration. This service will be deployed independently and manage all ParentFlow instances centrally.

### Architecture Decision
The admin dashboard will be implemented as a **separate microservice** to:
- Manage both web and future mobile applications
- Scale independently from main application
- Provide centralized control across all platforms
- Enable separate deployment and security policies
- Support multi-tenant administration

### Key Features
1. **Invite Code Registration System**: Control user registration with invite codes
2. **User Management**: CRUD operations, data export, anonymization
3. **Role-Based Access Control**: Parent, Guest, Admin roles
4. **Multi-Platform Support**: Manage web, iOS, and Android users
5. **Multi-Profile Support**: Multiple families and account switching
6. **Analytics Dashboard**: Cross-platform usage metrics, AI/voice analytics
7. **System Health Monitoring**: Service status across all platforms
8. **LLM Configuration**: Model settings, API keys, pricing
9. **Content Management**: Legal pages, subscriptions
10. **Email Configuration**: Mailgun settings management

### Goals
- **Security**: Strict admin authentication and audit logging
- **Scalability**: Support growing user base
- **Flexibility**: Easy configuration updates without code changes
- **Compliance**: GDPR/COPPA data management tools

---

## 🏗️ Architecture Overview

### Microservice Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                 ParentFlow Admin Service                     │
│                  (Standalone Application)                    │
│                   admin.parentflowapp.com                    │
│                                                               │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │   Invite     │  │   Users      │  │  Analytics   │      │
│  │   Codes      │  │  Management  │  │   Dashboard  │      │
│  └──────────────┘  └──────────────┘  └──────────────┘      │
│                                                               │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │   Platform   │  │    System    │  │     LLM      │      │
│  │   Manager    │  │    Health    │  │   Settings   │      │
│  └──────────────┘  └──────────────┘  └──────────────┘      │
└─────────────────────────────────────────────────────────────┘
                              │
                        Service-to-Service
                          Communication
                              │
        ┌─────────────────────┼─────────────────────┐
        ▼                     ▼                     ▼
┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│   ParentFlow  │     │  ParentFlow  │     │  ParentFlow  │
│      Web      │     │     iOS      │     │   Android    │
│   (NestJS)    │     │   (Swift)    │     │   (Kotlin)   │
├──────────────┤     ├──────────────┤     ├──────────────┤
│ Validates     │     │ Validates    │     │ Validates    │
│ invite codes  │     │ invite codes │     │ invite codes │
│ with admin    │     │ with admin   │     │ with admin   │
│ service       │     │ service      │     │ service      │
└──────────────┘     └──────────────┘     └──────────────┘
        │                     │                     │
        ▼                     ▼                     ▼
┌─────────────────────────────────────────────────────────────┐
│              Shared Database Infrastructure                  │
│                                                               │
│  • users (cross-platform)                                    │
│  • invite_codes (registration control)                       │
│  • platform_sessions (web/ios/android tracking)              │
│  • admin_audit_log (all admin actions)                       │
│  • system_configurations (per-platform settings)             │
└─────────────────────────────────────────────────────────────┘
```

### Admin Service Components

```
parentflow-admin-service/
├── src/
│   ├── modules/
│   │   ├── invite-codes/        # Invite code generation & validation
│   │   ├── user-management/     # Cross-platform user management
│   │   ├── platform-manager/    # Web/iOS/Android platform configs
│   │   ├── analytics/           # Unified analytics across platforms
│   │   ├── system-health/       # Monitor all platform services
│   │   ├── llm-config/          # AI configuration
│   │   ├── subscriptions/       # Subscription management
│   │   └── audit/               # Audit logging
│   ├── common/
│   │   ├── guards/              # Authentication guards
│   │   ├── interceptors/        # Service communication
│   │   └── decorators/          # Custom decorators
│   └── database/
│       └── migrations/          # Admin-specific migrations
├── admin-ui/                    # React admin dashboard
│   ├── pages/
│   │   ├── invite-codes/        # Manage invite codes
│   │   ├── users/               # User management
│   │   ├── platforms/           # Platform-specific settings
│   │   └── analytics/           # Analytics dashboard
│   └── components/
│       └── shared/              # Shared UI components
└── docker-compose.admin.yml    # Separate deployment

---

## 👥 Role-Based Access Control (RBAC)

### Role Definitions

#### 1. Parent (Default Role)
**Permissions**:
- Full access to their own families
- Create/manage children
- View all family data (activities, analytics)
- Invite guests to their families
- AI chat, voice commands
- Manage profile and settings

**Database**:
```typescript
enum UserRole {
  PARENT = 'parent',
  GUEST = 'guest', 
  ADMIN = 'admin',
}
```

#### 2. Guest (Limited Access)
**Permissions**:
- **CAN DO**:
  - Add activities (feeding, sleep, diaper, medication) - manual or voice
  - View real-time data for assigned family
  - Receive notifications
- **CANNOT DO**:
  - View historical data (>24 hours)
  - View analytics/insights
  - Edit or delete activities (except their own, within 1 hour)
  - Manage children profiles
  - Access AI chat
  - Invite other users
  - Change family settings

**Use Cases**:
- Nanny tracking daily activities
- Grandparents helping during visits
- Babysitter logging quick updates

#### 3. Admin (Full System Access)
**Permissions**:
- Access admin dashboard
- Manage all users (CRUD, anonymize, export)
- View system-wide analytics
- Configure LLM models
- Manage subscriptions and trials
- Edit legal pages
- Configure email settings
- View system health
- Audit logs access

**Security**:
- Admins CANNOT access user data without explicit audit trail
- All admin actions logged to `admin_audit_log`
- Require 2FA for admin accounts

---

## 🎟️ Invite Code Registration System

### Overview
Control user registration through invite codes to limit initial app access. This feature allows controlled rollout and beta testing across all platforms (web, iOS, Android).

### Features
- **Generate invite codes**: Batch or individual generation
- **Code types**: Single-use, multi-use, unlimited
- **Expiration dates**: Time-limited codes
- **Platform restrictions**: Limit codes to specific platforms
- **Usage tracking**: See who used which code
- **Enable/Disable**: Toggle registration requirement globally

### Database Schema

```sql
-- Invite codes table
CREATE TABLE invite_codes (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  code VARCHAR(20) UNIQUE NOT NULL, -- e.g., "BETA-2025-X7K9"
  type VARCHAR(20) NOT NULL, -- 'single', 'multi', 'unlimited'
  max_uses INTEGER DEFAULT 1, -- NULL for unlimited
  current_uses INTEGER DEFAULT 0,
  platform_restrictions VARCHAR(20)[], -- ['web', 'ios', 'android'] or NULL for all
  expires_at TIMESTAMP,
  metadata JSONB, -- Custom data: { "campaign": "beta", "referrer": "influencer1" }
  created_by UUID REFERENCES users(id),
  is_active BOOLEAN DEFAULT true,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_invite_codes_code ON invite_codes(code);
CREATE INDEX idx_invite_codes_active ON invite_codes(is_active) WHERE is_active = true;

-- Invite code usage tracking
CREATE TABLE invite_code_usage (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  invite_code_id UUID NOT NULL REFERENCES invite_codes(id),
  used_by_user_id UUID NOT NULL REFERENCES users(id),
  platform VARCHAR(20) NOT NULL, -- 'web', 'ios', 'android'
  device_info JSONB,
  ip_address INET,
  used_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_invite_code_usage_code ON invite_code_usage(invite_code_id);
CREATE INDEX idx_invite_code_usage_user ON invite_code_usage(used_by_user_id);

-- System configuration for registration
CREATE TABLE registration_config (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  require_invite_code BOOLEAN DEFAULT false,
  registration_enabled BOOLEAN DEFAULT true,
  custom_message TEXT, -- Message shown when registration is disabled
  whitelist_domains VARCHAR(255)[], -- Email domains that bypass invite requirement
  updated_by UUID REFERENCES users(id),
  updated_at TIMESTAMP DEFAULT NOW()
);
```

### API Endpoints

#### Admin Endpoints

```typescript
// Admin Service API
POST   /api/v1/admin/invite-codes                 // Generate codes
GET    /api/v1/admin/invite-codes                 // List all codes
GET    /api/v1/admin/invite-codes/:id             // Get code details
PATCH  /api/v1/admin/invite-codes/:id             // Update code
DELETE /api/v1/admin/invite-codes/:id             // Deactivate code
GET    /api/v1/admin/invite-codes/:id/usage       // Get usage history

// Batch operations
POST   /api/v1/admin/invite-codes/batch           // Generate multiple codes
POST   /api/v1/admin/invite-codes/export          // Export codes as CSV

// Configuration
GET    /api/v1/admin/registration/config          // Get registration settings
PATCH  /api/v1/admin/registration/config          // Update settings
```

#### Application Endpoints (Web/Mobile)

```typescript
// Public endpoint for all platforms
POST   /api/v1/auth/validate-invite-code
{
  "code": "BETA-2025-X7K9",
  "platform": "ios"
}

// Response
{
  "valid": true,
  "message": "Code accepted",
  "metadata": {
    "campaign": "beta"
  }
}

// Registration endpoint (modified)
POST   /api/v1/auth/register
{
  "email": "user@example.com",
  "password": "...",
  "inviteCode": "BETA-2025-X7K9",  // Required if enabled
  "platform": "web"
}
```

### Admin UI Components

```typescript
// pages/invite-codes/page.tsx
export default function InviteCodesPage() {
  const [requireInvite, setRequireInvite] = useState(false);

  return (
    <div>
      {/* Global toggle */}
      <Card>
        <h3>Registration Settings</h3>
        <Switch
          label="Require invite code for registration"
          checked={requireInvite}
          onChange={setRequireInvite}
        />
        <Text>Currently: {requireInvite ? 'Invite only' : 'Open registration'}</Text>
      </Card>

      {/* Code generator */}
      <Card>
        <h3>Generate Invite Codes</h3>
        <Form>
          <Input label="Prefix" placeholder="BETA-2025" />
          <Select label="Type">
            <option value="single">Single use</option>
            <option value="multi">Multi-use</option>
            <option value="unlimited">Unlimited</option>
          </Select>
          <Input label="Max uses" type="number" />
          <DatePicker label="Expires at" />
          <MultiSelect label="Platform restrictions">
            <option value="web">Web</option>
            <option value="ios">iOS</option>
            <option value="android">Android</option>
          </MultiSelect>
          <Input label="Quantity" type="number" defaultValue="1" />
          <Button>Generate Codes</Button>
        </Form>
      </Card>

      {/* Codes list */}
      <DataTable
        columns={[
          { key: 'code', label: 'Code' },
          { key: 'type', label: 'Type' },
          { key: 'uses', label: 'Uses', render: (row) => `${row.current_uses}/${row.max_uses || '∞'}` },
          { key: 'platforms', label: 'Platforms' },
          { key: 'expires_at', label: 'Expires' },
          { key: 'actions', label: 'Actions' }
        ]}
        data={inviteCodes}
      />
    </div>
  );
}
```

### Implementation in Main Application

```typescript
// src/modules/auth/auth.service.ts (ParentFlow Web/API)
@Injectable()
export class AuthService {

  async register(dto: RegisterDto) {
    // Check if invite codes are required
    const config = await this.getRegistrationConfig();

    if (config.requireInviteCode) {
      if (!dto.inviteCode) {
        throw new BadRequestException('Invite code is required for registration');
      }

      // Validate with admin service
      const validation = await this.adminService.validateInviteCode(
        dto.inviteCode,
        dto.platform || 'web'
      );

      if (!validation.valid) {
        throw new BadRequestException(validation.message || 'Invalid invite code');
      }

      // Track usage
      await this.adminService.recordInviteCodeUsage(
        dto.inviteCode,
        userId,
        dto.platform
      );
    }

    // Continue with normal registration...
  }

  private async getRegistrationConfig() {
    // Cache this for performance
    return await this.adminService.getRegistrationConfig();
  }
}
```

### Mobile Integration

```swift
// iOS - RegistrationViewController.swift
func validateInviteCode(_ code: String) async throws -> Bool {
    let response = try await AdminAPI.validateInviteCode(
        code: code,
        platform: "ios"
    )
    return response.valid
}

func register() async throws {
    // Check if invite code is required
    if registrationConfig.requireInviteCode {
        guard let inviteCode = inviteCodeTextField.text, !inviteCode.isEmpty else {
            throw RegistrationError.inviteCodeRequired
        }

        // Validate before proceeding
        let isValid = try await validateInviteCode(inviteCode)
        if !isValid {
            throw RegistrationError.invalidInviteCode
        }
    }

    // Continue with registration
}
```

### Analytics & Reporting

Track invite code effectiveness:
- **Conversion rate**: Codes generated vs. used
- **Platform distribution**: Usage by platform
- **Time to use**: Average time from generation to use
- **Referral tracking**: Which campaigns/sources are most effective
- **Geographic distribution**: Where users are registering from

---

## 🗄️ Database Schema Changes

### New Tables

#### 1. User Role Enhancement
```sql
-- Modify existing users table
ALTER TABLE users 
  ADD COLUMN global_role VARCHAR(20) DEFAULT 'parent',
  ADD COLUMN is_admin BOOLEAN DEFAULT false,
  ADD COLUMN admin_permissions JSONB DEFAULT '[]';

-- Add index for admin queries
CREATE INDEX idx_users_global_role ON users(global_role);
CREATE INDEX idx_users_is_admin ON users(is_admin) WHERE is_admin = true;
```

#### 2. Family Membership Roles
```sql
-- Modify family_memberships table
ALTER TABLE family_memberships
  ADD COLUMN family_role VARCHAR(20) DEFAULT 'parent', -- parent or guest
  ADD COLUMN permissions JSONB DEFAULT '{}',
  ADD COLUMN invited_by UUID REFERENCES users(id),
  ADD COLUMN access_granted_at TIMESTAMP DEFAULT NOW(),
  ADD COLUMN access_expires_at TIMESTAMP NULL;

-- Constraints
ALTER TABLE family_memberships
  ADD CONSTRAINT valid_family_role 
  CHECK (family_role IN ('parent', 'guest'));
```

#### 3. User Profiles (Multi-Profile Support)
```sql
CREATE TABLE user_profiles (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  profile_name VARCHAR(100) NOT NULL,
  profile_type VARCHAR(20) NOT NULL, -- 'primary', 'work', 'personal'
  default_family_id UUID REFERENCES families(id),
  is_active BOOLEAN DEFAULT true,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW(),
  
  UNIQUE(user_id, profile_name)
);

CREATE INDEX idx_user_profiles_user_id ON user_profiles(user_id);
```

#### 4. Admin Audit Log
```sql
CREATE TABLE admin_audit_log (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  admin_user_id UUID NOT NULL REFERENCES users(id),
  action VARCHAR(50) NOT NULL, -- 'user.create', 'user.delete', 'config.update'
  target_entity VARCHAR(50), -- 'user', 'subscription', 'config'
  target_id UUID,
  changes JSONB, -- before/after values
  ip_address INET,
  user_agent TEXT,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_admin_audit_log_admin_user ON admin_audit_log(admin_user_id);
CREATE INDEX idx_admin_audit_log_created_at ON admin_audit_log(created_at DESC);
CREATE INDEX idx_admin_audit_log_action ON admin_audit_log(action);
```

#### 5. LLM Configuration
```sql
CREATE TABLE llm_config (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  provider VARCHAR(50) NOT NULL, -- 'azure', 'openai', 'anthropic'
  service_type VARCHAR(50) NOT NULL, -- 'chat', 'whisper', 'embeddings'
  endpoint_url TEXT NOT NULL,
  api_key_encrypted TEXT NOT NULL, -- Encrypted with AES-256
  model_name VARCHAR(100) NOT NULL,
  deployment_name VARCHAR(100), -- For Azure
  api_version VARCHAR(20),
  price_per_1m_input_tokens DECIMAL(10, 4), -- e.g., 0.0015 for $1.50/1M
  price_per_1m_output_tokens DECIMAL(10, 4),
  max_tokens INTEGER DEFAULT 4000,
  temperature DECIMAL(3, 2) DEFAULT 0.7,
  is_active BOOLEAN DEFAULT true,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_llm_config_provider_service ON llm_config(provider, service_type);
```

#### 6. Subscription Plans
```sql
CREATE TABLE subscription_plans (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  name VARCHAR(100) NOT NULL UNIQUE,
  description TEXT,
  price_monthly DECIMAL(10, 2),
  price_yearly DECIMAL(10, 2),
  features JSONB, -- Feature flags: { "ai_queries": "unlimited", "voice_commands": 500 }
  max_children INTEGER,
  max_family_members INTEGER,
  ai_query_limit INTEGER, -- NULL = unlimited
  voice_command_limit INTEGER,
  trial_period_days INTEGER DEFAULT 14,
  is_active BOOLEAN DEFAULT true,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

-- Add subscription to users
ALTER TABLE users
  ADD COLUMN subscription_plan_id UUID REFERENCES subscription_plans(id),
  ADD COLUMN subscription_status VARCHAR(20) DEFAULT 'trial', -- trial, active, expired, cancelled
  ADD COLUMN subscription_started_at TIMESTAMP,
  ADD COLUMN subscription_expires_at TIMESTAMP,
  ADD COLUMN trial_ends_at TIMESTAMP;
```

#### 7. Email Configuration
```sql
CREATE TABLE email_config (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  provider VARCHAR(50) DEFAULT 'mailgun',
  region VARCHAR(10) DEFAULT 'US', -- US or EU
  api_key_encrypted TEXT NOT NULL,
  domain VARCHAR(255) NOT NULL,
  sender_email VARCHAR(255) NOT NULL,
  sender_name VARCHAR(255) NOT NULL,
  is_active BOOLEAN DEFAULT true,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);
```

#### 8. Legal Pages (CMS)
```sql
CREATE TABLE legal_pages (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  slug VARCHAR(100) NOT NULL UNIQUE, -- 'privacy', 'terms', 'eula', 'cookies'
  title VARCHAR(255) NOT NULL,
  content TEXT NOT NULL, -- Markdown or HTML
  language VARCHAR(5) DEFAULT 'en',
  version INTEGER DEFAULT 1,
  is_published BOOLEAN DEFAULT false,
  last_updated_by UUID REFERENCES users(id),
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW(),
  
  UNIQUE(slug, language)
);
```

---

## 🔐 Security & Permissions

### Admin Guard Implementation

**File**: `src/common/guards/admin.guard.ts`

```typescript
import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs/common';
import { JwtAuthGuard } from './jwt-auth.guard';

@Injectable()
export class AdminGuard extends JwtAuthGuard {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    // First check JWT authentication
    const isAuthenticated = await super.canActivate(context);
    if (!isAuthenticated) {
      return false;
    }

    const request = context.switchToHttp().getRequest();
    const user = request.user;

    // Check if user is admin
    if (!user.isAdmin) {
      throw new ForbiddenException('Admin access required');
    }

    return true;
  }
}
```

### Family Role Guard

**File**: `src/common/guards/family-role.guard.ts`

```typescript
import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';

export const RequireFamilyRole = (...roles: string[]) => 
  SetMetadata('familyRoles', roles);

@Injectable()
export class FamilyRoleGuard implements CanActivate {
  constructor(private reflector: Reflector, private familyService: FamilyService) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const requiredRoles = this.reflector.get<string[]>('familyRoles', context.getHandler());
    if (!requiredRoles) {
      return true;
    }

    const request = context.switchToHttp().getRequest();
    const user = request.user;
    const familyId = request.params.familyId || request.body.familyId;

    const membership = await this.familyService.getUserFamilyRole(user.id, familyId);

    if (!membership) {
      throw new ForbiddenException('Not a member of this family');
    }

    if (!requiredRoles.includes(membership.familyRole)) {
      throw new ForbiddenException(`Requires family role: ${requiredRoles.join(' or ')}`);
    }

    // Attach to request for use in controllers
    request.familyRole = membership.familyRole;
    return true;
  }
}
```

### Usage Example

```typescript
@Controller('api/v1/analytics')
export class AnalyticsController {
  
  @Get(':childId/insights')
  @UseGuards(JwtAuthGuard, FamilyRoleGuard)
  @RequireFamilyRole('parent') // Guests cannot access analytics
  async getInsights(@Param('childId') childId: string) {
    // Only parents can access
  }

  @Post(':childId/activities')
  @UseGuards(JwtAuthGuard, FamilyRoleGuard)
  @RequireFamilyRole('parent', 'guest') // Both can add activities
  async createActivity(@Param('childId') childId: string) {
    // Both parents and guests can add
  }
}
```

---

## 📊 Admin Dashboard Features

### 1. User Management

**Endpoint**: `GET /api/v1/admin/users`

**Features**:
- **List Users**: Paginated, searchable, filterable
- **User Details**: Full profile, activity history, subscription
- **Create User**: Manual user creation (for demos, test accounts)
- **Edit User**: Update profile, subscription, role
- **Delete User**: Soft delete with anonymization option
- **Anonymize User**: GDPR compliance - replace PII with anonymized data
- **Export User Data**: Full data export in JSON/CSV
- **Verify User**: Manual email verification override
- **Manage Subscription**: Change plan, extend trial, apply discount

**UI Components**:
```
maternal-web/app/admin/users/
├── page.tsx                    # User list with search/filter
├── [userId]/
│   ├── page.tsx                # User detail view
│   ├── edit/page.tsx           # Edit user form
│   └── export/page.tsx         # Data export interface
└── create/page.tsx             # Create user form
```

**Backend Module**:
```typescript
// src/modules/admin/user-management/user-management.service.ts
@Injectable()
export class UserManagementService {
  
  async listUsers(filters: UserFilters, pagination: Pagination) {
    // Query with filters, sorting, pagination
  }

  async getUserDetails(userId: string) {
    // Full user details including:
    // - Profile info
    // - Families and roles
    // - Subscription status
    // - Activity stats
    // - AI usage stats
  }

  async anonymizeUser(userId: string, adminId: string) {
    // GDPR compliance
    // Replace: name → "Anonymized User 12345"
    // Replace: email → "anon_12345@maternal.local"
    // Keep: aggregated analytics (anonymized)
    // Log action in audit_log
  }

  async exportUserData(userId: string) {
    // Full GDPR export
    // - User profile
    // - Children data
    // - Activities
    // - AI conversations
    // - Photos (URLs)
    return { json, csv };
  }

  async changeSubscription(userId: string, planId: string, adminId: string) {
    // Update subscription
    // Log in audit trail
  }
}
```

---

### 2. Role Management UI

**Components**:

```typescript
// components/admin/RoleSelector.tsx
export function RoleSelector({ userId, currentRole, onRoleChange }) {
  return (
    <Select value={currentRole} onChange={onRoleChange}>
      <option value="parent">Parent (Full Access)</option>
      <option value="guest">Guest (Limited Access)</option>
      <option value="admin">Admin (System Access)</option>
    </Select>
  );
}

// components/admin/FamilyRoleManager.tsx
export function FamilyRoleManager({ userId, families }) {
  // Show user's role in each family
  // Allow changing role per family
  return (
    <Table>
      {families.map(family => (
        <TableRow key={family.id}>
          <TableCell>{family.name}</TableCell>
          <TableCell>
            <RoleSelector 
              userId={userId} 
              familyId={family.id}
              currentRole={family.userRole}
            />
          </TableCell>
        </TableRow>
      ))}
    </Table>
  );
}
```

---

### 3. Multi-Profile Support

**User Stories**:

**Use Case 1**: Multiple Families, One Account
```
User: Sarah (Parent)
├── Profile: "Work Family" (childcare at work)
│   └── Family: "ABC Daycare"
│       ├── Child: Emma (not hers, she's a caregiver)
│       └── Role: Guest
└── Profile: "Home Family" (her own kids)
    └── Family: "Smith Family"
        ├── Child: Liam
        ├── Child: Olivia
        └── Role: Parent
```

**Use Case 2**: Multiple Accounts
```
User: John
├── Account 1: john@personal.com (Parent in "Doe Family")
└── Account 2: john@work.com (Guest in "Work Daycare")
```

**Implementation**:

```typescript
// components/layout/ProfileSwitcher.tsx
export function ProfileSwitcher() {
  const { user, profiles, currentProfile, switchProfile } = useAuth();

  return (
    <Menu>
      <MenuButton>
        <Avatar src={currentProfile.avatar} />
        {currentProfile.name}
      </MenuButton>
      <MenuList>
        {profiles.map(profile => (
          <MenuItem 
            key={profile.id} 
            onClick={() => switchProfile(profile.id)}
            isActive={profile.id === currentProfile.id}
          >
            <Avatar src={profile.avatar} size="sm" />
            <Box>
              <Text>{profile.name}</Text>
              <Text fontSize="xs" color="gray.500">
                {profile.familyName} · {profile.role}
              </Text>
            </Box>
          </MenuItem>
        ))}
        <MenuDivider />
        <MenuItem onClick={() => router.push('/add-profile')}>
          + Add Profile
        </MenuItem>
      </MenuList>
    </Menu>
  );
}
```

**Backend API**:

```typescript
// POST /api/v1/profiles
async createProfile(userId: string, dto: CreateProfileDto) {
  // Create new profile
  // Link to family
  // Set default
}

// PATCH /api/v1/profiles/:id/switch
async switchProfile(userId: string, profileId: string) {
  // Update user's active profile
  // Return new auth context
}
```

---

### 4. Analytics Dashboard

**Metrics to Track**:

#### User Analytics
- Total users (active, inactive, trial, paid)
- New users per day/week/month
- User growth rate
- Churn rate
- Average session duration
- Daily/Monthly Active Users (DAU/MAU)

#### Family & Children Analytics
- Total families
- Average children per family
- Average family size (members)
- Most active families

#### Feature Usage
- Activities logged per day (by type)
- AI queries per day
- Voice commands per day
- Photo uploads per day
- Most used features

#### AI/LLM Analytics
- Total AI queries (by model)
- Average tokens per query (input/output)
- Estimated costs per model
- Average response time
- Error rate

#### Voice Analytics
- Total voice commands
- Success rate (transcription accuracy)
- Most common voice intents
- Average processing time

**UI Components**:

```typescript
// app/admin/analytics/page.tsx
export default function AnalyticsDashboard() {
  return (
    <Grid columns={3}>
      <StatCard 
        label="Total Users" 
        value={stats.totalUsers}
        change={stats.userGrowth}
      />
      <StatCard 
        label="Active Families" 
        value={stats.activeFamilies}
      />
      <StatCard 
        label="AI Queries Today" 
        value={stats.aiQueriesToday}
        cost={stats.estimatedCost}
      />
      
      <Chart 
        title="User Growth"
        data={stats.userGrowthData}
        type="line"
      />
      
      <Chart 
        title="Feature Usage"
        data={stats.featureUsageData}
        type="bar"
      />
      
      <Chart 
        title="AI Cost Breakdown"
        data={stats.aiCostData}
        type="pie"
      />
    </Grid>
  );
}
```

**Backend**:

```typescript
// src/modules/admin/analytics/analytics-admin.service.ts
@Injectable()
export class AnalyticsAdminService {
  
  async getSystemStats() {
    return {
      users: await this.getUserStats(),
      families: await this.getFamilyStats(),
      usage: await this.getUsageStats(),
      ai: await this.getAIStats(),
      voice: await this.getVoiceStats(),
    };
  }

  async getAIStats() {
    // Query from ai_conversations table
    // Calculate token usage
    // Estimate costs based on llm_config pricing
    return {
      totalQueries: 15234,
      totalInputTokens: 2450000,
      totalOutputTokens: 1850000,
      estimatedCost: 5.47, // in USD
      byModel: [
        { model: 'gpt-4o-mini', queries: 12000, cost: 3.20 },
        { model: 'gpt-4', queries: 3234, cost: 2.27 },
      ],
    };
  }
}
```

---

### 5. System Health Monitoring

**Metrics**:
- Service status (backend, database, redis, mongodb)
- API response times (p50, p95, p99)
- Error rates
- Database connection pool status
- Redis cache hit/miss ratio
- Queue depths (background jobs)
- Memory/CPU usage
- Disk space

**Integration with Existing Health Endpoints**:

```typescript
// Reuse existing health endpoints
GET /health                  # Overall health
GET /health/liveness         # Liveness probe
GET /health/readiness        # Readiness probe

// New admin-specific endpoint
GET /api/v1/admin/system/health

// Response:
{
  "status": "healthy",
  "uptime": 345600, // seconds
  "services": {
    "postgres": { "status": "up", "responseTime": "15ms" },
    "redis": { "status": "up", "responseTime": "2ms" },
    "mongodb": { "status": "up", "responseTime": "18ms" },
    "minio": { "status": "up", "responseTime": "45ms" },
    "azureOpenAI": { "status": "up", "responseTime": "120ms" }
  },
  "metrics": {
    "apiResponseTime": { "p50": 85, "p95": 250, "p99": 450 },
    "errorRate": 0.02,
    "requestsPerMinute": 1250,
    "cacheHitRatio": 0.85
  },
  "resources": {
    "memoryUsage": { "used": "2.1GB", "total": "4GB", "percentage": 52.5 },
    "cpuUsage": 35.2,
    "diskSpace": { "used": "45GB", "total": "100GB", "percentage": 45 }
  }
}
```

**UI**:

```typescript
// app/admin/system/health/page.tsx
export default function SystemHealthPage() {
  const { data, refetch } = useQuery('/api/v1/admin/system/health', {
    refetchInterval: 10000, // Refresh every 10s
  });

  return (
    <>
      <HealthStatusBadge status={data.status} />
      
      <ServiceStatusGrid services={data.services} />
      
      <MetricsChart metrics={data.metrics} />
      
      <ResourceUsageCards resources={data.resources} />
    </>
  );
}
```

---

### 6. LLM Configuration Management

**UI Features**:
- Add/Edit LLM endpoints
- Manage API keys (encrypted storage)
- Set model names and deployments
- Configure pricing (per 1M tokens)
- Enable/disable models
- Test connections

**Backend**:

```typescript
// src/modules/admin/llm-config/llm-config.service.ts
@Injectable()
export class LLMConfigService {
  
  async createConfig(dto: CreateLLMConfigDto, adminId: string) {
    // Encrypt API key
    const encryptedKey = await this.encryptionService.encrypt(dto.apiKey);
    
    const config = await this.llmConfigRepository.save({
      ...dto,
      apiKeyEncrypted: encryptedKey,
    });

    // Audit log
    await this.auditService.log({
      adminUserId: adminId,
      action: 'llm_config.create',
      targetId: config.id,
      changes: { provider: dto.provider, serviceType: dto.serviceType },
    });

    return config;
  }

  async testConnection(configId: string) {
    const config = await this.llmConfigRepository.findOne(configId);
    const apiKey = await this.encryptionService.decrypt(config.apiKeyEncrypted);

    try {
      // Test API call
      const response = await axios.post(config.endpointUrl, {
        messages: [{ role: 'user', content: 'Test' }],
        max_tokens: 10,
      }, {
        headers: { 'api-key': apiKey },
      });

      return { success: true, latency: response.duration };
    } catch (error) {
      return { success: false, error: error.message };
    }
  }

  async getEstimatedCosts() {
    // Calculate monthly costs based on usage
    const usage = await this.getMonthlyTokenUsage();
    
    return usage.map(model => ({
      modelName: model.name,
      inputTokens: model.inputTokens,
      outputTokens: model.outputTokens,
      estimatedCost: (
        (model.inputTokens / 1000000) * model.pricePerMInput +
        (model.outputTokens / 1000000) * model.pricePerMOutput
      ),
    }));
  }
}
```

---

### 7. Content Management (Legal Pages)

**Features**:
- Create/Edit legal pages (Privacy Policy, Terms, EULA, Cookies)
- Markdown editor with preview
- Multi-language support
- Version history
- Publish/Unpublish
- SEO metadata

**UI**:

```typescript
// app/admin/pages/[slug]/edit/page.tsx
export default function EditLegalPage({ params }) {
  const [content, setContent] = useState('');
  const [language, setLanguage] = useState('en');

  return (
    <Form>
      <Input label="Title" />
      <Select label="Language" value={language} onChange={setLanguage}>
        <option value="en">English</option>
        <option value="es">Spanish</option>
        <option value="fr">French</option>
      </Select>
      
      <MarkdownEditor 
        value={content} 
        onChange={setContent}
        height="600px"
      />
      
      <MarkdownPreview content={content} />
      
      <ButtonGroup>
        <Button variant="outline">Save Draft</Button>
        <Button>Publish</Button>
      </ButtonGroup>
    </Form>
  );
}
```

---

### 8. Subscription Management

**Features**:
- Create subscription plans
- Set pricing (monthly/yearly)
- Define feature limits
- Trial period configuration
- Apply to users
- Discount codes

**Data Model**:

```typescript
interface SubscriptionPlan {
  id: string;
  name: string; // 'Free', 'Pro', 'Family'
  description: string;
  priceMonthly: number;
  priceYearly: number;
  features: {
    aiQueries: 'unlimited' | number;
    voiceCommands: 'unlimited' | number;
    maxChildren: number;
    maxFamilyMembers: number;
    analytics: boolean;
    prioritySupport: boolean;
  };
  trialPeriodDays: number;
}
```

**UI**:

```typescript
// app/admin/subscriptions/page.tsx
export default function SubscriptionPlansPage() {
  return (
    <>
      <PlanList plans={plans} />
      <Button onClick={openCreateDialog}>Create Plan</Button>
      
      <CreatePlanDialog>
        <Input label="Plan Name" />
        <Input label="Monthly Price" type="number" prefix="$" />
        <Input label="Yearly Price" type="number" prefix="$" />
        <Input label="Trial Days" type="number" />
        
        <FeatureLimits>
          <Input label="Max Children" />
          <Input label="AI Queries/Month" />
          <Toggle label="Analytics Access" />
        </FeatureLimits>
      </CreatePlanDialog>
    </>
  );
}
```

---

### 9. Email Configuration

**UI**:

```typescript
// app/admin/settings/email/page.tsx
export default function EmailSettingsPage() {
  return (
    <Form>
      <Select label="Region">
        <option value="US">US (api.mailgun.net)</option>
        <option value="EU">EU (api.eu.mailgun.net)</option>
      </Select>
      
      <Input 
        label="API Key" 
        type="password" 
        placeholder="key-xxxxx"
      />
      
      <Input label="Domain" placeholder="mg.maternal.com" />
      
      <Input label="Sender Email" placeholder="noreply@maternal.com" />
      
      <Input label="Sender Name" placeholder="Maternal App" />
      
      <Button onClick={testEmail}>Send Test Email</Button>
      <Button>Save Configuration</Button>
    </Form>
  );
}
```

**Backend**:

```typescript
// src/modules/admin/email-config/email-config.service.ts
@Injectable()
export class EmailConfigService {
  
  async updateConfig(dto: UpdateEmailConfigDto, adminId: string) {
    const encryptedKey = await this.encryptionService.encrypt(dto.apiKey);
    
    const config = await this.emailConfigRepository.save({
      ...dto,
      apiKeyEncrypted: encryptedKey,
    });

    // Update EmailService to use new config
    await this.emailService.reloadConfig();

    // Audit log
    await this.auditService.log({
      adminUserId: adminId,
      action: 'email_config.update',
      changes: { region: dto.region, domain: dto.domain },
    });

    return config;
  }

  async sendTestEmail(recipientEmail: string) {
    try {
      await this.emailService.sendEmail({
        to: recipientEmail,
        subject: 'Test Email from Maternal App Admin',
        text: 'If you received this, email configuration is working!',
      });
      return { success: true };
    } catch (error) {
      return { success: false, error: error.message };
    }
  }
}
```

---

## 🚀 Deployment Strategy

### Admin Service Deployment

The admin service will be deployed as a **separate microservice**:

#### Infrastructure
```yaml
# docker-compose.admin.yml
version: '3.8'

services:
  admin-api:
    build: ./parentflow-admin-service
    container_name: parentflow-admin-api
    ports:
      - "4000:4000"  # Admin API on separate port
    environment:
      NODE_ENV: production
      # Dedicated PostgreSQL Server
      DATABASE_URL: postgresql://postgres:a3ppq@10.0.0.207:5432/parentflow
      DATABASE_HOST: 10.0.0.207
      DATABASE_PORT: 5432
      DATABASE_NAME: parentflow
      DATABASE_USER: postgres
      DATABASE_PASSWORD: a3ppq
      # Redis on 10.0.0.240
      REDIS_HOST: 10.0.0.240
      REDIS_PORT: 6379
      # MongoDB on 10.0.0.240
      MONGODB_URI: mongodb://parentflow_admin:parentflow_mongo_password_2024@10.0.0.240:27017/parentflow_ai_chat?authSource=admin
      # Auth keys
      JWT_SECRET: ${ADMIN_JWT_SECRET}
      SERVICE_AUTH_KEY: ${SERVICE_AUTH_KEY}  # For service-to-service auth
    networks:
      - parentflow-network
    extra_hosts:
      - "host.docker.internal:host-gateway"  # For accessing host services

  admin-ui:
    build: ./parentflow-admin-service/admin-ui
    container_name: parentflow-admin-ui
    ports:
      - "4001:3000"  # Admin UI
    environment:
      REACT_APP_API_URL: http://admin-api:4000
      REACT_APP_MAIN_APP_URL: https://web.parentflowapp.com
    networks:
      - parentflow-network

networks:
  parentflow-network:
    external: true
```

#### Service Communication

```typescript
// Service-to-service authentication
export class AdminServiceClient {
  private readonly serviceKey: string;
  private readonly adminApiUrl: string;

  constructor() {
    this.serviceKey = process.env.SERVICE_AUTH_KEY;
    this.adminApiUrl = process.env.ADMIN_API_URL || 'http://localhost:4000';
  }

  async validateInviteCode(code: string, platform: string): Promise<ValidationResult> {
    const response = await axios.post(
      `${this.adminApiUrl}/api/v1/internal/validate-invite-code`,
      { code, platform },
      {
        headers: {
          'X-Service-Auth': this.serviceKey,
          'X-Service-Name': 'parentflow-web'
        }
      }
    );
    return response.data;
  }

  async getRegistrationConfig(): Promise<RegistrationConfig> {
    // Cache this for 5 minutes
    return this.cache.get('registration-config', async () => {
      const response = await axios.get(
        `${this.adminApiUrl}/api/v1/internal/registration-config`,
        {
          headers: {
            'X-Service-Auth': this.serviceKey,
            'X-Service-Name': 'parentflow-web'
          }
        }
      );
      return response.data;
    }, 300); // 5 minutes TTL
  }
}
```

#### Nginx Configuration

```nginx
# admin.parentflowapp.com
server {
    listen 443 ssl http2;
    server_name admin.parentflowapp.com;

    # SSL configuration
    ssl_certificate /etc/letsencrypt/live/admin.parentflowapp.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/admin.parentflowapp.com/privkey.pem;

    # IP whitelist for admin access (optional)
    allow 10.0.0.0/24;  # Office network
    allow 192.168.1.0/24;  # VPN
    deny all;

    # Admin UI
    location / {
        proxy_pass http://localhost:4001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

    # Admin API
    location /api/ {
        proxy_pass http://localhost:4000;
        proxy_http_version 1.1;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

### Deployment Servers

```
Production Environment:
├── Admin Service
│   ├── Server: 10.0.0.241 (separate from main app)
│   ├── URL: admin.parentflowapp.com
│   ├── Ports: 4000 (API), 4001 (UI)
│   └── Database: Connects to dedicated PostgreSQL server
│
├── Main Applications
│   ├── Web: 10.0.0.240:3030 → web.parentflowapp.com
│   ├── API: 10.0.0.240:3020 → api.parentflowapp.com
│   └── Mobile APIs: Will connect to api.parentflowapp.com
│
├── Database Infrastructure
│   ├── PostgreSQL: 10.0.0.207:5432
│   │   ├── Database: parentflow
│   │   ├── User: postgres
│   │   └── Password: a3ppq
│   │
│   └── Docker on 10.0.0.240
│       ├── Redis: Port 6379
│       ├── MongoDB: Port 27017
│       └── MinIO: Ports 9000/9001
│
└── Nginx Proxy Server (Separate)
    ├── SSL certificates configured
    └── Reverse proxy for all domains
```

---

## 🚀 Implementation Timeline

### Phase 1: Foundation (Week 1-2)

**Week 1: Database & Backend Core**
- [ ] Create database migrations for new tables
- [ ] Implement role enums and guards
- [ ] Create AdminGuard and FamilyRoleGuard
- [ ] Set up admin API module structure
- [ ] Implement audit logging service

**Week 2: User Management**
- [ ] User management endpoints (CRUD)
- [ ] Anonymization logic
- [ ] Data export functionality
- [ ] Subscription management endpoints
- [ ] Unit tests for user management

---

### Phase 2: Admin UI (Week 3-4)

**Week 3: Admin Dashboard Layout**
- [ ] Admin layout component
- [ ] Navigation sidebar
- [ ] User management UI (list, detail, edit)
- [ ] Role management UI
- [ ] Multi-profile UI components

**Week 4: Analytics & Monitoring**
- [ ] Analytics dashboard UI
- [ ] System health monitoring UI
- [ ] Charts and visualizations
- [ ] Real-time metric updates

---

### Phase 3: Configuration (Week 5-6)

**Week 5: LLM & Email Config**
- [ ] LLM configuration UI
- [ ] API key management (encrypted)
- [ ] Connection testing
- [ ] Email settings UI
- [ ] Test email functionality

**Week 6: Content & Subscriptions**
- [ ] Legal pages CMS
- [ ] Markdown editor integration
- [ ] Subscription plan management UI
- [ ] Trial period configuration
- [ ] Discount codes

---

### Phase 4: Security & Testing (Week 7-8)

**Week 7: Security Hardening**
- [ ] 2FA for admin accounts
- [ ] Admin session timeout (15 min)
- [ ] IP whitelisting option
- [ ] Audit log viewer UI
- [ ] Security testing

**Week 8: Final Testing & Documentation**
- [ ] Integration tests for all admin endpoints
- [ ] E2E tests for critical admin flows
- [ ] Performance testing
- [ ] Admin user documentation
- [ ] Developer API documentation

---

## ✅ Acceptance Criteria

### Security
- [ ] Only users with `isAdmin=true` can access admin dashboard
- [ ] All admin actions logged to audit trail
- [ ] API keys encrypted at rest (AES-256)
- [ ] Admin sessions expire after 15 minutes of inactivity
- [ ] 2FA required for admin accounts

### User Management
- [ ] Admin can create/edit/delete users
- [ ] Admin can anonymize user data (GDPR)
- [ ] Admin can export user data in JSON/CSV
- [ ] Admin can change user subscriptions
- [ ] Admin can verify user emails manually

### Role Management
- [ ] Parents have full access to their families
- [ ] Guests can only add activities, no historical data
- [ ] Admins have system-wide access
- [ ] Family roles can be changed per user per family

### Multi-Profile
- [ ] Users can switch between multiple families
- [ ] Users can manage multiple accounts
- [ ] Profile switcher in user menu
- [ ] Default profile saved per user

### Analytics
- [ ] Admin can view user growth metrics
- [ ] Admin can view feature usage stats
- [ ] Admin can view AI/LLM costs and usage
- [ ] Admin can view voice command analytics
- [ ] Real-time metrics with 10s refresh

### System Health
- [ ] Admin can view service status
- [ ] Admin can view API performance metrics
- [ ] Admin can view resource usage
- [ ] Alerts for service degradation

### Configuration
- [ ] Admin can add/edit LLM models
- [ ] Admin can test LLM connections
- [ ] Admin can view estimated AI costs
- [ ] Admin can update email settings
- [ ] Admin can edit legal pages
- [ ] Admin can create subscription plans

---

## 📚 Additional Features (Future Enhancements)

### Advanced Analytics
- [ ] Custom report builder
- [ ] Data export scheduler
- [ ] Cohort analysis
- [ ] Funnel visualization
- [ ] A/B testing dashboard

### Automation
- [ ] Automated user onboarding emails
- [ ] Trial expiration reminders
- [ ] Inactive user re-engagement
- [ ] Subscription renewal reminders

### Advanced Security
- [ ] IP whitelisting for admin access
- [ ] Admin activity anomaly detection
- [ ] Automated threat response
- [ ] SIEM integration

### Support Tools
- [ ] In-app user support chat
- [ ] Impersonate user (for debugging)
- [ ] Feature flag management
- [ ] Rollback deployments

---

## 🔗 Related Documentation

- [RBAC Implementation Guide](./RBAC_IMPLEMENTATION.md) (to be created)
- [Audit Logging Standards](./AUDIT_LOGGING.md) (to be created)
- [Data Anonymization Procedures](./DATA_ANONYMIZATION.md) (to be created)
- [API Gateway Architecture](./API_GATEWAY_ARCHITECTURE.md)

---

**Last Updated**: October 3, 2025  
**Next Review**: After Phase 1 completion  
**Owner**: Backend Team + Admin Team
