Skip to content

CFS Platform - Monorepo Migration Workflow (Multi-Project + SSO)

Overview

This workflow describes the step-by-step migration of the ZWB generator into a multi-project monorepo architecture featuring centralized authentication (SSO + 2FA) and external service integrations (Nextcloud).


Target Architecture

cfs-platform/                        # Monorepo Root

├── workspaces/                      # Project Workspaces
│   │
│   ├── core/                        # Core Platform (CFS Platform)
│   │   ├── apps/
│   │   │   ├── portal/              # Dashboard + SSO + User Management
│   │   │   ├── zuwendung/           # Donation Confirmations (ZWB)
│   │   │   ├── mailing/             # Bulk Mailing Tool
│   │   │   └── newsletter/          # Newsletter Generator
│   │   └── README.md
│   │
│   ├── project-alpha/               # Future Project 1
│   │   ├── apps/
│   │   │   └── app1/
│   │   └── README.md
│   │
│   ├── project-beta/                # Future Project 2
│   │   ├── apps/
│   │   │   └── app1/
│   │   └── README.md
│   │
│   └── integrations/                # External Integrations
│       ├── nextcloud/               # Nextcloud Integration App
│       └── README.md

├── packages/                        # Shared Code (All Projects)
│   ├── database/                    # Central Database Logic + Models
│   ├── ui-components/               # Shared UI + Style Guide
│   ├── auth/                        # SSO + 2FA/TOTP + User Management
│   ├── utils/                       # Shared Utilities
│   └── integrations/                # Integration Helpers (Nextcloud, etc.)

├── docker/                          # Docker Configuration
│   ├── docker-compose.yml
│   ├── docker-compose.dev.yml
│   ├── docker-compose.prod.yml
│   ├── nginx.conf
│   ├── start.sh
│   └── README.md

├── docs/                            # Documentation
│   ├── architecture.md
│   ├── authentication.md            # SSO + 2FA Documentation
│   ├── user-management.md
│   ├── integrations.md              # Nextcloud & others
│   ├── development.md
│   └── deployment.md

├── .github/                         # GitHub Workflows
│   └── workflows/
│       ├── ci.yml
│       └── deploy.yml

├── package.json                     # Root Package (Workspaces)
├── .gitignore
├── .gitattributes
└── README.md

Architectural Principles

1. Multi-Project Monorepo

  • Multiple project workspaces organized under workspaces/.
  • Each project holds its own workspace apps.
  • Shared logic consolidated in packages/.
  • Independent development per workspace/project.

2. Centralized Authentication (SSO)

  • Single sign-on login across all apps and projects.
  • 2FA via TOTP (Google Authenticator, Authy, etc.).
  • Active sessions tracked in a centralized Redis store.
  • JWT tokens for REST API security.

3. User Management

  • Role-based access control (RBAC - Admin, User, Guest).
  • User profile dashboards.
  • Activity audit logging.
  • Consolidated centralized user database.

4. Portal Dashboard Hub

  • Dashboard linking all active apps and projects.
  • Built-in user management administration.
  • Embedded/Direct Nextcloud integration.
  • Single Sign-On login screen entry point.

5. Nextcloud Integration

  • Embedded iframe views inside the Portal dashboard.
  • SSO bridge token exchange for automatic user sessions.
  • Direct links passing active user session parameters.

Authentication Architecture

┌─────────────────────────────────────────────────────┐
│                    PORTAL (SSO)                     │
│                                                     │
│  ┌─────────────────────────────────────────────┐  │
│  │         Login Screen                        │  │
│  │  ┌──────────────┐  ┌──────────────┐        │  │
│  │  │  Username    │  │  Password    │        │  │
│  │  └──────────────┘  └──────────────┘        │  │
│  │  ┌──────────────┐                          │  │
│  │  │  TOTP Code   │  (2FA)                   │  │
│  │  └──────────────┘                          │  │
│  │          [Login]                            │  │
│  └─────────────────────────────────────────────┘  │
│                       ↓                            │
│  ┌─────────────────────────────────────────────┐  │
│  │         Session Created                     │  │
│  │  - JWT Token generated                      │  │
│  │  - Redis Session cached                     │  │
│  │  - Safe Session cookie configured           │  │
│  └─────────────────────────────────────────────┘  │
│                       ↓                            │
│  ┌─────────────────────────────────────────────┐  │
│  │         Dashboard                           │  │
│  │  ┌─────────┐  ┌─────────┐  ┌─────────┐    │  │
│  │  │Zuwendung│  │ Mailing │  │Nextcloud│    │  │
│  │  └─────────┘  └─────────┘  └─────────┘    │  │
│  └─────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────┘

      ┌──────────────────┼──────────────────┐
      ↓                  ↓                   ↓
┌─────────┐      ┌─────────┐        ┌─────────┐
│Zuwendung│      │ Mailing │        │Nextcloud│
│  App    │      │   App   │        │  (ext.) │
└─────────┘      └─────────┘        └─────────┘
      ↓                  ↓                   ↓
[JWT Verified]   [JWT Verified]     [SSO Bridge]

Database Schema (Extension)

New Tables for Auth & User Management:

sql
-- Users (Central User Table)
CREATE TABLE users (
  id INT PRIMARY KEY AUTO_INCREMENT,
  username VARCHAR(255) UNIQUE NOT NULL,
  email VARCHAR(255) UNIQUE NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  totp_secret VARCHAR(255),              -- 2FA Secret
  totp_enabled BOOLEAN DEFAULT FALSE,
  role ENUM('admin', 'user', 'guest') DEFAULT 'user',
  is_active BOOLEAN DEFAULT TRUE,
  last_login TIMESTAMP,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- User Profiles
CREATE TABLE user_profiles (
  id INT PRIMARY KEY AUTO_INCREMENT,
  user_id INT NOT NULL,
  first_name VARCHAR(255),
  last_name VARCHAR(255),
  phone VARCHAR(50),
  avatar_url VARCHAR(500),
  preferences JSON,                       -- User Custom Preferences
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

-- Permissions
CREATE TABLE permissions (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(255) UNIQUE NOT NULL,
  description TEXT,
  resource VARCHAR(255),                  -- e.g., 'zuwendung', 'mailing'
  action VARCHAR(255)                     -- e.g., 'read', 'write', 'delete'
);

-- Role Permissions (Many-to-Many)
CREATE TABLE role_permissions (
  role ENUM('admin', 'user', 'guest'),
  permission_id INT,
  PRIMARY KEY (role, permission_id),
  FOREIGN KEY (permission_id) REFERENCES permissions(id) ON DELETE CASCADE
);

-- User Sessions
CREATE TABLE user_sessions (
  id VARCHAR(255) PRIMARY KEY,
  user_id INT NOT NULL,
  token VARCHAR(500) NOT NULL,
  ip_address VARCHAR(45),
  user_agent TEXT,
  expires_at TIMESTAMP,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

-- Activity Logs
CREATE TABLE activity_logs (
  id INT PRIMARY KEY AUTO_INCREMENT,
  user_id INT,
  action VARCHAR(255) NOT NULL,
  resource VARCHAR(255),
  details JSON,
  ip_address VARCHAR(45),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
);

-- Nextcloud Integration
CREATE TABLE nextcloud_sessions (
  id INT PRIMARY KEY AUTO_INCREMENT,
  user_id INT NOT NULL,
  nextcloud_user VARCHAR(255),
  session_token VARCHAR(500),
  expires_at TIMESTAMP,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

Migration Phases (Adapted)

Phase 0a: Preparation (Manual)

Tasks:

  1. Back up Production Version:

    bash
    cp -r /path/to/zwb-generator /path/to/zwb-generator-BACKUP
  2. Create Working Copy:

    bash
    cp -r /path/to/zwb-generator /path/to/zwb-generator-migration
  3. Initialize New Monorepo Directory:

    bash
    mkdir cfs-platform
    cd cfs-platform
  4. Prepare Style Guide:

    • Ensure your Style Guide assets are accessible.
    • Note the path to the Style Guide.
  5. Gather Nextcloud Parameters:

    • Nextcloud Base URL
    • Admin credentials for SSO provisioning
    • API Security Tokens

Checklist:

  • [ ] Backup created
  • [ ] Working copy created
  • [ ] Monorepo folder initialized
  • [ ] Style Guide path noted
  • [ ] Nextcloud parameters noted
  • [ ] Antigravity ready

Phase 0b: Git/GitHub Setup

Tasks:

  1. Create GitHub Repository:

    • Navigate to https://github.com/new
    • Repository Name: cfs-platform
    • Description: "Multi-Project Platform with SSO, User Management & Integrations"
    • Visibility: Private (recommended)
    • DO NOT initialize with a README, .gitignore, or License.
    • Click Create.
  2. Initialize Local Git:

    bash
    cd cfs-platform
    git init
    git branch -M main
  3. Add Remote Origin:

    bash
    git remote add origin https://github.com/USERNAME/cfs-platform.git
  4. Verify Git Configuration:

    bash
    git config user.name "Christian Friedrich Schacht"
    git config user.email "your@email.com"

Checklist:

  • [ ] GitHub repository created
  • [ ] Git initialized locally
  • [ ] Remote origin connected
  • [ ] Git configuration set

Phase 1: Initialize Multi-Project Monorepo Structure

Antigravity Prompt #1:

text
Create a multi-project monorepo structure with the following requirements:

STRUCTURE:
- Root directory: cfs-platform/
- Subdirectories: workspaces/, packages/, docker/, docs/, .github/
- Package Manager: npm workspaces
- Supporting multiple isolated project domains under workspaces/

FILES TO CREATE:

1. package.json (Root) with Multi-Workspace configuration:
{
  "name": "cfs-platform",
  "version": "1.0.0",
  "private": true,
  "workspaces": [
    "workspaces/*/apps/*",
    "packages/*"
  ],
  "scripts": {
    "install:all": "npm install",
    "dev:portal": "npm run dev --workspace=@cfs-platform/portal",
    "dev:zuwendung": "npm run dev --workspace=@cfs-platform/zuwendung",
    "dev:mailing": "npm run dev --workspace=@cfs-platform/mailing",
    "build:all": "npm run build --workspaces",
    "test:all": "npm run test --workspaces",
    "lint:all": "npm run lint --workspaces"
  },
  "devDependencies": {
    "eslint": "^8.0.0",
    "prettier": "^3.0.0"
  }
}

2. .gitignore:
# Dependencies
node_modules/
package-lock.json

# Build outputs
dist/
build/
.next/
out/

# Environment
.env
.env.local
.env.*.local

# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# OS
.DS_Store
Thumbs.db

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# Docker
docker/volumes/

# Testing
coverage/
.nyc_output/

# Temporary
tmp/
temp/

# Auth secrets
*.pem
*.key

3. .gitattributes:
* text=auto
*.js text
*.jsx text
*.json text
*.md text
*.yml text
*.yaml text
*.png binary
*.jpg binary
*.pdf binary

4. README.md:
# CFS Platform

Multi-project platform with centralized Single Sign-On (SSO + 2FA), User Management, and external service integrations.

## Architecture

Multi-project monorepo using npm Workspaces:
- **workspaces/**: Sandboxed project groups (core, project-alpha, project-beta, integrations).
- **packages/**: Shared modules (Database, UI, Auth, Utils, Integrations).
- **docker/**: Docker orchestration for dev and prod environments.

## Workspaces

### Core Platform (workspaces/core/)
- **portal**: Centralized landing dashboard, SSO credentials service, user profiles manager, and Nextcloud portal.
- **zuwendung**: Spendenbescheinigung PDF generation engine.
- **mailing**: Bulk-email dispatching pipeline.
- **newsletter**: Dynamic newsletter template editor.

### Future Workspaces
- **project-alpha**: [Description pending]
- **project-beta**: [Description pending]

### Integrations (workspaces/integrations/)
- **nextcloud**: Embedded Nextcloud cloud service workspace app.

## Shared Packages

- **@cfs-platform/database**: Consolidated schema mapping (users, profiles, activity, donations, etc.).
- **@cfs-platform/ui-components**: Core design tokens component library.
- **@cfs-platform/auth**: Complete SSO, 2FA/TOTP generation, JWT security middleware.
- **@cfs-platform/utils**: Reusable validator rules, formatters, and logger class.
- **@cfs-platform/integrations**: Shared external system connectivity helpers.

## Features

### Authentication
- ✅ Single Sign-On (SSO) credentials exchange across workspaces.
- ✅ 2FA OTP codes validation.
- ✅ Safe JWT session signatures.
- ✅ Redis session storage.

### User Management
- ✅ Role-Based Access Control (RBAC - Admin, User, Guest).
- ✅ Live activity logging logs.
- ✅ System user profile editor.

### Integrations
- ✅ Seamless Nextcloud cloud directory embedding.
- ✅ Automated OIDC/SAML token-based login bridge.

## Setup

### Prerequisites
- Node.js 18+
- npm 9+
- Docker & Docker Compose
- Redis instance (active)

### Installation

```bash
# Install packages
npm run install:all

# Launch local stack
cd docker
./start.sh
```

### Development

```bash
# Run portal dev server
npm run dev:portal

# Run donation app dev server
npm run dev:zuwendung

# Compile all workspaces
npm run build:all
```

## Deployment

Refer to [docs/deployment.md](docs/deployment.md)

## License

Proprietary - Christian Friedrich Schacht

5. workspaces/core/README.md:
# Core Platform

Core landing modules including Portal, Donation Generator, Bulk Mailing, and Newsletter.

## Apps

- **portal**: Single Sign-On Hub + Administrative Panel
- **zuwendung**: PDF Donation receipts tool
- **mailing**: Bulk marketing campaigns manager
- **newsletter**: Drag-and-drop newsletter builder

6. workspaces/project-alpha/README.md:
# Project Alpha

[Future project documentation placeholder]

## Apps

- **app1**: [Module details]

7. workspaces/project-beta/README.md:
# Project Beta

[Future project documentation placeholder]

## Apps

- **app1**: [Module details]

8. workspaces/integrations/README.md:
# Integrations

External third-party integration workspaces.

## Services

- **nextcloud**: Reusable Nextcloud connection modules.

9. docs/architecture.md:
# Architecture Documentation

## Multi-Project Monorepo Concept

The CFS Platform project implements a multi-project monorepo directory topology using npm workspaces.

### Workspace Structure

```
workspaces/
├── core/              # Main corporate platform applications
├── project-alpha/     # Sandbox project domain 1
├── project-beta/      # Sandbox project domain 2
└── integrations/      # External ecosystem adapters
```

Every workspace manages its specific apps while pulling global shared assets from the root packages.

### Benefits

- **Isolation**: Clean separation between unrelated projects.
- **Code Reuse**: Single import source for brand standards, auth, and database parameters.
- **Consistency**: Enforced uniform dependencies across projects.
- **Atomic Workflows**: Simultaneous changes across packages and workspaces commit as one.

## SSO Architecture

Single Sign-On implementation workflow across workspaces.

### Authentication Flow

1. User requests access to a protected app page (e.g., `/zuwendung`).
2. App router redirects unauthenticated users to the central Portal Login.
3. User enters standard credentials and verifies via a 2FA TOTP code.
4. Portal SSO signs a secure JWT session token and registers the token inside the Redis session cache.
5. User redirects back to the destination app workspace with JWT headers.
6. Local middleware intercepts and verifies the active token.

### Components

- **@cfs-platform/auth**: Core crypto, TOTP validations, and middleware layers.
- **Redis**: Persistent session database.
- **Portal**: The landing login UI portal.
- **Auth Middleware**: Route-level request guards.

## Database Architecture

Unified MySQL/MariaDB database configuration:

### Table Index

**Auth & User Management:**
- `users`: Core identity index.
- `user_profiles`: Detailed metadata for users.
- `permissions`: Fine-grained actions registry.
- `role_permissions`: Association map matching RBAC categories to privileges.
- `user_sessions`: Active database session tracking.
- `activity_logs`: Standard audit trails.

**Application Data:**
- `customers`: Main customer records table (shared CMS index).
- `donations`: Transaction logs for donation receipts.
- `email_campaigns`: Distribution targets for bulk mailing.
- `newsletters`: Newsletter templates metadata.

**Integrations:**
- `nextcloud_sessions`: Nextcloud single sign-on sessions.

All apps use the `@cfs-platform/database` shared workspace package for database interactions.

## Deployment Strategy

### Local Environment
- Docker Compose dev profiles with hot-reloading active.
- Localized database and Redis instances.

### Production Environment
- Consolidated production Docker Compose profiles.
- Nginx proxying external traffic.
- Let's Encrypt certificates management.
- Redis session management.
- Incrementing backup automation.

10. docs/authentication.md:
# Authentication Documentation

## Single Sign-On (SSO)

Centralized authentication across all active apps and projects.

### Core Stack

- **JWT (JSON Web Tokens)**: Secure stateless authentication packets.
- **TOTP**: Time-Based One-Time Passwords for 2FA.
- **Redis**: High-speed session caching.
- **bcrypt**: High-entropy password hashing.

### User Authentication Flow

1. **User opens target application** (e.g., `/zuwendung`).
2. **Middleware evaluates JWT signature**:
   - Token present & valid → Grant access.
   - Token missing/invalid → Redirect to Central Portal `/login`.
3. **Portal credentials request**:
   - Username/Password submission.
   - TOTP code requirement (if 2FA is active).
4. **Credential Verification**:
   - Check password hash using bcrypt.
   - Verify active TOTP code using speakeasy.
   - Issue signed JWT access packets.
   - Register session inside Redis.
   - Configure user session cookie.
5. **Final redirect back to app workspace**:
   - Pass cookie/headers to the destination app.
   - Access granted.

### JWT Payload Structure

```json
{
  "sub": "user_id_uuid",
  "username": "christian",
  "email": "christian@example.com",
  "role": "admin",
  "permissions": ["zuwendung:read", "zuwendung:write", "mailing:read"],
  "iat": 1234567890,
  "exp": 1234571490
}
```

### 2FA TOTP Provisioning Flow

1. **User requests 2FA activation** inside their profile preferences.
2. **SSO engine creates a cryptographically strong secret**:
   - Generate base32 secret string.
   - Generate unique QR code payload.
3. **Display QR code**:
   - User scans with mobile authenticator apps (Google Authenticator, Authy).
4. **Validation check**:
   - User enters active OTP code to verify connection.
   - Set `totp_enabled = true` on success.
5. **Subsequent logins**:
   - Password entry prompt followed by OTP verify screen.

### Session Management

**Redis key-value structure:**
```
session:{session_id} → {
  user_id: 123,
  username: "christian",
  role: "admin",
  ip: "192.168.1.1",
  user_agent: "Mozilla/5.0...",
  created_at: 1234567890,
  expires_at: 1234571490
}
```

**TTL Configuration:** 24 hours (configurable).

### Logout Procedure

1. User clicks log out button.
2. Session identifier removed from Redis.
3. Session cookies invalidated.
4. Redirect to login.

### Session Refreshing

- Access Token: 15 minutes.
- Refresh Token: 7 days.
- Transparent background refresh requests on expiry.

## REST API Authentication

Security for external services utilizing headers:

```bash
curl -H "Authorization: Bearer <JWT_TOKEN>" \
     https://domain.com/api/zuwendung/donations
```

## Permissions Matrix

### Roles

- **admin**: Unrestricted privileges.
- **user**: Read/write privileges within assigned workspace apps.
- **guest**: Read-only privileges.

### Permission Flags

Standard format: `resource:action`

Common instances:
- `zuwendung:read`
- `zuwendung:write`
- `mailing:read`
- `users:manage`

### Route Level Enforcement

```javascript
import { requirePermission } from '@cfs-platform/auth';

app.get('/donations', requirePermission('zuwendung:read'), (req, res) => {
  // Only users holding the 'zuwendung:read' permission flag are served
});
```

11. docs/user-management.md:
# User Management Documentation

## Overview

Centralized administration tools located in the Portal workspace.

## Key Actions

### User Directory
- Full user index table view.
- Search and query filters.
- Sorting options (name, email, role, last login).
- Integrated pagination.

### User Creation
- Unique username validation.
- Unique email check.
- Standardized password policy enforcement.
- RBAC role assignment.
- Profile metadata registration (first/last name, phone).

### Account Updates
- Change profile settings.
- Upgrade/downgrade user roles.
- Grant explicit individual permissions.
- Reset 2FA configuration keys.
- Trigger password recovery pipelines.

### Account Suspension/Removal
- Disable status flags: instanced sessions are rejected from logging in.
- Purge users from DB entirely.

### Self-Service Settings
- Adjust first and last names.
- Password change interface.
- Turn 2FA on/off.
- Upload custom avatars.
- Configure localization settings (language, UI theme).

### Audit Trail
- Trace admin and user activities.
- Display within the Admin panel.
- Filter by user name, action category, or date range.

## UI Designs

### User Index Panel (Admin View)

```
┌─────────────────────────────────────────────────────┐
│ User Management                          [+ New]    │
├─────────────────────────────────────────────────────┤
│ [Search: ___________] [Filter: All ▼] [Export]     │
├─────────────────────────────────────────────────────┤
│ Username    │ Email          │ Role  │ Active│ ... │
├─────────────────────────────────────────────────────┤
│ christian   │ c@example.com  │ Admin │  ✓    │ ... │
│ user1       │ u1@example.com │ User  │  ✓    │ ... │
│ guest1      │ g1@example.com │ Guest │  ✗    │ ... │
└─────────────────────────────────────────────────────┘
```

### Self-Service Profile Form

```
┌─────────────────────────────────────────────────────┐
│ My Profile                                          │
├─────────────────────────────────────────────────────┤
│ [Avatar Image Area]                                 │
│                                                     │
│ First Name:  [Christian        ]                    │
│ Last Name:   [Schacht          ]                    │
│ Email:       [c@example.com    ]                    │
│ Phone:       [+49...           ]                    │
│                                                     │
│ ┌─────────────────────────────────────────────┐    │
│ │ Security Preferences                        │    │
│ │ Passwords:        [Reset Password]          │    │
│ │ 2FA Settings:     [✓] Enabled    [Configure]│    │
│ └─────────────────────────────────────────────┘    │
│                                                     │
│ [Save Preferences]                                  │
└─────────────────────────────────────────────────────┘
```

## API Endpoint Reference

```
GET    /api/users              # List users
GET    /api/users/:id          # Fetch specific user
POST   /api/users              # Provision new user
PUT    /api/users/:id          # Update user profile
DELETE /api/users/:id          # Remove user
POST   /api/users/:id/disable  # Suspend account
POST   /api/users/:id/enable   # Reactivate account

GET    /api/users/me           # Get current user profile
PUT    /api/users/me           # Update current user details
POST   /api/users/me/password  # Change current user password

GET    /api/users/:id/logs     # Fetch user activity logs
```

12. docs/integrations.md:
# Integrations Documentation

## Nextcloud Integration

### Objective

Expose the Nextcloud document sharing system within the Portal shell under automatic Single Sign-On credentials exchange.

### Implementations Approaches

#### **Approach 1: Embedded Iframe** (Pragmatic & Quick)

```jsx
// Portal Page Workspace App
const NextcloudPage = () => {
  return (
    <AppShell activeModule="nextcloud">
      <iframe
        src="https://nextcloud.yourdomain.com"
        style={{ width: '100%', height: 'calc(100vh - 60px)' }}
        title="Nextcloud Docs"
      />
    </AppShell>
  );
};
```

**Pros:**
- Simple UI injection.
- Zero complex integration backend code required.

**Cons:**
- Lacks single sign-on integration; users must log in to Nextcloud manually inside the iframe.
- Browser security policies (CORS/X-Frame-Options) require Nextcloud server tuning.

#### **Approach 2: SSO Token Bridge** (Robust Enterprise Architecture)

**Authentication flow:**

1. User clicks the "Nextcloud" entry in the Portal.
2. Portal backend initiates a session creation request with Nextcloud using administrative credentials.
3. Nextcloud backend verifies the system token and replies with a secure user session token.
4. Portal redirects the user's iframe viewport to the Nextcloud auth endpoint containing the session token.
5. Nextcloud consumes the token and sets authentication cookies seamlessly.

**Prerequisites:**
- Nextcloud OIDC/SAML application plugin configured.
- Trusted domain settings calibrated.

**Reference Implementation:**

```javascript
// packages/integrations/src/nextcloud.js
import axios from 'axios';

export async function createNextcloudSession(userId, username) {
  const response = await axios.post(
    'https://nextcloud.yourdomain.com/ocs/v2.php/apps/user_oidc/api/v1/session',
    {
      userId: username,
      displayName: username
    },
    {
      headers: {
        'OCS-APIRequest': 'true',
        'Authorization': `Bearer ${process.env.NEXTCLOUD_ADMIN_TOKEN}`
      }
    }
  );

  return response.data.ocs.data.token;
}

// Portal Backend Router handler
app.get('/integrations/nextcloud', async (req, res) => {
  const user = req.user; // JWT session payload

  const token = await createNextcloudSession(user.id, user.username);

  res.redirect(`https://nextcloud.yourdomain.com/login?token=${token}`);
});
```

#### **Approach 3: Standalone Direct Link** (Standard Redirect)

Redirecting users to the external service directly:

```jsx
<a href="https://nextcloud.yourdomain.com" target="_blank" rel="noopener noreferrer">
  Open Nextcloud Shared Files
</a>
```

User performs standard log in under standard procedures.

### Recommendation

- **Initial Stage**: Deliver Iframe view (Approach 1) or Direct Links (Approach 3).
- **Target Stage**: Configure Nextcloud OpenID Connect and utilize Token Exchange (Approach 2).

### Portal Dashboard Setup

```jsx
// Portal Landing Dashboard modules definition
const modules = [
  // ... other applications
  {
    id: "nextcloud",
    name: "Nextcloud",
    icon: "☁️",
    path: "/integrations/nextcloud",
    color: "#0082C9",
    description: "Cloud storage and team sharing workspace."
  }
];
```

## Future Services Pipeline

- **Mattermost**: Corporate communication system.
- **GitLab**: Developer code management.
- **Grafana**: Platform metrics.

13. docs/development.md:
# Development Guide

## Adding a Workspace Application

### Under an Existing Group (e.g., core)

1. Create a fresh project folder: `workspaces/core/apps/new-app/`
2. Configure your package.json with name `@cfs-platform/new-app`.
3. Embed AppShell layouts inside components tree.
4. Register the module within `packages/ui-components/src/config/modules.json`.
5. Configure local Docker Compose service inside `docker/docker-compose.dev.yml`.
6. Inject redirect rules within `docker/nginx.conf`.

### Creating a Fresh Workspace Group (e.g., project-gamma)

1. Initialize workspace directory: `workspaces/project-gamma/`
2. Create standard README.md file.
3. Initialize the apps group directory: `workspaces/project-gamma/apps/`
4. Deploy the application as detailed above.
5. Record the new project path in root level package.json:
   ```json
   "workspaces": [
     "workspaces/*/apps/*",
     "packages/*"
   ]
   ```

## Creating a Shared Workspace Package

1. Initialize packages workspace folder: `packages/new-package/`
2. Configure package.json with name `@cfs-platform/new-package`.
3. Declare exported entry points inside `src/index.js`.
4. Consume shared package across the monorepo: `import { ... } from '@cfs-platform/new-package'`.

## Git Workflows

### Feature Development

```bash
# Checkout new branch
git checkout -b feature/new-capability

# Stage and Commit changes
git add .
git commit -m "feat: implement new capability"

# Push feature branch to origin
git push origin feature/new-capability

# Create Pull Request on GitHub
```

### Commit Standard Guidelines

- `feat:` Delivery of new functional modules.
- `fix:` Maintenance or logic repairs.
- `docs:` Readme/wiki adjustments only.
- `style:` Code formatting alterations (spacing, semicolons).
- `refactor:` Code restructuring without logic alterations.
- `test:` Introducing or updating unit tests.
- `chore:` Adjustments to build scripts or DevOps configurations.

## Testing Suites

```bash
# Run tests across workspaces
npm run test:all

# Run tests targeting specific workspace
npm run test --workspace=@cfs-platform/zuwendung
```

## Code Quality and Formatting

```bash
# Execute standard ESLint audits across workspaces
npm run lint:all
```

14. docs/deployment.md:
# Deployment Guide

## VPS Target Host Configuration

### Prerequisites
- Ubuntu 22.04 LTS installation.
- Docker & Docker Compose CLI packages.
- Domain DNS settings mapping to the host IP.
- Local Redis service.

### Host System Initialization

```bash
# Download Docker Engine packages
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Install Compose CLI tools
sudo apt install docker-compose-plugin

# Setup Redis Server
sudo apt install redis-server
sudo systemctl enable redis-server
sudo systemctl start redis-server

# Grant Docker group permissions
sudo usermod -aG docker $USER
```

## Platform Deployment

### 1. Synchronize Source Code

```bash
# SSH to the VPS
ssh user@your-vps.com

# Clone the codebase
git clone https://github.com/USERNAME/cfs-platform.git
cd cfs-platform
```

### 2. Configure Environment Parameters

```bash
# Duplicate example file
cp .env.example .env
nano .env

# Set required credentials:
DB_ROOT_PASSWORD=highly_secure_root_password
DB_NAME=cfs_platform
DB_USER=cfs_user
DB_PASSWORD=highly_secure_user_password

REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=redis_secure_password

JWT_SECRET=strong_jwt_cryptographic_secret
JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d

NEXTCLOUD_URL=https://nextcloud.yourdomain.com
NEXTCLOUD_ADMIN_TOKEN=nextcloud_api_token
```

### 3. Start Application Stack

```bash
cd docker
docker-compose -f docker-compose.prod.yml up -d
```

### 4. Enable Let's Encrypt HTTPS SSL/TLS

```bash
# Download Certbot packages
sudo apt install certbot python3-certbot-nginx

# Obtain and map certificate to Nginx
sudo certbot --nginx -d yourdomain.com
```

## System Updates

```bash
# Fetch changes
git pull origin main

# Rebuild containers
cd docker
docker-compose -f docker-compose.prod.yml up -d --build
```

## Backup & Recovery

```bash
# Create MySQL database dump
docker exec cfs_database_prod mysqldump -u root -p cfs_platform > backup.sql

# Restore database schema
docker exec -i cfs_database_prod mysql -u root -p cfs_platform < backup.sql

# Backup Redis state
redis-cli SAVE
cp /var/lib/redis/dump.rdb /backup/redis_backup.rdb
```

15. .github/workflows/ci.yml:
name: CI

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main, develop ]

jobs:
  build:
    runs-on: ubuntu-latest

    services:
      redis:
        image: redis:alpine
        ports:
          - 6379:6379

    steps:
    - uses: actions/checkout@v3

    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'

    - name: Install dependencies
      run: npm ci

    - name: Lint
      run: npm run lint:all

    - name: Test
      run: npm run test:all

    - name: Build
      run: npm run build:all

16. .github/workflows/deploy.yml:
name: Deploy to VPS

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Deploy to VPS
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.VPS_HOST }}
        username: ${{ secrets.VPS_USER }}
        key: ${{ secrets.VPS_SSH_KEY }}
        script: |
          cd /var/www/cfs-platform
          git pull origin main
          cd docker
          docker-compose -f docker-compose.prod.yml up -d --build

Instantiate the folder directory layout structure matching the specified details.

Post-Prompt #1 - Git Commit:

bash
# Check status
git status

# Stage files
git add .

# Commit
git commit -m "chore: Initial multi-project monorepo structure with SSO"

# Push
git push -u origin main

Phase 2: Establish Auth Shared Workspace Package (Before ZWB Migration)

Antigravity Prompt #2:

text
Create a shared authentication package supporting SSO, 2FA/TOTP, and administrative controls:

PACKAGE: @cfs-platform/auth
TARGET: packages/auth/

TECH STACK:
- jsonwebtoken (JWT)
- bcrypt (Password-Hashing)
- speakeasy (TOTP)
- qrcode (QR-Code-Generierung)
- express-session
- connect-redis (Session-Store)
- redis

STRUCTURE:
packages/auth/
├── src/
│   ├── jwt.js                # JWT handling
│   ├── totp.js               # 2FA encryption and validation
│   ├── password.js           # Password hash checking
│   ├── session.js            # Redis session tracking
│   ├── middleware.js         # Route security interceptors
│   ├── permissions.js        # RBAC and permissions mappings
│   └── index.js
├── package.json
└── README.md

TASKS:

1. JWT MANAGER SETUP:
Create packages/auth/src/jwt.js:

import jwt from 'jsonwebtoken';

const JWT_SECRET = process.env.JWT_SECRET || 'dev_secret_change_in_production';
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '15m';
const JWT_REFRESH_EXPIRES_IN = process.env.JWT_REFRESH_EXPIRES_IN || '7d';

export function generateToken(user) {
  const payload = {
    sub: user.id,
    username: user.username,
    email: user.email,
    role: user.role,
    permissions: user.permissions || []
  };

  return jwt.sign(payload, JWT_SECRET, { expiresIn: JWT_EXPIRES_IN });
}

export function generateRefreshToken(user) {
  const payload = {
    sub: user.id,
    type: 'refresh'
  };

  return jwt.sign(payload, JWT_SECRET, { expiresIn: JWT_REFRESH_EXPIRES_IN });
}

export function verifyToken(token) {
  try {
    return jwt.verify(token, JWT_SECRET);
  } catch (error) {
    throw new Error('Invalid token');
  }
}

export function decodeToken(token) {
  return jwt.decode(token);
}

2. 2FA TOTP MANAGER SETUP:
Create packages/auth/src/totp.js:

import speakeasy from 'speakeasy';
import QRCode from 'qrcode';

export function generateTOTPSecret(username) {
  const secret = speakeasy.generateSecret({
    name: `CFS Platform (${username})`,
    length: 32
  });

  return {
    secret: secret.base32,
    otpauthUrl: secret.otpauth_url
  };
}

export async function generateQRCode(otpauthUrl) {
  try {
    return await QRCode.toDataURL(otpauthUrl);
  } catch (error) {
    throw new Error('QR Code generation failed');
  }
}

export function verifyTOTP(secret, token) {
  return speakeasy.totp.verify({
    secret: secret,
    encoding: 'base32',
    token: token,
    window: 2  // Allow 60 seconds validation window skew
  });
}

3. CRYPTO HASHING MANAGER SETUP:
Create packages/auth/src/password.js:

import bcrypt from 'bcrypt';

const SALT_ROUNDS = 10;

export async function hashPassword(password) {
  return await bcrypt.hash(password, SALT_ROUNDS);
}

export async function verifyPassword(password, hash) {
  return await bcrypt.compare(password, hash);
}

export function validatePasswordStrength(password) {
  // Enforces 8+ characters containing at least 1 uppercase, 1 lowercase, and 1 numeric character
  const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/;
  return regex.test(password);
}

4. REDIS SESSION ENGINE SETUP:
Create packages/auth/src/session.js:

import session from 'express-session';
import RedisStore from 'connect-redis';
import { createClient } from 'redis';

let redisClient;

export async function initRedis() {
  redisClient = createClient({
    host: process.env.REDIS_HOST || 'localhost',
    port: process.env.REDIS_PORT || 6379,
    password: process.env.REDIS_PASSWORD
  });

  await redisClient.connect();

  return redisClient;
}

export function createSessionMiddleware() {
  return session({
    store: new RedisStore({ client: redisClient }),
    secret: process.env.SESSION_SECRET || 'dev_session_secret',
    resave: false,
    saveUninitialized: false,
    cookie: {
      secure: process.env.NODE_ENV === 'production',
      httpOnly: true,
      maxAge: 24 * 60 * 60 * 1000  // 24 Hours duration
    }
  });
}

export async function saveSession(userId, sessionData) {
  const sessionId = `session:${userId}:${Date.now()}`;
  await redisClient.setEx(sessionId, 86400, JSON.stringify(sessionData));
  return sessionId;
}

export async function getSession(sessionId) {
  const data = await redisClient.get(sessionId);
  return data ? JSON.parse(data) : null;
}

export async function deleteSession(sessionId) {
  await redisClient.del(sessionId);
}

5. ROUTE GUARDS AND MIDDLEWARES:
Create packages/auth/src/middleware.js:

import { verifyToken } from './jwt.js';

export function requireAuth(req, res, next) {
  try {
    const token = req.headers.authorization?.split(' ')[1] || req.cookies?.token;

    if (!token) {
      return res.status(401).json({ error: 'No token provided' });
    }

    const decoded = verifyToken(token);
    req.user = decoded;
    next();
  } catch (error) {
    return res.status(401).json({ error: 'Invalid token' });
  }
}

export function requireRole(role) {
  return (req, res, next) => {
    if (!req.user) {
      return res.status(401).json({ error: 'Not authenticated' });
    }

    if (req.user.role !== role && req.user.role !== 'admin') {
      return res.status(403).json({ error: 'Insufficient permissions' });
    }

    next();
  };
}

export function requirePermission(permission) {
  return (req, res, next) => {
    if (!req.user) {
      return res.status(401).json({ error: 'Not authenticated' });
    }

    if (req.user.role === 'admin') {
      return next();
    }

    if (!req.user.permissions.includes(permission)) {
      return res.status(403).json({ error: `Missing permission: ${permission}` });
    }

    next();
  };
}

6. ACCESS CONTROL POLICIES:
Create packages/auth/src/permissions.js:

export const PERMISSIONS = {
  // Zuwendung
  ZUWENDUNG_READ: 'zuwendung:read',
  ZUWENDUNG_WRITE: 'zuwendung:write',
  ZUWENDUNG_DELETE: 'zuwendung:delete',

  // Mailing
  MAILING_READ: 'mailing:read',
  MAILING_WRITE: 'mailing:write',
  MAILING_SEND: 'mailing:send',

  // Newsletter
  NEWSLETTER_READ: 'newsletter:read',
  NEWSLETTER_WRITE: 'newsletter:write',
  NEWSLETTER_SEND: 'newsletter:send',

  // User Management
  USERS_READ: 'users:read',
  USERS_WRITE: 'users:write',
  USERS_DELETE: 'users:delete',
  USERS_MANAGE: 'users:manage',

  // System
  SYSTEM_SETTINGS: 'system:settings',
  SYSTEM_LOGS: 'system:logs'
};

export const ROLE_PERMISSIONS = {
  admin: Object.values(PERMISSIONS),
  user: [
    PERMISSIONS.ZUWENDUNG_READ,
    PERMISSIONS.ZUWENDUNG_WRITE,
    PERMISSIONS.MAILING_READ,
    PERMISSIONS.MAILING_WRITE,
    PERMISSIONS.NEWSLETTER_READ,
    PERMISSIONS.NEWSLETTER_WRITE
  ],
  guest: [
    PERMISSIONS.ZUWENDUNG_READ,
    PERMISSIONS.MAILING_READ,
    PERMISSIONS.NEWSLETTER_READ
  ]
};

export function getUserPermissions(role) {
  return ROLE_PERMISSIONS[role] || [];
}

export function hasPermission(user, permission) {
  if (user.role === 'admin') return true;
  return user.permissions.includes(permission);
}

7. INDEX BARREL EXPORTS:
Create packages/auth/src/index.js:
export * from './jwt.js';
export * from './totp.js';
export * from './password.js';
export * from './session.js';
export * from './middleware.js';
export * from './permissions.js';

8. PACKAGE.JSON:
{
  "name": "@cfs-platform/auth",
  "version": "1.0.0",
  "main": "src/index.js",
  "type": "module",
  "dependencies": {
    "jsonwebtoken": "^9.0.0",
    "bcrypt": "^5.1.0",
    "speakeasy": "^2.0.0",
    "qrcode": "^1.5.0",
    "express-session": "^1.17.0",
    "connect-redis": "^7.1.0",
    "redis": "^4.6.0"
  }
}

9. README.MD:
Document:
- High level list of auth features.
- Basic JWT generation.
- TOTP 2FA setups.
- Middleware declarations.

Post-Prompt #2 - Git Commit:

bash
git add packages/auth/
git commit -m "feat: Add auth package with SSO, 2FA/TOTP and permissions"
git push origin main

Phase 3: Expand Database Workspace Package (Provision User-Management Schemas)

Antigravity Prompt #3:

text
Expand the `@cfs-platform/database` shared library package to orchestrate Identity and Access Control schemas:

PACKAGE: @cfs-platform/database
TARGET: packages/database/

TASKS:

1. DEFINE USERS MODEL:
Create packages/database/src/models/User.js:

import { DataTypes } from 'sequelize';

export default (sequelize) => {
  const User = sequelize.define('User', {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      autoIncrement: true
    },
    username: {
      type: DataTypes.STRING(255),
      allowNull: false,
      unique: true
    },
    email: {
      type: DataTypes.STRING(255),
      allowNull: false,
      unique: true
    },
    password_hash: {
      type: DataTypes.STRING(255),
      allowNull: false
    },
    totp_secret: {
      type: DataTypes.STRING(255),
      allowNull: true
    },
    totp_enabled: {
      type: DataTypes.BOOLEAN,
      defaultValue: false
    },
    role: {
      type: DataTypes.ENUM('admin', 'user', 'guest'),
      defaultValue: 'user'
    },
    is_active: {
      type: DataTypes.BOOLEAN,
      defaultValue: true
    },
    last_login: {
      type: DataTypes.DATE,
      allowNull: true
    }
  }, {
    tableName: 'users',
    timestamps: true,
    underscored: true
  });

  return User;
};

2. DEFINE USER PROFILES MODEL:
Create packages/database/src/models/UserProfile.js:

import { DataTypes } from 'sequelize';

export default (sequelize) => {
  const UserProfile = sequelize.define('UserProfile', {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      autoIncrement: true
    },
    user_id: {
      type: DataTypes.INTEGER,
      allowNull: false,
      references: {
        model: 'users',
        key: 'id'
      }
    },
    first_name: {
      type: DataTypes.STRING(255),
      allowNull: true
    },
    last_name: {
      type: DataTypes.STRING(255),
      allowNull: true
    },
    phone: {
      type: DataTypes.STRING(50),
      allowNull: true
    },
    avatar_url: {
      type: DataTypes.STRING(500),
      allowNull: true
    },
    preferences: {
      type: DataTypes.JSON,
      allowNull: true,
      defaultValue: {}
    }
  }, {
    tableName: 'user_profiles',
    timestamps: true,
    underscored: true
  });

  return UserProfile;
};

3. DEFINE PERMISSIONS MODEL:
Create packages/database/src/models/Permission.js:

import { DataTypes } from 'sequelize';

export default (sequelize) => {
  const Permission = sequelize.define('Permission', {
    id: {
      type: DataTypes.INTEGER,
      primaryKey: true,
      autoIncrement: true
    },
    name: {
      type: DataTypes.STRING(255),
      allowNull: false,
      unique: true
    },
    description: {
      type: DataTypes.TEXT,
      allowNull: true
    },
    resource: {
      type: DataTypes.STRING(255),
      allowNull: false
    },
    action: {
      type: DataTypes.STRING(255),
      allowNull: false
    }
  }, {
    tableName: 'permissions',
    timestamps: true,
    underscored: true
  });

  return Permission;
};

Released under proprietary license.