本卡屬 FR-090(母卡 CM-1682)第 4 棒。動
common/util/audit_nickname.py、module_frame 三支、flow_engine 一支、SOP。中量驗證。與第 3 棒並行(不重疊)。
「把帳號換成暱稱顯示」這件事,主專案有三種做法並存:一支共用 helper(15 個 consumer)、三支跟 helper 逐字相同的手寫複本、一支 DTO 收 map 由 service 算。而 D8 標準件 jedi_common.identity.IdentityContext(2026-08-30 落地,jedi-asset 已用)主專案 app/ 零處使用。共用 helper 本身是 D8 之前的土製版,直接 import jedi-iam 的 UserDomainService 與 UserQueryEntity 去查。本卡讓 helper 內部改走 IdentityContext,三支複本與 flow_engine 改呼叫 helper,主專案就只剩一條路。
首腦核對(2026-09-12):
common/util/audit_nickname.py:三個函式 enrich_audit_nicknames(dict list)/enrich_audit_nickname_one/enrich_audit_nickname_objs(物件 list),都收 user_domain_service 參數,內部 user_domain_service.get_users(UserQueryEntity(_in_login_name=...))。15 個 consumer:app/auth/service/{user,role}_app_service.py(第 3 棒會刪這兩處)、app/project_summary_report/service/project_summary_report_service.py、app/oscal/service/ssp_{inventory_items,system_characteristic,leveraged,components}_app_service.py、app/module_frame/service/module_frame_{leveraged,components,system_characteristic,inventory}_service.py、api/survey/__init__.py、infra/participant/user_directory_adapter.py、infra/survey/adapters.py、di_containers/survey/survey_containers.py。_enrich_nicknames:app/module_frame/service/module_frame_reference_document_service.py:259、module_frame_control_default_service.py:242、module_frame_control_objective_default_service.py:260。三支邏輯與 helper 的 enrich_audit_nickname_objs 逐字相同,各自收 user_domain_service 建構子參數。app/flow_engine/dto/flow_template_dto.py:25 收 user_nickname_map,由 app/flow_engine/service/flow_template_app_service.py:56/64 算 map 傳入。app/flow_control/service/project_service.py:315(查受評標的負責人 uid → 暱稱,不是 created_user);app/feedback/dto/feedback_issue_dto.py:27(entity 從 DB 帶上來的欄位)。IdentityContext 的介面:resolve_user_names(login_names: Iterable[str]) -> dict[str, str],內建去重與降級。主專案的 resolver 實作 infra/identity/user_name_resolver.py(UserNameResolver(label),延遲從 app.extensions 取 UserDomainService)。DI 已有兩處建 IdentityContext(di_containers/asset/、di_containers/bulletin/),各自 Singleton。主專案:/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/
common/util/audit_nickname.py 內部改走 IdentityContext;簽名保留相容
app/module_frame/service/module_frame_reference_document_service.py:259 _enrich_nicknames 刪,改呼叫 helper
app/module_frame/service/module_frame_control_default_service.py:242 同上
app/module_frame/service/module_frame_control_objective_default_service.py:260 同上
app/flow_engine/dto/flow_template_dto.py:25 user_nickname_map 參數拿掉
app/flow_engine/service/flow_template_app_service.py:56,64 改呼叫 helper
di_containers/containers.py 或新建 di_containers/identity_containers.py 一個共用 identity provider
docs/features/FR-069-2608-jedi-module-extraction/extraction-sop.md §5 統一規則
docs/claude/domain-capabilities.md helper 登記為 canonical
IdentityContext Singleton。收成一個:在 di_containers/containers.py 頂層建 identity = providers.Singleton(IdentityContext, user_name_resolver=providers.Singleton(UserNameResolver, label="主專案")),asset/bulletin container 改用 DependenciesContainer 接它。先查 UserNameResolver 的 label 是否影響行為(只是 log 標籤就可以統一)。audit_nickname.py 三個函式的第一個參數從 user_domain_service 改成 identity,內部 identity.resolve_user_names(login_names) 取代 get_users(UserQueryEntity(...));identity is None 時補 None(與原本一致)。拔掉 from jedi_iam... 兩行 import——這是本卡的核心:主專案 common/ 不該認識 jedi-iam 的查詢實體。user_domain_service,改成傳 identity。逐一改(建構子參數名、DI provider)。批次做完再驗,不要改一支測一支。enrich_audit_nickname_objs 與 jedi-asset/jedi-iam 的 _audit_names.fill_user_names 邏輯相同。本卡不把它搬進 jedi-common(那是套件異動,另案),但在 docstring 留一行「與套件內 _audit_names.fill_user_names 同型,日後收進 jedi-common」。_enrich_nicknames 方法,呼叫處改 enrich_audit_nickname_objs(self._identity, dtos);建構子 user_domain_service 參數改 identity;di_containers/module_frame/ 對應 provider 改。