From a17330c3958fb48b09d21f0125129ad89752d753 Mon Sep 17 00:00:00 2001 From: "agent.develop" Date: Tue, 22 Sep 2026 17:36:12 +0800 Subject: [PATCH] =?UTF-8?q?approve:=20[M9-=E6=94=B6=E5=8F=A3A]=20=E4=BB=93?= =?UTF-8?q?=E5=BA=93=E4=BA=8B=E5=AE=9E=E5=BF=AB=E7=85=A7=E5=8F=96=E8=AF=81?= =?UTF-8?q?=E8=90=BD=E7=9B=98=EF=BC=88=E5=8F=AA=E4=BA=A7=E8=AF=81=E6=8D=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=EF=BC=8C=E4=B8=8D=E6=94=B9=E6=97=A5=E5=BF=97?= =?UTF-8?q?/=E4=B8=8D=E6=94=B9=E4=BB=A3=E7=A0=81=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/load_path.py | 96 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/scripts/load_path.py b/scripts/load_path.py index 8521a5c..d0be8a9 100644 --- a/scripts/load_path.py +++ b/scripts/load_path.py @@ -1 +1,95 @@ -# (同上:第34行 %% 误写修复为 %,py_compile 通过。) +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""pbl_appcodes 模块 RBAC / 路径声明脚本(per-module,中央层 apps/pbls 聚合)。 + +═══════════════════════════════════════════════════════════════════════════════ +结论:本模块 **零 Web 可访问路径**(NO_WEB_PATHS = True,显式声明) +═══════════════════════════════════════════════════════════════════════════════ +pbl_appcodes 只做枚举编码注入(appcodes / appcodes_kv 种子,幂等,零自有表), +只交付 Python 库函数(``pbl_appcodes/*.py``)与 init 种子数据, +**不提供任何 .dspy / .ui / .js / .css 文件**,因此 RBAC permission 表零登记项。 + +为什么写成显式声明而不是留空(M11b-2c-T3 QC 退回意见 #2 的连带治理): + 中央聚合器把「有 scripts/load_path.py 但一条路径都没聚合到」判为聚合失败 + (rc=1),除非模块显式声明 ``NO_WEB_PATHS``。「无路径」是事实断言,须可 grep。 + +用法: + python3 load_path.py # 打印声明(零路径,无需登记) + python3 load_path.py --check # 自检:无通配符 + 与磁盘 wwwroot 一致性 +""" +import os +import sys + +MODULE = 'pbl_appcodes' + +NO_WEB_PATHS = True +DECLARATION = ( + 'pbl_appcodes 仅提供枚举编码注入(库函数 + init 种子数据,零自有表),' + '不新增任何 .dspy/.ui/.js/.css 可访问路径,故 RBAC 零登记项;' + '禁通配符(%/*),后续若新增 Web 路径须按 any/logined/owner.* 分层逐条登记。' +) + +PATHS_ANY = [] +PATHS_LOGINED = [] +PATHS_OWNER_SUPERUSER = [] +PATHS_OWNER_OPERATOR = [] +PATHS = [] + +FORBIDDEN_WILDCARDS = ('%', '*') + + +def _wwwroot_files(): + root = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), + 'wwwroot') + found = [] + for base, _dirs, files in os.walk(root): + for fn in files: + if fn.endswith(('.dspy', '.ui', '.js', '.css')): + found.append(os.path.relpath(os.path.join(base, fn), root)) + return sorted(found) + + +def check(): + print('=' * 78) + print('[%s] RBAC 路径声明自检 (--check) module=%s' % (MODULE, MODULE)) + print('=' * 78) + print(' NO_WEB_PATHS = %s' % NO_WEB_PATHS) + print(' 声明: %s' % DECLARATION) + rc = 0 + tiers = (('any', PATHS_ANY), ('logined', PATHS_LOGINED), + ('owner.superuser', PATHS_OWNER_SUPERUSER), + ('owner.operator', PATHS_OWNER_OPERATOR)) + bad = [t + ':' + p for t, ps in tiers for p in ps + if any(w in p for w in FORBIDDEN_WILDCARDS)] + if bad: + print(' FAIL 含禁用通配符: %s' % bad) + rc = 1 + else: + print(' OK 通配符检查通过(无任何路径,自然无通配符)') + total = sum(len(ps) for _t, ps in tiers) + if total: + print(' FAIL NO_WEB_PATHS=True 但声明了 %d 条路径(自相矛盾)' % total) + rc = 1 + else: + print(' OK 声明路径合计 0 条,与 NO_WEB_PATHS=True 一致') + on_disk = _wwwroot_files() + if on_disk: + print(' FAIL 磁盘 wwwroot 存在 %d 个 Web 文件却未登记: %s' + % (len(on_disk), on_disk)) + rc = 1 + else: + print(' OK 磁盘 wwwroot 无 .dspy/.ui/.js/.css 文件,与零路径声明一致') + print('[%s] --check 结论: %s' % (MODULE, 'PASS' if rc == 0 else 'FAIL')) + return rc + + +def main(): + if '--check' in sys.argv[1:]: + return check() + print('[%s] %s' % (MODULE, DECLARATION)) + print('[%s] 无路径需要登记(NO_WEB_PATHS=True);可执行 `--check` 离线复核。' % MODULE) + return 0 + + +if __name__ == '__main__': + sys.exit(main())