151 lines
6.7 KiB
Markdown
151 lines
6.7 KiB
Markdown
ACT AS: Senior Full Stack Architect & DevOps Engineer
|
|
|
|
CONTEXT & GOAL
|
|
|
|
I am architecting and building a robust, self-hosted, SaaS-ready Project Management System deployed on my personal Oracle Cloud Free Tier infrastructure. The target environment is specifically the ARM64 (Ampere) architecture with 4 OCPUs and 24GB RAM.
|
|
|
|
The system must solve the complexity of managing diverse project types (software, language learning, commercial, non-profit) through unlimited hierarchical nesting. Unlike flat project managers, this system treats hierarchy as a first-class citizen. The application must be multi-tenant by design, allowing different organizations or users to operate in complete data isolation within a shared application instance.
|
|
|
|
Your task is to design the end-to-end architecture, define a high-performance database schema, and provide the initial production-grade code scaffolding. You must prioritize resource efficiency (due to the self-hosted nature) and scalability (due to the SaaS goal).
|
|
|
|
INFRASTRUCTURE CONSTRAINTS & ENVIRONMENT
|
|
|
|
Hardware Architecture: Oracle Cloud ARM64 (Ampere A1 Compute).
|
|
|
|
Implication: All Docker images must be built for the linux/arm64 platform. You must ensure base images (e.g., node:alpine, postgres:alpine) are compatible.
|
|
|
|
Orchestration Layer: K3s Cluster managed by Rancher.
|
|
|
|
Implication: The application should be containerized and stateless to allow Kubernetes scaling. Resource limits (CPU/Memory) should be considered in the design.
|
|
|
|
DevOps Ecosystem:
|
|
|
|
VCS: Self-hosted Gitea.
|
|
|
|
CI/CD: Gitea Actions (Runner deployed on K3s).
|
|
|
|
Registry: Gitea Container Registry.
|
|
|
|
Development: Coder (Remote dev environment running in the cluster).
|
|
|
|
Implication: The CI/CD pipeline needs to handle multi-arch builds (likely using QEMU) if the runner architecture differs from the target, or native ARM builds if the runner is on the cluster.
|
|
|
|
TECHNOLOGY STACK SPECIFICATIONS
|
|
|
|
Backend Framework: NestJS (TypeScript).
|
|
|
|
Reasoning: Strict modularity, Dependency Injection, and TypeScript support are required for long-term maintainability.
|
|
|
|
ORM: TypeORM or Prisma (Select the one best suited for ltree raw query handling).
|
|
|
|
Database: PostgreSQL (v14 or higher).
|
|
|
|
Key Feature: Must utilize native extensions for hierarchy and JSON handling.
|
|
|
|
Frontend Framework: React (Vite build tool) + Ant Design (UI Component Library).
|
|
|
|
Visualization Engines:
|
|
|
|
React Flow: For the interactive, node-based Mind Map view.
|
|
|
|
Ant Design Tree: For the high-performance, lazy-loaded sidebar navigation.
|
|
|
|
State Management: Zustand.
|
|
|
|
Requirement: Must handle transient UI state (expanded nodes) separately from server state.
|
|
|
|
CORE REQUIREMENTS & IMPLEMENTATION DETAILS
|
|
|
|
1. Database Architecture (Hybrid Relational/Document)
|
|
|
|
The database must perform performantly even with deep nesting (e.g., 50+ levels deep) and millions of nodes.
|
|
|
|
Unlimited Hierarchy via LTREE:
|
|
|
|
Enable the PostgreSQL ltree extension.
|
|
|
|
Store the project path in a specific ltree column (e.g., TopLevel.SecondLevel.MyProject).
|
|
|
|
Performance Constraint: Do NOT use recursive CTEs (Common Table Expressions) for subtree fetching, as they scale poorly. Use ltree operators (<@, @>) which utilize GIST indices for O(log n) retrieval speed.
|
|
|
|
Flexibility via JSONB:
|
|
|
|
Use a JSONB column named attributes to store polymorphic metadata.
|
|
|
|
Example: A "Software" project stores {"repo_url": "...", "ci_status": "passing"}, while a "Language" project stores {"target_level": "C1", "daily_goal_minutes": 30}.
|
|
|
|
Create a GIN index on this column to allow efficient searching across arbitrary keys (e.g., "Find all projects where repo_url is not null").
|
|
|
|
Multi-Tenancy via RLS:
|
|
|
|
Implement Row Level Security (RLS) natively in PostgreSQL.
|
|
|
|
Every single table must include a tenant_id UUID column.
|
|
|
|
Define database policies that strictly enforce tenant_id = current_setting('app.current_tenant'). This prevents accidental data leaks at the database engine level, acting as a safety net below the application logic.
|
|
|
|
2. Backend Logic (NestJS)
|
|
|
|
Modular Architecture: Organize the codebase into distinct domains: ProjectsModule, AuthModule (handling JWTs), TenantsModule, and WikiModule.
|
|
|
|
Authentication & Context:
|
|
|
|
Use Passport.js with JWT strategy.
|
|
|
|
The JWT payload must contain the tenantId.
|
|
|
|
Global Guard/Interceptor: Implement a mechanism that extracts the tenantId from the request and sets the PostgreSQL session variable (for RLS) or injects it into the ORM scope for every transaction.
|
|
|
|
DTOs & Validation: Use class-validator to strictly validate the dynamic JSONB inputs to prevent arbitrary data injection, even in the "flexible" fields.
|
|
|
|
3. Frontend Experience (React + AntD)
|
|
|
|
Dual-View Synchronization:
|
|
|
|
Sidebar (AntD Tree): Must support "Load on Demand". Do not fetch the entire tree at startup. Fetch children only when a node is expanded.
|
|
|
|
Main View (React Flow): Visualizes the current context. If I click a folder in the Sidebar, the Mind Map should render that folder's direct children as nodes.
|
|
|
|
Sync Strategy: Use Zustand to hold the "Active Project ID". Both components must subscribe to this ID. When the Sidebar selection changes, the Mind Map re-renders. When a Mind Map node is double-clicked (drilled down), the Sidebar must expand to reflect the new depth.
|
|
|
|
i18n Architecture:
|
|
|
|
Configure i18next with HTTP backend to load translation files (TR, EN, AR) lazily.
|
|
|
|
Ensure RTL (Right-to-Left) support is fully functional for the Arabic interface, utilizing Ant Design's native ConfigProvider direction prop.
|
|
|
|
DELIVERABLES REQUESTED
|
|
|
|
Production-Ready Database Schema:
|
|
|
|
Provide the full SQL DDL.
|
|
|
|
Include CREATE EXTENSION commands.
|
|
|
|
Include the specific CREATE INDEX commands for GIST (ltree) and GIN (jsonb) to ensure performance.
|
|
|
|
Include the RLS Policy definitions.
|
|
|
|
Backend Scaffolding (NestJS):
|
|
|
|
Generate the ProjectsService specifically showing a method to "Move a project to a new parent". This involves updating the ltree path of the project and all its descendants. This is a complex operation; show the logic.
|
|
|
|
Show the Guard/Middleware that handles Tenant Isolation.
|
|
|
|
Frontend Component Strategy & State:
|
|
|
|
Provide a code snippet demonstrating the Zustand store structure. It should handle expandedKeys, selectedKey, and projectData cache.
|
|
|
|
Explain how to bridge the gap between AntD's tree data structure and React Flow's node/edge structure.
|
|
|
|
CI/CD Pipeline (Gitea Actions):
|
|
|
|
Create a .gitea/workflows/deploy.yaml.
|
|
|
|
Critical: Configure docker/setup-buildx-action and docker/build-push-action.
|
|
|
|
Explicitly set platforms: linux/amd64,linux/arm64 to ensure the image runs on your Oracle Ampere instance regardless of where the runner is hosted.
|
|
|
|
TONE
|
|
|
|
Be highly technical, precise, and production-oriented. Avoid generic "hello world" advice. Provide code snippets that fit the ARM64/K3s/NestJS ecosystem specifically. Assume the user is an experienced developer who needs architectural guidance, not basic tutorials. |