Portal
Project, tài liệu, board, planning, execution và delivery.
localhost:4200Dựng local hoặc POC, cấu hình Keycloak cho Portal và Console, chuẩn bị ENV và triển khai đúng domain. Bắt đầu từ một bản đồ hệ thống rõ ràng.
Hiểu trước khi chạy
Một mã nguồn backend NestJS phục vụ hai ứng dụng Angular độc lập. Cùng danh tính Keycloak, khác phạm vi công việc và client đăng nhập.
Project, tài liệu, board, planning, execution và delivery.
localhost:4200Kết nối tài khoản AI, cấp model và theo dõi cấu hình toàn hệ thống.
localhost:4300:3300/api/v1Xác minh token, kiểm quyền và điều phối công việc.
Realm role orkestr-admin mở Console và API quản trị. Owner, PO, BA, engineer và QC được cấp theo membership trong database. System Admin không tự có quyền vào nội dung project.
API, worker và runner là ba tiến trình của cùng backend, dùng cùng database và storage. Worker xử lý sync/planning; runner xử lý execution. Mã repository chạy trong container Docker của runner.
orkestr-guide.aila.vn chỉ phục vụ tài liệu tĩnh, không cần đăng nhập, API hay database. Địa chỉ trong tài liệu là cấu hình đích; kiểm tra thực tế theo checklist triển khai.
Luồng mặc định
Dùng Docker Keycloak orkestr-e2e, PostgreSQL local, Local Git sandbox và AI local-deterministic. Không cần tài khoản provider thật.
Các lệnh bên dưới chạy từ thư mục gốc repository orkestr/. Khối sao chép file dùng PowerShell; trên macOS/Linux thay Copy-Item bằng cp.
Chỉ sao chép khi chưa có backend/.env.local; giữ cấu hình cá nhân đã điền.
npm --prefix backend ci
npm --prefix frontend ci
Copy-Item backend/.env.example backend/.env.localKiểm tra CORS_ORIGINS chứa cả hai origin. Mặc định backend dùng realm local ở bước tiếp theo.
CORS_ORIGINS=http://localhost:4200,http://localhost:4300npm --prefix backend run db:up
npm --prefix frontend run auth:up
npm --prefix backend run migration:runPostgreSQL ở 127.0.0.1:55440; Keycloak ở http://127.0.0.1:18080. Realm và user test được nhập từ frontend/e2e/keycloak/realm-orkestr-e2e.json. Lấy thông tin user từ fixture local; không dùng tài khoản test trên dev/main.
Mở ba terminal riêng. Chờ API build xong rồi khởi động worker và runner.
npm --prefix backend run start:devnpm --prefix backend run start:workernpm --prefix backend run start:runnernpm --prefix frontend run start:portalnpm --prefix frontend run start:consolePortal · localhost:4200 để làm việc theo project; Console · localhost:4300 dành cho user có orkestr-admin. Nếu volume Keycloak cũ chưa có hai client mới, cập nhật realm local theo cấu hình client rồi đăng nhập lại; không xóa volume đang chứa định danh cần giữ.
Mở API health, xác nhận database: up. Trên Portal: tạo project → thêm Local Git sandbox → tạo PRD/Story → Publish → Create Technical Tasks → Analyze Codebase → Approve plan → Execute → Delivery report.
Trên Console: đăng nhập bằng admin, mở tổng quan và cấp provider/model cho project test. Việc cấp model không chạy inference.
| Cổng | Dịch vụ |
|---|---|
4200 / 4300 | Portal / Console; proxy /api về API local. |
3300 | API, health và OpenAPI tại /api/v1. |
55440 | PostgreSQL; bind loopback. |
18080 | Docker Keycloak, realm orkestr-e2e. |
3311 / 4211 | API / web riêng của browser E2E; database test bị reset khi chạy. |
Nếu cổng bị chiếm hoặc nằm trong dải reserved của Windows, chọn cổng trống khác. Ví dụ dưới dùng 15440; biến này chỉ đổi host port của Docker Compose.
$env:ORKESTR_POSTGRES_PORT = '15440'
npm --prefix backend run db:upSửa port trong DATABASE_URL của backend/.env.local hoặc .env.poc thành cùng giá trị trước migration/khởi động. Nếu chạy test, cập nhật TEST_DATABASE_URL tương ứng; không dùng database vận hành làm database test. Không xóa volume để sửa lỗi bind port.
Máy local · danh tính dùng chung
Portal, Console và backend vẫn chạy trên máy bạn; chỉ đăng nhập qua auth-dev.cloudsolution.vn, realm orkestr.
Mở discovery của realm orkestr. Chỉ tiếp tục khi endpoint trả JSON với issuer đúng. Nếu trả 404, kiểm realm đã được tạo và đường dẫn đúng; chưa thể dùng URL này để đăng nhập. Guide không tự tạo realm trên auth-dev.
orkestr; bật Email verified..env.poc ở root, giữ local database và điền issuer/JWKS của auth-dev. Không dùng .env.dev có database remote cho POC.Copy-Item .env.poc.example .env.pocCORS_ORIGINS=http://localhost:4200,http://localhost:4300
OIDC_ISSUER=https://auth-dev.cloudsolution.vn/realms/orkestr
OIDC_AUDIENCE=orkestr-api
OIDC_JWKS_URI=https://auth-dev.cloudsolution.vn/realms/orkestr/protocol/openid-connect/certs
OIDC_ALLOWED_ALGORITHMS=RS256Chạy migration một lần, sau đó chạy từng lệnh start:* trong terminal riêng. Dừng các process local cũ trước để giải phóng cổng và tránh xử lý queue bằng sai ENV.
npm --prefix backend run migration:pocnpm --prefix backend run start:poc
npm --prefix backend run start:worker:poc
npm --prefix backend run start:runner:poc
npm --prefix frontend run start:portal:poc
npm --prefix frontend run start:console:pocOrkestr định danh theo sub trong token. User trùng tên/email ở hai realm không tự kế thừa project. Dùng email đã xác minh để nhận lời mời hoặc tạo project test mới; kiểm quyền admin bằng role trong realm đang đăng nhập.
Đối chiếu trước khi khởi động
ENV backend dùng chung cho API, worker và runner. Angular nhận cấu hình công khai khi build; không tự đọc file ENV backend.
| Môi trường | Portal / Console | API & Keycloak | ENV backend |
|---|---|---|---|
| LocalMặc định | http://localhost:4200http://localhost:4300 | http://127.0.0.1:3300/api/v1Keycloak :18080 · orkestr-e2e | backend/.env.local |
| POCLocal + auth-dev | http://localhost:4200http://localhost:4300 | http://127.0.0.1:3300/api/v1auth-dev.cloudsolution.vn · orkestr | .env.poc |
| DevCấu hình đích | https://orkestr-portal-dev.aila.vnhttps://orkestr-console-dev.aila.vn | https://orkestr-api-dev.aila.vn/api/v1auth-dev.cloudsolution.vn · orkestr | .env.dev |
| MainDomain dự kiến | https://orkestr-portal.aila.vnhttps://orkestr-console.aila.vn | https://orkestr-api.aila.vn/api/v1Keycloak production: cần điền | .env.main |
Domain API dev là cấu hình dự kiến cho mô hình tách ứng dụng; cần DNS, TLS và backend tương ứng. Domain main và Keycloak production phải được chốt trước release.
| Nhóm | Key chính | Cách điền |
|---|---|---|
| Database | DATABASE_URL | URI PostgreSQL của đúng môi trường; URL-encode mật khẩu. Có database và user trước khi chạy migration. |
| HTTP | PORT, CORS_ORIGINS | Cổng API 3300; hai origin frontend ngăn bởi dấu phẩy, không có path hoặc dấu / cuối. |
| OIDC | OIDC_ISSUER, OIDC_JWKS_URI, OIDC_AUDIENCE | Lấy issuer/JWKS từ discovery của realm; audience luôn orkestr-api. |
| Storage | DATA_DIR | Thư mục bền vững, cùng path và quyền truy cập cho cả ba process. |
| Runner | RUNNER_IMAGE, RUNNER_CPUS, RUNNER_MEMORY | Dùng image và giới hạn trong mẫu ENV; host cần Docker. |
| Demo / AI | SANDBOX_ENABLED, MODEL_PROVIDER_DEFAULT | Local/POC có thể dùng sandbox + deterministic. Sandbox bị tắt khi NODE_ENV=production. |
CORS_ORIGINS=https://orkestr-portal-dev.aila.vn,https://orkestr-console-dev.aila.vnTạo .env.dev / .env.main từ mẫu cùng tên có đuôi .example. Các file đã điền không được commit hay đưa vào static hosting. Secret chỉ nằm ở backend hoặc secret store; frontend chỉ nhận URL, realm, client ID và tên môi trường.
--env-file không ghi đè biến đã có trong process cha. Kiểm tra terminal/service manager để biến local không lấn cấu hình dev/main. Các script local đọc backend/.env.local; dùng lệnh có file ENV rõ ràng trong quy trình triển khai.
Cấu hình từng client
Chuẩn bị một realm, hai public client cho trình duyệt và một audience cho API. Tên trường có thể khác nhẹ theo phiên bản Keycloak.
Trong Keycloak Admin Console của auth-dev.cloudsolution.vn, tạo hoặc chọn realm orkestr, bật Enabled. Dùng user có email đã xác minh; có thể tắt self-registration nếu quy trình tổ chức dùng tài khoản được cấp.
Mở OIDC discovery của realm dev. issuer phải đúng chuỗi dưới đây; jwks_uri là nguồn khóa công khai mà backend dùng.
https://auth-dev.cloudsolution.vn/realms/orkestrDocker local dùng realm orkestr-e2e. Main dùng Keycloak production riêng đã được chốt, không trỏ mặc định về auth-dev.
orkestr-apiVào Clients → Create client, chọn OpenID Connect, Client ID orkestr-api. Tắt Client authentication, Standard flow, Direct access grants, Implicit flow và Service accounts nếu có. Client này chỉ đại diện cho audience, không có redirect URI hay client secret dùng trong Orkestr.
Lặp lại Clients → Create client hai lần với ID orkestr-portal và orkestr-console. Cả hai dùng cấu hình chung:
| Thiết lập | Giá trị |
|---|---|
| Client type / protocol | OpenID Connect |
| Client authentication | Off — public client, không tạo secret |
| Standard flow | On — Authorization Code |
| Direct access grants / Implicit / Service accounts | Off |
| Advanced → Proof Key for Code Exchange Code Challenge Method | S256 |
| Default client scopes | basic, profile, email, roles (tên scope theo realm/version) |
| Root URL / Home URL | https://orkestr-portal-dev.aila.vn |
|---|---|
| Valid redirect URIs | https://orkestr-portal-dev.aila.vn/* |
| Valid post logout redirect URIs | https://orkestr-portal-dev.aila.vn/* |
| Web origins | https://orkestr-portal-dev.aila.vn |
Thêm các dòng dưới đây vào client orkestr-portal trên realm dev; giữ nguyên domain dev đã có.
http://localhost:4200/*http://localhost:4200/*http://localhost:4200| Root URL / Home URL | https://orkestr-console-dev.aila.vn |
|---|---|
| Valid redirect URIs | https://orkestr-console-dev.aila.vn/* |
| Valid post logout redirect URIs | https://orkestr-console-dev.aila.vn/* |
| Web origins | https://orkestr-console-dev.aila.vn |
Thêm các dòng dưới đây vào client orkestr-console trên realm dev.
http://localhost:4300/*http://localhost:4300/*http://localhost:4300Lưu từng client. Wildcard /* chỉ ở phần path của đúng origin; không dùng * cho toàn bộ URI hoặc Web origins. localhost và 127.0.0.1 là hai origin khác nhau: mở frontend bằng đúng localhost.
Main tạo lại hai client trong realm production với domain main đã xác nhận. Không mang origin dev/localhost sang production. Local Docker dùng cùng hai client ID, nhưng chỉ các origin local trong realm orkestr-e2e.
Trong từng client, mở Client scopes → [client-id]-dedicated → Add mapper → By configuration → Audience. Nếu giao diện khác, tìm dedicated client scope của client rồi thêm protocol mapper loại Audience.
| Name | orkestr-api audience |
|---|---|
| Included Client Audience | orkestr-api |
| Add to access token | On |
| Add to ID token | Off |
| Add to token introspection | On nếu phiên bản có tùy chọn này |
Access token từ cả Portal và Console phải có aud chứa orkestr-api. Backend không dùng client ID frontend làm audience.
Vào Realm roles → Create role, tạo orkestr-admin. Mở user quản trị → Role mapping → Assign role → chọn realm role này. Giữ client scope roles là default; nếu realm giới hạn role scope mappings, cho phép role xuất hiện trong scope của client cần dùng.
Đăng xuất và đăng nhập lại Console. Access token phải có realm_access.roles chứa orkestr-admin. Backend xác minh JWT trước khi trả quyền tại GET /api/v1/me; kết quả cần có user.systemAdmin: true.
Role trên Keycloak mở quyền quản trị toàn hệ thống. Membership và role từng project vẫn do Orkestr kiểm trong database; không thêm realm role để thay cho lời mời project.
Kiểm token tại máy của bạn: sub có giá trị, iss đúng realm, aud chứa orkestr-api, email_verified đúng, role admin chỉ cấp cho user phù hợp. Không gửi access token lên công cụ web công khai.
Mở Portal, đăng nhập và kiểm API. Mở Console, kiểm user admin và một user không có role. Đăng xuất từng ứng dụng, xác nhận quay về đúng origin và không có lỗi post_logout_redirect_uri.
Tên và ý nghĩa các trường đối chiếu theo Keycloak Server Administration Guide. Cấu hình ứng dụng ở đây dùng hai public client riêng; không dùng client cũ orkestr-web cho hai build mới.
Build · Hosting · DNS
Triển khai Portal, Console và Guide thành ba static site; API chạy trên host backend. Worker và runner không cần domain public.
| Dịch vụ | Hostname đích | Nguồn phục vụ |
|---|---|---|
| Portal dev | orkestr-portal-dev.aila.vn | frontend/dist/portal/browser |
| Console dev | orkestr-console-dev.aila.vn | frontend/dist/console/browser |
| API dev | orkestr-api-dev.aila.vn | Reverse proxy đến API :3300, giữ prefix /api/v1. |
| Guide | orkestr-guide.aila.vn | Thư mục guide/, không có build step. |
Từ repository root, build dev riêng từng ứng dụng. Kiểm API base, Keycloak URL/realm/client ID và URL liên kết qua lại trước khi upload.
npm --prefix frontend run build:portal:dev
npm --prefix frontend run build:console:devnpm --prefix frontend run build:apps build cả hai target. Với main, cần cấu hình production đã điền Keycloak và domain thực; không xuất bản build auth-dev dưới domain production.
index.html cho route ứng dụng: Portal /projects, /p/:slug/*; Console /overview, /ai-connections, /project-access, /access.CORS_ORIGINS của API. Kiểm API base đầy đủ https://orkestr-api-dev.aila.vn/api/v1.guide, không cần lệnh build. Gắn orkestr-guide.aila.vn. Host hỗ trợ _headers sẽ đọc chính sách cache/security đi kèm; host khác cấu hình header tương đương.Chỉ phục vụ file có thật, dùng 404.html cho URL không tồn tại và giữ HTTP 404. Không rewrite mọi đường dẫn về index.html; các mục trong Guide dùng trang thật và fragment như /setup/#keycloak.
index.html — trang tổng quansetup/index.html, runbook/index.html, playbook/index.html — ba phần hướng dẫnstyles.css, script.js, search-index.js — giao diện và tiện ích tìm kiếm/sao chépfavicon.svg, 404.html — biểu tượng và trang không tìm thấy_headers — chính sách HTTP cho host có hỗ trợ định dạng nàyvalidate.mjs là tiện ích kiểm tra source, không bắt buộc upload. Không upload file ENV, database, DATA_DIR hay toàn bộ repository.