fix: resolve Prettier markdown code block parsing errors

- Fix syntax errors in skills markdown files (.github/skills, .opencode/skills)
- Change typescript to tsx for code blocks with JSX
- Replace ellipsis (...) in array examples with valid syntax
- Separate CSS from TypeScript into distinct code blocks
- Convert JavaScript object examples to valid JSON in docs
- Fix enum definitions with proper comma separation
This commit is contained in:
2026-01-20 21:09:29 +01:00
parent 7932fe7386
commit cd05fc8648
177 changed files with 5042 additions and 5541 deletions

View File

@@ -9,26 +9,6 @@ datasource db {
directUrl = env("DATABASE_URL_DIRECT")
}
/// *
/// * PLATFORM USER (super-admin for Notso AI)
/// * Platform-level users who can manage companies and platform-wide settings
/// * Separate from Company users for platform management isolation
model PlatformUser {
id String @id @default(uuid())
/// Platform user email address
email String @unique @db.VarChar(255)
/// Hashed password for platform authentication
password String @db.VarChar(255)
/// Platform permission level
role PlatformUserRole @default(ADMIN)
/// Display name for platform user
name String @db.VarChar(255)
createdAt DateTime @default(now()) @db.Timestamptz(6)
updatedAt DateTime @updatedAt @db.Timestamptz(6)
@@index([email])
}
/// *
/// * COMPANY (multi-tenant root)
/// * Root entity for multi-tenant architecture
@@ -61,35 +41,30 @@ model Company {
}
/// *
/// * USER (authentication accounts)
/// * Application users with role-based access control
/// * Each user belongs to exactly one company for data isolation
/// * USER (unified authentication accounts)
/// * All users: platform admins (companyId=null) and company users (companyId set)
/// * Authentication handled by Neon Auth, this table stores authorization data
model User {
id String @id @default(uuid())
/// User email address, must be unique across all companies
email String @unique @db.VarChar(255)
/// Hashed password for authentication
password String @db.VarChar(255)
/// User permission level within their company
role UserRole @default(USER)
/// Foreign key to Company - enforces data isolation
companyId String
/// Temporary token for password reset functionality
resetToken String? @db.VarChar(255)
/// Expiration time for reset token
resetTokenExpiry DateTime? @db.Timestamptz(6)
createdAt DateTime @default(now()) @db.Timestamptz(6)
updatedAt DateTime @updatedAt @db.Timestamptz(6)
id String @id @default(uuid())
/// User email address, must be unique (synced from Neon Auth)
email String @unique @db.VarChar(255)
/// User permission level (includes both platform and company roles)
role UserRole @default(USER)
/// Foreign key to Company - null for platform users, set for company users
companyId String?
createdAt DateTime @default(now()) @db.Timestamptz(6)
updatedAt DateTime @updatedAt @db.Timestamptz(6)
/// Display name for the user
name String? @db.VarChar(255)
name String? @db.VarChar(255)
/// When this user was invited
invitedAt DateTime? @db.Timestamptz(6)
invitedAt DateTime? @db.Timestamptz(6)
/// Email of the user who invited this user (for audit trail)
invitedBy String? @db.VarChar(255)
company Company @relation("CompanyUsers", fields: [companyId], references: [id], onDelete: Cascade)
invitedBy String? @db.VarChar(255)
company Company? @relation("CompanyUsers", fields: [companyId], references: [id], onDelete: Cascade)
@@index([companyId])
@@index([email])
@@index([role])
}
/// *
@@ -328,24 +303,18 @@ model CompanyAIModel {
@@index([companyId, isDefault])
}
/// Platform-level user roles for Notso AI team
enum PlatformUserRole {
/// Full platform access, can create/suspend companies
SUPER_ADMIN
/// Platform administration, company management
ADMIN
/// Customer support access, read-only company access
SUPPORT
}
/// User permission levels within a company
/// Unified user roles for both platform and company users
enum UserRole {
/// Full access to company data and settings
/// Platform: Full platform access, can create/suspend companies
PLATFORM_SUPER_ADMIN
/// Platform: Platform administration, company management
PLATFORM_ADMIN
/// Platform: Customer support access, read-only company access
PLATFORM_SUPPORT
/// Company: Full access to company data and settings
ADMIN
/// Standard access to view and interact with data
/// Company: Standard access to view and interact with data
USER
/// Read-only access for compliance and auditing
AUDITOR
}
/// Company operational status

View File

@@ -1,63 +0,0 @@
import { PrismaClient, PlatformUserRole } from "@prisma/client";
import bcrypt from "bcryptjs";
const prisma = new PrismaClient();
async function main() {
console.log("🚀 Seeding platform users for Notso AI...");
// Create initial platform admin user
const adminPassword = await bcrypt.hash("NotsoAI2024!Admin", 12);
const admin = await prisma.platformUser.upsert({
where: { email: "admin@notso.ai" },
update: {},
create: {
email: "admin@notso.ai",
password: adminPassword,
name: "Platform Administrator",
role: PlatformUserRole.SUPER_ADMIN,
},
});
console.log("✅ Created platform super admin:", admin.email);
// Create support user
const supportPassword = await bcrypt.hash("NotsoAI2024!Support", 12);
const support = await prisma.platformUser.upsert({
where: { email: "support@notso.ai" },
update: {},
create: {
email: "support@notso.ai",
password: supportPassword,
name: "Support Team",
role: PlatformUserRole.SUPPORT,
},
});
console.log("✅ Created platform support user:", support.email);
console.log("\n🔑 Platform Login Credentials:");
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
console.log("Super Admin:");
console.log(" Email: admin@notso.ai");
console.log(" Password: NotsoAI2024!Admin");
console.log("");
console.log("Support:");
console.log(" Email: support@notso.ai");
console.log(" Password: NotsoAI2024!Support");
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
console.log("\n🌐 Platform Access:");
console.log(" Login: http://localhost:3000/platform/login");
console.log(" Dashboard: http://localhost:3000/platform/dashboard");
}
main()
.catch((e) => {
console.error("❌ Platform seeding failed:", e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});

View File

@@ -1,12 +1,12 @@
// seed.ts - Create initial admin user, company, and AI models
// seed.ts - Create initial company and AI models
// Note: Users are created via Neon Auth signup, this just creates the placeholder
import { PrismaClient } from "@prisma/client";
import bcrypt from "bcryptjs";
const prisma = new PrismaClient();
async function main() {
try {
console.log("🌱 Starting database seeding...");
console.log("Starting database seeding...");
// Create the Jumbo company
const company = await prisma.company.create({
@@ -17,19 +17,29 @@ async function main() {
csvPassword: "jumboadmin",
},
});
console.log(`Created company: ${company.name}`);
console.log(`Created company: ${company.name}`);
// Create admin user
const hashedPassword = await bcrypt.hash("8QbL26tB7fWS", 10);
// Create admin user placeholder (they'll complete signup via Neon Auth)
const adminUser = await prisma.user.create({
data: {
email: "max.kowalski.contact@gmail.com",
password: hashedPassword,
name: "Max Kowalski",
role: "ADMIN",
companyId: company.id,
},
});
console.log(`Created admin user: ${adminUser.email}`);
console.log(`Created admin user placeholder: ${adminUser.email}`);
// Create platform super admin placeholder
const platformAdmin = await prisma.user.create({
data: {
email: "admin@notso.ai",
name: "Platform Admin",
role: "PLATFORM_SUPER_ADMIN",
companyId: null, // Platform users have no company
},
});
console.log(`Created platform admin placeholder: ${platformAdmin.email}`);
// Create AI Models
const aiModels = [
@@ -59,13 +69,13 @@ async function main() {
},
];
const createdModels: any[] = [];
const createdModels: { id: string; name: string }[] = [];
for (const modelData of aiModels) {
const model = await prisma.aIModel.create({
data: modelData,
});
createdModels.push(model);
console.log(`Created AI model: ${model.name}`);
console.log(`Created AI model: ${model.name}`);
}
// Create current pricing for AI models (as of December 2024)
@@ -102,10 +112,10 @@ async function main() {
promptTokenCost: pricing.promptTokenCost,
completionTokenCost: pricing.completionTokenCost,
effectiveFrom: currentTime,
effectiveUntil: null, // Current pricing
effectiveUntil: null,
},
});
console.log(`Created pricing for: ${model.name}`);
console.log(`Created pricing for: ${model.name}`);
}
}
@@ -119,21 +129,25 @@ async function main() {
isDefault: true,
},
});
console.log(`Set default AI model for company: ${defaultModel.name}`);
console.log(`Set default AI model for company: ${defaultModel.name}`);
}
console.log("\n🎉 Database seeding completed successfully!");
console.log("\n📋 Summary:");
console.log("\nDatabase seeding completed successfully!");
console.log("\nSummary:");
console.log(`Company: ${company.name}`);
console.log(`Admin user: ${adminUser.email}`);
console.log(`Password: 8QbL26tB7fWS`);
console.log(
`Admin user: ${adminUser.email} (needs to sign up via /auth/sign-up)`
);
console.log(
`Platform admin: ${platformAdmin.email} (needs to sign up via /auth/sign-up)`
);
console.log(
`AI Models: ${createdModels.length} models created with current pricing`
);
console.log(`Default model: ${defaultModel?.name}`);
console.log("\n🚀 Ready to start importing CSV data!");
console.log("\nReady to start importing CSV data!");
} catch (error) {
console.error("Error seeding database:", error);
console.error("Error seeding database:", error);
process.exit(1);
} finally {
await prisma.$disconnect();