platform-datamask-run
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineseplatform-datamask-run: Salesforce Data Mask End-to-End Operation
platform-datamask-run: Salesforce Data Mask端到端操作
Use this skill to operate the Salesforce Data Mask feature on a sandbox: configure a
masking policy over PII fields, start a masking job, poll it to a terminal state, report which
records were masked, and abort a run that is still in progress.
Data Mask is sandbox-only — the run/abort REST endpoints return on production (a runtime
sandbox guard). Confirm the target org is a sandbox before starting.
403本技能用于在沙盒环境中操作Salesforce Data Mask功能:针对PII字段配置掩码策略、启动掩码任务、轮询任务直至进入终端状态、报告已掩码的记录,以及中止仍在进行中的任务。
Data Mask仅支持沙盒环境——在生产环境中调用运行/中止REST端点会返回(运行时沙盒防护机制)。启动任务前请确认目标组织为沙盒环境。
403When This Skill Owns the Task
本技能负责的任务场景
- Running a Data Mask job against a configured policy
- Polling masking-job status to completion
- Reporting masked-record counts / per-object results
- Aborting (canceling) an in-progress masking run
- Creating or identifying the policy the job runs against
Delegate elsewhere when the user is:
- hand-writing anonymization Apex →
platform-apex-generate - seeding or generating test data →
platform-data-manage - deploying unrelated metadata →
platform-metadata-deploy
- 针对已配置的策略运行Data Mask任务
- 轮询掩码任务状态直至完成
- 报告已掩码记录数量 / 按对象统计的结果
- 中止(取消)正在进行的掩码任务
- 创建或识别任务所使用的策略
当用户进行以下操作时,请委托至其他技能:
- 手动编写匿名化Apex代码 →
platform-apex-generate - 植入或生成测试数据 →
platform-data-manage - 部署无关元数据 →
platform-metadata-deploy
The One Thing to Get Right First: the API surface map
首要注意事项:API接口映射
The single biggest failure mode is assuming Data Mask entities are ordinary data-API objects.
They are not, and the surface differs per entity. Memorize this table before running anything —
guessing here is what turns a 3-second job into a 30-minute dead end.
| Entity | What it is | How you reach it |
|---|---|---|
| The masking policy shell (config) | Tooling API or Metadata API (thin shell: |
| An object targeted by a policy (holds the optional row filter) | Tooling API only — query AND insert; row-subset "sample" runs set |
| A field + its masking treatment | Tooling API only — query AND insert; treatment cols are |
| The job (one masking run) | Standard SOQL — |
| Per-object job detail (child, FK | Standard SOQL |
| Start a run | — | REST run API |
| Abort a run | — | REST run API |
Concretely:
- →
sf sobject describe --sobject DataMaskPolicy(don't retry it against standard API)NOT_FOUND - via
SELECT ... FROM DataMaskPolicy→sf data queryINVALID_TYPE - Query the policy via Tooling:
sf data query --use-tooling-api --query "SELECT Id, MasterLabel FROM DataMaskPolicy" - Query the job / job-detail via standard API:
sf data query --query "SELECT Id, Status FROM DataMaskPolicyJobRun"
Full command reference: .
references/api-surface.md最常见的失败原因是误以为Data Mask实体是普通的数据API对象。事实并非如此,且不同实体的接口存在差异。运行任何操作前请牢记下表——错误假设会让3秒就能完成的任务变成30分钟的死胡同。
| Entity | 类型说明 | 访问方式 |
|---|---|---|
| 掩码策略外壳(配置) | Tooling API 或 Metadata API(仅包含 |
| 策略目标对象(包含可选行过滤器) | 仅支持Tooling API —— 支持查询和插入;行子集“采样”运行需在此设置 |
| 字段及其掩码处理规则 | 仅支持Tooling API —— 支持查询和插入;处理规则列包括 |
| 任务实例(单次掩码运行) | 标准SOQL —— |
| 按对象统计的任务详情(子对象,外键 | 标准SOQL |
| 启动任务 | — | REST运行API |
| 中止任务 | — | REST运行API |
具体示例:
- →
sf sobject describe --sobject DataMaskPolicy(请勿在标准API中重试)NOT_FOUND - 通过执行
sf data query→SELECT ... FROM DataMaskPolicyINVALID_TYPE - 通过Tooling API查询策略:
sf data query --use-tooling-api --query "SELECT Id, MasterLabel FROM DataMaskPolicy" - 通过标准API查询任务/任务详情:
sf data query --query "SELECT Id, Status FROM DataMaskPolicyJobRun"
完整命令参考:。
references/api-surface.mdPick the workflow that matches the request
根据需求选择对应工作流
This skill has two distinct workflows. Select ONE up front from what the user asked for, then
run every step of that workflow — neither has optional steps:
| The user wants to… | Run | Ends when |
|---|---|---|
| Configure/edit a policy and mask records; report how many were masked | Workflow A — Mask & report (below) | The masked count is reported from the detail rows |
| Cancel / abort a masking run | Workflow B — Cancel a run (further below) | The job's status is confirmed |
Choose by the verb in the request. "Create/edit a policy and run it", "mask the PII", "how many
records were masked" → Workflow A only. "Abort", "cancel", "stop the run" → Workflow B. A
mask-and-report request does not include an abort: do not start a second job to "demonstrate"
cancelling — an unrequested run wastes a full ~5–10 min job (see the pool floor in A4) and is the top
cause of this task running out of turn before it finishes the masked count it was asked for.
本技能包含两种独立工作流。根据用户需求预先选择其中一种,然后执行该工作流的所有步骤——两种工作流均无可选步骤:
| 用户需求 | 运行工作流 | 结束标志 |
|---|---|---|
| 配置/编辑策略并掩码记录;报告已掩码的记录数量 | 工作流A — 掩码并报告(如下) | 从详情行中报告已掩码记录数量 |
| 取消/中止掩码任务 | 工作流B — 取消任务(如下) | 确认任务状态为 |
根据请求中的动词进行选择。“创建/编辑策略并运行”、“掩码PII”、“已掩码多少条记录” → 仅使用工作流A。“中止”、“取消”、“停止任务” → 使用工作流B。掩码并报告的请求不包含中止操作:请勿启动第二个任务来“演示”取消——未被请求的任务会浪费约5–10分钟的任务时间(见A4中的池底延迟),也是导致任务在完成已请求的掩码数量前超时的最主要原因。
Workflow A — Mask & report
工作流A — 掩码并报告
A1. Confirm sandbox + capture org context
A1. 确认沙盒环境并捕获组织上下文
Verify the org is a sandbox and grab the instance URL + a session token for the run-API calls:
bash
sf org display --target-org <alias> --json验证目标组织为沙盒环境,并获取实例URL和会话令牌用于调用运行API:
bash
sf org display --target-org <alias> --jsonA2. Identify or create the policy
A2. 识别或创建策略
Prefer reusing an existing policy (fastest, no deploy):
bash
sf data query --use-tooling-api --target-org <alias> \
--query "SELECT Id, DeveloperName, MasterLabel FROM DataMaskPolicy"If none targets the Contact PII you need, author one with the two-step recipe (the
Metadata shape is a thin shell; membership is Tooling-inserted):
DataMaskPolicy- Metadata-deploy the thin shell in mdapi format (+
--metadata-dir; a source-formatpackage.xmldeploy fails "Could not infer a metadata type"). The shell carries only--source-dir,<label>,<description>. This creates the policy with an active revision, which A2 requires.<runOnRefresh> - Tooling-insert the (one per object) then its
DataMaskPolicyObjectrows. Each field row's treatment isDataMaskPolicyField(MaskingCategory) +library(a snake_case token likeMaskValue,first_name,email). There is nophonecolumn.MaskingRuleType
Insert order matters: a Tooling-created parent (no active revision) makes the child insert fail. Metadata-deploy the shell first.INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY
See for the full recipe and the token table. Choose a
appropriate to each field; do not blanket-replace.
references/policy-authoring.mdMaskValueMaskValue优先复用现有策略(最快,无需部署):
bash
sf data query --use-tooling-api --target-org <alias> \
--query "SELECT Id, DeveloperName, MasterLabel FROM DataMaskPolicy"如果没有策略针对你需要处理的Contact PII数据,请按照两步法创建策略(元数据结构为轻量外壳;成员需通过Tooling API插入):
DataMaskPolicy- 以mdapi格式元数据部署轻量外壳(使用+
--metadata-dir;使用source格式的package.xml部署会失败,提示"Could not infer a metadata type")。外壳仅包含--source-dir、<label>、<description>。此步骤会创建带有活动版本的策略,这是A2的必要条件。<runOnRefresh> - 通过Tooling API插入(每个对象对应一条记录),然后插入
DataMaskPolicyObject记录。每条字段记录的处理规则为DataMaskPolicyField(MaskingCategory) +library(类似MaskValue、first_name、email的蛇形命名令牌)。不存在phone列。MaskingRuleType
插入顺序至关重要:通过Tooling API创建的父对象(无活动版本)会导致子对象插入失败,提示。请先部署元数据外壳。INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY
完整创建指南和令牌表请参考。为每个字段选择合适的;请勿统一替换。
MaskValuereferences/policy-authoring.mdMaskValueA3. Start the masking run (REST run API)
A3. 启动掩码任务(REST运行API)
bash
printf '{}' > ./empty-body.json
sf api request rest \
"/services/data/v67.0/platform/data-resilience/data-mask/policies/{policyId}/run" \
--method POST --body @./empty-body.json --target-org <alias>The endpoint needs an empty JSON body () — requires on a POST
even when the API takes no payload. Pass the file with an prefix ();
without it the literal path is sent as the body and the API returns . A returns , , (the run-API
status is UPPERCASE, e.g. ) and . A /
means a run is already in progress for that policy.
{}sf api request rest--body@--body @./empty-body.jsonJSON_PARSER_ERROR200jobRunIdpolicyIdstatusRUNNINGmessage: "Job started successfully"409CONFLICTWriteNOW, before you poll — do not wait until the end. The masking job takes several minutes (see below), and the single most common way this task scores zero is the turn ending during the poll with no output file written at all. The instant you have thereport.md, writejobRunIdwith everything known so far (policy Id/label, the run command, thereport.md, statusjobRunId, and a "polling for completion…" placeholder for the masked count). Then update that same file once the job finishes. A report that exists and says "still running" beats no file; a fabricated count is worse than either — only fill the count from the detail rows (A5).RUNNING
bash
printf '{}' > ./empty-body.json
sf api request rest \
"/services/data/v67.0/platform/data-resilience/data-mask/policies/{policyId}/run" \
--method POST --body @./empty-body.json --target-org <alias>该端点需要空JSON请求体()——即使API不需要负载,在POST请求时仍需指定。使用前缀传递文件();如果不添加,字面路径会被作为请求体发送,API会返回。返回状态码时会包含、、(运行API返回的状态为大写,例如)以及。返回/表示该策略已有任务在运行中。
{}sf api request rest--body@--body @./empty-body.json@JSON_PARSER_ERROR200jobRunIdpolicyIdstatusRUNNINGmessage: "Job started successfully"409CONFLICT立即编写,不要等到轮询结束。掩码任务需要数分钟时间(如下所述),导致任务得分为零的最常见原因是轮询期间任务超时,且未生成任何输出文件。一旦获取到report.md,立即编写jobRunId,填入当前已知的所有信息(策略ID/标签、运行命令、report.md、状态jobRunId,以及用于填写掩码数量的“轮询中……”占位符)。然后在任务完成后更新该文件。一份存在且显示“运行中”的报告比没有报告要好;编造的数量比这两种情况都糟——仅从A5的详情行中获取掩码数量。RUNNING
A4. Poll to a terminal state (standard SOQL)
A4. 轮询直至进入终端状态(标准SOQL)
Poll until it reaches a terminal value. Do not report a
mid-run status as final.
DataMaskPolicyJobRun.Status- Mid-run (pre-work): ,
pending— the job is queued but not yet abortablescheduled - Mid-run (working): — this is the only state in which abort succeeds
running - Terminal: ,
completed,completed_with_errorsfailed - Abort target: (single "l")
canceled
pendingrunningpendingscheduled409 CONFLICTrunningJobs are slow — expect several minutes, and poll with the bundled script. Data Mask runs on a
backend pool/scheduler with a ~5–10 minute floor: even a tiny (20-row) job usually does not
reach a terminal state or emit detail rows for several minutes after the run starts. This is fixed
overhead, not proportional to row count. Plan the run around it — the single biggest failure mode
is treating the job as instant, polling on a tight interval, and either timing out or writing a
"still pending" report.
Run as a single command — do not hand-roll a SOQL poll loop:
scripts/poll-job.shbash
bash scripts/poll-job.sh <alias> <jobRunId> # defaults: cap 600s (10 min), 20s intervalIt sleeps on a low-frequency interval, short-circuits the instant a ground-truth detail row appears,
prints the terminal signal (//) on stdout, and exits (or on
timeout). Call it once and read its result — do not wrap it in your own retry loop, and do not
poll on a sub-10s interval (it just burns tool calls against a job that cannot finish sooner).
completedfailedcanceled01Ground truth is the detail rows, not the parent status. The parent
can lag — it may read / for a while after masking actually finished. Once a
(or ) row exists, the masking is done.
already encodes all of this — the bounded interval and timeout, the short-circuit on
the ground-truth detail row, and the terminal-signal exit code — so you do not re-implement any
of it inline. Run the poller once, read its exit signal, then update (the stub you wrote
before polling) with the terminal status and the masked count from A5.
DataMaskPolicyJobRun.Statuspendingrunningtotal_records_maskedcompletedDataMaskPolicyJobRunDtlpoll-job.shreport.md轮询直至其变为终端值。请勿将运行中的状态报告为最终状态。
DataMaskPolicyJobRun.Status- 运行前(待处理):、
pending——任务已排队但尚未可中止scheduled - 运行中:——这是唯一可成功中止的状态
running - 终端状态:、
completed、completed_with_errorsfailed - 中止目标状态:(单个"l")
canceled
pendingrunningpendingscheduled409 CONFLICTrunning任务运行缓慢——预计需要数分钟,请使用捆绑脚本进行轮询。Data Mask运行在后端池/调度器上,存在约5–10分钟的基础延迟:即使是小型(20行)任务,通常在启动后数分钟内也不会进入终端状态或生成详情行。这是固定开销,与行数无关。请据此规划任务——最常见的失败原因是将任务视为即时完成,使用过短的间隔轮询,导致超时或生成“仍待处理”的报告。
运行作为单个命令——请勿手动编写SOQL轮询循环:
scripts/poll-job.shbash
bash scripts/poll-job.sh <alias> <jobRunId> # 默认设置:最长等待600秒(10分钟),间隔20秒该脚本会以低频率间隔休眠,一旦出现真实的详情行就会立即终止,在标准输出中打印终端信号(//),并返回(超时则返回)。调用一次并读取结果——请勿将其包裹在自定义重试循环中,也不要使用小于10秒的间隔轮询(这只会浪费工具调用次数,而任务无法更快完成)。
completedfailedcanceled01真实状态以详情行为准,而非父任务状态。父任务可能存在延迟——掩码实际完成后,它可能仍显示/状态一段时间。一旦出现包含(或)的记录,掩码即完成。已包含所有逻辑——有限的等待时间和超时机制、基于真实详情行的终止条件、终端信号退出码——因此你无需手动实现任何逻辑。运行一次轮询脚本,读取其退出信号,然后更新之前编写的(轮询前的草稿),填入终端状态和A5中的掩码数量。
DataMaskPolicyJobRun.Statuspendingrunningtotal_records_maskedcompletedDataMaskPolicyJobRunDtlpoll-job.shreport.mdA5. Report results from the job DETAIL object
A5. 从任务详情对象报告结果
The parent job carries an overall status; per-object masked counts live on the child
(linked by ). Report a concrete count, not a
fabricated one:
DataMaskPolicyJobRunDtlDataMaskPolicyJobRunIdbash
sf data query --target-org <alias> \
--query "SELECT Id, DataMaskPolicyJobRunId, Status FROM DataMaskPolicyJobRunDtl WHERE DataMaskPolicyJobRunId = '<jobRunId>'"Report only what the rows literally show — do not overstate granularity. The detail rows are
object-level status_update entries (, , for the object,
e.g. Contact). They are not per-field rows. So state per-object success as an observed fact
("Contact: 27/27 records masked, 0 error rows"), but frame field-level success as an inference,
not a direct observation — say "no field-level error rows were returned, so no field is reported as
failed", not "all 5 fields succeeded" (the data does not carry a per-field success row to back
that claim). Overstating an inference as an observation is the most common factuality miss here.
loadedcompletedtotal_records_masked父任务包含整体状态;按对象统计的掩码数量存储在子对象中(通过关联)。报告真实的统计数量,请勿编造:
DataMaskPolicyJobRunDtlDataMaskPolicyJobRunIdbash
sf data query --target-org <alias> \
--query "SELECT Id, DataMaskPolicyJobRunId, Status FROM DataMaskPolicyJobRunDtl WHERE DataMaskPolicyJobRunId = '<jobRunId>'"仅报告记录中明确显示的内容——不要夸大粒度。详情行是对象级的状态更新记录(、、对象的,例如Contact)。它们不是按字段统计的记录。因此,将对象级成功作为观察事实进行陈述("Contact:27/27条记录已掩码,0条错误行"),但将字段级成功作为推断而非直接观察结果——例如说"未返回字段级错误行,因此无字段被报告为失败",不要说"所有5个字段均成功"(数据中没有按字段统计的成功记录来支持这一说法)。将推断夸大视为观察结果是此处最常见的事实错误。
loadedcompletedtotal_records_maskedWorkflow B — Cancel a run
工作流B — 取消任务
Use this workflow when the request is to abort/cancel a masking run. It targets the run that is
currently in progress — aborting is an on-demand action against a live job; nobody starts a job
just to cancel it. Steps B1–B4 are all required.
当用户请求中止/取消掩码任务时使用本工作流。它针对当前正在运行的任务——中止是针对活跃任务的按需操作;没有人会为了取消而启动任务。步骤B1–B4均为必填步骤。
B1. Confirm sandbox + identify the run to cancel
B1. 确认沙盒环境并识别要取消的任务
Confirm the org is a sandbox () and get the of the run to abort — the one
the user is asking to cancel. Capture its too — you need it to start a
replacement run if the abort window is missed (B2 exit 3 / exit 1). If they just started it, use that
id; otherwise query for the active run:
sf org displayjobRunIdDataMaskPolicyIdbash
sf data query --target-org <alias> \
--query "SELECT Id, Status, DataMaskPolicyId FROM DataMaskPolicyJobRun ORDER BY CreatedDate DESC LIMIT 5"Note the ( prefix) of the run you pick — that is the A3 needs.
DataMaskPolicyId8dm<policyId>确认目标组织为沙盒环境(),并获取要中止的任务的——即用户请求取消的任务。同时捕获其——如果错过中止窗口(B2的退出码3/1),你需要用它启动替换任务。如果用户刚刚启动任务,使用该ID;否则查询活跃任务:
sf org displayjobRunIdDataMaskPolicyIdbash
sf data query --target-org <alias> \
--query "SELECT Id, Status, DataMaskPolicyId FROM DataMaskPolicyJobRun ORDER BY CreatedDate DESC LIMIT 5"记录你选择的任务的(前缀为)——这是A3中需要的。
DataMaskPolicyId8dm<policyId>B2. Wait for the job to be running
(the only abortable state)
runningB2. 等待任务变为running
状态(唯一可中止的状态)
runningYou can only abort while is . A / job
s; a terminal one is already done. Poll for the window with the bundled poller in its
mode — it exits the instant the status reads (unlike the default mode, which
waits for a terminal state), so it will not block past the abortable window:
DataMaskPolicyJobRun.Statusrunningpendingscheduled409runningrunningrunningbash
POLL_MODE=running bash scripts/poll-job.sh <alias> <jobRunId> 900 15The cap is 900s (15 min), above the ~5–10 min scheduling floor so a slow-to-start job still gets
caught. Handle every exit:
- Exit (prints
0) → go straight to B3.running - Exit → the job raced to a terminal state before
3was caught; the abort window is gone. Start a fresh run against the policy you captured in B1 (A3 with thatrunning), then return here and poll the new<policyId>.jobRunId - Exit (timeout — the cap expired) → re-query the job's status:
1If it is still non-terminal (bashsf data query --target-org <alias> \ --query "SELECT Id, Status FROM DataMaskPolicyJobRun WHERE Id = '<jobRunId>'"/pending/scheduled), re-run the poller once more (same command) to continue waiting. If it isrunning, go to B3. If it is terminal, treat it like exit 3 — start a fresh run (A3 with the B1running) and poll the new job.<policyId>
Because of the ~5–10 min pool floor the window is usually minutes wide, so there is time to
catch it; do not poll with no delay.
runningIf no run is currently in progress (the job already completed, or you must reproduce a run→cancel flow end to end), start one first with A3, then return here — poll it toand abort that live job. Never substitute an older, already-terminal job to "show" a cancel; the abort must target the run that is actually live.running
仅当为时才能中止任务。对/状态的任务执行中止会返回;终端状态的任务已完成。使用捆绑的轮询脚本的**模式**轮询窗口——一旦状态变为就会立即退出(与默认模式等待终端状态不同),因此不会在中止窗口过后继续阻塞:
DataMaskPolicyJobRun.Statusrunningpendingscheduled409runningrunningrunningbash
POLL_MODE=running bash scripts/poll-job.sh <alias> <jobRunId> 900 15最长等待时间为900秒(15分钟),高于约5–10分钟的调度基础延迟,因此即使启动缓慢的任务也能被捕获。处理所有退出情况:
- 退出码(打印
0)→ 直接进入B3。running - 退出码→ 任务在捕获到
3状态前已进入终端状态;中止窗口已关闭。针对B1中捕获的策略启动新任务(使用该running执行A3),然后返回此处轮询新的<policyId>。jobRunId - 退出码(超时——最长等待时间已到)→ 重新查询任务状态:
1如果状态仍为非终端(bashsf data query --target-org <alias> \ --query "SELECT Id, Status FROM DataMaskPolicyJobRun WHERE Id = '<jobRunId>'"/pending/scheduled),再次运行一次轮询脚本(相同命令)继续等待。如果状态为running,进入B3。如果状态为终端,按照退出码3处理——启动新任务(使用B1的running执行A3)并轮询新任务。<policyId>
由于约5–10分钟的基础延迟,窗口通常有数分钟宽,因此有足够时间捕获;请勿无延迟轮询。
running如果当前没有任务在运行(任务已完成,或者你必须完整复现运行→取消流程),先通过A3启动任务,然后返回此处——轮询至状态并中止该活跃任务。切勿使用已终止的旧任务来“演示”取消;中止操作必须针对实际活跃的任务。running
B3. Abort via the run API
B3. 通过运行API中止任务
Abort via the run API — not by DML/delete on the job record:
bash
sf api request rest \
"/services/data/v67.0/platform/data-resilience/data-mask/jobs/{jobRunId}/abort" \
--method POST --body @./empty-body.json --target-org <alias>Empty JSON body () via the -prefixed file, as above. A returns
(uppercase, from the run API) and . A means the job was not in
a state (usually still /) — return to B2 and resume polling.
{}@200status: "CANCELED"message: "Job abort requested"409runningpendingscheduled通过运行API中止任务——不要通过DML/删除任务记录来中止:
bash
sf api request rest \
"/services/data/v67.0/platform/data-resilience/data-mask/jobs/{jobRunId}/abort" \
--method POST --body @./empty-body.json --target-org <alias>使用前缀的文件传递空JSON请求体(),如上所述。返回状态码时会包含(运行API返回的状态为大写)以及。返回表示任务未处于状态(通常为/)——返回B2继续轮询。
@{}200status: "CANCELED"message: "Job abort requested"409runningpendingscheduledB4. Confirm and report the cancellation
B4. 确认并报告取消结果
Cancellation is asynchronous. Re-query and confirm
(lowercase, from SOQL) before reporting the abort succeeded. Verify:
DataMaskPolicyJobRunStatus = canceled- Confirmed the abort targeted the live job while its queried status was .
running - Re-queried after the abort and saw
DataMaskPolicyJobRun.Status = canceled
取消操作是异步的。重新查询并确认(SOQL返回的状态为小写)后,再报告中止成功。验证以下内容:
DataMaskPolicyJobRunStatus = canceled- 确认中止操作针对的是查询状态为的活跃任务。
running - 中止后重新查询,确认状态为
DataMaskPolicyJobRun。canceled
High-Signal Rules
高优先级规则
| Rule | Rationale |
|---|---|
Run each | |
Never use standard SOQL / | They return |
Read masked counts from | The child detail is the source of truth for per-object results |
Only | Reporting |
| Abort only via the run-API abort endpoint | DML/delete on the job record is not a real abort and corrupts state |
Always re-query status after abort and confirm | An abort call returning 200 is not proof the job stopped |
| Data Mask runs on sandboxes only | Run/abort endpoints |
Use API version | The run/abort endpoints are |
Poll via | The script caps attempts and short-circuits on the ground-truth detail row; a manual loop against the lagging parent status is the #1 cause of a run timing out with no report |
| 规则 | 理由 |
|---|---|
运行每个 | |
切勿对 | 它们会返回 |
从 | 子对象详情是按对象统计结果的唯一可信来源 |
仅 | 将 |
| 仅通过运行API的中止端点执行中止操作 | 通过DML/删除任务记录并非真正的中止操作,会破坏状态 |
中止后务必重新查询状态并确认 | 中止调用返回200并不代表任务已停止 |
| Data Mask仅在沙盒环境中运行 | 在生产环境中调用运行/中止端点会返回 |
使用API版本 | 运行/中止端点路径为 |
通过 | 该脚本会限制尝试次数,并基于真实的详情行终止轮询;手动循环依赖延迟的父任务状态是导致任务超时且无报告的头号原因 |
Gotchas
常见问题
| Issue | Resolution |
|---|---|
| It's a Tooling/MDAPI entity — query with |
| Same cause — use Tooling API for the policy; standard API only for |
Run start returns | A run is already in progress for that policy — poll the existing one or wait for it to finish |
Abort returns | The job is still |
| Small job finishes before you can abort it | The |
Abort returns | Cancellation is async — keep polling the SOQL status until |
Run API says | Case + surface differ: the run API is UPPERCASE, SOQL picklist is lowercase. Trust the SOQL value for terminal state |
| Job "finished" instantly | Re-check: |
Run/abort endpoint | The path must be |
| 问题 | 解决方案 |
|---|---|
| 这是Tooling/MDAPI实体——使用 |
| 原因同上——对策略使用Tooling API;仅对 |
启动任务返回 | 该策略已有任务在运行中——轮询现有任务或等待其完成 |
中止操作返回 | 任务仍处于 |
| 小型任务在你执行中止前已完成 | 在小型沙盒中 |
中止操作返回 | 取消操作是异步的——继续轮询SOQL状态直至变为 |
运行API返回 | 大小写和接口存在差异:运行API返回大写,SOQL选择列表返回小写。终端状态以SOQL值为准 |
| 任务“立即完成” | 重新检查: |
运行/中止端点返回 | 路径必须为 |
Output Format
输出格式
Report the sections for the workflow you ran — do not add sections for the other one. Keep it
tight — show each command once, at the step it belongs to; do not append a second "full command log"
that repeats calls already shown. Prefer a compact table over prose; a reader should reach the key
result in the first screenful.
Workflow A (mask & report):
- Policy used (Id + label, and whether reused or created)
- Run — job Id, final terminal status, masked-record count (from the detail object). Collapse
the poll loop to one line (e.g. "polled 5×, →
running"); do not print a row per poll.completed - Per-object results — from . Report the object-level counts the rows actually carry; if there are no field-level error rows, say so as an inference ("no field-level errors reported"), not as a claimed per-field success. See A5 for the exact phrasing.
DataMaskPolicyJobRunDtl - Commands run — already shown inline above; here just list any not yet shown. Do not re-paste the full sequence a second time.
Workflow B (cancel a run):
- Job cancelled — the job Id, that it was when aborted, that the abort was issued via the run-API abort endpoint, and the re-queried
runningstatus.canceled - Commands run — as above, no re-pasting.
Accuracy notes that keep factuality high:
- The run/abort REST response returns a 15-character (e.g.
jobRunId); SOQL returns the 18-character form of the same record (e.g.1aGXK0000000uob). They are the same job — when both appear, note that rather than presenting them as two IDs.1aGXK0000000uob2AA - Do not assert a masked count, a per-field outcome, or a terminal status you did not actually query. Every number in the report must trace to a query result shown in the command log.
仅报告你运行的工作流对应的章节——不要添加另一个工作流的章节。保持简洁——每个命令仅在对应步骤中显示一次;不要附加重复已显示调用的“完整命令日志”。优先使用紧凑表格而非 prose;读者应能在第一屏中看到关键结果。
工作流A(掩码并报告):
- 使用的策略(ID + 标签,以及是否复用或新建)
- 任务运行情况——任务ID、最终终端状态、已掩码记录数量(来自详情对象)。将轮询循环简化为一行(例如“轮询5次,→
running”);不要打印每次轮询的记录。completed - 按对象统计的结果——来自。报告记录中实际包含的对象级数量;如果没有字段级错误行,将其作为推断陈述(“未报告字段级错误”),不要声称每个字段都成功。详见A5中的准确表述。
DataMaskPolicyJobRunDtl - 运行的命令——已在上述步骤中内联显示;此处仅列出未显示的命令。不要再次粘贴完整命令序列。
工作流B(取消任务):
- 已取消的任务——任务ID、中止时状态为、通过运行API中止端点执行中止操作,以及重新查询得到的
running状态。canceled - 运行的命令——如上所述,不要再次粘贴。
提升事实准确性的注意事项:
- 运行/中止REST响应返回15位(例如
jobRunId);SOQL返回同一记录的18位格式(例如1aGXK0000000uob)。它们是同一个任务——当两者同时出现时,请注明这一点,不要将其视为两个不同的ID。1aGXK0000000uob2AA - 不要断言你未实际查询到的掩码数量、字段级结果或终端状态。报告中的每个数字都必须能追溯到命令日志中显示的查询结果。
Cross-Skill Integration
跨技能集成
| Need | Delegate to | Reason |
|---|---|---|
| Seed realistic PII records to mask | platform-data-manage | Test-data creation |
| Author custom anonymization Apex | platform-apex-generate | Apex authoring |
| Deploy the policy metadata to the org | platform-metadata-deploy | Metadata deployment |
| 需求 | 委托至 | 理由 |
|---|---|---|
| 植入真实的PII记录以便掩码 | platform-data-manage | 测试数据创建 |
| 编写自定义匿名化Apex代码 | platform-apex-generate | Apex代码编写 |
| 将策略元数据部署至组织 | platform-metadata-deploy | 元数据部署 |
Reference File Index
参考文件索引
| File | When to read |
|---|---|
| Exact per-entity API surface, all CLI commands, run/abort REST endpoints, and status picklist values |
| Two-step authoring recipe (MDAPI thin shell → Tooling object/field inserts) and the |
| The run → poll → report → re-run → abort sequence in full, with sample responses |
| Bounded poller: waits for a terminal status (default) or, with |
| 文件 | 阅读场景 |
|---|---|
| 各实体的准确API接口、所有CLI命令、运行/中止REST端点,以及状态选择列表值 |
| 两步法创建指南(MDAPI轻量外壳 → Tooling对象/字段插入)以及 |
| 完整的运行 → 轮询 → 报告 → 重新运行 → 中止流程,包含示例响应 |
| 有限轮询工具:默认等待终端状态,设置 |