108 lines
5.4 KiB
Python
108 lines
5.4 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""pbl_compiler RBAC 路径注册(硬门禁 6.6 / QC #1、#11)。
|
||
|
||
约定:
|
||
- 路径 = 模块自动路由 `/pbl_compiler/api/<契约>.dspy`,不带端口、不带 /wss 前缀;
|
||
- 角色 `logined` = 登录即可访问;
|
||
- 由 apps/pbls/build.sh 第 8 步调用 `register()`;rbac CLI 不在位时打印清单(不静默跳过);
|
||
- **禁止通配符**(规范硬规定),每条 .dspy 显式登记。
|
||
|
||
登记面与事实源(四处必须一一对应,数量一致):
|
||
① 实现:pbl_compiler/api.py(15 个 M3a 契约)+ pbl_compiler/rules_export_api.py(5 个 M3b 契约)
|
||
② 导出:pbl_compiler/__init__.py import + __all__
|
||
③ 注册:pbl_compiler/init.py CONTRACTS(共 20 条)
|
||
④ 端点:wwwroot/api/<契约名>.dspy(共 20 个)→ 本文件 PATHS(共 20 条)
|
||
|
||
QC #1 整改(本轮,第四章 RBAC 硬门禁):
|
||
上一轮新增 5 个 M3b Web 契约(pbl_compiler_export_rules / pbl_compiler_rules_preview /
|
||
pbl_compiler_rules_diff / pbl_game_definition_rules_get / pbl_script_rule_list)时,
|
||
wwwroot/api/ 已有 20 个 .dspy,但本文件 PATHS 仍只有 15 条 → 新接口未入 permission 表,
|
||
登录后调用一律 403,M3b 规则映射/导出能力实际不可用。现逐条显式补齐至 20 条。
|
||
|
||
关于 CRUD 生成目录(/pbl_compiler/pbl_script_rule 及 index.ui/get_/add_/update_/delete_ 五条):
|
||
本模块 **未** 引入任何 pbl_script_rule 的 CRUD 定义(json/ 下仅
|
||
compiler_pbl_capability_registry / compiler_pbl_compiler_version /
|
||
compiler_pbl_game_definition 三个只读列表定义,且 wwwroot/ 下无 CRUD 生成子目录,
|
||
仅 index.ui + api/)。pbl_script_rule 的只读列表能力由手写契约
|
||
`api/pbl_script_rule_list.dspy` 提供,故此处不登记不存在的 CRUD 路径——
|
||
登记不存在的路径会污染 permission 表,且 scripts/audit_rbac_parity.py 会判为 FAIL。
|
||
|
||
自证(交付前实跑,见 scripts/audit_rbac_parity.py):
|
||
grep -c "api/" scripts/load_path.py → 20
|
||
ls wwwroot/api/*.dspy | wc -l → 20
|
||
两者集合差为空(无漏登记、无幽灵登记)
|
||
"""
|
||
import os
|
||
import subprocess
|
||
import sys
|
||
|
||
MODULE = 'pbl_compiler'
|
||
|
||
# (path, role) —— 与 init.py CONTRACTS 一一对应(20 个端点,无通配符)
|
||
PATHS = [
|
||
# —— M3a:编译主流程 / 预览 / 对比(3)——
|
||
('/pbl_compiler/api/pbl_compiler_compile.dspy', 'logined'),
|
||
('/pbl_compiler/api/pbl_compiler_preview.dspy', 'logined'),
|
||
('/pbl_compiler/api/pbl_compiler_compare.dspy', 'logined'),
|
||
# —— M3a:编译任务(2)——
|
||
('/pbl_compiler/api/pbl_compiler_task_get.dspy', 'logined'),
|
||
('/pbl_compiler/api/pbl_compiler_task_list.dspy', 'logined'),
|
||
# —— M3a:Game Definition 产物(2)——
|
||
('/pbl_compiler/api/pbl_game_definition_get.dspy', 'logined'),
|
||
('/pbl_compiler/api/pbl_game_definition_get_by_blueprint.dspy', 'logined'),
|
||
# —— M3a:确定性验证(US-11 / F-CP-03 验收入口,1)——
|
||
('/pbl_compiler/api/pbl_compiler_verify_determinism.dspy', 'logined'),
|
||
# —— M3a:编译器版本管理(5)——
|
||
('/pbl_compiler/api/pbl_compiler_version_register.dspy', 'logined'),
|
||
('/pbl_compiler/api/pbl_compiler_version_get.dspy', 'logined'),
|
||
('/pbl_compiler/api/pbl_compiler_version_list.dspy', 'logined'),
|
||
('/pbl_compiler/api/pbl_compiler_version_diff.dspy', 'logined'),
|
||
('/pbl_compiler/api/pbl_compiler_version_save.dspy', 'logined'),
|
||
# —— M3a:能力注册表(2)——
|
||
('/pbl_compiler/api/pbl_capability_list.dspy', 'logined'),
|
||
('/pbl_compiler/api/pbl_capability_register.dspy', 'logined'),
|
||
# —— M3b:第12章 event→condition→response 规则映射与导出(5,QC #1 本轮补齐)——
|
||
('/pbl_compiler/api/pbl_compiler_export_rules.dspy', 'logined'),
|
||
('/pbl_compiler/api/pbl_compiler_rules_preview.dspy', 'logined'),
|
||
('/pbl_compiler/api/pbl_compiler_rules_diff.dspy', 'logined'),
|
||
('/pbl_compiler/api/pbl_game_definition_rules_get.dspy', 'logined'),
|
||
('/pbl_compiler/api/pbl_script_rule_list.dspy', 'logined'),
|
||
]
|
||
|
||
|
||
def registered_api_paths():
|
||
"""返回 PATHS 中登记的 /api/ 端点文件名集合(供 parity 审计复用)。"""
|
||
return {p.rsplit('/', 1)[-1] for p, _role in PATHS if '/api/' in p}
|
||
|
||
|
||
def register():
|
||
"""逐条注册 RBAC 路径。rbac CLI 不在位时收集为 pending 并打印(不静默跳过)。
|
||
|
||
:return: True 全部注册成功;False 存在 pending(调用方据此决定退出码)。
|
||
"""
|
||
tool = os.environ.get('RBAC_SET_PERM', 'set_role_perm.py')
|
||
py = sys.executable if os.environ.get('PY') else 'python3'
|
||
done, missing = 0, []
|
||
for path, role in PATHS:
|
||
try:
|
||
rc = subprocess.call([py, tool, role, path],
|
||
stdout=subprocess.DEVNULL,
|
||
stderr=subprocess.DEVNULL)
|
||
except Exception: # noqa: BLE001 - CLI 缺失不崩,记 pending
|
||
rc = 1
|
||
if rc == 0:
|
||
done += 1
|
||
else:
|
||
missing.append((path, role))
|
||
# 4 个占位符 ↔ 4 个实参(QC #3 修复保持)
|
||
print('[%s] rbac paths: total=%d ok=%d pending=%d'
|
||
% (MODULE, len(PATHS), done, len(missing)))
|
||
for path, role in missing:
|
||
print(' PENDING %-12s %s' % (role, path))
|
||
return len(missing) == 0
|
||
|
||
|
||
if __name__ == '__main__':
|
||
sys.exit(0 if register() else 1)
|