feat: V2 microservices stack — backend services, gateway, JWT auth
Add full V2 architecture: identity, content, studio (.NET 10) and file, render, notification, gateway (Go) services with vendored deps, plus DB migrations, event/API contracts, and an init-db script. Wire the Next.js frontend to the gateway: server-side JWT auth routes (login/register/refresh/logout/me), gateway fetch helper, and session/ cookie/jwt helpers under src/lib. Containerize the stack via docker-compose.v2.yml and per-service Dockerfiles. Base images resolve through a Nexus mirror (Docker Hub) and MCR directly; npm/NuGet pull from Nexus groups. Self-host fonts via next/font/local to avoid Google Fonts (geo-blocked). Add CI workflow and ignore .env.v2, *.stackdump, and .NET bin/obj. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
-- =====================================================================
|
||||
-- CONTENT SCHEMA — Part 1: Taxonomy & Assets (categories, tags, fonts, music)
|
||||
-- =====================================================================
|
||||
|
||||
SET search_path TO content, public;
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- categories — hierarchical
|
||||
-- ---------------------------------------------------------------------
|
||||
CREATE TABLE categories (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
parent_id UUID REFERENCES categories(id) ON DELETE SET NULL,
|
||||
|
||||
name TEXT NOT NULL,
|
||||
slug CITEXT NOT NULL UNIQUE,
|
||||
description TEXT,
|
||||
image_url TEXT,
|
||||
icon TEXT,
|
||||
|
||||
-- SEO
|
||||
meta_title TEXT,
|
||||
meta_description TEXT,
|
||||
meta_keywords TEXT,
|
||||
bot_follow BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
|
||||
sort INT NOT NULL DEFAULT 0,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX idx_categories_parent ON categories(parent_id);
|
||||
CREATE INDEX idx_categories_active ON categories(is_active) WHERE deleted_at IS NULL;
|
||||
|
||||
CREATE TRIGGER tg_categories_updated_at
|
||||
BEFORE UPDATE ON categories FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at();
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- container_categories — many-to-many
|
||||
-- ---------------------------------------------------------------------
|
||||
-- Will be created after project_containers table
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- tags
|
||||
-- ---------------------------------------------------------------------
|
||||
CREATE TYPE choose_mode AS ENUM ('FIX','FLEXIBLE','MockUp','MusicVisualizer','VoiceOver');
|
||||
|
||||
CREATE TABLE tags (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
latin_name TEXT,
|
||||
slug CITEXT NOT NULL UNIQUE,
|
||||
applies_to_mode choose_mode,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX idx_tags_active ON tags(is_active) WHERE deleted_at IS NULL;
|
||||
|
||||
CREATE TRIGGER tg_tags_updated_at
|
||||
BEFORE UPDATE ON tags FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at();
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- fonts
|
||||
-- ---------------------------------------------------------------------
|
||||
CREATE TABLE fonts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL, -- display name
|
||||
original_name TEXT, -- as registered in AE
|
||||
system_name TEXT, -- exact OS family name
|
||||
family TEXT,
|
||||
weight INT, -- 100-900
|
||||
style TEXT, -- 'normal' | 'italic'
|
||||
direction TEXT NOT NULL DEFAULT 'LTR', -- LTR/RTL/Auto
|
||||
file_url TEXT, -- .ttf/.otf URL
|
||||
sample_image_url TEXT,
|
||||
is_premium BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
installed_on_nodes BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
sort INT NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX idx_fonts_active ON fonts(is_active) WHERE deleted_at IS NULL;
|
||||
|
||||
CREATE TRIGGER tg_fonts_updated_at
|
||||
BEFORE UPDATE ON fonts FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at();
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- music_tracks
|
||||
-- ---------------------------------------------------------------------
|
||||
CREATE TABLE music_tracks (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
caption TEXT,
|
||||
keywords TEXT,
|
||||
url TEXT NOT NULL,
|
||||
waveform_data JSONB, -- precomputed visualization
|
||||
duration_sec NUMERIC(8,2) NOT NULL,
|
||||
bpm INT,
|
||||
genre TEXT,
|
||||
mood TEXT,
|
||||
is_premium BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
sort INT NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX idx_music_active ON music_tracks(is_active) WHERE deleted_at IS NULL;
|
||||
CREATE INDEX idx_music_genre ON music_tracks(genre);
|
||||
|
||||
CREATE TRIGGER tg_music_updated_at
|
||||
BEFORE UPDATE ON music_tracks FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at();
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- project_servers — render server configs (multi-region)
|
||||
-- ---------------------------------------------------------------------
|
||||
CREATE TABLE project_servers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
region TEXT NOT NULL, -- 'tehran','frankfurt',...
|
||||
ip INET,
|
||||
physical_path_output TEXT,
|
||||
default_project_address TEXT,
|
||||
render_output_location TEXT,
|
||||
pre_need_folder_address TEXT,
|
||||
minio_endpoint TEXT,
|
||||
minio_bucket_templates TEXT,
|
||||
minio_bucket_outputs TEXT,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_project_servers_region ON project_servers(region) WHERE is_active = TRUE;
|
||||
|
||||
CREATE TRIGGER tg_project_servers_updated_at
|
||||
BEFORE UPDATE ON project_servers FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at();
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- admin_files — admin-uploaded resources
|
||||
-- ---------------------------------------------------------------------
|
||||
CREATE TABLE admin_files (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT,
|
||||
url TEXT NOT NULL,
|
||||
thumbnail_url TEXT,
|
||||
file_type TEXT,
|
||||
size_bytes BIGINT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
Reference in New Issue
Block a user