/home/techb158/balavpn.abdallabala.com/prisma
Edit: /home/techb158/balavpn.abdallabala.com/prisma/import-project.js (11325B)
const fs = require("fs");
const path = require("path");
const { PrismaClient } = require("@prisma/client");
const prisma = new PrismaClient();
function mapStatus(s) {
if (!s) return "PENDING";
const m = { completed: "Completed", in_progress: "In Progress", planned: "Pending", active_pilot: "ACTIVE", active: "ACTIVE" };
return m[s.toLowerCase()] || s;
}
function mapRiskStatus(s) {
if (!s) return "OPEN";
const m = { open: "OPEN", in_mitigation: "IN_MITIGATION", controlled: "ACCEPTED", closed: "CLOSED" };
return m[s.toLowerCase()] || "OPEN";
}
function mapApprovalStatus(s) {
if (!s) return "PENDING";
const m = { pending: "PENDING", pending_legal: "PENDING", pending_ethics: "PENDING", pending_security: "PENDING", approved: "APPROVED", accepted: "ACCEPTED", rejected: "REJECTED" };
return m[s.toLowerCase()] || "PENDING";
}
function mapMitigationStatus(s) {
if (!s) return "NOT_STARTED";
const m = { planned: "NOT_STARTED", in_progress: "IN_PROGRESS", completed: "DONE", rejected: "REJECTED" };
return m[s.toLowerCase()] || "NOT_STARTED";
}
function mapGateStatus(s) {
if (!s) return "READY";
const m = { passed: "READY", conditional_pass: "WARNING", blocked: "BLOCKED", warning: "WARNING" };
return m[s.toLowerCase()] || "READY";
}
function scoreFromStatus(s) {
const m = { "Completed": 100, "completed": 100, "In Progress": 50, "in_progress": 50, "Pending": 10, "planned": 10 };
return m[s] || 25;
}
async function importProject(jsonPath) {
const raw = JSON.parse(fs.readFileSync(jsonPath, "utf8"));
const data = raw.project ? raw : { project: raw };
const p = data.project;
const ai = data.aiSystem || {};
const lifecycleStages = data.lifecycleStages || [];
const risks = data.risks || [];
const mitigations = data.mitigations || [];
const metrics = data.metrics || [];
const experiments = data.experiments || [];
const gates = data.gates || [];
const governance = data.governance || {};
// Use or create the demo organization
let org = await prisma.organization.findUnique({ where: { slug: "cosmic-demo" } });
if (!org) {
org = await prisma.organization.create({
data: { name: "COSMIC Demo Organization", slug: "cosmic-demo", status: "TRIAL", planCode: "pilot", manualBilling: true }
});
}
let workspace = await prisma.workspace.findFirst({ where: { organizationId: org.id } });
if (!workspace) {
workspace = await prisma.workspace.create({
data: { organizationId: org.id, name: "AI Risk Governance", slug: "ai-risk-governance", type: "B2B_TEAM", status: "TRIAL" }
});
}
// Ensure platform users have access to this organization
const ownerRole = await prisma.role.findUnique({ where: { code: "owner" } });
if (ownerRole) {
for (const email of ["super-owner@cosmic.local", "super-admin@cosmic.local"]) {
const u = await prisma.user.findUnique({ where: { email } });
if (u) {
await prisma.membership.upsert({
where: { organizationId_userId: { organizationId: org.id, userId: u.id } },
update: { roleId: ownerRole.id, status: "ACTIVE" },
create: { organizationId: org.id, userId: u.id, roleId: ownerRole.id, status: "ACTIVE" }
}).catch(() => {});
console.log(` Added ${email} as member of ${org.name}`);
}
}
}
// Create project
const projectType = (p.projectTypology && p.projectTypology[0]) || "AI-Enabler";
const project = await prisma.project.upsert({
where: { id: `imported-${p.id || p.name}`.replace(/[^a-zA-Z0-9_-]/g, "_") },
update: { name: p.name, description: p.description || "", projectType, status: mapStatus(p.status) || "ACTIVE", currentLifecyclePhase: "", riskAppetite: 50, ownerDisplayName: p.managerRole || "", thresholds: { source: jsonPath, importedAt: new Date().toISOString(), governance: governance, aiSystem: ai }, reviews: {} },
create: { id: `imported-${p.id || p.name}`.replace(/[^a-zA-Z0-9_-]/g, "_"), workspaceId: workspace.id, name: p.name, description: p.description || "", projectType, status: mapStatus(p.status) || "ACTIVE", currentLifecyclePhase: "", riskAppetite: 50, ownerDisplayName: p.managerRole || "", thresholds: { source: jsonPath, importedAt: new Date().toISOString(), governance: governance, aiSystem: ai }, reviews: {} }
}).catch(async () => {
// Fallback — create without custom ID
return prisma.project.create({
data: { workspaceId: workspace.id, name: p.name, description: p.description || "", projectType, status: mapStatus(p.status) || "ACTIVE", riskAppetite: 50, ownerDisplayName: p.managerRole || "", thresholds: { source: jsonPath, importedAt: new Date().toISOString(), governance: governance, aiSystem: ai }, reviews: {} }
});
});
console.log(`Project: ${project.id} — ${project.name}`);
// Map lifecycle stage IDs to names and create phases
const lifecycleIdToName = {};
for (let i = 0; i < lifecycleStages.length; i++) {
const ls = lifecycleStages[i];
const name = ls.name;
lifecycleIdToName[ls.id] = name;
await prisma.lifecyclePhase.upsert({
where: { projectId_name: { projectId: project.id, name } },
update: { status: mapStatus(ls.status), readinessScore: scoreFromStatus(ls.status), sequence: i + 1 },
create: { projectId: project.id, name, status: mapStatus(ls.status), readinessScore: scoreFromStatus(ls.status), sequence: i + 1 }
}).catch(() => {});
}
// Set current lifecycle phase
if (p.currentLifecycleStageId && lifecycleIdToName[p.currentLifecycleStageId]) {
await prisma.project.update({ where: { id: project.id }, data: { currentLifecyclePhase: lifecycleIdToName[p.currentLifecycleStageId] } });
}
// Import indicators (metrics)
const metricIdMap = {};
for (const m of metrics) {
const indicator = await prisma.indicator.upsert({
where: { projectId_name: { projectId: project.id, name: m.name } },
update: { dimension: m.dimension || "Technical", measurand: m.measurand || "", unit: m.unit || "", target: m.target || "", interpretationRule: m.interpretationRule || "" },
create: { projectId: project.id, name: m.name, dimension: m.dimension || "Technical", measurand: m.measurand || "", unit: m.unit || "", target: m.target || "", interpretationRule: m.interpretationRule || "" }
}).catch(() => null);
if (indicator) metricIdMap[m.id] = indicator.id;
}
console.log(` Imported ${metrics.length} indicators`);
// Import risks
const riskIdMap = {};
for (const r of risks) {
const lifecyclePhaseName = lifecycleIdToName[r.lifecycleStageId] || r.lifecycleStageId || "";
const created = await prisma.risk.create({
data: {
projectId: project.id,
title: r.title,
description: r.interpretationRule || "",
dimension: r.governanceDimension || "Technical",
domain: r.category || "",
lifecyclePhase: lifecyclePhaseName,
probability: Math.round((r.likelihood || 3) * 20),
impact: Math.round((r.impact || 3) * 20),
detectability: Math.round((r.uncertainty || 3) * 20),
status: mapRiskStatus(r.status),
approvalStatus: mapApprovalStatus(r.approvalState),
dueDate: r.dueDate ? new Date(r.dueDate) : null,
ownerDisplayName: r.ownerRole || "",
evidenceSummary: r.gateEffect ? `Gate effect: ${r.gateEffect}. Residual: ${r.residualScore}/100. Inherent: ${r.inherentScore}/100.` : ""
}
}).catch(e => {
console.warn(` Skipped risk "${r.title}": ${e.message}`);
return null;
});
if (created) {
riskIdMap[r.id] = created.id;
}
}
console.log(` Imported ${Object.keys(riskIdMap).length}/${risks.length} risks`);
// Import mitigations
let mitigationCount = 0;
for (const m of mitigations) {
const dbRiskId = riskIdMap[m.riskId];
if (!dbRiskId) continue;
await prisma.mitigation.create({
data: {
riskId: dbRiskId,
title: m.title,
ownerDisplayName: m.ownerRole || "",
status: mapMitigationStatus(m.status),
progressPercent: m.completionPercent || 0,
effectivenessPercent: m.completionPercent || 0,
dueDate: m.dueDate ? new Date(m.dueDate) : null
}
}).catch(() => {});
mitigationCount++;
}
console.log(` Imported ${mitigationCount} mitigations`);
// Import experiments
for (const e of experiments) {
const experiment = await prisma.experiment.upsert({
where: { projectId_name: { projectId: project.id, name: e.name } },
update: { modelName: e.modelVersion || "", selected: e.status === "completed" || e.status === "in_progress" },
create: { projectId: project.id, name: e.name, modelName: e.modelVersion || "", selected: e.status === "completed" || e.status === "in_progress" }
}).catch(() => null);
if (!experiment) continue;
// Import experiment metrics
if (e.metrics && typeof e.metrics === "object") {
for (const [metricName, metricValue] of Object.entries(e.metrics)) {
if (typeof metricValue === "number") {
await prisma.modelMetric.create({
data: {
experimentId: experiment.id,
metricName,
metricValue,
thresholdValue: 0,
status: "pass",
measuredAt: new Date()
}
}).catch(() => {});
}
}
}
}
console.log(` Imported ${experiments.length} experiments`);
// Import gates
for (const g of gates) {
const status = mapGateStatus(g.status);
const decisionDate = g.decisionDate ? new Date(g.decisionDate) : null;
const gate = await prisma.gateEvaluation.create({
data: {
projectId: project.id,
status,
reviewStatus: g.status === "blocked" ? "Blocked" : g.status === "conditional_pass" ? "Conditional Pass" : "Approved",
summary: `Gate: ${g.name}${g.conditions && g.conditions.length ? `. Conditions: ${g.conditions.join("; ")}` : ""}`,
evaluatedAt: decisionDate || new Date(),
reviewedAt: decisionDate
}
}).catch(() => null);
if (!gate) continue;
// Import gate criteria
for (const c of g.criteria || []) {
await prisma.gateCriterion.create({
data: {
gateId: gate.id,
name: c.name,
actualValue: c.status || "",
expectedRule: c.metricId || "",
status: c.status === "pass" ? "Pass" : c.status === "fail" ? "Fail" : c.status === "watch" ? "Watch" : c.status === "pending" ? "Pending" : c.status || "",
blocking: c.status === "fail",
evidenceTitle: c.blockedRiskIds ? `Blocked by risks: ${c.blockedRiskIds.join(", ")}` : (c.metricId || "")
}
}).catch(() => {});
}
}
console.log(` Imported ${gates.length} gates`);
console.log(`\nImport complete. Project: ${project.name} (${project.id})`);
console.log(` Indicators: ${metrics.length}, Risks: ${Object.keys(riskIdMap).length}, Mitigations: ${mitigationCount}, Experiments: ${experiments.length}, Gates: ${gates.length}`);
}
const filePath = process.argv[2];
if (!filePath) {
console.error("Usage: node prisma/import-project.js
");
process.exit(1);
}
importProject(filePath)
.catch(e => { console.error(e); process.exit(1); })
.finally(() => prisma.$disconnect());