Skip to content

Commit a2e9b5b

Browse files
committed
feat: add sdk contributor guidelines
1 parent 8081a0a commit a2e9b5b

File tree

5 files changed

+353
-4
lines changed

5 files changed

+353
-4
lines changed

docs/sdks/_category_.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
2-
"label": "SDK",
3-
"position": 6,
2+
"label": "SDKs",
3+
"position": 4,
44
"link": {
55
"type": "generated-index",
6-
"description": "The OpenTDF platform provides Software Development Kits in the Go, Java, and JavaScript languages. The SDKs include guides and working examples for managing policy, creating Trusted Data Format (TDF) protected objects, and making authorization decisions within an application."
6+
"description": "Documentation for official OpenTDF SDK guidelines and implementations"
77
}
8-
}
8+
}

docs/sdks/go/_category_.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"label": "Go SDK",
3+
"position": 3,
4+
"link": {
5+
"type": "generated-index",
6+
"description": "Documentation for the Go SDK - the reference implementation of OpenTDF"
7+
}
8+
}

docs/sdks/java/_category_.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"label": "Java SDK",
3+
"position": 4,
4+
"link": {
5+
"type": "generated-index",
6+
"description": "Documentation for the Java SDK implementation of OpenTDF"
7+
}
8+
}
Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
---
2+
sidebar_position: 2
3+
title: Official SDK Guidelines
4+
description: Official guidelines and standards for implementing OpenTDF SDKs
5+
---
6+
7+
# Official SDK Guidelines
8+
9+
This document provides the official guidelines and standards for:
10+
- OpenTDF contributors implementing new language SDKs
11+
- Developers who want to understand the official SDK architecture and implementation details
12+
13+
If you're looking to *use* an existing OpenTDF SDK, please see the [SDK Overview](/sdks/overview) instead.
14+
15+
## Core Principles for Official OpenTDF SDKs
16+
17+
All official OpenTDF SDKs must adhere to these core principles to ensure functional parity and consistent developer experience across languages:
18+
19+
### 1. Platform-First Initialization
20+
21+
Every SDK requires a platform base URL (endpoint) at initialization, along with necessary credentials. This endpoint is the entry point to OpenTDF platform services. The SDK will automatically:
22+
23+
- Discover service endpoints (KAS, Policy, etc.)
24+
- Configure network clients
25+
- Retrieve well-known configuration
26+
27+
### 2. Service Communication via Generated Clients
28+
29+
SDKs use auto-generated API clients (using Protocol Buffers/Connect RPC) for communicating with OpenTDF services. This ensures:
30+
31+
- Consistent interfaces across languages
32+
- Type-safe API calls
33+
- Reduced boilerplate code
34+
- Up-to-date API definitions
35+
36+
### 3. Format Support and Cryptography
37+
38+
Every SDK must support:
39+
40+
- Standard TDF (ZIP/JSON format) with manifest
41+
- NanoTDF (compact binary format)
42+
- Attribute-Based Access Control (ABAC)
43+
- Signed assertions and policy binding
44+
45+
### 4. Language-Idiomatic Design
46+
47+
While maintaining functional parity, each SDK should follow patterns natural to its language:
48+
49+
#### Go SDK (Reference Implementation)
50+
```go
51+
// Functional options pattern
52+
client := tdf.NewClient(
53+
WithPlatformURL("https://platform.example.com"),
54+
WithClientCredentials("id", "secret"),
55+
)
56+
```
57+
58+
#### Java SDK
59+
```java
60+
// Builder pattern
61+
TdfClient client = TdfClient.builder()
62+
.platformUrl("https://platform.example.com")
63+
.clientCredentials("id", "secret")
64+
.build();
65+
```
66+
67+
#### JavaScript/TypeScript SDK
68+
```typescript
69+
// Options object pattern
70+
const client = new TdfClient({
71+
platformUrl: "https://platform.example.com",
72+
credentials: {
73+
clientId: "id",
74+
clientSecret: "secret"
75+
}
76+
});
77+
```
78+
79+
## Unified Interface Strategy
80+
81+
### Java SDK Implementation
82+
83+
The Java SDK should provide a clean, unified interface through the new `TdfClient` class:
84+
85+
```java
86+
// Future unified API
87+
TdfClient client = TdfClient.builder()
88+
.platformUrl("https://platform.example.com")
89+
.clientCredentials("id", "secret")
90+
.build();
91+
92+
// Encrypt with data attributes
93+
client.setDataAttributes(List.of("attr1", "attr2"));
94+
client.addAssertion("classification", "SECRET", signingKey);
95+
96+
// Encrypt/decrypt methods support both formats
97+
try (InputStream in = new FileInputStream("plain.txt");
98+
OutputStream out = new FileOutputStream("encrypted.tdf")) {
99+
client.encrypt(in, out, TdfClient.Format.TDF); // or Format.NANO
100+
}
101+
```
102+
103+
### Web SDK Implementation
104+
105+
The Web SDK should provide a similar unified interface through TypeScript:
106+
107+
```typescript
108+
const client = new TdfClient({
109+
platformUrl: "https://platform.example.com",
110+
oidcOrigin: "https://idp.example.com",
111+
credentials: {
112+
clientId: "myClientId",
113+
clientSecret: "secretToken"
114+
}
115+
});
116+
117+
// Set policy and assertions
118+
await client.setDataAttributes(["https://opentdf.io/attr/class/value/secret"]);
119+
await client.addAssertion("clearance", "SECRET", signingKey);
120+
121+
// Encrypt data (automatically selects format based on size/config)
122+
const ciphertext = await client.encrypt(plaintext, { format: "nano" });
123+
const decrypted = await client.decrypt(ciphertext); // auto-detects format
124+
```
125+
126+
## Migration Strategy
127+
128+
Here's how to migrate existing code to the new unified interface:
129+
130+
### 1. Client Initialization Migration
131+
132+
**Old approach (pre-4.0):**
133+
```typescript
134+
// JavaScript/TypeScript
135+
const client = await NanoTDFClient.fromConfig({
136+
kasUrl: "https://kas.example.com",
137+
authProvider: new OIDCCredentials(/*...*/)
138+
});
139+
140+
// Java
141+
NanoTDFClient client = new NanoTDFClient();
142+
client.setKasUrl("https://kas.example.com");
143+
client.setAuthProvider(new OIDCCredentials());
144+
```
145+
146+
**New unified approach (4.0+):**
147+
```typescript
148+
// JavaScript/TypeScript
149+
const client = new TdfClient({
150+
platformUrl: "https://platform.example.com", // Single endpoint
151+
credentials: {
152+
clientId: "id",
153+
clientSecret: "secret"
154+
}
155+
});
156+
157+
// Java
158+
TdfClient client = TdfClient.builder()
159+
.platformUrl("https://platform.example.com")
160+
.clientCredentials("id", "secret")
161+
.build();
162+
```
163+
164+
### 2. Encryption/Decryption Migration
165+
166+
**Old approach:**
167+
168+
```typescript
169+
// JavaScript/TypeScript - separate clients for different formats
170+
const nanoClient = new NanoTDFClient(config);
171+
const tdfClient = new TDFClient(config);
172+
173+
const nanoEncrypted = await nanoClient.encrypt(data);
174+
const tdfEncrypted = await tdfClient.encrypt(data);
175+
176+
// Java
177+
NanoTDFClient nanoClient = new NanoTDFClient();
178+
TDFClient tdfClient = new TDFClient();
179+
180+
byte[] nanoEncrypted = nanoClient.encrypt(data);
181+
byte[] tdfEncrypted = tdfClient.encrypt(data);
182+
```
183+
184+
**New unified approach:**
185+
```typescript
186+
// JavaScript/TypeScript - single client handles both formats
187+
const client = new TdfClient(config);
188+
189+
// Format is auto-selected or explicitly specified
190+
const encrypted = await client.encrypt(data, { format: "nano" });
191+
const decrypted = await client.decrypt(encrypted); // Format auto-detected
192+
193+
// Java
194+
TdfClient client = TdfClient.builder().build();
195+
196+
// Streaming API with format selection
197+
try (InputStream in = new FileInputStream("plain.txt");
198+
OutputStream out = new FileOutputStream("encrypted.tdf")) {
199+
client.encrypt(in, out, TdfClient.Format.NANO);
200+
}
201+
```
202+
203+
### 3. Testing Migration
204+
205+
Replace abstract test suites with concrete integration tests:
206+
207+
```typescript
208+
describe('TDF Client Migration', () => {
209+
// Test unified client with legacy format
210+
it('should decrypt legacy NanoTDF format', async () => {
211+
const unified = new TdfClient(config);
212+
const legacyEncrypted = await getLegacyEncryptedData();
213+
const decrypted = await unified.decrypt(legacyEncrypted);
214+
expect(decrypted).toEqual(originalData);
215+
});
216+
217+
// Test format interoperability
218+
it('should support cross-format operations', async () => {
219+
const client = new TdfClient(config);
220+
221+
// Encrypt as NanoTDF
222+
const nano = await client.encrypt(data, { format: 'nano' });
223+
224+
// Decrypt with format auto-detection
225+
const decrypted1 = await client.decrypt(nano);
226+
expect(decrypted1).toEqual(data);
227+
228+
// Encrypt as standard TDF
229+
const tdf = await client.encrypt(data, { format: 'tdf' });
230+
231+
// Decrypt with format auto-detection
232+
const decrypted2 = await client.decrypt(tdf);
233+
expect(decrypted2).toEqual(data);
234+
});
235+
});
236+
```
237+
238+
### Migration Gotchas
239+
240+
1. **Attribute Format Changes**
241+
- Legacy: Simple strings (`"SECRET"`)
242+
- New: Full URIs (`"https://opentdf.io/attr/classification/value/secret"`)
243+
- Migration helper: `client.normalizeAttribute(legacyAttr)`
244+
245+
2. **Error Handling Changes**
246+
- Legacy: Multiple error types (`NanoTDFError`, `TDFError`)
247+
- New: Unified `TdfError` with error codes
248+
- Example: `TdfError.FORMAT_INVALID` instead of `InvalidNanoTDFError`
249+
250+
3. **Configuration Changes**
251+
- Legacy configs won't work with unified client
252+
- Use `ConfigMigrationTool` (included) to convert:
253+
```typescript
254+
const unifiedConfig = ConfigMigrationTool.migrate(legacyConfig);
255+
const client = new TdfClient(unifiedConfig);
256+
```
257+
258+
## Implementing a New SDK
259+
260+
### Prerequisites
261+
262+
1. Familiarize yourself with:
263+
- [OpenTDF Architecture](/architecture)
264+
- [TDF Specification](https://github.com/opentdf/spec)
265+
- [Go SDK](https://github.com/opentdf/platform) (reference implementation)
266+
267+
2. Required capabilities:
268+
- Protocol Buffers / Connect RPC support
269+
- Modern cryptography library support
270+
- ZIP handling (for standard TDF)
271+
- JSON parsing
272+
273+
### Implementation Steps
274+
275+
1. **Service Client Generation**
276+
- Generate API clients from Protocol Buffer definitions
277+
- Implement authentication flow
278+
- Configure service discovery
279+
280+
2. **Core Cryptographic Operations**
281+
- Implement key derivation
282+
- Support ECC for NanoTDF
283+
- Implement signature verification
284+
285+
3. **Format Support**
286+
- Implement TDF manifest creation/parsing
287+
- Implement NanoTDF binary format
288+
- Support streaming for large files
289+
290+
4. **Policy and Assertions**
291+
- Implement ABAC policy binding
292+
- Support signed assertions
293+
- Validate integrity during decryption
294+
295+
## Implementation Checklist
296+
297+
For each new SDK implementation:
298+
299+
- [ ] Service Integration
300+
- [ ] Platform URL configuration
301+
- [ ] Well-known endpoint discovery
302+
- [ ] Authentication flow
303+
- [ ] Generated service clients
304+
305+
- [ ] TDF Support
306+
- [ ] Manifest creation/parsing
307+
- [ ] ZIP packaging
308+
- [ ] Streaming support
309+
- [ ] Policy binding
310+
311+
- [ ] NanoTDF Support
312+
- [ ] Binary format handling
313+
- [ ] ECC cryptography
314+
- [ ] Performance optimization
315+
316+
- [ ] Policy & Security
317+
- [ ] ABAC implementation
318+
- [ ] Assertion signing/verification
319+
- [ ] Key derivation
320+
- [ ] Integrity validation
321+
322+
For detailed technical specifications and implementation guidance, see:
323+
- [TDF Format Specification](/spec/schema/opentdf)
324+
- [NanoTDF Specification](/spec/schema/nanotdf)
325+
- [Protocol Documentation](/spec/protocol)

docs/sdks/web/_category_.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"label": "Web SDK",
3+
"position": 5,
4+
"link": {
5+
"type": "generated-index",
6+
"description": "Documentation for the JavaScript/TypeScript Web SDK implementation of OpenTDF"
7+
}
8+
}

0 commit comments

Comments
 (0)