diff --git a/.gitignore b/.gitignore index 1c356aa..9933f9e 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,11 @@ uploads/* .github/* .next/* .env.local -.vite/* \ No newline at end of file +.vite/* + +# Developer Documentation +/rules.md +/memory.md +/phases.md +/architecture.md +/Guide.md \ No newline at end of file diff --git a/Guide.md b/Guide.md deleted file mode 100644 index e52188f..0000000 --- a/Guide.md +++ /dev/null @@ -1,186 +0,0 @@ -# Channel Partner Portal & Secure Asset Management - -## Enterprise Architecture & Implementation Guide - -This guide details the complete system architecture, visual design specs, existing code evidence, and future implementation roadmap for the secure, multi-tenant Channel Partner Onboarding Platform. - ---- - -## 📖 Table of Contents - -1. [Project Overview & Vision](#1-project-overview--vision) -2. [Database Schema (Prisma Models)](#2-database-schema-prisma-models) -3. [Completed Implementations & Code Evidence](#3-completed-implementations--code-evidence) -4. [MinIO S3-Compatible Storage Migration Guide](#4-minio-s3-compatible-storage-migration-guide) -5. [Future Development Roadmap & Milestones](#5-future-development-roadmap--milestones) - ---- - -## 1. Project Overview & Vision - -The Channel Partner Portal is a premium SaaS onboarding and secure document hub designed to look like modern workspaces (Notion/Linear) rather than standard tabular dashboards. - -### Core Product Pillars - -* **Secure Document Hub**: Multi-format document rendering engine with sandbox protections. -* **Role-Based Access Control (RBAC)**: Fine-grained permissions defining view-only vs. downloadable scopes. -* **Dynamic Sharing Scopes**: Direct share targeting to specific organizations or filtered to singular organization users. -* **Onboarding legal flow**: Gated portal requiring formal signature and tracking for NDA/MSA documents. - ---- - -## 2. Database Schema (Prisma Models) - -Our active PostgreSQL schema in `/Channel-Backend/prisma/schema.prisma` is designed around multi-tenancy and audit compliance: - -| Model | Purpose | Key Relations | -| :------------------ | :--------------------------------------- | :------------------------------------------------------------------- | -| `Organization` | Tenant container | Has many`User` & `SharedAsset` | -| `User` | Authenticated users (Admin/Partner) | Belongs to`Organization`, Has many `DownloadRequest` | -| `Asset` | Physical/URL resource registry | Belongs to`Folder`, Has many `SharedAsset` & `DownloadRequest` | -| `SharedAsset` | Connects assets to organizations/users | Unique on`[assetId, organizationId, userId]` | -| `DownloadRequest` | Pending/Approved requests for download | Unique on`[assetId, userId]` | -| `LegalDocument` | Repository of NDA/MSA text templates | Versioned, Has many`LegalAcceptance` | -| `LegalAcceptance` | Tracks IP/hashes of accepted legal forms | Connected to`User` and `LegalDocument` | -| `AuditLog` | Immutable event tracker | Linked to actor (`User`) | - ---- - -## 3. Completed Implementations & Code Evidence - -Here is the exact code evidence showing which files and configuration settings run the current production-ready portal features. - -### A. Backend security & CSP Configuration - -We modified **[Channel-Backend/src/app.ts](file:///home/tech4biz/work/channel-partner/Tech4biz-channel/Channel-Backend/src/app.ts#L18-L30)** to support secure document embedding inside frontend iframes without exposing vulnerabilities: - -* **Disabled Frameguard**: Removed default `X-Frame-Options: SAMEORIGIN` block. -* **Custom Content Security Policy**: Added `Content-Security-Policy` with the `frame-ancestors` directive allowlisting `http://localhost:5173` and `http://localhost:5000` to satisfy modern Chrome iframe sandbox checks. -* **TypeScript Safety**: Avoided default fallback blockers using `dangerouslyDisableDefaultSrc` and `useDefaults: false`. - -```typescript -app.use(helmet({ - crossOriginResourcePolicy: { policy: "cross-origin" }, - contentSecurityPolicy: { - useDefaults: false, - directives: { - "default-src": helmet.contentSecurityPolicy.dangerouslyDisableDefaultSrc, - "frame-ancestors": ["'self'", "http://localhost:5173", "http://localhost:5000"], - }, - }, - frameguard: false, -})); -``` - -### B. Expandable Preview Modal & Multi-Engine Document Reader - -We overhauled the modal system in **[Channel-Frontend/src/pages/AssetsPage.tsx](file:///home/tech4biz/work/channel-partner/Tech4biz-channel/Channel-Frontend/src/pages/AssetsPage.tsx#L1250-L1356)** to support multi-format previews: - -* **Expandable Viewport Layout**: Added a Maximize/Minimize toggle button in the modal header. Maximizing updates the classes to `w-[96vw] h-[92vh] max-w-none` to prevent layout clipping and display long documents natively. -* **GitHub Repository Markdown Fetcher**: Added a regex parser (`getGithubRawUrl`) and hook to automatically extract the repository name, fetch the `README.md` raw file in the background, and output the text directly inside a clean, scrollable Inter-font document reader. -* **Office Online Document Preview**: Embedded a Microsoft Office Web Viewer wrapper for PowerPoint, Excel, and Word files, with a clean local-mode notice for developers working on `localhost` endpoints. -* **Secure Image/PDF Viewer**: Uses the standard PDF frame and constrained image container (`max-h-full object-contain`). - -### C. Access Control and Protected Links - -* **Removed Direct Links**: Removed the "Open Native Viewer" button to prevent users from bypassing access controls and downloading documents directly. -* **Protected Website URLs**: Blocked the "Open Link in New Tab" action for URL-based assets. It is now hidden behind the `isDownloadable` or approved download request validation, prompting unapproved users to ask for access first. -* **Download request reset**: Client request states are fully synchronized. When an admin rejects a download request, the frontend allows the user to re-submit a request by resetting the request status back to `PENDING` in the database. - ---- - -## 4. MinIO S3-Compatible Storage Migration Guide - -Currently, files are uploaded to `/uploads` on the backend's local directory. To support scaling, high-performance CDN setups, and enterprise security, we will migrate the static storage engine to **MinIO** (an open-source S3-compatible object storage). - -### A. MinIO Deployment Setup (Docker) - -Add the MinIO service to your local developer containers or run it in the background: - -```bash -docker run -d \ - -p 9000:9000 \ - -p 9001:9001 \ - --name minio-storage \ - -e "MINIO_ROOT_USER=admin" \ - -e "MINIO_ROOT_PASSWORD=SuperSecretPassword123" \ - minio/minio server /data --console-address ":9001" -``` - -Log in to `http://localhost:9001` and create a private bucket named `secure-assets`. - -### B. Backend Node SDK Integration - -1. Install AWS S3 SDK packages: - ```bash - npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner multer-s3 - ``` -2. Create an S3 configuration client (`/src/utils/s3.ts`): - ```typescript - import { S3Client } from "@aws-sdk/client-s3"; - - export const s3Client = new S3Client({ - endpoint: process.env.MINIO_ENDPOINT || "http://localhost:9000", - region: "us-east-1", // MinIO defaults - credentials: { - accessKeyId: process.env.MINIO_ACCESS_KEY || "admin", - secretAccessKey: process.env.MINIO_SECRET_KEY || "SuperSecretPassword123", - }, - forcePathStyle: true, // Crucial for MinIO path style endpoints - }); - ``` - -### C. Securing Pre-Signed Preview URLs - -To prevent unauthorized users from sharing document links, the files inside the MinIO bucket must remain **private**. - -When a user opens the preview modal: - -1. The frontend requests a temporary view link from the backend. -2. The backend generates a **pre-signed URL** that expires in **5 minutes**: - ```typescript - import { GetObjectCommand } from "@aws-sdk/client-s3"; - import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; - import { s3Client } from "./s3"; - - export const generateAssetPreviewUrl = async (fileKey: string): Promise => { - const command = new GetObjectCommand({ - Bucket: "secure-assets", - Key: fileKey, - }); - - // Generates a link that becomes useless after 300 seconds - return await getSignedUrl(s3Client, command, { expiresIn: 300 }); - }; - ``` -3. The frontend renders this temporary link inside the `