Architecture

Data model

The core entities, enums, and relationships behind the Knowledge & Advisor Core.

The schema is defined with Drizzle ORM in packages/database/drizzle/schema/ and split by concern (auth-org, knowledge, conversation, usage, audit, policy, billing, vector, reporting, kpi-reference-library, feature-flags, ai-model-config, enums, and others). All identifiers are CUIDs.

Entity map

organization ─┬─< member >── user
              ├─< invitation
              ├─< knowledgeDoc ─┬─< kbChunk (embedding)
              │                 └─< ingestionJob
              ├─< conversation ──< message
              ├─< policyGapReport
              ├─< aiUsageLog
              ├─< usageCounter
              ├─< auditLog

              ├─< lp ──< template ──< templateVersion ─┬─< templateParseJob
              │                                        └─< templateFieldBinding >── kpi
              ├─< kpi ─┬─< kpiMapping
              │        ├─< kpiMethodologyHistory
              │        ├─< kpiTemplateSource
              │        └─< kpiCalculation
              ├─< investee ──< submission ─┬─< dqcRun ──< dqcFindingResolution
              │                            └─< submissionCorrection
              ├─< gpSubmission
              ├─< report
              └─< cycleAutomationRun ──< cycleAutomationEvent

Tenancy & identity

organization

The tenant. Holds plan tier and lifecycle state.

ColumnTypeNotes
idtextPrimary key.
name, slugtextslug is unique and used in workspace URLs.
planOrganizationPlanPlan tier. Default full.
suspendedAttimestampNon-null means the tenant is suspended and workspace access is blocked.
legalName, description, logotextFund profile fields.

user, member, session

TableKey columnsNotes
useremail (unique), role, lastActiveOrganizationIdrole = 'admin' marks a platform operator; otherwise null.
memberorganizationId, userId, roleOrganization-level role: member, admin, or owner.
sessionuserId, activeOrganizationId, impersonatedByactiveOrganizationId scopes the session to a tenant; impersonatedBy marks an operator support session.
invitationorganizationId, email, statusPending invitations; signup is invitation-only.

Knowledge

knowledgeDoc

One row per uploaded document, global or organization-scoped.

ColumnTypeNotes
idtextPrimary key.
organizationIdtextNull when tenantScope = 'global'.
tenantScopeTenantScopeglobal or org. A check constraint ties this to organizationId.
source, title, categorytextDocument metadata.
r2KeytextObject-storage key for the original file.
statusKnowledgeDocStatuspending, indexed, or failed.
mimeType, byteSizeFile details.
supersededAttimestampSet when a newer version replaces this document (latest-wins).

kbChunk

The embedded, searchable units of a document.

ColumnTypeNotes
docIdtextParent document.
organizationId, tenantScope, fundIdCarried from the document for scoped retrieval.
contenttextChunk text.
chunkIndex, tokenCountintegerPosition and approximate token count.
embeddingvector(1536)The embedding. Indexed with an HNSW index using cosine distance.

ingestionJob

The state machine that drives a document to indexed. See the ingestion pipeline for the full lifecycle.

ColumnTypeNotes
knowledgeDocIdtextDocument being processed.
stageIngestionJobStageCurrent stage (see enums below).
attempts, maxAttemptsintegerRetry accounting; maxAttempts defaults to 5.
nextRunAttimestampBack-off schedule for the next retry.
lastErrortextMost recent failure message.

Conversations & advisor

TableKey columnsNotes
conversationorganizationId, userId, channel, title, retentionExpiresAtOne thread; channel is web or whatsapp.
messageconversationId, role, content, citations, refused, model, tokensIn, tokensOutOne turn. citations is JSON; refused flags out-of-corpus answers.
policyGapReportorganizationId, knowledgeDocId, status, gaps, suggestionsGap analysis for a policy document.

A partial index on message (assistant messages where refused = true) powers the operator Knowledge Gaps view.

LP Reporting

Defined in packages/database/drizzle/schema/reporting.ts. Every table carries an organizationId, and same-fund integrity is enforced at database level.

Set-up

TableKey columnsNotes
lporganizationId, nameAn LP the fund reports to.
templatelpId, format, status, reporting frequencyAn LP's reporting template. status: uploadedparsingparsed / failed.
templateVersiontemplateId, version metadataOne row per uploaded version, so versions can be compared.
templateParseJobtemplateVersionId, stage, errorThe parse/extraction job behind a version.
kpiorganizationId, name, unit, frequency, theme, level, aggregation, referenceCanonicalName, referenceLinkSourceThe fund's dictionary. name is unique per fund, case-insensitively.
kpiMappingkpiId, standard, alignmentStandards tagging (direct / partial / proxy).
templateFieldBindingtemplateVersionId, kpiId, cell reference, confirmedOne KPI per template cell. Suggestions are unconfirmed rows.
kpiMethodologyHistorykpiId, prior valuesChange history for methodology text.
kpiTemplateSourcekpiId, templateIdProvenance — which templates a KPI came from, so delete can be selective.
kpiCalculationkpiId, expressionDerived-KPI expressions.

Data collection

TableKey columnsNotes
investeeorganizationId, lpId, contactEmail, active flagA portfolio company. lpId links it to the LP it reports to.
submissioninvesteeId, period, status, source, dataA portfolio-company submission. period is mandatory.
gpSubmissionorganizationId, period, dataFund-level figures — no LP dimension.
dqcRunsubject type (investee / gp), findingsOne quality-check run and its findings.
dqcFindingResolutiondqcRunId, finding, reason, actorPer-finding acknowledgement, tied to the exact run.
submissionCorrectionsubmissionId, original value, corrected value, actor, reasonAppend-only correction trail.

Output

TableKey columnsNotes
reportlpId, period, status, narrative, valuesSnapshotvaluesSnapshot freezes the figures and the cells they fill.
cycleAutomationRunorganizationId, periodAtomic claim — stops two automatic runs on the same fund and period.
cycleAutomationEventstep, statusAppend-only log per step attempt.

The KPI reference library

packages/database/drizzle/schema/kpi-reference-library.ts holds Nia's master KPI list: canonical names and aliases, units, methodology prose (clear definition, calculation method, numerator, denominator), and aggregation rules including weighted-average denominators and unsafe-to-aggregate markers. It is platform-wide, not tenant-scoped, and funds import from or link to it.

Usage & audit

TableKey columnsNotes
aiUsageLogorganizationId, userId, channel, kind, model, tokensIn, tokensOutImmutable per-run log of AI spend. kind is e.g. advisor, gap_review, embed.
usageCounter(organizationId, fundId, period), runsUsed, runsCapRolling monthly counter (period is YYYY-MM). runsCap = 0 means "use the plan default".
auditLogorganizationId, actorUserId, action, targetType, targetId, metadataRecords operator actions like tier changes, suspensions, and support sessions.

Enums

Defined in packages/database/drizzle/schema/enums.ts:

EnumValues
OrganizationPlanbot_only, policy_hub, full
TenantScopeglobal, org
KnowledgeDocStatuspending, indexed, failed
IngestionJobStagequeued, parsing, chunking, embedding, indexing, completed, failed, dead_letter
ConversationChannelweb, whatsapp
MessageRoleuser, assistant, system
PolicyGapReportStatuspending, completed, failed
TemplateFormatxlsx, docx, pdf, csv, image
TemplateStatusuploaded, parsing, parsed, failed
KpiThemeenvironmental, social, governance, impact, financial
KpiFrequencyquarterly, half, annual, monthly
KpiLevelinvestee, gp, fund
KpiAggregationperiod_end, sum, average, none
KpiStandardiris_plus, two_x, gri, other, ifc_ps, hipso
MappingAlignmentdirect, partial, proxy
SubmissionSourceexcel, form, api
SubmissionStatusdraft, reviewing, approved, rejected
DqcSubjectTypeinvestee, gp
LpReportStatuspending, generating, completed, failed
ReportExportFormatxlsx, pdf, docx
CycleAutomationStepaggregation, generation, period_open
CycleAutomationStatuscompleted, failed, skipped_cap, skipped_waiting, skipped_complete
FeatureFlagKeyadvisor_hub, advisor_guidance, lp_reporting
AiTaskKindextract, dqc, advisor, gap_review, narrative, embed

Postgres enums are append-only in this schema. New values are ADDed only, never reordered or removed.

Vector storage

Embeddings live in kbChunk.embedding as a pgvector column with a fixed dimension (default 1536, configurable via EMBEDDING_DIMENSIONS). An HNSW index (vector_cosine_ops) provides approximate-nearest-neighbour search; queries set hnsw.ef_search per request to tune the recall/latency trade-off. The stored dimension must match the embedding model's output. Changing it requires a migration and re-embedding.

On this page