Appearance
Classification, claim by claim
WIN-DLP-EPIC-019 asks to apply, read and interoperate with classification labels, because a label is the only piece of policy that travels with the file.
The agent now reads labels and can add its own bounded metadata label on Windows. It deliberately does not write customer-owned labels. A legacy policy's optional apply_label instruction names the value and must set replace_existing: true before a different MyDLP label may be replaced. Governed automatic rollout never replaces a different MyDLP label. Microsoft Purview/AIP labels remain read-only inputs.
1. The condition exists and now has tests
FileCondition::labels unions the labels on the file with those on the evaluation context and matches case-insensitively.
| Claim | Proved by |
|---|---|
| A label on the file matches a policy naming it | evaluate::tests::a_label_condition_matches_a_label_the_file_carries |
| Case does not decide it | same test |
| An unlabelled file does not match a label condition | evaluate::tests::a_label_condition_does_not_match_a_file_without_one |
| A label on the context counts as well as one on the file | evaluate::tests::a_label_on_the_context_counts_as_well_as_one_on_the_file |
Those are new (DLP-133). The condition had been implemented since the contract was written and had no test at all - which for the only piece of policy that travels with the file is the one worth having.
Case-insensitivity earns its own assertion because the failure is silent in the dangerous direction: a labelling system writing CONFIDENTIAL and a policy author typing Confidential mean the same thing, and a control that turned on the difference would quietly protect nothing.
The union of two sources is deliberate: a label read from the file, and one the surrounding context supplies - a labelled mailbox, a labelled share. A policy author should not have to know which one their labelling system uses.
2. What the endpoint reads and writes
Read: implemented on Windows. agent/core/src/classification_labels.rs reads the agent's MyDLP.Label alternate stream, the documented MSIP_Labels stream, and MSIP_Label_* values in OOXML docProps/custom.xml. Values are bounded and de-duplicated before they reach FileMetadata.labels; a malformed or unreadable metadata source never drops the file event. The Linux agent has no provider-specific label reader and continues to report no labels rather than guessing from a path.
Apply: implemented for the agent's own label on Windows. A policy may set apply_label: { value, replace_existing }. The agent writes only the MyDLP.Label stream. An existing customer label is preserved and an existing different MyDLP label is preserved unless replace_existing is explicitly true. The outcome - applied, already present, preserved, unsupported or failed - is included in the policy explanation carried by the event.
Interoperate: read-only by design. Purview labels are policy inputs, not an action. MyDLP never writes, downgrades or removes them, so Microsoft policy evaluation cannot be changed by a MyDLP label operation.
The existing condition remains compatible: a policy written as labels: ["Confidential"] matches case-insensitively against labels read from the file. apply_label is separate from the response action so a label write cannot be mistaken for a block or an allow. DLP-191 is the ticket, and its title carries the constraint that matters most: never overwrite a customer's.
3. Why "never overwrite" is the hard part
Recorded here because it is the security boundary DLP-191 implements and it is easy to get wrong on the way to something that demos well.
A classification label is an assertion by an organisation's own labelling system, usually with a signed or tenant-bound component. A DLP agent that writes labels is either:
- participating in that system - which means holding its keys, honouring its hierarchy, and getting downgrade rules right, or
- overwriting it - at which point the label no longer means what the organisation's other tools believe it means, and the one piece of policy that travels with the file has been corrupted by the tool that was supposed to enforce it.
Reading is far safer than writing and delivers most of the value: "this file is labelled Confidential and is going to a USB stick" is a complete policy without the agent ever writing anything. MyDLP therefore writes only its own stream and records the precedence decision beside the policy outcome.
4. Tenant governance and offline recommendation (DLP-405)
The signed policy payload now also carries the tenant's label-governance revision. Labels have stable ids, unique priorities, optional parents, exact channel scopes and optional display color/marking. Each recommendation mapping pins one classification id, semantic version and aggregate revision; it cannot silently follow a later definition.
The endpoint evaluates classifications once and passes those results to a pure resolver from the same verified bundle. Multiple matches select the label with the highest unique priority. If none maps, an exact-channel default wins over the tenant-wide default. Mandatory state and not_evaluated classifications remain explicit. This needs no server lookup, so connected and disconnected Windows endpoints reach the same result.
PolicyDecision.label reports detection, recommendation and application as separate fields and explicitly records that enforcement is independent. The current legacy apply_label operation still writes only MyDLP.Label; rollout from a recommendation is not silently enabled by adding the governance model. The separately gated automatic path is described below.
A removal or lower-priority transition can be configured to require one of a small set of reason codes. The transition contract contains stable ids and the code only-never document content, file paths or free-form text. External labels remain read-only and are always preserved.
The /labels console is the authoring surface for the revisioned aggregate. The server rejects hierarchy cycles, ambiguous priority, stale classification mappings and out-of-scope defaults before compiling a new bundle.
Microsoft and repository mapping boundary (DLP-407)
The same audited, signed governance revision can declare an Entra tenant GUID, one-to-one MyDLP label ↔ Microsoft sensitivity GUID coordinates, and exact SharePoint site/list/column/managed-term coordinates. The console shows these as read-only mappings, not a write permission. Invalid or unbound GUIDs, duplicate targets and MyDLP labels that no longer exist are rejected. Removing a MyDLP label in the console removes its external coordinates; rollback restores the prior mapping under a new governance revision.
The Windows reader continues to report the existing MSIP_Labels ADS and OOXML custom-property values to label policy conditions. Separately, it parses valid GUID groups with source (ADS or OOXML), SiteId, enabled state, set date and method. SiteId is matched to the declared tenant; a missing/foreign tenant, unknown GUID or disagreeing enabled ADS/OOXML observations cannot be interpreted as a MyDLP label. Set date and method do not establish the last human writer, which remains unknown. Mapping interpretation is not fed back into the existing label policy or used to write any Microsoft metadata.
ADR-0020 records the MIP File SDK and licensing/consent gates for a future local writer, and the separate Graph permission decision needed for a SharePoint writer. Neither writer, a protected-coauthoring LabelInfo reader, nor offline SDK labeling is present. On Linux, provider-specific metadata is still unsupported.
5. Staged rollout (DLP-406)
Each exact classification version/revision and channel can be Manual, Recommended, Shadow or Automatic. Manual is the safe default. Recommended emits a recommendation but writes nothing. Shadow evaluates the same pure projection used by the Windows file-scan path and records only outcome and bounded reason codes. The simulator evaluates the latest signed bundle as one versioned snapshot; it never stores the supplied text or a file path. Console users can record structured accept/reject feedback on a recommendation without storing content or document identity. That feedback is from the console simulation; this change does not add a signed-in-user desktop prompt.
Automatic is restricted to Windows file-create and file-modify events. The operator must set minimum confidence and match count for every contributing detector, collect at least 20 distinct inputs in recent Shadow simulations, including at least one the label would apply to and one it leaves alone, with no conflict or NotEvaluated result, and obtain approval from another authorized reviewer. Inputs are told apart by a keyed digest (PRIVACY_MODEL.md §33); running the same text again adds a sample but not an input (DLP-864). The evidence names who recorded the samples, so the reviewer can see when one person recorded all of them. Promotion and rollback are audited. Direct edits of Automatic governance are rejected; demote to Shadow and repeat review. Rollback republishes the immediately prior definition under a new, monotonic revision so endpoint anti-rollback is preserved.
The agent writes only its own MyDLP.Label stream when the projection is automatic and eligible. Encrypted, unsupported, timed-out, partially extracted and relevant NotEvaluated evidence fails closed. A different MyDLP label is a conflict; external labels are preserved. A legacy policy label action also prevents a second rollout write. Recommended and Shadow modes have unit tests proving the metadata writer is not invoked.
The Labels console reports active Windows agents, which checked in within ten minutes, which report the current signed bundle, and seven-day content-free endpoint outcome/reason counts. A published bundle is not fleet adoption. Simulation counts are runs, not independent files or statistical proof; reviewers must use representative cases and monitor live reasons and coverage before or after promotion. A quiet endpoint, older binary or filesystem that cannot write ADS is not counted as verified application. An endpoint write failure is reported as a failed label application, not silently reclassified as an applied label.
6. What is not covered
- No Purview label is written. Microsoft owns that taxonomy and its MIP licensing/keys; changing it would create a state neither product can explain. The read hook is intentionally limited to the documented ADS and OOXML property locations.
- No signed-in-user desktop acceptance flow. Recommendation feedback is recorded through the console simulator; it does not mutate the user's file. Manual mode never auto-applies. A desktop labelling UI would need a separate user/session-to-service authorization design and Windows fleet validation.
- A real signed-in Purview/Office tenant is not part of CI. Unit tests cover precedence and bounded policy input; the Windows target check covers the reader/writer build. End-to-end validation against a customer label still needs a Windows host carrying that customer's files and consent.