Correct schema architecture: YAML is source of truth, not Prisma

Key Corrections:
- Remove manually copied Prisma schema (should be auto-generated from YAML)
- DBAL YAML schemas at /dbal/shared/api/schema/entities/ are source of truth
- Prisma schema is auto-generated from YAML via codegen:prisma
- Update CLAUDE.md and ARCHITECTURE.md to clarify this hierarchy

Schema Layers:
1. /schemas/package-schemas/ - Package system architecture (top-level)
2. /dbal/shared/api/schema/entities/ - Database structure (DBAL source of truth)
3. /prisma/schema.prisma - Generated Prisma schema (derived artifact)

Correct Workflow:
- Edit YAML schemas at /dbal/shared/api/schema/entities/
- Run: npm --prefix dbal/development run codegen:prisma (generates Prisma)
- Run: npm --prefix dbal/development run db:push (applies to DB)

This prevents bot errors of manually editing Prisma schema.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
rmac
2026-01-14 18:41:40 +00:00
parent 8bcc85a470
commit 971d5054f8
3 changed files with 67 additions and 155 deletions

View File

@@ -177,15 +177,27 @@ export async function seedDatabase(dbal: DBALClient): Promise<void>
- Loads package-specific seed data
- Uses entity operations, not raw adapter
### 5. Prisma Schema Ownership
### 5. Schema Ownership - YAML is Source of Truth
```
dbal/development/prisma/schema.prisma
dbal/shared/api/schema/entities/
├── core/
│ ├── user.yaml
│ ├── session.yaml
│ ├── ui_page.yaml
│ ├── workflow.yaml
│ └── package.yaml
├── access/
│ ├── credential.yaml
│ ├── page_config.yaml
│ └── component_node.yaml
└── packages/
└── [package-specific entities]
```
- DBAL owns and versions the database schema
- Moved from `/prisma/schema.prisma` (frontend location)
- Defines all entities (User, PageConfig, Component, etc.)
- Used by DBAL's PrismaClient
- **YAML schemas** are the source of truth for database structure
- Generated Prisma schema (from YAML via `gen_prisma_schema.js`)
- Prisma schema is at `/prisma/schema.prisma` (auto-generated)
- DBAL's PrismaClient uses the generated Prisma schema
---
@@ -251,10 +263,10 @@ export async function POST() {
The `/schemas` folder defines the structure; DBAL implements it:
| Schema | DBAL Implementation |
|--------|-------------------|
| Top-Level Schema | DBAL Implementation |
|------------------|-------------------|
| `metadata_schema.json` | Package loading & exports in DBALClient.packages |
| `entities_schema.json` | Entity definitions reflected in Prisma schema, DBAL entity operations |
| `entities_schema.json` | Entity definitions reflected in DBAL YAML schemas |
| `types_schema.json` | Type system in TypeScript types, used by entity operations |
| `validation_schema.json` | Validation applied in entity create/update operations |
| `components_schema.json` | Component metadata stored in database, accessible via API |
@@ -266,6 +278,12 @@ The `/schemas` folder defines the structure; DBAL implements it:
| `script_schema.json` | Scripts have access to DBAL operations and stdlib |
| `stdlib_schema.json` | Standard library functions available to scripts |
| DBAL YAML Schemas | Prisma Implementation |
|-------------------|----------------------|
| `/dbal/shared/api/schema/entities/core/*.yaml` | Generated Prisma models (User, Session, etc.) |
| `/dbal/shared/api/schema/entities/access/*.yaml` | Generated Prisma models (Credential, PageConfig, etc.) |
| `/dbal/shared/api/schema/entities/packages/*.yaml` | Package-specific entity definitions |
---
## Refactoring Roadmap

View File

@@ -156,12 +156,14 @@ for (const user of seedData) {
### Mistake 4: Trying to Edit Prisma Schema Directly
```typescript
// ❌ WRONG
// ❌ WRONG - Prisma schema is auto-generated
// Don't edit /prisma/schema.prisma directly
// Don't edit /dbal/development/prisma/schema.prisma
// ✅ CORRECT
// Schema is at /dbal/development/prisma/schema.prisma
// Edit there, then run: npm run db:generate && npm run db:push
// ✅ CORRECT - Edit YAML schemas instead
// 1. Edit: /dbal/shared/api/schema/entities/core/[entity].yaml
// 2. Generate Prisma: npm --prefix dbal/development run codegen:prisma
// 3. Push to DB: npm --prefix dbal/development run db:push
```
### Mistake 5: Forgetting Database Schema Exists
@@ -180,7 +182,8 @@ for (const user of seedData) {
| File | Purpose |
|------|---------|
| `/dbal/development/prisma/schema.prisma` | **Database schema** (DBAL owns this now) |
| `/dbal/shared/api/schema/entities/` | **YAML schemas** (source of truth for database structure) |
| `/prisma/schema.prisma` | Generated Prisma schema (auto-generated from YAML) |
| `/dbal/development/src/core/client/factory.ts` | `getDBALClient()`, `useDBAL()` factories |
| `/dbal/development/src/runtime/prisma-client.ts` | `getPrismaClient()` factory |
| `/dbal/development/src/seeds/index.ts` | `seedDatabase()` orchestration |
@@ -223,10 +226,10 @@ await seedDatabase(db)
```
### Task 4: Modify Database Schema
1. Edit `/dbal/development/prisma/schema.prisma`
2. Run: `npm --prefix dbal/development run db:generate`
3. Run: `npm --prefix dbal/development run db:push`
4. Verify tables exist: Check `/prisma/prisma/dev.db` exists
1. Edit YAML schema: `/dbal/shared/api/schema/entities/core/[entity-name].yaml`
2. Generate Prisma schema: `npm --prefix dbal/development run codegen:prisma`
3. Push to database: `npm --prefix dbal/development run db:push`
4. Verify: Check `/prisma/prisma/dev.db` and `/prisma/schema.prisma` updated
---
@@ -249,17 +252,25 @@ npm run test:e2e
---
## 📚 Source of Truth: /schemas Folder
The `/schemas/package-schemas/` folder defines the **complete MetaBuilder architecture**:
## 📚 Multiple Layers of Schema
### 1. Package System Schemas (`/schemas/package-schemas/`)
Defines the complete MetaBuilder **package architecture**:
- `metadata_schema.json` - Package structure
- `entities_schema.json` - Database models
- `entities_schema.json` - Database models from packages perspective
- `types_schema.json` - Type system
- `validation_schema.json` - Validation rules
- Plus 14 more schemas defining components, API, events, jobs, etc.
**For architectural questions**, check `/schemas` first.
**For architectural and package design questions**, check `/schemas` first.
### 2. DBAL YAML Schemas (`/dbal/shared/api/schema/entities/`)
Defines the actual **database structure** (source of truth):
- `/dbal/shared/api/schema/entities/core/*.yaml` - Core entities (User, Session, Workflow, etc.)
- `/dbal/shared/api/schema/entities/access/*.yaml` - Access control entities (Credential, PageConfig, etc.)
- `/dbal/shared/api/schema/entities/packages/*.yaml` - Package-specific entities
**For database schema changes**, edit YAML files here, then regenerate Prisma schema.
---
@@ -268,7 +279,8 @@ The `/schemas/package-schemas/` folder defines the **complete MetaBuilder archit
### Database Code
- ❌ Don't use `prisma` client directly
- ❌ Don't use old `getAdapter()` from frontend
- ❌ Don't edit `/prisma/schema.prisma` (it's at `/dbal/development/prisma/schema.prisma`)
- ❌ Don't edit `/prisma/schema.prisma` directly (it's auto-generated)
- ❌ Don't manually edit Prisma schema - edit YAML schemas instead
- ❌ Don't hardcode seed data in TypeScript
- ❌ Don't assume database tables exist (they might not until db:push is run)
@@ -290,21 +302,23 @@ The `/schemas/package-schemas/` folder defines the **complete MetaBuilder archit
- ✅ Read ARCHITECTURE.md before starting database work
- ✅ Use `getDBALClient()` from `@/dbal` for all database access
- ✅ Put seed data in `/seed/` folder or `/packages/*/seed/metadata.json`
-Run `npm --prefix dbal/development run db:push` if tables are missing
-Edit YAML schemas at `/dbal/shared/api/schema/entities/` for database changes
- ✅ Generate Prisma from YAML: `npm --prefix dbal/development run codegen:prisma`
- ✅ Run `npm --prefix dbal/development run db:push` to apply schema changes
- ✅ Follow entity operations pattern (db.users.list(), etc.)
- ✅ Check /schemas folder for architectural questions
-Verify Prisma schema exists at `/dbal/development/prisma/schema.prisma`
- ✅ Check `/schemas/` folder for architectural/package design questions
-Check `/dbal/shared/api/schema/` folder for database schema questions
---
## 🔍 Refactoring Status
**Phase 1 - DBAL Improvements** ✅ (COMPLETE)
- [x] Moved Prisma schema to DBAL ownership
- [x] Created Prisma client factory
- [x] Created DBAL client factory
- [x] Set up seed orchestration structure
- [x] Created Prisma client factory (`getPrismaClient`)
- [x] Created DBAL client factory (`getDBALClient`, `useDBAL`)
- [x] Set up seed orchestration structure (`seedDatabase`)
- [x] Updated DBAL exports
- [x] Clarified YAML schemas as source of truth (Prisma is auto-generated)
**Phase 2 - Next.js Cleanup** ⏳ (PENDING)
- [ ] Delete duplicate adapter code from frontend
@@ -324,7 +338,8 @@ See `DBAL_REFACTOR_PLAN.md` for detailed steps.
### Error: "The table `X` does not exist"
```bash
# Solution: Push the schema
# Solution: Generate Prisma schema from YAML, then push
npm --prefix dbal/development run codegen:prisma
npm --prefix dbal/development run db:push
```
@@ -342,8 +357,8 @@ ls -la seed/database/
### Tests fail with database errors
```bash
# Solution: Run database setup before tests
npm --prefix dbal/development run db:generate
# Solution: Generate schema from YAML, push to DB, then run tests
npm --prefix dbal/development run codegen:prisma
npm --prefix dbal/development run db:push
npm run test:e2e
```

View File

@@ -1,121 +0,0 @@
datasource db {
provider = "sqlite"
}
generator client {
provider = "prisma-client-js"
}
model User {
id String @id
username String @unique
email String @unique
role String
profilePicture String?
bio String?
createdAt BigInt
tenantId String?
isInstanceOwner Boolean @default(false)
passwordChangeTimestamp BigInt?
firstLogin Boolean @default(false)
@@index([tenantId])
@@index([role])
}
model Credential {
username String @id
passwordHash String
}
model Session {
id String @id
userId String
token String @unique
expiresAt BigInt
createdAt BigInt
lastActivity BigInt
ipAddress String?
userAgent String?
@@index([userId])
@@index([expiresAt])
@@index([token])
}
model PageConfig {
id String @id
tenantId String?
packageId String?
path String // Route pattern: /media/jobs, /forum/:id
title String
description String?
icon String?
component String?
componentTree String // JSON: full component tree
level Int
requiresAuth Boolean
requiredRole String?
parentPath String?
sortOrder Int @default(0)
isPublished Boolean @default(true)
params String?
meta String?
createdAt BigInt?
updatedAt BigInt?
@@unique([tenantId, path])
@@index([tenantId])
@@index([packageId])
@@index([level])
@@index([parentPath])
}
model ComponentNode {
id String @id
type String
parentId String?
childIds String // JSON: string[]
order Int
pageId String
@@index([pageId])
@@index([parentId])
}
model ComponentConfig {
id String @id
componentId String
props String // JSON
styles String // JSON
events String // JSON
conditionalRendering String?
@@index([componentId])
}
model Workflow {
id String @id
tenantId String?
name String
description String?
nodes String // JSON: WorkflowNode[]
edges String // JSON: WorkflowEdge[]
enabled Boolean
version Int @default(1)
createdAt BigInt?
updatedAt BigInt?
createdBy String?
@@index([tenantId])
@@index([enabled])
}
model InstalledPackage {
packageId String @id
tenantId String?
installedAt BigInt
version String
enabled Boolean
config String?
@@index([tenantId])
}
model PackageData {
packageId String @id
data String // JSON
}