192.168.50.188:25432/guidant_ai_dev(帳號 cmmgr,全程唯讀:pg_dump --schema-only、SELECT、catalog 查詢)+ BE repo scripts/sql/ + jedi-auth 套件源碼。docs/features/FR-065-2608-installer/,但 docs/features/README.md 登記名為 FR-065-2608-onprem-installer,依 FR 編號鐵則採 README 登記名。| 項目 | 數量 | 備註 |
|---|---|---|
| PostgreSQL 版本 | 16.4 | Debian 套件版 |
| Schema | 5 | public(57 表)、compliance(45)、oscal(58)、config(11)、survey(15) |
| Table | 186 | 含 2 張分區母表(public.api_logs、public.system_logs)與其月分區子表 |
| Sequence | 156 | |
| Index | 579 | |
| View | 6 | v_role_routes、v_user_capabilities、v_user_routes、vw_user_job_queue、debug_org_units、v_tenant_parent_debug(後兩支為 debug 用,是否出貨待裁決) |
| Function | 82(去除 extension 後約 40 支自訂) | app_* RLS helper 一族、trg_* trigger function 一族、get_user_task_queue(SP)、maintain_log_partitions、scope_rank、set_tenant_path 等 |
| Trigger | 18 | touch/validate/fill-tenant 類 |
| Event trigger | 1 | trg_auto_grant_cm_app(見 §2) |
| RLS 啟用表 | 29 | policy 共 107 條 |
| Extension | uuid-ossp 1.1、pg_trgm 1.6(+內建 plpgsql) |
init 必裝 |
| pg_dump --schema-only | 31,119 行 | 含 400 行 GRANT、18 行 ALTER DEFAULT PRIVILEGES、107 行 CREATE POLICY |
分區維護:maintain_log_partitions() 負責 api_logs / system_logs 月分區滾動;init 時需建立母表+當月分區+default 分區(DEV 現況有 2026_05~2026_08 各月子表——歷史月份子表不屬基線,init 只需母表+default+當期)。
| 表 | 現況 | init 基線角色 |
|---|---|---|
public.schema_migrations |
138 筆(filename / applied_at / note),首筆 __baseline_pre_2026-05-28__ 是上次基線化的 marker |
基線版位標記主體——init 完成時應把「已收斂進基線的 migration 檔名」全數登記(或登記一筆新 baseline marker),讓後續增量 migration 判斷起點(方案見 §5) |
public.schema_version |
2 筆(1.4.0 / 1.5.0 semver stamp) | init 收尾補一筆基線版號 |
public.alembic_version |
1 筆 f20ca741a9bd |
⚠️ 待裁決:repo 內無 alembic 目錄,此值來源不明(推測是 legacy 或某 jedi 套件早期 migration 殘留)。需查明是否有任何程式在讀它;若無 → 基線不帶此表 |
scripts/sql/ 有 224 支 .sql + manifest.tsv(CM-1086 建,四欄:filename/phase/envs/note)。*、11 筆是環境限定(dev/stg/poc 專屬——如 DEV cleanup、STG cutover 類,不屬產品基線)。schema_migrations 登記 138 筆與 manifest active 段一致(含 __baseline_pre_2026-05-28__ marker 與 2 支無日期前綴的 oscal-v2 檔)。scripts/sql/view/vw_user_job_queue.sql、scripts/sql/store_procedure/sp_get_user_task_queue.sql(view/SP 的 canonical 源,dump 內已含定義)、scripts/sql/seeds/bpmn/ 4 支內建 BPMN(builtin-full-audit / builtin-full-audit-with-review / builtin-internal-check / builtin-self-assessment,對應 flow_templates 內建流程)。用 has_table_privilege / has_sequence_privilege / has_function_privilege 對 cm_app 全量掃描(5 schema、186 表、156 sequence、6 view、全部 function):
「歷史 migration 常漏 GRANT」的坑在 DEV 已被兩層機制補平:
SELECT,INSERT,UPDATE,DELETE、sequences USAGE,SELECT,UPDATE、functions EXECUTE 自動授予 cm_app。之後由 cmmgr 建的新物件天生有權限。trg_auto_grant_cm_app(auto_grant_cm_app_on_new_schema()):CREATE SCHEMA 時自動 GRANT USAGE +補設該 schema 的 default privileges。→ 基線 init 的正確做法不是逐表 GRANT 400 行,而是複製這套機制:建 schema 後先設 default privileges,再建物件;event trigger 一併帶入。逐表 GRANT 僅作為驗收檢查(掃描 SQL 可直接沿用本次盤點語句)。
| Role | 屬性 | 用途 |
|---|---|---|
cmmgr |
LOGIN, SUPERUSER, CREATEDB, CREATEROLE, BYPASSRLS;DB owner | 管理帳號:套 migration、init。RLS 對它無效 |
cm_app |
LOGIN(無任何特權,受 RLS);member of cm_app_group |
應用程式連線帳號(.env DB_USER) |
cm_app_group |
NOLOGIN 群組 | 目前僅 cm_app 一個成員;群組自身未見額外授權(實際授權都直接給 cm_app)——基線可簡化或保留,待裁決(傾向保留以利未來多 app 帳號) |
其他(ammgr/nicsmgr/camunda/audit_manager_mgr) |
同主機他系統/legacy 角色 | 不屬本產品基線,init 不建 |
RLS 運作方式:107 條 policy 全部掛在 public(即對所有非 BYPASSRLS 角色生效),判斷條件不是 DB role 而是 session GUC——app.user_id、app.allowed_tenant_paths、app.is_super_admin 等,由 session_scope() 每次查詢前注入(helper:app_tenant_allowed_for_session() 一族)。因此:
app_* helper functions 原樣建齊(皆已含在 pg_dump 內)。pg_db_role_setting 為空——沒有任何 DB/role 層級的 GUC 預設值,不需搬。分類定義:①產品必備=新客戶空庫必 seed;②環境相依=installer 參數化或安裝後由管理介面設定;③DEV 殘留=不隨產品出貨。業務資料表(projects / ssp / 評鑑 / survey 答題 / job 執行 / log 類)在新庫本來就該是空的,不逐一列出——DEV 裡它們有資料屬開發測試產物,全數不出貨。
| 表 | DEV 行數 | 判斷理由 |
|---|---|---|
public.operations |
8 | 操作類型字典(VIEW/INSERT/…/VERIFY),程式 enum 對應 |
public.system_menus |
73 | 16 組下拉選單字典(ANS_TYPE/DEVICE_TYPE/STORAGE_TYPE/TASK_TYPE…),UI 依賴 |
public.ui_routes |
53 | 前端選單樹(真選單來源),有 unique(name) 約束 |
public.capabilities |
130 | 權限能力字典(is_platform 24/一般 106),FR-048 授權體系核心 |
public.route_capabilities |
136 | 路由↔︎capability 綁定 |
public.tenants |
只取 id=1 | root tenant(Guidant.AI,path /1/)——B-2 模型:系統級資源掛 root,「tenant_id NULL=壞資料」。各環境 root 固定 id=1 是硬約定(migration 直接寫字面值 1),init 必須保證 |
public.org_units |
只取 id=1 | root org unit(同上,id=1 硬約定) |
public.roles + role_capabilities |
只取 root 的 Administrator(DEV id=2,掛 130 條 capability) |
平台管理員角色。其餘 10 個 role 皆 tenant-scoped(DEV/測試租戶的),不出貨 |
public.users + user_tenants/user_org_units/user_roles |
只取 1 個超管帳號 | 初始 admin(見 §4);密碼不出廠寫死,安裝時產生 |
public.system_configs 之 RUNTIME_CONFIG 群 |
7 筆(tenant 1) | 登入/密碼/JWT 運行參數(CHANGE_PASSWORD_THRESHOLD_DAYS=90、JWT_EXPIRES、LOGIN 鎖定、MFA_REQUIRED),FR-063.1g 已有 seed migration 2026-08-14-fr063-1g-runtime-config-seed.sql 可直接復用 |
public.system_configs 之 WEB_IDEL_CONFIG |
1 筆 | 前端閒置逾時預設值 |
config.detection_tools |
8 | 檢測工具定義(openvas/nessus/sonarqube/openscap/zap/inspec(cinc)/nmap/gcb),FR-056~058 一整串 seed migration 的收斂結果 |
config.detection_tool_param_schemas |
14 | 各工具參數 schema |
compliance.flow_templates |
只取 tenant 1 的 4 筆 | 內建稽核流程範本(對應 scripts/sql/seeds/bpmn/ 4 支 builtin BPMN);tenant 102 的 9 筆是 DEV 自建測試 |
public.schema_migrations / schema_version |
— | init 收尾 stamp(§1.2、§5) |
| 表 | DEV 行數 | 說明 |
|---|---|---|
public.system_configs 之 SMTP |
1 | 寄信主機——安裝時填或裝完後台設定;出廠建議帶 disabled 空殼 |
public.system_configs 之 STORAGE_CONFIG |
3(tenant 1/102/131 各一) | MinIO/儲存後端座標——只出貨 root(tenant 1)一筆且值參數化(bucket/endpoint 隨客戶環境) |
public.system_configs 之 THIRD_PARTY_LOGIN(LDAP) |
2 | 客戶自家 AD/LDAP——不出廠帶值,後台設定 |
config.tenant_licenses / tenant_license_events / public.license_clock_watermark |
25/29/1 | FR-062 license 導入後 runtime 自建——init 不 seed,首次匯入 license 時產生(watermark 亦 runtime 初始化) |
| 初始 admin 密碼 | — | 安裝時隨機產生或安裝者輸入(§4/§5) |
survey.question_answers_dedup_backup_20260428、config.detection_tool_profiles_deprecated_20260803、public.system_logs_old——基線 schema 不帶這三張(連結構都不帶)。public.system_configs 之 NOTIFY_CONFIG(tenant 102 的 Discord/Telegram webhook,內含真實 secret)——不出貨。| # | 項目 | 拿不準的點 |
|---|---|---|
| D1 | CMMC 框架 catalog 整族(oscal.frameworks 1 / framework_versions 3 / catalogs 79 / catalog_groups 296 / catalog_controls 980 / catalog_control_parts 5651 / catalog_control_params,加 oscal.metadata/profiles/profile_imports 中屬框架的部分) |
是產品資產沒錯,但 DEV 的 79 個 catalog 混雜「內建 CMMC」與「開發測試匯入的」,無法從 schema 判斷哪些屬出貨集。且出貨形式有兩路:(a) seed dump 直灌;(b) 出廠帶 OSCAL JSON 檔、首次啟動走既有匯入流程(見 §5 方案 C 註)。需要 user 指認出貨框架清單 |
| D2 | 內建 workflow_templates(tenant NULL、provider=Billows-Official 的控制項任務範本+snapshot 的凍結快照,共 191 筆;另 tenant 1 有 59 筆) |
provider=Billows-Official 看起來是內建 canonical,但 snapshot 類是專案運行產物;且它們與 D1 的框架綁定。需一併裁決出貨範圍 |
| D3 | 樣板 SSP/MF defaults 家族(compliance.module_frames tenant 1/158 各 1 筆、oscal.system_security_plans 中 template 性質者;FR-036 已把 defaults 遷進 template SSP) |
新客戶初始該有哪些「內建模組框架+樣板 SSP」?DEV 現況分不出「產品內建」vs「開發試作」 |
| D4 | 檢測 Profile 庫(config.detection_profiles tenant 1 的 10 筆+detection_profile_versions 11/_controls 4841/_taxonomies 13) |
資料列看是產品資產(dev-sec 基準+TWGCB 8 支),但 profile 版本的檔案實體存在 storage(MinIO),DB seed 灌了列、檔案不在就是壞連結——出貨機制需連檔案一起解(隨 installer 帶檔上傳?or 首次啟動重新上傳?) |
| D5 | public.labels 35 筆 |
前段(系統回饋/系統操作/選單>專案管理…)像產品字典,後段(textbook-、resource-)像特定專案用——需逐筆指認 |
| D6 | system_configs 之 ISSUE_INTEGRATE_CONFIG(GITHUB/GITLAB,enable=false 空殼) |
功能是否對客戶開放?開放則出廠帶 disabled 空殼,否則不 seed |
| D7 | public.alembic_version |
來源不明(repo 無 alembic);查無 reader 則基線不帶 |
| D8 | root tenant/org/admin 的出廠命名 | DEV 值是 Guidant.AI/Guidant.AI Manage/admin——正式出貨是否沿用(或 installer 讓客戶命名 root tenant)? |
| D9 | debug view(debug_org_units/v_tenant_parent_debug)與 cm_app_group 空群組 |
出貨基線帶不帶 |
| D10 | DB 命名:新標準 <系統>_{dev|stg}、prod 不帶後綴 → 落地版 DB 名應為 guidant_ai?installer 預設值需定案 |
2026-08-08 新制說「guidant_ai_* 舊制沿用不回頭改」,但落地新客戶算新建置,適用新制與否待拍板 |
scripts/sql/ 與 docs 全量 grep 無 CREATE ROLE cmmgr/cm_app——推測(標註:推測)是當年 DB server 手動建立,屬 cluster-level 操作本來就不進單庫 migration。→ init 機制必須自己補上這塊(首次在客戶主機建 cluster 帳號)。$2b$12$(cost 12),per-user salt 存 users.salt 欄(bcrypt.gensalt()),hash 60 字元存 users.password。DEV 39 個帳號全部同一格式,無 legacy 雜湊。實作在 jedi-auth user_domain_service.add_user()。admin(tenant 1,is_super_admin=true,DEV id=16)+blsadmin(tenant 102 的租戶超管)。admin 的建立同樣查無 seed SQL(推測 legacy 手動/早期工具建立);後續由 2026-06-29-b2-admin-root-tenant.sql 把它掛進 root tenant(users.tenant_id→1 + user_tenants + user_org_units 三筆,B-2 模型)。init 建初始 admin 時這三件事要一次做齊,否則重演「super admin 寫入 tenant_id=NULL 孤兒」bug。app.is_super_admin='t' 放行全庫,值由登入時從 users.is_super_admin 帶出。jedi-auth 已內建完整機制,init 不必新造:
add_user() 流程會自動產 12 碼複雜密碼(generate_complex_password(12))+建立 user_change_password_request(type=FIRST_REGISTER,7 天效期)+寄密碼信。登入時有 pending request 會被導去改密頁;change_password_by_request() 走密碼政策驗證(≥12 碼+大小寫+數字,CM-683)。RUNTIME_CONFIG.CHANGE_PASSWORD_THRESHOLD_DAYS(預設 90)+ type=PASSWORD_EXPIRE 請求。RUNTIME_CONFIG.MFA_REQUIRED + totp_secrets 表。postgres 庫的權限,後者連目標庫。ON CONFLICT DO NOTHING / INSERT ... WHERE NOT EXISTS;schema 段以「schema_migrations 有無 baseline marker」判斷跳過整段。root tenant/org id=1 硬約定需在空庫 seed 時顯式指定 id 並 setval sequence。schema_migrations 登記(建議登記一筆 __init_baseline_v<版號>__ marker + 把已收斂的 active migration 檔名全數補登),讓日後增量 migration 與三環境 diff 工具無縫接軌;schema_version 補基線版號。這與既有 sql-migration 慣例(檔頭 Date、--single-transaction、cmmgr 執行)完全相容——基線之後的新 migration 照舊制走,不受影響。pg_dump schema 段+seed 段+stamp 段串成一支,installer 用 psql --single-transaction -v ON_ERROR_STOP=1 一發套完。
-v 變數穿插在巨檔裡,易錯;cluster 層(CREATE ROLE/DATABASE 不能在交易內、要連不同庫)根本塞不進同一支——實務上一定會裂成「殼腳本+大 SQL」,那不如直接選 B。scripts/init/
00-cluster.sql # CREATE ROLE cmmgr(降規版)/cm_app/cm_app_group、CREATE DATABASE(連 postgres 庫,殼腳本執行)
01-extensions.sql # uuid-ossp、pg_trgm
02-schema.sql # 由 pg_dump --schema-only 產出後整理(去 DEV 殘留表、去歷史月分區)
03-grants.sql # default privileges ×5 schema + event trigger +(驗收用逐項掃描)
04-seed-core.sql # §3.1 字典/權限/選單/root tenant+org/內建流程範本
05-seed-catalog.sql # D1~D4 裁決後的框架/profile 資產(可能改走匯入流程,見下)
06-admin.sql # 初始 admin(bcrypt hash 由外部算好以 -v 傳入)+ B-2 三件套
99-stamp.sql # schema_migrations baseline marker + schema_version
init.sh # 依序執行、參數注入(env vars)、冪等判斷、失敗即停
服務容器 entrypoint 起 binary 前檢測 DB,空庫就跑 init。
docker run 即全好。B(installer 觸發的分段腳本)為主,C 的 init-job 容器作為執行載體:installer 負責產參數(兩組 DB 密碼、admin 初始密碼)→ 起 one-shot init 容器(或直接在主機跑 psql)執行 init.sh → 成功後才起服務容器(只給 cm_app 憑證)。A 不建議單獨採用。
D1 框架資產的特別註記:若裁決結果是「出廠帶 OSCAL JSON、首次啟動匯入」,則 05-seed-catalog.sql 整段換成應用層匯入指令(既有框架匯入 pipeline),DB init 只管空殼——這會顯著縮小 seed dump 的維護面,但拉長首次安裝時間且依賴應用已能啟動。兩路成本留給實作棒對照裁決結果細算。
| 參數 | 用途 | 預設 |
|---|---|---|
INIT_DB_HOST / INIT_DB_PORT |
目標 DB | —(必填) |
INIT_DB_NAME |
資料庫名 | guidant_ai(D10 待裁決) |
INIT_CMMGR_PASSWORD / INIT_CMAPP_PASSWORD |
兩組帳號密碼 | installer 隨機產生 |
INIT_ADMIN_LOGIN / INIT_ADMIN_PASSWORD |
初始 admin | admin/隨機產生+首登改密(D8) |
INIT_ROOT_TENANT_NAME |
root tenant 顯示名 | D8 待裁決 |
INIT_STORAGE_* |
STORAGE_CONFIG 座標 | 安裝時填或裝後後台設 |
-- 缺 GRANT 的表(應回 0 列)
SELECT n.nspname||'.'||c.relname FROM pg_class c JOIN pg_namespace n ON n.oid=c.relnamespace
WHERE c.relkind IN ('r','p') AND n.nspname IN ('public','compliance','config','oscal','survey')
AND NOT (has_table_privilege('cm_app',c.oid,'SELECT') AND has_table_privilege('cm_app',c.oid,'INSERT')
AND has_table_privilege('cm_app',c.oid,'UPDATE') AND has_table_privilege('cm_app',c.oid,'DELETE'));
-- 缺 USAGE 的 sequence(應回 0 列)
SELECT schemaname||'.'||sequencename FROM pg_sequences
WHERE NOT has_sequence_privilege('cm_app', quote_ident(schemaname)||'.'||quote_ident(sequencename),'USAGE');
-- RLS 啟用表清單/policy 數
SELECT n.nspname||'.'||c.relname FROM pg_class c JOIN pg_namespace n ON n.oid=c.relnamespace WHERE c.relrowsecurity;
SELECT count(*) FROM pg_policies;