102 lines
2.7 KiB
Go
102 lines
2.7 KiB
Go
package main
|
|
|
|
import "time"
|
|
|
|
type SenderMode string
|
|
|
|
const (
|
|
SenderHuman SenderMode = "human"
|
|
SenderTwin SenderMode = "twin"
|
|
)
|
|
|
|
type AutonomyLevel string
|
|
|
|
const (
|
|
AutonomyL0 AutonomyLevel = "L0"
|
|
AutonomyL1 AutonomyLevel = "L1"
|
|
AutonomyL2 AutonomyLevel = "L2"
|
|
)
|
|
|
|
type User struct {
|
|
ID uint `gorm:"primaryKey"`
|
|
InviteCode string `gorm:"uniqueIndex;not null"`
|
|
DisplayName string `gorm:"not null"`
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
// Contact carries per-peer state like the veto flag (tech-design.md §4:
|
|
// twin_disabled_by_peer), independent of any one conversation.
|
|
type Contact struct {
|
|
ID uint `gorm:"primaryKey"`
|
|
OwnerUserID uint `gorm:"not null;index"`
|
|
ContactUserID *uint
|
|
DisplayName string `gorm:"not null"`
|
|
RelationshipNote string
|
|
TwinDisabledByPeer bool `gorm:"not null;default:false"`
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
type Conversation struct {
|
|
ID uint `gorm:"primaryKey"`
|
|
IsGroup bool `gorm:"not null;default:false"`
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
type ConversationParticipant struct {
|
|
ID uint `gorm:"primaryKey"`
|
|
ConversationID uint `gorm:"not null;index"`
|
|
UserID uint `gorm:"not null;index"`
|
|
}
|
|
|
|
type Message struct {
|
|
ID uint `gorm:"primaryKey"`
|
|
ConversationID uint `gorm:"not null;index"`
|
|
SenderID uint `gorm:"not null"`
|
|
SenderMode SenderMode `gorm:"not null;default:human"`
|
|
Text string `gorm:"not null"`
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
type TwinSettings struct {
|
|
ID uint `gorm:"primaryKey"`
|
|
UserID uint `gorm:"uniqueIndex;not null"`
|
|
AutonomyLevel AutonomyLevel `gorm:"not null;default:L0"`
|
|
CreatedAt time.Time
|
|
UpdatedAt time.Time
|
|
}
|
|
|
|
// WhitelistRule is the L2 auto-send whitelist -- a (contact, topic) pair the
|
|
// owner has approved for unattended replies. ContactID nil = any counterpart
|
|
// (PRD.md §3.1).
|
|
type WhitelistRule struct {
|
|
ID uint `gorm:"primaryKey"`
|
|
UserID uint `gorm:"not null;index"`
|
|
ContactID *uint
|
|
TopicKeyword string `gorm:"not null"`
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
// EscalationLog is one row per escalation_filter trigger -- the post-hoc
|
|
// notification + undo trail required by AGENTS.md's absolute safety
|
|
// invariants.
|
|
type EscalationLog struct {
|
|
ID uint `gorm:"primaryKey"`
|
|
UserID uint `gorm:"not null;index"`
|
|
ConversationID uint `gorm:"not null;index"`
|
|
Reason string `gorm:"not null"`
|
|
MessageSnippet string `gorm:"not null"`
|
|
Resolved bool `gorm:"not null;default:false"`
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
var allModels = []interface{}{
|
|
&User{},
|
|
&Contact{},
|
|
&Conversation{},
|
|
&ConversationParticipant{},
|
|
&Message{},
|
|
&TwinSettings{},
|
|
&WhitelistRule{},
|
|
&EscalationLog{},
|
|
}
|