{ "module": "pbl_scense_ext", "milestone": "M9(覆盖层前端与页面注册)", "note": "pbl_scense_ext 26 条 RBAC 路径权限种子清单(M9-收口C,消 P-1/P-2 pending=26)。逐条显式登记,禁止 % / * 通配符(module-development-spec 硬门禁 6.6)。消费端:scripts/m9c_rbac_seed.py(--check 离线三方一致性校验 / --emit-sql 出幂等 SQL / --apply 连库幂等导入 permission+rolepermission,id 用 path/role 的 md5 派生);scripts/rbac_set_perm.py 作为 scripts/load_path.py register() 的 RBAC_SET_PERM 工具,使 'rbac paths: total=26 ok=26 pending=0'。traceability 中函数名/文件/行号均为 grep 实测值(沿用 pbl_runtime_ext b54ff00 做法)。", "source_of_truth": "scripts/load_path.py PATHS(26 条,22 logined + 4 any)", "default_role": "logined", "permissions": [ { "name": "pbl_session_context_get", "path": "/pbl_scense_ext/api/pbl_session_context_get.dspy", "kind": "api", "role": "logined", "endpoint": "wwwroot/api/pbl_session_context_get.dspy", "milestone": "M9", "title": "会话上下文读取(租户/世界/角色)", "traceability": "pbl_scense_ext/api.py::pbl_session_context_get(api.py:102)→ __init__.py:9 → init.py:20 env 挂载 → wwwroot/api/pbl_session_context_get.dspy → load_path.py PATHS[0]" }, { "name": "pbl_page_registry_list", "path": "/pbl_scense_ext/api/pbl_page_registry_list.dspy", "kind": "api", "role": "logined", "endpoint": "wwwroot/api/pbl_page_registry_list.dspy", "milestone": "M9", "title": "覆盖层 12 页面注册表(含渲染时延预算)", "traceability": "pbl_scense_ext/api.py::pbl_page_registry_list(api.py:46,读 PAGES api.py:16)→ __init__.py:10 → init.py:21 → wwwroot/api/pbl_page_registry_list.dspy → load_path.py PATHS[1]" }, { "name": "pbl_playtest_feedback_save", "path": "/pbl_scense_ext/api/pbl_playtest_feedback_save.dspy", "kind": "api", "role": "logined", "endpoint": "wwwroot/api/pbl_playtest_feedback_save.dspy", "milestone": "M9", "title": "Playtest 反馈/反思落库", "traceability": "pbl_scense_ext/api.py::pbl_playtest_feedback_save(api.py:113)→ __init__.py:11 → init.py:22 → wwwroot/api/pbl_playtest_feedback_save.dspy → load_path.py PATHS[2]" }, { "name": "pbl_overlay_bootstrap", "path": "/pbl_scense_ext/api/pbl_overlay_bootstrap.dspy", "kind": "api", "role": "logined", "endpoint": "wwwroot/api/pbl_overlay_bootstrap.dspy", "milestone": "M9", "title": "覆盖层启动上下文(bootstrap)", "traceability": "pbl_scense_ext/api.py::pbl_overlay_bootstrap(api.py:62)→ __init__.py:12 → init.py:23 → wwwroot/api/pbl_overlay_bootstrap.dspy → load_path.py PATHS[3]" }, { "name": "pbl_scense_ext_root", "path": "/pbl_scense_ext", "kind": "page", "role": "logined", "endpoint": "wwwroot/index.ui(模块根目录路由,indexes=index.ui)", "milestone": "M9", "title": "pbl_scense_ext 模块入口(目录路由)", "traceability": "wwwroot/index.ui(由 wwwroot 软链挂载,apps/pbls build.sh 第 5 步)→ load_path.py PATHS[4]" }, { "name": "pbl_scense_ext_index_ui", "path": "/pbl_scense_ext/index.ui", "kind": "page", "role": "logined", "endpoint": "wwwroot/index.ui", "milestone": "M9", "title": "pbl_scense_ext 入口页壳", "traceability": "wwwroot/index.ui → load_path.py PATHS[5]" }, { "name": "pbl_overlay_loader_js", "path": "/pbl_scense_ext/overlay/pbl_overlay_loader.js", "kind": "static", "role": "any", "endpoint": "wwwroot/overlay/pbl_overlay_loader.js", "milestone": "M9", "title": "覆盖层脚本/CSS 注入器 + 运行时 i18n(预鉴权页壳首屏)", "traceability": "wwwroot/overlay/pbl_overlay_loader.js:2(FILES L51 注入 core/transport/play;I18N_DIR L48 fetch msg.txt)→ load_path.py PATHS[6](any,QC #1/#6)" }, { "name": "pbl_overlay_css", "path": "/pbl_scense_ext/overlay/pbl_overlay.css", "kind": "static", "role": "any", "endpoint": "wwwroot/overlay/pbl_overlay.css", "milestone": "M9", "title": "覆盖层主题 CSS(页壳首屏样式,不含业务数据)", "traceability": "wwwroot/overlay/pbl_overlay.css → load_path.py PATHS[7](any,QC #1)" }, { "name": "pbl_overlay_core_js", "path": "/pbl_scense_ext/overlay/pbl_overlay_core.js", "kind": "static", "role": "logined", "endpoint": "wwwroot/overlay/pbl_overlay_core.js", "milestone": "M9", "title": "覆盖层业务内核 JS(登录后由 loader 注入)", "traceability": "wwwroot/overlay/pbl_overlay_loader.js FILES L51 → wwwroot/overlay/pbl_overlay_core.js → load_path.py PATHS[8](logined)" }, { "name": "pbl_overlay_transport_js", "path": "/pbl_scense_ext/overlay/pbl_overlay_transport.js", "kind": "static", "role": "logined", "endpoint": "wwwroot/overlay/pbl_overlay_transport.js", "milestone": "M9", "title": "覆盖层广播/意图通道 JS", "traceability": "wwwroot/overlay/pbl_overlay_loader.js FILES L51 → wwwroot/overlay/pbl_overlay_transport.js → load_path.py PATHS[9](logined)" }, { "name": "pbl_overlay_play_js", "path": "/pbl_scense_ext/overlay/pbl_overlay_play.js", "kind": "static", "role": "logined", "endpoint": "wwwroot/overlay/pbl_overlay_play.js", "milestone": "M9", "title": "覆盖层装配 JS(世界内 5 页)", "traceability": "wwwroot/overlay/pbl_overlay_loader.js FILES L51 → wwwroot/overlay/pbl_overlay_play.js → load_path.py PATHS[10](logined)" }, { "name": "pbl_overlay_i18n_zh", "path": "/pbl_scense_ext/i18n/zh/msg.txt", "kind": "static", "role": "any", "endpoint": "wwwroot/i18n/zh/msg.txt", "milestone": "M9", "title": "覆盖层中文文案表(运行时 i18n 单一事实源)", "traceability": "wwwroot/overlay/pbl_overlay_loader.js loadLang()(I18N_DIR L48)→ wwwroot/i18n/zh/msg.txt;生成期同源校验 scripts/gen_overlay_pages.py::load_msg(gen_overlay_pages.py:90)→ load_path.py PATHS[11](any,QC #6)" }, { "name": "pbl_overlay_i18n_en", "path": "/pbl_scense_ext/i18n/en/msg.txt", "kind": "static", "role": "any", "endpoint": "wwwroot/i18n/en/msg.txt", "milestone": "M9", "title": "覆盖层英文文案表(运行时 i18n 单一事实源)", "traceability": "wwwroot/overlay/pbl_overlay_loader.js loadLang()(I18N_DIR L48)→ wwwroot/i18n/en/msg.txt;生成期同源校验 scripts/gen_overlay_pages.py::load_msg(gen_overlay_pages.py:90)→ load_path.py PATHS[12](any,QC #6)" }, { "name": "pbl_overlay_page_home", "path": "/pbl_scense_ext/pbl_overlay/home.ui", "kind": "page", "role": "logined", "endpoint": "wwwroot/pbl_overlay/home.ui", "milestone": "M9", "title": "PBL 首页(覆盖层页壳)", "traceability": "scripts/gen_overlay_pages.py PAGES(gen_overlay_pages.py:72)→ wwwroot/pbl_overlay/home.ui;运行时路由 pbl_scense_ext/api.py PAGES[0](api.py:17)→ load_path.py PATHS[13]" }, { "name": "pbl_overlay_page_blueprint_list", "path": "/pbl_scense_ext/pbl_overlay/blueprint_list.ui", "kind": "page", "role": "logined", "endpoint": "wwwroot/pbl_overlay/blueprint_list.ui", "milestone": "M9", "title": "蓝图列表(覆盖层页壳)", "traceability": "scripts/gen_overlay_pages.py PAGES(gen_overlay_pages.py:72)→ wwwroot/pbl_overlay/blueprint_list.ui;运行时路由 api.py PAGES[1](api.py:18)→ load_path.py PATHS[14]" }, { "name": "pbl_overlay_page_blueprint_editor", "path": "/pbl_scense_ext/pbl_overlay/blueprint_editor.ui", "kind": "page", "role": "logined", "endpoint": "wwwroot/pbl_overlay/blueprint_editor.ui", "milestone": "M9", "title": "蓝图编辑器(覆盖层页壳)", "traceability": "scripts/gen_overlay_pages.py PAGES(gen_overlay_pages.py:72)→ wwwroot/pbl_overlay/blueprint_editor.ui;运行时路由 api.py PAGES[2](api.py:19)→ load_path.py PATHS[15]" }, { "name": "pbl_overlay_page_validation_report", "path": "/pbl_scense_ext/pbl_overlay/validation_report.ui", "kind": "page", "role": "logined", "endpoint": "wwwroot/pbl_overlay/validation_report.ui", "milestone": "M9", "title": "校验报告 14 维(覆盖层页壳)", "traceability": "scripts/gen_overlay_pages.py PAGES(gen_overlay_pages.py:72)→ wwwroot/pbl_overlay/validation_report.ui;运行时路由 api.py PAGES[3](api.py:20)→ load_path.py PATHS[16]" }, { "name": "pbl_overlay_page_agent_console", "path": "/pbl_scense_ext/pbl_overlay/agent_console.ui", "kind": "page", "role": "logined", "endpoint": "wwwroot/pbl_overlay/agent_console.ui", "milestone": "M9", "title": "Agent 控制台(覆盖层页壳)", "traceability": "scripts/gen_overlay_pages.py PAGES(gen_overlay_pages.py:72)→ wwwroot/pbl_overlay/agent_console.ui;运行时路由 api.py PAGES[4](api.py:21)→ load_path.py PATHS[17]" }, { "name": "pbl_overlay_page_approval_center", "path": "/pbl_scense_ext/pbl_overlay/approval_center.ui", "kind": "page", "role": "logined", "endpoint": "wwwroot/pbl_overlay/approval_center.ui", "milestone": "M9", "title": "人工审批中心(覆盖层页壳)", "traceability": "scripts/gen_overlay_pages.py PAGES(gen_overlay_pages.py:72)→ wwwroot/pbl_overlay/approval_center.ui;运行时路由 api.py PAGES[5](api.py:22)→ load_path.py PATHS[18]" }, { "name": "pbl_overlay_page_play_preview", "path": "/pbl_scense_ext/pbl_overlay/play_preview.ui", "kind": "page", "role": "logined", "endpoint": "wwwroot/pbl_overlay/play_preview.ui", "milestone": "M9", "title": "Play 预览(覆盖层页壳,世界内)", "traceability": "scripts/gen_overlay_pages.py PAGES(gen_overlay_pages.py:72)→ wwwroot/pbl_overlay/play_preview.ui;运行时路由 api.py PAGES[6](api.py:23)→ load_path.py PATHS[19]" }, { "name": "pbl_overlay_page_mission_board", "path": "/pbl_scense_ext/pbl_overlay/mission_board.ui", "kind": "page", "role": "logined", "endpoint": "wwwroot/pbl_overlay/mission_board.ui", "milestone": "M9", "title": "驱动问题板(覆盖层页壳,世界内)", "traceability": "scripts/gen_overlay_pages.py PAGES(gen_overlay_pages.py:72)→ wwwroot/pbl_overlay/mission_board.ui;运行时路由 api.py PAGES[7](api.py:24)→ load_path.py PATHS[20]" }, { "name": "pbl_overlay_page_role_panel", "path": "/pbl_scense_ext/pbl_overlay/role_panel.ui", "kind": "page", "role": "logined", "endpoint": "wwwroot/pbl_overlay/role_panel.ui", "milestone": "M9", "title": "角色面板(覆盖层页壳,世界内)", "traceability": "scripts/gen_overlay_pages.py PAGES(gen_overlay_pages.py:72)→ wwwroot/pbl_overlay/role_panel.ui;运行时路由 api.py PAGES[8](api.py:25)→ load_path.py PATHS[21]" }, { "name": "pbl_overlay_page_artifact_studio", "path": "/pbl_scense_ext/pbl_overlay/artifact_studio.ui", "kind": "page", "role": "logined", "endpoint": "wwwroot/pbl_overlay/artifact_studio.ui", "milestone": "M9", "title": "产出物工坊(覆盖层页壳,世界内)", "traceability": "scripts/gen_overlay_pages.py PAGES(gen_overlay_pages.py:72)→ wwwroot/pbl_overlay/artifact_studio.ui;运行时路由 api.py PAGES[9](api.py:26)→ load_path.py PATHS[22]" }, { "name": "pbl_overlay_page_evidence_wall", "path": "/pbl_scense_ext/pbl_overlay/evidence_wall.ui", "kind": "page", "role": "logined", "endpoint": "wwwroot/pbl_overlay/evidence_wall.ui", "milestone": "M9", "title": "证据墙(覆盖层页壳,世界内)", "traceability": "scripts/gen_overlay_pages.py PAGES(gen_overlay_pages.py:72)→ wwwroot/pbl_overlay/evidence_wall.ui;运行时路由 api.py PAGES[10](api.py:27)→ load_path.py PATHS[23]" }, { "name": "pbl_overlay_page_assessment_report", "path": "/pbl_scense_ext/pbl_overlay/assessment_report.ui", "kind": "page", "role": "logined", "endpoint": "wwwroot/pbl_overlay/assessment_report.ui", "milestone": "M9", "title": "评估报告(覆盖层页壳)", "traceability": "scripts/gen_overlay_pages.py PAGES(gen_overlay_pages.py:72)→ wwwroot/pbl_overlay/assessment_report.ui;运行时路由 api.py PAGES[11](api.py:28)→ load_path.py PATHS[24]" }, { "name": "pbl_overlay_page_dir", "path": "/pbl_scense_ext/pbl_overlay", "kind": "page", "role": "logined", "endpoint": "wwwroot/pbl_overlay/(目录路由)", "milestone": "M9", "title": "覆盖层页面壳目录(目录路由)", "traceability": "wwwroot/pbl_overlay/(12 个 .ui)→ load_path.py PATHS[25](目录条目,audit 不做文件存在性检查)" } ], "role_grants": { "logined": [ "pbl_session_context_get", "pbl_page_registry_list", "pbl_playtest_feedback_save", "pbl_overlay_bootstrap", "pbl_scense_ext_root", "pbl_scense_ext_index_ui", "pbl_overlay_core_js", "pbl_overlay_transport_js", "pbl_overlay_play_js", "pbl_overlay_page_home", "pbl_overlay_page_blueprint_list", "pbl_overlay_page_blueprint_editor", "pbl_overlay_page_validation_report", "pbl_overlay_page_agent_console", "pbl_overlay_page_approval_center", "pbl_overlay_page_play_preview", "pbl_overlay_page_mission_board", "pbl_overlay_page_role_panel", "pbl_overlay_page_artifact_studio", "pbl_overlay_page_evidence_wall", "pbl_overlay_page_assessment_report", "pbl_overlay_page_dir" ], "any": [ "pbl_overlay_loader_js", "pbl_overlay_css", "pbl_overlay_i18n_zh", "pbl_overlay_i18n_en" ] }, "superadmin_grant": { "note": "超管授权:由 scripts/m9c_rbac_seed.py::resolve_superadmin() 在导入时运行时解析——先查 role 表列集合(information_schema 取交集),按 role/name/rolelabel 三列命中 role_names 后回填真实 32 位主键 id,再为全部 26 条写 rolepermission。本段刻意不再放 role_ids:rbac role.id 是 32 位主键,把角色名塞进 role_ids 语义错位、按 id 查必零命中并静默不授权(M9-收口C QC 退回意见 #12)。解析不到任何超管实体角色时打印 WARN 并在 dev-notes 留证,不 FAIL——logined/any 两条伪角色已按 rbac userperm.py:204/217/298 语义覆盖全部登录/匿名主体。", "role_names": [ "pbl_admin", "superadmin", "admin", "超级管理员", "系统管理员" ], "grant_all": true } }