From 77b499c7f8f68ee4f2cf1b23e2e6d696ad61f1d5 Mon Sep 17 00:00:00 2001 From: Mary Dickson Date: Wed, 29 Apr 2026 13:02:38 -0700 Subject: [PATCH 1/4] feat(docs): document SDK.IsHealthy reachability probe Add a Health checks section to platform-client.mdx covering the new IsHealthy(ctx) method shipped in opentdf/platform sdk v0.18.0 (opentdf/platform#3412). Documents the (bool, error) contract, SERVING/NOT_SERVING/UNKNOWN behavior, and the IPC mode and transport error sentinels. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/sdks/platform-client.mdx | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/sdks/platform-client.mdx b/docs/sdks/platform-client.mdx index 6995b5cc..d1b7f03d 100644 --- a/docs/sdks/platform-client.mdx +++ b/docs/sdks/platform-client.mdx @@ -6,6 +6,7 @@ title: Overview import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import JsAuthNote from '../../code_samples/js_auth_note.mdx' +import SdkVersion from '@site/src/components/SdkVersion'; # Overview @@ -90,6 +91,36 @@ const platform = new PlatformClient({ ...auth, platformUrl: 'http://localhost:80 +## Health checks + +`IsHealthy` reports whether the platform is reachable and serving requests. Use it in readiness probes, smoke tests, or to gate startup logic on platform availability. + + + +```go +healthy, err := client.IsHealthy(ctx) +if err != nil { + // transport failure or context cancellation + log.Printf("platform unreachable: %v", err) + return +} +if !healthy { + // reachable, but reports NOT_SERVING or UNKNOWN + log.Println("platform is not ready") +} +``` + +The check honors the supplied `context.Context` for deadlines and cancellation, and propagates OTEL tracing when `otelconnect.NewInterceptor` is registered via `WithExtraClientOptions`. + +### Return values + +| Result | Meaning | +|---|---| +| `(true, nil)` | Platform reports `SERVING`. | +| `(false, nil)` | Platform is reachable but reports `NOT_SERVING` or `UNKNOWN`. | +| `(false, err)` | Transport failure or context cancellation. The error wraps `sdk.ErrPlatformUnreachable`. | +| `(false, sdk.ErrHealthCheckUnsupported)` | The SDK is configured in IPC mode, which does not support health checks. | + ## Response Objects All platform API calls return protobuf response objects. The way you access fields differs by language: **Go** uses generated getter methods prefixed with `Get`, **Java** uses standard getters, and **JavaScript** uses direct property access with optional chaining. From b48e3483268829e6ee34fc011b80fdea7a615f75 Mon Sep 17 00:00:00 2001 From: Mary Dickson Date: Wed, 29 Apr 2026 13:20:10 -0700 Subject: [PATCH 2/4] fix(docs): link unresolved type references in SDK reference tables Several PascalCase type cells in SDK reference tables were rendering as plain text instead of links to their definitions, forcing readers to scroll or grep to learn the type's shape. authorization.mdx: - Link Action cells to /sdks/policy#action - Add GetDecisionMultiResourceRequest heading inline so its parameter cell resolves to a real anchor tdf.mdx: - Add RequiredObligations entry to the Type Reference and link the TriggeredObligations cell - Promote Manifest sub-tables (EncryptionInformation, KeyAccess, Payload) to H4 subheadings so they have anchors; disambiguate Payload with {#manifest-payload} since the TDF Reader method already owns #payload - Fully link the Assertion fields table (AssertionType, Scope, AppliesToState, Statement, Binding) and add a Binding type-ref entry - Link AssertionKey in AssertionVerificationKeys.DefaultKey policy.mdx: - Link SubjectSet in UpdateSubjectConditionSet parameters - Link SubjectProperty in MatchSubjectMappings parameters Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/sdks/authorization.mdx | 8 ++++-- docs/sdks/policy.mdx | 4 +-- docs/sdks/tdf.mdx | 55 +++++++++++++++++++++++++++---------- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/docs/sdks/authorization.mdx b/docs/sdks/authorization.mdx index 0b600d36..fa80b0a6 100644 --- a/docs/sdks/authorization.mdx +++ b/docs/sdks/authorization.mdx @@ -602,7 +602,7 @@ await platform.v2.authorization.getDecision({ ... }) | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `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`). | +| `action` | [`Action`](/sdks/policy#action) | Yes | The action being performed (e.g., `decrypt`, `read`). | | `resource` | [`Resource`](#resource) | Yes | The resource being accessed. Use [helpers](#resource) like `ForAttributeValues(...)` (Go) or `Resources.forAttributeValues(...)` (Java/JS). | **Example** @@ -827,14 +827,16 @@ await platform.v2.authorization.getDecisionBulk({ ... }) | Parameter | Type | Required | Description | |-----------|------|----------|-------------| -| `decisionRequests` | `[]GetDecisionMultiResourceRequest` | Yes | Each entry contains an entity, action, and one or more resources to evaluate. | +| `decisionRequests` | [`[]GetDecisionMultiResourceRequest`](#getdecisionmultiresourcerequest) | Yes | Each entry contains an entity, action, and one or more resources to evaluate. | + +### GetDecisionMultiResourceRequest Each `GetDecisionMultiResourceRequest` contains: | Field | Type | Required | Description | |-------|------|----------|-------------| | `entityIdentifier` | [`EntityIdentifier`](#entityidentifier) | Yes | The entity requesting access. | -| `action` | `Action` | Yes | The action being performed. | +| `action` | [`Action`](/sdks/policy#action) | Yes | The action being performed. | | `resources` | [`[]Resource`](#resource) | Yes | Resources to evaluate, each with an `ephemeralId` for correlation. | **Example** diff --git a/docs/sdks/policy.mdx b/docs/sdks/policy.mdx index 65e6a6cb..fec4316a 100644 --- a/docs/sdks/policy.mdx +++ b/docs/sdks/policy.mdx @@ -1616,7 +1616,7 @@ await platform.v1.subjectMapping.updateSubjectConditionSet({ ... }) | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `id` | `string` (UUID) | Yes | The subject condition set ID to update. | -| `subjectSets` | `[]SubjectSet` | No | Replaces the entire condition tree. Omit to update metadata only. | +| `subjectSets` | [`[]SubjectSet`](#subjectset) | No | Replaces the entire condition tree. Omit to update metadata only. | | `metadata` | [`Metadata`](#metadata) | No | Optional [labels](#metadata). | | `metadataUpdateBehavior` | `string` | No | `METADATA_UPDATE_ENUM_REPLACE` or `METADATA_UPDATE_ENUM_EXTEND` (default). | @@ -2345,7 +2345,7 @@ await platform.v1.subjectMapping.matchSubjectMappings({ ... }) | Parameter | Type | Required | Description | |-----------|------|----------|-------------| -| `subjectProperties` | `[]SubjectProperty` | Yes | Key-value pairs from an entity's claims. Each has `externalSelectorValue` (the claim path, e.g., `.clientId`) and `externalValue` (the claim value). | +| `subjectProperties` | [`[]SubjectProperty`](#subjectproperty) | Yes | Key-value pairs from an entity's claims. Each has `externalSelectorValue` (the claim path, e.g., `.clientId`) and `externalValue` (the claim value). | **Example** diff --git a/docs/sdks/tdf.mdx b/docs/sdks/tdf.mdx index 592be43e..9baa9727 100644 --- a/docs/sdks/tdf.mdx +++ b/docs/sdks/tdf.mdx @@ -628,7 +628,7 @@ func (s SDK) PrepareBulkDecrypt(ctx context.Context, opts ...BulkDecryptOption) |-------|------|-------------| | `Reader` | `io.ReadSeeker` | Source of the encrypted TDF. | | `Writer` | `io.Writer` | Destination for the decrypted plaintext. | -| `TriggeredObligations` | `RequiredObligations` | Populated after rewrap with obligation FQNs required by this TDF. See [Obligations in bulk decrypt](#obligations-in-bulk-decrypt). | +| `TriggeredObligations` | [`RequiredObligations`](#requiredobligations) | Populated after rewrap with obligation FQNs required by this TDF. See [Obligations in bulk decrypt](#obligations-in-bulk-decrypt). | **Options** @@ -1423,19 +1423,19 @@ The `Manifest` type is returned by [`CreateTDF`](#createtdf) and accessible via | Field | Type | Description | |-------|------|-------------| | `TDFVersion` | `string` | TDF spec version (e.g. `"4.3.0"`). Serialized as `schemaVersion` in the manifest JSON. | -| `EncryptionInformation` | `EncryptionInformation` | Encryption method, key access objects, and integrity information. | -| `Payload` | `Payload` | Metadata about the encrypted payload. | -| `Assertions` | `[]Assertion` | Cryptographically bound or signed statements attached to the TDF. Empty if none were added at encrypt time. | +| `EncryptionInformation` | [`EncryptionInformation`](#encryptioninformation) | Encryption method, key access objects, and integrity information. | +| `Payload` | [`Payload`](#manifest-payload) | Metadata about the encrypted payload. | +| `Assertions` | [`[]Assertion`](#assertion) | Cryptographically bound or signed statements attached to the TDF. Empty if none were added at encrypt time. | -**EncryptionInformation Fields** +#### EncryptionInformation | Field | Type | Description | |-------|------|-------------| -| `KeyAccessObjs` | `[]KeyAccess` | One entry per KAS holding a key grant. Split TDFs have multiple entries. | +| `KeyAccessObjs` | [`[]KeyAccess`](#keyaccess) | One entry per KAS holding a key grant. Split TDFs have multiple entries. | | `Method.Algorithm` | `string` | Encryption algorithm (e.g. `"AES-256-GCM"`). | | `Policy` | `string` | Base64-encoded policy object. Use [`tdfReader.Policy()`](#policy) to decode. | -**KeyAccess Fields** +#### KeyAccess | Field | Type | Description | |-------|------|-------------| @@ -1444,7 +1444,7 @@ The `Manifest` type is returned by [`CreateTDF`](#createtdf) and accessible via | `SplitID` | `string` | Key split identifier. Entries sharing the same ID share a key segment; different IDs represent independent splits. | | `KID` | `string` | Key identifier on the KAS, if set. | -**Payload Fields** +#### Payload (manifest field) {#manifest-payload} | Field | Type | Description | |-------|------|-------------| @@ -1503,11 +1503,24 @@ for _, a := range manifest.Assertions { | Field | Type | Description | |-------|------|-------------| | `ID` | `string` | Assertion identifier (matches the `AssertionConfig.ID` used at encrypt time). | -| `Type` | `AssertionType` | `"handling"` or `"other"`. | -| `Scope` | `Scope` | `"tdo"` or `"payload"`. | -| `AppliesToState` | `AppliesToState` | `"encrypted"` or `"unencrypted"`. | -| `Statement` | `Statement` | The assertion content. | -| `Binding` | `Binding` | Cryptographic binding — `Method` (`"jws"`) and `Signature` (JWS token). | +| `Type` | [`AssertionType`](#assertion-types) | `"handling"` or `"other"`. | +| `Scope` | [`Scope`](#scopes) | `"tdo"` or `"payload"`. | +| `AppliesToState` | [`AppliesToState`](#appliestostate) | `"encrypted"` or `"unencrypted"`. | +| `Statement` | [`Statement`](#statement-type) | The assertion content. | +| `Binding` | [`Binding`](#binding) | Cryptographic binding — `Method` (`"jws"`) and `Signature` (JWS token). | + +--- + +### Binding + +The cryptographic binding attached to a signed [`Assertion`](#assertion). + +**Fields** + +| Field | Type | Description | +|-------|------|-------------| +| `Method` | `string` | Binding method. Currently `"jws"`. | +| `Signature` | `string` | The JWS token that binds the assertion to the TDF. | --- @@ -1542,11 +1555,25 @@ Passed to `WithAssertionVerificationKeys` when loading a TDF. Maps assertion IDs | Field | Type | Description | |-------|------|-------------| -| `DefaultKey` | `AssertionKey` | Fallback key used when no ID-specific key is found. | +| `DefaultKey` | [`AssertionKey`](#assertionkey) | Fallback key used when no ID-specific key is found. | | `Keys` | `map[string]AssertionKey` | Map of assertion ID to verification key. | --- +### RequiredObligations + +Returned by [`Reader.Obligations()`](#obligations) and populated on each `BulkTDF.TriggeredObligations` field after [`PrepareBulkDecrypt`](#bulkdecrypt). Wraps the obligation FQNs the platform requires the consuming application to enforce before granting access to the TDF's payload. + +Supported in the Go and JavaScript SDKs. + +**Fields** + +| Field | Go | JavaScript | Description | +|-------|-----|------------|-------------| +| FQNs / fqns | `FQNs []string` | `fqns: string[]` | Obligation value FQNs required for this TDF. Empty when no obligations are triggered. | + +--- + --- From bfe33b2ec40c993ea1bf3ed62bb0610064ecec5c Mon Sep 17 00:00:00 2001 From: Mary Dickson Date: Wed, 29 Apr 2026 13:47:34 -0700 Subject: [PATCH 3/4] fix(docs): link ActionsList type and route obligations link to SDK page authorization.mdx: - Link map in EntityEntitlements.actionsPerAttributeValueFqn and add a new Type Reference entry explaining the protobuf wrapper (ActionsList exists because protobuf maps cannot have repeated value types directly). The new section documents the actions field and how Go/Java/JS surface the wrapper. - Update obligations link in the GetDecision Returns description to point at /sdks/obligations (the SDK obligations page) instead of /components/policy/obligations. The SDK page is the right target for readers learning how to handle obligations from SDK code. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/sdks/authorization.mdx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/sdks/authorization.mdx b/docs/sdks/authorization.mdx index fa80b0a6..a5dbb85a 100644 --- a/docs/sdks/authorization.mdx +++ b/docs/sdks/authorization.mdx @@ -789,7 +789,7 @@ if (decision?.decision === Decision.PERMIT) { **Returns** -A [ResourceDecision](#resourcedecision) with a [Decision](#decision) (permit/deny) and any required [obligations](/components/policy/obligations) the consuming application must enforce. +A [ResourceDecision](#resourcedecision) with a [Decision](#decision) (permit/deny) and any required [obligations](/sdks/obligations) the consuming application must enforce. --- @@ -1116,7 +1116,7 @@ Returned by [GetEntitlements](#getentitlements). One per entity, mapping attribu | Field | Type | Description | |-------|------|-------------| | `ephemeralId` | `string` | Correlates with the entity in the request. | -| `actionsPerAttributeValueFqn` | `map` | Keys are attribute value FQNs. Values are lists of [actions](/sdks/policy#action) the entity can perform on data carrying that attribute value. | +| `actionsPerAttributeValueFqn` | [`map`](#actionslist) | Keys are attribute value FQNs. Values are lists of [actions](/sdks/policy#action) the entity can perform on data carrying that attribute value. | ```go for _, e := range resp.GetEntitlements() { @@ -1134,6 +1134,16 @@ for (const e of resp.entitlements) { } ``` +### ActionsList + +A thin wrapper around a list of [`Action`](/sdks/policy#action) used as the value type in `EntityEntitlements.actionsPerAttributeValueFqn`. The wrapper exists because protobuf maps cannot have repeated value types directly. + +| Field | Type | Description | +|-------|------|-------------| +| `actions` | [`[]Action`](/sdks/policy#action) | The actions the entity can perform on data carrying the keyed attribute value. | + +In Go, reach the underlying slice with `actionsList.GetActions()`. In Java, `actionsList.getActionsList()`. In JavaScript, the value is surfaced directly as an `Actions` object whose `.actions` field is the array. + ### GetDecisionMultiResourceResponse Returned by [GetDecisionBulk](#getdecisionbulk). One per entity+action combination in the request. From 20a7446783f5d703aad8f1e40e69faceef966242 Mon Sep 17 00:00:00 2001 From: Mary Dickson Date: Wed, 29 Apr 2026 14:20:17 -0700 Subject: [PATCH 4/4] docs: clarify IsHealthy example error handling Address Gemini Code Assist review feedback: the previous example logged "platform unreachable" for any non-nil err, which misrepresents the IPC mode case. Update the comment to enumerate the three error sources (ErrHealthCheckUnsupported, wrapped ErrPlatformUnreachable on transport failure, wrapped ErrPlatformUnreachable on ctx cancellation) and switch the log line to a generic "health check failed" message. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/sdks/platform-client.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/sdks/platform-client.mdx b/docs/sdks/platform-client.mdx index d1b7f03d..0e11aca2 100644 --- a/docs/sdks/platform-client.mdx +++ b/docs/sdks/platform-client.mdx @@ -100,8 +100,9 @@ const platform = new PlatformClient({ ...auth, platformUrl: 'http://localhost:80 ```go healthy, err := client.IsHealthy(ctx) if err != nil { - // transport failure or context cancellation - log.Printf("platform unreachable: %v", err) + // err is sdk.ErrHealthCheckUnsupported (IPC mode), or wraps + // sdk.ErrPlatformUnreachable on transport failure or ctx cancellation + log.Printf("health check failed: %v", err) return } if !healthy {