Files
AIclinicalresearch/docs/03-业务模块/ADMIN-运营管理端/00-系统设计/00-权限与角色体系梳理报告_v1.0.md
HaHafeng 1b53ab9d52 feat(aia): Complete AIA V2.0 with universal streaming capabilities
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%)
2026-01-14 19:15:01 +08:00

40 KiB
Raw Blame History

*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>

  1. [蠖灘燕邉サ扈溽憾諤∝<E8ABA4>譫疹(#1-蠖灘燕邉サ扈溽憾諤∝<E8ABA4>譫?
  2. [謨ー謐ョ蠎灘アる擇譴ウ逅<EFBDB3>(#2-謨ー謐ョ蠎灘アる擇譴ウ逅?
  3. [蜷守ォッ譚<EFBDAF>剞螳樒鴫譴ウ逅<EFBDB3>(#3-蜷守ォッ譚<EFBDAF>剞螳樒鴫譴ウ逅<EFBDB3>)
  4. [蜑咲ォッ譚<EFBDAF>剞螳樒鴫譴ウ逅<EFBDB3>(#4-蜑咲ォッ譚<EFBDAF>剞螳樒鴫譴ウ逅<EFBDB3>)
  5. [蟾ョ霍晏<E99C8D>譫疹(#5-蟾ョ霍晏<E99C8D><EFBFBD>)
  6. [譁ーPRD髴€豎りァ」隸サ](#6-譁ーprd髴€豎りァ」隸?
  7. 譫カ譫<EFBFBD>ョセ隶。蟒コ隶ョ
  8. [螳樊命霍ッ郤ソ蝗セ](#8-螳樊命霍ッ郤ソ蝗?
  9. [<5B><> Prompt邂。逅<EFBDA1>ウサ扈滓紛蜷<E7B49B>(#9-prompt邂。逅<EFBDA1>ウサ扈滓紛蜷<E7B49B>)
  10. [<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>?

  1. 豐。譛臥匳蠖<EFBFBD>/豕ィ蜀窟PI
  2. *豐。譛雨WT隶、隸∽クュ髣エ莉?
  3. 豐。譛臥ァ滓姐(Tenant)菴鍋ウサ
  4. 豐。譛芽ァ定牡譚<EFBFBD>剞邉サ扈<EFBFBD>(RBAC)
  5. 豐。譛宇eature Flag謗ァ蛻カ
  6. 豐。譛牙ョ。隶。譌・蠢礼ウサ扈<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 陦?
  • *莉サ蜉。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
  • *Day 3<>? 螳樒鴫隶、隸∽クュ髣エ莉?

    • requireAuth
    • requireRole
    • requireTenantAccess
    • 蠎皮畑蛻ー邇ー譛鵜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>サ楢ョコ

  1. 蠖灘燕邉サ扈溷ョ悟<EFBFBD>豐。譛芽ョ、隸<EFBFBD>/謗域揀邉サ扈<EFBDBB> 笶?
  2. 謨ー謐ョ蠎捺怏荳、荳ェUser陦ィ<EFBFBD>碁怙扈滉ク€<><E7AC9E><EFBFBD>
  3. 蜑咲ォッ譚<EFBFBD>剞譯<EFBFBD>楔隶セ隶。螳悟埋<EFBFBD>御ス<EFBFBD><EFBFBD>クコmock<><E7AC9E><EFBFBD>
  4. *遘滓姐菴鍋ウサ螳悟<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>?

  1. 笨?**Review譛ャ謚・蜻?*<2A>檎。ョ隶、謚€譛ッ譁ケ譯?
  2. 笨?**遑ョ螳壼シ€蜿第賜譛?*<2A>亥サコ隶?蜻ィ蜀イ蛻コ<E89BBB><EFBDBA>
  3. 笨?蜷ッ蜉ィPhase 0<EFBFBD>壽焚謐ョ蠎楢。ィ扈滉ク€蜥郡chema隶セ隶。
  4. 笨?**蟷カ陦悟星蜉ィ蜑咲ォッ逋サ蠖暮。オ隶セ隶?*<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>?

  1. 豬玖ッ慕識蠅<EFBFBD>裏豕墓ィ。諡溽悄螳樊焚謐ョ

    • ASL逧<EFBFBD>枚迪ョ遲幃€蛾怙隕?0遽<30>悄螳槫現蟄ヲ隶コ譁<EFBDBA>ェ瑚ッ∝㊥遑ョ邇<EFBDAE>
    • DC逧<EFBFBD>焚謐ョ貂<EFBFBD>エ鈴怙隕∫悄螳樒羅蜴<EFBFBD>焚謐ョ鬪瑚ッ∵歓蜿匁譜譫?
    • 豬玖ッ慕識蠅<EFBFBD>噪蛛<EFBFBD>焚謐ョ螳悟<EFBFBD><EFBFBD>豕墓垓髴イPrompt逧<EFBFBD>悄螳樣琉鬚?
  2. *蠖灘燕蠑€蜿第オ∫ィ区譜邇<EFBFBD>栫菴?

    • 豈乗ャ。隹<EFBFBD>紛Prompt髴€<EFBFBD>シ壽隼莉」遐?竊?commit 竊?驛ィ鄂イ 竊?遲牙セ<E78999>AE驥榊星<E6A68A>育コヲ5蛻<35><EFBFBD>?
    • 荳エ蠎贋ク灘ョカ譌<EFBFBD>豕募盾荳手ー<EFBFBD>ッ包シ井サ紋サャ荳堺シ壼<EFBFBD>莉」遐<EFBFBD>シ?
    • <EFBFBD>豕募ソォ騾溯ソュ莉」<EFBFBD>御ク€螟ゥ蜿ェ閭ス蟆晁ッ募<EFBFBD>谺?
  3. *逕滉コァ莠区腐鬟朱勦鬮?

    • €譌ヲ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>

  1. 蛻帛サコcapability_schema逧Пrompt逶ク蜈ウ陦?
  2. 豺サ蜉<EFBFBD>prompt:*<EFBFBD>剞蛻ーplatform_schema.permissions
  3. 蛻帛サコPROMPT_ENGINEER隗定牡
  4. 螳樒鴫PromptService譬ク蠢<EFBFBD>€サ霎<EFBFBD>

Phase 1: 霑占是遶ッMVP<56>?螟ゥ<E89E9F><EFBDA9>

  1. 蜑咲ォッ邂。逅<EFBFBD>阜髱「<EFBFBD><EFBFBD>陦ィ縲∫シ冶セ大勣縲∫沿譛ャ蜴<EFBFBD><EFBFBD><EFBFBD>
  2. 蜈ィ螻€<EFBFBD>ッ募シ€蜈ウ扈<EFBFBD>サ?
  3. 闕臥ィソ菫晏ュ<EFBFBD>/蜿大ク<E5A4A7>粥閭ス

Phase 2: 荳壼苅讓。蝮玲磁蜈・<E89C88>磯囂荳壼苅蠑€蜿托シ<E68998>

  • ASL遲幃€画ィ。蝮苓ー<EFBFBD>promptService.get()
  • DC謨ー謐ョ貂<EFBFBD>エ玲ィ。蝮苓ー<EFBFBD>promptService.get()
  • 蜈カ莉匁ィ。蝮玲潔髴€謗・蜈・

9.5 螳牙<E89EB3>荳朱」取<EFBDA3>?

  1. <EFBFBD>剞髫皮ヲサ

    • 荳・譬シ譽€譟・prompt:debug<EFBFBD><EFBFBD>碁亟豁「譎ョ騾夂畑謌キ隸ッ蜈・隹<EFBFBD>ッ墓ィ。蠑?
    • <EFBFBD>ッ墓ィ。蠑冗憾諤∝ュ伜お蝨ィ蜀<EFBFBD>ュ假シ育畑謌キ逋サ蜃コ閾ェ蜉ィ螟ア謨茨シ<EFBFBD>
  2. 螳。隶。譌・蠢<EFBFBD>

    • PromptVersion.createdBy隶ー蠖穂ソョ謾ケ莠?
    • AdminOperationLog隶ー蠖募書蟶<EFBFBD>。御クコ
  3. 蜈懷コ墓惻蛻カ

    • 莉」遐∽クュ菫晉蕗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>