Tích hợp với Shell
Mỗi satellite trong hệ sinh thái VENI-AI là một Hệ thống Tự trị (Self-Contained System - SCS). Để cung cấp một trải nghiệm đồng nhất, các satellite phải tích hợp với Shell trung tâm thông qua Module Federation và quy trình Bắt tay SSO.
🏗️ 1. Khai báo Entry Component
Shell yêu cầu mọi remote app phải export một component có tên là ShellEntry. Component này là gốc (root) của giao diện người dùng (UI) satellite của bạn.
// apps/your-app/ui/src/federation/shell-entry.tsx
import { BrowserRouter } from 'react-router-dom';
import App from '../App';
export default function ShellEntry() {
// Tự động phát hiện nếu đang chạy dưới subpath hoặc root
const basename = window.location.pathname.startsWith('/your-app')
? '/your-app'
: '/';
return (
<BrowserRouter basename={basename}>
<App />
</BrowserRouter>
);
}🧩 2. Cấu hình Module Federation
Trong tệp vite.config.ts, bạn phải sử dụng plugin federation để khai báo điểm truy cập (entry point) và chia sẻ các thư viện quan trọng.
// apps/your-app/ui/vite.config.ts
import federation from "@originjs/vite-plugin-federation";
export default defineConfig({
plugins: [
federation({
name: "your_app",
filename: "remoteEntry.js",
exposes: {
"./ShellEntry": "./src/federation/shell-entry.tsx",
},
shared: {
// QUAN TRỌNG: Các Satellite phải tự đóng gói React của riêng mình.
// Đừng bao giờ đặt 'singleton: true, import: false' cho React
// trừ khi bạn chắc chắn Shell cung cấp nó.
react: {},
"react-dom": {},
"react-router-dom": {},
},
}),
],
build: {
target: "esnext",
minify: false,
cssCodeSplit: false,
},
});🛡️ 3. Quy trình Bắt tay Định danh
Các satellite không có trang đăng nhập riêng. Chúng dựa hoàn toàn vào phiên SSO của Shell.
A. Lắng nghe Broadcast
Shell phát sóng JWT của nó đến tất cả các tab đang mở thông qua một BroadcastChannel.
// apps/your-app/ui/src/federation/token-broadcast.ts
const authChannel = new BroadcastChannel('veni-ai-auth-channel');
authChannel.onmessage = (event) => {
if (event.data?.token) {
// 1. Nhận Shell JWT
const shellToken = event.data.token;
// 2. Kích hoạt đổi token
exchangeToken(shellToken);
}
};B. Đổi Token (Token Exchange)
Giao diện của satellite gửi Shell JWT đến API của chính nó để lấy một token có phạm vi dịch vụ (service-scoped token).
// apps/your-app/ui/src/federation/token-exchange.ts
export async function exchangeToken(shellToken: string) {
const response = await fetch(`${API_BASE}/auth/exchange`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token: shellToken }),
});
if (response.ok) {
const { serviceToken } = await response.json();
localStorage.setItem('your_app_service_jwt', serviceToken);
}
}📡 4. Xác thực ở Backend
API của satellite xác thực Shell JWT gửi đến bằng cách sử dụng Khóa công khai (Public Keys - JWKS) của Shell.
// apps/your-app/api/src/services/auth.service.ts
const JWKS_URL = 'http://shell-api:3000/api/.well-known/jwks.json';
export async function verifyShellToken(token: string) {
// 1. Lấy JWKS từ Shell
// 2. Xác minh chữ ký RS256
// 3. Trích xuất sub (userId) và organizationId
// 4. Cấp JWT mới cho satellite này
}📝 5. Đăng ký (Registration)
Cuối cùng, hãy đăng ký satellite của bạn trong cơ sở dữ liệu của Shell để nó xuất hiện trong thanh khởi chạy (launcher).
veni register your-app \
--ui-url http://localhost:417x \
--api-url http://localhost:301x/apiTiện ích CLI
CLI veni tự động xử lý các cổng (ports) và đăng ký khi bạn sử dụng lệnh veni create app.