package domain import ( "crypto/rand" "encoding/hex" "fmt" "regexp" "strings" "time" ) // NewID generates a readable prefixed ID as specified in BRAIN.md (e.g. th_4x8z19a0b1) func NewID(prefix string) string { b := make([]byte, 5) _, _ = rand.Read(b) return fmt.Sprintf("%s_%s", prefix, hex.EncodeToString(b)) } // NowISO returns the current UTC timestamp in ISO-8601 format func NowISO() string { return time.Now().UTC().Format(time.RFC3339) } var hashtagRegex = regexp.MustCompile(`#([a-zA-Z0-9äöüÄÖÜß_-]+)`) // ExtractTags extracts #hashtags from content func ExtractTags(content string) []string { matches := hashtagRegex.FindAllStringSubmatch(content, -1) seen := make(map[string]bool) tags := make([]string, 0, len(matches)) for _, m := range matches { if len(m) > 1 { tag := strings.ToLower(m[1]) if !seen[tag] { seen[tag] = true tags = append(tags, tag) } } } return tags } type User struct { ID string `json:"id"` Email string `json:"email"` PasswordHash string `json:"-"` DisplayName string `json:"displayName"` CreatedAt string `json:"createdAt"` } type ThoughtStatus string const ( StatusInbox ThoughtStatus = "inbox" StatusKept ThoughtStatus = "kept" StatusDiscarded ThoughtStatus = "discarded" StatusConverted ThoughtStatus = "converted" ) type Thought struct { ID string `json:"id"` UserID string `json:"userId"` Content string `json:"content"` Tags []string `json:"tags"` Priority string `json:"priority"` // low | normal | high | urgent Source string `json:"source"` // manual | voice | webhook Status ThoughtStatus `json:"status"` IsCompleted bool `json:"isCompleted"` ConvertedType string `json:"convertedType,omitempty"` // task | document | list_item ConvertedRefID string `json:"convertedRefId,omitempty"` // referenced entity ID DueDate string `json:"dueDate,omitempty"` CreatedAt string `json:"createdAt"` TriagedAt string `json:"triagedAt,omitempty"` } type DocumentBlock struct { ID string `json:"id"` Type string `json:"type"` // h1 | h2 | h3 | paragraph | todo | bullet | code | callout | divider Content string `json:"content"` Checked bool `json:"checked,omitempty"` Lang string `json:"lang,omitempty"` } type Document struct { ID string `json:"id"` UserID string `json:"userId"` SpaceID string `json:"spaceId,omitempty"` Title string `json:"title"` Icon string `json:"icon"` Content string `json:"content"` Blocks []DocumentBlock `json:"blocks"` Tags []string `json:"tags"` IsPinned bool `json:"isPinned"` IsArchived bool `json:"isArchived"` CreatedAt string `json:"createdAt"` UpdatedAt string `json:"updatedAt"` } type SpaceMember struct { SpaceID string `json:"spaceId"` UserID string `json:"userId"` DisplayName string `json:"displayName"` Email string `json:"email"` Role string `json:"role"` // owner | editor | viewer JoinedAt string `json:"joinedAt"` } type Space struct { ID string `json:"id"` Name string `json:"name"` Icon string `json:"icon"` Description string `json:"description"` InviteCode string `json:"inviteCode"` IsPersonal bool `json:"isPersonal"` OwnerID string `json:"ownerId"` Members []SpaceMember `json:"members,omitempty"` ListsCount int `json:"listsCount"` CreatedAt string `json:"createdAt"` } type ListItem struct { ID string `json:"id"` ListID string `json:"listId"` Content string `json:"content"` Category string `json:"category,omitempty"` Quantity string `json:"quantity,omitempty"` IsCompleted bool `json:"isCompleted"` CompletedBy string `json:"completedBy,omitempty"` CompletedByName string `json:"completedByName,omitempty"` SortOrder int `json:"sortOrder"` CreatedAt string `json:"createdAt"` CompletedAt string `json:"completedAt,omitempty"` } type SharedList struct { ID string `json:"id"` SpaceID string `json:"spaceId"` Title string `json:"title"` Icon string `json:"icon"` ListType string `json:"listType"` // shopping | checklist | vacation Items []ListItem `json:"items"` UpdatedAt string `json:"updatedAt"` CreatedAt string `json:"createdAt"` } type APIKey struct { ID string `json:"id"` UserID string `json:"userId"` Name string `json:"name"` KeyPrefix string `json:"keyPrefix"` KeyHash string `json:"-"` RawKey string `json:"rawKey,omitempty"` // Only returned once on creation Scopes string `json:"scopes"` LastUsedAt string `json:"lastUsedAt,omitempty"` CreatedAt string `json:"createdAt"` } type WSMessage struct { Event string `json:"event"` // ITEM_CREATED | ITEM_UPDATED | ITEM_TOGGLED | ITEM_DELETED | LIST_CLEARED | USER_PRESENCE SpaceID string `json:"space_id"` ListID string `json:"list_id,omitempty"` Payload interface{} `json:"payload"` Timestamp string `json:"timestamp"` } type DashboardStats struct { InboxCount int `json:"inboxCount"` TasksOpenCount int `json:"tasksOpenCount"` TasksDoneCount int `json:"tasksDoneCount"` DocsCount int `json:"docsCount"` ListsCount int `json:"listsCount"` DiscardedCount int `json:"discardedCount"` } type FullExport struct { ExportedAt string `json:"exportedAt"` Version string `json:"version"` User User `json:"user"` Thoughts []Thought `json:"thoughts"` Documents []Document `json:"documents"` Spaces []Space `json:"spaces"` Lists []SharedList `json:"lists"` }