Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions docs/sdks/obligations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,57 @@ The created [Obligation Trigger object](#obligation-trigger-object).

</details>

<details id="get-obligation-trigger">
Comment thread
marythought marked this conversation as resolved.
<summary>Get an Obligation Trigger</summary>

**Signature**

<Tabs>
<TabItem value="go" label="Go">

```go
client.Obligations.GetObligationTrigger(ctx, &obligations.GetObligationTriggerRequest{...})
```

*Available since [SDK v0.16.0](https://github.com/opentdf/platform/releases/tag/sdk/v0.16.0)*

</TabItem>
</Tabs>

**Parameters**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `id` | `string` (UUID) | Yes | The trigger UUID. |

**Example**

<Tabs>
<TabItem value="go" label="Go">

```go
import "github.com/opentdf/platform/protocol/go/policy/obligations"

resp, err := client.Obligations.GetObligationTrigger(context.Background(),
&obligations.GetObligationTriggerRequest{
Id: "7e8f9a0b-...",
},
)
if err != nil {
log.Fatal(err)
}
log.Printf("Trigger ID: %s\n", resp.GetTrigger().GetId())
```

</TabItem>
</Tabs>

**Returns**

A single [Obligation Trigger object](#obligation-trigger-object).

</details>

<details id="list-obligation-triggers">
<summary>List Obligation Triggers</summary>

Expand Down
45 changes: 45 additions & 0 deletions docs/sdks/troubleshooting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ Check that your identity provider is accessible:
curl https://<idp-endpoint>/
```

## OIDC Discovery Fails with Trailing-Slash Issuer

**Error**: `unexpected end of JSON input` during OIDC discovery

**Cause**: Some identity providers (e.g., [Authentik](https://goauthentik.io/)) include a trailing slash in their OIDC issuer URL (e.g., `https://idp.example/app/`). The Go SDK before v0.16.0 concatenated this with `/.well-known/openid-configuration`, producing a double-slash URL that returned a redirect instead of JSON. The JavaScript SDK is unaffected (browser fetch follows redirects automatically).

**Solution**: Upgrade to Go SDK **v0.16.0+**, which normalizes the issuer URL automatically. No code changes required.

## Token Expired

**Error**: `token expired`, `invalid token`, or `jwt expired`
Expand Down Expand Up @@ -245,6 +253,43 @@ otdfctl policy subject-mappings create \
3. **Verify file integrity** — TDFs are tamper-evident; any modification after encryption will cause decryption to fail
4. **Check file transfer** — binary TDF files can be corrupted by text-mode transfers; ensure files are transferred in binary mode

## KAS Error Classification (Go SDK v0.16.0+)

:::caution Breaking Change in v0.16.0
The Go SDK v0.16.0 changed how KAS (Key Access Server) errors are classified. If your code checks `errors.Is(err, sdk.ErrTampered)`, read this section carefully.
:::

**Background**: When decrypting a TDF, the SDK contacts the KAS to unwrap keys. The KAS can return errors for two very different reasons:

1. **Integrity failure (tamper)** — the TDF's policy binding or encrypted key has been modified
2. **Misconfiguration** — the request was malformed, used an unsupported key type, or the client lacks permission

**What changed**: Prior to v0.16.0, *all* KAS 400-level errors were classified as `ErrTampered`. This made `errors.Is(err, sdk.ErrTampered)` unreliable — it returned `true` even for configuration errors. Starting in v0.16.0, the SDK distinguishes between tamper and misconfiguration:

| Error source | SDK sentinel | `errors.Is(err, sdk.ErrTampered)`? |
|---|---|---|
| Policy binding mismatch | `sdk.ErrRewrapBadRequest` | Yes |
| DEK decryption failure | `sdk.ErrRewrapBadRequest` | Yes |
| Corrupted policy body | `sdk.ErrRewrapBadRequest` | Yes |
| Misconfiguration (e.g., wrong key type) | `sdk.ErrKASRequestError` | No |
| Access denied (403) | `sdk.ErrRewrapForbidden` | No |
Comment thread
marythought marked this conversation as resolved.

**Migration**: If your code catches all KAS errors via `ErrTampered`, add a check for `ErrKASRequestError`:

```go
if errors.Is(err, sdk.ErrTampered) {
// Integrity failure — the TDF was modified after encryption
} else if errors.Is(err, sdk.ErrKASRequestError) {
// Client or configuration error (400 or 403 from KAS)
}
```

:::note
`ErrRewrapForbidden` (403) now wraps `ErrKASRequestError`, so `errors.Is(err, sdk.ErrKASRequestError)` matches both misconfiguration 400s and forbidden 403s.
:::

See [opentdf/platform#3166](https://github.com/opentdf/platform/issues/3166) for full details.

## Entity Resolution Failed

**Error**: `entity resolution failed` or `failed to resolve entity`
Expand Down
Loading