Skip to content

Instantly share code, notes, and snippets.

@hnordt
Last active February 13, 2026 20:10
Show Gist options
  • Select an option

  • Save hnordt/4ee218ed67df7e8ddb8d9ea5684e2989 to your computer and use it in GitHub Desktop.

Select an option

Save hnordt/4ee218ed67df7e8ddb8d9ea5684e2989 to your computer and use it in GitHub Desktop.
Use a Structural UML Diagram to Improve AI Code Generation (https://x.com/hnordt/status/2022402880733315372)

Model

This file defines the structural abstraction of the system. It includes the main entities, their attributes, relationships, and key operations. The model serves as a blueprint for implementation and guides the design of the database schema, API endpoints, and business logic.

classDiagram
  class Workspace {
    +int id
    +string name
    +datetime createdAt
    +datetime updatedAt
  }

  class User {
    +int id
    +int workspaceId
    +string name
    +string email
    +datetime createdAt
    +datetime updatedAt
    +me()
  }

  class Contact {
    +int id
    +int workspaceId
    +string name
    +string company
    +string segment
    +string role
    +string phone
    +string city
    +string state
    +datetime createdAt
    +datetime updatedAt
    +list()
    +get()
    +create()
    +update()
    +merge()
    +setScore()
    +getQualification()
    +setQualification()
    +templateDownload()
    +contactsUpload()
    +contactsExcel()
  }

  class ContactPin {
    +int id
    +int workspaceId
    +int userId
    +int contactId
    +int slot
    +datetime createdAt
    +datetime updatedAt
    +list()
    +set()
    +clear()
  }

  class ContactQualification {
    +int id
    +int workspaceId
    +int userId
    +int contactId
    +string kindKey
    +int score
    +datetime createdAt
    +datetime updatedAt
  }

  class ContactScore {
    +int id
    +int workspaceId
    +int userId
    +int contactId
    +string sourceKey
    +int value
    +datetime createdAt
    +datetime updatedAt
  }

  class Pipeline {
    +int id
    +int workspaceId
    +string name
    +datetime createdAt
    +datetime updatedAt
    +list()
  }

  class Stage {
    +int id
    +int workspaceId
    +int pipelineId
    +string name
    +int sortIndex
    +datetime updatedAt
  }

  class Deal {
    +int id
    +int workspaceId
    +int contactId
    +int pipelineId
    +int stageId
    +string statusKey
    +datetime createdAt
    +datetime updatedAt
    +create()
    +changeStage()
    +markWon()
    +markLost()
  }

  class Conversation {
    +int id
    +int workspaceId
    +string kindKey
    +string statusKey
    +datetime createdAt
    +datetime updatedAt
    +get()
    +openForContact()
    +openDirect()
    +setStatus()
    +setScore()
  }

  class ConversationParticipant {
    +int id
    +int workspaceId
    +int conversationId
    +string actorKindKey
    +int userId
    +int contactId
    +datetime createdAt
    +datetime updatedAt
  }

  class ConversationQualification {
    +int id
    +int workspaceId
    +int userId
    +int conversationId
    +string sourceKey
    +string kindKey
    +int score
    +datetime createdAt
    +datetime updatedAt
  }

  class ConversationScore {
    +int id
    +int workspaceId
    +int userId
    +int conversationId
    +string sourceKey
    +int value
    +datetime createdAt
    +datetime updatedAt
  }

  class Message {
    +int id
    +int workspaceId
    +int conversationId
    +string authorKindKey
    +int authorUserId
    +int authorContactId
    +string channelKey
    +string kindKey
    +string body
    +string payloadJson
    +string externalId
    +datetime createdAt
    +datetime updatedAt
    +list()
    +listUnread()
    +markRead()
    +markReadBatch()
    +send()
    +ingestInbound()
  }

  class MessageAttachment {
    +int id
    +int workspaceId
    +int messageId
    +string kindKey
    +string url
    +string fileName
    +int sizeBytes
    +datetime createdAt
    +datetime updatedAt
  }

  class MessageReceipt {
    +int id
    +int workspaceId
    +int userId
    +int messageId
    +string statusKey
    +datetime createdAt
    +datetime updatedAt
  }

  class Delivery {
    +int id
    +int workspaceId
    +int messageId
    +string statusKey
    +string providerMessageId
    +string errorCode
    +string errorMessage
    +datetime updatedAt
    +retry()
    +updateFromProvider()
  }

  class Call {
    +int id
    +int workspaceId
    +int conversationId
    +int startedByUserId
    +int startedByContactId
    +string channelKey
    +string kindKey
    +string statusKey
    +datetime startedAt
    +datetime endedAt
    +string payloadJson
    +datetime createdAt
    +datetime updatedAt
    +list()
    +start()
    +ingestInbound()
    +updateStatus()
    +end()
  }

  class Event {
    +int id
    +int workspaceId
    +string typeKey
    +string entityTypeKey
    +int entityId
    +int actorUserId
    +string payloadJson
    +datetime createdAt
    +counters()
    +performance()
  }

  class Job {
    +int id
    +int workspaceId
    +int createdByUserId
    +string kindKey
    +string statusKey
    +string inputJson
    +string resultJson
    +string fileUrl
    +datetime createdAt
    +datetime startedAt
    +datetime finishedAt
    +datetime updatedAt
    +get()
  }

  class ChannelAdapter {
    <<abstract>>
    +sendMessage()
    +ingestInboundMessage()
    +startCall()
    +ingestInboundCall()
    +updateDelivery()
  }

  class JobRunner {
    <<abstract>>
    +enqueue()
    +run()
    +retry()
  }

  class EventLog {
    <<abstract>>
    +append()
    +listByEntity()
  }

  class Qualifier {
    <<abstract>>
    +classifyContact()
    +overrideContactQualification()
  }

  Workspace "1" --> "*" User : has
  Workspace "1" --> "*" Contact : has
  Workspace "1" --> "*" ContactPin : has
  Workspace "1" --> "*" ContactQualification : has
  Workspace "1" --> "*" ContactScore : has
  Workspace "1" --> "*" Pipeline : has
  Workspace "1" --> "*" Stage : has
  Workspace "1" --> "*" Deal : has
  Workspace "1" --> "*" Conversation : has
  Workspace "1" --> "*" ConversationParticipant : has
  Workspace "1" --> "*" ConversationQualification : has
  Workspace "1" --> "*" ConversationScore : has
  Workspace "1" --> "*" Message : has
  Workspace "1" --> "*" MessageAttachment : has
  Workspace "1" --> "*" MessageReceipt : has
  Workspace "1" --> "*" Delivery : has
  Workspace "1" --> "*" Call : has
  Workspace "1" --> "*" Event : has
  Workspace "1" --> "*" Job : has

  Contact "1" --> "*" ContactPin : pinned
  Contact "1" --> "*" ContactQualification : qualifiedBy
  Contact "1" --> "*" ContactScore : scoredBy
  Contact "1" --> "*" Deal : has
  Contact "1" --> "*" ConversationParticipant : participates

  Pipeline "1" --> "*" Stage : includes
  Pipeline "1" --> "*" Deal : uses
  Stage "1" --> "*" Deal : in

  Conversation "1" --> "*" ConversationParticipant : has
  Conversation "1" --> "*" ConversationQualification : qualifiedBy
  Conversation "1" --> "*" ConversationScore : scoredBy
  Conversation "1" --> "*" Message : contains
  Conversation "1" --> "*" Call : contains

  Message "1" --> "*" MessageAttachment : has
  Message "1" --> "*" MessageReceipt : tracks
  Message "1" --> "*" Delivery : tracks

  User "1" --> "*" ContactPin : sets
  User "1" --> "*" ContactQualification : sets
  User "1" --> "*" ContactScore : sets
  User "1" --> "*" ConversationParticipant : participates
  User "1" --> "*" ConversationQualification : sets
  User "1" --> "*" ConversationScore : sets
  User "1" --> "*" MessageReceipt : recipient
  User "1" --> "*" Event : actor
  User "1" --> "*" Job : creates

  Contact ..> ContactQualification : set/get qualification
  Contact ..> ContactScore : set score
  Conversation ..> ConversationParticipant : manage participants
  Conversation ..> ConversationScore : set score
  Message ..> MessageReceipt : unread/read
  Message ..> Delivery : send/track

  ChannelAdapter ..> Message : message channel adapters
  ChannelAdapter ..> Call : call channel adapters
  ChannelAdapter ..> Delivery : provider status updates
  JobRunner ..> Job : background work state
  JobRunner ..> Contact : contact import/export
  JobRunner ..> Delivery : message delivery
  JobRunner ..> ContactQualification : AI classification outputs
  EventLog ..> Event : append-only events
  Qualifier ..> ContactQualification : contact qualification

  note for Workspace "Workspace: tenant boundary for data and permissions."
  note for User "User: CRM member who sends messages and manages contacts."
  note for Contact "Contact: person/company; participates in conversations and owns deals."
  note for ContactPin "Pin: user-priority contact slot (max 5 in UI)."
  note for ContactQualification "Contact Qualification: category assignment for contact."
  note for ContactScore "Contact Score: 1-5 rating assigned to a contact."
  note for Pipeline "Pipeline: named set of deal stages."
  note for Stage "Stage: step in a pipeline for deal position."
  note for Deal "Deal: sales opportunity linked to a contact."
  note for Conversation "Conversation: thread with participants (contact or direct), contains messages/calls."
  note for ConversationParticipant "Conversation Participant: actor membership entry for conversation (user or contact)."
  note for ConversationScore "Conversation Score: 1-5 rating assigned to a conversation."
  note for Message "Message: authored communication item with channel, kind, body. Author invariant: user => authorUserId set and authorContactId null; contact => authorContactId set and authorUserId null; system => both null."
  note for MessageAttachment "Attachment: media metadata plus file reference."
  note for MessageReceipt "Message Receipt: per-user read state for message: unread/read."
  note for Delivery "Delivery: outbound provider delivery tracking and error details."
  note for Call "Call: communication record with channel, kind, status, timestamps."
  note for Event "Event: immutable audit/timeline/metrics record."
  note for Job "Job: background task record (delivery, classify, import, export)."

  note for Message "Message keys: authorKind(user/contact/system), channel(internal/email/sms/whatsapp/telegram), kind(text/media)."
  note for Delivery "Delivery status: queued/sent/delivered/read/failed."
  note for Call "Call keys: channel(internal/whatsapp/telegram/phone), kind(voice/video), status(initiated/ringing/connected/ended/missed/failed)."
  note for Deal "Deal status: open/won/lost."
  note for Job "Job status: queued/running/succeeded/failed. Job kind: deliver_message/classify_conversation/import_contacts/export_contacts."
  note for ChannelAdapter "Normalize inbound webhooks and send outbound messages/calls per channel."
  note for JobRunner "Runs delivery, AI classification, import, and export using job kind keys."
  note for EventLog "Append-only event stream used for audit, timelines, counters, and performance metrics."
  note for Qualifier "Applies qualification keys and allows user overrides on the latest value."
Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment