Skip to content

Commit 2cc862d

Browse files
marythoughtclaude
andcommitted
chore(docs): DSPX-2959 use shorthand enum names in subject mapping docs
Replace verbose proto enum names and numeric codes with readable shorthand aliases (IN, NOT_IN, IN_CONTAINS, AND, OR) throughout subject mapping documentation. The platform now accepts these via HTTP middleware (opentdf/platform#3401). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a82f860 commit 2cc862d

3 files changed

Lines changed: 65 additions & 55 deletions

File tree

docs/components/policy/subject_mappings.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ Subject Condition Sets can also optionally be associated with a namespace. See [
5757

5858
### Operators
5959

60+
:::tip Shorthand enum names
61+
The API accepts readable shorthand names (e.g., `IN`, `AND`) in addition to full canonical proto names (e.g., `SUBJECT_MAPPING_OPERATOR_ENUM_IN`, `CONDITION_BOOLEAN_TYPE_ENUM_AND`). The examples below use shorthand names.
62+
:::
63+
6064
#### Condition Operators
6165

6266
Each Condition uses an operator to compare the entity's claim (extracted by the selector) against the list of expected values.

docs/guides/subject-mapping-guide.md

Lines changed: 50 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -157,18 +157,22 @@ The selector syntax depends on whether the token claim is a **string** or an **a
157157
158158
### Operators Explained
159159
160-
| Operator | Value | Behavior | Example |
161-
|----------|-------|----------|---------|
162-
| **IN** | `1` | Exact match: value is IN list | `.role` IN `["admin", "editor"]` |
163-
| **NOT_IN** | `2` | Exclusion: value is NOT IN list | `.department` NOT_IN `["sales"]` |
164-
| **IN_CONTAINS** | `3` | Substring match | `.email` IN_CONTAINS `["@example.com"]` |
160+
| Operator | Behavior | Example |
161+
|----------|----------|---------|
162+
| **`IN`** | Exact match: value is IN list | `.role` IN `["admin", "editor"]` |
163+
| **`NOT_IN`** | Exclusion: value is NOT IN list | `.department` NOT_IN `["sales"]` |
164+
| **`IN_CONTAINS`** | Substring match | `.email` IN_CONTAINS `["@example.com"]` |
165165
166166
### Boolean Operators
167167
168-
| Operator | Value | Behavior |
169-
|----------|-------|----------|
170-
| **AND** | `1` | All conditions must be TRUE |
171-
| **OR** | `2` | At least one condition must be TRUE |
168+
| Operator | Behavior |
169+
|----------|----------|
170+
| **`AND`** | All conditions must be TRUE |
171+
| **`OR`** | At least one condition must be TRUE |
172+
173+
:::tip Shorthand enum names
174+
The API accepts readable shorthand names (`IN`, `NOT_IN`, `IN_CONTAINS`, `AND`, `OR`) as well as the full canonical proto names (e.g., `SUBJECT_MAPPING_OPERATOR_ENUM_IN`, `CONDITION_BOOLEAN_TYPE_ENUM_AND`). Numeric values (`1`, `2`, `3`) also work. The examples in this guide use shorthand names for readability.
175+
:::
172176
173177
### Example 1: Multiple Roles (OR)
174178
@@ -178,16 +182,16 @@ The selector syntax depends on whether the token claim is a **string** or an **a
178182
{
179183
"subject_sets": [{
180184
"condition_groups": [{
181-
"boolean_operator": 2,
185+
"boolean_operator": "OR",
182186
"conditions": [
183187
{
184188
"subject_external_selector_value": ".role",
185-
"operator": 1,
189+
"operator": "IN",
186190
"subject_external_values": ["admin"]
187191
},
188192
{
189193
"subject_external_selector_value": ".role",
190-
"operator": 1,
194+
"operator": "IN",
191195
"subject_external_values": ["editor"]
192196
}
193197
]
@@ -201,10 +205,10 @@ The selector syntax depends on whether the token claim is a **string** or an **a
201205
{
202206
"subject_sets": [{
203207
"condition_groups": [{
204-
"boolean_operator": 1,
208+
"boolean_operator": "AND",
205209
"conditions": [{
206210
"subject_external_selector_value": ".role",
207-
"operator": 1,
211+
"operator": "IN",
208212
"subject_external_values": ["admin", "editor"]
209213
}]
210214
}]
@@ -220,16 +224,16 @@ The selector syntax depends on whether the token claim is a **string** or an **a
220224
{
221225
"subject_sets": [{
222226
"condition_groups": [{
223-
"boolean_operator": 1,
227+
"boolean_operator": "AND",
224228
"conditions": [
225229
{
226230
"subject_external_selector_value": ".level",
227-
"operator": 1,
231+
"operator": "IN",
228232
"subject_external_values": ["senior", "staff", "principal"]
229233
},
230234
{
231235
"subject_external_selector_value": ".department",
232-
"operator": 1,
236+
"operator": "IN",
233237
"subject_external_values": ["engineering"]
234238
}
235239
]
@@ -252,10 +256,10 @@ The selector syntax depends on whether the token claim is a **string** or an **a
252256
{
253257
"subject_sets": [{
254258
"condition_groups": [{
255-
"boolean_operator": 1,
259+
"boolean_operator": "AND",
256260
"conditions": [{
257261
"subject_external_selector_value": ".email",
258-
"operator": 3,
262+
"operator": "IN_CONTAINS",
259263
"subject_external_values": ["@example.com"]
260264
}]
261265
}]
@@ -279,26 +283,26 @@ The selector syntax depends on whether the token claim is a **string** or an **a
279283
"subject_sets": [
280284
{
281285
"condition_groups": [{
282-
"boolean_operator": 1,
286+
"boolean_operator": "AND",
283287
"conditions": [{
284288
"subject_external_selector_value": ".role",
285-
"operator": 1,
289+
"operator": "IN",
286290
"subject_external_values": ["ceo", "cfo", "cto", "vp"]
287291
}]
288292
}]
289293
},
290294
{
291295
"condition_groups": [{
292-
"boolean_operator": 1,
296+
"boolean_operator": "AND",
293297
"conditions": [
294298
{
295299
"subject_external_selector_value": ".level",
296-
"operator": 1,
300+
"operator": "IN",
297301
"subject_external_values": ["senior", "staff"]
298302
},
299303
{
300304
"subject_external_selector_value": ".department",
301-
"operator": 1,
305+
"operator": "IN",
302306
"subject_external_values": ["finance"]
303307
}
304308
]
@@ -341,7 +345,7 @@ Subject Mapping 1 (linked to `department/value/finance`):
341345
```json
342346
{
343347
"subject_external_selector_value": ".attributes.department[]",
344-
"operator": 1,
348+
"operator": "IN",
345349
"subject_external_values": ["Finance"]
346350
}
347351
```
@@ -350,7 +354,7 @@ Subject Mapping 2 (linked to `country/value/us`):
350354
```json
351355
{
352356
"subject_external_selector_value": ".attributes.country[]",
353-
"operator": 1,
357+
"operator": "IN",
354358
"subject_external_values": ["US"]
355359
}
356360
```
@@ -380,10 +384,10 @@ All attribute values in OpenTDF must be explicitly created before they can be us
380384
"subject_condition_set": {
381385
"subject_sets": [{
382386
"condition_groups": [{
383-
"boolean_operator": 1,
387+
"boolean_operator": "AND",
384388
"conditions": [{
385389
"subject_external_selector_value": ".email",
386-
"operator": 1,
390+
"operator": "IN",
387391
"subject_external_values": ["alice@example.com"]
388392
}]
389393
}]
@@ -396,7 +400,7 @@ All attribute values in OpenTDF must be explicitly created before they can be us
396400

397401
### Recommended: Pattern-Based Access
398402

399-
Use `IN_CONTAINS` (operator `3`) to match token claim substrings, covering many users with one Subject Mapping:
403+
Use `IN_CONTAINS` to match token claim substrings, covering many users with one Subject Mapping:
400404

401405
```json
402406
{
@@ -405,10 +409,10 @@ Use `IN_CONTAINS` (operator `3`) to match token claim substrings, covering many
405409
"subject_condition_set": {
406410
"subject_sets": [{
407411
"condition_groups": [{
408-
"boolean_operator": 1,
412+
"boolean_operator": "AND",
409413
"conditions": [{
410414
"subject_external_selector_value": ".email",
411-
"operator": 3,
415+
"operator": "IN_CONTAINS",
412416
"subject_external_values": ["@example.com"]
413417
}]
414418
}]
@@ -498,10 +502,10 @@ Attribute value FQN: `https://example.com/attr/clearance/value/confidential`
498502
"subject_condition_set": {
499503
"subject_sets": [{
500504
"condition_groups": [{
501-
"boolean_operator": 1,
505+
"boolean_operator": "AND",
502506
"conditions": [{
503507
"subject_external_selector_value": ".realm_access.roles[]",
504-
"operator": 1,
508+
"operator": "IN",
505509
"subject_external_values": ["admin"]
506510
}]
507511
}]
@@ -520,10 +524,10 @@ Attribute value FQN: `https://example.com/attr/clearance/value/confidential`
520524
{
521525
"subject_sets": [{
522526
"condition_groups": [{
523-
"boolean_operator": 1,
527+
"boolean_operator": "AND",
524528
"conditions": [{
525529
"subject_external_selector_value": ".groups[]",
526-
"operator": 3,
530+
"operator": "IN_CONTAINS",
527531
"subject_external_values": ["/finance/"]
528532
}]
529533
}]
@@ -548,16 +552,16 @@ The trailing slash in `/finance/` makes the `IN_CONTAINS` match more precise —
548552
{
549553
"subject_sets": [{
550554
"condition_groups": [{
551-
"boolean_operator": 1,
555+
"boolean_operator": "AND",
552556
"conditions": [
553557
{
554558
"subject_external_selector_value": ".groups[]",
555-
"operator": 3,
559+
"operator": "IN_CONTAINS",
556560
"subject_external_values": ["/finance/"]
557561
},
558562
{
559563
"subject_external_selector_value": ".realm_access.roles[]",
560-
"operator": 1,
564+
"operator": "IN",
561565
"subject_external_values": ["admin"]
562566
}
563567
]
@@ -580,7 +584,7 @@ This walkthrough assumes basic familiarity with OpenTDF. If you haven't set up O
580584

581585
### Step 1: Create Subject Condition Set
582586

583-
This example matches any user whose `.email` claim contains `@example.com`. The numeric values are enum codes — `boolean_operator: 1` = AND (all conditions must be true), `operator: 3` = IN_CONTAINS (substring match). See [Operators Explained](#operators-explained) for the full list.
587+
This example matches any user whose `.email` claim contains `@example.com`. `boolean_operator: "AND"` means all conditions must be true, and `operator: "IN_CONTAINS"` performs a substring match. See [Operators Explained](#operators-explained) for the full list.
584588

585589
`subject_external_selector_value` is a path into the JWT your IdP issues — `.email` selects the top-level `email` claim. If your claim is named differently, use `otdfctl dev selectors generate --subject "<your-jwt>"` to see all available selectors. See [Selectors: String vs. Array Claims](#selectors-string-vs-array-claims) for the full syntax.
586590

@@ -591,10 +595,10 @@ otdfctl policy subject-condition-sets create \
591595
--subject-sets '[
592596
{
593597
"condition_groups": [{
594-
"boolean_operator": 1,
598+
"boolean_operator": "AND",
595599
"conditions": [{
596600
"subject_external_selector_value": ".email",
597-
"operator": 3,
601+
"operator": "IN_CONTAINS",
598602
"subject_external_values": ["@example.com"]
599603
}]
600604
}]
@@ -762,7 +766,7 @@ Use `.groups[]` (not `.groups`) to match each element:
762766
```json
763767
{
764768
"subject_external_selector_value": ".groups[]",
765-
"operator": 1,
769+
"operator": "IN",
766770
"subject_external_values": ["admin"]
767771
}
768772
```
@@ -799,10 +803,10 @@ otdfctl policy subject-condition-sets create \
799803
--subject-sets '[
800804
{
801805
"condition_groups": [{
802-
"boolean_operator": 1,
806+
"boolean_operator": "AND",
803807
"conditions": [{
804808
"subject_external_selector_value": ".clientId",
805-
"operator": 1,
809+
"operator": "IN",
806810
"subject_external_values": ["my-service-account-client-id"]
807811
}]
808812
}]
@@ -874,10 +878,10 @@ otdfctl policy subject-condition-sets create \
874878
--subject-sets '[
875879
{
876880
"condition_groups": [{
877-
"boolean_operator": 1,
881+
"boolean_operator": "AND",
878882
"conditions": [{
879883
"subject_external_selector_value": ".department",
880-
"operator": 1,
884+
"operator": "IN",
881885
"subject_external_values": ["engineering"]
882886
}]
883887
}]

docs/sdks/policy.mdx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,7 @@ await platform.v1.attributes.listAttributeValues({ ... })
903903
| Parameter | Type | Required | Description |
904904
|-----------|------|----------|-------------|
905905
| `attributeId` | `string` (UUID) | Yes | The parent attribute ID. |
906-
| `state` | `string` | No | Filter by state: `ACTIVE_STATE_ENUM_ACTIVE` (default), `ACTIVE_STATE_ENUM_INACTIVE`, or `ACTIVE_STATE_ENUM_ANY`. |
906+
| `state` | `string` | No | Filter by state: `ACTIVE` (default), `INACTIVE`, or `ANY`. Full canonical names (e.g., `ACTIVE_STATE_ENUM_ACTIVE`) are also accepted. |
907907

908908
**Example**
909909

@@ -1365,7 +1365,7 @@ Empty response. The value is soft-deleted and will no longer appear in listings
13651365
| `id` | `string` (UUID) | Unique identifier, generated by the platform. |
13661366
| `name` | `string` | The attribute name (e.g., `department`, `clearance`). |
13671367
| `fqn` | `string` | Fully qualified name, e.g., `https://opentdf.io/attr/department`. |
1368-
| `rule` | `string` | Access rule: `ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF`, `ATTRIBUTE_RULE_TYPE_ENUM_ANY_OF`, or `ATTRIBUTE_RULE_TYPE_ENUM_HIERARCHY`. |
1368+
| `rule` | `string` | Access rule: `ALL_OF`, `ANY_OF`, or `HIERARCHY`. Full canonical names (e.g., `ATTRIBUTE_RULE_TYPE_ENUM_ALL_OF`) are also accepted. |
13691369
| `values` | `[]Value` | The [attribute values](#attribute-value-object) defined under this attribute. |
13701370
| `namespace` | `Namespace` | The parent [Namespace](#namespace-object). |
13711371
| `active` | `bool` | `true` until explicitly deactivated. |
@@ -1947,7 +1947,7 @@ SubjectConditionSet
19471947

19481948
| Field | Type | Description |
19491949
|-------|------|-------------|
1950-
| `booleanOperator` | `string` | How to combine conditions: `CONDITION_BOOLEAN_TYPE_ENUM_AND` or `CONDITION_BOOLEAN_TYPE_ENUM_OR`. |
1950+
| `booleanOperator` | `string` | How to combine conditions: `AND` or `OR`. Full canonical names (e.g., `CONDITION_BOOLEAN_TYPE_ENUM_AND`) are also accepted. |
19511951
| `conditions` | `[]Condition` | One or more [conditions](#condition) to evaluate. |
19521952

19531953
### Condition
@@ -1964,9 +1964,11 @@ A single claim match against an entity's token.
19641964

19651965
| Operator | Description |
19661966
|----------|-------------|
1967-
| `SUBJECT_MAPPING_OPERATOR_ENUM_IN` | The claim value must exactly match one of the `subjectExternalValues`. |
1968-
| `SUBJECT_MAPPING_OPERATOR_ENUM_NOT_IN` | The claim value must not match any of the `subjectExternalValues`. |
1969-
| `SUBJECT_MAPPING_OPERATOR_ENUM_IN_CONTAINS` | The claim value must contain (substring match) one of the `subjectExternalValues`. |
1967+
| `IN` | The claim value must exactly match one of the `subjectExternalValues`. |
1968+
| `NOT_IN` | The claim value must not match any of the `subjectExternalValues`. |
1969+
| `IN_CONTAINS` | The claim value must contain (substring match) one of the `subjectExternalValues`. |
1970+
1971+
Full canonical names (e.g., `SUBJECT_MAPPING_OPERATOR_ENUM_IN`) are also accepted.
19701972

19711973
**Example:** "Match entities whose `.clientId` is `my-service` AND whose `.realm_access.roles` contains `developer`":
19721974

@@ -1976,16 +1978,16 @@ A single claim match against an entity's token.
19761978
{
19771979
"conditionGroups": [
19781980
{
1979-
"booleanOperator": "CONDITION_BOOLEAN_TYPE_ENUM_AND",
1981+
"booleanOperator": "AND",
19801982
"conditions": [
19811983
{
19821984
"subjectExternalSelectorValue": ".clientId",
1983-
"operator": "SUBJECT_MAPPING_OPERATOR_ENUM_IN",
1985+
"operator": "IN",
19841986
"subjectExternalValues": ["my-service"]
19851987
},
19861988
{
19871989
"subjectExternalSelectorValue": ".realm_access.roles",
1988-
"operator": "SUBJECT_MAPPING_OPERATOR_ENUM_IN_CONTAINS",
1990+
"operator": "IN_CONTAINS",
19891991
"subjectExternalValues": ["developer"]
19901992
}
19911993
]

0 commit comments

Comments
 (0)