ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

OpenMed 结构化访问复核(Structured Access Review):本地、确定性、无值的字段权限核对机制

OpenMed 结构化访问复核(Structured Access Review):本地、确定性、无值的字段权限核对机制 OpenMed 结构化访问复核Structured Access Review本地、确定性、无值的字段权限核对机制【免费下载链接】openmedLocal-first healthcare AI: clinical NER HIPAA PII de-identification that runs 100% on-device. 2,200 medical models, 21 languages, Apple MLX Python, no cloud, no patient data leaving your network. Apache-2.0项目地址: https://gitcode.com/GitHub_Trending/ope/openmed本文基于 docs/security/access-review.md 编写。OpenMed 是一个本地优先local-first的医疗 AI 与 HIPAA PII 去标识化项目其风险模块提供了一套结构化访问复核机制将工作流workflow声明的read/export字段集合与资源 Schema、可选的拒绝deny策略进行本地比对输出三类复核发现Missing / Excessive / Denied并渲染为确定性的 JSON 与 Markdown 报告。读完本文你将掌握openmed.risk.review_structured_access的完整调用方式、报告结构、输入约束与安全边界并了解如何在集成配置阶段用它做最小必要minimum-necessary字段的配置证据核验。一、功能定位配置证据而非合规认证openmed.risk.review_structured_access回答的是一个范围极窄的治理问题工作流为read与export两种访问模式声明的字段是否恰好落在资源 Schema 暴露的字段集合、以及调用方拒绝策略所允许的范围之内该函数是集成配置的本地复核辅助工具local review aid它不是合规认证compliance certification不是临床决策保证clinical decision guarantee不授予任何访问权限不证明某个集成真的强制执行了这份声明不检查任何记录record内容不发起任何网络调用。复核结果应当被当作**配置证据configuration evidence**使用。一份完整complete的报告只意味着对于所有已声明的工作流与访问模式不存在 Missing、Excessive、Denied 三类发现中的任何一项。二、快速上手最小可用示例以下示例来自文档完整可直接运行from openmed.risk import render_access_review, review_structured_access report review_structured_access( { triage: { read: {patient_id, age}, export: {diagnosis}, } }, { properties: { patient_id: {}, age: {}, diagnosis: {}, notes: {}, } }, denied_fields{export: {diagnosis}}, ) print(report.to_json()) print(render_access_review(report))其中第一个参数workflow_requirements工作流名 → 字段声明的映射第二个参数resource_schema资源 Schema支持多种形状见下文关键字参数denied_fields全局或按模式mode区分的拒绝字段集合。三、报告内容三类复核发现针对每个访问模式read/export报告识别三类发现发现类别含义Missing缺失工作流声明了该字段但资源 Schema 中不存在该字段——可能是拼写错误或依赖了已删除的列Excessive越界Schema 中存在该字段但当前工作流与访问模式没有声明它——意味着潜在的超范围访问Denied拒绝声明的字段命中全局或模式级拒绝策略——配置与策略冲突需要显式处理以文档示例为例资源 Schema 拥有patient_id、age、diagnosis、notes四个字段triage工作流声明read {patient_id, age}、export {diagnosis}拒绝策略声明export模式拒绝diagnosis。复核结果read模式requested {patient_id, age}available {patient_id, age, diagnosis, notes}无 Missing、无 Denied但Excessive {diagnosis, notes}export模式requested {diagnosis}available同上Denied {diagnosis}Excessive {patient_id, age, notes}整体complete False存在 Excessive 与 Denied 发现。这里有一个反直觉但重要的设计Excessive 是常态而非异常。因为 Excessive 的定义是「Schema 中有、但本工作流本模式未声明」的字段只要资源 Schema 比工作流声明的字段宽就一定会出现。所以一个**完整complete**的结果要求工作流声明恰好覆盖 Schema 的全部字段——这在语义上等价于「声明的字段集合必须与 Schema 完全一致」配合 deny 策略时还需要被拒绝的字段不在声明集合内。这一点在 源码实现 中可以看到denied global_denied_set | set(mode_denied.get(mode, ())) denied_requested requested_set denied mode_reviews[mode] AccessModeReview( modemode, requested_fieldsrequested, available_fieldsresource_fields, allowed_fieldstuple(sorted((requested_set resource_set) - denied)), missing_fieldstuple(sorted(requested_set - resource_set)), excessive_fieldstuple(sorted(resource_set - requested_set)), denied_fieldstuple(sorted(denied_requested)), )missing requested - available声明了但 Schema 没有excessive available - requestedSchema 有但未声明denied requested ∩ denied声明了但被策略拒绝allowed (requested ∩ available) - denied。四个集合互斥恰好覆盖全部字段关系。测试用例 tests/unit/risk/test_access_review.py#L47-L60 完整验证了这三类发现的判定逻辑。四、Schema 映射值被忽略报告永不携带记录值一个至关重要的隐私设计是Schema 的映射值mapping values一律被忽略。Schema 中的example、default、description等元数据不会进入报告报告只包含经过校验的结构性字段名与工作流名访问决策decision各类计数counts。在 openmed/risk/access_review.py#L103-L125 的_field_tuple中可以看到当字段声明是Mapping时只取value.keys()绝不遍历值if isinstance(value, Mapping): # A mapping is a convenient schema/field declaration. Its values may # contain examples or defaults and are intentionally never traversed. candidates value.keys()因此即使 Schema 中写着{patient_id: {example: PATIENT-0007}}报告里也永远不会出现PATIENT-0007。测试 tests/unit/risk/test_access_review.py#L63-L87 明确断言PATIENT-0007、PRIVATE-DIAGNOSIS、RAW-SCHEMA-VALUE等值绝不会出现在序列化后的 JSON 中而结构性的patient_id会保留。这也解释了「非法名称被拒绝时不会在异常中回显」的设计调用方完全可能把敏感值误填在字段名位置若异常消息回显输入值就会击穿报告的价值边界。因此所有校验错误消息只描述「输入位置与类型」从不回显具体值——参见_identifier的注释与实现 openmed/risk/access_review.py#L74-L84以及测试 tests/unit/risk/test_access_review.py#L123-L132SENSITIVE-RAW-VALUE不出现在异常字符串中。五、输入形状灵活而受控5.1 资源 Schema 的四种形状resource_schema参数类型ResourceSchema支持多种常见形状由 _resource_fields 统一提取字段名JSON Schema 风格映射含properties键的映射如{properties: {patient_id: {...}, ...}}普通映射以字段名为键此时fields键也可用带属性的对象暴露fields、columns或names属性的对象可迭代的字段名集合如[patient_id, age, ...]或集合。无论哪种形状映射的值一律不检查只提取键名。5.2 工作流声明的多种写法workflow_requirements支持映射形式{triage: {read: {...}, export: {...}}}简写形式如果键只有read/export或其长写法read_fields/export_fields会被自动包装为名为default的工作流单个带名称的声明含name或workflow键的映射两者不能同时出现WorkflowRequirement对象序列WorkflowRequirement(name, read_fields[...], export_fields[...])见 openmed/risk/access_review.py#L173-L214 与测试 tests/unit/risk/test_access_review.py#L104-L120。访问模式键支持短写法与长写法两种拼写read/export与read_fields/export_fields。但同一模式不能同时声明两次例如同时写read和read_fields会报错模式对象中也不能出现未知键。5.3 拒绝策略的全局与模式级写法denied_fields支持普通字段集合{diagnosis}或[diagnosis]—— 全局拒绝策略映射{all: [...], read: [...], export: [...]}——all表示全局拒绝read/export表示模式级拒绝。策略映射中只允许这三个键出现其他键会被拒绝见 _normalize_denied_fields。六、安全边界与资源上限复核机制对输入施加了严格的边界约束常量定义见 openmed/risk/access_review.py#L24-L36约束限制字段标识符最多 128 个 ASCII 结构字符且须匹配[A-Za-z_][A-Za-z0-9_.:-]{0,127}_SAFE_IDENTIFIER字段声明总数至多 4,096_MAX_FIELDS工作流总数至多 128_MAX_WORKFLOWS非法名称处理拒绝且异常消息不含输入值超大/异常迭代器以通用、无值value-free的错误拒绝这些边界由_bounded_tuple在物化迭代器时强制实施 openmed/risk/access_review.py#L87-L100超过上限即抛AccessReviewValidationError迭代过程中抛出的任意异常RuntimeError、TypeError、MemoryError等都会被包装成不带原始值、不带__cause__链的通用错误structured access review declarations are invalid——测试 tests/unit/risk/test_access_review.py#L146-L178 验证了这一行为。其余被拒绝的输入还包括歧义的访问模式别名read与read_fields并存模式对象或 deny 策略对象中的未知键同一工作流重复命名、name与workflow并存AccessReviewReport/AccessModeReview等公开类型被构造为自相矛盾的发现例如allowed与requested/available/denied不一致见 openmed/risk/access_review.py#L229-L261。这些边界保证输入无论多畸形都不可能把原始内容注入报告或异常消息报告的隐私边界因此成立。七、确定性输出等价的声明产生逐字节相同的报告实现完全基于集合运算与排序字段名与工作流名在构造时被规范化为排序去重的元组工作流按名称排序模式按固定的read→export顺序输出JSON 序列化使用sort_keysTrue、ensure_asciiTrue、allow_nanFalse见 to_json。因此等价声明产生的 JSON 与 Markdown 逐字节相同。测试 tests/unit/risk/test_access_review.py#L63-L87 用两种不同书写顺序的等价声明验证了first.to_json() second.to_json()。这对在 CI 中做配置漂移检测diff非常友好配置未变报告哈希不变。7.1 报告对象 APIAccessReviewReport是返回值也是公开的不可变数据类 openmed/risk/access_review.py#L347-L540主要成员report.workflow(name)按名称取单个工作流复核report.workflows_with_findings含有任何发现的工作流report.missing_fields/report.excessive_fields/report.denied_fields跨工作流的去重字段report.summary聚合计数workflow_count、workflows_with_findings、resource_field_count、missing_field_count、excessive_field_count、denied_field_count、completereport.complete所有工作流所有模式均无发现时为Truereport.to_dict()/report.to_json(indent2)/report.to_markdown()三种确定性输出report.schema_versionACCESS_REVIEW_SCHEMA_VERSION 1。render_access_review(report)是对report.to_markdown()的包装要求传入真正的AccessReviewReport实例 openmed/risk/access_review.py#L790-L795。Markdown 输出包含摘要表Workflows / Resource fields / Missing / Excessive / Denied / Complete与每个工作流的发现表Access / Missing fields / Excessive fields / Denied fields / Status状态为pass或review。此外源码为保持 API 可发现性提供了三个等价别名build_access_review_report、access_review_report、review_access均指向同一实现 openmed/risk/access_review.py#L798-L802并从 openmed/risk/init.py 对外导出。八、命名与报告即元数据字段名必须无 PHI由于报告会原样呈现字段名与工作流名字段名和工作流名属于报告可见的元数据绝不能包含受保护健康信息PHI。例如不要用{workflow: patient-john-doe, read: {disease-name-...}}这类命名。每个字段标识符限定为 128 个 ASCII 结构字符正则[A-Za-z_][A-Za-z0-9_.:-]{0,127}这意味着字段名中不允许出现空格、非 ASCII 字符与特殊字符天然阻断了将自由文本如fever 39.2C, chest pain误作字段名注入报告的可能。九、本地性与运行前提复核实现不执行任何强制的网络调用也不检查任何记录。整条计算链在 review_structured_access 中完成提取 Schema 字段 → 规范化拒绝策略 → 规范化工作流 → 逐模式集合比对 → 组装报告。没有模型推理、没有远端服务、没有记录扫描因此可以在离线环境、CI 流水线或集成配置评审中随时运行且执行成本可忽略。适用前提本机制针对的是结构化structured字段访问声明的核对并不适用于非结构化自由文本的去标识化校验后者应配合 OpenMed 核心 PII 去标识化能力使用参见 docs/anonymization.md 与 docs/security/minimum-necessary.md。十、与周边模块的协同配置证据链结构化访问复核并非孤岛它与 OpenMed 风险/合规模块中的同类确定性机制构成一套「配置证据链」docs/compliance/access-review-expiry.mdopenmed.compliance.access_review_expiry为结构化访问复核提供过期门禁expiry gate——校验复核的签发时间、排他性过期边界、策略指纹policy fingerprint与必需决策类别输出稳定的pass/block与错误码not_yet_valid、expired、policy_fingerprint_mismatch、missing_decision_categories。两者共享相同的设计哲学仅含白名单元数据、忽略映射值、错误不回显输入、完全离线确定。若要将访问复核接入发布自动化建议配合该过期门禁一起使用openmed/risk/minimum_necessary.py最小必要字段选择器——按「用途purpose声明 策略 profile」从源记录中挑选导出字段与访问复核一样保持「策略声明与记录值分离」「全部调用方元数据有界」的设计。访问复核回答「声明是否与 Schema/策略一致」最小必要选择器回答「按声明实际导出哪些字段」二者可组成「声明核对 → 实际导出」的完整最小必要链路docs/security/access-scope.md等安全文档提供了访问范围相关的策略背景。十一、结论与使用建议openmed.risk.review_structured_access是 OpenMed 中一类少见的「纯治理」工具它不读取一行记录不发起一次网络请求仅凭三份输入工作流声明、资源 Schema、拒绝策略就能产出确定性的、无值的结构化访问复核报告。使用时请牢记其边界把它当作配置证据报告完整 ≠ 实际访问已获授权也不证明集成真的强制执行声明命名必须无 PHI字段名与工作流名会原样进入报告与异常消息配合过期门禁与最小必要选择器使用形成可审计、可复现的发布前核验链利用确定性输出做漂移检测将to_json()结果纳入 CI 基线配置变更即产生可 diff 的报告差异。在集成开发或对接外部系统时将本文示例中的triage替换为你的真实工作流名、properties替换为对接资源的真实字段清单、denied_fields替换为你的策略声明即可在代码评审与发布门禁中获得一份可引用、可复现的结构化访问证据。【免费下载链接】openmedLocal-first healthcare AI: clinical NER HIPAA PII de-identification that runs 100% on-device. 2,200 medical models, 21 languages, Apple MLX Python, no cloud, no patient data leaving your network. Apache-2.0项目地址: https://gitcode.com/GitHub_Trending/ope/openmed创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表