# 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 (
{/* Global toggle */}

Registration Settings

Currently: {requireInvite ? 'Invite only' : 'Open registration'}
{/* Code generator */}

Generate Invite Codes

{/* Codes list */} `${row.current_uses}/${row.max_uses || 'โˆž'}` }, { key: 'platforms', label: 'Platforms' }, { key: 'expires_at', label: 'Expires' }, { key: 'actions', label: 'Actions' } ]} data={inviteCodes} />
); } ``` ### 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 { // 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 { const requiredRoles = this.reflector.get('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 ( ); } // components/admin/FamilyRoleManager.tsx export function FamilyRoleManager({ userId, families }) { // Show user's role in each family // Allow changing role per family return ( {families.map(family => ( {family.name} ))}
); } ``` --- ### 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 ( {currentProfile.name} {profiles.map(profile => ( switchProfile(profile.id)} isActive={profile.id === currentProfile.id} > {profile.name} {profile.familyName} ยท {profile.role} ))} router.push('/add-profile')}> + Add Profile ); } ``` **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 ( ); } ``` **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 ( <> ); } ``` --- ### 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 (
); } ``` --- ### 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 ( <> ); } ``` --- ### 9. Email Configuration **UI**: ```typescript // app/admin/settings/email/page.tsx export default function EmailSettingsPage() { return (
); } ``` **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 { 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 { // 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