world_sync/scripts/load_path.py
2026-09-22 14:02:41 +08:00

165 lines
7.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""world_sync 模块 RBAC / 路径声明脚本(per-module,双写中央 apps/pbls/scripts/load_path.py)。
用法:
python3 load_path.py # 找到 Sage 根时逐条 set_role_perm 登记;找不到则打印跳过说明
python3 load_path.py --check # 离线自检:不连库,校验声明合规(无通配符、分层正确)并回显登记表
═══════════════════════════════════════════════════════════════════════════════
里程碑 RBAC 声明台账(每个里程碑必须显式登记一行,禁止留空/待补)
═══════════════════════════════════════════════════════════════════════════════
M11b-2(T3 本任务,2026-09-22):
结论 = 无新路径登记。
理由 = M11b-2 里程碑(world_sync 列级差异比对 + 单事务事件/状态写入 pbl_runtime_ext)
只交付 **Python 库函数**(world_sync/*.py、pbl_runtime_ext/*.py)与
models/*.json 表定义,**不新增任何 .dspy / .ui / .js / .css 前端可访问路径**,
因此本里程碑在 RBAC 中 **零新增登记项**;下方 PATHS_ANY / PATHS_LOGINED
为 M11b-2 之前既有页面/接口路径的存量声明,保持原样未增删。
铁律 = 通配符(% / *)在本脚本中一律禁止,所有路径逐条显式声明;
若后续里程碑(M11b-3 及以后)新增 .dspy/.ui/.js/.css,必须按
any / logined / owner.superuser / owner.operator 分层在本脚本 +
中央 apps/pbls/scripts/load_path.py 双写登记,并在本台账追加一行。
═══════════════════════════════════════════════════════════════════════════════
"""
import os
import sys
MODULE = 'world_sync'
# ── 既有(M11b-2 之前)路径:any 层——无需登录即可访问的静态/公共资源 ──────────
PATHS_ANY = [
f'/{MODULE}',
]
# ── 既有(M11b-2 之前)路径:logined 层——.ui 页面与 .dspy 接口 ────────────────
# M11b-2 未在此列表新增任何条目(见文件头「里程碑 RBAC 声明台账」)。
PATHS_LOGINED = [
f'/{MODULE}', f'/{MODULE}/index.ui', f'/{MODULE}/sync_form.ui',
f'/{MODULE}/world_sync', f'/{MODULE}/world_sync/index.ui',
f'/{MODULE}/world_sync/get_world_sync.dspy', f'/{MODULE}/world_sync/add_world_sync.dspy',
f'/{MODULE}/world_sync/update_world_sync.dspy', f'/{MODULE}/world_sync/delete_world_sync.dspy',
f'/{MODULE}/api/world_sync.dspy', f'/{MODULE}/api/create_world_sync.dspy',
f'/{MODULE}/api/world_sync_update.dspy', f'/{MODULE}/api/world_sync_delete.dspy',
f'/{MODULE}/api/get_search_world_id.dspy', f'/{MODULE}/api/get_search_sync_type.dspy',
f'/{MODULE}/api/get_search_sync_status.dspy',
]
# ── 既有:owner.* 角色受限路径(当前无,显式声明为空,避免「漏登记」被误判为「待补」)
PATHS_OWNER_SUPERUSER = []
PATHS_OWNER_OPERATOR = []
# ── 里程碑声明台账(供 --check 回显,也是 QC 可 grep 的硬证据)────────────────
MILESTONE_DECLARATIONS = [
{
'milestone': 'M11b-2',
'new_paths': 0,
'declaration': (
'M11b-2 本里程碑不新增 .dspy/.ui/.js/.css 路径,仅提供库函数'
'(world_sync / pbl_runtime_ext 的 *.py 与 models/*.json),'
'故无 RBAC 登记项;禁通配符(%/*),'
'如有路径须按 any/logined/owner.* 分层逐条登记。'
),
},
]
FORBIDDEN_WILDCARDS = ('%', '*')
def _find_sage_root():
for c in [os.path.expanduser('~/repos/sage'), os.path.expanduser('~/sage'), '/d/ymq/repos/sage']:
if os.path.isdir(os.path.join(c, 'wwwroot')) and os.path.isdir(os.path.join(c, 'py3', 'bin')):
return c
return None
def _assert_no_wildcard():
"""通配符硬门禁:任何一层路径出现 % 或 * 直接失败退出(非静默)。"""
bad = []
for tier, paths in (
('any', PATHS_ANY),
('logined', PATHS_LOGINED),
('owner.superuser', PATHS_OWNER_SUPERUSER),
('owner.operator', PATHS_OWNER_OPERATOR),
):
for p in paths:
if any(w in p for w in FORBIDDEN_WILDCARDS):
bad.append(f'{tier}:{p}')
if bad:
print(f'[world_sync] FAIL 路径声明含禁用通配符: {bad}')
return 1
print('[world_sync] OK 通配符检查通过(PATHS_ANY/LOGINED/OWNER.* 均为逐条显式路径,无 % / *)')
return 0
def check():
"""离线自检模式:不连库、不写权限表,只回显声明台账与合规检查结果。"""
print('=' * 78)
print(f'[world_sync] RBAC 路径声明自检 (--check) module={MODULE}')
print('=' * 78)
rc = _assert_no_wildcard()
print('\n[声明台账]')
for d in MILESTONE_DECLARATIONS:
print(f" - {d['milestone']}: 新增路径 {d['new_paths']} 条 -> {d['declaration']}")
print('\n[无新 API 路径正式声明]')
print(' M11b-2(含 T1/T2/T3 子任务)未新增任何 .dspy / .ui / .js / .css 可访问路径;')
print(' 本里程碑交付物为库函数(world_sync/*.py、pbl_runtime_ext/*.py)与表定义')
print(' (models/world_sync_column_map.json 等),由宿主应用进程内调用,不经 HTTP 路由,')
print(' 因此本里程碑在 RBAC permission 表中零新增条目。')
print(' 说明文件: modules/world_sync/wwwroot/api/README-N-A-M11b2.md')
print(' 中央双写: apps/pbls/scripts/load_path.py 含等价 M11b-2 声明。')
print('\n[存量路径登记(M11b-2 之前既有,未增删)]')
for tier, paths in (
('any', PATHS_ANY),
('logined', PATHS_LOGINED),
('owner.superuser', PATHS_OWNER_SUPERUSER),
('owner.operator', PATHS_OWNER_OPERATOR),
):
print(f' tier={tier} count={len(paths)}')
for p in paths:
print(f' {p}')
total = len(PATHS_ANY) + len(PATHS_LOGINED) + len(PATHS_OWNER_SUPERUSER) + len(PATHS_OWNER_OPERATOR)
print(f'\n[汇总] 存量路径合计 {total} 条;M11b-2 新增 0 条')
print('[world_sync] --check 结论: PASS(无新路径需登记,声明已显式化)' if rc == 0
else '[world_sync] --check 结论: FAIL(存在违规通配符)')
return rc
def main():
if '--check' in sys.argv[1:]:
return check()
root = _find_sage_root()
if not root:
print('[world_sync] 未找到 Sage 根目录,跳过(请确认中央 load_path.py 已登记)')
print('[world_sync] 本里程碑 M11b-2 无新路径登记(仅库函数),跳过不影响 RBAC 完整性;')
print('[world_sync] 可执行 `python3 load_path.py --check` 离线校验声明合规性。')
return 0
sys.path.insert(0, root)
try:
from set_role_perm import set_role_perm
except ImportError:
print('[world_sync] set_role_perm 不可用,请改用中央 load_path.py')
return 0
rc = _assert_no_wildcard()
if rc != 0:
return rc
for p in PATHS_ANY:
set_role_perm(p, 'any')
for p in PATHS_LOGINED:
set_role_perm(p, 'logined')
for p in PATHS_OWNER_SUPERUSER:
set_role_perm(p, 'owner.superuser')
for p in PATHS_OWNER_OPERATOR:
set_role_perm(p, 'owner.operator')
print(f'[world_sync] 已注册 {len(PATHS_ANY)+len(PATHS_LOGINED)+len(PATHS_OWNER_SUPERUSER)+len(PATHS_OWNER_OPERATOR)} 条 RBAC 路径'
f'(M11b-2 新增 0 条,全部为存量路径)')
return 0
if __name__ == '__main__':
sys.exit(main())