Skip to content

Data Model

85 Prisma models and 8 enums in a single schema at libraries/nestjs-libraries/src/database/prisma/schema.prisma. This page lists every model grouped by domain with a one-line purpose and key relationships.


Core Identity, RBAC & Sessions (9)

ModelPurposeKey Relationships
OrganizationTenant — every resource belongs to an orgFK to Subscription; has many Integration, UserOrganization, Post, Campaign
UserIdentity/auth only — email, password, providerName/providerId, isSuperAdmin, activated, last-online telemetryUnique on (email, providerName); has one UserProfile, many Session, UserOrganization
UserProfile1:1 profile split off from User — name, lastName, bio, avatarUrl (provider/Gravatar), pictureId (uploaded), IANA timezone, notification prefsFK → User (unique, cascade), File (picture)
SessionLogin session backing refresh-token rotation — tokenHash (sha256 of the refresh token, rotated on every use), previousTokenHash (last rotated-out hash; reusing it revokes the session), userAgent/ip, expiresAt, revokedAtFK → User (cascade)
UserOrganizationMany-to-many join between users and orgs. roleIdAppRole is the role pointer.FK → Organization, User, AppRole (nullable roleId)
AppRoleRBAC role. Org-scoped when organizationId is set; NULL org = seeded system role (owner/admin/editor/member/viewer, isSystem: true)FK → Organization (nullable); has many AppRolePermission, UserOrganization
PermissionFine-grained (resource, action) capability — 18 resources × 5 actions = 90 seededUnique on (resource, action); has many AppRolePermission
AppRolePermissionJoin table linking roles to permissionsComposite PK (roleId, permissionId); cascade on both
AuthProviderConfigPlatform-wide login provider config (managed by the separate administration app — this repo ships no /admin frontend and reads it DB-first) — client ID/secret encrypted, OIDC endpoints, enabled flag. Env vars remain the bootstrap fallback.Unique on (provider, version)

Org Content Helpers (11)

ModelPurposeKey Relationships
TagsPer-org color-coded tags for postsFK → Organization; has many TagsPosts
TagsPostsMany-to-many join between posts and tagsFK → Post, Tags
SetsNamed, reusable post templates (serialized composer payload)FK → Organization
SignaturesPer-org post signatures — content, channel scope (channels[]), auto-add, usage count, optional logo/stickerFK → Organization, FK → File (pictureId)
NotificationsPer-org notification feed entriesFK → Organization
NotificationReadPer-user read state for notification feed entriesFK → Notifications, User
NotificationPreferencePer-user master channel toggles + category toggles for Notifications V2FK → User (unique)
NotificationDigestQueueQueued digest entries waiting to be flushedFK → User, Organization
PushTokenMobile/push notification tokens per userFK → User
ErrorsPost-publish errors with platform and messageFK → Organization, Post
AnnouncementSystem-wide announcements (info/warning/error)Standalone

Media (12)

ModelPurposeKey Relationships
FileUploaded media files (image/video/audio), with path, type, thumbnail, tags, and metadata Json? (dimensions, duration, model, provenance)FK → Organization, FileFolder
ContentPackConfigPer-org premium content-pack (stock) provider config — encrypted credentials + provider extraConfig; the active pack is pointed to by Organization.activeContentPackIdentifierFK → Organization
FileFolderFolder tree for organizing files, supports cloud-store mountingFK → Organization, parent FileFolder, StorageProviderConfig
StorageProviderConfigPer-org cloud storage config (S3, R2, B2, IDrive E2, LOCAL, and many S3-compatible backends). accountFingerprint enforces unique account per org.FK → Organization; has many FileFolder, MediaProviderConfig
MediaProviderConfigPer-org AI media-generation provider config — encrypted credentials, storage binding (storageProviderId, null = LOCAL; storageRootFolderId)FK → Organization, StorageProviderConfig (nullable); unique on (organizationId, identifier, version)
MultipartUploadTracks ownership and state of multipart S3 uploadsFK → Organization
DesignEditable Designer (Konva) document — doc JSON, dimensions, previewFK → Organization, User, Campaign; preview File
DesignTemplateSystem-seeded or org-saved templates for the Designer Templates panelFK → Organization (nullable); thumbnail File
AiDesignerSessionPersistent chat thread for the AI Designer (/media/ai-designer)FK → Organization, User; has many AiDesignerMessage
AiDesignerMessagePersisted chat/form/plan/media/progress payloads for an AI Designer sessionFK → AiDesignerSession
PopularPostsCurated popular post templates (category + topic + content + hook)Standalone
MentionsCross-platform mention trackingStandalone

Channel Integrations (5)

ModelPurposeKey Relationships
IntegrationConnected social/chat channel with encrypted OAuth tokensFK → Organization, Customer; has many Post, Plugs, AnalyticsSnapshot
PlugsInstalled plug functions (analytics, comments, etc.) per integrationFK → Organization, Integration
WebhooksPer-org webhook URLs (outbound notifications)FK → Organization; implicit many-to-many with Integration
AutoPostRSS/feed-based auto-posting configurationFK → Organization
CustomerBilling customer name per orgFK → Organization

Provider Configuration (3)

ModelPurposeKey Relationships
OrgProviderConfigurationPer-org channel provider OAuth credentials (encrypted). Many named sets per provider — unique on (organizationId, identifier, name, version); resolved by row id.FK → Organization; back-ref → Integration[]
OrgVpnConfigPer-org VPN/proxy provider config (Settings → VPN) — encrypted credentials, enabled regions JSON; SOCKS5/HTTP-CONNECT proxies power per-channel VPN egressFK → Organization
FeaturedProviderPlatform-wide curated featured-provider list surfaced at the top of each domain's provider configuration UIUnique on (domain, providerId)

A connected Integration carries a nullable providerConfigId FK (onDelete: SetNull) binding it to the named credential set it was connected through, so OAuth handshake, token refresh, and API calls use that set's own auth. Connect flows always bind a named config; API-key connect flows without one resolve the platform env OAuth-app credentials only.


Posts & Content (3)

ModelPurposeKey Relationships
PostScheduled/social post — content, state (QUEUE/PUBLISHED/ERROR/DRAFT/PUBLISHING), publish date, media, settings, campaign, optional brandId (per-post brand voice)FK → Organization, Integration, Campaign, AIBrandProfile (nullable brandId); self-referential parentPost for threads
CommentsInternal team comments on postsFK → Organization, Post, User
MentionsCross-platform mention trackingComposite PK (name, username, platform, image)

Analytics (7)

ModelPurposeKey Relationships
AnalyticsSnapshotDaily per-integration metric snapshot (views, likes, followers, etc.)FK → Integration
PostAnalyticsSnapshotDaily per-post metric snapshotFK → Post, Integration
WatchedAccountCompetitor/watchlist account being trackedFK → Organization; has many WatchedAccountMetric
WatchedAccountMetricIndividual metric reading for a watched accountFK → WatchedAccount
AnalyticsAnomalyPersisted metric anomaly (spike/drop) for idempotent Inngest retries and dashboard alertsFK → Integration
AnalyticsAlertRuleUser-defined alert rule evaluated by the daily sweepFK → Organization, Integration (nullable)
AnalyticsShareOrg-level public share dashboard config + tokenFK → Organization (unique)

Social Comments (2)

ModelPurposeKey Relationships
SocialCommentSynced platform comment — author, content, sentiment, status, assignmentFK → Post, Integration, Organization, User (assignee)
PostCommentReadPer-user per-post last-read cursor for social commentsFK → User, Post

AI (10)

ModelPurposeKey Relationships
AIOrgProviderConfigPer-org AI provider + encrypted credentials + defaultModel and reasoningModelFK → Organization
AISpendLogCost ledger — input/output tokens, cost, provider, model, scopeFK → Organization (nullable), User (nullable)
AIBrandProfileBrand voice instructions + language + brand kit (palette, fontFamilies, logoFileIds, enforcement, assets[]). Many per org (name, isDefault, slug); one default per org, selectable per-post via Post.brandId.FK → Organization; has many Post
AIPromptTemplateEditable prompt templates (org-scoped or global, with key)FK → Organization (nullable)
AISettingsAuditAppend-only audit of AI-settings changesFK → User (nullable)
AIMediaJobMedia pipeline job — operation, status, artifact URL, provenance, cost. Tracks async media generation (video/audio/avatar/stt) in the media-provider system.FK → Organization, User (nullable)
AIPromptLibraryItemUser-created reusable prompt library entriesFK → Organization
AIContentIndexRAG index — chunk metadata + BM25 text; embeddings in side tableFK → Organization
AISystemSettingsLive instance-wide AI governance store — fallback providers, guardrails, budget, observability, MCP, RAG, cache, routing, and secret settingsStandalone
OrgDefaultModelPer-org per-domain/category default model/media settings (domain, category, providerId, version, model, settings)Unique on (organizationId, domain, category)

ModelPurposeKey Relationships
OrgShortLinkConfigPer-org short-link provider config — provider type, API credentials (encrypted), custom domain, active flag. Multi-account: name + accountFingerprint with unique on (organizationId, identifier, version, accountFingerprint).FK → Organization
ShortLinkLedger of generated short links — original URL, short URL, provider, post referenceFK → Organization, Post (nullable)
ShortLinkSnapshotDaily click-count snapshot per short link, collected by the analytics sweepFK → ShortLink

Campaigns (4)

ModelPurposeKey Relationships
CampaignGrouping folder for posts — name, color, date range, archive state, goals, public-share token/settings, UTM toggleFK → Organization; has many Post, CampaignNote, CampaignItem, Design
CampaignItemPolymorphic tagged item (entityType + entityId) linking a campaign to one of 9 non-post entity typesFK → Campaign
CampaignNoteInternal Discussion thread note — sanitized rich HTML content, parentId (one-level threading), mentions (JSON userId[]), pinned, resolvedAt, editedAt, soft deletedAtFK → Campaign; self-FK parent/replies; has many CampaignNoteReaction
CampaignNoteReactionEmoji reaction on a note, toggledFK → CampaignNote; unique (noteId, userId, emoji)

Post carries approvalStatus / approvedById / approvedAt for the campaign draft-approval flow, and Campaign.utmEnabled drives automatic UTM append on publish.


OAuth (2)

ModelPurposeKey Relationships
OAuthAppOAuth 2.0 application registration (client credentials, redirect URL)FK → Organization, File (picture)
OAuthAuthorizationOAuth authorization grant — PKCE, scopes, encrypted tokens, expiry, revocationFK → OAuthApp, User, Organization

Billing (5)

ModelPurposeKey Relationships
SubscriptionBilling subscription — tier, period, channel count, lifetime flag, add-on storage/video exportsFK → Organization (unique)
StripeEventDeduplication ledger for Stripe webhooksUnique on id (the Stripe event id)
CustomerBilling customer name per orgFK → Organization
CreditsAI credit balance per org (type: ai_images/ai_videos)FK → Organization
UsedCodesUsed promo/referral codes per orgFK → Organization

API Keys (1)

ModelPurposeKey Relationships
ApiKeyPer-user per-org hashed API keys (pm_live_*, sha256-stored, show-once)FK → User, Organization

Mastra Telemetry (6)

All 6 models are managed by the Mastra framework. They are not accessed through Prisma repositories — Mastra manages its own tables.

ModelPurpose
mastra_messagesAgent messages
mastra_resourcesAgent resources/working memory
mastra_scorersScoring/evaluation runs
mastra_threadsConversation threads
mastra_tracesTrace data for observability
mastra_workflow_snapshotWorkflow state snapshots

Miscellaneous (4)

ModelPurposeKey Relationships
AuditLogDB-backed audit log for credential and storage mutationsFK → Organization
EmailLogEmail send-log metadata (no body). Lifecycle: queued → sent → delivered/bounced/complained/opened/clickedIndexed on (provider, providerMessageId), sentAt, status
MigrationLedgerInternal migration bookkeepingUnique on key
InngestFunctionRunLatest run timing/status per Inngest cron function for /healthUnique on functionId

Enums

EnumValues
StateQUEUE, PUBLISHED, ERROR, DRAFT, PUBLISHING
CampaignEntityTypePOST, INTEGRATION, ORG_VPN_CONFIG, AI_ORG_PROVIDER_CONFIG, AI_BRAND_PROFILE, STORAGE_PROVIDER_CONFIG, FILE, SETS, SIGNATURES
SubscriptionTierSTARTER, PRO, TEAM, AGENCY
ProviderLOCAL, GITHUB, GOOGLE, FARCASTER, WALLET, GENERIC
ShortLinkPreferenceASK, YES, NO
CreationMethodUNKNOWN, WEB, MCP, API, AUTOPOST, CLI
StorageProviderTypeLOCAL, S3, CLOUDFLARE_R2, BACKBLAZE_B2, IDRIVE_E2, WASABI, DIGITALOCEAN_SPACES, HETZNER, STORJ, SCALEWAY, VULTR, LINODE, S3_COMPATIBLE, MEDIALOCKER
AnnouncementColorINFO, WARNING, ERROR

MEDIALOCKER was added to StorageProviderType additively by migration 20260714150606_add_medialocker_storage_type (ALTER TYPE ... ADD VALUE — backward-compatible, no data rewrite).

Verified against v1.0.0

The AI-native social media management platform — postmill.ai