# Breaking Changes

This document tracks breaking changes introduced during the Oshun platform
consolidation. Each change includes migration guidance and deprecation
timelines.

## Table of Contents

1. [Version Compatibility](#version-compatibility)
2. [API Breaking Changes](#api-breaking-changes)
3. [SDK Breaking Changes](#sdk-breaking-changes)
4. [Event Schema Changes](#event-schema-changes)
5. [Database Schema Changes](#database-schema-changes)
6. [Authentication Changes](#authentication-changes)
7. [Configuration Changes](#configuration-changes)
8. [Deprecation Schedule](#deprecation-schedule)

---

## Version Compatibility

| Oshun Version | Lilith Compatibility     | Yemaya Compatibility     | Migration Required |
| ------------- | ------------------------ | ------------------------ | ------------------ |
| 1.0.0         | Breaking                 | Breaking                 | Yes                |
| 0.9.x         | Partial (shim available) | Partial (shim available) | Recommended        |
| < 0.9.0       | Not compatible           | Not compatible           | Required           |

---

## API Breaking Changes

### 1. Authentication Header Changes

**Breaking in**: Oshun 1.0.0

**Before**:

```http
# Lilith
Authorization: Bearer {lilith_token}
X-Lilith-API-Key: {api_key}

# Yemaya
Authorization: Bearer {yemaya_token}
X-API-Key: {api_key}
```

**After**:

```http
# All domains use unified format
Authorization: Bearer {oshun_jwt}
# OR
Authorization: ApiKey {oshun_api_key}
# OR
X-API-Key: {oshun_api_key}
```

**Migration**:

```typescript
// Old
const headers = {
  'X-Lilith-API-Key': process.env.LILITH_API_KEY,
};

// New
const headers = {
  Authorization: `ApiKey ${process.env.OSHUN_API_KEY}`,
};
```

---

### 2. API Base URL Structure

**Breaking in**: Oshun 1.0.0

**Before**:

```
# Lilith
https://api.lilith.io/v1/meditations
https://api.lilith.io/v1/users

# Yemaya
https://api.yemaya.studio/projects
https://api.yemaya.studio/assets
```

**After**:

```
# Unified gateway with domain prefixes
https://api.oshun.io/lilith/v1/meditations
https://api.oshun.io/lilith/v1/users

https://api.oshun.io/yemaya/v1/projects
https://api.oshun.io/yemaya/v1/assets

# New domains
https://api.oshun.io/isis/v1/generation
https://api.oshun.io/sophia/v1/search
https://api.oshun.io/hathor/v1/worlds
https://api.oshun.io/bellona/v1/exports
```

**Migration**:

```typescript
// Old
const LILITH_API = 'https://api.lilith.io/v1';
const response = await fetch(`${LILITH_API}/meditations`);

// New
const OSHUN_API = 'https://api.oshun.io';
const response = await fetch(`${OSHUN_API}/lilith/v1/meditations`);
```

---

### 3. Response Envelope Format

**Breaking in**: Oshun 1.0.0

**Before (Lilith)**:

```json
{
  "success": true,
  "data": { ... },
  "error": null,
  "meta": { "page": 1, "total": 100 }
}
```

**Before (Yemaya)**:

```json
{
  "result": { ... },
  "status": "ok",
  "pagination": { ... }
}
```

**After (All domains)**:

```json
// Success response
{
  "data": { ... },
  "meta": {
    "pagination": { "page": 1, "pageSize": 20, "total": 100 },
    "requestId": "req_abc123"
  }
}

// Error response
{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "Meditation not found",
    "details": { "id": "med-123" },
    "requestId": "req_abc123"
  }
}
```

**Migration**:

```typescript
// Old (Lilith)
const response = await fetch(url);
const { success, data, error } = await response.json();
if (!success) throw new Error(error);

// Old (Yemaya)
const response = await fetch(url);
const { result, status } = await response.json();
if (status !== 'ok') throw new Error('Request failed');

// New (All)
const response = await fetch(url);
const json = await response.json();
if (json.error) {
  throw new ApiError(json.error.code, json.error.message);
}
return json.data;
```

---

### 4. Pagination Parameters

**Breaking in**: Oshun 1.0.0

**Before**:

```
# Lilith
?page=1&limit=20

# Yemaya
?offset=0&count=20
```

**After**:

```
# Unified
?page=1&pageSize=20
# OR cursor-based
?cursor=abc123&pageSize=20
```

**Response**:

```json
{
  "data": [...],
  "meta": {
    "pagination": {
      "page": 1,
      "pageSize": 20,
      "total": 100,
      "totalPages": 5,
      "hasNext": true,
      "hasPrev": false,
      "nextCursor": "eyJpZCI6MTAwfQ=="
    }
  }
}
```

---

### 5. Error Code Standardization

**Breaking in**: Oshun 1.0.0

**Before (Mixed formats)**:

```json
// Lilith
{ "error": "MEDITATION_NOT_FOUND" }
{ "error": { "code": 404, "message": "Not found" } }

// Yemaya
{ "error": "project_not_found" }
{ "status": "error", "message": "Project not found" }
```

**After (Standardized)**:

```json
{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "The requested resource was not found",
    "details": {
      "resourceType": "meditation",
      "resourceId": "med-123"
    }
  }
}
```

**Standard Error Codes**:

| Code                  | HTTP Status | Description                     |
| --------------------- | ----------- | ------------------------------- |
| `VALIDATION_ERROR`    | 400         | Request validation failed       |
| `INVALID_REQUEST`     | 400         | Malformed request               |
| `UNAUTHORIZED`        | 401         | Authentication required         |
| `INVALID_TOKEN`       | 401         | Token invalid or expired        |
| `FORBIDDEN`           | 403         | Permission denied               |
| `RESOURCE_NOT_FOUND`  | 404         | Resource doesn't exist          |
| `CONFLICT`            | 409         | Resource conflict               |
| `RATE_LIMITED`        | 429         | Rate limit exceeded             |
| `INTERNAL_ERROR`      | 500         | Internal server error           |
| `SERVICE_UNAVAILABLE` | 503         | Service temporarily unavailable |

---

## SDK Breaking Changes

### 1. Client Instantiation

**Breaking in**: SDK v2.0.0

**Before**:

```typescript
// Lilith SDK
import { LilithClient } from '@lilith/sdk';
const client = new LilithClient({
  apiKey: 'your-api-key',
  environment: 'production',
});

// Yemaya SDK
import Yemaya from 'yemaya-sdk';
const client = Yemaya.init({
  key: 'your-api-key',
});
```

**After**:

```typescript
// All SDKs use factory functions
import { createLilithClient } from '@lilith/sdk';
import { createYemayaClient } from '@yemaya/sdk';
import { createIsisClient } from '@isis/client';

const lilith = createLilithClient({
  baseUrl: 'https://api.oshun.io/lilith',
  auth: {
    type: 'api-key',
    credentials: 'your-api-key',
  },
});

const yemaya = createYemayaClient({
  baseUrl: 'https://api.oshun.io/yemaya',
  auth: {
    type: 'api-key',
    credentials: 'your-api-key',
  },
});
```

---

### 2. Method Naming Conventions

**Breaking in**: SDK v2.0.0

**Before**:

```typescript
// Lilith - mixed conventions
await client.getMeditation(id);
await client.meditation.fetch(id);
await client.fetchMeditation(id);

// Yemaya - snake_case in some places
await client.get_project(id);
await client.projects.getById(id);
```

**After**:

```typescript
// Consistent resource.action() pattern
await lilith.meditations.get(id);
await lilith.meditations.list({ page: 1 });
await lilith.meditations.create(data);
await lilith.meditations.update(id, data);
await lilith.meditations.delete(id);

await yemaya.projects.get(id);
await yemaya.projects.list();
await yemaya.projects.create(data);
```

---

### 3. Promise vs Callback API

**Breaking in**: SDK v2.0.0

**Before**:

```typescript
// Lilith supported callbacks
client.getMeditation(id, (err, meditation) => {
  if (err) console.error(err);
  else console.log(meditation);
});
```

**After**:

```typescript
// Promises only (use async/await)
const meditation = await lilith.meditations.get(id);

// For error handling
try {
  const meditation = await lilith.meditations.get(id);
} catch (error) {
  if (error instanceof NotFoundError) {
    // Handle not found
  }
}
```

---

### 4. Type Definitions

**Breaking in**: SDK v2.0.0

**Before**:

```typescript
// Loose typing
interface Meditation {
  id: string;
  title: any;
  data: object;
}
```

**After**:

```typescript
// Strict Zod-validated types
import { z } from 'zod';

export const MeditationSchema = z.object({
  id: z.string().uuid(),
  title: z.string().min(1).max(200),
  description: z.string().optional(),
  duration: z.number().positive(),
  audioUrl: z.string().url().optional(),
  createdAt: z.string().datetime(),
  updatedAt: z.string().datetime(),
});

export type Meditation = z.infer<typeof MeditationSchema>;
```

---

## Event Schema Changes

### 1. Event Envelope Format

**Breaking in**: Oshun 1.0.0

**Before**:

```json
// Lilith events
{
  "event": "meditation.completed",
  "userId": "user-123",
  "timestamp": 1704067200000
}

// Yemaya events
{
  "type": "project_created",
  "data": { "projectId": "proj-123" },
  "time": "2024-01-15T10:30:00Z"
}
```

**After**:

```json
{
  "id": "evt_550e8400-e29b-41d4-a716-446655440000",
  "type": "lilith.meditation.completed",
  "source": "lilith",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "correlationId": "req_abc123",
  "payload": {
    "meditationId": "med-123",
    "userId": "user-456",
    "duration": 600
  },
  "metadata": {
    "environment": "production",
    "version": "1.0.0"
  }
}
```

---

### 2. Event Type Naming

**Breaking in**: Oshun 1.0.0

| Old Event (Lilith)     | New Event                     |
| ---------------------- | ----------------------------- |
| `meditation.completed` | `lilith.meditation.completed` |
| `meditation.started`   | `lilith.meditation.started`   |
| `user.achievement`     | `lilith.achievement.earned`   |
| `session.created`      | `lilith.session.created`      |

| Old Event (Yemaya) | New Event                  |
| ------------------ | -------------------------- |
| `project_created`  | `yemaya.project.created`   |
| `asset_uploaded`   | `yemaya.asset.uploaded`    |
| `export_complete`  | `bellona.export.completed` |
| `generation_done`  | `isis.asset.generated`     |

---

### 3. Event Subscription API

**Breaking in**: Oshun 1.0.0

**Before**:

```typescript
// Lilith
redis.subscribe('meditation:completed', handler);

// Yemaya
bullMQ.on('completed', handler);
```

**After**:

```typescript
import { EventBus } from '@oshun/event-bus';

const eventBus = new EventBus({
  redis: { url: process.env.REDIS_URL },
  consumerGroup: 'my-service',
});

// Pattern subscription
eventBus.subscribe('lilith.meditation.*', handler);

// Specific event
eventBus.subscribe('lilith.meditation.completed', handler);

await eventBus.start();
```

---

## Database Schema Changes

### 1. Multi-Schema Architecture

**Breaking in**: Oshun 1.0.0

**Before**: Separate databases per domain

```
lilith-db    → all tables
yemaya-db    → all tables
```

**After**: Single cluster, multiple schemas

```
oshun-db
  ├── oshun_auth    → users, sessions, permissions
  ├── lilith        → meditations, progress, achievements
  ├── yemaya        → projects, assets, teams
  ├── isis          → generation_jobs, assets
  ├── sophia        → documents, embeddings
  ├── hathor        → worlds, characters, quests
  └── bellona       → builds, exports, artifacts
```

**Migration**:

```prisma
// Before
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

// After
datasource db {
  provider = "postgresql"
  url      = env("LILITH_DATABASE_URL")
  schemas  = ["lilith"]
}

model Meditation {
  id String @id
  // ...
  @@schema("lilith")
}
```

---

### 2. User ID References

**Breaking in**: Oshun 1.0.0

**Before**:

```prisma
model Meditation {
  userId String  // Direct user ID
  user   User    @relation(...)
}
```

**After**:

```prisma
model Meditation {
  authUserId    String  // Reference to oshun_auth.users.id
  lilithProfile LilithProfile @relation(fields: [authUserId], ...)
}
```

**Migration Script**:

```sql
-- Add new column
ALTER TABLE lilith.meditation ADD COLUMN auth_user_id UUID;

-- Migrate data
UPDATE lilith.meditation m
SET auth_user_id = (
  SELECT auth_user_id FROM lilith.profile p WHERE p.id = m.user_id
);

-- Drop old column (after verification)
ALTER TABLE lilith.meditation DROP COLUMN user_id;
ALTER TABLE lilith.meditation RENAME COLUMN auth_user_id TO user_id;
```

---

### 3. Timestamp Format

**Breaking in**: Oshun 1.0.0

**Before**:

```prisma
model Entity {
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  deletedAt DateTime?  // Optional soft delete
}
```

**After**:

```prisma
model Entity {
  createdAt DateTime @default(now()) @db.Timestamptz
  updatedAt DateTime @updatedAt @db.Timestamptz
  deletedAt DateTime? @db.Timestamptz
}
```

All timestamps now use `TIMESTAMPTZ` (timestamp with timezone) stored in UTC.

---

## Authentication Changes

### 1. JWT Claims Structure

**Breaking in**: Oshun 1.0.0

**Before (Lilith)**:

```json
{
  "sub": "user-123",
  "email": "user@example.com",
  "tier": "premium",
  "exp": 1704067200
}
```

**Before (Yemaya)**:

```json
{
  "userId": "user-123",
  "organizationId": "org-456",
  "role": "admin",
  "exp": 1704067200
}
```

**After (Unified)**:

```json
{
  "sub": "user-123",
  "email": "user@example.com",
  "iss": "https://auth.oshun.io",
  "aud": ["lilith", "yemaya", "isis"],
  "iat": 1704066300,
  "exp": 1704067200,
  "jti": "token-789",
  "org": "org-456",
  "permissions": ["read:meditations", "write:projects"],
  "roles": ["user", "creator"]
}
```

---

### 2. API Key Format

**Breaking in**: Oshun 1.0.0

**Before**:

```
# Lilith
lil_live_abc123...
lil_test_xyz789...

# Yemaya
ym_abc123...
```

**After**:

```
# Live keys
sk_live_oshun_abc123...

# Test keys
sk_test_oshun_xyz789...

# Restricted keys (limited scope)
rk_oshun_def456...
```

---

### 3. OAuth Scopes

**Breaking in**: Oshun 1.0.0

**Before**:

```
# Lilith scopes
meditation:read
meditation:write
user:profile

# Yemaya scopes
projects
assets
export
```

**After**:

```
# Domain-prefixed scopes
lilith:meditation:read
lilith:meditation:write
lilith:user:read

yemaya:projects:read
yemaya:projects:write
yemaya:assets:read
yemaya:assets:write

isis:generation:read
isis:generation:write

# Wildcard scopes
lilith:*        # All Lilith permissions
yemaya:*:read   # Read all Yemaya resources
*               # Full access (admin)
```

---

## Configuration Changes

### 1. Environment Variables

**Breaking in**: Oshun 1.0.0

| Old Variable               | New Variable          | Notes                    |
| -------------------------- | --------------------- | ------------------------ |
| `LILITH_DATABASE_URL`      | `LILITH_DATABASE_URL` | Unchanged                |
| `YEMAYA_DB_URL`            | `YEMAYA_DATABASE_URL` | Renamed                  |
| `REDIS_HOST`, `REDIS_PORT` | `REDIS_URL`           | Combined                 |
| `S3_BUCKET`, `S3_REGION`   | `STORAGE_URL`         | S3-compatible URL        |
| `OPENAI_API_KEY`           | `ISIS_OPENAI_API_KEY` | Domain-prefixed          |
| `JWT_SECRET`               | `AUTH_JWT_PUBLIC_KEY` | RSA instead of symmetric |

**Full Environment Template**:

```bash
# Core
NODE_ENV=production
LOG_LEVEL=info

# Databases (per domain)
LILITH_DATABASE_URL=postgresql://...?schema=lilith
YEMAYA_DATABASE_URL=postgresql://...?schema=yemaya
ISIS_DATABASE_URL=postgresql://...?schema=isis
# ... etc

# Shared Infrastructure
REDIS_URL=redis://localhost:6379
STORAGE_URL=s3://oshun-assets.s3.us-east-1.amazonaws.com

# Authentication
AUTH_JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----..."
AUTH_ISSUER=https://auth.oshun.io

# AI Providers (managed by Isis)
ISIS_OPENAI_API_KEY=sk-...
ISIS_ANTHROPIC_API_KEY=sk-ant-...
ISIS_REPLICATE_API_TOKEN=r8_...

# Observability
OTEL_EXPORTER_OTLP_ENDPOINT=https://otel.oshun.io
SENTRY_DSN=https://...@sentry.io/...
```

---

### 2. Configuration File Format

**Breaking in**: Oshun 1.0.0

**Before**: Mixed formats

```yaml
# lilith-config.yaml
database:
  host: localhost
  port: 5432

# yemaya.config.json
{
  "storage": {
    "bucket": "yemaya-assets"
  }
}
```

**After**: Unified config structure

```typescript
// config/lilith.config.ts
import { defineConfig } from '@oshun/config';

export default defineConfig({
  domain: 'lilith',
  database: {
    url: process.env.LILITH_DATABASE_URL,
    schema: 'lilith',
  },
  redis: {
    url: process.env.REDIS_URL,
  },
  // Type-safe configuration
});
```

---

## Deprecation Schedule

### Immediate (Oshun 1.0.0)

| Feature                    | Status     | Removal |
| -------------------------- | ---------- | ------- |
| Lilith standalone API      | Deprecated | v2.0.0  |
| Yemaya standalone API      | Deprecated | v2.0.0  |
| Legacy event formats       | Deprecated | v1.5.0  |
| Callback-based SDK methods | Removed    | N/A     |

### Oshun 1.5.0 (Q2 2024)

| Feature                      | Status     | Removal |
| ---------------------------- | ---------- | ------- |
| Legacy event formats         | Removed    | N/A     |
| Old API response format shim | Deprecated | v2.0.0  |
| Symmetric JWT validation     | Deprecated | v2.0.0  |

### Oshun 2.0.0 (Q4 2024)

| Feature                         | Status  | Removal |
| ------------------------------- | ------- | ------- |
| Standalone domain APIs          | Removed | N/A     |
| Old API response format shim    | Removed | N/A     |
| Non-schema database connections | Removed | N/A     |
| Legacy API key formats          | Removed | N/A     |

---

## Compatibility Shims

For gradual migration, compatibility shims are available:

### Response Format Shim

```typescript
import { legacyResponseMiddleware } from '@oshun/compat';

// Converts new format to legacy format for old clients
app.use(
  '/api/v1/*',
  legacyResponseMiddleware({
    format: 'lilith', // or 'yemaya'
  })
);
```

### Event Bridge

```typescript
import { EventBridge } from '@oshun/compat';

// Translates old event names to new format
const bridge = new EventBridge({
  mappings: {
    'meditation:completed': 'lilith.meditation.completed',
    project_created: 'yemaya.project.created',
  },
});

await bridge.start();
```

### API Key Translation

```typescript
import { translateApiKey } from '@oshun/compat';

// Converts old format keys to new format
const newKey = translateApiKey('lil_live_abc123');
// Returns: sk_live_oshun_abc123
```

---

## Getting Help

- **Migration Support**: `#oshun-migration` on Slack
- **Breaking Changes Questions**: Create GitHub Issue with `breaking-change`
  label
- **Compatibility Shims**: See `/libs/compat/` for source code
