mirror of
https://github.com/AeThex-Corporation/AeThex-OS.git
synced 2026-04-18 14:27:20 +00:00
- ModuleManager: Central tracking for installed marketplace modules - DataAnalyzerWidget: Real-time CPU/RAM/Battery/Storage widget (unlocked by Data Analyzer module) - BottomNavBar: Navigation bar for Projects/Chat/Marketplace/Settings - RootShell: Real root command execution utility - TerminalActivity: Full root shell with neofetch, sysinfo, real Linux commands - Terminal Pro module: Adds aliases (ll, la, h), command history - ArcadeActivity + SnakeGame: Pixel Arcade module unlocks retro games - fade_in/fade_out animations for smooth transitions
337 lines
14 KiB
PL/PgSQL
337 lines
14 KiB
PL/PgSQL
-- Migration 003: GameForge Studio Management System
|
|
-- Complete project lifecycle tracking for the GameForge game development studio
|
|
-- Ported from aethex-forge
|
|
|
|
-- ============================================================================
|
|
-- GAMEFORGE PROJECTS
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS gameforge_projects (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name VARCHAR(300) NOT NULL,
|
|
description TEXT,
|
|
status VARCHAR(50) NOT NULL DEFAULT 'planning' CHECK (status IN ('planning', 'in_development', 'qa', 'released', 'hiatus', 'cancelled')),
|
|
lead_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
platform VARCHAR(50) NOT NULL CHECK (platform IN ('Unity', 'Unreal', 'Godot', 'Custom', 'WebGL')),
|
|
genre TEXT[] NOT NULL DEFAULT '{}',
|
|
target_release_date TIMESTAMP WITH TIME ZONE,
|
|
actual_release_date TIMESTAMP WITH TIME ZONE,
|
|
budget NUMERIC(12, 2),
|
|
current_spend NUMERIC(12, 2) NOT NULL DEFAULT 0,
|
|
team_size INTEGER DEFAULT 0,
|
|
repository_url VARCHAR(500),
|
|
documentation_url VARCHAR(500),
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gf_projects_status ON gameforge_projects(status);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_projects_lead ON gameforge_projects(lead_id);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_projects_platform ON gameforge_projects(platform);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_projects_created ON gameforge_projects(created_at DESC);
|
|
|
|
-- ============================================================================
|
|
-- GAMEFORGE TEAM MEMBERS
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS gameforge_team_members (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
role VARCHAR(50) NOT NULL CHECK (role IN ('engineer', 'designer', 'artist', 'producer', 'qa', 'sound_designer', 'writer', 'manager')),
|
|
position VARCHAR(200),
|
|
contract_type VARCHAR(50) NOT NULL DEFAULT 'employee' CHECK (contract_type IN ('employee', 'contractor', 'consultant', 'intern')),
|
|
hourly_rate NUMERIC(8, 2),
|
|
project_ids UUID[] NOT NULL DEFAULT '{}',
|
|
skills TEXT[] DEFAULT '{}',
|
|
bio TEXT,
|
|
joined_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
|
left_date TIMESTAMP WITH TIME ZONE,
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
UNIQUE(user_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gf_team_user ON gameforge_team_members(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_team_role ON gameforge_team_members(role);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_team_active ON gameforge_team_members(is_active);
|
|
|
|
-- ============================================================================
|
|
-- GAMEFORGE BUILDS
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS gameforge_builds (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
project_id UUID NOT NULL REFERENCES gameforge_projects(id) ON DELETE CASCADE,
|
|
version VARCHAR(50) NOT NULL,
|
|
build_type VARCHAR(50) NOT NULL CHECK (build_type IN ('alpha', 'beta', 'release_candidate', 'final')),
|
|
release_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
|
download_url VARCHAR(1000),
|
|
changelog TEXT,
|
|
file_size BIGINT,
|
|
target_platforms TEXT[] NOT NULL DEFAULT '{}',
|
|
download_count INTEGER NOT NULL DEFAULT 0,
|
|
created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
UNIQUE(project_id, version)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gf_builds_project ON gameforge_builds(project_id);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_builds_release ON gameforge_builds(release_date DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_builds_type ON gameforge_builds(build_type);
|
|
|
|
-- ============================================================================
|
|
-- GAMEFORGE SPRINTS
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS gameforge_sprints (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
project_id UUID NOT NULL REFERENCES gameforge_projects(id) ON DELETE CASCADE,
|
|
sprint_number INTEGER NOT NULL,
|
|
title VARCHAR(200) NOT NULL,
|
|
description TEXT,
|
|
phase VARCHAR(50) NOT NULL DEFAULT 'planning' CHECK (phase IN ('planning', 'active', 'completed', 'cancelled')),
|
|
status VARCHAR(50) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'active', 'on_hold', 'completed')),
|
|
goal TEXT,
|
|
start_date TIMESTAMP WITH TIME ZONE,
|
|
end_date TIMESTAMP WITH TIME ZONE,
|
|
planned_velocity INTEGER,
|
|
actual_velocity INTEGER,
|
|
created_by UUID NOT NULL REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
UNIQUE(project_id, sprint_number)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gf_sprints_project ON gameforge_sprints(project_id);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_sprints_phase ON gameforge_sprints(phase);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_sprints_status ON gameforge_sprints(status);
|
|
|
|
-- ============================================================================
|
|
-- GAMEFORGE SPRINT MEMBERS
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS gameforge_sprint_members (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
sprint_id UUID NOT NULL REFERENCES gameforge_sprints(id) ON DELETE CASCADE,
|
|
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
role VARCHAR(50) NOT NULL DEFAULT 'contributor' CHECK (role IN ('lead', 'contributor', 'reviewer')),
|
|
joined_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
UNIQUE(sprint_id, user_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gf_sprint_members_sprint ON gameforge_sprint_members(sprint_id);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_sprint_members_user ON gameforge_sprint_members(user_id);
|
|
|
|
-- ============================================================================
|
|
-- GAMEFORGE TASKS
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS gameforge_tasks (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
sprint_id UUID REFERENCES gameforge_sprints(id) ON DELETE SET NULL,
|
|
project_id UUID NOT NULL REFERENCES gameforge_projects(id) ON DELETE CASCADE,
|
|
title VARCHAR(500) NOT NULL,
|
|
description TEXT,
|
|
status VARCHAR(50) NOT NULL DEFAULT 'todo' CHECK (status IN ('todo', 'in_progress', 'in_review', 'done', 'blocked')),
|
|
priority VARCHAR(50) NOT NULL DEFAULT 'medium' CHECK (priority IN ('low', 'medium', 'high', 'critical')),
|
|
estimated_hours NUMERIC(6, 1),
|
|
actual_hours NUMERIC(6, 1),
|
|
assigned_to UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
created_by UUID NOT NULL REFERENCES auth.users(id) ON DELETE SET NULL,
|
|
due_date TIMESTAMP WITH TIME ZONE,
|
|
completed_at TIMESTAMP WITH TIME ZONE,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gf_tasks_sprint ON gameforge_tasks(sprint_id);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_tasks_project ON gameforge_tasks(project_id);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_tasks_assigned ON gameforge_tasks(assigned_to);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_tasks_status ON gameforge_tasks(status);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_tasks_priority ON gameforge_tasks(priority);
|
|
|
|
-- ============================================================================
|
|
-- GAMEFORGE METRICS
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS gameforge_metrics (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
project_id UUID NOT NULL REFERENCES gameforge_projects(id) ON DELETE CASCADE,
|
|
metric_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
|
metric_type VARCHAR(50) NOT NULL CHECK (metric_type IN ('monthly', 'sprint', 'milestone')),
|
|
velocity INTEGER,
|
|
hours_logged INTEGER,
|
|
team_size_avg INTEGER,
|
|
bugs_found INTEGER DEFAULT 0,
|
|
bugs_fixed INTEGER DEFAULT 0,
|
|
build_count INTEGER DEFAULT 0,
|
|
days_from_planned_to_release INTEGER,
|
|
on_schedule BOOLEAN,
|
|
budget_allocated NUMERIC(12, 2),
|
|
budget_spent NUMERIC(12, 2),
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_gf_metrics_project ON gameforge_metrics(project_id);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_metrics_date ON gameforge_metrics(metric_date DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_gf_metrics_type ON gameforge_metrics(metric_type);
|
|
|
|
-- ============================================================================
|
|
-- ENABLE ROW LEVEL SECURITY
|
|
-- ============================================================================
|
|
|
|
ALTER TABLE gameforge_projects ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE gameforge_team_members ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE gameforge_builds ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE gameforge_sprints ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE gameforge_sprint_members ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE gameforge_tasks ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE gameforge_metrics ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- ============================================================================
|
|
-- RLS POLICIES
|
|
-- ============================================================================
|
|
|
|
-- Projects: Readable by all authenticated users
|
|
CREATE POLICY "gf_projects_select" ON gameforge_projects
|
|
FOR SELECT USING (auth.role() = 'authenticated');
|
|
|
|
CREATE POLICY "gf_projects_insert" ON gameforge_projects
|
|
FOR INSERT WITH CHECK (auth.uid() = lead_id);
|
|
|
|
CREATE POLICY "gf_projects_update" ON gameforge_projects
|
|
FOR UPDATE USING (auth.uid() = lead_id);
|
|
|
|
-- Team Members: Readable by all authenticated users
|
|
CREATE POLICY "gf_team_select" ON gameforge_team_members
|
|
FOR SELECT USING (auth.role() = 'authenticated');
|
|
|
|
CREATE POLICY "gf_team_insert" ON gameforge_team_members
|
|
FOR INSERT WITH CHECK (auth.uid() = user_id);
|
|
|
|
CREATE POLICY "gf_team_update" ON gameforge_team_members
|
|
FOR UPDATE USING (auth.uid() = user_id);
|
|
|
|
-- Builds: Readable by all, writable by project leads
|
|
CREATE POLICY "gf_builds_select" ON gameforge_builds
|
|
FOR SELECT USING (auth.role() = 'authenticated');
|
|
|
|
CREATE POLICY "gf_builds_insert" ON gameforge_builds
|
|
FOR INSERT WITH CHECK (
|
|
EXISTS(SELECT 1 FROM gameforge_projects WHERE id = project_id AND lead_id = auth.uid())
|
|
);
|
|
|
|
CREATE POLICY "gf_builds_update" ON gameforge_builds
|
|
FOR UPDATE USING (
|
|
EXISTS(SELECT 1 FROM gameforge_projects WHERE id = project_id AND lead_id = auth.uid())
|
|
);
|
|
|
|
-- Sprints: Readable by authenticated, writable by project leads
|
|
CREATE POLICY "gf_sprints_select" ON gameforge_sprints
|
|
FOR SELECT USING (auth.role() = 'authenticated');
|
|
|
|
CREATE POLICY "gf_sprints_insert" ON gameforge_sprints
|
|
FOR INSERT WITH CHECK (
|
|
EXISTS(SELECT 1 FROM gameforge_projects WHERE id = project_id AND lead_id = auth.uid())
|
|
);
|
|
|
|
CREATE POLICY "gf_sprints_update" ON gameforge_sprints
|
|
FOR UPDATE USING (
|
|
EXISTS(SELECT 1 FROM gameforge_projects WHERE id = project_id AND lead_id = auth.uid())
|
|
);
|
|
|
|
-- Sprint Members
|
|
CREATE POLICY "gf_sprint_members_select" ON gameforge_sprint_members
|
|
FOR SELECT USING (auth.role() = 'authenticated');
|
|
|
|
CREATE POLICY "gf_sprint_members_insert" ON gameforge_sprint_members
|
|
FOR INSERT WITH CHECK (auth.uid() = user_id);
|
|
|
|
CREATE POLICY "gf_sprint_members_delete" ON gameforge_sprint_members
|
|
FOR DELETE USING (auth.uid() = user_id);
|
|
|
|
-- Tasks: Readable by authenticated, updatable by assigned user or project lead
|
|
CREATE POLICY "gf_tasks_select" ON gameforge_tasks
|
|
FOR SELECT USING (auth.role() = 'authenticated');
|
|
|
|
CREATE POLICY "gf_tasks_insert" ON gameforge_tasks
|
|
FOR INSERT WITH CHECK (auth.uid() = created_by);
|
|
|
|
CREATE POLICY "gf_tasks_update" ON gameforge_tasks
|
|
FOR UPDATE USING (
|
|
auth.uid() = assigned_to
|
|
OR EXISTS(SELECT 1 FROM gameforge_projects WHERE id = project_id AND lead_id = auth.uid())
|
|
);
|
|
|
|
-- Metrics: Readable by all authenticated
|
|
CREATE POLICY "gf_metrics_select" ON gameforge_metrics
|
|
FOR SELECT USING (auth.role() = 'authenticated');
|
|
|
|
CREATE POLICY "gf_metrics_insert" ON gameforge_metrics
|
|
FOR INSERT WITH CHECK (
|
|
EXISTS(SELECT 1 FROM gameforge_projects WHERE id = project_id AND lead_id = auth.uid())
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- TRIGGERS FOR updated_at
|
|
-- ============================================================================
|
|
|
|
CREATE OR REPLACE FUNCTION update_gameforge_updated_at()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DROP TRIGGER IF EXISTS trigger_gf_projects_updated ON gameforge_projects;
|
|
CREATE TRIGGER trigger_gf_projects_updated
|
|
BEFORE UPDATE ON gameforge_projects
|
|
FOR EACH ROW EXECUTE FUNCTION update_gameforge_updated_at();
|
|
|
|
DROP TRIGGER IF EXISTS trigger_gf_team_updated ON gameforge_team_members;
|
|
CREATE TRIGGER trigger_gf_team_updated
|
|
BEFORE UPDATE ON gameforge_team_members
|
|
FOR EACH ROW EXECUTE FUNCTION update_gameforge_updated_at();
|
|
|
|
DROP TRIGGER IF EXISTS trigger_gf_builds_updated ON gameforge_builds;
|
|
CREATE TRIGGER trigger_gf_builds_updated
|
|
BEFORE UPDATE ON gameforge_builds
|
|
FOR EACH ROW EXECUTE FUNCTION update_gameforge_updated_at();
|
|
|
|
DROP TRIGGER IF EXISTS trigger_gf_sprints_updated ON gameforge_sprints;
|
|
CREATE TRIGGER trigger_gf_sprints_updated
|
|
BEFORE UPDATE ON gameforge_sprints
|
|
FOR EACH ROW EXECUTE FUNCTION update_gameforge_updated_at();
|
|
|
|
DROP TRIGGER IF EXISTS trigger_gf_tasks_updated ON gameforge_tasks;
|
|
CREATE TRIGGER trigger_gf_tasks_updated
|
|
BEFORE UPDATE ON gameforge_tasks
|
|
FOR EACH ROW EXECUTE FUNCTION update_gameforge_updated_at();
|
|
|
|
-- ============================================================================
|
|
-- TRIGGER TO UPDATE PROJECT TEAM SIZE
|
|
-- ============================================================================
|
|
|
|
CREATE OR REPLACE FUNCTION update_project_team_size()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
-- Update team_size for all affected projects
|
|
UPDATE gameforge_projects
|
|
SET team_size = (
|
|
SELECT COUNT(*) FROM gameforge_team_members
|
|
WHERE is_active = true AND project_ids @> ARRAY[gameforge_projects.id]
|
|
)
|
|
WHERE id = ANY(COALESCE(NEW.project_ids, OLD.project_ids));
|
|
|
|
RETURN NULL;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DROP TRIGGER IF EXISTS trigger_update_team_size ON gameforge_team_members;
|
|
CREATE TRIGGER trigger_update_team_size
|
|
AFTER INSERT OR UPDATE OR DELETE ON gameforge_team_members
|
|
FOR EACH ROW EXECUTE FUNCTION update_project_team_size();
|