# Marking grammar

Source: https://www.testifysec.com/docs/badger/reference/marking-grammar/

The classification markings Badger connectors accept, the order their parts must appear in, and how two markings compare.

Status: available on `main`, in `testifysec/connectors/internal/marking/`.

 

A connector's `--classification` value is parsed by this grammar. A marking that does not parse is an error; the parser never guesses.

 

## Vocabulary

 

The tokens the parser knows live in one data file, `testifysec/connectors/internal/marking/tokens.json`, each with the regulation or manual it comes from. Adding a token means adding it there with its source. This page describes the structure; the file is the list.

 

## Characters

 

The input is upper-cased and must match `^[A-Z0-9 ,/-]{1,512}$`: letters, digits, space, comma, slash and hyphen, at most 512 characters. A newline, `<`, `.` or anything else is refused.

 

## Structure

 

A marking is groups separated by `//`. The first group is the level; the rest follow in a fixed order, and a group may appear once.

 

| Order | Group | Example values | Allowed with |
| --- | --- | --- | --- |
| 0 | Level | `UNCLASSIFIED`, `CONFIDENTIAL`, `SECRET`, `TOP SECRET`, and a controlled unclassified level | always first |
| 1 | Compartments (SCI) | a control system, optionally with `-SUFFIX` sub-compartments | classified levels |
| 2 | Special access programs | `SAR-` followed by an identifier | classified levels |
| 3 | Atomic energy markings | restricted data and its variants | any |
| 4 | Foreign government information | `FGI`, optionally followed by country codes | any |
| 5 | Controlled unclassified categories | the categories for the controlled unclassified level | that level only |
| 6 | Dissemination controls | originator and imagery controls, foreign-release limits, proprietary | see below |
| 7 | Non-intelligence controls | limited, exclusive and no distribution, and agency-specific labels | any |

 

`REL TO` and `DISPLAY ONLY` lists sit in the dissemination group. Inside any other group, values are separated by `/` and may come in any order; the parser prints them in a canonical order.

 

Below `CONFIDENTIAL` only the limited-dissemination controls defined for the controlled unclassified level are allowed; a classified-only control on an unclassified marking is refused.

 

### Release lists

 

`REL TO` lists start with `USA`, then ISO 3166-1 alpha-3 country codes in alphabetical order, then coalition codes (`ACGU`, `FVEY`, `NATO`), which expand to their members when markings are compared. A list may appear once. A code that exists only in another standard is refused. A marking cannot carry both a release list and the control that forbids foreign release.

 

### Banner form only

 

`--classification` takes the banner form only, such as `SECRET//REL TO USA, FVEY`. Portion marks such as `(S//REL TO USA, FVEY)`, abbreviated control names and retired legacy markings are refused.

 

## Examples

 

| Input | Result |
| --- | --- |
| `SECRET` | parses |
| `SECRET//REL TO USA, FVEY` | parses |
| `secret//rel to usa, fvey` | parses; upper-cased |
| `CONFIDENTIAL//REL TO USA, CAN, GBR` | parses |
| `CONFIDENTIAL//REL TO USA, GBR, CAN` | refused: countries after `USA` must be in alphabetical order |
| `SECRET/REL TO USA, FVEY` | refused: a single `/` does not separate groups |
| `SECRET//REL TO FVEY, USA` | refused: `USA` must come first |
| `(S//REL TO USA, FVEY)` | refused: portion marks are not accepted |
| `SECRET//REL TO USA, XYZ` | refused: unknown country code |

 

These examples were run against the parser; `SECRET` dominates `SECRET//REL TO USA, FVEY` and not the reverse.

 

## Comparing markings

 

The rules for **dominance** (may data with marking B flow to a place accredited for A?) and **join** (the high-water mark of two markings) are in [classification markings](https://www.testifysec.com/docs/badger/concepts/classification#how-markings-compare). In code they are `Dominates` and `Join` in `dominance.go`; the Lean model in [PR #182](https://github.com/testifysec/badger/pull/182) checks both against 441 pairs each.

Reference generated from the product documentation. Match commands and support details to your installed release.
