diff --git a/code_samples/authorization/get_decision.mdx b/code_samples/authorization/get_decision.mdx
index 04276737..0475f6b3 100644
--- a/code_samples/authorization/get_decision.mdx
+++ b/code_samples/authorization/get_decision.mdx
@@ -34,19 +34,16 @@ func main() {
// Get Decision using v2 API
// Convenience constructors live in the authorization/v2 package:
- // ForClientID, ForEmail, ForUserName, ForToken, WithRequestToken
+ // Entity: ForClientID, ForEmail, ForUserName, ForToken, WithRequestToken
+ // Resource: ForAttributeValues, ForRegisteredResourceValueFqn
decisionReq := &authorization.GetDecisionRequest{
EntityIdentifier: authorization.ForClientID("opentdf"),
Action: &policy.Action{
Name: "decrypt",
},
- Resource: &authorization.Resource{
- Resource: &authorization.Resource_AttributeValues_{
- AttributeValues: &authorization.Resource_AttributeValues{
- Fqns: []string{"https://opentdf.io/attr/role/value/developer"},
- },
- },
- },
+ Resource: authorization.ForAttributeValues(
+ "https://opentdf.io/attr/role/value/developer",
+ ),
}
decision, err := client.AuthorizationV2.GetDecision(context.Background(), decisionReq)
@@ -141,7 +138,6 @@ import io.opentdf.platform.sdk.*;
import java.util.concurrent.ExecutionException;
import io.opentdf.platform.authorization.*;
-import io.opentdf.platform.entity.*;
import io.opentdf.platform.policy.*;
public class GetDecision {
@@ -158,28 +154,13 @@ public class GetDecision {
// Get Decision using v2 API
GetDecisionRequest request = GetDecisionRequest.newBuilder()
- .setEntityIdentifier(
- EntityIdentifier.newBuilder()
- .setEntityChain(
- EntityChain.newBuilder()
- .addEntities(
- Entity.newBuilder()
- .setId("entity-1")
- .setClientId("opentdf")
- )
- )
- )
+ .setEntityIdentifier(EntityIdentifiers.forClientId("opentdf"))
.setAction(
Action.newBuilder()
.setName("decrypt")
)
- .setResource(
- Resource.newBuilder()
- .setAttributeValues(
- Resource.AttributeValues.newBuilder()
- .addFqns("https://opentdf.io/attr/role/value/developer")
- )
- )
+ .setResource(Resources.forAttributeValues(
+ "https://opentdf.io/attr/role/value/developer"))
.build();
GetDecisionResponse resp = sdk.getServices().authorization().getDecision(request).get();
@@ -202,6 +183,7 @@ public class GetDecision {
import {
Decision,
} from "@opentdf/sdk/platform/authorization/v2/authorization_pb.js";
+import { EntityIdentifiers, Resources } from "@opentdf/sdk";
import { platformConnect, PlatformClient } from "@opentdf/sdk/platform";
async function main() {
@@ -223,33 +205,11 @@ async function main() {
// Get Decision using v2 API
try {
const response = await platformClient.v2.authorization.getDecision({
- entityIdentifier: {
- identifier: {
- case: "entityChain",
- value: {
- entities: [
- {
- ephemeralId: "entity-1",
- entityType: {
- case: "clientId",
- value: "opentdf",
- },
- },
- ],
- },
- },
- },
- action: {
- name: "decrypt",
- },
- resource: {
- resource: {
- case: "attributeValues",
- value: {
- fqns: ["https://opentdf.io/attr/role/value/developer"],
- },
- },
- },
+ entityIdentifier: EntityIdentifiers.forClientId("opentdf"),
+ action: { name: "decrypt" },
+ resource: Resources.forAttributeValues(
+ "https://opentdf.io/attr/role/value/developer",
+ ),
});
const decision = response.decision;
diff --git a/docs/sdks/authorization.mdx b/docs/sdks/authorization.mdx
index 72640fb5..0b600d36 100644
--- a/docs/sdks/authorization.mdx
+++ b/docs/sdks/authorization.mdx
@@ -37,8 +37,8 @@ func main() {
log.Fatal(err)
}
- // All Go snippets below use `client` and `context.Background()`.
- _, _ = client, context.Background()
+ // All Go snippets below use `client` and `ctx`.
+ ctx := context.Background()
}
```
@@ -240,6 +240,140 @@ const response = await platform.v2.authorization.getDecision({
- **Claims** are used by the Entity Resolution Service (ERS) for custom claim-based entity resolution.
- **Registered Resource** identifies an entity by a [registered resource](/components/policy/registered_resources) value FQN stored in platform policy, where the resource acts as a single entity for authorization decisions.
+### Resource
+
+A `Resource` identifies the data being accessed in [GetDecision](#getdecision) and [GetDecisionBulk](#getdecisionbulk) calls. It can be specified as a set of attribute value FQNs (most common — e.g. the attributes on a TDF) or as a [registered resource](/components/policy/registered_resources) value FQN stored in platform policy.
+
+
+
+
+
+
+| Helper | Description |
+|--------|-------------|
+| `authorizationv2.ForAttributeValues(fqns...)` | Resource from attribute value FQNs (e.g. those on a TDF) |
+| `authorizationv2.ForRegisteredResourceValueFqn(fqn)` | Resource from a registered resource value FQN in policy |
+
+```go
+import authorizationv2 "github.com/opentdf/platform/protocol/go/authorization/v2"
+
+req := &authorizationv2.GetDecisionRequest{
+ Resource: authorizationv2.ForAttributeValues(
+ "https://example.com/attr/classification/value/confidential",
+ "https://example.com/attr/department/value/finance",
+ ),
+ // ...
+}
+```
+
+
+Without helpers (manual proto construction)
+
+```go
+&authorizationv2.Resource{
+ Resource: &authorizationv2.Resource_AttributeValues_{
+ AttributeValues: &authorizationv2.Resource_AttributeValues{
+ Fqns: []string{
+ "https://example.com/attr/classification/value/confidential",
+ "https://example.com/attr/department/value/finance",
+ },
+ },
+ },
+}
+```
+
+
+
+
+
+
+
+
+| Helper | Description |
+|--------|-------------|
+| `Resources.forAttributeValues(String... fqns)` | Resource from attribute value FQNs (e.g. those on a TDF) |
+| `Resources.forRegisteredResourceValueFqn(String fqn)` | Resource from a registered resource value FQN in policy |
+
+```java
+import io.opentdf.platform.sdk.Resources;
+
+GetDecisionRequest request = GetDecisionRequest.newBuilder()
+ .setResource(Resources.forAttributeValues(
+ "https://example.com/attr/classification/value/confidential",
+ "https://example.com/attr/department/value/finance"))
+ // ...
+ .build();
+```
+
+
+Without helpers (manual proto construction)
+
+```java
+Resource.newBuilder()
+ .setAttributeValues(
+ Resource.AttributeValues.newBuilder()
+ .addFqns("https://example.com/attr/classification/value/confidential")
+ .addFqns("https://example.com/attr/department/value/finance"))
+ .build()
+```
+
+
+
+
+
+
+
+
+| Helper | Description |
+|--------|-------------|
+| `Resources.forAttributeValues(...fqns)` | Resource from attribute value FQNs (e.g. those on a TDF) |
+| `Resources.forRegisteredResourceValueFqn(fqn)` | Resource from a registered resource value FQN in policy |
+
+```typescript
+import { Resources } from '@opentdf/sdk';
+
+const response = await platform.v2.authorization.getDecision({
+ resource: Resources.forAttributeValues(
+ 'https://example.com/attr/classification/value/confidential',
+ 'https://example.com/attr/department/value/finance',
+ ),
+ // ...
+});
+```
+
+
+Without helpers (manual object construction)
+
+```typescript
+{
+ resource: {
+ case: 'attributeValues',
+ value: {
+ fqns: [
+ 'https://example.com/attr/classification/value/confidential',
+ 'https://example.com/attr/department/value/finance',
+ ],
+ },
+ },
+}
+```
+
+
+
+
+
+
+**Resource variants:**
+
+| Variant | Go | Java | JavaScript |
+|---------|-----|------|------------|
+| Attribute values | `authorizationv2.ForAttributeValues(fqns...)` | `Resources.forAttributeValues(String... fqns)` | `Resources.forAttributeValues(...fqns)` |
+| Registered resource | `authorizationv2.ForRegisteredResourceValueFqn(fqn)` | `Resources.forRegisteredResourceValueFqn(fqn)` | `Resources.forRegisteredResourceValueFqn(fqn)` |
+
+:::note
+The helpers do not set `ephemeralId`. For [GetDecisionBulk](#getdecisionbulk) where you need to correlate requests with responses, set `ephemeralId` separately after construction (in Go, assign the field directly; in Java, use `.toBuilder().setEphemeralId(...).build()`) or use manual construction.
+:::
+
---
## GetEntitlements
@@ -276,7 +410,7 @@ await platform.v2.authorization.getEntitlements({ ... })
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
-| `entityIdentifier` | `EntityIdentifier` | Yes | The entity to query. Use [helpers](#entityidentifier) like `ForEmail(...)` (Go) or `EntityIdentifiers.forEmail(...)` (Java/JS). |
+| `entityIdentifier` | [`EntityIdentifier`](#entityidentifier) | Yes | The entity to query. Use [helpers](#entityidentifier) like `ForEmail(...)` (Go) or `EntityIdentifiers.forEmail(...)` (Java/JS). |
| `withComprehensiveHierarchy` | `bool` | No | When true, returns all entitled values for attributes with hierarchy rules, propagating down from the entitled value. |
**Example**
@@ -467,9 +601,9 @@ await platform.v2.authorization.getDecision({ ... })
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
-| `entityIdentifier` | `EntityIdentifier` | Yes | The entity requesting access. Use [helpers](#entityidentifier) like `ForEmail(...)` (Go) or `EntityIdentifiers.forEmail(...)` (Java/JS). |
+| `entityIdentifier` | [`EntityIdentifier`](#entityidentifier) | Yes | The entity requesting access. Use [helpers](#entityidentifier) like `ForEmail(...)` (Go) or `EntityIdentifiers.forEmail(...)` (Java/JS). |
| `action` | `Action` | Yes | The action being performed (e.g., `decrypt`, `read`). |
-| `resource` | `Resource` | Yes | The resource being accessed, identified by attribute value FQNs. |
+| `resource` | [`Resource`](#resource) | Yes | The resource being accessed. Use [helpers](#resource) like `ForAttributeValues(...)` (Go) or `Resources.forAttributeValues(...)` (Java/JS). |
**Example**
@@ -487,16 +621,10 @@ decisionReq := &authorizationv2.GetDecisionRequest{
Action: &policy.Action{
Name: "decrypt",
},
- Resource: &authorizationv2.Resource{
- Resource: &authorizationv2.Resource_AttributeValues_{
- AttributeValues: &authorizationv2.Resource_AttributeValues{
- Fqns: []string{
- "https://company.com/attr/clearance/value/confidential",
- "https://company.com/attr/department/value/finance",
- },
- },
- },
- },
+ Resource: authorizationv2.ForAttributeValues(
+ "https://company.com/attr/clearance/value/confidential",
+ "https://company.com/attr/department/value/finance",
+ ),
}
decision, err := client.AuthorizationV2.GetDecision(
@@ -529,13 +657,9 @@ import (
decisionReq := &authorizationv2.GetDecisionRequest{
EntityIdentifier: authorizationv2.ForToken(jwtToken),
Action: &policy.Action{Name: "decrypt"},
- Resource: &authorizationv2.Resource{
- Resource: &authorizationv2.Resource_AttributeValues_{
- AttributeValues: &authorizationv2.Resource_AttributeValues{
- Fqns: []string{"https://company.com/attr/clearance/value/public"},
- },
- },
- },
+ Resource: authorizationv2.ForAttributeValues(
+ "https://company.com/attr/clearance/value/public",
+ ),
}
decision, err := client.AuthorizationV2.GetDecision(
@@ -604,6 +728,7 @@ for _, dr := range decisionResponse.GetDecisionResponses() {
```java
import io.opentdf.platform.sdk.EntityIdentifiers;
+import io.opentdf.platform.sdk.Resources;
GetDecisionRequest request = GetDecisionRequest.newBuilder()
.setEntityIdentifier(EntityIdentifiers.forEmail("user@company.com"))
@@ -611,14 +736,9 @@ GetDecisionRequest request = GetDecisionRequest.newBuilder()
Action.newBuilder()
.setName("decrypt")
)
- .setResource(
- Resource.newBuilder()
- .setAttributeValues(
- Resource.AttributeValues.newBuilder()
- .addFqns("https://company.com/attr/clearance/value/confidential")
- .addFqns("https://company.com/attr/department/value/finance")
- )
- )
+ .setResource(Resources.forAttributeValues(
+ "https://company.com/attr/clearance/value/confidential",
+ "https://company.com/attr/department/value/finance"))
.build();
GetDecisionResponse resp = sdk.getServices()
@@ -641,23 +761,16 @@ if (decision.getDecision() == Decision.DECISION_PERMIT) {
```typescript
-import { EntityIdentifiers } from '@opentdf/sdk';
+import { EntityIdentifiers, Resources } from '@opentdf/sdk';
import { Decision } from '@opentdf/sdk/platform/authorization/v2/authorization_pb.js';
const response = await platform.v2.authorization.getDecision({
entityIdentifier: EntityIdentifiers.forEmail('user@company.com'),
action: { name: 'decrypt' },
- resource: {
- resource: {
- case: 'attributeValues',
- value: {
- fqns: [
- 'https://company.com/attr/clearance/value/confidential',
- 'https://company.com/attr/department/value/finance',
- ],
- },
- },
- },
+ resource: Resources.forAttributeValues(
+ 'https://company.com/attr/clearance/value/confidential',
+ 'https://company.com/attr/department/value/finance',
+ ),
});
const decision = response.decision;
@@ -720,9 +833,9 @@ Each `GetDecisionMultiResourceRequest` contains:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
-| `entityIdentifier` | `EntityIdentifier` | Yes | The entity requesting access. |
+| `entityIdentifier` | [`EntityIdentifier`](#entityidentifier) | Yes | The entity requesting access. |
| `action` | `Action` | Yes | The action being performed. |
-| `resources` | `[]Resource` | Yes | Resources to evaluate, each with an `ephemeralId` for correlation. |
+| `resources` | [`[]Resource`](#resource) | Yes | Resources to evaluate, each with an `ephemeralId` for correlation. |
**Example**
@@ -962,29 +1075,38 @@ Identifies the data being accessed. A resource can be specified in two ways:
| `attributeValues.fqns` | `[]string` | Attribute value FQNs on the resource (1–20). Use this for TDF payloads or any resource identified by attribute values. |
| `registeredResourceValueFqn` | `string` (URI) | A [registered resource](/components/policy/registered_resources) value FQN stored in platform policy. Alternative to `attributeValues`. |
+Use the [Resource helpers](#resource) for concise construction:
+
+
+
+
```go
-// Go
-&authorizationv2.Resource{
- EphemeralId: "resource-1",
- Resource: &authorizationv2.Resource_AttributeValues_{
- AttributeValues: &authorizationv2.Resource_AttributeValues{
- Fqns: []string{"https://example.com/attr/classification/value/secret"},
- },
- },
-}
+// With helpers
+authorizationv2.ForAttributeValues("https://example.com/attr/classification/value/secret")
+authorizationv2.ForRegisteredResourceValueFqn("https://example.com/registered/value/my-resource")
```
+
+
+
+```java
+// With helpers
+Resources.forAttributeValues("https://example.com/attr/classification/value/secret")
+Resources.forRegisteredResourceValueFqn("https://example.com/registered/value/my-resource")
+```
+
+
+
+
```typescript
-// JavaScript
-{
- ephemeralId: 'resource-1',
- resource: {
- case: 'attributeValues',
- value: { fqns: ['https://example.com/attr/classification/value/secret'] },
- },
-}
+// With helpers
+Resources.forAttributeValues('https://example.com/attr/classification/value/secret')
+Resources.forRegisteredResourceValueFqn('https://example.com/registered/value/my-resource')
```
+
+
+
### EntityEntitlements
Returned by [GetEntitlements](#getentitlements). One per entity, mapping attribute value FQNs to the actions that entity can perform.
diff --git a/docs/sdks/discovery.mdx b/docs/sdks/discovery.mdx
index f47ed8bd..faeb532e 100644
--- a/docs/sdks/discovery.mdx
+++ b/docs/sdks/discovery.mdx
@@ -39,8 +39,8 @@ func main() {
log.Fatal(err)
}
- // All Go snippets below use `client` and `context.Background()`.
- _, _ = client, context.Background()
+ // All Go snippets below use `client` and `ctx`.
+ ctx := context.Background()
}
```
diff --git a/docs/sdks/tdf.mdx b/docs/sdks/tdf.mdx
index 0364aa94..592be43e 100644
--- a/docs/sdks/tdf.mdx
+++ b/docs/sdks/tdf.mdx
@@ -25,7 +25,7 @@ This page covers the core TDF operations:
- **[Decrypt Options](#decrypt-options)** — full option reference for `LoadTDF`
- **[Assertions](#assertions)** — signed metadata: types, scopes, signing, and verification
- **[Session Encryption](#session-encryption)** — provide your own RSA key for KAS response encryption
-- **[Type Reference](#type-reference)** — `KASInfo`, `PolicyObject`, `Manifest`, `AssertionConfig`
+- **[Type Reference](#type-reference)** — `TDFObject`, `KASInfo`, `PolicyObject`, `Manifest`, `AssertionConfig`
- **[Experimental: Streaming Writer](#experimental-streaming-writer)** — segment-based API for large files and out-of-order assembly
---
@@ -280,7 +280,7 @@ See [Encrypt Options](#encrypt-options) for the full list of configuration optio
-`(*TDFObject, error)` — On success, a `TDFObject` with a `.Manifest()` method returning the [Manifest](#manifest-object) and a `.Size()` method returning the encrypted byte count. Returns a non-nil `error` on failure.
+[`(*TDFObject, error)`](#tdfobject) — On success, a `TDFObject` with a `.Manifest()` method returning the [Manifest](#manifest-object) and a `.Size()` method returning the encrypted byte count. Returns a non-nil `error` on failure.
@@ -1269,6 +1269,23 @@ See the [Encrypt Options](#encrypt-options) and [Decrypt Options](#decrypt-optio
The following types are returned by or passed to the methods above.
+### TDFObject
+
+**Go only.** Returned by [`CreateTDF`](#createtdf). Contains the manifest and size of the encrypted TDF.
+
+**Methods**
+
+| Method | Return type | Description |
+|--------|-------------|-------------|
+| `Manifest()` | [`Manifest`](#manifest-object) | The TDF manifest, including encryption info, key access objects, and assertions. |
+| `Size()` | `int64` | Total byte count of the encrypted TDF written to the output. |
+
+:::note
+Java's `CreateTDF` returns a [`Manifest`](#manifest-object) directly. JavaScript's returns a `DecoratedStream`.
+:::
+
+---
+
### KASInfo
`KASInfo` is the input type passed to `WithKasInformation` (Go) or used to build a `Config.KASInfo` (Java). It identifies a KAS endpoint and the key configuration to use when wrapping the data encryption key.