Skip to content

Database Schema Documentation

This document describes the EIAS database schema, entity relationships, and data model design decisions.

Overview

EIAS uses PostgreSQL with Prisma ORM. The schema supports: - Multi-tenant project management - Expert interview sessions with conversation history - VOI-based knowledge state tracking - Expert calibration and competence scoring - Insight extraction and review workflow

Entity Relationship Diagram

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                              EIAS Database Schema                                   │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                     │
│  ┌──────────┐         ┌─────────────────┐        ┌──────────────────┐             │
│  │   User   │────────▶│     Project     │◀───────│  SubQuestion     │             │
│  └──────────┘  owns   └─────────────────┘ has    └──────────────────┘             │
│       │                       │                          │                         │
│       │                       │ has                      │ addresses               │
│       │                       ▼                          ▼                         │
│       │              ┌─────────────────┐        ┌──────────────────┐             │
│       │              │ UncertaintyArea │        │FindingSubQuestion│             │
│       │              └─────────────────┘        └──────────────────┘             │
│       │                       │                          │                         │
│       │                       │ focuses                  │                         │
│       │                       ▼                          ▼                         │
│       │              ┌─────────────────┐        ┌──────────────────┐             │
│       │              │ InterviewAgent  │        │     Finding      │◀────────┐   │
│       │              └─────────────────┘        └──────────────────┘         │   │
│       │                       │                          │                   │   │
│       │                       │ has                      │ extracted from    │   │
│       │                       ▼                          ▼                   │   │
│       │              ┌─────────────────┐        ┌──────────────────┐        │   │
│       │              │   Invitation    │───────▶│ InterviewSession │────────┘   │
│       │              └─────────────────┘ starts └──────────────────┘             │
│       │                                                  │                         │
│       │                                                  │ has                     │
│       │                                                  ▼                         │
│       │                                         ┌──────────────────┐             │
│       │                                         │     Message      │             │
│       │                                         └──────────────────┘             │
│       │                                                  │                         │
│       │                                                  │ yields                  │
│       │                                                  ▼                         │
│       │         approves                        ┌──────────────────┐             │
│       └────────────────────────────────────────▶│     Insight      │             │
│                                                 └──────────────────┘             │
│                                                          │                         │
│                                                          │ becomes                 │
│                                                          ▼                         │
│                                                 ┌──────────────────┐             │
│                                                 │IntegratedKnowledge│            │
│                                                 └──────────────────┘             │
│                                                                                     │
│  ┌──────────────────────────────────────────────────────────────────────────────┐  │
│  │                        VOI Knowledge State Entities                          │  │
│  │  ┌──────────────────┐    ┌──────────────────┐    ┌──────────────────┐       │  │
│  │  │   Contradiction  │    │ ExpertCompetence │    │  GoldenQuestion  │       │  │
│  │  └──────────────────┘    └──────────────────┘    └──────────────────┘       │  │
│  │          │                                               │                   │  │
│  │          │                                               ▼                   │  │
│  │          │                                       ┌──────────────────┐       │  │
│  │          │                                       │GoldenQResponse   │       │  │
│  │          │                                       └──────────────────┘       │  │
│  └──────────────────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────────────────┘

Core Entities

User

Authenticated researchers who manage projects.

Field Type Description
id UUID Primary key
email String Unique email address
name String? Display name
emailVerified DateTime? When email was verified (NextAuth.js)
image String? Profile image URL

Relations: - Has many Projects (as owner) - Has many IntegratedKnowledge (as approver)

Project

Research project containing uncertainty areas and interview agents.

Field Type Description
id UUID Primary key
name String Project name
description String Research question/description
goals String[] Array of project goals
status Enum active, paused, completed, archived
ownerId UUID Foreign key to User

Relations: - Belongs to User (owner) - Has many UncertaintyAreas - Has many InterviewAgents - Has many SubQuestions - Has many Contradictions

UncertaintyArea

Knowledge gaps that the project aims to address.

Field Type Description
id UUID Primary key
title String Brief title
description String Detailed description
priority Enum high, medium, low
status Enum open, partially_addressed, resolved
questions String[] Specific questions to answer
projectId UUID Foreign key to Project

Relations: - Belongs to Project - Many-to-many with InterviewAgent via AgentFocusArea

InterviewAgent

AI interview agent configuration.

Field Type Description
id UUID Primary key
name String Agent name
systemPrompt String Generated system prompt
style Enum exploratory, focused, validating
timeEstimateMinutes Int Expected interview duration
status Enum draft, active, paused, retired
topicPriorities JSON? Interview Protocol Framework config
guardrails JSON? Topic constraints and time allocation
interviewRules JSON? Probing depth and follow-up style
completionCriteria JSON? When to consider interview complete
projectId UUID Foreign key to Project

Relations: - Belongs to Project - Has many Invitations - Many-to-many with UncertaintyArea via AgentFocusArea

Invitation

Secure link for experts to access interviews.

Field Type Description
id UUID Primary key
expertName String Invited expert's name
expertRole String Expert's role/title
expertEmail String? Expert's email (optional)
token String Unique access token
expiresAt DateTime Token expiration
status Enum pending, opened, in_progress, completed, expired
agentId UUID Foreign key to InterviewAgent

Relations: - Belongs to InterviewAgent - Has one InterviewSession

InterviewSession

Active or completed interview session.

Field Type Description
id UUID Primary key
status Enum active, paused, completed, abandoned
startedAt DateTime When interview started
completedAt DateTime? When interview completed
turnCount Int Number of conversation turns
expertCorrections String? Expert's corrections/clarifications
expertRating Int? Expert's rating (1-5)
analytics JSON? Interview analytics data
progressPercent Int? Completion progress (0-100)
invitationId UUID Foreign key to Invitation

Relations: - Belongs to Invitation - Has many Messages - Has many Insights - Has many Findings

Message

Individual conversation message.

Field Type Description
id UUID Primary key
role Enum assistant, user
content String Message text
timestamp DateTime When message was sent
metadata JSON? Additional metadata
qualityFlags JSON? Question quality analysis
sessionId UUID Foreign key to InterviewSession

Relations: - Belongs to InterviewSession - Many-to-many with Insight via InsightSourceMessage

VOI Knowledge State Entities

SubQuestion

Atomic component of the research question for VOI tracking.

Field Type Description
id UUID Primary key
projectId UUID Foreign key to Project
title String Brief title
description String? Detailed description
status Enum uncovered, partial, answered
confidence Float Confidence score (0.0-1.0)
currentAnswer String? Provisional answer
dependencies String[] IDs of prerequisite sub-questions
priority Enum high, medium, low

Relations: - Belongs to Project - Many-to-many with Finding via FindingSubQuestion

Finding

Information extracted from expert responses.

Field Type Description
id UUID Primary key
content String Full finding content
summary String Brief summary
confidence Float Confidence score (0.0-1.0)
verbatimExcerpt String? Direct quote from expert
expertId String Reference to expert
sessionId UUID Foreign key to InterviewSession
turnNumber Int Which conversation turn

Relations: - Belongs to InterviewSession - Many-to-many with SubQuestion via FindingSubQuestion - Has many Contradictions (as findingA or findingB)

Contradiction

Conflicting information between findings.

Field Type Description
id UUID Primary key
projectId UUID Foreign key to Project
description String Description of the conflict
nature String? factual, interpretive, scope-dependent
status Enum unresolved, resolved, acknowledged
resolution String? How it was resolved
findingAId UUID First conflicting finding
findingBId UUID Second conflicting finding

Relations: - Belongs to Project - References two Findings

ExpertCompetence

Calibration scores for experts (Cooke's Classical Model).

Field Type Description
id UUID Primary key
expertId String Unique expert identifier
expertName String? Expert's name
expertRole String? Expert's role
statisticalAccuracy Float Calibration score (0.0-1.0)
informativeness Float Entropy measure (0.0-1.0)
competenceScore Float accuracy × informativeness
calibrationCount Int Number of calibration questions answered
lastCalibratedAt DateTime? Last calibration time
domains String[] Areas of expertise

GoldenQuestion

Calibration questions with known answers.

Field Type Description
id UUID Primary key
projectId UUID? Optional project scope
question String The calibration question
knownAnswer String Verified correct answer
domain String? Domain/area covered
difficulty String? easy, medium, hard
source String? Answer source
isActive Boolean Whether question is active

Relations: - Optionally belongs to Project - Has many GoldenQuestionResponses

Insight & Knowledge Integration

Insight

Extracted insight pending review.

Field Type Description
id UUID Primary key
content String Insight content
category String factual_claim, expert_opinion, etc.
confidence Enum high, medium, low
status Enum pending_review, integrated, discarded, review_later
reviewerNotes String? Reviewer's notes
sessionId UUID Foreign key to InterviewSession

Relations: - Belongs to InterviewSession - Many-to-many with Message via InsightSourceMessage - Has one IntegratedKnowledge

IntegratedKnowledge

Approved insights added to project knowledge base.

Field Type Description
id UUID Primary key
content String Approved content
sourceExpert String Expert who provided the insight
approvedAt DateTime When approved
projectId UUID Foreign key to Project
insightId UUID Foreign key to Insight
approvedById UUID Foreign key to User

Relations: - Belongs to Project - Belongs to Insight - Belongs to User (approver)

Enums

Project & Agent Status

enum ProjectStatus {
  active
  paused
  completed
  archived
}

enum AgentStatus {
  draft
  active
  paused
  retired
}

Interview Status

enum InvitationStatus {
  pending
  opened
  in_progress
  completed
  expired
}

enum SessionStatus {
  active
  paused
  completed
  abandoned
}

VOI Status

enum SubQuestionStatus {
  uncovered   // No evidence yet
  partial     // Some evidence but incomplete
  answered    // Sufficient evidence
}

enum ContradictionStatus {
  unresolved   // Active conflict
  resolved     // Resolved with explanation
  acknowledged // Acknowledged but not resolved
}

Insight Categories

enum InsightStatus {
  pending_review
  integrated
  discarded
  review_later
}

// Categories (stored as String)
// factual_claim, expert_opinion, process_description,
// recommendation, warning, opportunity, constraint

Database Operations

Common Queries

Get project with knowledge state:

const project = await prisma.project.findUnique({
  where: { id: projectId },
  include: {
    subQuestions: true,
    contradictions: true,
    agents: {
      include: {
        invitations: {
          include: {
            session: {
              include: {
                findings: true,
              },
            },
          },
        },
      },
    },
  },
});

Get interview session with messages:

const session = await prisma.interviewSession.findUnique({
  where: { id: sessionId },
  include: {
    messages: {
      orderBy: { timestamp: 'asc' },
    },
    invitation: {
      include: {
        agent: true,
      },
    },
  },
});

Migrations

# Create a new migration
npm run db:migrate -- --name add_new_field

# Push schema changes (development)
npm run db:push

# Reset database (caution: deletes all data)
npm run db:reset

# Open Prisma Studio
npm run db:studio

Indexes

The schema includes indexes for common query patterns:

Table Index Purpose
Project ownerId, status Filter projects by owner/status
UncertaintyArea projectId, priority List areas by project
Invitation token, agentId, status Token lookup, list by agent
Message sessionId, timestamp Load conversation in order
SubQuestion projectId, status, priority VOI queries
Finding sessionId, expertId, confidence Finding queries

Data Integrity

Cascade Deletes

Most relations use onDelete: Cascade: - Deleting a Project deletes all related UncertaintyAreas, Agents, SubQuestions - Deleting an InterviewAgent deletes all Invitations - Deleting an InterviewSession deletes all Messages, Insights, Findings

Unique Constraints

  • User.email
  • Invitation.token
  • ExpertCompetence.expertId
  • [agentId, uncertaintyId] on AgentFocusArea
  • [findingId, subQuestionId] on FindingSubQuestion