Platform V2 Detailed Specifications
๐ฏ User Stories
Student (Primary User)
- As a student, I want to investigate a realistic business scenario so I can practice professional skills
- As a student, I want to schedule meetings with company staff so I can gather information systematically
- As a student, I want to receive email confirmations so the experience feels authentic
- As a student, I want to access multimedia content (audio, video, documents) so I can analyze diverse evidence
- As a student, I want to track my investigation progress so I know what Iโve completed
- As a student, I want to collaborate with teammates so we can share findings and insights
Unit Coordinator (Content Creator)
- As a UC, I want to create custom company scenarios so my students get relevant practice
- As a UC, I want to upload any file type (Word, Excel, PDF, audio, video) so I can provide rich content
- As a UC, I want to schedule events (meetings, incidents, revelations) so the story unfolds realistically
- As a UC, I want to customize company branding and content so each unit has its own experience
- As a UC, I want to see student engagement analytics so I can improve my scenarios
- As a UC, I want simple content editing so I donโt need technical skills
Site Administrator (Platform Manager)
- As an admin, I want to manage multiple institutions so the platform can scale
- As an admin, I want to monitor system performance so the platform stays reliable
- As an admin, I want to create new UC accounts so institutions can self-manage
- As an admin, I want to backup and restore data so content is never lost
๐๏ธ Technical Architecture
Database Schema
-- Core Tables
CREATE TABLE institutions (
id UUID PRIMARY KEY,
VARCHAR(255) NOT NULL,
name domain VARCHAR(255),
settings JSONB,TIMESTAMP DEFAULT NOW()
created_at
);
CREATE TABLE units (
id UUID PRIMARY KEY,
REFERENCES institutions(id),
institution_id UUID VARCHAR(50) NOT NULL, -- ISYS6018
code VARCHAR(255) NOT NULL,
name REFERENCES users(id),
coordinator_id UUID VARCHAR(100),
company_template
settings JSONB,BOOLEAN DEFAULT true
active
);
CREATE TABLE users (
id UUID PRIMARY KEY,
VARCHAR(255) UNIQUE NOT NULL,
email role VARCHAR(50) NOT NULL, -- admin, coordinator, student
-- Array of accessible units
unit_ids UUID[], profile JSONB,
TIMESTAMP DEFAULT NOW()
created_at
);
-- Content Management
CREATE TABLE companies (
id UUID PRIMARY KEY,
REFERENCES units(id),
unit_id UUID VARCHAR(255) NOT NULL,
name VARCHAR(100),
template -- colors, logo, styling
branding JSONB,
backstory TEXT,-- dynamic company state
current_state JSONB, TIMESTAMP DEFAULT NOW()
created_at
);
CREATE TABLE characters (
id UUID PRIMARY KEY,
REFERENCES companies(id),
company_id UUID VARCHAR(255) NOT NULL,
name role VARCHAR(255),
VARCHAR(255),
department
personality JSONB,
schedule JSONB,VARCHAR(50), -- available, in_meeting, out_of_office
status
ai_prompt TEXT,TIMESTAMP DEFAULT NOW()
created_at
);
CREATE TABLE content (
id UUID PRIMARY KEY,
REFERENCES companies(id),
company_id UUID VARCHAR(255) NOT NULL,
title type VARCHAR(50), -- document, policy, email, memo, audio, video
VARCHAR(500),
file_path
markdown_content TEXT,
metadata JSONB,
access_rules JSONB,TIMESTAMP DEFAULT NOW(),
created_at TIMESTAMP DEFAULT NOW()
updated_at
);
-- Simulation Engine
CREATE TABLE scenarios (
id UUID PRIMARY KEY,
REFERENCES companies(id),
company_id UUID VARCHAR(255) NOT NULL,
name
description TEXT,-- array of events with triggers
timeline JSONB, VARCHAR(50), -- draft, active, completed
status TIMESTAMP DEFAULT NOW()
created_at
);
CREATE TABLE events (
id UUID PRIMARY KEY,
REFERENCES scenarios(id),
scenario_id UUID VARCHAR(255) NOT NULL,
name type VARCHAR(100), -- meeting, incident, revelation, deadline
TIMESTAMP,
scheduled_for -- conditions that trigger this event
triggered_by JSONB, -- event details, emails to send, etc.
content JSONB, BOOLEAN DEFAULT false
completed
);
CREATE TABLE student_sessions (
id UUID PRIMARY KEY,
REFERENCES users(id),
student_id UUID REFERENCES companies(id),
company_id UUID TIMESTAMP DEFAULT NOW(),
start_time -- completed events, accessed content
progress JSONB, VARCHAR(50) -- active, paused, completed
status
);
-- Chatbot System
CREATE TABLE meetings (
id UUID PRIMARY KEY,
REFERENCES users(id),
student_id UUID REFERENCES characters(id),
character_id UUID TIMESTAMP,
scheduled_for INTEGER,
duration_minutes VARCHAR(50), -- scheduled, confirmed, cancelled, completed
status VARCHAR(500),
meeting_link
transcript TEXT,TIMESTAMP DEFAULT NOW()
created_at
);
CREATE TABLE character_availability (
id UUID PRIMARY KEY,
REFERENCES characters(id),
character_id UUID INTEGER, -- 0-6 (Sunday-Saturday)
day_of_week TIME,
start_time TIME,
end_time BOOLEAN DEFAULT true
available
);
CREATE TABLE character_exceptions (
id UUID PRIMARY KEY,
REFERENCES characters(id),
character_id UUID date DATE,
VARCHAR(255), -- "Board meeting", "Vacation", "Sick"
reason BOOLEAN DEFAULT false
available );
API Design
// Core API Endpoints
// Authentication
/api/auth/login
POST /api/auth/logout
POST /api/auth/me
GET
// Companies & Scenarios
/api/companies/:unitId
GET /api/companies
POST /api/companies/:id
PUT /api/companies/:id
DELETE
/api/companies/:id/characters
GET /api/companies/:id/characters
POST /api/characters/:id
PUT /api/characters/:id
DELETE
// Content Management
/api/companies/:id/content
GET /api/companies/:id/content
POST /api/content/:id
PUT /api/content/:id
DELETE /api/content/:id/upload
POST
// Simulation Engine
/api/companies/:id/scenarios
GET /api/companies/:id/scenarios
POST /api/scenarios/:id
PUT /api/scenarios/:id/start
POST /api/scenarios/:id/events
POST
// Chatbot & Scheduling
/api/characters/:id/availability
GET /api/characters/:id/schedule
POST /api/meetings/mine
GET /api/meetings/:id
PUT /api/meetings/:id
DELETE
// Analytics
/api/units/:id/analytics
GET /api/students/:id/progress
GET /api/companies/:id/engagement GET
Frontend Components
// UC Dashboard Components
const CompanyBuilder = () => {
// Drag-and-drop scenario creator
// Character relationship mapper
// Event timeline editor
;
}
const ContentManager = () => {
// File upload with type detection
// Markdown editor with preview
// Access rule configuration
;
}
const AnalyticsDashboard = () => {
// Student engagement metrics
// Content access patterns
// Chatbot interaction analysis
;
}
// Student Interface Components
const CompanyPortal = () => {
// Responsive company website
// Navigation based on access rules
// Progress tracking sidebar
;
}
const CharacterDirectory = () => {
// Staff listing with availability
// Meeting scheduling interface
// Character profiles and roles
;
}
const MeetingScheduler = () => {
// Calendar integration
// Time slot selection
// Email confirmation system
;
}
// Chatbot Components
const CharacterChat = () => {
// Real-time messaging
// Context-aware responses
// Meeting booking integration
;
}
const AvailabilityWidget = () => {
// Real-time status display
// Next available time
// Out-of-office messages
; }
๐ฎ Feature Specifications
1. Company Template System
interface CompanyTemplate {
: string;
id: string; // "Tech Startup", "Financial Services"
name: string;
description: string;
industry: {
defaultStructure: Department[];
departments: Role[];
roles: Relationship[];
relationships;
}: ScenarioTemplate[];
scenarios: {
branding: string[];
colorScheme: string;
logoPlaceholder: TypographySettings;
typography;
}
}
interface ScenarioTemplate {
: string;
name: string; // "2 weeks", "1 month"
duration: EventTemplate[];
events: string[];
learningObjectives: string[];
assessmentCriteria
}
interface EventTemplate {
: number;
day: string;
time: 'incident' | 'meeting' | 'revelation' | 'deadline';
type: 'automatic' | 'student_action' | 'manual';
trigger: {
content: string;
title: string;
description?: string[];
documents?: EmailTemplate[];
emails;
} }
2. Dynamic Event System
interface Event {
: string;
id: string;
scenarioId: string;
name: EventType;
type: Date;
scheduledFor: EventCondition[];
conditions: EventAction[];
actions: 'pending' | 'triggered' | 'completed';
status
}
interface EventCondition {
: 'time_passed' | 'student_action' | 'content_accessed';
type: any;
parameters
}
interface EventAction {
: 'send_email' | 'unlock_content' | 'schedule_meeting' | 'character_status_change';
type: any;
parameters
}
// Example Event Configuration
const dataBreachEvent: Event = {
: "Data Breach Discovery",
name: "incident",
type: new Date("2024-03-15T09:00:00"),
scheduledFor: [
conditions
{: "time_passed",
type: { afterEvent: "semester_start", days: 7 }
parameters
},
]: [
actions
{: "send_email",
type: {
parameters: "sophia_martines",
from: "all_staff",
to: "emergency_all_hands",
template: "URGENT: Security Incident Response"
subject
},
}
{: "character_status_change",
type: {
parameters: "sophia_martines",
characterId: "emergency_mode",
status: "24_hours"
duration
},
}
{: "unlock_content",
type: {
parameters: ["incident_report_1", "forensic_logs"],
contentIds: "consultant"
accessLevel
}
}
]; }
3. Chatbot Scheduling System
interface CharacterSchedule {
: string;
characterId: TimeSlot[];
workingHours: string;
timeZone: ScheduleException[];
exceptions: number; // minutes
meetingDuration: number; // minutes between meetings
bufferTime
}
interface TimeSlot {
: number; // 0-6
dayOfWeek: string; // "09:00"
startTime: string; // "17:00"
endTime
}
interface ScheduleException {
: string; // "2024-03-15"
date: string; // "Board meeting", "Conference travel"
reason: 'unavailable' | 'limited_availability' | 'emergency_only';
type?: string; // "Contact my assistant"
alternativeContact
}
interface MeetingRequest {
: string;
studentId: string;
characterId: Date[];
preferredTimes: number;
duration: string;
topic: 'low' | 'medium' | 'high';
urgency
}
// Meeting Scheduler Logic
class MeetingScheduler {
async scheduleMeeting(request: MeetingRequest): Promise<Meeting> {
const character = await this.getCharacter(request.characterId);
const availableSlots = await this.getAvailableSlots(character, request.preferredTimes);
if (availableSlots.length === 0) {
throw new Error("No available time slots");
}
const meeting = await this.createMeeting({
...request,
: availableSlots[0],
scheduledFor: 'scheduled'
status;
})
// Send confirmation email
await this.sendConfirmationEmail(meeting);
// Randomly schedule cancellations (for realism)
if (Math.random() < 0.1) { // 10% chance
await this.scheduleRandomCancellation(meeting);
}
return meeting;
}
async scheduleRandomCancellation(meeting: Meeting): Promise<void> {
const cancellationTime = new Date(meeting.scheduledFor.getTime() - (2 * 60 * 60 * 1000)); // 2 hours before
setTimeout(async () => {
await this.cancelMeeting(meeting.id, "urgent_board_meeting");
await this.sendCancellationEmail(meeting);
, cancellationTime.getTime() - Date.now());
}
} }
4. Email Integration (Brevo)
interface EmailService {
sendMeetingConfirmation(meeting: Meeting): Promise<void>;
sendMeetingCancellation(meeting: Meeting, reason: string): Promise<void>;
sendEventNotification(event: Event, recipients: string[]): Promise<void>;
sendWeeklyDigest(studentId: string, progress: StudentProgress): Promise<void>;
}
class BrevoEmailService implements EmailService {
async sendMeetingConfirmation(meeting: Meeting): Promise<void> {
const character = await this.getCharacter(meeting.characterId);
const student = await this.getStudent(meeting.studentId);
const emailTemplate = {
: student.email,
to: `${character.name} <${character.email}>`,
from: `Meeting Confirmed: ${meeting.topic}`,
subject: 'meeting_confirmation',
template: {
variables: student.name,
studentName: character.name,
characterName: meeting.scheduledFor.toLocaleString(),
meetingTime: meeting.duration,
meetingDuration: meeting.topic,
meetingTopic: meeting.link,
meetingLink: character.role
characterTitle
};
}
await this.brevoClient.sendEmail(emailTemplate);
}
async sendEventNotification(event: Event, recipients: string[]): Promise<void> {
// Send dynamic emails based on event type
// Examples: "Security breach detected", "Audit findings available"
} }
5. Analytics and Progress Tracking
interface StudentProgress {
: string;
studentId: string;
companyId: Date;
startDate: number;
completionPercentage: ContentAccess[];
contentAccessed: Meeting[];
meetingsScheduled: Event[];
eventsTriggered: number; // minutes
timeSpent: SkillAssessment[];
skillsAssessed
}
interface EngagementMetrics {
: number;
totalStudents: number;
averageTimeSpent: ContentPopularity[];
contentPopularity: ChatbotMetrics[];
chatbotInteractions: LearningOutcome[];
learningOutcomes
}
interface LearningOutcome {
: string; // "Communication", "Analysis", "Technical"
skillArea: number;
preAssessment: number;
postAssessment: number;
improvement: number;
confidence
}
class AnalyticsService {
async generateUCDashboard(unitId: string): Promise<UnitAnalytics> {
return {
: await this.getUnitOverview(unitId),
overview: await this.getStudentProgress(unitId),
studentProgress: await this.getContentEngagement(unitId),
contentEngagement: await this.getChatbotMetrics(unitId),
chatbotMetrics: await this.getLearningOutcomes(unitId)
learningOutcomes;
}
}
async trackStudentAction(action: StudentAction): Promise<void> {
// Track every click, content access, meeting booking
// Build rich analytics for improving educational outcomes
} }
๐จ UI/UX Specifications
Design System
// Color Schemes for Different Company Templates
const colorSchemes = {
: {
tech_startup: '#667eea',
primary: '#764ba2',
secondary: '#f093fb',
accent: '#718096'
neutral,
}: {
financial_services: '#2d3748',
primary: '#4a5568',
secondary: '#48bb78',
accent: '#a0aec0'
neutral,
}: {
healthcare: '#3182ce',
primary: '#2c5282',
secondary: '#38b2ac',
accent: '#718096'
neutral
};
}
// Responsive Breakpoints
const breakpoints = {
: '320px',
mobile: '768px',
tablet: '1024px',
desktop: '1440px'
wide;
}
// Typography Scale
const typography = {
: {
headings: { size: '2.5rem', weight: '700', lineHeight: '1.2' },
h1: { size: '2rem', weight: '600', lineHeight: '1.3' },
h2: { size: '1.5rem', weight: '600', lineHeight: '1.4' }
h3,
}: {
body: { size: '1.125rem', weight: '400', lineHeight: '1.6' },
large: { size: '1rem', weight: '400', lineHeight: '1.5' },
medium: { size: '0.875rem', weight: '400', lineHeight: '1.4' }
small
}; }
Key Interface Mockups
// UC Dashboard Layout
const UCDashboardLayout = () => (
<Grid areas={`
"header header header"
"sidebar main analytics"
"sidebar main analytics"
`} columns="250px 1fr 300px">
<Header area="header">
<UnitSelector />
<NotificationBell />
<UserMenu />
</Header>
<Sidebar area="sidebar">
<NavItem icon="๐ข" label="Company Overview" />
<NavItem icon="๐ฅ" label="Characters" />
<NavItem icon="๐" label="Content" />
<NavItem icon="๐
" label="Events" />
<NavItem icon="๐" label="Analytics" />
<NavItem icon="โ๏ธ" label="Settings" />
</Sidebar>
<MainContent area="main">
<TabContainer>
<Tab label="Company Builder" />
<Tab label="Content Manager" />
<Tab label="Event Timeline" />
</TabContainer>
</MainContent>
<AnalyticsPanel area="analytics">
<QuickStats />
<RecentActivity />
<StudentProgress />
</AnalyticsPanel>
</Grid>
;
)
// Student Portal Layout
const StudentPortalLayout = () => (
<Layout>
<CompanyHeader>
<CompanyLogo />
<Navigation />
<ProgressIndicator />
</CompanyHeader>
<MainArea>
<ContentGrid>
<ContentCard type="document" />
<ContentCard type="character" />
<ContentCard type="meeting" />
</ContentGrid>
</MainArea>
<Sidebar>
<UpcomingMeetings />
<RecentDocuments />
<ContactDirectory />
</Sidebar>
</Layout>
; )
๐ฑ Mobile Specifications
Progressive Web App Features
- Offline Access: Cache essential content for reading without internet
- Push Notifications: Meeting reminders, new content alerts
- Home Screen Install: Full app-like experience
- Touch Gestures: Swipe navigation, pull-to-refresh
- Camera Integration: Upload photos of physical documents
Mobile-First Design
/* Mobile-first responsive design */
.content-grid {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
}
@media (min-width: 768px) {
.content-grid {
grid-template-columns: 1fr 1fr;
}
}
@media (min-width: 1024px) {
.content-grid {
grid-template-columns: 1fr 1fr 1fr;
}
}
/* Touch-friendly interactive elements */
.button {
min-height: 44px;
min-width: 44px;
padding: 12px 16px;
}
.meeting-slot {
padding: 16px;
margin: 8px 0;
border-radius: 8px;
font-size: 16px; /* Prevent zoom on iOS */
}
๐ Security & Privacy Specifications
Data Protection
- GDPR Compliance: Right to export, delete, and modify personal data
- Student Privacy: No tracking beyond educational purposes
- Institutional Isolation: Complete data separation between institutions
- Encryption: All data encrypted at rest and in transit
- Access Logging: Audit trail for all data access
๐ Performance Requirements
Technical Targets
- Page Load Time: < 2 seconds on 3G connection
- Server Response: < 200ms for API calls
- Uptime: 99.9% availability
- Concurrent Users: Support 1000+ simultaneous users
- Data Backup: Automated daily backups with point-in-time recovery
Scalability Planning
// Database partitioning strategy
const partitioningStrategy = {
: {
horizontal: 'student_sessions',
table: 'institution_id',
partitionKey: 'Isolate institutional data for compliance'
reasoning,
}: {
vertical: 'content',
table: ['file_data'],
splitColumns: 'Separate metadata from large file content'
reasoning
};
}
// Caching strategy
const cachingLayers = {
: 'Static assets (images, videos, documents)',
cdn: 'Session data, character availability, API responses',
redis: 'Company branding, navigation, user preferences'
browser; }
This specification provides the technical foundation for building Platform V2 while maintaining the educational focus that makes the current system successful.