arkavo-org / arkavo-org/OpenTDFKit

Improve NanoTDF Developer Experience

Open
#25 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Swift
Stars
1
Forks
1
Avg merge
9d 4h
Merged PRs (30d)
1

Description

## Summary
While integrating NanoTDF encryption into an iOS app, several API design aspects could be improved to enhance developer experience.

## Current Challenges

### 1. Failable Initializers Without Clear Documentation
`ResourceLocator` has a failable initializer but the conditions for failure aren't immediately clear from the API:
```swift
public init?(protocolEnum: ProtocolEnum, body: String, identifier: Data? = nil)
```
**Impact**: Developers need to handle optionals and understand validation rules (e.g., body length 1-255 bytes)

### 2. PublicKeyType Requires Manual PEM Parsing
When working with PEM-formatted public keys from a KAS endpoint, developers must manually:
- Strip PEM headers/footers
- Base64 decode
- Parse DER representation
- Convert to `P256.KeyAgreement.PublicKey`

**Current code needed**:
```swift
let base64String = pem
.replacingOccurrences(of: "-----BEGIN PUBLIC KEY-----", with: "")
.replacingOccurrences(of: "-----END PUBLIC KEY-----", with: "")
.replacingOccurrences(of: "\n", with: "")
.trimmingCharacters(in: .whitespacesAndNewlines)
guard let derData = Data(base64Encoded: base64String) else {
throw Error()
}
let publicKey = try P256.KeyAgreement.PublicKey(derRepresentation: derData)
```

### 3. Module vs Instance Method Naming Collision
The global function `createNanoTDF(kas:policy:plaintext:)` can collide with instance methods, requiring:
```swift
let nanoTDF = try await OpenTDFKit.createNanoTDF(kas: kasMetadata, policy: &policy, plaintext: content)
```

### 4. Missing High-Level Decryption API
While encryption has `createNanoTDF()`, there's no equivalent high-level `decryptNanoTDF()` function that handles:
- Parsing NanoTDF structure
- KAS rewrap
- Symmetric key derivation
- Payload decryption

Developers must manually orchestrate these steps using low-level APIs.

## Suggested Improvements

### 1. Throwing Initializers or Validation Helpers
```swift
// Option A: Throwing init
public init(protocolEnum: ProtocolEnum, body: String, identifier: Data? = nil) throws

// Option B: Static factory with clear errors
public static func create(protocolEnum: ProtocolEnum, body: String) throws -> ResourceLocator
```

### 2. PEM Parsing Helper
```swift
extension KasMetadata {
public static func fromPEM(
endpoint: String,
publicKeyPEM: String,
curve: Curve = .secp256r1
) throws -> KasMetadata
}
```

### 3. High-Level Decryption API
```swift
public func decryptNanoTDF(
nanoTDF: Data,
kasRewrapClient: KASRewrapClient
) async throws -> Data
```

### 4. Convenience Constructors
```swift
extension Policy {
public static func embedded(
json: String,
ownerID: String? = nil
) throws -> Policy
}
```

## Use Case
iOS app encrypting user-generated content with policy-based access control, using a remote KAS at `https://kas.example.com/kas`.

## Priority
Medium - These are quality-of-life improvements, not blockers. Current API is functional but requires more boilerplate.

## Related
- NanoTDF specification compliance
- iOS/mobile developer experience
- API ergonomics for common use cases

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reviewing the ResourceLocator initializer, PublicKeyType handling, createNanoTDF entry point, and the low-level decryption APIs named in the issue. Agree on which API improvements are in scope and define completion around the selected constructors, PEM helper, and high-level decryption flow being usable without the current boilerplate.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
api, developer-experience, mobile-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.