This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/server/export/entities.go
Jeffrey Smith 11fd8c1e57 step 1: rename module chat-switchboard → switchboard-core
- go.mod module name
- All 714 import references across 289 Go files
- VERSION: 0.1.0
- CI DB names: switchboard_core_{ci,dev,test}
- Docker image: gobha/switchboard-core
- Test fixtures: JWT issuer, repo names
- .env.example, docker-compose container name
- Compiles clean (go build exit 0)
2026-03-25 19:48:04 -04:00

217 lines
7.3 KiB
Go

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 (
"switchboard-core/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).