Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.kaireonai.com/llms.txt

Use this file to discover all available pages before exploring further.

KaireonAI persists all platform state in 104 Prisma models declared in the platform schema. This page indexes every model by domain, names the underlying PostgreSQL table (via @@map), and links each model back to the API or operator surface that owns it.

What it indexes

The platform schema is the single source of truth for every persisted entity. Every API route, cron job, MCP tool, and worker reads or writes one or more of these models. The Tenant model anchors multi-tenancy — most other models carry a tenantId column and an index on it. This page exists because operators and contributors need a one-screen overview before they grep for symbols. For per-API request and response shapes, follow the per-domain links in the Reference tables below; this page only documents the persistence layer.

Quick start

# View live models in a browser at localhost:5555
cd platform && npx prisma studio

# Format schema in place
cd platform && npx prisma format

# Sync schema changes to the database (dev only — destructive in production)
cd platform && npx prisma db push

# Regenerate the Prisma client into the gitignored generated directory
cd platform && npx prisma generate
The schema file is 2,333 lines long; jump to a model with the editor’s go-to-symbol command on the model name.

How it works

Prisma 7 lifecycle

Every model in the schema maps to one PostgreSQL table via the @@map("table_name") directive. The Prisma client generator emits a typed client into a gitignored generated directory; that path is regenerated by npm run build (which runs prisma generate && next build) and by the postinstall hook on npm install. The datasource block in the schema declares only the provider — provider = "postgresql" (no url). The connection URL lives in the Prisma config file and is read from DATABASE_URL. This split is required by Prisma 7; setting url directly inside the schema errors out with The datasource property 'url' is no longer supported in schema files.

Multi-tenant isolation

Every tenant-scoped model carries a tenantId String column and at least one composite index that begins with tenantId. API routes enforce isolation by adding where: { tenantId } on every query through the shared tenant-resolution helper. The Tenant table itself (tenants) holds tenant-level settings — settings (JSON), aiAnalyzerSettings (JSON), isPlayground (boolean) — that gate features per tenant. A handful of models — User, audit log rows, Account, Session, the email-verification token table, and the per-tenant region tag — either hold cross-tenant rows or scope by userId instead. Each is called out in its row below.

Soft delete vs hard delete

Models with operator-visible “archive” semantics carry a nullable deletedAt DateTime? column and an index on [tenantId, deletedAt]. API routes filter out soft-deleted rows by default; the audit log captures the soft-delete event. Models with deletedAt include Category, SubCategory, Channel, Placement, FlowRoute, Offer, Creative, OutcomeType, QualificationRule, ContactPolicy, DecisionFlow, TriggerRule, GuardrailRule, ArbitrationProfile, and SummaryDefinition. Other tables — the suppression ledger, the transactional outbox, the dead-letter store, pipeline run records, decision traces, and the interaction history fact table — are hard-deleted by retention crons per the per-tenant retention policy data class.

IR-native pipelines

Pipeline.irVersion is String NOT NULL DEFAULT "1.0" — every pipeline is IR-native after the legacy ETL editor was deleted on 2026-04-28. The full DAG lives in the pipeline IR version row’s ir JSONB column. The legacy per-node and per-edge tables were removed in the same change; the underlying pipeline_nodes and pipeline_edges Postgres tables were dropped via the 04_drop_legacy_pipeline_tables.sql manual SQL script.

Reference

Each subsection groups models by domain. Tables list the model name, the underlying Postgres table (@@map), the most operationally relevant fields, primary relations, and a one-line purpose. Schema line numbers below are valid against the schema as of 2026-04-30.

Decisioning core

The studio entities that make up an offer catalog and the four-stage decisioning pipeline (Eligibility / Fit Filters / Match Scoring / Ranking).
Model@@mapKey FieldsRelationsPurpose
Tenanttenantsname, slug, settings, aiAnalyzerSettings, isPlaygroundConversation childrenMulti-tenant root; per-tenant feature flags live in settings JSON (schema line 12).
Categorycategoriesname, customFields, ordinal, deletedAtsub-category and offer childrenTop-level offer grouping (e.g. “Cards”, “Loans”). Computed-field formulas live in customFields (schema line 30).
Sub-categorysub_categoriesname, categoryId, customFieldsparent category, offer childrenChild grouping below a category (e.g. “Travel” under “Cards”) (schema line 54).
ChannelchannelschannelType, deliveryMode, impressionMode, providerConfig, fileConfigcreative and placement childrenDelivery channel — email/sms/push/web/whatsapp/etc. impressionMode decides whether /recommend auto-records impressions (schema line 80).
PlacementplacementsslotType, maxSlots, channelId, targetingparent channel, creative childrenA targeted slot inside a channel (hero, banner, modal). Used by flow-route lookups (schema line 105).
Flow routeflow_routeschannelId, placementId, decisionFlowId, priorityMaps (channel, placement) to a decision flow. Cached 120s in the /recommend hot path (schema line 127).
OfferofferscategoryId, subCategoryId, priority, mandatory, eligibility, budget, scheduleoptional category, optional sub-category, creative children, interaction-history rowsDecisioning offer — what the platform recommends. mandatory=true bypasses eligibility (schema line 147).
CreativecreativesofferId, channelId, placementId, templateType, content, personalization, weightparent offer, channel, optional placement, optional content item, interaction-history rowsChannel-specific rendering of an offer. Maps to legacy “treatment” table semantically (schema line 194).
Outcome typeoutcome_typeskey, classification, category, isSystemPer-tenant taxonomy of outcomes (impression, click, dismiss, convert). System rows are undeletable (schema line 231).
Qualification rulequalification_rulesruleType, config, priority, stage, scope (deprecated)scope rowsStages: eligibility, fit, match. The legacy scope/scopeId columns are kept for back-compat; new code uses scopes[] (schema line 360).
Qualification rule scopequalification_rule_scopesqualificationRuleId, scope, scopeIdparent ruleMulti-scope assignment — one rule can apply globally and to specific categories/offers (schema line 387).
Contact policycontact_policiesruleType, config, priority, scope (deprecated)scope rowsFrequency caps, cooldowns, mutual exclusion. ruleType includes customer_total_cap (Phase 2B-3) and offer_category_cap (schema line 403).
Contact policy scopecontact_policy_scopescontactPolicyId, scope, scopeIdparent policyMulti-scope assignment for contact policies (schema line 429).
Decision flowdecision_flowskey, draftConfig, publishedVersions, arbitrationProfileId, isDefault, isProtectedrun childrenVisual decisioning flow. draftConfig holds the working version; publishedVersions[] holds immutable snapshots (schema line 765).
Arbitration profilearbitration_profileskey, weights, statusMulti-objective ranking weights (revenue, margin, propensity, engagement) (schema line 1705).
Cross-offer constraintcross_offer_constraintsscope, ruleType, config, statusMulti-offer arbitration constraints. Read by the Lagrangian cross-offer arbitration helper; threaded into both realtime and batch decisioning paths (schema line 2273).
Guardrail ruleguardrail_ruleskey, severity, expressionAstHard/soft filter expressions evaluated alongside qualification rules (schema line 743).
SuppressionsuppressionscustomerId, scope, policyId, expiresAtPre-computed contact-policy block per customer × scope. Expired rows cleaned by retention cron (schema line 1883).
Volume constraintvolume_constraintsscope, scopeId, maxVolume, period, currentCount, resetAtSystem-wide delivery caps on offers, categories, channels. See Volume Constraints (schema line 1840).
Budget allocationbudget_allocationsscope, scopeId, periodType, maxImpressions, maxSpend, maxConversions, periodKeyBudget tracking with rolling-window counters per scope (global / category / offer) (schema line 1307).

Customer & interactions

Customer-scoped rows that drive the decisioning loop and the analytics fact tables.
Model@@mapKey FieldsRelationsPurpose
Interaction historyinteraction_historycustomerId, recommendationId, offerId, creativeId, interactionType, outcomeTypeKey, direction, deduplicationIdoptional offer, creativeAppend-only fact table for impressions, recommendations, clicks, conversions. Partitioned in production via manual SQL (schema line 255).
Interaction summaryinteraction_summariesperiodType, periodKey, customerId, offerId, dimensionKey, definitionId, impressions, positive, converts, totalValuePre-aggregated rollups by [periodType, periodKey, customerId, offerId, creativeId, channelId]. Driven by the summary definition table (schema line 304).
ImpressionimpressionscustomerId, offerId, creativeId, channelId, placementId, contextChannel-level impression mirror written by /respond; the interaction-history table is the canonical record (schema line 1976).
Customer engagement healthcustomer_engagement_healthcustomerId, score (0-1), inputs, computedAtNightly-computed engagement score from a 90-day rollup. Read by engagement-aware contact-policy caps (Phase 2C-3) (schema line 344).
Customer CLVcustomer_clvcustomerId, clvScore, predictedRevenue, churnProbability, rfmRecency, rfmFrequency, rfmMonetary, segmentPer-customer RFM and lifetime-value scores. Segments: high, medium, low, at_risk (schema line 2061).
Identity linkidentity_linkscanonicalId, identifierType, identifierValue, confidenceIdentity resolution graph — maps email/phone/session/device → canonicalId per tenant (schema line 1333).
SegmentsegmentsbaseSchemaId, joins, filters, viewName, customerCountparent data schema, run childrenDefinition of an audience over data-schema rows. Materializes to a Postgres view named seg_{idPrefix} (schema line 796).
Consent recordconsent_recordssubjectId, purpose, status, source, grantedAt, revokedAtGDPR/privacy consent ledger per customer × purpose (schema line 1996).

Algorithm models

ML model registry, versioning, governance, and per-scope adaptive learning state.
Model@@mapKey FieldsRelationsPurpose
Algorithm modelalgorithm_modelskey, modelType, targetField, predictors, metrics, modelState, outcomeWeights, registryStatus, registryFamilymodel versions, model adaptations, experiments, experiment challengersThe model record. modelType is one of scorecard, bayesian, logistic_regression, gradient_boosted (schema line 572).
Model versionmodel_versionsmodelId, version, config, modelState, metrics, predictorsparent algorithm modelImmutable historical snapshot of algorithm-model state (schema line 657).
Model adaptationmodel_adaptationsmodelId, scope, scopeId, positives, negatives, positiveRate, predictorBins, predictorAucsparent algorithm modelPer-scope (global / category / offer / channel) learned propensity. Updated atomically by online learning loop (schema line 629).
Model approvalmodel_approvalsmodelId, version, status, requestedBy, reviewedBy, metricsProduction-promotion governance ticket per model version (schema line 1231).
Model drift checkmodel_drift_checksmodelId, checkType, baseline, current, driftScore, driftedPeriodic drift snapshot. checkType is one of psi, ks_test, auc_decay, feature_drift (schema line 1249).
Experimentexperimentskey, championModelId, trafficSplit, autoPromote, holdoutPercent, resultsoptional algorithm model, challenger rowsChampion/challenger experiment definition (schema line 676).
Experiment challengerexperiment_challengersexperimentId, modelId, trafficPctparent experiment, algorithm modelJoin row binding a challenger model to an experiment with a traffic percentage (schema line 701).
Experiment assignmentexperiment_assignmentscustomerId, experimentId, variant, assignedAtSticky customer-to-experiment mapping (schema line 1959).
Variant assignmentvariant_assignmentscustomerId, experimentKey, variantName, assignedAt, expiresAtVariant assignment with optional TTL — used for blueprint/decision-flow A/B tests (schema line 1449).
ML job resultml_job_resultsjobType, status, input, result, errorAsync ML job ledger — policy_analysis, segmentation, content_analysis (schema line 1746).

Audit & compliance

Tamper-evident logs, retention, consent, and DSAR machinery.
Model@@mapKey FieldsRelationsPurpose
Audit logaudit_logsrequestId, integrityHash, prevHash, userId, action, entityType, entityId, before, after, entityVersionImmutable audit chain. integrityHash = SHA-256(content + prevHash) builds a tamper-evident chain. API routes block UPDATE/DELETE on this table (schema line 1063).
Retention configretention_configsdataClass, retentionDays, legalHoldPer-tenant retention policy. dataClass includes interactions, decisions, metrics, audit. Cleanup cron honors per-tenant overrides (schema line 1690).
DSAR requestdsar_requestsrequestType (export/delete/rectify), subjectId, subjectType, status, requestedBy, resultData Subject Access Request workflow. See DSAR Portability (schema line 1286).
Policy snapshotpolicy_snapshotspolicyVersionHash, interactionId, eligibilityPolicies, suppressionPolicies, guardrailRulesFrozen policy configuration referenced by the decision-trace policyVersionHash. One row per unique 16-char hash per tenant (schema line 1269).
Decision tracedecision_tracesrequestId, customerId, candidateCount, afterQualification, afterContactPolicy, qualificationResults, scoringResults, selectedOffers, policyVersionHash, degradedScoringForensic per-decision trace. Sample rate set by tenantSettings.decisionTraceSampleRate (schema line 1604).

Governance

Approval workflows, four-eyes governance, and operator-driven change control.
Model@@mapKey FieldsRelationsPurpose
Approval requestapproval_requestsentityType, entityId, action, payload, requesterId, approverId, statusSingle-stage approval ticket — gates production changes when four-eyes is enabled (schema line 930).
Approval request stageapproval_request_stagesapprovalRequestId, stageName, ordinal, requiredRole, status, approverIdMulti-stage four-eyes (W14) — one approval request can require N sequential approvals (schema line 2255).
Custom rolecustom_rolesname, permissions (JSON array of permission strings)role-assignment childrenTenant-defined role bundles for fine-grained authorization (schema line 1418).
Custom role assignmentcustom_role_assignmentsuserId, roleIdparent custom roleJoin row binding a user to a custom role per tenant (schema line 1434).
SSO configsso_configsprovider (saml/oidc/none), samlEntityId, oidcIssuer, defaultRole, allowedDomains, autoProvision, enforceForAllUsersPer-tenant SSO configuration. One row per tenant (unique on tenantId) (schema line 1393).
WebAuthn credentialwebauthn_credentialsuserId, credentialId, publicKey (CBOR base64), counter, transports, deviceLabelHardware-backed FIDO2/WebAuthn credentials per user (W18) (schema line 2303).

Operator & infra

Tables consumed by operators, cron jobs, and out-of-band workers.
Model@@mapKey FieldsRelationsPurpose
Userusersemail, password, role, mfaSecret, mfaEnabled, mfaBackupCodes, lockedUntil, failedLoginAttempts, onboardingProgressaccount, session, conversation childrenNextAuth v5 user. Optional tenantId because some users (admins) are cross-tenant (schema line 990).
AccountaccountsuserId, provider, providerAccountId, OAuth tokensparent userNextAuth v5 OAuth account binding (schema line 1018).
SessionsessionssessionToken, userId, expiresparent userNextAuth v5 active sessions (schema line 1039).
Verification tokenverification_tokensidentifier, token, expiresNextAuth v5 email-verification + magic-link tokens (schema line 1051).
API keyapi_keysprefix (first 12 chars displayed), hashedKey (SHA-256), expiresAt, lastUsedAt, revokedAtLong-lived API key for X-API-Key auth. Raw key starts with krn_ (schema line 1124).
OAuth clientoauth_clientsclientId (kci_-prefixed), hashedSecret, scopes (read,write,admin)OAuth2 client credentials grant — server-to-server callers (schema line 1144).
Tenant settingstenant_settingsmlWorkerConfig, aiAnalyzerSettings, flowIrEnabled (defaults true)Per-tenant operational toggles. aiAnalyzerSettings.arbitration holds EXP3-IX bandit config; flowIrEnabled is a kill-switch for pipelines (schema line 1944).
Platform settingplatform_settingscategory, key, value, encryptedPer-tenant key-value config — SES from-address, Twilio SID, etc. AES-encrypted when encrypted=true (schema line 1586).
Outbox eventoutbox_eventstopic, payload, status, retryCount, maxRetries, lastError, publishedAtTransactional outbox for events. Drained by the outbox publisher worker; on max retries the row moves to the dead-letter store (schema line 1162).
Dead-letter eventdead_letter_eventsoriginalEventId, topic, payload, failedAt, errorMessageTerminal event store for outbox publish failures. Read by the Operations Runbook (schema line 1180).
Channel deliverychannel_deliveriesinteractionId, channelType, providerName, providerMessageId, idempotencyKey, status (pending/sent/delivered/bounced/failed/opened/clicked), attemptsPer-message delivery tracking with provider IDs and idempotency. Powers retry/bounce handling (schema line 1196).
Export checkpointexport_checkpointsexportType, lastExportAt, filePath, statusResume point for the Hive interaction-history export job (schema line 1906).
Alert rulealert_rulesmetric, operator, threshold, windowMinutes, cooldownMinutes, channels, lastFiredAt, statusThreshold-based alerts. channels is a JSON list of notification destinations (schema line 1466).
RunrunsdecisionFlowId (mapped to blueprintId), segmentId, scheduleType, volumeConstraints, fileConfig, channelIdsparent decision flow, segment, campaign-run childrenScheduled batch campaign config. Triggers campaign-run rows on each execution (schema line 823).
Campaign runcampaign_runscampaignId, runNumber, status, totalCustomers, processed, recommended, summaryparent runOne execution of a Run (campaign). One row per fired schedule tick (schema line 876).
Trigger ruletrigger_ruleseventType, condition, actionType, actionConfig, priority, cooldownMsEvent-driven trigger — when eventType matches condition, fire actionType (schema line 904).
Simulation runsimulation_runssegmentId, decisionFlowKey (mapped to blueprintKey), sampleSize, config, resultsWhat-if simulation snapshot. Re-runs a flow over a segment sample without writing decisions (schema line 955).
Attribution resultattribution_resultscustomerId, conversionId, model, touchpoints, totalValuePer-conversion multi-touch attribution result. model is the attribution model name (e.g. linear, time_decay) (schema line 973).
Geofencegeofenceslatitude, longitude, radiusMeters, triggerOn (enter/exit/dwell), actionPer-tenant geofence — fires action.type (recommend/notify) when a customer crosses (schema line 2036).
Tenant regiontenant_regionstenantId (PK), region, primary, failoverRegionPer-tenant region tag for active-active routing (W18) (schema line 2292).

AI & imports

Conversation ledger, AI recommendations, and the AI document import pipeline (V1).
Model@@mapKey FieldsRelationsPurpose
ConversationconversationsuserId, titletenant, user, message childrenOne AI assistant conversation per (tenant, user) (schema line 1807).
Conversation messageconversation_messagesconversationId, role, content, toolInvocationsparent conversationSingle message in a conversation. toolInvocations is the tool-call/result trace (schema line 1824).
AI recommendationai_recommendationstype (policy/rule/segment/content), title, payload, confidence, source (llm/ml_worker), statusPending AI suggestion that can be applied as an entity (schema line 1726).
AI customer segmentcustomer_segments_ainame, filterRules, schemaId, size, percentage, characteristics, suggestedUseAI-generated customer segment proposal — separate from the user-defined segment table (schema line 1785).
Creative performancecreative_performancecreativeId, channelId, offerId, impressions, clicks, conversions, revenue, periodStart, periodEndPre-aggregated creative-level performance window for AI content analysis (schema line 1764).
AI attachment (no @@map)(model-name table)conversationId, originalFilename, mimeType, sha256, storageKey, pageCount, tokensUsed, estimatedTokens, statusUploaded document (PDF/PPTX) for AI document import. Dedup by [tenantId, sha256] (schema line 2170).
AI import proposal (no @@map)(model-name table)attachmentId, entityType, extractedName, extractedFields, sourcePageNumber, sourceQuote, dedupeMatchId, dedupeStrategy, verdictTyped proposal extracted from an attachment with page citations (schema line 2196).
AI import apply (no @@map)(model-name table)attachmentId, conversationId, appliedById, createdEntityIds, mergedEntityIds, skippedProposalIds, status, revertedAtAtomic apply ledger — records what was created/merged/skipped per import. Soft-revert via revertedAt (schema line 2217).
AI import token ledger (no @@map)(model-name table)tenantId, yearMonth, tokensUsedPer-tenant per-month LLM token spend for AI document import (schema line 2233).
AI import skip digest (no @@map)(model-name table)digest, entityType, extractedNameSkip-tally bookkeeping — remembers proposals the operator dismissed so re-imports don’t re-surface them (schema line 2243).
Negotiation sessionnegotiation_sessionscustomerId, offerId, state, status (active/accepted/rejected/expired)Multi-turn negotiation state (W15). The state column deserializes to the multi-turn session shape used by the negotiation runtime (schema line 2320).

Journeys

Multi-step customer journey orchestration — entry conditions, step definitions, and per-customer enrollment state.
Model@@mapKey FieldsRelationsPurpose
Journeyjourneysname, definition (journey definition JSON), entryCondition, maxDurationDaysenrollment childrenVisual journey definition — steps, branches, wait/decision/action nodes. definition is the full DAG (schema line 1349).
Journey enrollmentjourney_enrollmentsjourneyId, customerId, currentStepId, status (active/completed/exited), enteredAt, lastStepAt, historyparent journeyPer-customer enrollment state. history is the chronological list of visited steps (schema line 1368).

Flow & pipeline

Data ingestion, schema management, and pipeline runtime.
Model@@mapKey FieldsRelationsPurpose
Connectorconnectorstype (54 registered types), config, authMethod, authConfig, status, lastTestedAt, lastErrorpipeline childrenExternal data source connection (S3, Snowflake, Kafka, Salesforce, etc.). The full connector registry is exposed via the Connectors API (schema line 501).
Data schemadata_schemasname, tableName (ds_*), entityType, schemaType, linkedSchemaId, joinMapping, summaryColumns, autoEnrichfield children, pipeline children, segment childrenDefines an entity (customer, account, custom). Creates a real Postgres table named ds_{name} (schema line 445).
Schema fieldschema_fieldsname, dataType, length, precision, scale, isNullable, isPrimaryKey, isUnique, isPredictor, defaultValueparent data schemaTyped column on a data schema. isPredictor=true exposes the field to ML model training. isPrimaryKey=true skips the auto-generated id BIGSERIAL column at table creation — use this when your data has its own natural key (e.g. customer_id). The schema-create form has an inline “Custom primary key column” pane: filling it makes that column the PK and avoids the auto id entirely. Schemas without any user-defined PK still get the auto id column. (schema line 476)
Schema joinschema_joinsprimarySchemaId, primaryKey, foreignSchemaId, foreignKey, joinType (left/inner), autoEnrichAuto-enrichment join definition between two data schemas. Used by the runtime to widen customer rows (schema line 2016).
Data sourcedata_sourcesconnectorKey, sourceConfig, fileFormat, syncMode (full_refresh/incremental_append/incremental_dedupe/cdc), schedule, schemaKeyA logical source bound to a connector. Schedules + sync mode drive the pipeline runner (schema line 716).
PipelinepipelinesconnectorId, schemaId, irVersion (always "1.0"), executionConfig, lastRunStatusparent connector, data schema, run childrenIR-native pipeline. The DAG is in the pipeline IR version row (JSONB) — there is no per-node or per-edge table anymore (schema line 525).
Pipeline IR versionpipeline_ir_versionspipelineId, version, ir, authoredBy (user id or "ai"), commentVersion-controlled pipeline IR document. version is monotonically increasing per pipeline (schema line 550).
Pipeline runpipeline_runspipelineId, status, rowsProcessed, rowsTotal, rowsFailed, validationErrors, loadStrategy (append/truncate/upsert/blue_green), partitions, lastProcessedRowparent pipelineSingle pipeline execution record. lastProcessedRow is the resume checkpoint (schema line 1091).

Content

Reusable content templates, CMS-sync content items, and template inheritance.
Model@@mapKey FieldsRelationsPurpose
Templatetemplatescategory (email/push/sms/blueprint/offer), type, content, variables, isSystemReusable template — including system-shipped seeds when isSystem=true (schema line 1489).
Content item (no @@map; inferred model-name table)(model-name table)name, channelType, status (draft/in_review/approved/published/archived), parentTemplateId, sourceType (internal/wordpress/contentful/strapi/sanity), versionoptional parent and child content items, optional content source, version children, creative childrenChannel-typed content payload. CMS-synced when sourceType != "internal" (schema line 1510).
Content version (no @@map)(model-name table)contentItemId, version, content, blocks, personalization, changedBy, changeNoteparent content itemImmutable historical snapshot of a content item (schema line 1545).
Content source (no @@map)(model-name table)provider (wordpress/contentful/strapi/sanity), config, syncMode (webhook/polling), autoPublish, mappings, webhookSecretcontent-item childrenExternal CMS connection — pulls content into content-item rows (schema line 1562).
Treatmenttreatmentsname, channel, subject, headline, body, config, impressions, clicks, conversionsAI-generated content entity — separate table from creatives (schema line 1921).

Reports

Scheduled report templates, schedules, and execution runs.
Model@@mapKey FieldsRelationsPurpose
Report templatereport_templatesdataSources, sections, formats (default ["pdf"]), narrative ({enabled, prompt?, modelOverride?}), filters, enabledComposable report definition. Reusable across schedules (schema line 2103).
Report schedulereport_schedulestemplateId, cronExpression, timezone, destinations, lastRunAt, nextRunAt, lastStatusCron schedule binding a template to delivery destinations (schema line 2123).
Report runreport_runstemplateId, scheduleId, triggeredBy (default cron), sectionsData, narrativeOutput, artifactPayloads, deliveryResultsPer-execution audit row. Artifact payloads are inlined; the runner documents an S3 upgrade path (schema line 2143).

Behavioral metrics & summaries

User-defined metrics evaluated against the interaction stream.
Model@@mapKey FieldsRelationsPurpose
Metric definitionmetric_definitionsaggregateFunction (count/sum/avg/min/max/ratio), sourceField, windowDays (max 365), groupByDimensions (max 2), filterConditions, sqlFilter (max 500 chars), computeMode (realtime/batch), batchIntervalMinmetric-value childrenUser-defined behavioral metric. Compiled into a query against the interaction-summary table (schema line 1641).
Metric valuemetric_valuesmetricId, customerId, dimensionKey, value, computedAtparent metric definitionMaterialized per-customer × dimension value. Unique on [tenantId, metricId, customerId, dimensionKey] (schema line 1670).
Summary definitionsummary_definitionsdimensions, aggregates (default ["count"]), windows (default ["7d","30d"]), isSystemPluggable shape for interaction-summary aggregation. isSystem=true rows are undeletable (schema line 1860).

Configuration

Prisma 7 datasource split

// platform/prisma/schema.prisma — datasource block
datasource db {
  provider = "postgresql"
}
// platform/prisma.config.ts — connection URL
import "dotenv/config";
import { defineConfig } from "prisma/config";

export default defineConfig({
  schema: "prisma/schema.prisma",
  migrations: { path: "prisma/migrations" },
  datasource: { url: process.env["DATABASE_URL"]! },
});
The url field is illegal inside the schema file under Prisma 7. The connection URL is read from DATABASE_URL by the Prisma config and passed to the generated client.

ds_* tables created outside the schema

Data-schema rows do not declare their column shape inside the Prisma schema. Each row holds metadata; the actual ds_{name} table is created at runtime by the platform’s DDL helper via CREATE TABLE statements when the schema is published. Adding a schema field issues ALTER TABLE ds_{name} ADD COLUMN. This split exists because the column shape is per-tenant and dynamic — it cannot be declared statically in a global schema. Operators viewing \d ds_* in psql will see real Postgres tables that are not represented in the Prisma schema.

Manual SQL for partitioning and migrations

Schema changes that Prisma cannot express are stored in the manual-sql directory under the Prisma folder:
FilePurpose
01_registry_status_check.sqlAdds CHECK constraint to algorithm_models.registryStatus
02_flow_ir_phase1.sqlInitial flow IR table grants
04_drop_legacy_pipeline_tables.sqlDrops legacy pipeline_nodes + pipeline_edges (2026-04-28)
05_campaign_id_additive.sqlAdds nullable campaignId to interaction_history + interaction_summaries
06_customer_engagement_health.sqlBootstrap for the customer-engagement-health table
07_flow_run_checkpoints.sqlPer-tenant flow checkpoint storage
08_ai_import.sqlAI document import bootstrap
09_parity_w11_to_w19.sqlW11–W19 parity-sprint additions
Run these in numerical order against any database that pre-dates them. Production databases run them through CI; local databases need a manual psql -f or prisma db execute --file.

Honest limits

  • ds_* tables are not in the Prisma schema. The dynamic per-tenant entity tables created from data-schema rows live outside the schema file. There is no way to type-check them through Prisma — runtime queries against ds_{name} go through raw SQL or generated query builders.
  • Interaction history is partitioned in production. The model declares one logical table; production deployments range-partition interaction_history by month, which is why /recommend writes use prisma.$executeRaw instead of prisma.createMany({ skipDuplicates }). The Prisma model does not declare partitioning.
  • Soft-delete is not Prisma-enforced. Models with deletedAt rely on every API route to filter where: { deletedAt: null }. There is no global Prisma middleware enforcing this — a raw query or a route that forgets the filter will return soft-deleted rows.
  • Cross-offer constraints have no UI surface yet. The model is wired into Lagrangian arbitration in both realtime and batch decisioning paths via the cross-offer arbitration helper, but rows must be inserted directly via SQL or a future admin API — there is no Studio UI for editing them today.
  • Some operator-internal tables have no public API surface. The transactional outbox, dead-letter store, channel-delivery ledger, export checkpoints, ML job results, AI-import token ledger, AI-import skip digest, policy snapshots, approval-request stages, custom-role assignments, NextAuth verification tokens, WebAuthn credentials, the per-tenant region tag, model-adaptation rows, and customer-engagement-health rollups are read/written by internal code paths only — there is no /api/v1/{model} REST surface for them.
  • Several alternate storage backends are referenced but not declared here. ScyllaDB / DynamoDB / OpenSearch backends mentioned in Scaling are write paths inside platform adapters; their row shapes are not declared in the Prisma schema. Treat the Prisma schema as the authoritative shape for the canonical Postgres path only.
  • AI import models and content models lack @@map directives. Their Postgres table names default to the model name as written rather than snake_case — verify via \dt in psql.