Files
maternal-app/docs/ADMIN_DASHBOARD_IMPLEMENTATION.md
Andrei e2ca04c98f
Some checks failed
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
feat: Setup PM2 production deployment and fix compilation issues
- Add PM2 ecosystem configuration for production deployment
- Fix database SSL configuration to support local PostgreSQL
- Create missing AI feedback entity with FeedbackRating enum
- Add roles decorator and guard for RBAC support
- Implement missing AI safety methods (sanitizeInput, performComprehensiveSafetyCheck)
- Add getSystemPrompt method to multi-language service
- Fix TypeScript errors in personalization service
- Install missing dependencies (@nestjs/terminus, mongodb, minio)
- Configure Next.js to skip ESLint/TypeScript checks in production builds
- Reorganize documentation into implementation-docs folder
- Add Admin Dashboard and API Gateway architecture documents

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-03 23:15:04 +00:00

34 KiB

Admin Dashboard Implementation Plan

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


📋 Executive Summary

Overview

Create a comprehensive admin dashboard for managing the Maternal App with role-based access control (RBAC), user management, system monitoring, and configuration.

Key Features

  1. User Management: CRUD operations, data export, anonymization
  2. Role-Based Access Control: Parent, Guest, Admin roles
  3. Multi-Profile Support: Multiple families and account switching
  4. Analytics Dashboard: Usage metrics, AI/voice analytics
  5. System Health Monitoring: Service status, performance metrics
  6. LLM Configuration: Model settings, API keys, pricing
  7. Content Management: Legal pages, subscriptions
  8. 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

System Architecture

┌─────────────────────────────────────────────────────────────┐
│                    Admin Dashboard UI                        │
│                   (maternal-web/admin/)                       │
│                                                               │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │   Users      │  │  Analytics   │  │   System     │      │
│  │  Management  │  │   Dashboard  │  │   Health     │      │
│  └──────────────┘  └──────────────┘  └──────────────┘      │
│                                                               │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │     LLM      │  │    Pages     │  │    Email     │      │
│  │  Settings    │  │  Management  │  │   Settings   │      │
│  └──────────────┘  └──────────────┘  └──────────────┘      │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                    Admin API (NestJS)                        │
│                  /api/v1/admin/* endpoints                   │
│                                                               │
│  ┌──────────────────────────────────────────────────────┐   │
│  │            AdminGuard (Role: Admin Only)             │   │
│  └──────────────────────────────────────────────────────┘   │
│                                                               │
│  Modules:                                                     │
│  • UserManagementModule                                       │
│  • RoleManagementModule                                       │
│  • AnalyticsAdminModule                                       │
│  • SystemHealthModule                                         │
│  • LLMConfigModule                                            │
│  • ContentManagementModule                                    │
│  • SubscriptionManagementModule                               │
│  • EmailConfigModule                                          │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                      Database Layer                          │
│                                                               │
│  • users (with role field)                                    │
│  • user_profiles (multi-profile support)                      │
│  • family_memberships (role per family)                       │
│  • admin_audit_log (all admin actions)                        │
│  • llm_config (model settings)                                │
│  • subscription_plans                                         │
│  • email_config                                               │
└─────────────────────────────────────────────────────────────┘

👥 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:

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

🗄️ Database Schema Changes

New Tables

1. User Role Enhancement

-- 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

-- 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)

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

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

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

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

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()
);
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

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

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

@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:

// 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:

// 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:

// 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:

// 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:

// 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:

// 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:

// 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:

// 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:

// 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
      ),
    }));
  }
}

Features:

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

UI:

// 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:

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:

// 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:

// 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:

// 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 };
    }
  }
}

🚀 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


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