Major Changes: - Add StreamingService with OpenAI Compatible format - Upgrade Chat component V2 with Ant Design X integration - Implement AIA module with 12 intelligent agents - Update API routes to unified /api/v1 prefix - Update system documentation Backend (~1300 lines): - common/streaming: OpenAI Compatible adapter - modules/aia: 12 agents, conversation service, streaming integration - Update route versions (RVW, PKB to v1) Frontend (~3500 lines): - modules/aia: AgentHub + ChatWorkspace (100% prototype restoration) - shared/Chat: AIStreamChat, ThinkingBlock, useAIStream Hook - Update API endpoints to v1 Documentation: - AIA module status guide - Universal capabilities catalog - System overview updates - All module documentation sync Tested: Stream response verified, authentication working Status: AIA V2.0 core completed (85%)
40 KiB
*AIclinicalresearch 譚<>剞荳手ァ定牡菴鍋ウサ譴ウ逅<EFBDB3>冠蜻?
*譁<EFBFBD>。」迚域悽<EFBFBD>? v1.1<EFBFBD>域紛蜷<EFBFBD>rompt邂。逅<EFBFBD>怙豎ゑシ<EFBFBD>
*蛻帛サコ譌・譛滂シ? 2026-01-11
譛蜷取峩譁ー<EFBFBD><EFBFBD> 2026-01-11
菴懆<EFBFBD>シ<EFBFBD> AI譫カ譫<EFBDB6>ク? *逶ョ逧<EFBFBD>シ? 邉サ扈滓ァ譴ウ逅<EFBDB3>ス灘燕譚<E78795>剞螳樒鴫迥カ蜀オ<E89C80>御クコ霑占是邂。逅<EFBDA1>ォッ蜥梧惻譫<E683BB>ョ。逅<EFBDA1>ォッ蠑蜿大★蜃<E29885>、<EFBFBD>
*蜿俶峩隸エ譏趣シ? 謨エ蜷亥渚鬥亥サコ隶ョ + Prompt邂。逅<EFBDA1>ウサ扈滄怙豎?
<EFBFBD>搭 逶ョ蠖<EFBDAE>
- [蠖灘燕邉サ扈溽憾諤∝<E8ABA4>譫疹(#1-蠖灘燕邉サ扈溽憾諤∝<E8ABA4>譫?
- [謨ー謐ョ蠎灘アる擇譴ウ逅<EFBDB3>(#2-謨ー謐ョ蠎灘アる擇譴ウ逅?
- [蜷守ォッ譚<EFBDAF>剞螳樒鴫譴ウ逅<EFBDB3>(#3-蜷守ォッ譚<EFBDAF>剞螳樒鴫譴ウ逅<EFBDB3>)
- [蜑咲ォッ譚<EFBDAF>剞螳樒鴫譴ウ逅<EFBDB3>(#4-蜑咲ォッ譚<EFBDAF>剞螳樒鴫譴ウ逅<EFBDB3>)
- [蟾ョ霍晏<E99C8D>譫疹(#5-蟾ョ霍晏<E99C8D>譫<EFBFBD>)
- [譁ーPRD髴豎りァ」隸サ](#6-譁ーprd髴豎りァ」隸?
- 譫カ譫<EFBFBD>ョセ隶。蟒コ隶ョ
- [螳樊命霍ッ郤ソ蝗セ](#8-螳樊命霍ッ郤ソ蝗?
- [<5B><> Prompt邂。逅<EFBDA1>ウサ扈滓紛蜷<E7B49B>(#9-prompt邂。逅<EFBDA1>ウサ扈滓紛蜷<E7B49B>)
- [<5B><> 蜿埼ヲ磯㊦郤ウ隸エ譏讃(#10-蜿埼ヲ磯㊦郤ウ隸エ譏<EFBDB4>)
1. 蠖灘燕邉サ扈溽憾諤∝<E8ABA4>譫?
1.1 譬ク蠢<EFBDB8>書邇ー <20>剥
笨?蟾イ譛牙渕遑<EFBFBD>?
- 謨ー謐ョ蠎捺怏蝓コ遑逧Фser陦ィ<EFBFBD><EFBFBD>platform_schema.users
蜥?public.users`荳、荳ェ迚域悽<E59F9F>? - 譛牙渕譛ャ逧вole蟄玲ョオ<EFBFBD>磯サ倩ョ、蛟シ<EFBFBD><EFBFBD>"user"<22>?
- 蜑咲ォッ譛画揀髯先。<EFBFBD>楔<EFBFBD><EFBFBD>PermissionContext`<60>会シ御ス?莉<EFBFBD>ock謨ー謐ョ*
- 蜷守ォッ螳悟<EFBFBD>豐。譛芽ョ、隸<EFBFBD>/謗域揀邉サ扈<EFBDBB>
笶?郛コ螟ア蜈ウ髞ョ閭ス蜉<EFBDBD><EFBFBD>?
- 豐。譛臥匳蠖<EFBFBD>/豕ィ蜀窟PI
- *豐。譛雨WT隶、隸∽クュ髣エ莉?
- 豐。譛臥ァ滓姐(Tenant)菴鍋ウサ
- 豐。譛芽ァ定牡譚<EFBFBD>剞邉サ扈<EFBFBD>(RBAC)
- 豐。譛宇eature Flag謗ァ蛻カ
- 豐。譛牙ョ。隶。譌・蠢礼ウサ扈<EFBFBD>
**<2A>識 蠖灘燕迥カ諤?*<2A>?
- 邉サ扈溷、<EFBFBD>コ<EFBFBD>**蜊墓オ玖ッ戊エヲ蜿?*髦カ谿オ
- 謇譛陰PI驛ス譏ッ**譌<>隶、隸√∵裏驩エ譚<EFBDB4>**迥カ諤?
- 蜑咲ォッ譚<EFBFBD>剞謗ァ蛻カ譏?*郤ッ螻慕、コ諤?*逧<>ock螳樒鴫
2. 謨ー謐ョ蠎灘アる擇譴ウ逅?
2.1 蠖灘燕User陦ィ扈捺<E68988>?
platform_schema.users 笨?譁ー譫カ譫<EFBDB6>シ<EFBFBD>risma螳壻ケ会シ?
model User {
id String @id @default(uuid())
email String @unique
password String
name String?
avatarUrl String? @map("avatar_url")
role String @default("user") // 笞<><E7AC9E><EFBFBD> 邂蜊募ュ礼ャヲ荳イ<E88DB3>御ク榊、溽畑
status String @default("active")
kbQuota Int @default(3)
kbUsed Int @default(0)
trialEndsAt DateTime? @map("trial_ends_at")
isTrial Boolean @default(true)
lastLoginAt DateTime? @map("last_login_at")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@schema("platform_schema")
}
public.users 笶?譌ァ陦ィ<E999A6>亥紙蜿イ驕礼蕗<E7A4BC><E89597>
model users {
id String
email String @unique
password String
name String?
avatar_url String?
role String @default("user") // 笞<><E7AC9E><EFBFBD> 蜷梧<E89CB7>キ邂蜊?
status String @default("active")
kb_quota Int @default(3)
kb_used Int @default(0)
// ... 蜈カ莉門ュ玲ョオ
@@schema("public")
}
*笞<EFBFBD><EFBFBD><EFBFBD> 髣ョ鬚假シ?
- 荳、荳ェUser陦ィ蟷カ蟄假シ悟多蜷堺ク堺ク閾エ<EFBFBD><EFBFBD>sers vs User<65>?
role蟄玲ョオ莉<EFBFBD>クコ蟄礼ャヲ荳イ<EFBFBD>梧裏enum郤ヲ譚<EFBFBD>- *豐。譛臥ァ滓姐蜈ウ閨泌ュ玲ョオ<EFBFBD><EFBFBD>enantId<EFBFBD>?
- *豐。譛蛾Κ髣ィ蟄玲ョオ<EFBFBD><EFBFBD>epartment<EFBFBD>?
- 豐。譛画揀髯宣<EFBFBD>鄂ョ蟄玲ョオ
2.2 郛コ螟ア逧<EFBDB1><E980A7>ク蠢<EFBDB8>。ィ
譬ケ謐ョPRD髴豎ゑシ碁怙隕∵眠蠅樔サ・荳玖。ィ<EFBFBD>?
| 陦ィ蜷<EFBFBD> | Schema菴咲スョ | 逕ィ騾? | 莨伜<EFBFBD>郤? |
|---|---|---|---|
| tenants | platform_schema | 遘滓姐荳サ陦ィ<EFBFBD>亥現髯「縲∬艮莨√∵悄蛻奇シ<EFBFBD> | P0 |
| tenant_users | platform_schema | 遘滓姐-逕ィ謌キ蜈ウ閨碑。? | P0 |
| departments | platform_schema | 驛ィ髣ィ/遘大ョ、陦? | P1 |
| feature_flags | platform_schema | Feature Flag驟咲スョ | P0 |
| tenant_modules | platform_schema | 遘滓姐隶「髦<EFBFBD>ィ。蝮鈴<EFBFBD>鄂ョ | P0 |
| tenant_quotas | platform_schema | 遘滓姐驟埼「晉ョ。逅<EFBFBD> | P1 |
| admin_operation_logs | admin_schema | 霑占是謫堺ス懈律蠢<EFBFBD> | P1 |
*豕ィ諢擾シ? 蠖灘燕譛我ク荳ェAdminLog陦ィ蝨ィpublicschema<EFBFBD>御ス<EFBFBD>ク榊ョ梧紛縲?
2.3 蟾イ譛臥噪螳。隶。譌・蠢?
*IIT讓。蝮礼噪螳。隶。譌・蠢? 笨?<3F>亥庄蜿り<E3828A>シ会シ?
model IitAuditLog {
id String @id @default(uuid())
projectId String
userId String
actionType String
entityType String
entityId String
details Json?
traceId String
createdAt DateTime @default(now())
@@schema("iit_schema")
}
蜿ッ螟咲畑諤ァ<EFBFBD><EFBFBD> 笨?譫カ譫<EFBDB6>ョセ隶。莨倡ァ<EFBDA7>悟庄菴應クコ蜈ィ螻螳。隶。譌・蠢礼噪蜿り<E3828A>?
3. 蜷守ォッ譚<EFBDAF>剞螳樒鴫譴ウ逅<EFBDB3>
3.1 隶、隸∫ウサ扈溽憾諤?笶?*譛ェ螳樒<EFBFBD>?
*謳懃エ「扈捺棡<EFBFBD>?
- 笶?豐。譛画伽蛻ー
/api/auth/login謌?/api/auth/register - 笶?豐。譛雨WT逕滓<E98095>/鬪瑚ッ∝キ・蜈キ
- 笶?豐。譛芽ョ、隸∽クュ髣エ莉カ<E88E89>亥ヲ?
requireAuth<EFBFBD>?
蟇ケ豈泌<EFBFBD>莉夜。ケ逶ョ<EFBFBD>井サ残odebase_search扈捺棡<EFBFBD>会シ<EFBFBD>
- ODJ鬘ケ逶ョ譛牙ョ梧紛逧Пassport JWT隶、隸<EFBDA4> 笨?
- BYSY鬘ケ逶ョ譛雨WT隶、隸∽クュ髣エ莉?笨?
- 譛ャ鬘ケ逶ョ<EFBFBD>壼ョ悟<EFBFBD>遨コ逋ス 笶?
3.2 謗域揀邉サ扈溽憾諤?笶?*譛ェ螳樒<EFBFBD>?
*郛コ螟ア蜀<EFBFBD>ョケ<EFBFBD>?
- 笶?豐。譛芽ァ定牡譽譟・荳ュ髣エ莉カ<E88E89>亥ヲ<E4BAA5>
requireRole(['admin'])<EFBFBD>? - 笶?豐。譛画揀髯先丐蟆<E4B890>。ィ<EFBDA1><EFBDA8>OLE_PERMISSIONS<4E>?
- 笶?豐。譛宇eature Flag譽譟・騾サ霎<EFBDBB>
*蠖ア蜩搾シ?
- 謇譛陰PI遶ッ轤ケ驛ス譏ッ蜈ャ蠑逧<EFBFBD>シ梧裏譚<EFBFBD>剞菫晄<EFBFBD>?
- 譌<EFBFBD>豕募玄蛻<EFBFBD>ョ。逅<EFBFBD>遭蜥梧勸騾夂畑謌?
- 譌<EFBFBD>豕募ョ樒鴫螟夂ァ滓姐謨ー謐ョ髫皮ヲ?
3.3 蠖灘燕API扈捺桷
Legacy Routes (譌<>隶、隸?<3F>?
/api/v1/aia/* - AI譎コ閭ス髣ョ遲費シ域裏譚<E8A38F>剞譽譟・<E8AD9F><EFBDA5>
/api/v1/pkb/* - 荳ェ莠コ遏・隸<EFBDA5>コ難シ域裏譚<E8A38F>剞譽譟・<E8AD9F><EFBDA5>
/api/v1/rvw/* - 遞ソ莉カ螳。譟・<E8AD9F>域裏譚<E8A38F>剞譽譟・<E8AD9F><EFBDA5>
*髣ョ鬚假シ?
- 莉サ菴穂ココ驛ス蜿ッ莉・隶ソ髣ョ莉サ菴慕畑謌キ逧<EFBFBD>焚謐?
- 豐。譛<EFBFBD>
userId驩エ譚<EFBDB4>サ霎<EFBDBB> - 豐。譛臥ァ滓姐謨ー謐ョ髫皮ヲサ
4. 蜑咲ォッ譚<EFBDAF>剞螳樒鴫譴ウ逅<EFBDB3>
4.1 譚<>剞譯<E5899E>楔蟄伜惠 笨?菴<>サ<EFBFBD>クコMock
*譁<EFBFBD>サカ菴咲スョ<EFBFBD>? frontend-v2/src/framework/permission/PermissionContext.tsx
*譬ク蠢<EFBFBD>サ」遐<EFBFBD>シ?
// 笞<><E7AC9E><EFBFBD> 遑ャ郛也<E9839B>∽クコ譛鬮俶揀髯撰シ御サ<E5BEA1>セ帛シ蜿第オ玖ッ?
const MOCK_USER: UserInfo = {
id: 'test-user-001',
name: '豬玖ッ慕<EFBDAF>皮ゥカ蜻?,
email: 'test@example.com',
version: 'premium', // <20>争 遑ャ郛也<E9839B>?
avatar: null,
isTrial: false,
}
// 譚<>剞譽譟・蜃ス謨ー<E8ACA8>亥渕莠散serVersion遲臥コァ<EFBDBA>?
const checkModulePermission = (requiredVersion?: UserVersion): boolean => {
if (!user) return false
if (!requiredVersion) return true
return checkVersionLevel(user.version, requiredVersion)
}
*UserVersion螳壻ケ会シ?
// framework/permission/types.ts
export type UserVersion = 'free' | 'basic' | 'professional' | 'premium'
4.2 譚<>剞譽譟・騾サ霎<EFBDBB> 笨?譫カ譫<EFBDB6>ョ梧紛
*讓。蝮玲ウィ蜀梧慮逧<EFBFBD>揀髯仙」ー譏趣シ?
// 讓。蝮怜ョ壻ケ画磁蜿」
interface ModuleDefinition {
id: string
name: string
path: string
requiredVersion?: UserVersion // <20>識 譚<>剞隕∵ア<E288B5>
// ...
}
*霍ッ逕ア螳亥梱<EFBFBD>?
// RouteGuard.tsx
if (module.requiredVersion && !checkModulePermission(module.requiredVersion)) {
return <PermissionDenied />
}
*笨?莨倡せ<E580A1>?
- 譚<EFBFBD>剞譯<EFBFBD>楔隶セ隶。螳悟埋
- 譏謎コ取黄螻募芦逵溷ョ櫁ョ、隸?
*笶?郛コ轤ケ<E8BDA4>?
- 逕ィ謌キ菫。諱ッ螳悟<EFBFBD>hardcode
- 豐。譛牙ッケ謗・蜷守ォッAPI
- 豐。譛臥匳蠖<EFBFBD>/逋サ蜃コUI
5. 蟾ョ霍晏<E99C8D>譫<EFBFBD>
5.1 荳傘RD髴豎ら噪蟾ョ霍<EFBDAE>
| PRD髴豎? | 蠖灘燕迥カ諤? | 蟾ョ霍<EFBFBD> | 莨伜<EFBFBD>郤? |
|---|---|---|---|
| 遘滓姐邂。逅<EFBFBD> | 笶?譌? | 髴螳梧紛螳樒鴫Tenant菴鍋ウサ | P0 |
| *4遘崎ァ定<EFBFBD>? (SUPER_ADMIN/HOSPITAL_ADMIN/PHARMA_ADMIN/USER) | 笶?蜿ェ譛臥ョ蜊瓶ole蟄礼ャヲ荳? | 髴RBAC菴鍋ウサ | P0 |
| 蜩∫煙螳壼宛 (Logo/逋サ蠖暮。? | 笶?譌? | 髴tenant.config JSONB蟄玲ョオ | P0 |
| 逋サ蠖慕ウサ扈<EFBFBD> | 笶?譌? | 髴JWT隶、隸∫ウサ扈<EFBFBD> | P0 |
| 譚<EFBFBD>剞謗ァ蛻カ | 笨?蜑咲ォッMock / 笶?蜷守ォッ譌? | 髴蜷守ォッ荳ュ髣エ莉? | P0 |
| Feature Flag | 笶?譌? | 髴驟咲スョ陦?譽譟・騾サ霎<EFBDBB> | P0 |
| *霑占是遶? (/admin/*) | 笶?譌? | 髴蜈ィ譁ー蠑蜿? | P0 |
| *譛コ譫<EFBFBD>ォ? (/org/hospital/, /org/pharma/) | 笶?譌? | 髴蜈ィ譁ー蠑蜿? | P1 |
| 螳。隶。譌・蠢<EFBFBD> | 笞<EFBFBD><EFBFBD><EFBFBD> 莉<>IT讓。蝮<EFBDA1> | 髴蜈ィ螻螳。隶。邉サ扈<EFBFBD> | P1 |
5.2 譫カ譫<EFBDB6>アる擇蟾ョ霍<EFBDAE>
*蠖灘燕譫カ譫<EFBFBD>シ? 蜊慕畑謌キ縲∵裏遘滓姐縲∵裏譚<E8A38F>剞
User (蜊戊。ィ)
竊?
Projects/KnowledgeBases/... (逶エ謗・蜈ウ閨<EFBDB3> userId)
*逶ョ譬<EFBFBD>楔譫<EFBFBD>シ? 螟夂ァ滓姐縲ヽBAC縲∵焚謐ョ髫皮ヲ?
Tenant (遘滓姐)
竊?
Department (驛ィ髣ィ/遘大ョ、)
竊?
User (逕ィ謌キ) + Role (隗定牡)
竊?
Projects/KnowledgeBases/... (tenant_id + user_id)
6. 譁ーPRD髴豎りァ」隸?
6.1 譬ク蠢<EFBDB8>ァ定牡螳壻ケ会シ域擂閾ェPRD v2.1<EFBFBD>?
| 隗定牡Code | 蠖貞ア<EFBFBD> | 譚<EFBFBD>剞闌<EFBFBD>峩 | URL蜑咲シ | 譬ク蠢<EFBFBD>′雍」 |
|---|---|---|---|---|
| SUPER_ADMIN | 蟷ウ蜿ー | 蜈ィ螻謨ー謐ョ | /admin | 遘滓姐蠑騾壹∝刀迚碁<EFBFBD>鄂ョ縲 ̄rompt隹<EFBFBD>シ<EFBFBD> |
| HOSPITAL_ADMIN | 蛹サ髯「遘滓姐 | 譛ャ髯「謨ー謐ョ | /org/hospital | 遘大ョ、邂。逅<EFBFBD><EFBFBD><EFBFBD>鬚晏<EFBFBD>驟? |
| PHARMA_ADMIN | 闕ッ莨∫ァ滓姐 | 譛ャ莨<EFBFBD>。ケ逶ョ | /org/pharma | 鬘ケ逶ョ逶第而縲,RO邂。逅<EFBFBD>∝ョ。隶? |
| USER | 莉サ諢冗ァ滓姐 | 荳ェ莠コ/陲ォ謗域揀謨ー謐? | /app | 遘醍<EFBFBD>比ク壼苅謫堺ス<EFBFBD> |
6.2 遘滓姐邀サ蝙具シ<E585B7>enant Type<70>?
enum TenantType {
HOSPITAL = 'HOSPITAL', // 蛹サ髯「螳「謌キ
PHARMA = 'PHARMA', // 闕ッ莨∝ョ「謌キ
JOURNAL = 'JOURNAL', // 譛溷<E8AD9B>螳「謌キ
}
6.3 蜩∫煙螳壼宛髴豎?<3F><>
*URL遲也払<EFBFBD>?
騾夂畑逋サ蠖包シ喇ttps://app.yizhengxun.com/auth/login
荳灘ア樒匳蠖包シ喇ttps://app.yizhengxun.com/t/{tenant_code}/login
遘滓姐驟咲スョ<EFBFBD><EFBFBD>SONB<EFBFBD>会シ<EFBFBD>
{
"branding": {
"logoUrl": "https://oss.../jst_logo.png",
"loginBackgroundUrl": "https://oss.../jst_bldg.jpg",
"primaryColor": "#0056b3",
"welcomeTitle": "蛹嶺コャ遘ッ豌エ貎ュ蛹サ髯?AI 荳エ蠎顔ァ醍<EFBDA7>泌ケウ蜿ー",
"welcomeSubTitle": "譎コ閭ス蛹?ツキ 隗<EFBFBD>激蛹?ツキ 鬮俶譜邇?
}
}
6.4 譎コ閭ス霍ッ逕ア蛻<EFBDB1>書<EFBFBD>育匳蠖募錘霍ウ霓ャ<E99C93>?
function getRedirectPath(user, tenant) {
if (user.role === 'SUPER_ADMIN') return '/admin/dashboard';
if (user.role === 'TENANT_ADMIN') {
if (tenant.type === 'HOSPITAL') return '/org/hospital/dashboard';
if (tenant.type === 'PHARMA') return '/org/pharma/dashboard';
}
if (tenant.type === 'JOURNAL') return '/app/rvw/dashboard';
return '/app/dashboard'; // 鮟倩ョ、<EFBDAE>壽勸騾夂畑謌?
}
7. 譫カ譫<EFBDB6>ョセ隶。蟒コ隶ョ
7.1 謨ー謐ョ蠎鉄chema隶セ隶。
*7.1.1 platform_schema<6D>亥ケウ蜿ー譬ク蠢<EFBDB8>。ィ<EFBDA1>?
*A. tenants 陦? <20><>0<EFBFBD>?
model Tenant {
id String @id @default(uuid())
name String // 遘滓姐蜷咲ァー<EFBDA7>亥ヲゑシ壼圏莠ャ遘ッ豌エ貎ュ蛹サ髯「<E9ABAF>?
code String @unique // 遘滓姐莉」遐<EFBDA3>シ亥ヲゑシ嗚st-hospital<61>檎畑莠散RL<52>?
type TenantType // 遘滓姐邀サ蝙具シ唏OSPITAL/PHARMA/JOURNAL
status String @default("active") // active/suspended/expired
// 蜩∫煙驟咲スョ<EFBDBD><EFBDAE>SONB<4E>?
config Json @default("{}") // branding驟咲スョ縲∵ィ。蝮苓ョ「髦<EFBDA2>ュ<EFBFBD>
// 驟埼「晉ョ。逅<EFBDA1>
tokenQuota Int? // 諤サToken鬚晏コヲ
tokenUsed Int @default(0) // 蟾イ菴ソ逕ィToken
// 譌カ髣エ謌?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
expiresAt DateTime? // 隶「髦<EFBDA2>芦譛滓慮髣エ
// 蜈ウ邉サ
users TenantUser[]
departments Department[]
modules TenantModule[]
@@index([code])
@@index([type])
@@index([status])
@@map("tenants")
@@schema("platform_schema")
}
enum TenantType {
HOSPITAL
PHARMA
JOURNAL
@@schema("platform_schema")
}
*B. users 陦ィ謇ゥ螻? <20><>0<EFBFBD>?
model User {
id String @id @default(uuid())
email String @unique
password String
name String?
avatarUrl String? @map("avatar_url")
// <20><> 螟夂ァ滓姐謾ッ謖?
tenantId String? @map("tenant_id") // 謇螻樒ァ滓姐<E6BB93><E5A790>ULL=蟷ウ蜿ー邂。逅<EFBDA1>遭<EFBFBD><E981AD>
departmentId String? @map("department_id") // 謇螻樣Κ髣?遘大ョ、
// <20><> 隗定牡邉サ扈<EFBDBB>
role UserRole // SUPER_ADMIN/TENANT_ADMIN/USER
// 蜈カ莉門ュ玲ョオ菫晄戟荳榊序...
status String @default("active")
kbQuota Int @default(3)
trialEndsAt DateTime?
lastLoginAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// 蜈ウ邉サ
tenant Tenant? @relation(fields: [tenantId], references: [id])
department Department? @relation(fields: [departmentId], references: [id])
@@index([tenantId])
@@index([departmentId])
@@index([role])
@@map("users")
@@schema("platform_schema")
}
enum UserRole {
SUPER_ADMIN // 蟷ウ蜿ー雜<EFBDB0>コァ邂。逅<EFBDA1><E98085>?
TENANT_ADMIN // 遘滓姐邂。逅<EFBDA1>遭<EFBFBD>亥現髯「/闕ッ莨<EFBDAF>シ?
USER // 譎ョ騾夂畑謌キ<E8AC8C>亥現逕<E78FBE>/遐皮ゥカ蜻假シ<E58187>
@@schema("platform_schema")
}
*C. tenant_members 陦? <20><>0<EFBFBD>俄恟<E4BF84>?驥<>コウ蜿埼ヲ茨シ壽隼蜷堺クコTenantMember
model TenantMember {
id String @id @default(uuid())
tenantId String @map("tenant_id")
userId String @map("user_id")
role String // 蝨ィ隸・遘滓姐荳ュ逧<EFBDAD>ァ定牡
joinedAt DateTime @default(now()) @map("joined_at")
tenant Tenant @relation(fields: [tenantId], references: [id])
@@unique([tenantId, userId])
@@map("tenant_members") // 隸ュ荵画峩貂<E5B3A9><E8B282>?
@@schema("platform_schema")
}
*D. departments 陦? <20><>1<EFBFBD>?
model Department {
id String @id @default(uuid())
tenantId String @map("tenant_id")
name String // 遘大ョ、蜷咲ァー<EFBDA7>亥ヲゑシ壼ソ<E5A3BC><EFBDBF>遘托シ?
parentId String? @map("parent_id") // 荳顔コァ遘大ョ、<EFBDAE>域髪謖∵<E8AC96>大ス「扈捺桷<E68DBA><E6A1B7>
tokenQuota Int? @map("token_quota") // 遘大ョ、Token鬚晏コヲ
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id])
users User[]
parent Department? @relation("DepartmentHierarchy", fields: [parentId], references: [id])
children Department[] @relation("DepartmentHierarchy")
@@index([tenantId])
@@map("departments")
@@schema("platform_schema")
}
*E. feature_flags 陦? <20><>0<EFBFBD>?
model FeatureFlag {
id String @id @default(uuid())
featureKey String @unique @map("feature_key") // 蜉溯<E89C89>譬<EFBFBD>ッ<EFBFBD>シ亥ヲゑシ嗽se_gpt_5<5F>?
displayName String @map("display_name")
description String?
isEnabled Boolean @default(false) @map("is_enabled")
targetRoles String[] @map("target_roles") // 蜈∬ョク逧<EFBDB8>ァ定牡蛻苓。?
targetTenants String[] @default([]) @map("target_tenants") // 蜈∬ョク逧<EFBDB8>ァ滓姐ID蛻苓。ィ
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("feature_flags")
@@schema("platform_schema")
}
*F. tenant_modules 陦? <20><>0<EFBFBD>?
model TenantModule {
id String @id @default(uuid())
tenantId String @map("tenant_id")
moduleCode String @map("module_code") // 讓。蝮嶺サ」遐<EFBDA3>シ<EFBFBD>SL/DC/IIT遲会シ<E4BC9A>
isEnabled Boolean @default(true) @map("is_enabled")
expiresAt DateTime? @map("expires_at") // 讓。蝮苓ョ「髦<EFBDA2>芦譛滓慮髣エ
createdAt DateTime @default(now())
tenant Tenant @relation(fields: [tenantId], references: [id])
@@unique([tenantId, moduleCode])
@@map("tenant_modules")
@@schema("platform_schema")
}
*G. tenant_quota_allocations 陦? <20><>0<EFBFBD>解氣?驥<>コウ蜿埼ヲ茨シ夂イセ扈<EFBDBE>喧驟埼「晏<EFBDA2>驟<EFBFBD>
model TenantQuotaAllocation {
id Int @id @default(autoincrement())
tenantId String @map("tenant_id")
targetType String @map("target_type") // 'DEPARTMENT' | 'USER'
targetKey String @map("target_key") // DepartmentID 謌?UserID
limitAmount BigInt @map("limit_amount") // 蛻<><E89BBB>逧Уoken鬚晏コヲ
usedAmount BigInt @default(0) @map("used_amount") // 蟾イ菴ソ逕?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([tenantId, targetType, targetKey])
@@index([tenantId])
@@index([targetType, targetKey])
@@map("tenant_quota_allocations")
@@schema("platform_schema")
}
逕ィ騾費シ<EFBFBD> 蛹サ髯「遶ッ蜿ッ莉・蟆<EFBDA5>サToken鬚晏コヲ蛻<EFBDA6><E89BBB>扈?蠢<><E8A0A2>遘?<3F><>epartment<6E>画<EFBFBD>"蠑<>蛹サ逕?<3F><>ser<65>?
7.1.2 admin_schema<6D>郁ソ占是邂。逅<EFBDA1>シ<EFBFBD>
*H. admin_operation_logs 陦? <20><>1<EFBFBD>俄恟<E4BF84>?驥<>コウ蜿埼ヲ茨シ壼「槫刈module蟄玲ョオ
model AdminOperationLog {
id Int @id @default(autoincrement())
adminId String @map("admin_id")
operationType String @map("operation_type") // CREATE_TENANT/UPDATE_FEATURE_FLAG遲?
targetType String @map("target_type") // tenant/user/config
targetId String @map("target_id")
module String? @map("module") // <20><> 謇螻樊ィ。蝮暦シ<E69AA6>IT/ASL/邉サ扈滄<E68988>鄂ョ遲会シ<E4BC9A>
beforeData Json? @map("before_data")
afterData Json? @map("after_data")
ipAddress String? @map("ip_address")
userAgent String? @map("user_agent")
createdAt DateTime @default(now())
@@index([adminId])
@@index([operationType])
@@index([module]) // <20><> 闕ッ莨∫ォッ謖画ィ。蝮玲衍隸「
@@index([createdAt])
@@map("admin_operation_logs")
@@schema("admin_schema")
}
7.2 蜷守ォッAPI譫カ譫<EFBDB6>ョセ隶。
A. 隶、隸∫ウサ扈<EFBDBB> <20><>0<EFBFBD>?
*霍ッ逕ア<EFBFBD>? /api/v1/auth/*
// backend/src/platform/auth/routes.ts
POST /api/v1/auth/register // 逕ィ謌キ豕ィ蜀<EFBDA8>
POST /api/v1/auth/login // 逋サ蠖包シ郁ソ泌屓JWT<57>?
POST /api/v1/auth/logout // 逋サ蜃コ
POST /api/v1/auth/refresh // 蛻キ譁ーToken
GET /api/v1/auth/me // 闔キ蜿門ス灘燕逕ィ謌キ菫。諱ッ
*JWT Payload扈捺桷<E68DBA>?
interface JWTPayload {
userId: string
email: string
role: UserRole
tenantId?: string
tenantType?: TenantType
exp: number // 霑<>悄譌カ髣エ
}
*B. 隶、隸∽クュ髣エ莉? <20><>0<EFBFBD>?
// backend/src/common/middleware/auth.ts
/**
* JWT隶、隸∽クュ髣エ莉?
* 鬪瑚ッゝoken蟷カ蟆<EFBDB6>畑謌キ菫。諱ッ謖りスス蛻?req.user
*/
export const requireAuth = async (req, res, next) => {
const token = extractToken(req)
if (!token) return res.status(401).send({ error: 'Unauthorized' })
try {
const payload = verifyJWT(token)
req.user = await prisma.user.findUnique({ where: { id: payload.userId } })
if (!req.user) return res.status(401).send({ error: 'User not found' })
next()
} catch (error) {
return res.status(401).send({ error: 'Invalid token' })
}
}
/**
* 隗定牡譚<E789A1>剞荳ュ髣エ莉?
* 譽譟・逕ィ謌キ譏ッ蜷ヲ蜈キ譛画欠螳夊ァ定<EFBDA7>?
*/
export const requireRole = (...allowedRoles: UserRole[]) => {
return (req, res, next) => {
if (!req.user) return res.status(401).send({ error: 'Unauthorized' })
if (!allowedRoles.includes(req.user.role)) {
return res.status(403).send({ error: 'Forbidden' })
}
next()
}
}
/**
* 遘滓姐謨ー謐ョ髫皮ヲサ荳ュ髣エ莉?
* 遑ョ菫晉畑謌キ蜿ェ閭ス隶ソ髣ョ閾ェ蟾ア遘滓姐逧<E5A790>焚謐?
*/
export const requireTenantAccess = (req, res, next) => {
if (!req.user) return res.status(401).send({ error: 'Unauthorized' })
// SUPER_ADMIN蜿ッ莉・隶ソ髣ョ謇譛臥ァ滓姐謨ー謐?
if (req.user.role === 'SUPER_ADMIN') return next()
// 蜈カ莉也畑謌キ蜿ェ閭ス隶ソ髣ョ閾ェ蟾ア遘滓姐逧<E5A790>焚謐?
req.tenantId = req.user.tenantId
next()
}
C. 霑占是邂。逅<EFBDA1>ォッAPI <20><>0<EFBFBD>?
*霍ッ逕ア<EFBFBD>? /api/v1/admin/*
// 遘滓姐邂。逅<EFBDA1>
POST /api/v1/admin/tenants // 蛻帛サコ遘滓姐
GET /api/v1/admin/tenants // 遘滓姐蛻苓。ィ
GET /api/v1/admin/tenants/:id // 遘滓姐隸ヲ諠<EFBDA6>
PUT /api/v1/admin/tenants/:id // 譖エ譁ー遘滓姐
DELETE /api/v1/admin/tenants/:id // 蛻<>髯、遘滓姐
// Feature Flag邂。逅<EFBDA1>
GET /api/v1/admin/feature-flags // 闔キ蜿匁園譛宇eature Flag
PUT /api/v1/admin/feature-flags/:key // 譖エ譁ーFeature Flag
// 逕ィ謌キ邂。逅<EFBDA1>
GET /api/v1/admin/users // 蜈ィ螻逕ィ謌キ蛻苓。ィ
POST /api/v1/admin/users/:id/assign-tenant // 蛻<><E89BBB>遘滓姐
*譚<EFBFBD>剞隕∵アゑシ? 蜈ィ驛ィ髴隕?requireRole('SUPER_ADMIN')
D. 譛コ譫<EFBDBA>ョ。逅<EFBDA1>ォッAPI <20><>1<EFBFBD>?
*霍ッ逕ア<EFBFBD>? /api/v1/org/*
// 蛹サ髯「邂。逅<EFBDA1>ォ?
GET /api/v1/org/hospital/departments // 遘大ョ、蛻苓。ィ
POST /api/v1/org/hospital/departments // 蛻帛サコ遘大ョ、
GET /api/v1/org/hospital/members // 謌仙遭蛻苓。ィ
POST /api/v1/org/hospital/members/import // 謇ケ驥丞ッシ蜈・謌仙遭
// 闕ッ莨∫ョ。逅<EFBDA1>ォ?
GET /api/v1/org/pharma/projects // 鬘ケ逶ョ蛻苓。ィ
GET /api/v1/org/pharma/audit-logs // 螳。隶。譌・蠢<EFBDA5>
*譚<EFBFBD>剞隕∵アゑシ? requireRole('TENANT_ADMIN') + requireTenantAccess
E. 蜈ャ蠑API <20><>0<EFBFBD>?
*霍ッ逕ア<EFBFBD>? /api/public/*
// 遘滓姐蜩∫煙驟咲スョ<EFBDBD>域裏髴逋サ蠖包シ?
GET /api/public/tenant-config?code={code} // 闔キ蜿也ァ滓姐蜩∫煙驟咲スョ
7.3 蜑咲ォッ譫カ譫<EFBDB6>ョセ隶。
A. 隶、隸∵ィ。蝮<EFBDA1> <20><>0<EFBFBD>?
*逶ョ蠖慕サ捺桷<EFBFBD>?
frontend-v2/src/modules/auth/
笏懌楳笏 pages/
笏? 笏懌楳笏 LoginPage.tsx # 騾夂畑逋サ蠖暮。?
笏? 笏懌楳笏 TenantLoginPage.tsx # 遘滓姐荳灘ア樒匳蠖暮。オ<EFBDA1>亥勘諤∝刀迚鯉シ<E9AF89>
笏? 笏披楳笏 RegisterPage.tsx # 豕ィ蜀碁。?
笏懌楳笏 api/
笏? 笏披楳笏 authApi.ts # 隶、隸、PI隹<49>畑
笏懌楳笏 hooks/
笏? 笏披楳笏 useAuth.ts # 隶、隸?ook
笏披楳笏 routes.tsx # 隶、隸∬キッ逕ア
*B. 霑占是邂。逅<EFBDA1>ォッ讓。蝮? <20><>0<EFBFBD>?
*逶ョ蠖慕サ捺桷<EFBFBD>?
frontend-v2/src/modules/admin/
笏懌楳笏 pages/
笏? 笏懌楳笏 Dashboard.tsx # 霑占是莉ェ陦ィ逶?
笏? 笏懌楳笏 TenantManagement/ # 遘滓姐邂。逅<EFBDA1>
笏? 笏? 笏懌楳笏 TenantList.tsx
笏? 笏? 笏懌楳笏 TenantCreate.tsx
笏? 笏? 笏懌楳笏 TenantEdit.tsx
笏? 笏? 笏披楳笏 BrandingConfig.tsx # 蜩∫煙驟咲スョ
笏? 笏懌楳笏 FeatureFlagManagement.tsx # Feature Flag邂。逅<EFBDA1>
笏? 笏披楳笏 UserManagement.tsx # 逕ィ謌キ邂。逅<EFBDA1>
笏懌楳笏 api/
笏? 笏披楳笏 adminApi.ts
笏披楳笏 index.tsx # 讓。蝮怜ョ壻ケ<E5A3BB>
*讓。蝮玲ウィ蜀鯉シ?
const AdminModule: ModuleDefinition = {
id: 'admin',
name: '霑占是邂。逅<EFBDA1>',
path: '/admin',
requiredVersion: undefined, // 荳榊渕莠思ersion譽譟?
requireRole: ['SUPER_ADMIN'], // <20><> 蝓コ莠手ァ定牡譽譟?
component: lazy(() => import('./layouts/AdminLayout')),
}
*C. 譛コ譫<EFBDBA>ョ。逅<EFBDA1>ォッ讓。蝮? <20><>1<EFBFBD>?
*逶ョ蠖慕サ捺桷<EFBFBD>?
frontend-v2/src/modules/org/
笏懌楳笏 hospital/ # 蛹サ髯「邂。逅<EFBDA1>ォ?
笏? 笏懌楳笏 pages/
笏? 笏? 笏懌楳笏 Dashboard.tsx
笏? 笏? 笏懌楳笏 DepartmentManagement.tsx
笏? 笏? 笏披楳笏 MemberManagement.tsx
笏? 笏披楳笏 index.tsx
笏披楳笏 pharma/ # 闕ッ莨∫ョ。逅<EFBDA1>ォ?
笏懌楳笏 pages/
笏? 笏懌楳笏 Dashboard.tsx
笏? 笏懌楳笏 ProjectManagement.tsx
笏? 笏披楳笏 AuditLogs.tsx
笏披楳笏 index.tsx
8. 螳樊命霍ッ郤ソ蝗?
8.1 Phase 0<>壼㊥螟<E38AA5>キ・菴懶シ<E687B6>1螟ゥ<E89E9F><EFBDA9>
*逶ョ譬<EFBFBD>シ? 扈滉ク謨ー謐ョ蠎楢。ィ扈捺桷<E68DBA>梧ク<E6A2A7>炊蜴<E7828A>彰驕礼<E9A995>?
-
*莉サ蜉。1<EFBFBD>? 蜀ウ遲紋ソ晉蕗
platform_schema.users霑俶弍public.users- 蟒コ隶ョ<EFBFBD>壻ソ晉<EFBFBD>?
platform_schema.users<EFBFBD>域眠譫カ譫<EFBFBD>シ? - 霑∫ァサ
public.users逧<>紙蜿イ謨ー謐ョ蛻ーplatform_schema.users - 蛻<EFBFBD>髯、
public.users陦?
- 蟒コ隶ョ<EFBFBD>壻ソ晉<EFBFBD>?
-
*莉サ蜉。2<EFBFBD>? 蛻帛サコ霑∫ァサ譁<EFBDBB>。」
- 譴ウ逅<EFBFBD>園譛我ク壼苅讓。蝮怜ッケ User 陦ィ逧<EFBDA8>シ慕畑
- 蛻カ螳壽焚謐ョ霑∫ァサ閼壽悽
8.2 Phase 1<>壽焚謐ョ蠎鉄chema隶セ隶。<E99AB6>?螟ゥ<E89E9F><EFBDA9>
P0 譬ク蠢<EFBDB8>。ィ<EFBDA1><EFBDA8>
- *Day 1荳雁壕<E99B81>? 隶セ隶。蟷カ蛻帛サ?
tenants陦? - *Day 1荳句壕<E58FA5>? 謇ゥ螻<EFBDA9>
users陦ィ<E999A6>亥「槫刈 tenantId, departmentId, role enum<75>? - *Day 2荳雁壕<E99B81>? 蛻帛サコ
tenant_users,feature_flags,tenant_modules陦? - *Day 2荳句壕<E58FA5>? 蛻帛サコ Prisma Schema 蟷カ霑占。瑚ソ∫ァ?
莠、莉倡黄<EFBFBD><EFBFBD>
- 笨?Prisma Schema螳梧紛螳壻ケ<E5A3BB>
- 笨?霑∫ァサ閼壽悽霑占。碁夊ソ<E5A48A>
- 笨?豬玖ッ墓焚謐ョ謠貞<E8ACA0>鬪瑚ッ<E7919A>
8.3 Phase 2<>壼錘遶ッ隶、隸∫ウサ扈滂シ<E6BB82>3螟ゥ<E89E9F><EFBDA9>
-
*Day 1<>? 螳樒鴫JWT蟾・蜈キ邀?
generateToken()verifyToken()refreshToken()
-
*Day 2<>? 螳樒鴫隶、隸、PI
- POST
/api/v1/auth/register - POST
/api/v1/auth/login - GET
/api/v1/auth/me
- POST
-
*Day 3<>? 螳樒鴫隶、隸∽クュ髣エ莉?
requireAuthrequireRolerequireTenantAccess- 蠎皮畑蛻ー邇ー譛鵜egacy API
莠、莉倡黄<EFBFBD><EFBFBD>
- 笨?螳梧紛逧<E7B49B>ョ、隸∫ウサ扈?
- 笨?謇譛陰PI蜉<49>荳願ョ、隸∽ソ晄侃
- 笨?Postman豬玖ッ暮夊ソ<E5A48A>
8.4 Phase 3<>壼燕遶ッ隶、隸∝ッケ謗・<E8AC97><EFBDA5>2螟ゥ<E89E9F><EFBDA9>
-
*Day 1<>? 螳樒鴫逋サ蠖暮。オ髱「
- LoginPage.tsx
- useAuth Hook
- Token蟄伜お<EFBFBD><EFBFBD>ocalStorage<EFBFBD>?
-
*Day 2<>? 蟇ケ謗・譚<EFBDA5>剞譯<E5899E>楔
- 譖ソ謐「PermissionContext荳ュ逧<EFBFBD>ock謨ー謐ョ
- 螳樒鴫莉主錘遶ッ闔キ蜿也畑謌キ菫。諱?
- 螳樒鴫逋サ蜃コ蜉溯<EFBFBD>
莠、莉倡黄<EFBFBD><EFBFBD>
- 笨?蜿ッ逕ィ逧<EFBDA8>匳蠖?逋サ蜃コ豬∫ィ<E288AB>
- 笨?蜑咲ォッ譚<EFBDAF>剞謗ァ蛻カ逕滓譜
8.5 Phase 4<>夊ソ占是邂。逅<EFBDA1>ォッMVP<56>?螟ゥ<E89E9F><EFBDA9>
*P0 譬ク蠢<EFBDB8>粥閭ス<E996AD>?
-
*Day 1-2<>? 遘滓姐邂。逅<EFBDA1>
- 遘滓姐蛻苓。ィ鬘?
- 蛻帛サコ遘滓姐陦ィ蜊包シ亥渕譛ャ菫。諱?遘滓姐邀サ蝙具シ?
- 遘滓姐隸ヲ諠<EFBFBD>。?
-
*Day 3<>? 蜩∫煙驟咲スョ
- Logo荳贋シ<EFBFBD>蛻ーOSS
- 逋サ蠖暮。オ閭梧勹蝗セ荳贋シ<EFBFBD>
- 驟咲スョ鬚<EFBFBD>ァ<EFBFBD>
-
*Day 4<>? Feature Flag邂。逅<EFBDA1>
- Feature Flag蛻苓。ィ
- 蠑蜈ウ蛻<EFBFBD><EFBFBD>?
- 逶ョ譬<EFBFBD>ァ滓姐驟咲スョ
-
*Day 5<>? 髮<><E9ABAE>豬玖ッ<E78E96>
- 霑占是遶ッ螳梧紛豬∫ィ区オ玖ッ?
- 譚<EFBFBD>剞謗ァ蛻カ豬玖ッ<EFBFBD>
莠、莉倡黄<EFBFBD><EFBFBD>
- 笨?霑占是邂。逅<EFBDA1>ォッMVP蜿ッ逕ィ
- 笨?蜿ッ莉・蛻帛サコ遘滓姐
- 笨?蜿ッ莉・驟咲スョ蜩∫煙
- 笨?蜿ッ莉・邂。逅<EFBDA1>eature Flag
8.6 Phase 5<>夂ァ滓姐荳灘ア樒匳蠖包シ<E58C85>2螟ゥ<E89E9F><EFBDA9>
-
*Day 1<>? 螳樒鴫TenantLoginPage
- 蜉ィ諤∝刈霓ス遘滓姐蜩∫煙驟咲ス?
- 譖ソ謐「Logo蜥瑚レ譎ッ蝗セ
- 蜉ィ諤∽クサ鬚倩牡
-
*Day 2<>? 螳樒鴫譎コ閭ス霍ッ逕ア蛻<EFBDB1>書
- 逋サ蠖募錘譬ケ謐ョrole+tenantType霍ウ霓ャ
- 豬玖ッ穂ク榊酔隗定牡逧<EFBFBD>キウ霓ャ騾サ霎<EFBFBD>
莠、莉倡黄<EFBFBD><EFBFBD>
- 笨?遘滓姐荳灘ア樒匳蠖暮。オ蜿ッ逕?
- 笨?URL<52>啻/t/{code}/login` 逕滓譜
8.7 Phase 6<>壽惻譫<E683BB>ョ。逅<EFBDA1>ォッ<EFBDAB>域潔髴蠑蜿托シ<E68998>
*P1 蜉溯<E89C89><E6BAAF>亥錘扈ュ謗呈悄<E59188>会シ?
- 蛹サ髯「邂。逅<EFBFBD>ォッ<EFBFBD>夂ァ大ョ、邂。逅<EFBFBD>∵<EFBFBD>蜻倡ョ。逅<EFBFBD><EFBFBD><EFBFBD>鬚晏<EFBFBD>驟?
- 闕ッ莨∫ョ。逅<EFBFBD>ォッ<EFBFBD>夐。ケ逶ョ逶第而縲∝ョ。隶。譌・蠢?
9. 蜈ウ髞ョ蜀ウ遲也<E981B2>?
9.1 謚譛ッ蜀ウ遲?
| 蜀ウ遲也<EFBFBD>? | 騾蛾。ケ | 蟒コ隶ョ | 逅<EFBFBD>罰 |
|---|---|---|---|
| User陦ィ騾画叫 | platform_schema.users vs public.users | 笨?platform_schema.users | 隨ヲ蜷域眠譫カ譫<EFBFBD>シ郡chema髫皮ヲサ貂<EFBFBD>匆 |
| JWT蠎馴画叫 | jsonwebtoken vs jose | 笨?jsonwebtoken | 謌千<EFBFBD>遞ウ螳夲シ檎、セ蛹コ豢サ霍? |
| 蟇<EFBFBD><EFBFBD>∝刈蟇<EFBFBD> | bcrypt vs argon2 | 笨?bcrypt | 鬘ケ逶ョ蟾イ譛我セ晁オ厄シ郁ァ!IT讓。蝮暦シ? |
| Token蟄伜お | localStorage vs httpOnly Cookie | 笨?localStorage | 蜑榊錘遶ッ蛻<EFBFBD>ヲサ<EFBFBD>瑚キィ蝓溷暑螂ス |
| 隗定牡螳壻ケ画婿蠑<EFBFBD> | 蟄礼ャヲ荳?vs Enum | 笨?Prisma Enum | 邀サ蝙句ョ牙<EFBFBD><EFBFBD>碁∩蜈肴蕎蜀咎漠隸? |
9.2 荳壼苅蜀ウ遲<EFBDB3>
| 蜀ウ遲也<EFBFBD>? | 騾蛾。ケ | 蟒コ隶ョ | 逅<EFBFBD>罰 |
|---|---|---|---|
| *遘滓姐莉」遐∝髪荳諤? | 蜈ィ螻蜚ッ荳 vs 邀サ蝙句<E89D99>蜚ッ荳 | 笨?蜈ィ螻蜚ッ荳 | URL /t/{code} 髴蜈ィ螻蜚ッ荳 |
| *驛ィ髣ィ譬大アらコ? | 蝗コ螳<EFBFBD>2螻?vs 譌<>髯仙アらコァ | 笨?譌<>髯仙アらコァ | 謾ッ謖∝、肴揩扈<EFBFBD>サ<EFBFBD>楔譫<EFBFBD> |
| Feature Flag邊貞コヲ | 遘滓姐郤?vs 逕ィ謌キ郤? | 笨?遘滓姐郤? | 隨ヲ蜷亥膚荳壽ィ。蠑擾シ檎ョ。逅<EFBFBD>ョ蜊? |
10. 鬟朱勦荳取倦謌?
10.1 謚譛ッ鬟朱<E9AC9F>?
| 鬟朱勦 | 蠖ア蜩<EFBFBD> | 郛楢ァ」謗ェ譁ス |
|---|---|---|
| *邇ー譛陰PI譌<EFBFBD>隶、隸? | 髴隕∝<EFBFBD>髱「謾ケ騾? | 貂占ソ帛シ丞刈蜈・隶、隸<EFBFBD>シ御シ伜<EFBFBD>菫晄侃謨乗─API |
| *荳、荳ェUser陦? | 謨ー謐ョ荳堺ク閾? | 蟆ス蠢ォ扈滉ク<EFBFBD>檎シ門<EFBFBD>霑∫ァサ閼壽<EFBFBD>? |
| 遘滓姐謨ー謐ョ髫皮ヲサ | 蜿ッ閭ス豕<EFBFBD>愆謨ー謐ョ | 荳・譬シ豬玖ッ<EFBFBD> requireTenantAccess 荳ュ髣エ莉? |
10.2 蠑蜿第倦謌?
| 謖第<EFBFBD> | 髫セ蠎ヲ | 蠎泌ッケ譁ケ譯<EFBFBD> |
|---|---|---|
| JWT隶、隸∫ウサ扈<EFBFBD> | 荳ュ遲<EFBFBD> | 蜿りグDJ/BYSY鬘ケ逶ョ螳樒鴫 |
| *蜩∫煙蜉ィ諤∝刈霓? | 荳ュ遲<EFBFBD> | 菴ソ逕ィCSS蜿倬㍼+OSS蝗セ迚ⅡRL |
| 譎コ閭ス霍ッ逕ア蛻<EFBFBD>書 | 邂蜊? | 蝓コ莠屍ole+tenantType逧<65>f-else |
11. 蠑蜿題オ<E9A18C>コ宣怙豎?
11.1 莠コ蜉幃怙豎?
- 蜷守ォッ蠑蜿托シ<EFBFBD> 1莠?テ<> 10螟ゥ<E89E9F><EFBDA9>hase 0-3<>?
- 蜑咲ォッ蠑蜿托シ<EFBFBD> 1莠?テ<> 7螟ゥ<E89E9F><EFBDA9>hase 3-5<>?
- *豬玖ッ包シ? 0.5莠?テ<> 3螟ゥ<E89E9F>磯寔謌先オ玖ッ包シ?
*諤サ隶。<EFBFBD>? 郤?0莠コ螟ゥ<E89E9F>育コヲ3蜻ィ<E89CBB><EFBDA8>
11.2 謚譛ッ萓晁オ?
譁ー蠅柤pm蛹<EFBFBD>シ<EFBFBD>
{
"dependencies": {
"jsonwebtoken": "^9.0.0",
"bcryptjs": "^2.4.3"
},
"devDependencies": {
"@types/jsonwebtoken": "^9.0.0",
"@types/bcryptjs": "^2.4.2"
}
}
12. 諤サ扈<EFBDBB>
12.1 譬ク蠢<EFBDB8>サ楢ョコ
- 蠖灘燕邉サ扈溷ョ悟<EFBFBD>豐。譛芽ョ、隸<EFBFBD>/謗域揀邉サ扈<EFBDBB> 笶?
- 謨ー謐ョ蠎捺怏荳、荳ェUser陦ィ<EFBFBD>碁怙扈滉ク 笞<><E7AC9E><EFBFBD>
- 蜑咲ォッ譚<EFBFBD>剞譯<EFBFBD>楔隶セ隶。螳悟埋<EFBFBD>御ス<EFBFBD>サ<EFBFBD>クコmock 笞<><E7AC9E><EFBFBD>
- *遘滓姐菴鍋ウサ螳悟<EFBFBD>郛コ螟ア<EFBFBD>碁怙莉朱峺蠑蜿? 笶?
12.2 莨伜<E88EA8>郤ァ蟒コ隶?
P0<EFBFBD><EFBFBD>eek 1-2<>会シ<E4BC9A> 謳ュ蟒コ蝓コ遑譫カ譫<EFBDB6>
- 謨ー謐ョ蠎鉄chema隶セ隶。 + 霑∫ァサ
- JWT隶、隸∫ウサ扈<EFBFBD>
- 隶、隸∽クュ髣エ莉?
- 逋サ蠖<EFBFBD>/逋サ蜃コ蜉溯<E89C89>
- 霑占是邂。逅<EFBFBD>ォッMVP<EFBFBD>育ァ滓姐邂。逅?蜩∫煙驟咲スョ<EFBDBD>?
P1<EFBFBD><EFBFBD>eek 3-4<>会シ<E4BC9A> 螳悟埋譬ク蠢<EFBDB8>粥閭ス
- Feature Flag邂。逅<EFBDA1>
- 遘滓姐荳灘ア樒匳蠖暮。?
- 譛コ譫<EFBFBD>ョ。逅<EFBFBD>ォッ<EFBFBD>亥現髯「迚茨シ<EFBFBD>
P2<EFBFBD><EFBFBD>eek 5+<2B>会シ<E4BC9A> 謇ゥ螻募粥閭ス
- 譛コ譫<EFBFBD>ョ。逅<EFBFBD>ォッ<EFBFBD>郁艮莨∫沿<EFBFBD><EFBFBD>
- 鬮倡コァ螳。隶。譌・蠢<EFBFBD>
- 譚<EFBFBD>剞扈<EFBFBD>イ貞コヲ謗ァ蛻?
12.3 荳倶ク豁・陦悟<E999A6>?
- 笨?**Review譛ャ謚・蜻?*<2A>檎。ョ隶、謚譛ッ譁ケ譯?
- 笨?**遑ョ螳壼シ蜿第賜譛?*<2A>亥サコ隶?蜻ィ蜀イ蛻コ<E89BBB><EFBDBA>
- 笨?蜷ッ蜉ィPhase 0<EFBFBD>壽焚謐ョ蠎楢。ィ扈滉ク蜥郡chema隶セ隶。
- 笨?**蟷カ陦悟星蜉ィ蜑咲ォッ逋サ蠖暮。オ隶セ隶?*<2A><>I隶セ隶。蟶茨シ<E88CA8>
9. <20><> Prompt邂。逅<EFBDA1>ウサ扈滓紛蜷<E7B49B>
9.1 荳コ莉荵<C280>rompt邂。逅<EFBDA1>弍霑占是邂。逅<EFBDA1>ォッ逧<EFBDAF><E980A7>鬲?
譬ケ謐ョ縲?2-騾夂畑閭ス蜉帛ア<E5B89B>03-Prompt邂。逅<EFBDA1>ウサ扈滉ク守<EFBDB8>蠎ヲ鬚<EFBDA6>ァ郁ョセ隶。譁ケ譯?md縲具シ<E585B7>Prompt邂。逅<EFBFBD>ク肴弍蜿ッ騾牙粥閭ス<EFBFBD>瑚梧弍霑占是邂。逅<EFBFBD>ォッ蟄伜惠逧<EFBFBD><EFBFBD>ク蠢<EFBFBD>炊逕ア荵倶ク縲?
*荳壼苅逞帷せ<EFBFBD>?
-
豬玖ッ慕識蠅<EFBFBD>裏豕墓ィ。諡溽悄螳樊焚謐ョ
- ASL逧<EFBFBD>枚迪ョ遲幃蛾怙隕?0遽<30>悄螳槫現蟄ヲ隶コ譁<EFBDBA>ェ瑚ッ∝㊥遑ョ邇<EFBDAE>
- DC逧<EFBFBD>焚謐ョ貂<EFBFBD>エ鈴怙隕∫悄螳樒羅蜴<EFBFBD>焚謐ョ鬪瑚ッ∵歓蜿匁譜譫?
- 豬玖ッ慕識蠅<EFBFBD>噪蛛<EFBFBD>焚謐ョ螳悟<EFBFBD>譌<EFBFBD>豕墓垓髴イPrompt逧<EFBFBD>悄螳樣琉鬚?
-
*蠖灘燕蠑蜿第オ∫ィ区譜邇<EFBFBD>栫菴?
- 豈乗ャ。隹<EFBFBD>紛Prompt髴隕<EFBFBD>シ壽隼莉」遐?竊?commit 竊?驛ィ鄂イ 竊?遲牙セ<E78999>AE驥榊星<E6A68A>育コヲ5蛻<35>帖<EFBFBD>?
- 荳エ蠎贋ク灘ョカ譌<EFBFBD>豕募盾荳手ー<EFBFBD>ッ包シ井サ紋サャ荳堺シ壼<EFBFBD>莉」遐<EFBFBD>シ?
- 譌<EFBFBD>豕募ソォ騾溯ソュ莉」<EFBFBD>御ク螟ゥ蜿ェ閭ス蟆晁ッ募<EFBFBD>谺?
-
*逕滉コァ莠区腐鬟朱勦鬮?
- 荳譌ヲPrompt蜿醍沿<EFBFBD>梧園譛臥畑謌キ遶句叉蜿怜スア蜩<EFBFBD>
- 豐。譛臥<EFBFBD>蠎ヲ譛コ蛻カ<EFBFBD>梧裏豕募ー剰激蝗エ鬪瑚ッ<EFBFBD>
*隗」蜀ウ譁ケ譯茨シ夂函莠ァ邇ッ蠅<EFBFBD><EFBFBD>蠎ヲ鬚<EFBFBD>ァ?
隹<EFBFBD>ッ戊<EFBFBD>シ蜷ッDebug讓。蠑丞錘<EFBFBD>瑚<EFBFBD>蜉ィ霍ッ逕ア蛻ーDRAFT迚<EFBFBD>rompt<EFBFBD>碁ェ瑚ッ<EFBFBD>夊ソ<EFBFBD>錘荳髞ョ蜿大ク<EFBFBD>クコACTIVE迚医?
9.2 Prompt邂。逅<EFBDA1>ウサ扈滓楔譫<E6A594>
*9.2.1 謨ー謐ョ蠎楢ョセ隶。<E99AB6><EFBDA1>apability_schema<6D>?
// --- Prompt Management System ---
model PromptTemplate {
id Int @id @default(autoincrement())
code String @unique // 蜚ッ荳譬<C280>ッ<EFBFBD>: 'ASL_SCREENING_TitleAbstract'
name String // 莠コ邀サ蜿ッ隸サ蜷咲ァー
module String // 謇螻樊ィ。蝮? ASL, DC, AIA, IIT
description String?
variables Json? // 鬚<>悄蜿倬㍼: ["title", "abstract"]
versions PromptVersion[]
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("prompt_templates")
@@schema("capability_schema")
}
model PromptVersion {
id Int @id @default(autoincrement())
templateId Int @map("template_id")
version Int // 迚域悽蜿?1, 2, 3...
content String @db.Text // Prompt蜀<74>ョケ<EFBDAE>域髪謖?andlebars讓。譚ソ<E8AD9A>?
modelConfig Json? // {"temperature": 0.1, "model": "deepseek-chat"}
status PromptStatus @default(DRAFT)
changelog String? // 菫ョ謾ケ隸エ譏<EFBDB4>
createdBy String? @map("created_by") // <20>剥 螳。隶。<E99AB6>夊ー∽ソョ謾ケ逧?
template PromptTemplate @relation(fields: [templateId], references: [id])
createdAt DateTime @default(now()) @map("created_at")
@@map("prompt_versions")
@@schema("capability_schema")
@@index([templateId, status]) // 鬮倬「第衍隸「莨伜喧
}
enum PromptStatus {
DRAFT // 闕臥ィソ<EFBDA8>井サ<E4BA95>ebug讓。蠑丞庄隗<E5BA84>シ?
ACTIVE // 郤ソ荳顔函謨茨シ磯サ倩ョ、<EFBDAE><EFBDA4>
ARCHIVED // 蠖呈。」
@@schema("capability_schema")
}
*9.2.2 譁ー蠅櫁ァ定牡荳取揀髯?
| 隗定牡 | 譚<EFBFBD>剞 Code | 隸エ譏<EFBFBD> |
|---|---|---|
| SUPER_ADMIN | prompt:* | 雜<EFBFBD>コァ邂。逅<EFBFBD>遭諡・譛画園譛画揀髯? |
| PROMPT_ENGINEER <20><> | prompt:view prompt:edit prompt:debug prompt:publish |
<EFBFBD>識 譬ク蠢<EFBFBD>ァ定牡<EFBFBD>壻ク謎ク啀rompt蟾・遞句ク域<EFBFBD>荳エ蠎贋ク灘ョカ |
| HOSPITAL_ADMIN | - | 譛コ譫<EFBFBD>ョ。逅<EFBFBD>遭譌<EFBFBD>Prompt譚<EFBFBD>剞 |
| PHARMA_ADMIN | - | 闕ッ莨∫ョ。逅<EFBFBD>遭譌<EFBFBD>Prompt譚<EFBFBD>剞 |
*譚<EFBFBD>剞隸ヲ隗」<EFBFBD>?
prompt:view- 譟・逵輝rompt蛻苓。ィ蜥悟紙蜿イ迚域<E8BF9A>?prompt:edit- 蛻帛サコ/菫ョ謾ケDRAFT迚域悽prompt:debug- 箝?譬ク蠢<EFBDB8>シ壼シ蜷ッ隹<EFBDAF>ッ墓ィ。蠑?prompt:publish- 蜿大クゥRAFT荳コACTIVE
*9.2.3 譬ク蠢<EFBDB8>橿譛ッ螳樒<E89EB3>?
A. PromptService<63>亥錘遶ッ<E981B6><EFBDAF>
// backend/src/common/capabilities/prompt/prompt.service.ts
export class PromptService {
private debugUsers = new Set<string>(); // 蜀<>ュ伜ュ伜お隹<E3818A>ッ慕畑謌キ
private activeCache = new Map<string, string>(); // ACTIVE迚域悽郛灘ュ<E78198>
/**
* 隶セ鄂ョ隹<EFBDAE>ッ墓ィ。蠑<EFBDA1>
* @requires Permission: prompt:debug
*/
async setDebugMode(userId: string, enabled: boolean) {
if (enabled) {
this.debugUsers.add(userId);
} else {
this.debugUsers.delete(userId);
}
}
/**
* 闔キ蜿鳳rompt<70>域<EFBFBD>ク蠢<EFBDB8><E8A0A2>蠎ヲ騾サ霎托シ?
*/
async get(code: string, variables: any, userId: string): Promise<string> {
// 1. 譽譟・譏ッ蜷ヲ荳コ隹<EFBDBA>ッ戊?
if (this.debugUsers.has(userId)) {
// 莨伜<E88EA8>闔キ蜿縫RAFT迚域悽
const draft = await this.getDraftVersion(code);
if (draft) {
return this.render(draft.content, variables);
}
}
// 2. 譎ョ騾夂畑謌キ謌匁裏DRAFT譌カ<E8AD8C>瑚執蜿泡CTIVE迚域悽
let active = this.activeCache.get(code);
if (!active) {
const version = await prisma.promptVersion.findFirst({
where: {
template: { code },
status: 'ACTIVE'
},
orderBy: { version: 'desc' }
});
active = version?.content || this.getFallback(code);
this.activeCache.set(code, active);
}
return this.render(active, variables);
}
/**
* Postgres LISTEN/NOTIFY 辜ュ譖エ譁?
*/
async initHotReload() {
const client = await pool.connect();
await client.query('LISTEN prompt_update');
client.on('notification', (msg) => {
console.log('[PromptService] Received update:', msg.payload);
this.activeCache.clear(); // 貂<>ゥコ郛灘ュ<E78198>
});
}
}
B. API遶ッ轤ケ隶セ隶。
| 譁ケ豕<EFBFBD> | 霍ッ蠕<EFBFBD> | 譚<EFBFBD>剞 | 謠剰ソー |
|---|---|---|---|
| GET | /api/admin/prompts | prompt:view | 闔キ蜿匁園譛臼rompt讓。譚ソ蛻苓。ィ |
| GET | /api/admin/prompts/:id | prompt:view | 闔キ蜿冶ッヲ諠<EFBFBD>シ亥性蜴<EFBFBD>彰迚域悽<EFBFBD>? |
| POST | /api/admin/prompts/draft | prompt:edit | 菫晏ュ倩拷遞ソ<EFBFBD>育函謌先眠迚域悽<EFBFBD>茎tatus=DRAFT<46>? |
| POST | /api/admin/prompts/publish | prompt:publish | 蜿大ク<EFBFBD>沿譛ャ<EFBFBD><EFBFBD>RAFT竊但CTIVE<EFBFBD>瑚ァヲ蜿鮮OTIFY<EFBFBD>? |
| POST | /api/admin/prompts/debug | prompt:debug | *蠑蜈ウ隹<EFBFBD>ッ墓ィ。蠑? |
*C. 蜑咲ォッ蜈ィ螻隹<C280>ッ募シ蜈?
// frontend-v2/src/modules/admin/components/PromptDebugSwitch.tsx
export const PromptDebugSwitch = () => {
const { hasPermission } = usePermission();
const [debugMode, setDebugMode] = useState(false);
// <20>白 譚<>剞謗ァ蛻カ<E89BBB>壻サ<E5A3BB>rompt:debug譚<67>剞逕ィ謌キ蜿ッ隗<EFBDAF>
if (!hasPermission('prompt:debug')) {
return null;
}
const handleToggle = async (enabled: boolean) => {
await api.post('/api/admin/prompts/debug', { enabled });
setDebugMode(enabled);
};
return (
<>
<Switch
checked={debugMode}
onChange={handleToggle}
checkedChildren="<22>菅 隹<>ッ墓ィ。蠑<EFBDA1>"
unCheckedChildren="逕滉コァ讓。蠑<EFBDA1>"
/>
{debugMode && (
<Alert
type="warning"
message="笞<><E7AC9E><EFBFBD> 隹<>ッ墓ィ。蠑丞キイ蠑蜷ッ<E89CB7>壽お蠖灘燕豁」蝨ィ菴ソ逕ィ闕臥ィソ迚茨シ<E88CA8>RAFT<46>画署遉コ隸<EFBDBA>"
banner
closable={false}
/>
)}
</>
);
};
9.3 豸牙所逧<E68980>園譛我ク壼苅讓。蝮?
譬ケ謐ョ譁<EFBFBD>。」隨?闃ゑシ碁怙隕 ̄rompt邂。逅<EFBDA1>噪讓。蝮暦シ<E69AA6>
| 讓。蝮<EFBFBD> | 譬ク蠢<EFBFBD>惻譎ッ | Prompt螟肴揩蠎? | 莨伜<EFBFBD>郤? |
|---|---|---|---|
| ASL | 譬<EFBFBD>「俶遭隕∝<EFBFBD>遲帙∝<EFBFBD>譁<EFBFBD>、咲ュ帙∬ッ∵紺蜷域<EFBFBD>? | 箝絶ュ絶ュ絶ュ絶ュ? | P0 |
| DC | Tool B謠仙叙縲ゝool C貂<43>エ励∝<C280>遯∵」豬? | 箝絶ュ絶ュ絶ュ絶ュ? | P0 |
| IIT | 雍ィ謗ァ譽譟・縲∵э蝗セ隸<EFBFBD>悪縲∵衍隸「逕滓<EFBFBD>? | 箝絶ュ絶ュ絶ュ絶ュ? | P1 |
| PKB | RAG髣ョ遲斐∵音螟<EFBFBD>炊髦<EFBFBD>ッサ | 箝絶ュ絶ュ絶ュ<EFBFBD> | P1 |
| AIA | 10+譎コ閭ス菴薙∵э蝗セ隸<EFBDBE><E99AB8>? | 箝絶ュ絶ュ? | P2 |
| RVW | 隗<EFBFBD>激諤ァ譽譟? | 箝絶ュ絶ュ? | P2 |
9.4 Prompt邂。逅<EFBDA1>シ蜿題ョ。蛻?
Phase 0: 蝓コ遑隶セ譁ス<E8AD81>?螟ゥ<E89E9F><EFBDA9>
- 蛻帛サコ
capability_schema逧Пrompt逶ク蜈ウ陦? - 豺サ蜉<EFBFBD>
prompt:*譚<EFBFBD>剞蛻ーplatform_schema.permissions - 蛻帛サコ
PROMPT_ENGINEER隗定牡 - 螳樒鴫
PromptService譬ク蠢<EFBFBD>サ霎<EFBFBD>
Phase 1: 霑占是遶ッMVP<56>?螟ゥ<E89E9F><EFBDA9>
- 蜑咲ォッ邂。逅<EFBFBD>阜髱「<EFBFBD>亥<EFBFBD>陦ィ縲∫シ冶セ大勣縲∫沿譛ャ蜴<EFBFBD>彰<EFBFBD><EFBFBD>
- 蜈ィ螻隹<EFBFBD>ッ募シ蜈ウ扈<EFBFBD>サ?
- 闕臥ィソ菫晏ュ<EFBFBD>/蜿大ク<E5A4A7>粥閭ス
Phase 2: 荳壼苅讓。蝮玲磁蜈・<E89C88>磯囂荳壼苅蠑蜿托シ<E68998>
- ASL遲幃画ィ。蝮苓ー<EFBFBD>畑
promptService.get() - DC謨ー謐ョ貂<EFBFBD>エ玲ィ。蝮苓ー<EFBFBD>畑
promptService.get() - 蜈カ莉匁ィ。蝮玲潔髴謗・蜈・
9.5 螳牙<E89EB3>荳朱」取<EFBDA3>?
-
譚<EFBFBD>剞髫皮ヲサ
- 荳・譬シ譽譟・
prompt:debug譚<EFBFBD>剞<EFBFBD>碁亟豁「譎ョ騾夂畑謌キ隸ッ蜈・隹<EFBFBD>ッ墓ィ。蠑? - 隹<EFBFBD>ッ墓ィ。蠑冗憾諤∝ュ伜お蝨ィ蜀<EFBFBD>ュ假シ育畑謌キ逋サ蜃コ閾ェ蜉ィ螟ア謨茨シ<EFBFBD>
- 荳・譬シ譽譟・
-
螳。隶。譌・蠢<EFBFBD>
PromptVersion.createdBy隶ー蠖穂ソョ謾ケ莠?AdminOperationLog隶ー蠖募書蟶<EFBFBD>。御クコ
-
蜈懷コ墓惻蛻カ
- 莉」遐∽クュ菫晉蕗Hardcoded Prompt菴應クコ邉サ扈溽コァ蜈懷コ?
- 謨ー謐ョ蠎捺衍隸「螟ア雍・譌カ霑泌屓鮟倩ョ、迚域悽
10. <20><> 蜿埼ヲ磯㊦郤ウ隸エ譏<EFBDB4>
10.1 驥<>コウ逧<EFBDB3><E980A7>髞ョ蟒コ隶?
蝓コ莠弱?2-騾夂畑閭ス蜉帛ア<E5B89B>10-譚<>剞菴鍋ウサ譴ウ逅<EFBDB3>渚鬥井ク惹ソョ豁」蟒コ隶?md縲具シ御サ・荳句サコ隶ョ蟾イ謨エ蜷亥芦譛ャ譁<EFBDAC>。」<EFBDA1><EFBDA3>
笨?*1. 蠅槫刈TenantQuotaAllocation陦ィ<E999A6><EFBDA8>0<EFBFBD>?
*蜴溷屏<EFBFBD>? PRD譏守。ョ隕∵アょ現髯「遶ッ謖臥ァ大ョ、/荳ェ莠コ蛻<EFBDBA><E89BBB>驟埼「<E59FBC>
*螳樊命<EFBFBD>? 蟾イ蝨ィ7.1.1遶<EFBFBD>闃よ眠蠅杼tenant_quota_allocations`陦?
model TenantQuotaAllocation {
targetType String // 'DEPARTMENT' | 'USER'
targetKey String // DepartmentID 謌?UserID
limitAmount BigInt // 蛻<><E89BBB>逧<EFBFBD>「晏コ?
usedAmount BigInt // 蟾イ菴ソ逕?
}
笨?*2. 陦ィ蜷肴隼荳コTenantMember<65><72>1<EFBFBD>?
*蜴溷屏<EFBFBD>? "Member"隸ュ荵牙シコ隹<EFBDBA>サ<EFBFBD>サ<EFBFBD><EFBDBB>邉サ<E98289>?User"騾壼クク謖<EFBDB8>匳蠖戊エヲ蜿キ螳樔ス?
*螳樊命<EFBFBD>? 蟾イ蟆<EFBDB2>TenantUser謾ケ荳コTenantMember`
笨?*3. 螳。隶。譌・蠢怜「槫刈module蟄玲ョオ<EFBDAE><EFBDB5>1<EFBFBD>?
*蜴溷屏<EFBFBD>? 闕ッ莨∫ォッ髴隕∵衍隸「IIT讓。蝮嶺ク灘ア樊律蠢暦シ<E69AA6>DA 21 CFR Part 11蜷郁ァ<E98381>シ?
*螳樊命<EFBFBD>? 蟾イ蝨ィAdminOperationLog陦ィ蠅槫刈module蟄玲ョオ蜥檎エ「蠑?
笨?*4. Prompt蟾・遞句喧譚<E596A7>剞<EFBFBD><E5899E>0<EFBFBD>?
*蜴溷屏<EFBFBD>? 霑占是邂。逅<EFBDA1>ォッ譬ク蠢<EFBDB8>粥閭?
*螳樊命<EFBFBD>? 蟾イ蝨ィ隨?遶<>螳梧紛隶セ隶。Prompt邂。逅<EFBDA1>ウサ扈<EFBDBB>
笨?*5. 雜<>コァ邂。逅<EFBDA1>遭遘榊ュ先焚謐ョ<E8AC90><EFBDAE>0<EFBFBD>?
*蜴溷屏<EFBFBD>? 蜷ヲ蛻咏ウサ扈滉ク顔コソ蜷取裏豕戊ソ帛<EFBDBF>蜷主<E89CB7>?
*螳樊命<EFBFBD>? 蟆<>惠Phase 0螳樒鴫Prisma Seed閼壽悽
笨?*6. Phase 0蝗樊サ壽婿譯茨シ<E88CA8>0<EFBFBD>?
*蜴溷屏<EFBFBD>? 謨ー謐ョ螳牙<E89EB3>蝓コ譛ャ蜴溷<E89CB4>
*螳樊命<EFBFBD>? 霑∫ァサ閼壽悽蟆<E682BD><E89F86>驥榊多蜷港public.users荳コpublic.users_backup`<60>御ソ晉<EFBDBF>?蜻?
笨?*7. 遘滓姐驟咲スョAPI郛灘ュ假シ<E58187>1<EFBFBD>?
*蜴溷屏<EFBFBD>? 豈丈クェ逕ィ謌キ謇灘シ逋サ蠖暮。オ驛ス莨夊ー<E5A48A>畑<EFBFBD>碁ォ伜ケカ蜿台ク矩怙隕∫シ灘ュ?
*螳樊命<EFBFBD>? 蟆<>惠螳樊命譌カ豺サ蜉<EFBDBB>Cache-Control: public, max-age=3600
10.2 蜷守サュ謾ケ霑帛サコ隶ョ
莉・荳句サコ隶ョ證ゆク榊惠MVP髦カ谿オ螳樊命<EFBFBD>御ス<EFBFBD><EFBFBD>蜈・謚譛ッ蛟コ蜉。貂<EFBFBD>黒<EFBFBD>?
<EFBFBD>売 *1. JWT螳牙<E89EB3>諤ァ<E8ABA4><EFBDA7>2<EFBFBD>?
*蟒コ隶ョ<EFBFBD>? 菴ソ逕ィHttpOnly Cookie譖ソ莉」localStorage
*逅<EFBFBD>罰<EFBFBD>? localStorage螳ケ譏灘女XSS謾サ蜃サ
*隶。蛻抵シ? 蝨ィ闕ッ莨∫ォッ荳顔コソ蜑搾シ磯怙譖エ鬮伜ョ牙<EFBDAE>諤ァ<E8ABA4>牙ョ樊命
<EFBFBD>売 *2. Prisma Extension螟夂ァ滓姐髫皮ヲサ<EFBDA6><EFBDBB>1<EFBFBD>?
*蟒コ隶ョ<EFBFBD>? 蝨ィORM螻ょシコ蛻カ蜉<EFBDB6>蜈・tenantId霑<EFBFBD>サ、
*逅<EFBFBD>罰<EFBFBD>? 髦イ豁「蠑蜿台ココ蜻伜ソ倩ョー蝨ィController螻ょ刈荳ュ髣エ莉?
*隶。蛻抵シ? Phase 2蠑募<E8A091>
const prismaExtended = prisma.$extends({
query: {
$allModels: {
async findMany({ args, query }) {
args.where = { ...args.where, tenantId: currentTenantId };
return query(args);
}
}
}
});
10.3 蜿埼ヲ郁エィ驥剰ッ<E589B0>サキ
*諤サ菴楢ッ<EFBFBD>シー<EFBFBD>? 莨倡ァ 箝絶ュ絶ュ絶ュ絶ュ?
- 笨?9譚。蟒コ隶ョ荳ュ<E88DB3>?譚。遶句叉驥<E58F89>コウ<EFBDBA><EFBDB3>2譚。郤ウ蜈・蜷守サュ隶。蛻?
- 笨?蜿醍鴫莠<E9B4AB><E88EA0>鬚晏<E9AC9A>驟肴ィ。蝙狗噪隶セ隶。郛コ髯キ<E9ABAF><EFBDB7>ritical<61>?
- 笨?蠑コ隹<EFBDBA>コ<EFBFBD>rompt邂。逅<EFBDA1>噪譬ク蠢<EFBDB8>慍菴?
- 笨?謠仙<E8ACA0>莠<EFBFBD>ョ樒畑逧<E79591>キ・遞句ョ櫁キオ蟒コ隶ョ<E99AB6>亥屓貊壽婿譯医∫ァ榊ュ先焚謐ョ<E8AC90><EFBDAE>
*扈楢ョコ<EFBFBD>? 譁<>。」雍ィ驥城ォ假シ碁」朱勦蜿ッ謗ァ<E8AC97>?*蜿ッ莉・蠑蟋句シ蜿?*縲?
謚・蜻雁ョ梧ッ輔ょ㊥螟<EFBFBD>・ス蠑蟋句シ蜿台コ<EFBFBD>雛<EFBFBD><EFBFBD> <20>噫