Data Classification Labels
Every asset (cog) in MOD carries a data classification label. Labels are a handling-and-routing mechanism: they decide how content may be used by MOD's AI features and, when export-control gating is turned on, which users and workers may touch it. MOD supports an operator's classification controls; MOD does not make a customer compliant with any framework, and setting labels does not by itself satisfy any control — the operator remains responsible for their own policy and assessment.
The label levels
Labels are strictly ordered, low to high:
public < internal < confidential < restricted < CUI < EAR < ITAR
public,internal,confidential,restrictedare the four internal handling tiers. New assets default tointernal.CUI(Controlled Unclassified Information) sits above the internal tiers: it carries marking and dissemination controls stricter than ordinary internal handling, while remaining "unclassified".EAR(Export Administration Regulations) ranks above CUI: release to unauthorized persons can be an export violation even without a federal contract.ITAR(International Traffic in Arms Regulations) is the top tier: defence articles and services with the strictest US-person rules.
Labels are stored on the asset (cogs.data_classification) and are matched
case-insensitively against the seven known levels. An unrecognised stored
label is never silently accepted or downgraded — it fails closed (treated as
restricted), so a corrupt label cannot become a loophole.
How labels propagate to outputs
When a workflow run produces an output asset, the output inherits the
highest label among its inputs (max(input levels)). If the output was
already hand-marked at a higher level, that marking is kept — propagation
never silently downgrades an output.
Who can set and change labels
- Moves entirely within the four internal tiers (
public…restricted) can be made by ordinary users. CUI,EARandITARare admin-gated: only a tenant admin or a platform admin may raise an asset into, lower it out of, or move it within that gated band. A non-admin attempt is refused with a 403.- Every label change is audited. Audit events:
DATA_CLASSIFICATION_SET(raise) andDATA_CLASSIFICATION_LOWERED(lower), each recording the cog id, old and new level, and the actor.
What the labels enforce today
1. Labelled data is never sent to external AI providers
Any request that references restricted-labelled content — restricted,
CUI, EAR or ITAR — is refused at the LLM-egress gate when the AI
binding points at an external (non-local, non-managed) provider. This
covers the support chat, the logs chat and the assistant; Node
Wizard coverage is being added.
- Governed by the platform setting
labels.block_external_llm(group "labels", default on). - Local and MOD-hosted models are unaffected. A local or stack LLM endpoint (e.g. an Ollama instance, a LAN IP, or a stack alias) keeps serving labelled content; only provider URLs classified as external are refused.
- The label block overrides any tenant external-LLM opt-in: a tenant that opted into external LLM use is still refused for labelled content.
- The policy fails closed: if the settings read or the label lookup errors, the request is blocked rather than silently allowed.
- Refusals are audited as
LLM_EXTERNAL_BLOCKED_LABEL(details carry the surface, provider host and setting — never the prompt), and the API log shows aGY.C7: external LLM binding refusedline.
2. Export-control US-person gating
On top of the taxonomy, an optional US-person gate can be enabled with two platform settings (both default off, so nothing changes until the operator opts in):
compliance.export_control_enforced— master switch. When on, EAR/ITAR assets require a US person, and tasks whose inputs carry EAR/ITAR run only on US-person-operated workers.compliance.cui_requires_us_person— additionally gates CUI assets (requires the master switch to be on as well).
The US-person attribute on a user is set only by a tenant admin or platform
admin (PATCH /v1/users/{user_id}/export-control); non-admin and
cross-tenant attempts are refused. With gating on, a non-US user reading or
downloading an EAR/ITAR asset gets a 403, and a multi-file download is denied
if any file in the set is EAR/ITAR labelled.
How to verify
Check the audit trail (audit_events):
| Action | Event name |
|---|---|
| Label raised / lowered | DATA_CLASSIFICATION_SET / DATA_CLASSIFICATION_LOWERED |
| External-LLM request refused by the label block | LLM_EXTERNAL_BLOCKED_LABEL |
| US-person attribute set | US_PERSON_FLAG_SET |
| Export-control read/download denial | EXPORT_CONTROL_ACCESS_DENIED |
Manual test steps for each path live in CORE/API/tests/MANUAL_TEST_DATA_CLASSIFICATION.md
(GY.V2a / GY.V2b) and CORE/API/tests/MANUAL_TEST_GSEC_FIXES.md (GY.C7).
Watermark on labelled downloads (GY.V1b)
An optional download watermark (three platform settings, all default off, so nothing changes until the operator opts in):
compliance.watermark_downloads_enabled— master switch. When on, an asset whose label is at or above the minimum is not handed out as a direct presigned URL: it is streamed through MOD's API with the watermark applied, and the delivery audit row recordsdelivery_path = "watermark".compliance.watermark_min_label— the lowest label that triggers it (defaultconfidential).compliance.watermark_unsupported_action—allow(default) delivers the original bytes for a content type this release cannot watermark and recordsmetadata.watermark = "unsupported";blockrefuses the delivery with a 403.
Two layers are applied to images (PNG / JPEG / WebP only in this release):
- a visible tiled semi-transparent diagonal overlay naming the recipient, the UTC timestamp and the download id;
- an invisible payload carrying the same download id in the luma channel as block-DCT sign bits with a checksum, so a leaked copy is self-identifying without trusting the client. It survives a lossless PNG round-trip and a JPEG quality-90 re-encode.
MOD supports leak tracing for an operator's own policy; MOD does not make a customer compliant with TPN or any other framework, and a watermark is a deterrent plus an attribution aid — not a control that satisfies one on its own.
Extended to share-link and zip deliveries (GY.V1c)
The same three settings and the same label gate cover the other two delivery paths:
- Share-link downloads (public embed run-surface output presign): a gated image output is not handed out as a presigned URL for the original blob — it is watermarked and re-published to a short-lived temp object that the presign points at. The payload identifies the share link (link id), not a user.
- Zip / bulk export (folder, multi-cog and download-job archives): labelled image members are watermarked in place before the archive is written; non-image and unlabelled members pass through byte-identical.
Both paths still emit the existing delivery audit row. Fail-closed: if a label
requires a watermark and it cannot be applied (e.g. a non-image under
unsupported_action = "block", or an embedding that fails), the delivery is
refused and the refusal is audited (metadata.watermark = "refused") rather than
serving the unmarked file.
MOD supports leak tracing for an operator's own policy across every delivery path; MOD does not make a customer compliant with TPN or any other framework, and a watermark is a deterrent plus an attribution aid — not a control that satisfies one on its own.
Manual test steps: CORE/API/tests/MANUAL_TEST_GSEC_FIXES.md (GY.V1b and GY.V1c
sections), including the one-liner that reads the invisible payload back out of a
saved file.
Download and export marking (GY.V2 R-133)
A label used to "die at the asset row" — the file you downloaded carried none of
it. R-133 closes that gap for every content type (the image watermark above
is a separate, additional mechanism). An asset is considered marked when its
label is above public/internal; a corrupt stored label fails closed as ITAR.
- Response headers. Every marked download, stream, zip export and share-link
output carries
X-MOD-Classification(the export-control banner for CUI/EAR/ITAR —CUI//<cat>,EAR (ECCN ..),ITAR— or the level name for higher internal tiers). CUI, EAR and ITAR additionally carry a shortX-MOD-Handlingcaveat. Presigned S3 URLs cannot carry custom headers, so the marking rides on the API's JSON response and, for zips, inside the archive itself. - Zip marking file. A folder/multi-cog zip with at least one marked member
gets a top-level
CLASSIFICATION.txtlisting the highest label in the archive and the per-member labels. Zips with no marked members are byte-identical to before. - Filename marking (opt-in). The platform setting
labels.mark_download_filenames(default off) prefixes the saved filename of an export-controlled file with[CUI],[EAR]or[ITAR]. - Propagation. Run outputs inherit the highest input label (as above); the inherited label then rides the output's own downloads, zips and share links — so the marking follows the data end-to-end.
MOD supports an operator's classification marking on egress; it does not make
a customer compliant with any framework. Manual steps:
CORE/API/tests/MANUAL_TEST_GSEC_FIXES.md (GY.V2 R-133 section).