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,143 @@
|
||||
-- =====================================================================
|
||||
-- CONTENT SCHEMA — Part 2: Project Containers & Projects (Templates)
|
||||
-- =====================================================================
|
||||
|
||||
SET search_path TO content, public;
|
||||
|
||||
-- Tenants can mark projects as private (only their users see them)
|
||||
-- or use the global FlatRender catalog.
|
||||
|
||||
CREATE TYPE resolution_kind AS ENUM ('HD','FullHD','TwoK','FourK');
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- project_containers — the "product" (template pack)
|
||||
-- ---------------------------------------------------------------------
|
||||
CREATE TABLE project_containers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
tenant_id UUID, -- NULL = global
|
||||
-- FK to identity.tenants is enforced via service code (cross-schema FK kept loose)
|
||||
|
||||
slug CITEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
keywords TEXT,
|
||||
news_text TEXT,
|
||||
|
||||
-- Media
|
||||
image TEXT,
|
||||
demo TEXT,
|
||||
full_demo TEXT,
|
||||
mini_demo TEXT,
|
||||
demo_script_tag TEXT,
|
||||
|
||||
-- Modes & classifications
|
||||
is_published BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
is_premium BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
is_mockup BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
primary_mode choose_mode NOT NULL DEFAULT 'FLEXIBLE',
|
||||
|
||||
-- Stats (denormalized for speed)
|
||||
rate_avg NUMERIC(3,2),
|
||||
rate_count INT NOT NULL DEFAULT 0,
|
||||
view_count BIGINT NOT NULL DEFAULT 0,
|
||||
use_count BIGINT NOT NULL DEFAULT 0,
|
||||
|
||||
sort INT NOT NULL DEFAULT 0,
|
||||
sort_date TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX idx_containers_published ON project_containers(is_published, sort_date DESC) WHERE deleted_at IS NULL;
|
||||
CREATE INDEX idx_containers_tenant ON project_containers(tenant_id) WHERE deleted_at IS NULL;
|
||||
CREATE INDEX idx_containers_name_trgm ON project_containers USING gin (name gin_trgm_ops);
|
||||
|
||||
CREATE TRIGGER tg_containers_updated_at
|
||||
BEFORE UPDATE ON project_containers FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at();
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- M2M: container ↔ categories
|
||||
-- ---------------------------------------------------------------------
|
||||
CREATE TABLE container_categories (
|
||||
container_id UUID NOT NULL REFERENCES project_containers(id) ON DELETE CASCADE,
|
||||
category_id UUID NOT NULL REFERENCES categories(id) ON DELETE CASCADE,
|
||||
sort INT NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (container_id, category_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_cc_category ON container_categories(category_id);
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- M2M: container ↔ tags
|
||||
-- ---------------------------------------------------------------------
|
||||
CREATE TABLE container_tags (
|
||||
container_id UUID NOT NULL REFERENCES project_containers(id) ON DELETE CASCADE,
|
||||
tag_id UUID NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (container_id, tag_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_ct_tag ON container_tags(tag_id);
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- projects — one aspect-ratio variant of a container
|
||||
-- ---------------------------------------------------------------------
|
||||
CREATE TABLE projects (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
container_id UUID NOT NULL REFERENCES project_containers(id) ON DELETE CASCADE,
|
||||
project_server_id UUID REFERENCES project_servers(id),
|
||||
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
image TEXT,
|
||||
full_demo TEXT,
|
||||
demo_script_tag TEXT,
|
||||
download_link TEXT,
|
||||
|
||||
-- AEP file storage
|
||||
aep_minio_bucket TEXT,
|
||||
aep_minio_key TEXT,
|
||||
aep_file_url TEXT,
|
||||
aep_file_md5 TEXT, -- for node cache check
|
||||
aep_file_size_bytes BIGINT,
|
||||
aep_uploaded_at TIMESTAMPTZ,
|
||||
folder TEXT, -- legacy path on server
|
||||
|
||||
-- Geometry
|
||||
original_width INT NOT NULL,
|
||||
original_height INT NOT NULL,
|
||||
aspect TEXT, -- '16:9','9:16','1:1','4:5',...
|
||||
|
||||
-- Timing
|
||||
project_duration_sec NUMERIC(8,2) NOT NULL,
|
||||
min_duration_sec NUMERIC(8,2),
|
||||
max_duration_sec NUMERIC(8,2),
|
||||
free_fps INT NOT NULL DEFAULT 30,
|
||||
|
||||
-- Mode
|
||||
choose_mode choose_mode NOT NULL,
|
||||
resolution resolution_kind NOT NULL DEFAULT 'FullHD',
|
||||
vip_factor NUMERIC(4,2) NOT NULL DEFAULT 1.0,
|
||||
render_aep_comp TEXT NOT NULL DEFAULT 'flatrender', -- main comp name
|
||||
|
||||
-- Misc (legacy artifacts to preserve)
|
||||
shared_layer_image TEXT,
|
||||
shared_colors_svg TEXT,
|
||||
shared_color_presets_svg TEXT,
|
||||
|
||||
-- Status
|
||||
is_published 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_projects_container ON projects(container_id) WHERE deleted_at IS NULL;
|
||||
CREATE INDEX idx_projects_published ON projects(is_published) WHERE deleted_at IS NULL;
|
||||
CREATE INDEX idx_projects_aep_md5 ON projects(aep_file_md5) WHERE aep_file_md5 IS NOT NULL;
|
||||
|
||||
CREATE TRIGGER tg_projects_updated_at
|
||||
BEFORE UPDATE ON projects FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at();
|
||||
Reference in New Issue
Block a user