本卡屬 FR-091(母卡 CM-1690)第三批。重:32 條 route、ctx() 63 處、22 個 entity、14 張表、施工日誌 64 處,是 route 最多的一支。**STATE §3 說 survey 要「拔 repo 層 JOIN users 並開 identity port」——實查 CM-1512 已把 JOIN 拔掉改走
IAuditNicknameEnricherport,且infra/repository/identity_enrichment.py已是名冊 mixin;剩下的是survey_discussion_service.py一處直接 importjedi_iam.UserDomainService,以及IAuditNicknameEnricher這張套件自己的 port 與 D8identity標準件並存。本卡把它們收成一條:D8 identity。**主專案接線在core/plugins/survey.py(CM-1689)與infra/survey/adapters.py(守衛白名單例外),本卡只動 adapters 那支的 import。
jedi-survey(問卷設計、填答、討論)是 route 最多的套件:plugin.py 378 行 6 dataclass;api/init.py 135 行含兩組路由表(設計端/填答端)與 ctx(),api/guard.py 另放 license 守門;ctx() 在五支 route 檔共 63 處;logger 23 處 __name__(log 落不到 app.log);22 個 entity 全非 dataclass;64 處施工日誌。暱稱補名走三條路:套件自己的 IAuditNicknameEnricher port(主專案 infra/survey/adapters.py 實作)、identity_enrichment.py mixin 走 jedi-participant 的 IUserDirectory、survey_discussion_service 直接 import jedi_iam。三條收成 D8 identity 一條。
首腦核對(2026-09-13):plugin.py 378 行 6 dataclass;api/init.py 135 行(ctx 4+兩個 mount 函式)+guard.py(configure/is_wired/require_license);route 32;ctx() 63(survey_route 14、question 9、page 7、folder 7、task_survey 6、plugin 4 等);entity 檔 22(0 dataclass);表 14 張(含 4 張 _trans 翻譯表);migration 0;tests 320 支(無 integration);harness 無;施工日誌 64 處;logger common.jedi_survey 8/__name__ 23/_audit_logger_name 1;jedi_iam import:survey_discussion_service.py:1(UserDomainService)+ route 五處 from jedi_iam.authz import require_capability(這五處是 FR-069 P8 裁定的合法依賴,jedi_iam.authz 是身分疆界標準件,不拔);tests/...:25 _PKG_ROOT = Path(__file__).parent.parent / "jedi_survey"(不中 plugin 坑,不用改)。主專案 20 檔 import;venv 指工作樹。
套件:/Users/chouraymond/Projects/Jedicogy/module/jedi-python-package/jedi-survey/
domain/ports.py:65 IAuditNicknameEnricher(要退役改 D8 identity)
infra/repository/identity_enrichment.py(mixin,走 jedi-participant IUserDirectory;審計姓名那半改走 identity,部門那半保留)
app/service/survey_discussion_service.py:1(拔 jedi_iam,改 identity.resolve_user_names)
api/routes/*.py 的 `from jedi_iam.authz import require_capability`(合法,不動)
identity 範例:jedi-asset plugin/contract.py:83+app/service/_audit_names.py;jedi-iam CM-1686 1668abb
SOP:extraction-sop.md §4.3/§3.4/§8;說明:plugin-anatomy.md
主專案(本卡允許動的):
infra/survey/adapters.py(IAuditNicknameEnricher 的實作——port 退役後此檔內容改成把 identity 塞進 adapters 或整支刪,守衛白名單 `_PORT_IMPL_ALLOWED_OUTSIDE_PLUGINS` 那列跟著處理)
core/plugins/survey.py(build_adapters 加 identity=container.identity_container.identity())
di_containers/survey/(只改 import)
順收三處 evidence-classification 死引用:di_containers/containers.py:396 註解、scripts/gen_postman_collection.py:399 的 ("api.evidence_classification", ...) 那列、infra/survey/adapters.py:11 註解
主專案 import 面:grep -rn "from jedi_survey\|import jedi_survey" compliance-manager-be --include='*.py' --exclude-dir=.venv(20 檔,含 socketio handler)
plugin.py → plugin/ 五檔(無 migration);api/__init__.py+api/guard.py → guards.py(runtime()+license 守門的 lazy decorator,require_license/configure/is_wired 對外名字不變)+routing.py(設計端/填答端兩張表分兩段,mount_design_routes/mount_answer_routes 名字保留)。socketio 模式只掛填答那段的邏輯要保住(core/plugins/survey.py 靠它)。對外 import 一字不改,20 檔 AST 掃逐一實跑。rt);logger 23 處 __name__ 改 common.jedi_survey;暱稱三條收一條:plugin/contract.py Adapters 加 identity(D8);domain/ports.py 的 IAuditNicknameEnricher 退役(刪,或留 deprecated shim 一版由 runner 判斷回寫);survey_app_service 改用 _audit_names.fill_user_names(dtos, identity);identity_enrichment.py 審計姓名那半改走 identity(部門那半仍走 participant IUserDirectory,那是部門名冊不是 identity);survey_discussion_service.py 拔 UserDomainService,改 identity.resolve_user_names。疆界守衛突變:加回 from jedi_iam.domain... → 紅(jedi_iam.authz 仍在白名單,jedi_iam.domain 不在)。inspect.signature 逐欄對照;翻譯表相關 entity 的 locale 欄預設值要特別對。harness/(compose+dev_app.py --smoke:test client 打設計端一條 401/200、填答端一條、斷言 created_user_name 由假 identity 補上);pyproject.toml 加 addopts = "--import-mode=importlib";README 補新結構、identity 接法、socketio 模式說明。core/plugins/survey.py 填 identity=;infra/survey/adapters.py 依 port 退役結果處理並更新守衛白名單;di_containers/survey 改 import;順收三處 evidence-classification 死引用(兩處註解改文字、gen_postman 那列刪掉或改指 core/plugins)。jedi_iam.domain 的突變。tests/integration/test_service_behaviour.py(目錄新建,14 張表用 Base.metadata.create_all):建資料夾→問卷→頁→題→填答→歷史一輪,翻譯表 failover 讀取一次。