Changeset 0.34.0 (#208)
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit is contained in:
216
server/export/entities.go
Normal file
216
server/export/entities.go
Normal file
@@ -0,0 +1,216 @@
|
||||
package export
|
||||
|
||||
// entities.go — v0.34.0 CS0
|
||||
//
|
||||
// Per-entity sanitization: strips sensitive, instance-specific, or
|
||||
// non-portable fields before writing to the export archive. Each
|
||||
// Sanitize* function returns a clean map ready for JSON marshalling.
|
||||
|
||||
import (
|
||||
"chat-switchboard/models"
|
||||
)
|
||||
|
||||
// ── User ─────────────────────────────────────
|
||||
|
||||
// SanitizeUser strips password_hash (json:"-" already), vault fields,
|
||||
// and external_id. The User struct's json tags already exclude
|
||||
// password_hash, so standard marshalling is safe. We nil out a few
|
||||
// more fields for cross-instance portability.
|
||||
func SanitizeUser(u *models.User) *models.User {
|
||||
out := *u // shallow copy
|
||||
out.PasswordHash = ""
|
||||
out.ExternalID = nil
|
||||
return &out
|
||||
}
|
||||
|
||||
// ── Channel ──────────────────────────────────
|
||||
|
||||
// ExportChannel is a Channel without instance-specific provider binding.
|
||||
type ExportChannel struct {
|
||||
models.Channel
|
||||
ProviderConfigID *string `json:"provider_config_id,omitempty"` // always nil in export
|
||||
}
|
||||
|
||||
// SanitizeChannel strips provider_config_id.
|
||||
func SanitizeChannel(ch *models.Channel) ExportChannel {
|
||||
return ExportChannel{
|
||||
Channel: *ch,
|
||||
ProviderConfigID: nil,
|
||||
}
|
||||
}
|
||||
|
||||
// SanitizeChannels batch-sanitizes a slice.
|
||||
func SanitizeChannels(chs []models.Channel) []ExportChannel {
|
||||
out := make([]ExportChannel, len(chs))
|
||||
for i := range chs {
|
||||
chs[i].ProviderConfigID = nil
|
||||
out[i] = SanitizeChannel(&chs[i])
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ── Message ──────────────────────────────────
|
||||
|
||||
// ExportMessage is a Message without provider_config_id.
|
||||
type ExportMessage struct {
|
||||
models.Message
|
||||
ProviderConfigID *string `json:"provider_config_id,omitempty"` // always nil
|
||||
}
|
||||
|
||||
// SanitizeMessages strips provider_config_id from each message.
|
||||
func SanitizeMessages(msgs []models.Message) []ExportMessage {
|
||||
out := make([]ExportMessage, len(msgs))
|
||||
for i := range msgs {
|
||||
msgs[i].ProviderConfigID = nil
|
||||
out[i] = ExportMessage{Message: msgs[i]}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ── Channel Model ────────────────────────────
|
||||
|
||||
// ExportChannelModel strips provider_config_id and persona_id.
|
||||
type ExportChannelModel struct {
|
||||
ID string `json:"id"`
|
||||
ChannelID string `json:"channel_id"`
|
||||
ModelID string `json:"model_id"`
|
||||
Handle string `json:"handle,omitempty"`
|
||||
DisplayName string `json:"display_name,omitempty"`
|
||||
SystemPrompt string `json:"system_prompt,omitempty"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
}
|
||||
|
||||
// SanitizeChannelModels strips instance-specific refs.
|
||||
func SanitizeChannelModels(cms []models.ChannelModel) []ExportChannelModel {
|
||||
out := make([]ExportChannelModel, len(cms))
|
||||
for i, cm := range cms {
|
||||
out[i] = ExportChannelModel{
|
||||
ID: cm.ID,
|
||||
ChannelID: cm.ChannelID,
|
||||
ModelID: cm.ModelID,
|
||||
Handle: cm.Handle,
|
||||
DisplayName: cm.DisplayName,
|
||||
SystemPrompt: cm.SystemPrompt,
|
||||
IsDefault: cm.IsDefault,
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ── User Model Settings ──────────────────────
|
||||
|
||||
// ExportUserModelSetting strips provider_config_id.
|
||||
type ExportUserModelSetting struct {
|
||||
models.UserModelSetting
|
||||
ProviderConfigID *string `json:"provider_config_id,omitempty"` // always nil
|
||||
}
|
||||
|
||||
// SanitizeUserModelSettings strips instance-specific provider binding.
|
||||
func SanitizeUserModelSettings(ums []models.UserModelSetting) []ExportUserModelSetting {
|
||||
out := make([]ExportUserModelSetting, len(ums))
|
||||
for i := range ums {
|
||||
ums[i].ProviderConfigID = nil
|
||||
out[i] = ExportUserModelSetting{UserModelSetting: ums[i]}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ── Usage Entry ──────────────────────────────
|
||||
|
||||
// ExportUsageEntry strips provider_config_id and routing_decision.
|
||||
type ExportUsageEntry struct {
|
||||
ID string `json:"id"`
|
||||
ChannelID *string `json:"channel_id,omitempty"`
|
||||
UserID string `json:"user_id"`
|
||||
ModelID string `json:"model_id"`
|
||||
Role *string `json:"role,omitempty"`
|
||||
PromptTokens int `json:"prompt_tokens"`
|
||||
CompletionTokens int `json:"completion_tokens"`
|
||||
CacheCreationTokens int `json:"cache_creation_tokens"`
|
||||
CacheReadTokens int `json:"cache_read_tokens"`
|
||||
CostInput *float64 `json:"cost_input,omitempty"`
|
||||
CostOutput *float64 `json:"cost_output,omitempty"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
}
|
||||
|
||||
// SanitizeUsageEntries strips instance-specific fields.
|
||||
func SanitizeUsageEntries(ues []models.UsageEntry) []ExportUsageEntry {
|
||||
out := make([]ExportUsageEntry, len(ues))
|
||||
for i, ue := range ues {
|
||||
out[i] = ExportUsageEntry{
|
||||
ID: ue.ID,
|
||||
ChannelID: ue.ChannelID,
|
||||
UserID: ue.UserID,
|
||||
ModelID: ue.ModelID,
|
||||
Role: ue.Role,
|
||||
PromptTokens: ue.PromptTokens,
|
||||
CompletionTokens: ue.CompletionTokens,
|
||||
CacheCreationTokens: ue.CacheCreationTokens,
|
||||
CacheReadTokens: ue.CacheReadTokens,
|
||||
CostInput: ue.CostInput,
|
||||
CostOutput: ue.CostOutput,
|
||||
CreatedAt: ue.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ── Workspace ────────────────────────────────
|
||||
|
||||
// ExportWorkspace strips root_path (json:"-" already) and git credentials.
|
||||
type ExportWorkspace struct {
|
||||
models.Workspace
|
||||
GitCredentialID *string `json:"git_credential_id,omitempty"` // always nil
|
||||
}
|
||||
|
||||
// SanitizeWorkspaces strips git credential refs.
|
||||
func SanitizeWorkspaces(ws []models.Workspace) []ExportWorkspace {
|
||||
out := make([]ExportWorkspace, len(ws))
|
||||
for i := range ws {
|
||||
ws[i].GitCredentialID = nil
|
||||
ws[i].GitLastSync = nil
|
||||
out[i] = ExportWorkspace{Workspace: ws[i]}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ── Persona ──────────────────────────────────
|
||||
|
||||
// ExportPersona strips provider_config_id.
|
||||
type ExportPersona struct {
|
||||
models.Persona
|
||||
ProviderConfigID *string `json:"provider_config_id,omitempty"` // always nil
|
||||
}
|
||||
|
||||
// SanitizePersonas strips instance-specific provider binding.
|
||||
func SanitizePersonas(ps []models.Persona) []ExportPersona {
|
||||
out := make([]ExportPersona, len(ps))
|
||||
for i := range ps {
|
||||
ps[i].ProviderConfigID = nil
|
||||
out[i] = ExportPersona{Persona: ps[i]}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ── Workflow ─────────────────────────────────
|
||||
|
||||
// SanitizeWorkflows strips webhook secrets.
|
||||
func SanitizeWorkflows(wfs []models.Workflow) []models.Workflow {
|
||||
out := make([]models.Workflow, len(wfs))
|
||||
for i := range wfs {
|
||||
out[i] = wfs[i]
|
||||
out[i].WebhookSecret = ""
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Note links use models.ExportNoteLink (includes source_note_id).
|
||||
// See models/models.go for the type definition.
|
||||
|
||||
// Note, Memory, Folder, NotificationPreference,
|
||||
// ChannelParticipant, ChannelCursor, Project, ProjectChannel,
|
||||
// ProjectKB, ProjectNote, WorkspaceFile, PersonaGroup,
|
||||
// PersonaGroupMember, KnowledgeBase, KBDocument, Group,
|
||||
// GroupMember, ResourceGrant, Team, TeamMember, WorkflowVersion,
|
||||
// WorkflowStage — these are exported as-is (no sensitive fields
|
||||
// after query-level exclusion of embeddings).
|
||||
Reference in New Issue
Block a user