# Solomon AI Financial Engine SDK

The official TypeScript SDK for the Solomon AI Financial Platform and Financial Workspace Backend.

## Features

- 🔐 **Authentication & API Key Management** - Full CRUD operations for API keys
- 🏦 **Financial Services** - Banking integrations with Plaid, GoCardless, and EnableBanking
- 🤖 **AI-Powered Intelligence** - Transaction categorization, tax optimization, and business insights
- 📊 **Analytics & Metrics** - Comprehensive usage analytics and verification data
- 🚦 **Rate Limiting** - Advanced rate limiting with overrides and monitoring
- 🔄 **Connections Management** - Banking connection lifecycle management
- 💰 **Transaction Processing** - Real-time transaction data and recurring pattern detection
- 📋 **Financial Statements** - Statement retrieval and PDF generation
- 🎯 **Permissions & RBAC** - Role-based access control and fine-grained permissions

## Installation

```bash
npm install @solomonai/financial-engine-sdk
# or
pnpm add @solomonai/financial-engine-sdk
# or
yarn add @solomonai/financial-engine-sdk
```

## Quick Start

```typescript
import { SolomonAI } from "@solomonai/financial-engine-sdk";

const solomonAI = new SolomonAI({
  rootKey: "your-root-key",
  baseUrl: "https://fwb-api.solomon-ai.app", // Optional: defaults to production
});

// Create an API key
const created = await solomonAI.keys.create({
  apiId: "your-api-id",
  prefix: "myapp",
  byteLength: 16,
  ownerId: "user-123",
  meta: {
    userId: "user-123",
    plan: "pro",
  },
});

// Verify an API key
const verified = await solomonAI.keys.verify({
  apiId: "your-api-id",
  key: "myapp_1234567890abcdef",
});

console.log(verified.result?.valid); // true/false
```

## Builder Pattern (Fluent Interface)

The SDK includes a powerful builder pattern for enhanced type safety and developer experience:

### Key Creation with Builder

```typescript
// Enhanced key creation with fluent interface
const result = await solomonAI.keys
  .builder()
  .forApi("api_123456")
  .withName("Production API Key")
  .withPermissions(["read:users", "write:posts"])
  .withExpiration(Date.now() + 86400000) // 24 hours
  .withMetadata({
    environment: "production",
    team: "backend",
  })
  .withRateLimit({
    type: "fast",
    limit: 1000,
    refillRate: 100,
    refillInterval: 60000,
  })
  .create();
```

### Type-Safe Key Verification

```typescript
// Define your app's permission types
type AppPermissions = "read:users" | "write:posts" | "admin:system";

// Type-safe permission verification
const result = await solomonAI.keys
  .verifyWith<AppPermissions>("sk_123")
  .requireAllPermissions(["read:users", "write:posts"])
  .execute();

// Complex permission logic
const complexResult = await solomonAI.keys
  .verifyWith("sk_123")
  .withPermissionQuery({
    or: [{ and: ["admin:system"] }, { and: ["read:users", "write:users"] }],
  })
  .execute();
```

### API Management with Builder

```typescript
// Create API with builder pattern
const api = await solomonAI.apis
  .builder()
  .withName("Payment Processing API")
  .inWorkspace("ws_123456")
  .create();
```

### Permission and Role Management

```typescript
// Create permissions
const permission = await solomonAI.permissions
  .permissionBuilder()
  .withName("manage:webhooks")
  .withDescription("Permission to create and manage webhooks")
  .create();

// Create roles with permissions
const role = await solomonAI.permissions
  .roleBuilder()
  .withName("content-manager")
  .withDescription("Can manage content and posts")
  .withPermissions(["read:posts", "write:posts"])
  .addPermission("delete:posts")
  .create();
```

### Validation and Error Handling

```typescript
// Built-in validation
const builder = solomonAI.keys
  .builder()
  .withName("Test Key")
  .withExpiration(Date.now() - 1000); // Invalid: past date

const validation = builder.validate();
if (!validation.valid) {
  console.log("Validation errors:", validation.errors);
  // Output: ['API ID is required', 'Expiration date must be in the future']

  // Fix errors programmatically
  builder.forApi("api_123").withExpiration(Date.now() + 86400000);
}

// Create only if valid
if (builder.validate().valid) {
  const result = await builder.create();
}
```

### Available Builders

| Builder                  | Purpose             | Key Methods                                                                  |
| ------------------------ | ------------------- | ---------------------------------------------------------------------------- |
| `KeyBuilder`             | API key creation    | `forApi()`, `withName()`, `withPermissions()`, `withExpiration()`            |
| `KeyVerificationBuilder` | Key verification    | `requireAllPermissions()`, `requireAnyPermission()`, `withPermissionQuery()` |
| `ApiBuilder`             | API creation        | `withName()`, `inWorkspace()`                                                |
| `PermissionBuilder`      | Permission creation | `withName()`, `withDescription()`                                            |
| `RoleBuilder`            | Role creation       | `withName()`, `withPermissions()`, `addPermission()`                         |

## Financial Services

### Banking Provider Authentication

#### Plaid Integration

```typescript
// Create Plaid connection
const plaidConnection = await solomonAI.financial.createPlaidConnection({
  apiId: "your-api-id",
  userId: "user-123",
  clientName: "Your App Name",
  countryCode: "US",
  products: ["transactions", "accounts"],
});

if (plaidConnection.result) {
  const { linkToken, exchangePublicToken } = plaidConnection.result;

  // Use linkToken in Plaid Link frontend
  // After user completes flow, exchange public token
  const tokens = await exchangePublicToken("public-token-from-frontend");
}
```

#### GoCardless Integration

```typescript
// Create GoCardless connection
const gcConnection = await solomonAI.financial.createGocardlessConnection({
  apiId: "your-api-id",
  userId: "user-123",
  institutionId: "SANDBOXFINANCE_SFIN0000",
  redirectUrl: "https://yourapp.com/callback",
});

if (gcConnection.result) {
  const { linkUrl, agreementId, exchangeTokens } = gcConnection.result;

  // Redirect user to linkUrl
  // After user completes flow, exchange tokens
  const tokens = await exchangeTokens("auth-code-from-callback");
}
```

### Financial Data Access

#### Accounts Management

```typescript
// List financial accounts
const accounts = await solomonAI.financial.accounts.list({
  apiId: "your-api-id",
  connectionId: "conn-123", // Optional: filter by connection
});

// Get account balance
const balance = await solomonAI.financial.accounts.getBalance({
  apiId: "your-api-id",
  accountId: "acc-123",
});

// Get account details
const account = await solomonAI.financial.accounts.get({
  id: "acc-123",
  apiId: "your-api-id",
});
```

#### Transactions

```typescript
// List transactions
const transactions = await solomonAI.financial.transactions.list({
  apiId: "your-api-id",
  accountId: "acc-123",
  startDate: "2024-01-01",
  endDate: "2024-01-31",
});

// Get recurring transactions
const recurring = await solomonAI.financial.transactions.getRecurring({
  apiId: "your-api-id",
  accountId: "acc-123",
});
```

#### Statements

```typescript
// List statements
const statements = await solomonAI.financial.statements.list({
  apiId: "your-api-id",
  accountId: "acc-123",
});

// Get statement PDF
const pdf = await solomonAI.financial.statements.getPdf({
  apiId: "your-api-id",
  statementId: "stmt-123",
  accountId: "acc-123",
});
```

## AI-Powered Financial Intelligence

### Transaction Categorization

```typescript
// Categorize single transaction
const category = await solomonAI.financial.intelligence.categorize.single({
  apiId: "your-api-id",
  transaction: {
    description: "STARBUCKS COFFEE #1234",
    amount: -4.5,
    date: "2024-01-15",
  },
});

// Bulk categorization
const categories = await solomonAI.financial.intelligence.categorize.bulk({
  apiId: "your-api-id",
  transactions: [
    {
      description: "UBER RIDE",
      amount: -15.25,
      date: "2024-01-15",
    },
    {
      description: "OFFICE SUPPLIES INC",
      amount: -89.99,
      date: "2024-01-16",
    },
  ],
});
```

### Business Purpose Analysis

```typescript
// Analyze business purpose
const purpose = await solomonAI.financial.intelligence.businessPurpose.single({
  apiId: "your-api-id",
  transaction: {
    description: "ZOOM MONTHLY SUBSCRIPTION",
    amount: -14.99,
    date: "2024-01-15",
  },
});

// Result: { businessPurpose: "Software/SaaS", confidence: 0.95, deductible: true }
```

### Tax Deduction Optimization

```typescript
// Optimize tax deductions
const deductions = await solomonAI.financial.intelligence.taxDeductions.single({
  apiId: "your-api-id",
  transaction: {
    description: "HOME OFFICE EQUIPMENT",
    amount: -299.99,
    date: "2024-01-15",
  },
  countryCode: "US",
  taxYear: 2024,
  businessType: "LLC",
});

// Result: { deductible: true, percentage: 100, category: "Business Equipment" }
```

### Receipt Requirements

```typescript
// Check receipt requirements
const receipt =
  await solomonAI.financial.intelligence.receiptRequirements.single({
    apiId: "your-api-id",
    transaction: {
      description: "CLIENT DINNER",
      amount: -125.5,
      date: "2024-01-15",
    },
    countryCode: "US",
  });

// Result: { receiptRequired: true, threshold: 75, reason: "Meal expense over $75" }
```

### Per Diem Analysis

```typescript
// Analyze per diem eligibility
const perDiem = await solomonAI.financial.intelligence.perDiem.single({
  apiId: "your-api-id",
  transaction: {
    description: "HOTEL STAY",
    amount: -150.0,
    date: "2024-01-15",
  },
  countryCode: "US",
  location: "New York, NY",
  travelDates: {
    startDate: "2024-01-15",
    endDate: "2024-01-16",
  },
});

// Result: { eligible: true, maxAllowable: 200, withinLimit: true }
```

### Worker Classification

```typescript
// Classify worker type
const classification =
  await solomonAI.financial.intelligence.workerClassification.single({
    apiId: "your-api-id",
    transaction: {
      description: "FREELANCE DESIGN WORK",
      amount: -500.0,
      date: "2024-01-15",
    },
  });

// Result: { classification: "1099", confidence: 0.88, requiresForm: true }
```

## Connection Management

```typescript
// Get connection status
const status = await solomonAI.financial.connections.getStatus({
  apiId: "your-api-id",
  connectionId: "conn-123",
});

// Delete connection
const deleted = await solomonAI.financial.connections.delete({
  apiId: "your-api-id",
  connectionId: "conn-123",
});

// Get connection by reference
const connection = await solomonAI.financial.connections.getByReference({
  reference: "ref-123",
  apiId: "your-api-id",
});
```

## API Key Management

### Create Keys

```typescript
const key = await solomonAI.keys.create({
  apiId: "your-api-id",
  prefix: "myapp",
  byteLength: 16,
  ownerId: "user-123",
  meta: {
    userId: "user-123",
    plan: "pro",
  },
  expires: Date.now() + 30 * 24 * 60 * 60 * 1000, // 30 days
  ratelimit: {
    type: "fast",
    limit: 100,
    refillRate: 10,
    refillInterval: 60000,
  },
});
```

### Verify Keys

```typescript
const result = await solomonAI.keys.verify({
  apiId: "your-api-id",
  key: "myapp_1234567890abcdef",
});

if (result.result?.valid) {
  console.log("Key is valid");
  console.log("Owner:", result.result.ownerId);
  console.log("Metadata:", result.result.meta);
} else {
  console.log("Key is invalid:", result.result?.code);
}
```

### Update Keys

```typescript
const updated = await solomonAI.keys.update({
  keyId: "key-123",
  name: "Updated Key Name",
  ownerId: "new-owner-123",
  meta: {
    plan: "enterprise",
  },
  expires: Date.now() + 60 * 24 * 60 * 60 * 1000, // 60 days
});
```

## Rate Limiting

### Set Rate Limit Override

```typescript
const override = await solomonAI.ratelimits.setOverride({
  namespaceName: "api-123",
  identifier: "user-456",
  limit: 1000,
  duration: 60000, // 1 minute
  async: false,
});
```

### Check Rate Limit

```typescript
const limit = await solomonAI.ratelimits.limit({
  namespaceName: "api-123",
  identifier: "user-456",
  limit: 100,
  duration: 60000,
});

if (limit.result?.success) {
  console.log("Request allowed");
  console.log("Remaining:", limit.result.remaining);
} else {
  console.log("Rate limit exceeded");
}
```

## Permissions & RBAC

### Create Roles

```typescript
const role = await solomonAI.permissions.createRole({
  name: "admin",
  description: "Administrator role with full access",
});
```

### Create Permissions

```typescript
const permission = await solomonAI.permissions.createPermission({
  name: "financial.read",
  description: "Read access to financial data",
});
```

### Assign Permissions to Keys

```typescript
const assigned = await solomonAI.keys.setPermissions({
  keyId: "key-123",
  permissions: [
    {
      name: "financial.read",
    },
    {
      name: "financial.write",
    },
  ],
});
```

## Analytics

### Get Verification Analytics

```typescript
const analytics = await solomonAI.analytics.getVerifications({
  apiId: "your-api-id",
  start: Date.now() - 30 * 24 * 60 * 60 * 1000, // 30 days ago
  end: Date.now(),
  granularity: "1d",
});
```

### Get Key Verifications

```typescript
const verifications = await solomonAI.keys.getVerifications({
  keyId: "key-123",
  start: Date.now() - 7 * 24 * 60 * 60 * 1000, // 7 days ago
  end: Date.now(),
  granularity: "1h",
});
```

## Error Handling

All SDK methods return a `Result` type that contains either a `result` or an `error`:

```typescript
const result = await solomonAI.keys.create({
  apiId: "your-api-id",
  prefix: "myapp",
});

if (result.error) {
  console.error("Error:", result.error.message);
  console.error("Code:", result.error.code);
  console.error("Docs:", result.error.docs);
  console.error("Request ID:", result.error.requestId);
} else {
  console.log("Success:", result.result);
}
```

## Configuration

### Custom Base URL

```typescript
const solomonAI = new SolomonAI({
  rootKey: "your-root-key",
  baseUrl: "https://your-custom-domain.com",
});
```

### Retry Configuration

```typescript
const solomonAI = new SolomonAI({
  rootKey: "your-root-key",
  retry: {
    attempts: 3,
    backoff: (retryCount) => Math.pow(2, retryCount) * 1000,
  },
});
```

### Disable Telemetry

```typescript
const solomonAI = new SolomonAI({
  rootKey: "your-root-key",
  disableTelemetry: true,
});
```

## Observability & Monitoring

The SDK provides comprehensive observability features including OpenTelemetry metrics export and advanced logging capabilities.

### OpenTelemetry Metrics Export

Configure the SDK to export metrics to any OpenTelemetry-compatible monitoring system:

#### Basic OpenTelemetry Setup

```typescript
import {
  FinancialWorkspaceBackendClient,
  createMetricsPlugin,
} from "@solomonai/financial-engine-sdk";
import { metrics } from "@opentelemetry/api";

const meter = metrics.getMeter("my-financial-app", "1.0.0");

const client = new FinancialWorkspaceBackendClient({
  rootKey: "your-root-key",
  plugins: [
    {
      plugin: createMetricsPlugin(),
      options: {
        // Enable OpenTelemetry integration
        enableOTel: true,
        otelMeter: meter,
        serviceName: "financial-app",
        serviceVersion: "1.0.0",

        // Configure export endpoint
        otelExportEndpoint: "https://otlp.example.com/v1/metrics",
        otelExportHeaders: {
          Authorization: "Bearer your-api-key-here",
        },
        otelExportTimeout: 15000,
        otelExportProtocol: "http/json", // or 'http/protobuf'

        // Enable metrics collection
        enableTiming: true,
        enableErrorTracking: true,
      },
    },
  ],
});
```

#### Production OpenTelemetry Configuration

```typescript
import {
  FinancialWorkspaceBackendClient,
  createMetricsPlugin,
  getOTelMeter,
} from "@solomonai/financial-engine-sdk";

// Safely get OpenTelemetry meter
const meter = getOTelMeter("financial-workspace", "2.1.0");

const client = new FinancialWorkspaceBackendClient({
  rootKey: process.env.FWB_ROOT_KEY!,
  plugins: [
    {
      plugin: createMetricsPlugin(),
      options: {
        enableOTel: !!meter,
        otelMeter: meter,
        serviceName: "financial-workspace-backend",
        serviceVersion: "2.1.0",

        // Production OTLP configuration
        otelExportEndpoint: "https://otlp-gateway.company.com/v1/metrics",
        otelExportHeaders: {
          Authorization: `Bearer ${process.env.OTLP_API_KEY}`,
          "X-Tenant-ID": process.env.TENANT_ID || "default",
          "X-Environment": process.env.NODE_ENV || "production",
        },
        otelExportTimeout: 10000,
        otelExportProtocol: "http/protobuf", // More efficient for production

        // Metrics configuration
        enableTiming: true,
        enableErrorTracking: true,
        defaultTags: {
          service: "fwb-client",
          environment: process.env.NODE_ENV || "production",
          version: "2.1.0",
        },
      },
    },
  ],
});
```

#### Standard Metrics Collected

When OpenTelemetry is enabled, the SDK automatically collects these metrics:

| Metric Name            | Type      | Description               | Unit    |
| ---------------------- | --------- | ------------------------- | ------- |
| `fwb_request_duration` | Histogram | Request duration          | seconds |
| `fwb_request_count`    | Counter   | Total number of requests  | count   |
| `fwb_error_count`      | Counter   | Total number of errors    | count   |
| `fwb_response_size`    | Histogram | Response size             | bytes   |
| `fwb_request_size`     | Histogram | Request size              | bytes   |
| `fwb_active_requests`  | Gauge     | Number of active requests | count   |

### Advanced Logging with Log Levels

Configure detailed logging with different levels, colors, and formats:

#### Development Logging

```typescript
import {
  FinancialWorkspaceBackendClient,
  createLoggerPlugin,
  LogLevel,
} from "@solomonai/financial-engine-sdk";

const client = new FinancialWorkspaceBackendClient({
  rootKey: "your-root-key",
  plugins: [
    {
      plugin: createLoggerPlugin(),
      options: {
        // Development logging settings
        logLevel: LogLevel.DEBUG,
        format: "text",
        useColors: true,
        includeTimestamp: true,
        includePluginName: true,

        // Log everything in development
        logRequests: true,
        logResponses: true,
        logErrors: true,
        logResponseBodies: true, // Be careful with sensitive data
        includeStackTrace: true,
      },
    },
  ],
});
```

#### Production Logging

```typescript
import {
  FinancialWorkspaceBackendClient,
  createLoggerPlugin,
  LogLevel,
} from "@solomonai/financial-engine-sdk";

const client = new FinancialWorkspaceBackendClient({
  rootKey: process.env.FWB_ROOT_KEY!,
  plugins: [
    {
      plugin: createLoggerPlugin(),
      options: {
        // Production logging settings - only warnings and errors
        logLevel: LogLevel.WARN,
        format: "json", // Structured logging for log aggregation
        useColors: false, // No colors in production logs
        includeTimestamp: true,
        includePluginName: false, // Reduce log size

        // Minimal logging in production
        logRequests: false,
        logResponses: false,
        logErrors: true,
        logResponseBodies: false, // Never log response bodies in production
        includeStackTrace: true, // Keep stack traces for debugging errors
      },
    },
  ],
});
```

#### Log Levels

The SDK supports the following log levels (in order of verbosity):

| Level   | Value | Description            | Color      |
| ------- | ----- | ---------------------- | ---------- |
| `TRACE` | 0     | Most verbose debugging | Gray       |
| `DEBUG` | 1     | Debug information      | Cyan       |
| `INFO`  | 2     | General information    | Green      |
| `WARN`  | 3     | Warning messages       | Yellow     |
| `ERROR` | 4     | Error messages         | Red        |
| `FATAL` | 5     | Critical errors        | Bright Red |
| `OFF`   | 6     | No logging             | -          |

#### Environment-Specific Configuration

```typescript
import {
  FinancialWorkspaceBackendClient,
  createMetricsPlugin,
  createLoggerPlugin,
  LogLevel,
  getOTelMeter,
} from "@solomonai/financial-engine-sdk";

const isDevelopment = process.env.NODE_ENV === "development";
const meter = getOTelMeter("financial-app", "1.0.0");

const client = new FinancialWorkspaceBackendClient({
  rootKey: process.env.FWB_ROOT_KEY!,
  baseUrl: isDevelopment
    ? "http://localhost:3000"
    : "https://api.solomon-ai.app",
  plugins: [
    // Metrics plugin configuration
    {
      plugin: createMetricsPlugin(),
      options: {
        enableOTel: !!meter && !isDevelopment, // Only use OTel in production
        otelMeter: meter,
        serviceName: "financial-app",
        serviceVersion: "1.0.0",

        // Only configure export in production
        ...(isDevelopment
          ? {}
          : {
              otelExportEndpoint: process.env.OTLP_ENDPOINT,
              otelExportHeaders: {
                Authorization: `Bearer ${process.env.OTLP_API_KEY}`,
              },
              otelExportTimeout: 10000,
              otelExportProtocol: "http/protobuf",
            }),

        enableTiming: true,
        enableErrorTracking: true,
        defaultTags: {
          environment: process.env.NODE_ENV || "development",
        },
      },
    },
    // Logging plugin configuration
    {
      plugin: createLoggerPlugin(),
      options: {
        logLevel: isDevelopment ? LogLevel.DEBUG : LogLevel.WARN,
        format: isDevelopment ? "text" : "json",
        useColors: isDevelopment,
        includeTimestamp: true,
        includePluginName: isDevelopment,

        logRequests: isDevelopment,
        logResponses: isDevelopment,
        logErrors: true,
        logResponseBodies: isDevelopment,
        includeStackTrace: true,
      },
    },
  ],
});
```

### Monitoring Integration Examples

#### Grafana + Prometheus

```typescript
const client = new FinancialWorkspaceBackendClient({
  rootKey: process.env.FWB_ROOT_KEY!,
  plugins: [
    {
      plugin: createMetricsPlugin(),
      options: {
        enableOTel: true,
        otelMeter: metrics.getMeter("fwb-client", "1.0.0"),
        otelExportEndpoint:
          "http://prometheus-gateway:9090/api/v1/otlp/v1/metrics",
        otelExportProtocol: "http/protobuf",
        enableTiming: true,
        enableErrorTracking: true,
      },
    },
  ],
});
```

#### Jaeger Tracing

```typescript
const client = new FinancialWorkspaceBackendClient({
  rootKey: process.env.FWB_ROOT_KEY!,
  plugins: [
    {
      plugin: createMetricsPlugin(),
      options: {
        enableOTel: true,
        otelMeter: metrics.getMeter("fwb-client", "1.0.0"),
        otelExportEndpoint: "http://jaeger:14268/api/traces",
        otelExportHeaders: {
          "Content-Type": "application/json",
        },
        otelExportProtocol: "http/json",
        enableTiming: true,
        enableErrorTracking: true,
      },
    },
  ],
});
```

#### DataDog Integration

```typescript
const client = new FinancialWorkspaceBackendClient({
  rootKey: process.env.FWB_ROOT_KEY!,
  plugins: [
    {
      plugin: createMetricsPlugin(),
      options: {
        enableOTel: true,
        otelMeter: metrics.getMeter("fwb-client", "1.0.0"),
        otelExportEndpoint: "https://otlp.datadoghq.com/v1/metrics",
        otelExportHeaders: {
          "DD-API-KEY": process.env.DATADOG_API_KEY!,
        },
        otelExportProtocol: "http/protobuf",
        enableTiming: true,
        enableErrorTracking: true,
        defaultTags: {
          service: "financial-workspace",
          env: process.env.NODE_ENV || "production",
        },
      },
    },
  ],
});
```

## TypeScript Support

The SDK is fully typed with TypeScript. All request and response types are automatically generated from the OpenAPI specification.

```typescript
import type {
  CreateKeyRequest,
  CreateKeyResponse,
  VerifyKeyRequest,
  VerifyKeyResponse,
} from "@solomonai/financial-engine-sdk";

// Types are available for all endpoints
const request: CreateKeyRequest = {
  apiId: "your-api-id",
  prefix: "myapp",
};
```

## Examples

Comprehensive examples are available in the `examples/` directory:

- **`builder-pattern-examples.ts`** - Demonstrates the fluent interface builder pattern for creating keys, APIs, permissions, and roles
- **`otel-logging-configuration.ts`** - Shows OpenTelemetry export configuration and advanced logging setups for different environments

### Running Examples

```bash
# Install dependencies
npm install

# Run builder pattern examples
npx tsx examples/builder-pattern-examples.ts

# View OpenTelemetry and logging configuration examples
npx tsx examples/otel-logging-configuration.ts
```

## Contributing

We welcome contributions! Please see our [Contributing Guide](https://github.com/SolomonAIEngineering/financial-workspace-backend-platform/blob/main/CONTRIBUTING.md) for details.

## License

MIT License - see [LICENSE](https://github.com/SolomonAIEngineering/financial-workspace-backend-platform/blob/main/LICENSE) for details.

## Support

- 📖 [Documentation](https://docs.solomon-ai.app)
- 💬 [Discord Community](https://discord.gg/solomon-ai)
- 🐛 [GitHub Issues](https://github.com/SolomonAIEngineering/financial-workspace-backend-platform/issues)
- ✉️ [Email Support](mailto:support@solomon-ai.app)
