platform-policy-rule-generate

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Authoring Policy Rule Definitions

编写政策规则定义

Gating:
@WsdlGuard("EnforceOMatic.orgCanUsePolicyRuleMDAPI")
=
OrgPermissions.EnforceOMatic && OrgPermissions.PolicyRuleMDAPI
Min API version: 64.0 (66.0 for conditions using
PolicyJsonExpression
)
For human maintainers (not the agent): the Java source-of-truth lives at
enforce-o-matic-impl/java/src/enforce/o/matic/metadata/
and reference fixtures at
enforce-o-matic-impl/test/func/filemetadata/<name>/
. The agent should rely on the templates and reference docs in this skill bundle — those impl paths are not readable from the Vibes/MCP runtime.
This skill covers the on-disk metadata XML format for authoring policies. Use it whenever a task asks to write a
*.policyRuleDefinition
or
*.policyRuleDefinitionSet
file, add a fixture under
test/func/filemetadata/
, or ship a metadata package. The runtime side (RuleProvider, hooks) is out of scope.

Eval coverage: This skill is exercised by the team's ADK eval framework, not by
tests/evals/
under the skill directory. Five datasets covering the ACCESS / GOVERNANCE / RECORD / TRANSFORM variants live in
packages/adk-eval/eval/domains/platform-policy-rule-generate/datasets/
.
准入条件:
@WsdlGuard("EnforceOMatic.orgCanUsePolicyRuleMDAPI")
=
OrgPermissions.EnforceOMatic && OrgPermissions.PolicyRuleMDAPI
最低API版本: 64.0(使用
PolicyJsonExpression
的条件需66.0)
面向人工维护者(非Agent): Java权威源码位于
enforce-o-matic-impl/java/src/enforce/o/matic/metadata/
,参考示例位于
enforce-o-matic-impl/test/func/filemetadata/<name>/
。Agent应依赖本技能包中的模板和参考文档——这些实现路径无法在Vibes/MCP运行时读取。
本技能涵盖用于编写政策的磁盘元数据XML格式。当任务要求编写
*.policyRuleDefinition
*.policyRuleDefinitionSet
文件、在
test/func/filemetadata/
下添加示例,或发布元数据包时,请使用本技能。运行时相关内容(RuleProvider、钩子)不在本技能范围内。

评估覆盖范围: 本技能由团队的ADK评估框架测试,而非技能目录下的
tests/evals/
。涵盖ACCESS / GOVERNANCE / RECORD / TRANSFORM变体的五组数据集位于
packages/adk-eval/eval/domains/platform-policy-rule-generate/datasets/

1. Package Layout

1. 包结构

A deployable package always contains:
text
<fixture>/
  package.xml
  policyRuleDefinitionSets/<setName>.policyRuleDefinitionSet
  policyRuleDefinitions/<ruleName>.policyRuleDefinition
package.xml
template (use
<version>[ftest]</version>
for ftests,
64.0
or higher for real orgs):
xml
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Rule0</members>
        <name>PolicyRuleDefinition</name>
    </types>
    <types>
        <members>Set1</members>
        <name>PolicyRuleDefinitionSet</name>
    </types>
    <version>64.0</version>
</Package>

可部署包始终包含以下内容:
text
<fixture>/
  package.xml
  policyRuleDefinitionSets/<setName>.policyRuleDefinitionSet
  policyRuleDefinitions/<ruleName>.policyRuleDefinition
package.xml
模板(功能测试使用
<version>[ftest]</version>
,正式组织使用
64.0
或更高版本):
xml
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Rule0</members>
        <name>PolicyRuleDefinition</name>
    </types>
    <types>
        <members>Set1</members>
        <name>PolicyRuleDefinitionSet</name>
    </types>
    <version>64.0</version>
</Package>

2. PolicyRuleDefinitionSet Schema

2. PolicyRuleDefinitionSet架构

xml
<PolicyRuleDefinitionSet xmlns="http://soap.sforce.com/2006/04/metadata">
    <label>Set1</label>
    <description>Optional free text</description>
    <replicated>false</replicated>             <!-- MinAppVersion 260 -->
    <builderCompatible>true</builderCompatible> <!-- MinAppVersion 262, author-settable -->
    <!-- builderValidated: server-managed — do not set in authored XML -->
</PolicyRuleDefinitionSet>
ElementReqNotes
<label>
yesMaster label. File basename (devName) is the MDAPI identifier, not the label.
<description>
noFree text.
<replicated>
no
true
triggers placeholder transformation across companion orgs. Omit for null/false.
<builderCompatible>
no
true
= rules audited per §7 checklist.
false
= API-only. Omit = unaudited. Informational only — no deploy/runtime effect.
<builderValidated>
noServer-managed. Never set in authored XML. Server overwrites on validation.

xml
<PolicyRuleDefinitionSet xmlns="http://soap.sforce.com/2006/04/metadata">
    <label>Set1</label>
    <description>可选自由文本</description>
    <replicated>false</replicated>             <!-- 最低应用版本260 -->
    <builderCompatible>true</builderCompatible> <!-- 最低应用版本262,可由编写者设置 -->
    <!-- builderValidated: 由服务器管理——请勿在编写的XML中设置 -->
</PolicyRuleDefinitionSet>
元素必填说明
<label>
主标签。文件基名(devName)是MDAPI标识符,而非标签。
<description>
自由文本。
<replicated>
设置为
true
会触发关联组织间的占位符转换。省略则为null/false。
<builderCompatible>
true
= 规则需符合第7节检查清单;
false
= 仅支持API。省略则表示未审核。仅为信息性设置——不影响部署/运行时。
<builderValidated>
由服务器管理。请勿在编写的XML中设置。 服务器会在验证时覆盖该值。

3. PolicyRuleDefinition — Core Fields

3. PolicyRuleDefinition — 核心字段

ElementReqNotes
<label>
yesMasterLabel.
<category>
yesSee §4. Drives
resourceScopeType
and whether
policyRuleResourceDomains
/
resourceTransform
are required. Does NOT constrain
effect
outside of TRANSFORM.
<effect>
yes
Permit
,
Forbid
, or
Transform
. The only category-coupling enforced by core:
effect=Transform ↔ category=TRANSFORM_POLICY_RULE_DEFINITION
(bidirectional). All other categories accept Permit and Forbid freely.
<action>
yes (≥1)
Read
,
TupleRead
,
Create
, etc. Multiple elements OR-combine.
<policyRuleDefinitionSetName>
yesDeveloper name of parent set.
<principalScopeType>
yesAlways
ANY
.
<resourceScopeType>
yes
ANY
,
FIELD
,
RECORD
,
DATASPACE
, or
SPAN
. Must match category (§4).
<principalAuthenticationLevel>
no
INTERNAL
,
AUTHENTICATED
,
UNIDENTIFIED
,
IDENTIFIED
.
<ruleConsumer>
no
ALL
,
DATACLOUD
,
MULESOFT
,
TABLEAU
,
CORE
.
<policyRuleResourceDomains>
noRequired for RECORD (RLS) and FIELD-scope TRANSFORM rules only. Forbidden on ACCESS/GOVERNANCE.
<resourceTransform>
noRequired (and only valid) when
category=TRANSFORM
.
<whenPolicyRuleDefinitionClauseConjunction>
noWHEN conditions.
<unlessPolicyRuleDefinitionClauseConjunction>
noUNLESS conditions. Not UI-editable — prefer WHEN + negated operator.

元素必填说明
<label>
MasterLabel。
<category>
参见第4节。决定
resourceScopeType
以及是否需要
policyRuleResourceDomains
/
resourceTransform
除TRANSFORM外,不限制
effect
的取值。
<effect>
Permit
Forbid
Transform
。核心层唯一强制的类别与效果关联规则:
effect=Transform ↔ category=TRANSFORM_POLICY_RULE_DEFINITION
(双向绑定)。其他所有类别均可自由选择Permit和Forbid。
<action>
是(至少1个)
Read
TupleRead
Create
等。多个元素为OR组合。
<policyRuleDefinitionSetName>
父集合的开发者名称。
<principalScopeType>
始终为
ANY
<resourceScopeType>
ANY
FIELD
RECORD
DATASPACE
SPAN
。必须与类别匹配(第4节)。
<principalAuthenticationLevel>
INTERNAL
AUTHENTICATED
UNIDENTIFIED
IDENTIFIED
<ruleConsumer>
ALL
DATACLOUD
MULESOFT
TABLEAU
CORE
<policyRuleResourceDomains>
仅RECORD(RLS)和FIELD范围的TRANSFORM规则需要。ACCESS/GOVERNANCE规则禁止使用。
<resourceTransform>
仅当
category=TRANSFORM
时必填(且仅在此场景有效)。
<whenPolicyRuleDefinitionClauseConjunction>
WHEN条件。
<unlessPolicyRuleDefinitionClauseConjunction>
UNLESS条件。不可通过UI编辑——优先使用WHEN+否定运算符。

4. Category Decision Tree

4. 类别决策树

Category names a domain (where in the platform's enforcement layers the rule applies). Effect names the action (allow / deny / transform). They are independent except for TRANSFORM.
The only Category × Effect rule the platform validates (
enforce-o-matic-api/java/src/enforce/o/matic/api/module/api/RuleBuilder.java
):
  • effect=Transform
    category=TRANSFORM_POLICY_RULE_DEFINITION
    (bidirectional; mismatched throws
    INVALIDFORCATEGORY
    ).
  • All other categories (
    ACCESS
    ,
    GOVERNANCE
    ,
    RECORD
    ,
    IDENTIFIED_RECORD
    ) accept either
    Permit
    or
    Forbid
    .
Note on the platform's auto-fill default: When
<category>
is omitted from authored XML, the impl-side save hook (
PolicyRuleDefinitionObject.saveHook_Validate
) fills it in from
effect
:
Permit→ACCESS
,
Forbid→GOVERNANCE
,
Transform→TRANSFORM
. This is a default-fill, not a validation. If you author an explicit category that contradicts this default, it is accepted and persisted as-is.
类别指定规则在平台执行层中的应用域,效果指定操作(允许/拒绝/转换)。除TRANSFORM外,二者相互独立。
平台唯一验证的类别×效果规则(位于
enforce-o-matic-api/java/src/enforce/o/matic/api/module/api/RuleBuilder.java
):
  • effect=Transform
    category=TRANSFORM_POLICY_RULE_DEFINITION
    (双向绑定;不匹配会抛出
    INVALIDFORCATEGORY
    错误)。
  • 其他所有类别(
    ACCESS
    GOVERNANCE
    RECORD
    IDENTIFIED_RECORD
    )均可接受
    Permit
    Forbid
平台自动填充默认值说明: 如果编写的XML中省略
<category>
,实现层的保存钩子(
PolicyRuleDefinitionObject.saveHook_Validate
)会根据
effect
自动填充:
Permit→ACCESS
Forbid→GOVERNANCE
Transform→TRANSFORM
这是默认填充,而非验证规则。 如果您编写的显式类别与该默认值矛盾,系统会接受并按原样持久化。

Picking the category

类别选择指南

text
What kind of policy?
├── OLS/FLS allow/deny on tagged or classified resources
│     category = ACCESS_POLICY_RULE_DEFINITION (allow/deny attestation in the access plane)
│              | GOVERNANCE_POLICY_RULE_DEFINITION (governance-audited)
│     effect = Permit | Forbid (chosen independently from category)
│     resourceScopeType = ANY | FIELD | DATASPACE
│     NO <policyRuleResourceDomains>
│     condition: resourcePath=TAG|CLASSIFICATION CONTAINS_ANY <ref>
│     For "objects AND all their fields" → action=TupleRead + OR-of-ENTITYTYPE clause (§7)
│     Note: "Block access to Foo object" → tag Foo with <yourTag>, write rule on tag
│        Do NOT use <resourceDomain>Foo</resourceDomain> — forbidden for ACCESS/GOVERNANCE
├── Row-level filter on a DMO/DLO
│     category = RECORD_POLICY_RULE_DEFINITION
│     effect = Permit | Forbid
│     resourceScopeType = RECORD
│     <policyRuleResourceDomains> = the DMO/DLO API name  ← entity targeting allowed here
├── Identified-Guest record access
│     NOT authorable via MDAPI — SESSION_CONSUMER_ID is not in RuleContextPathType
│        Must be implemented as a runtime RuleProvider.
└── Field masking
      category = TRANSFORM_POLICY_RULE_DEFINITION   ← required by RuleBuilder validator
      effect = Transform                            ← required by RuleBuilder validator
      resourceScopeType = FIELD (structured) or SPAN (unstructured)
      <policyRuleResourceDomains> = the DMO whose field is masked
      <resourceTransform> required (e.g. NULL_RESOURCE_TRANSFORM, LAST_N_CHARS_RESOURCE_TRANSFORM)
text
您需要哪种政策?
├── 对标记或分类资源的OLS/FLS允许/拒绝
│     category = ACCESS_POLICY_RULE_DEFINITION(访问层的允许/拒绝验证)
│              | GOVERNANCE_POLICY_RULE_DEFINITION(经治理审计)
│     effect = Permit | Forbid(与类别独立选择)
│     resourceScopeType = ANY | FIELD | DATASPACE
│     禁止使用 <policyRuleResourceDomains>
│     条件:resourcePath=TAG|CLASSIFICATION CONTAINS_ANY <ref>
│     若需“对象及其所有字段”→ action=TupleRead + OR-of-ENTITYTYPE子句(第7节)
│     注意:“阻止访问Foo对象”→ 为Foo添加<yourTag>标记,基于该标记编写规则
│        请勿使用 <resourceDomain>Foo</resourceDomain> —— ACCESS/GOVERNANCE规则禁止此操作
├── DMO/DLO上的行级过滤
│     category = RECORD_POLICY_RULE_DEFINITION
│     effect = Permit | Forbid
│     resourceScopeType = RECORD
│     <policyRuleResourceDomains> = DMO/DLO的API名称 ← 此处允许实体定位
├── 已识别访客的记录访问
│     无法通过MDAPI编写 —— SESSION_CONSUMER_ID不在RuleContextPathType中
│        必须通过运行时RuleProvider实现。
└── 字段掩码
      category = TRANSFORM_POLICY_RULE_DEFINITION   ← RuleBuilder验证器要求
      effect = Transform                            ← RuleBuilder验证器要求
      resourceScopeType = FIELD(结构化)或SPAN(非结构化)
      <policyRuleResourceDomains> = 字段被掩码的DMO
      必须包含<resourceTransform>(例如NULL_RESOURCE_TRANSFORM、LAST_N_CHARS_RESOURCE_TRANSFORM)

ACCESS vs GOVERNANCE — how to choose

ACCESS与GOVERNANCE的选择

Both legally accept Permit and Forbid. Pick by which enforcement layer should record/audit the rule and what the prompt literally asks for:
Use casePickReason
The prompt names "ACCESS policy rule" / "access rule" / "OLS/FLS" explicitly
ACCESS_POLICY_RULE_DEFINITION
Matches the prompt's vocabulary; sits in the data-access enforcement layer.
The prompt names "governance" / "audit" / "policy framework" / data-residency or compliance language
GOVERNANCE_POLICY_RULE_DEFINITION
Matches the prompt's vocabulary; rules surface in governance reporting.
Prompt is ambiguous and only describes allow/deny semanticsDefault to
ACCESS
for Permit,
GOVERNANCE
for Forbid (mirrors the platform's auto-fill default; safe and deployable, but not required)
Important — honor the explicit category in the prompt. If the prompt says "ACCESS policy rule that denies …" or "GOVERNANCE policy rule that permits …", emit exactly that category. Do not silently swap to the auto-fill default just because effect is Forbid (or Permit). The platform accepts both. The agent must not override the user's stated intent.
Scope × category compatibility — any combination outside this matrix throws
INVALIDFORCATEGORY
:
ACCESS
GOVERNANCE
TRANSFORM
RECORD
ANY
YesYesNoNo
DATASPACE
YesYesNoNo
FIELD
YesYesYesNo
RECORD
NoNoNoYes
SPAN
NoNoYesNo

两者均支持Permit和Forbid。请根据规则应记录/审计的执行层以及提示的字面要求进行选择:
使用场景选择原因
提示明确提及“ACCESS政策规则”/“访问规则”/“OLS/FLS”
ACCESS_POLICY_RULE_DEFINITION
匹配提示词汇;位于数据访问执行层。
提示提及“治理”/“审计”/“政策框架”/数据驻留或合规相关表述
GOVERNANCE_POLICY_RULE_DEFINITION
匹配提示词汇;规则会出现在治理报告中。
提示模糊,仅描述允许/拒绝语义默认Permit选
ACCESS
,Forbid选
GOVERNANCE
(与平台自动填充默认值一致;安全且可部署,但非强制要求
重要提示:请遵循提示中的明确类别。 如果提示要求“拒绝访问的ACCESS政策规则”或“允许访问的GOVERNANCE政策规则”,请严格输出指定类别。不要因为效果是Forbid(或Permit)就自动替换为默认值。平台接受这两种组合,Agent不得覆盖用户的明确意图。
范围×类别兼容性 —— 超出以下矩阵的组合会抛出
INVALIDFORCATEGORY
错误:
ACCESS
GOVERNANCE
TRANSFORM
RECORD
ANY
DATASPACE
FIELD
RECORD
SPAN

5. Condition Patterns (Quick Reference)

5. 条件模式(快速参考)

Every
<conditions>
block needs all four:
<clause>
,
<operator>
, one path element, and the value.
Goalpath elementoperatorvalue
Resource has tag
<resourcePath>TAG</resourcePath>
CONTAINS_ANY
<valueReferenceType>CUSTOM_TAG
|
STANDARD_TAG</valueReferenceType>
Resource has classification
<resourcePath>CLASSIFICATION</resourcePath>
CONTAINS_ANY
CUSTOM_CLASSIFICATION
|
STANDARD_CLASSIFICATION
Principal has permission
<principalPath>ASSIGNED_PERMISSIONS_PATH</principalPath>
CONTAINS_ANY
|
CONTAINS_NONE
<valueReferenceType>CUSTOM_PERMISSION</valueReferenceType>
Session in dataspace
<contextPath>SESSION_DATASPACE</contextPath>
CONTAINS_ANY
<valueReferenceType>DATASPACE</valueReferenceType>
Record field = user attribute
<resourcePath>RECORDFIELD</resourcePath>
+
<valueDomain>Schema:field</valueDomain>
EQUALS
<valuePrincipalPath>USER_ID
|
ORGANIZATION_ID
|
USER_ROLE_ID</valuePrincipalPath>
Entity type check
<resourcePath>ENTITYTYPE</resourcePath>
IS
<valueString>{"t":"Text","v":"FIELD"}</valueString>
<conjunctionExpression>
is 1-indexed prefix notation:
1
,
(AND 1 2)
,
(OR 1 2)
,
(AND (OR 1 2) (AND 3))
. A bare top-level index like
1
is valid for deploy (impl fixtures use it) but crashes the Data Governance Policy Builder UI — see §7 if UI editability matters.
For full path enums (
RulePrincipalPathType
,
RuleResourcePathType
,
RuleContextPathType
), operators, and JSON expressions (PROJECTION / ARGLIST / SOQLTARGETLISTEXPR), see
references/policy-schema-full.md
. For copy-paste templates for all policy variants, see
references/templates.md
.

每个
<conditions>
块必须包含四个元素
<clause>
<operator>
、一个路径元素和值。
目标路径元素运算符
资源带有标记
<resourcePath>TAG</resourcePath>
CONTAINS_ANY
<valueReferenceType>CUSTOM_TAG
|
STANDARD_TAG</valueReferenceType>
资源带有分类
<resourcePath>CLASSIFICATION</resourcePath>
CONTAINS_ANY
CUSTOM_CLASSIFICATION
|
STANDARD_CLASSIFICATION
主体拥有权限
<principalPath>ASSIGNED_PERMISSIONS_PATH</principalPath>
CONTAINS_ANY
|
CONTAINS_NONE
<valueReferenceType>CUSTOM_PERMISSION</valueReferenceType>
会话位于数据空间
<contextPath>SESSION_DATASPACE</contextPath>
CONTAINS_ANY
<valueReferenceType>DATASPACE</valueReferenceType>
记录字段=用户属性
<resourcePath>RECORDFIELD</resourcePath>
+
<valueDomain>Schema:field</valueDomain>
EQUALS
<valuePrincipalPath>USER_ID
|
ORGANIZATION_ID
|
USER_ROLE_ID</valuePrincipalPath>
实体类型检查
<resourcePath>ENTITYTYPE</resourcePath>
IS
<valueString>{"t":"Text","v":"FIELD"}</valueString>
<conjunctionExpression>
采用1索引前缀表示法:
1
(AND 1 2)
(OR 1 2)
(AND (OR 1 2) (AND 3))
。顶级裸索引(如
1
)可正常部署(实现示例中使用此格式),但会导致Data Governance Policy Builder UI崩溃——若需UI可编辑性,请参见第7节。
完整路径枚举(
RulePrincipalPathType
RuleResourcePathType
RuleContextPathType
)、运算符和JSON表达式(PROJECTION / ARGLIST / SOQLTARGETLISTEXPR)请参见
references/policy-schema-full.md
。所有政策变体的复制粘贴模板请参见
references/templates.md

6. Validation Guardrails

6. 验证防护准则

  1. Every
    <conditions>
    needs an
    <operator>
    . Missing operator → reject.
  2. Every
    <conditions>
    needs at least one path element (
    <resourcePath>
    ,
    <principalPath>
    ,
    <contextPath>
    , or
    <valueDomain>
    ).
  3. <contextPath>
    is exclusively
    SESSION_DATASPACE
    . Never put a resource path value there.
  4. Scope × category must be in the §4 matrix. Common offenders: ACCESS/GOVERNANCE + RECORD scope; RECORD + ANY/FIELD scope; TRANSFORM + ANY/RECORD scope. (Effect is independent of category except for TRANSFORM — see §4.)
  5. <resourceTransform>
    and
    effect=Transform
    are coupled. Transform effect needs a resourceTransform. Permit/Forbid must not have one.
  6. <policyRuleResourceDomains>
    is required for RECORD (RLS) and FIELD-scope TRANSFORM; forbidden on ACCESS/GOVERNANCE.
  7. <conjunctionExpression>
    indices must match actual
    <conditions>
    count. Off-by-one → reject.
  8. <clause>
    inside
    <conditions>
    must match the wrapper (
    WHEN
    inside
    <when…>
    ,
    UNLESS
    inside
    <unless…>
    ).
  9. JSON literals in
    <valueString>
    must escape
    "
    to
    &quot;
    . Wrong escaping silently corrupts the literal.
  10. Reference targets (
    <valueReference>
    ,
    <resourceDomain>
    ) must exist in the target org at deploy time.
  11. SCALAR_ATTRIBUTE
    /
    PLURAL_ATTRIBUTE
    are not in
    RulePrincipalPathType
    — not in MDAPI contract. Use a runtime RuleProvider for those shapes.
  12. IDENTIFIED_RECORD
    is not authorable via MDAPI —
    SESSION_CONSUMER_ID
    not in
    RuleContextPathType
    .
  13. Standard tag/classification dev names are fully-qualified dotted paths (e.g.
    DataGovernanceTags.ExternalData.Visibility.Public
    ). Retrieve an existing rule to get the exact string before authoring.
  14. Min API versions:
    PolicyRuleDefinition
    = 64.0;
    PolicyJsonExpression
    conditions = 66.0;
    <replicated>
    = 260+;
    <builderCompatible>
    /
    <builderValidated>
    = 262+.
Note on
<conjunctionExpression>
shape:
A bare top-level index (e.g.
<conjunctionExpression>1</conjunctionExpression>
) deploys cleanly — the impl-side parser accepts bare tokens at the top level, and most positive single-condition fixtures in
enforce-o-matic-impl/test/func/filemetadata/
use it. It is not a deploy-time validation error. It does, however, crash the Data Governance Policy Builder UI on load — see §7.

  1. 每个
    <conditions>
    必须包含
    <operator>
    。缺少运算符→拒绝。
  2. 每个
    <conditions>
    必须至少包含一个路径元素(
    <resourcePath>
    <principalPath>
    <contextPath>
    <valueDomain>
    )。
  3. <contextPath>
    只能是
    SESSION_DATASPACE
    。请勿在此处放置资源路径值。
  4. 范围×类别必须符合第4节的矩阵。常见错误:ACCESS/GOVERNANCE + RECORD范围;RECORD + ANY/FIELD范围;TRANSFORM + ANY/RECORD范围。(除TRANSFORM外,效果与类别独立——参见第4节。)
  5. <resourceTransform>
    effect=Transform
    绑定。Transform效果需要resourceTransform,Permit/Forbid不得包含该元素。
  6. <policyRuleResourceDomains>
    必须用于RECORD(RLS)和FIELD范围的TRANSFORM规则;禁止用于ACCESS/GOVERNANCE规则。
  7. <conjunctionExpression>
    的索引必须与实际
    <conditions>
    数量匹配。索引偏移→拒绝。
  8. <conditions>
    内的
    <clause>
    必须与外层包装匹配(
    <when…>
    内为
    WHEN
    <unless…>
    内为
    UNLESS
    )。
  9. <valueString>
    中的JSON字面量必须将
    "
    转义为
    &quot;
    。错误转义会静默破坏字面量。
  10. 引用目标(
    <valueReference>
    <resourceDomain>
    )必须在部署时存在于目标组织中。
  11. SCALAR_ATTRIBUTE
    /
    PLURAL_ATTRIBUTE
    不在
    RulePrincipalPathType
    中——不属于MDAPI约定。此类场景请使用运行时RuleProvider。
  12. IDENTIFIED_RECORD
    无法通过MDAPI编写——
    SESSION_CONSUMER_ID
    不在
    RuleContextPathType
    中。
  13. 标准标记/分类的开发者名称为全限定点路径(例如
    DataGovernanceTags.ExternalData.Visibility.Public
    )。编写前请先检索现有规则以获取准确字符串。
  14. 最低API版本:
    PolicyRuleDefinition
    = 64.0;
    PolicyJsonExpression
    条件 = 66.0;
    <replicated>
    = 260+;
    <builderCompatible>
    /
    <builderValidated>
    = 262+。
关于
<conjunctionExpression>
格式的说明:
顶级裸索引(例如
<conjunctionExpression>1</conjunctionExpression>
)可正常部署——实现层解析器接受顶级裸标记,且
enforce-o-matic-impl/test/func/filemetadata/
中的大多数单条件示例均使用此格式。这不是部署时验证错误,但会导致Data Governance Policy Builder UI加载时崩溃——请参见第7节。

7. UI Compatibility — Core Rules

7. UI兼容性——核心规则

The Data Governance Policy Builder edits a strict subset of the MDAPI. Default goal: produce UI-compatible policies. Always confirm with the operator before producing API-only XML.
Hard blockers — any of these make the policy uneditable (and several crash the builder on load):
  • Missing OR-of-ENTITYTYPE clause on ACCESS/GOVERNANCE rules → hard crash:
    Cannot use 'in' operator to search for 'Permit' in undefined
    . Required even when paired with
    TupleRead
    (where it's functionally redundant at runtime). Must include
    IS
    conditions for
    {"t":"Text","v":"OBJECT"}
    and
    {"t":"Text","v":"FIELD"}
    .
  • Bare top-level condition index in
    <conjunctionExpression>
    (e.g.
    1
    , or
    (AND (OR 1 2) 3)
    ) → crash on builder load in
    buildCriteria
    . Deploy is unaffected, but the policy is uneditable in the UI. Always wrap:
    (AND 1)
    for a single condition;
    (AND (OR 1 2) (AND 3))
    instead of
    (AND (OR 1 2) 3)
    .
  • category = ACCESS_POLICY_RULE_DEFINITION
    +
    effect = Forbid
    → the Data Governance Policy Builder UI (not MDAPI) collapses it to GOVERNANCE on save; round-trip via the builder will rewrite the category. MDAPI deploy is unaffected — the original ACCESS+Forbid combination is valid and deploys without modification. If your goal is UI round-trippability, prefer GOVERNANCE for Forbid; if the source of truth is MDAPI, ACCESS+Forbid is fine.
  • Any
    <unlessPolicyRuleDefinitionClauseConjunction>
    block → silently dropped on first UI save.
  • More than one
    <action>
    → only the first is kept.
  • ruleConsumer
    DATACLOUD
    → UI hardcodes DATACLOUD on save.
  • Top-level
    (OR 1 2)
    conjunction → triggers
    // ERROR: Unsupported rule!
    path, rule silently dropped.
UI-compatible "unless" rewrite:
Author intentUI-compatible shape
unless principal has permission X
WHEN ASSIGNED_PERMISSIONS_PATH CONTAINS_NONE X
unless resource has tag X
WHEN TAG CONTAINS_NONE X
unless record field = value
WHEN RECORDFIELD NOT_EQUALS value
For the full UI-compatibility checklist, round-trip rules, and operator support matrix, see
references/ui-compatibility.md
.

Data Governance Policy Builder仅支持MDAPI的严格子集。默认目标:生成UI兼容的政策。在生成仅支持API的XML前,请务必与操作者确认。
硬性障碍——以下任何情况都会导致政策无法编辑(部分情况会导致Builder加载时崩溃):
  • ACCESS/GOVERNANCE规则缺少OR-of-ENTITYTYPE子句→ 严重崩溃:
    Cannot use 'in' operator to search for 'Permit' in undefined
    。即使与
    TupleRead
    配合使用(运行时功能冗余),也必须包含此子句。必须添加针对
    {"t":"Text","v":"OBJECT"}
    {"t":"Text","v":"FIELD"}
    IS
    条件。
  • <conjunctionExpression>
    中使用顶级裸条件索引(例如
    1
    (AND (OR 1 2) 3)
    )→ Builder加载时在
    buildCriteria
    中崩溃。部署不受影响,但政策无法在UI中编辑。请始终包装为:单条件使用
    (AND 1)
    ;将
    (AND (OR 1 2) 3)
    替换为
    (AND (OR 1 2) (AND 3))
  • category = ACCESS_POLICY_RULE_DEFINITION
    +
    effect = Forbid
    Data Governance Policy Builder UI(非MDAPI)会在保存时将其转换为GOVERNANCE;通过Builder往返编辑会重写类别。MDAPI部署不受影响——原始的ACCESS+Forbid组合有效且可正常部署。若需UI往返编辑兼容性,Forbid效果优先选择GOVERNANCE类别;若以MDAPI为权威来源,ACCESS+Forbid组合是可行的。
  • 任何
    <unlessPolicyRuleDefinitionClauseConjunction>
    块→ 首次UI保存时会被静默丢弃。
  • 多个
    <action>
    → 仅保留第一个。
  • ruleConsumer
    DATACLOUD
    → UI会在保存时硬编码为DATACLOUD。
  • 顶级
    (OR 1 2)
    组合→ 触发
    // ERROR: Unsupported rule!
    路径,规则被静默丢弃。
UI兼容的“unless”重写方式:
编写意图UI兼容格式
unless principal has permission X
WHEN ASSIGNED_PERMISSIONS_PATH CONTAINS_NONE X
unless resource has tag X
WHEN TAG CONTAINS_NONE X
unless record field = value
WHEN RECORDFIELD NOT_EQUALS value
完整的UI兼容性检查清单、往返规则以及运算符/路径支持矩阵请参见
references/ui-compatibility.md

8. Authoring Workflow

8. 编写流程

  1. Start from the closest template in
    references/templates.md
    — modify from there, don't start blank.
  2. Pick category first (§4). Category fixes effect, resourceScopeType, and whether policyRuleResourceDomains/resourceTransform are required.
  3. Lay out the bare rule: top-level fields only, no conditions. Match the category template in
    references/templates.md
    .
  4. Add conditions one at a time, each with all four anchors:
    <clause>
    ,
    <operator>
    , one path element, and the value.
  5. Update
    <conjunctionExpression>
    — 1-indexed prefix notation. Bare top-level index (e.g.
    1
    ) deploys but breaks the UI; wrap as
    (AND 1)
    if UI editability matters (§7).
  6. Run the UI-compatibility check (§7 /
    references/ui-compatibility.md
    ). If any item trips, attempt the "unless" rewrite first; if not possible, get explicit operator confirmation before continuing.
  7. Update
    package.xml
    — list each
    <members>
    for both types.
  8. Set
    <builderCompatible>
    on the set to
    true
    if §7 checklist passes;
    false
    if intentionally API-only.
  9. Sanity-check against §6 (guardrails) before considering done.
  10. Validate with dry-run before any non-dry deploy to a persistent org. Surface errors using the error reference in
    references/deploy-errors.md
    .
Three-layer correctness check before done:
  • Runtime / Cedar — does the rule enforce what's intended? (action choice, condition shape)
  • MDAPI deploy validity — does it deploy? (§6 guardrails, scope×category, tag dev names, org perms)
  • UI editability — can the builder render and re-save it? (§7 checklist, OR-of-ENTITYTYPE requirement)

  1. 从最接近的模板开始,位于
    references/templates.md
    ——基于模板修改,不要从零开始。
  2. 先选择类别(第4节)。类别决定效果、resourceScopeType以及是否需要policyRuleResourceDomains/resourceTransform。
  3. 搭建规则框架:仅包含顶级字段,无条件。匹配
    references/templates.md
    中的类别模板。
  4. 逐个添加条件,每个条件必须包含四个锚点:
    <clause>
    <operator>
    、一个路径元素和值。
  5. 更新
    <conjunctionExpression>
    ——采用1索引前缀表示法。顶级裸索引(如
    1
    )可部署但会破坏UI;若需UI可编辑性,请包装为
    (AND 1)
    (第7节)。
  6. 运行UI兼容性检查(第7节 /
    references/ui-compatibility.md
    )。若触发任何项,请先尝试“unless”重写;若无法重写,请在继续前获得操作者的明确确认。
  7. 更新
    package.xml
    ——列出两种类型的每个
    <members>
  8. 设置
    <builderCompatible>
    :若通过第7节检查清单,将集合的该值设为
    true
    ;若为故意仅支持API,则设为
    false
  9. 完成前对照第6节(防护准则)进行 sanity 检查
  10. 在非试运行部署到持久化组织前,先进行试运行验证。使用
    references/deploy-errors.md
    中的错误参考排查问题。
完成前的三层正确性检查
  • 运行时 / Cedar——规则是否按预期执行?(操作选择、条件格式)
  • MDAPI部署有效性——能否部署?(第6节防护准则、范围×类别、标记开发者名称、组织权限)
  • UI可编辑性——Builder能否渲染并重新保存?(第7节检查清单、OR-of-ENTITYTYPE要求)

Reference Docs

参考文档

DetailFile
Full path enums, operators, value sets, JSON expressions (PROJECTION / ARGLIST / SOQLTARGETLISTEXPR)
references/policy-schema-full.md
Copy-paste templates — index at
references/templates.md
; per-variant:
templates-access.md
,
templates-record.md
,
templates-transform.md
,
templates-advanced.md
Full UI-compatibility checklist, round-trip rules, operator/path support matrix
references/ui-compatibility.md
详情文件
完整路径枚举、运算符、值集、JSON表达式(PROJECTION / ARGLIST / SOQLTARGETLISTEXPR)
references/policy-schema-full.md
复制粘贴模板——索引位于
references/templates.md
;按变体分类:
templates-access.md
templates-record.md
templates-transform.md
templates-advanced.md
完整UI兼容性检查清单、往返规则、运算符/路径支持矩阵
references/ui-compatibility.md