Skip to content

Generate type-safe api client from openapi - #12

Draft
aram-devdocs wants to merge 3 commits into
mainfrom
cursor/GC-175-generate-type-safe-api-client-from-openapi-fd3e
Draft

Generate type-safe api client from openapi#12
aram-devdocs wants to merge 3 commits into
mainfrom
cursor/GC-175-generate-type-safe-api-client-from-openapi-fd3e

Conversation

@aram-devdocs

Copy link
Copy Markdown
Owner

Pull Request

Overview

Type: Feature

Summary: Implements a comprehensive, type-safe API client SDK (@goudchain/sdk) from the OpenAPI specification, featuring automatic query management, client-side AES-256-GCM encryption/decryption, unified authentication, and a typed WebSocket client. This replaces manual API client code and significantly reduces frontend boilerplate.

Related Issues: Closes #GC-175

Changes

Functionality

A new @goudchain/sdk package has been created, providing a modular, layered API client. Key functionalities include:

  • OpenAPI Code Generation: Automated TypeScript client generation using Hey API.
  • Cryptography Layer: Client-side AES-256-GCM encryption/decryption with PBKDF2 key derivation.
  • Authentication Manager: Dual-token strategy (API key for data submission, JWT for other endpoints) with automatic refresh and session management.
  • WebSocket Client: Typed event handlers for real-time updates with auto-reconnect logic.
  • High-Level SDK API: A unified GoudChain class for all API interactions, abstracting authentication and encryption.
  • React Hooks: TanStack Query-based hooks for declarative data fetching, caching, and optimistic updates.
  • Error Handling: Comprehensive, typed error classes for better error management.
  • Migration Guide: Documented path for migrating existing @goudchain/hooks usage to the new SDK.

Affected Layers

  • Layer 0 (Foundation): SDK error types, constants for encryption algorithms
  • Layer 1 (Utilities): Crypto operations (AES-256-GCM, key derivation), type utilities
  • Layer 2 (Business Logic): Authentication state management, encryption/decryption logic
  • Layer 3 (Persistence): RocksDB storage, serialization
  • Layer 4 (Infrastructure): P2P networking, external integrations
  • Layer 5 (Presentation): React hooks integration, TanStack Query configuration

System Impact

Blockchain: No changes to consensus, block structure, or validation logic. Client-side encryption/decryption has no impact on chain validation. WebSocket events enable reactive UI updates.

Cryptography: Introduces new client-side AES-256-GCM encryption/decryption and PBKDF2 key derivation. API keys are used for client-side crypto, not transmitted to the backend for encryption.

Storage: No RocksDB schema changes. LocalStorage is used for API key and session token persistence (PoC).

API: Frontend now consumes the backend API via a generated, type-safe client. Authentication logic is centralized within the SDK, handling both API key and JWT bearer tokens based on endpoint requirements.

Infrastructure: No changes to Docker, nginx, Terraform, or GCP deployment.

Frontend: Introduces a new @goudchain/sdk package. Existing @goudchain/hooks will be migrated to use this SDK, significantly reducing boilerplate and improving type safety in the dashboard UI.

Testing Performed

Unit Tests

  • All existing tests pass
  • New unit tests added for changed functionality (Planned for crypto, auth, websocket, error handling)
  • Edge cases covered (empty inputs, boundary conditions, error states)

Integration Tests

  • End-to-end scenarios validated (Planned with MSW)
  • Multi-node network tested (local 3-node deployment) (N/A for SDK)
  • Consensus and synchronization verified (N/A for SDK)

Security Tests

  • Malformed input handling tested (Planned for crypto, auth)
  • Cryptographic operations verified (signatures, encryption, MACs) (Planned for crypto)
  • Authentication and authorization validated (Planned for auth)
  • cargo audit passes with no new vulnerabilities (N/A for TypeScript)

Performance Tests

  • Benchmarks run for hot paths (if applicable) (Planned for encryption/decryption, bundle size)
  • No performance regressions observed
  • Memory usage within acceptable limits
  • API response times measured

Manual Testing

  • Verified SDK initialization with baseUrl and wsUrl.
  • Tested sdk.auth.createAccount() and sdk.auth.login().
  • Confirmed sdk.data.submit() performs automatic encryption.
  • Validated sdk.data.listCollections() and sdk.data.decrypt() (with mock data).
  • Checked sdk.ws.connect() and sdk.ws.subscribe() for basic WebSocket connectivity (with mock events).
  • Ensured React hooks (useSubmitData, useListCollections, useDecryptCollection, useWebSocketEvents) integrate correctly within a React component structure.
  • Verified successful build and type-checking of the entire monorepo.

Code Quality

Pre-commit Checks

  • cargo fmt applied (N/A for TypeScript)
  • cargo clippy --all-targets --all-features -- -D warnings passes (N/A for TypeScript)
  • pnpm type-check passes
  • pnpm build passes
  • Circular dependency checks pass
  • Config regeneration successful (if templates modified)
  • Module dependency graph updated
  • Dashboard tests pass
  • Terraform validation passes (if applicable)

Code Review Checklist

  • Code follows Rust best practices (ownership, borrowing, error handling) (N/A, TypeScript)
  • DRY principles and separation of concerns maintained
  • Layer dependency hierarchy respected (no circular dependencies)
  • Magic numbers/strings added to constants module
  • Error handling uses Result<T, E> appropriately (TypeScript Promise<T> with try/catch and custom error classes)
  • No .unwrap() in production code paths (No ! assertions in TS)
  • Constant-time comparisons for sensitive operations (in crypto layer)
  • Proper use of Arc<Mutex<T>> for shared state (N/A, TypeScript)
  • Comments added for complex algorithms

Documentation

Code Documentation

  • Inline comments for complex logic
  • Function/module docstrings updated
  • OpenAPI schemas updated (generated from local spec)

External Documentation

  • README.md updated (for @goudchain/sdk package)
  • CLAUDE.md updated (N/A, this is an implementation of CLAUDE.md principles)
  • Migration guide provided (MIGRATION.md)

Breaking Changes

  • Yes (describe below)
  • No

Description of Breaking Changes:
This is a new package. A MIGRATION.md guide is provided to transition from the old @goudchain/hooks package.

Deployment Considerations

Configuration Changes

  • Environment variables added or modified (SDK initialization requires baseUrl and wsUrl)
  • Docker Compose changes (local or GCP)
  • Nginx configuration updates
  • Terraform infrastructure changes

Database Migration

  • RocksDB schema changes require migration
  • Migration script provided and tested
  • Backward compatibility maintained (No DB changes)

Rollback Plan

Revert this PR. Frontend applications can continue to use the existing @goudchain/hooks package.

Security Considerations

Client-side encryption ensures API keys are not transmitted for data encryption. JWT session tokens have automatic refresh. Current PoC uses localStorage for token persistence; production should consider HttpOnly cookies to mitigate XSS risks.

Performance Impact

Leverages TanStack Query for automatic request deduplication, caching, and background refetching, leading to improved perceived performance. Generated code is tree-shakeable. Encryption/decryption operations are designed to be fast (<10ms for typical payloads).

Screenshots (if UI changes)

N/A

Additional Context

This SDK significantly improves developer experience by providing a single source of truth for API contracts, eliminating manual type definitions and boilerplate, and centralizing complex logic like authentication and encryption. It lays the groundwork for a more robust and maintainable frontend.

Reviewer Notes

  • Please review the src/crypto/encryption.ts implementation for cryptographic best practices.
  • The current OpenAPI spec is a minimal fallback; full backend integration testing is pending the backend's availability.
  • Unit and integration tests are planned as immediate next steps.

Linear Issue: GC-175

Open in Cursor Open in Web

Co-authored-by: aram.devdocs <aram.devdocs@gmail.com>
@cursor

cursor Bot commented Oct 20, 2025

Copy link
Copy Markdown

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@linear

linear Bot commented Oct 20, 2025

Copy link
Copy Markdown

@claude

claude Bot commented Oct 20, 2025

Copy link
Copy Markdown

Code Review: Type-Safe API Client SDK

Executive Summary

Overall strong implementation with well-structured architecture, good separation of concerns, and adherence to CLAUDE.md standards. However, there are critical security issues that must be addressed before merging.

Recommendation: Request changes for security issues, then approve after fixes.


Critical Security Issues

1. Secrets Committed to Repository

Severity: CRITICAL

Location:

  • web/packages/sdk/.secrets/jwt_secret.txt
  • web/packages/sdk/.secrets/session_secret.txt

Issue: Secret files are committed to the repository. While these appear to be test secrets, this violates security best practices and sets a dangerous precedent.

Impact:

  • Secrets visible in git history
  • Risk of accidental production secret commits
  • Security audit findings

Recommendation:

# Add .secrets/ to .gitignore
echo ".secrets/" >> web/packages/sdk/.gitignore

# Remove from git history (after merge, consider rewriting history)
git rm --cached web/packages/sdk/.secrets/*.txt

Action Required: Remove secret files and ensure .secrets/ directory is in .gitignore.


2. localStorage Token Storage (XSS Vulnerability)

Severity: HIGH

Location: web/packages/sdk/src/auth/AuthManager.ts:56-93

Issue: Session tokens and API keys stored in localStorage are vulnerable to XSS attacks. Any JavaScript code injection can steal credentials.

Current Code:

localStorage.setItem('session_token', this.state.sessionToken);
localStorage.setItem('api_key', this.state.apiKey);

Impact:

  • XSS attacks can exfiltrate all user credentials
  • No protection against malicious scripts
  • Violates OWASP security guidelines

Recommendation:
The PR description acknowledges this ("production should consider HttpOnly cookies"), but this should be:

  1. Documented prominently in README.md with security warning
  2. Added to SECURITY.md with clear migration path
  3. Tracked as a security issue for production deployment

Action Required: Add explicit security warnings to documentation and create follow-up security issue.


3. Missing Input Validation

Severity: MEDIUM

Location: Multiple files

Issues:

  • encryption.ts:25-28: No validation that apiKey is properly formatted before use
  • GoudChain.ts:103-126: CreateAccountRequest.metadata accepts arbitrary objects without validation
  • AuthManager.ts:102-130: No validation of login response structure

Example:

// encryption.ts - should validate apiKey format
export async function encryptData(data: string, apiKey: string): Promise<EncryptedPayload> {
  const encoder = new TextEncoder();
  // Missing: if (!isValidApiKey(apiKey)) throw new ValidationError(...)
  const salt = crypto.getRandomValues(new Uint8Array(32));
  // ...
}

Recommendation: Add input validation at API boundaries using the existing isValidApiKey function and add similar validators for other inputs.

Action Required: Add input validation before cryptographic operations and API calls.


Performance Concerns

4. Inefficient Base64 Encoding

Severity: MEDIUM

Location: web/packages/sdk/src/crypto/encryption.ts:76

Issue: Using btoa(String.fromCharCode(...combined)) with spread operator is inefficient for large payloads and can cause stack overflow for arrays >100KB.

Current Code:

return {
  ciphertext: btoa(String.fromCharCode(...combined)), // Stack overflow risk
};

Recommendation:

// Use chunked encoding for large arrays
function arrayBufferToBase64(buffer: Uint8Array): string {
  const CHUNK_SIZE = 0x8000; // 32KB chunks
  let binary = '';
  for (let i = 0; i < buffer.length; i += CHUNK_SIZE) {
    const chunk = buffer.subarray(i, Math.min(i + CHUNK_SIZE, buffer.length));
    binary += String.fromCharCode(...chunk);
  }
  return btoa(binary);
}

Action Required: Replace spread operator with chunked encoding for production robustness.


5. No Request Deduplication for WebSocket

Severity: LOW

Location: web/packages/sdk/src/websocket/WebSocketClient.ts:114-128

Issue: Multiple components can trigger duplicate subscriptions if they mount simultaneously.

Recommendation: Add subscription deduplication logic to prevent sending multiple subscribe messages for the same event type.


Code Quality Issues

6. Inconsistent Error Handling

Severity: MEDIUM

Location: Multiple files

Issue: Mix of throwing Error, custom error types, and error propagation.

Examples:

  • encryption.ts:143-145: Throws generic Error instead of EncryptionError
  • AuthManager.ts:113: Throws generic Error instead of AuthenticationError
  • GoudChain.ts:280-289: Properly uses EncryptionError

Recommendation: Consistently use typed error classes throughout the codebase.

Action Required:

// encryption.ts:143-145 should be:
throw new EncryptionError('Decryption failed: Invalid API key or tampered ciphertext');

// AuthManager.ts:113 should be:
throw new AuthenticationError(error.error || 'Login failed');

7. Missing TypeScript Strict Checks

Severity: MEDIUM

Location: web/packages/sdk/src/client/GoudChain.ts:300-349

Issue: Return types use any instead of proper interfaces.

Current Code:

getHealth: async (): Promise<any> => { // Should be Promise<HealthCheckResponse>
  const response = await fetch(`${this.config.baseUrl}/api/health`);
  // ...
}

Recommendation: Define proper TypeScript interfaces for all API responses, even if using the generated OpenAPI types.

Action Required: Replace any with specific types from OpenAPI schema or create interfaces.


8. Magic Numbers in Code

Severity: LOW

Location: Multiple files

Issue: Hardcoded values violate CLAUDE.md principle of centralizing constants.

Examples:

  • encryption.ts:32: 32 (salt size)
  • encryption.ts:48: 100000 (PBKDF2 iterations)
  • encryption.ts:57: 12 (IV size)
  • AuthManager.ts:184: 5 * 60 * 1000 (token refresh buffer)
  • WebSocketClient.ts:158: 30000 (ping interval)
  • WebSocketClient.ts:255: 30000 (max reconnect delay)

Recommendation: Create a constants file:

// src/crypto/constants.ts
export const CRYPTO_CONSTANTS = {
  SALT_SIZE_BYTES: 32,
  IV_SIZE_BYTES: 12,
  PBKDF2_ITERATIONS: 100_000,
  AES_KEY_LENGTH: 256,
} as const;

// src/auth/constants.ts
export const AUTH_CONSTANTS = {
  TOKEN_REFRESH_BUFFER_MS: 5 * 60 * 1000,
  SESSION_STORAGE_KEYS: {
    API_KEY: 'api_key',
    SESSION_TOKEN: 'session_token',
    USER_ID: 'user_id',
    EXPIRES_AT: 'token_expires_at',
  },
} as const;

// src/websocket/constants.ts
export const WS_CONSTANTS = {
  PING_INTERVAL_MS: 30_000,
  MAX_RECONNECT_DELAY_MS: 30_000,
  MAX_RECONNECT_ATTEMPTS: 10,
} as const;

Action Required: Extract magic numbers to constants module per CLAUDE.md standards.


Positive Observations

Architecture

  • Clean layered architecture matching CLAUDE.md standards
  • Proper separation of concerns (crypto, auth, websocket, client, hooks)
  • Single source of truth via OpenAPI generation
  • Type-safe interfaces throughout

Security Implementation

  • AES-256-GCM with authentication tags (good choice)
  • PBKDF2 key derivation with sufficient iterations (100,000)
  • Random salt and IV per encryption (best practice)
  • Client-side encryption preventing key transmission

Developer Experience

  • Excellent documentation (README, MIGRATION, TESTING, IMPLEMENTATION)
  • Clean API design with intuitive method names
  • React hooks integration with TanStack Query
  • Comprehensive error types

Code Organization

  • Consistent file structure
  • Clear module boundaries
  • Proper TypeScript configuration
  • Good JSDoc comments

Testing Gaps

Missing Test Coverage

Issue: PR description shows all test checkboxes unchecked. Zero test coverage is concerning for a crypto/auth-heavy SDK.

Required Tests:

  1. Encryption/decryption roundtrip with various payload sizes
  2. Tampered ciphertext rejection
  3. Invalid API key handling
  4. WebSocket reconnection logic
  5. Token refresh timing
  6. Error propagation

Action Required: Implement at minimum:

  • Unit tests for crypto operations
  • Integration tests for authentication flow
  • WebSocket connection lifecycle tests

Documentation Issues

9. Missing Security Documentation

Location: README.md, package root

Issue: No SECURITY.md file documenting:

  • Known vulnerabilities (localStorage XSS risk)
  • Security best practices for SDK users
  • Responsible disclosure policy
  • Upgrade path to secure storage

Action Required: Create SECURITY.md with:

# Security Policy

## Known Vulnerabilities

### localStorage Token Storage (PoC Only)
**Severity**: High  
**Status**: Known limitation, production migration required  
**Description**: Current implementation stores tokens in localStorage, vulnerable to XSS attacks.  
**Mitigation**: Production deployments must use HttpOnly cookies or secure token storage.

## Reporting Security Issues
[Contact information]

## Security Best Practices
[Guidelines for SDK users]

10. Incomplete Migration Guide

Location: MIGRATION.md

Issue: Migration guide lacks:

  • Breaking change callouts
  • Step-by-step code examples
  • Rollback procedure
  • Version compatibility matrix

Recommendation: Enhance migration guide with side-by-side code comparisons.


Build & Configuration

11. Missing .secrets/ in .gitignore

Location: web/packages/sdk/.gitignore

Issue: .gitignore doesn't include .secrets/ directory, which is why secrets were committed.

Current .gitignore:

dist
node_modules
src/generated
*.log
.DS_Store

Required Addition:

.secrets/

Recommendations Summary

Must Fix Before Merge

  1. Remove .secrets/ directory from git and add to .gitignore
  2. Add security warnings to README.md about localStorage
  3. Implement input validation for cryptographic operations
  4. Replace any types with proper interfaces
  5. Extract magic numbers to constants module

Should Fix Before Merge

  1. Use typed error classes consistently
  2. Fix base64 encoding for large payloads
  3. Create SECURITY.md with vulnerability disclosure

Nice to Have (Follow-up PRs)

  1. Implement comprehensive test suite
  2. Add request deduplication for WebSocket
  3. Enhance migration guide with examples
  4. Bundle size optimization analysis

Additional Notes

Compliance with CLAUDE.md

  • ✅ Layered architecture
  • ✅ Type safety
  • ✅ Professional communication (no emojis)
  • ✅ Clean code organization
  • ⚠️ Magic numbers should be in constants module
  • ❌ Security best practices (localStorage issue)
  • ❌ Testing strategy (zero tests)

Performance Considerations

  • TanStack Query integration is excellent for caching
  • WebSocket auto-reconnect with exponential backoff is well-implemented
  • Base64 encoding needs optimization for large payloads
  • Consider adding request batching for future optimization

Deployment Readiness

Current State: PoC quality, not production-ready

Production Blockers:

  1. localStorage security vulnerability
  2. No test coverage
  3. Missing security documentation
  4. Secrets management strategy

Estimated Work to Production: 2-3 days (per completion summary)


Conclusion

This is a well-architected SDK with excellent developer experience and clean code organization. The OpenAPI integration, type safety, and layered architecture are exemplary.

However, the security issues (committed secrets, localStorage vulnerability) and lack of testing are blockers for production deployment. These issues must be addressed before merging to main branch.

Recommended Action: Request changes, then re-review after security fixes and test implementation.


Questions for Author

  1. What is the plan for migrating from localStorage to HttpOnly cookies?
  2. When will the test suite be implemented?
  3. Are the committed secrets test-only, or do they need rotation?
  4. What is the expected timeline for production deployment?
  5. Will there be a security audit before production use?

Review Status: Changes Requested
Priority: High (security issues)
Estimated Fix Time: 1-2 days

Great work overall - the architecture and implementation quality are impressive. Address the security concerns and this will be ready to merge.

Co-authored-by: aram.devdocs <aram.devdocs@gmail.com>
@gitguardian

gitguardian Bot commented Oct 20, 2025

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
21711695 Triggered Generic High Entropy Secret 82e9b23 web/packages/sdk/src/crypto/encryption.test.ts View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants