Changeset 0.23.0 (#153)
This commit is contained in:
640
store/interfaces.go
Normal file
640
store/interfaces.go
Normal file
@@ -0,0 +1,640 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
)
|
||||
|
||||
// =========================================
|
||||
// STORES — Data Access Layer
|
||||
// =========================================
|
||||
// Every database operation goes through these interfaces.
|
||||
// Handlers never touch SQL directly. This makes the DB
|
||||
// portable (Postgres today, SQLite/MySQL later) and
|
||||
// handlers testable with in-memory implementations.
|
||||
// =========================================
|
||||
|
||||
// Stores bundles all store interfaces for dependency injection.
|
||||
type Stores struct {
|
||||
Providers ProviderStore
|
||||
Catalog CatalogStore
|
||||
Personas PersonaStore
|
||||
Policies PolicyStore
|
||||
UserSettings UserModelSettingsStore
|
||||
Users UserStore
|
||||
Teams TeamStore
|
||||
Channels ChannelStore
|
||||
Messages MessageStore
|
||||
Audit AuditStore
|
||||
Notes NoteStore
|
||||
NoteLinks NoteLinkStore
|
||||
GlobalConfig GlobalConfigStore
|
||||
Usage UsageStore
|
||||
Pricing PricingStore
|
||||
Extensions ExtensionStore
|
||||
Files FileStore
|
||||
KnowledgeBases KnowledgeBaseStore
|
||||
Groups GroupStore
|
||||
ResourceGrants ResourceGrantStore
|
||||
Memories MemoryStore
|
||||
Projects ProjectStore
|
||||
Notifications NotificationStore
|
||||
NotifPrefs NotificationPreferenceStore
|
||||
Workspaces WorkspaceStore
|
||||
GitCredentials GitCredentialStore
|
||||
CapOverrides CapabilityOverrideStore
|
||||
RoutingPolicies RoutingPolicyStore
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// PROVIDER STORE
|
||||
// =========================================
|
||||
|
||||
type ProviderStore interface {
|
||||
Create(ctx context.Context, cfg *models.ProviderConfig) error
|
||||
GetByID(ctx context.Context, id string) (*models.ProviderConfig, error)
|
||||
Update(ctx context.Context, id string, patch models.ProviderConfigPatch) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
|
||||
// Scoped queries
|
||||
ListGlobal(ctx context.Context) ([]models.ProviderConfig, error)
|
||||
ListForTeam(ctx context.Context, teamID string) ([]models.ProviderConfig, error)
|
||||
ListForUser(ctx context.Context, userID string) ([]models.ProviderConfig, error) // personal scope
|
||||
ListAccessible(ctx context.Context, userID string) ([]models.ProviderConfig, error) // all user can access
|
||||
|
||||
// Access check
|
||||
UserCanAccess(ctx context.Context, userID, configID string) (bool, error)
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// CATALOG STORE
|
||||
// =========================================
|
||||
|
||||
type CatalogStore interface {
|
||||
// Sync from provider API
|
||||
UpsertFromSync(ctx context.Context, providerConfigID string, entries []CatalogSyncEntry) (added, updated int, err error)
|
||||
|
||||
// Queries
|
||||
GetByID(ctx context.Context, id string) (*models.CatalogEntry, error)
|
||||
GetByModelID(ctx context.Context, providerConfigID, modelID string) (*models.CatalogEntry, error)
|
||||
GetByModelIDAny(ctx context.Context, modelID string) (*models.CatalogEntry, error) // any provider, most recently synced
|
||||
ListVisible(ctx context.Context) ([]models.CatalogEntry, error)
|
||||
ListEnabledForProvider(ctx context.Context, providerConfigID string) ([]models.CatalogEntry, error)
|
||||
ListForProvider(ctx context.Context, providerConfigID string) ([]models.CatalogEntry, error)
|
||||
ListAll(ctx context.Context) ([]models.CatalogEntry, error) // everything (internal use)
|
||||
ListAllGlobal(ctx context.Context) ([]models.CatalogEntry, error) // admin view — global-scope providers only
|
||||
|
||||
// Visibility management
|
||||
SetVisibility(ctx context.Context, id string, visibility string) error
|
||||
BulkSetVisibility(ctx context.Context, providerConfigID string, visibility string) error
|
||||
BulkSetVisibilityAll(ctx context.Context, visibility string) error
|
||||
|
||||
// Delete
|
||||
Delete(ctx context.Context, id string) error
|
||||
DeleteForProvider(ctx context.Context, providerConfigID string) error
|
||||
}
|
||||
|
||||
// CatalogSyncEntry is the input format from provider FetchModels.
|
||||
type CatalogSyncEntry struct {
|
||||
ModelID string
|
||||
DisplayName string
|
||||
ModelType string // "chat", "embedding", "image" — from provider API
|
||||
Capabilities models.ModelCapabilities
|
||||
Pricing *models.ModelPricing
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// PERSONA STORE
|
||||
// =========================================
|
||||
|
||||
type PersonaStore interface {
|
||||
Create(ctx context.Context, p *models.Persona) error
|
||||
GetByID(ctx context.Context, id string) (*models.Persona, error)
|
||||
Update(ctx context.Context, id string, patch models.PersonaPatch) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
|
||||
// Scoped queries
|
||||
ListForUser(ctx context.Context, userID string) ([]models.Persona, error) // all visible to user
|
||||
ListForTeam(ctx context.Context, teamID string) ([]models.Persona, error)
|
||||
ListGlobal(ctx context.Context) ([]models.Persona, error)
|
||||
ListPersonal(ctx context.Context, userID string) ([]models.Persona, error) // user's own
|
||||
|
||||
// Grants
|
||||
SetGrants(ctx context.Context, personaID string, grants []models.Grant) error
|
||||
GetGrants(ctx context.Context, personaID string) ([]models.Grant, error)
|
||||
GetToolGrants(ctx context.Context, personaID string) ([]string, error)
|
||||
|
||||
// Access check
|
||||
UserCanAccess(ctx context.Context, userID, personaID string) (bool, error)
|
||||
|
||||
// Knowledge base bindings
|
||||
SetKBs(ctx context.Context, personaID string, kbIDs []string, autoSearch map[string]bool) error
|
||||
GetKBs(ctx context.Context, personaID string) ([]models.PersonaKB, error)
|
||||
GetKBIDs(ctx context.Context, personaID string) ([]string, error)
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// POLICY STORE
|
||||
// =========================================
|
||||
|
||||
type PolicyStore interface {
|
||||
Get(ctx context.Context, key string) (string, error)
|
||||
GetBool(ctx context.Context, key string) (bool, error)
|
||||
Set(ctx context.Context, key, value string, updatedBy string) error
|
||||
GetAll(ctx context.Context) (map[string]string, error)
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// USER MODEL SETTINGS STORE
|
||||
// =========================================
|
||||
|
||||
type UserModelSettingsStore interface {
|
||||
GetForUser(ctx context.Context, userID string) ([]models.UserModelSetting, error)
|
||||
GetHiddenModelIDs(ctx context.Context, userID string) (map[string]bool, error)
|
||||
Set(ctx context.Context, userID, modelID string, providerConfigID *string, patch models.UserModelSettingPatch) error
|
||||
BulkSetHidden(ctx context.Context, userID string, entries []models.HiddenEntry, hidden bool) error
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// USER STORE
|
||||
// =========================================
|
||||
|
||||
type UserStore interface {
|
||||
Create(ctx context.Context, u *models.User) error
|
||||
GetByID(ctx context.Context, id string) (*models.User, error)
|
||||
GetByUsername(ctx context.Context, username string) (*models.User, error)
|
||||
GetByEmail(ctx context.Context, email string) (*models.User, error)
|
||||
GetByLogin(ctx context.Context, login string) (*models.User, error) // username or email
|
||||
Update(ctx context.Context, id string, fields map[string]interface{}) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
List(ctx context.Context, opts ListOptions) ([]models.User, int, error)
|
||||
UpdateLastLogin(ctx context.Context, id string) error
|
||||
SetActive(ctx context.Context, id string, active bool) error
|
||||
|
||||
// Refresh tokens
|
||||
CreateRefreshToken(ctx context.Context, userID, tokenHash string, expiresAt time.Time) error
|
||||
GetRefreshToken(ctx context.Context, tokenHash string) (userID string, err error)
|
||||
RevokeRefreshToken(ctx context.Context, tokenHash string) error
|
||||
RevokeAllRefreshTokens(ctx context.Context, userID string) error
|
||||
CleanExpiredTokens(ctx context.Context) error
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// TEAM STORE
|
||||
// =========================================
|
||||
|
||||
type TeamStore interface {
|
||||
Create(ctx context.Context, t *models.Team) error
|
||||
GetByID(ctx context.Context, id string) (*models.Team, error)
|
||||
Update(ctx context.Context, id string, fields map[string]interface{}) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
List(ctx context.Context) ([]models.Team, error)
|
||||
|
||||
// Members
|
||||
AddMember(ctx context.Context, teamID, userID, role string) error
|
||||
RemoveMember(ctx context.Context, teamID, userID string) error
|
||||
UpdateMemberRole(ctx context.Context, teamID, userID, role string) error
|
||||
ListMembers(ctx context.Context, teamID string) ([]models.TeamMember, error)
|
||||
GetMember(ctx context.Context, teamID, userID string) (*models.TeamMember, error)
|
||||
GetUserTeamIDs(ctx context.Context, userID string) ([]string, error)
|
||||
IsTeamAdmin(ctx context.Context, teamID, userID string) (bool, error)
|
||||
IsMember(ctx context.Context, teamID, userID string) (bool, error)
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// CHANNEL STORE
|
||||
// =========================================
|
||||
|
||||
type ChannelStore interface {
|
||||
Create(ctx context.Context, ch *models.Channel) error
|
||||
GetByID(ctx context.Context, id string) (*models.Channel, error)
|
||||
Update(ctx context.Context, id string, fields map[string]interface{}) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
ListForUser(ctx context.Context, userID string, opts ListOptions) ([]models.Channel, int, error)
|
||||
Search(ctx context.Context, userID, query string, opts ListOptions) ([]models.Channel, int, error)
|
||||
|
||||
// Cursor management (conversation forking)
|
||||
GetCursor(ctx context.Context, channelID, userID string) (*models.ChannelCursor, error)
|
||||
SetCursor(ctx context.Context, channelID, userID, leafID string) error
|
||||
|
||||
// Channel models
|
||||
SetModel(ctx context.Context, cm *models.ChannelModel) error
|
||||
GetModels(ctx context.Context, channelID string) ([]models.ChannelModel, error)
|
||||
GetModelByID(ctx context.Context, id string) (*models.ChannelModel, error)
|
||||
UpdateModel(ctx context.Context, id string, fields map[string]interface{}) error
|
||||
DeleteModel(ctx context.Context, id string) error
|
||||
|
||||
// Ownership check
|
||||
UserOwns(ctx context.Context, channelID, userID string) (bool, error)
|
||||
|
||||
// Workspace resolution: channel workspace_id > project workspace_id
|
||||
ResolveWorkspaceID(ctx context.Context, channelID string) (string, error)
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// MESSAGE STORE
|
||||
// =========================================
|
||||
|
||||
type MessageStore interface {
|
||||
Create(ctx context.Context, m *models.Message) error
|
||||
GetByID(ctx context.Context, id string) (*models.Message, error)
|
||||
Update(ctx context.Context, id string, fields map[string]interface{}) error
|
||||
Delete(ctx context.Context, id string) error // soft delete
|
||||
ListForChannel(ctx context.Context, channelID string, opts ListOptions) ([]models.Message, error)
|
||||
|
||||
// Tree operations
|
||||
GetChildren(ctx context.Context, parentID string) ([]models.Message, error)
|
||||
GetSiblings(ctx context.Context, messageID string) ([]models.Message, error)
|
||||
GetPathToRoot(ctx context.Context, messageID string) ([]models.Message, error)
|
||||
GetNextSiblingIndex(ctx context.Context, parentID string) (int, error)
|
||||
|
||||
// Count
|
||||
CountForChannel(ctx context.Context, channelID string) (int, error)
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// AUDIT STORE
|
||||
// =========================================
|
||||
|
||||
type AuditStore interface {
|
||||
Log(ctx context.Context, entry *models.AuditEntry) error
|
||||
List(ctx context.Context, opts AuditListOptions) ([]models.AuditEntry, int, error)
|
||||
}
|
||||
|
||||
type AuditListOptions struct {
|
||||
ListOptions
|
||||
ActorID string
|
||||
Action string
|
||||
ResourceType string
|
||||
ResourceID string
|
||||
Since *time.Time
|
||||
Until *time.Time
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// NOTE STORE
|
||||
// =========================================
|
||||
|
||||
type NoteStore interface {
|
||||
Create(ctx context.Context, n *models.Note) error
|
||||
GetByID(ctx context.Context, id string) (*models.Note, error)
|
||||
Update(ctx context.Context, id string, fields map[string]interface{}) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
ListForUser(ctx context.Context, userID string, opts NoteListOptions) ([]models.Note, int, error)
|
||||
Search(ctx context.Context, userID, query string, opts ListOptions) ([]models.Note, int, error)
|
||||
SearchTitles(ctx context.Context, userID, query string, limit int) ([]models.Note, error)
|
||||
BulkDelete(ctx context.Context, ids []string, userID string) (int, error)
|
||||
}
|
||||
|
||||
type NoteListOptions struct {
|
||||
ListOptions
|
||||
FolderPath string
|
||||
Tag string
|
||||
TeamID string
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// NOTE LINK STORE
|
||||
// =========================================
|
||||
|
||||
// NoteLinkStore manages wikilink edges between notes.
|
||||
type NoteLinkStore interface {
|
||||
// ReplaceLinks deletes existing links for sourceNoteID and inserts new ones.
|
||||
ReplaceLinks(ctx context.Context, sourceNoteID string, links []models.NoteLink) error
|
||||
|
||||
// ResolveByTitle sets target_note_id on dangling links matching the title for a user.
|
||||
ResolveByTitle(ctx context.Context, userID, targetNoteID, title string) error
|
||||
|
||||
// Backlinks returns notes that link to the given note.
|
||||
Backlinks(ctx context.Context, noteID string) ([]models.NoteLinkResult, error)
|
||||
|
||||
// Graph returns all nodes and edges for a user's note graph.
|
||||
Graph(ctx context.Context, userID string) (*models.NoteGraph, error)
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// GLOBAL CONFIG STORE
|
||||
// =========================================
|
||||
|
||||
type GlobalConfigStore interface {
|
||||
Get(ctx context.Context, key string) (models.JSONMap, error)
|
||||
Set(ctx context.Context, key string, value models.JSONMap, updatedBy string) error
|
||||
GetAll(ctx context.Context) (map[string]models.JSONMap, error)
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// USAGE STORE
|
||||
// =========================================
|
||||
|
||||
type UsageStore interface {
|
||||
Log(ctx context.Context, entry *models.UsageEntry) error
|
||||
CountRecentByRole(ctx context.Context, userID, role string, since time.Time) (int, error)
|
||||
QueryByUser(ctx context.Context, userID string, opts UsageQueryOptions) ([]models.UsageAggregate, error)
|
||||
QueryByUserPersonal(ctx context.Context, userID string, opts UsageQueryOptions) ([]models.UsageAggregate, error)
|
||||
QueryByTeam(ctx context.Context, teamID string, opts UsageQueryOptions) ([]models.UsageAggregate, error)
|
||||
QueryByTeamProviders(ctx context.Context, teamID string, opts UsageQueryOptions) ([]models.UsageAggregate, error)
|
||||
QueryByModel(ctx context.Context, opts UsageQueryOptions) ([]models.UsageAggregate, error)
|
||||
GetTotals(ctx context.Context, opts UsageQueryOptions) (*models.UsageTotals, error)
|
||||
GetTeamProviderTotals(ctx context.Context, teamID string, opts UsageQueryOptions) (*models.UsageTotals, error)
|
||||
GetPersonalTotals(ctx context.Context, userID string, opts UsageQueryOptions) (*models.UsageTotals, error)
|
||||
}
|
||||
|
||||
type UsageQueryOptions struct {
|
||||
Since *time.Time
|
||||
Until *time.Time
|
||||
GroupBy string // "day", "model", "user", "provider"
|
||||
ExcludeBYOK bool // true for admin views — filters provider_scope != 'personal'
|
||||
Limit int
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// PRICING STORE
|
||||
// =========================================
|
||||
|
||||
type PricingStore interface {
|
||||
GetForModel(ctx context.Context, providerConfigID, modelID string) (*models.PricingEntry, error)
|
||||
Upsert(ctx context.Context, entry *models.PricingEntry) error
|
||||
UpsertFromCatalog(ctx context.Context, providerConfigID, modelID string, pricing *models.ModelPricing) error
|
||||
List(ctx context.Context) ([]models.PricingEntry, error)
|
||||
Delete(ctx context.Context, providerConfigID, modelID string) error
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// EXTENSION STORE
|
||||
// =========================================
|
||||
|
||||
type ExtensionStore interface {
|
||||
// Admin CRUD
|
||||
Create(ctx context.Context, ext *models.Extension) error
|
||||
GetByID(ctx context.Context, id string) (*models.Extension, error)
|
||||
GetByExtID(ctx context.Context, extID string) (*models.Extension, error)
|
||||
Update(ctx context.Context, id string, ext *models.Extension) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
|
||||
// Listing
|
||||
ListAll(ctx context.Context) ([]models.Extension, error)
|
||||
ListEnabled(ctx context.Context) ([]models.Extension, error)
|
||||
ListForUser(ctx context.Context, userID string) ([]models.UserExtension, error)
|
||||
|
||||
// User settings
|
||||
GetUserSettings(ctx context.Context, extID, userID string) (*models.ExtensionUserSettings, error)
|
||||
SetUserSettings(ctx context.Context, s *models.ExtensionUserSettings) error
|
||||
DeleteUserSettings(ctx context.Context, extID, userID string) error
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// FILE STORE
|
||||
// =========================================
|
||||
|
||||
type FileStore interface {
|
||||
Create(ctx context.Context, f *models.File) error
|
||||
GetByID(ctx context.Context, id string) (*models.File, error)
|
||||
GetByChannel(ctx context.Context, channelID string, origin string) ([]models.File, error)
|
||||
GetByMessage(ctx context.Context, messageID string) ([]models.File, error)
|
||||
GetByProject(ctx context.Context, projectID string) ([]models.File, error)
|
||||
GetByUser(ctx context.Context, userID string, page, perPage int) ([]models.File, int, error) // paginated, returns total
|
||||
SetMessageID(ctx context.Context, fileID, messageID string) error
|
||||
UpdateMetadata(ctx context.Context, id string, metadata map[string]interface{}) error
|
||||
SetExtractedText(ctx context.Context, id string, text string) error
|
||||
Delete(ctx context.Context, id string) (*models.File, error) // returns deleted row for storage cleanup
|
||||
DeleteByChannel(ctx context.Context, channelID string) ([]string, error) // returns storage_keys
|
||||
UserUsageBytes(ctx context.Context, userID string) (int64, error)
|
||||
ListOrphans(ctx context.Context, olderThan time.Duration) ([]models.File, error)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// =========================================
|
||||
// KNOWLEDGE BASE STORE
|
||||
// =========================================
|
||||
|
||||
type KnowledgeBaseStore interface {
|
||||
// KB CRUD
|
||||
Create(ctx context.Context, kb *models.KnowledgeBase) error
|
||||
GetByID(ctx context.Context, id string) (*models.KnowledgeBase, error)
|
||||
Update(ctx context.Context, id string, fields map[string]interface{}) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
|
||||
// Scoped listing
|
||||
ListForUser(ctx context.Context, userID string, teamIDs []string) ([]models.KnowledgeBase, error)
|
||||
ListGlobal(ctx context.Context) ([]models.KnowledgeBase, error)
|
||||
ListForTeam(ctx context.Context, teamID string) ([]models.KnowledgeBase, error)
|
||||
ListPersonal(ctx context.Context, userID string) ([]models.KnowledgeBase, error)
|
||||
|
||||
// Documents
|
||||
CreateDocument(ctx context.Context, doc *models.KBDocument) error
|
||||
GetDocument(ctx context.Context, id string) (*models.KBDocument, error)
|
||||
ListDocuments(ctx context.Context, kbID string) ([]models.KBDocument, error)
|
||||
UpdateDocumentStatus(ctx context.Context, id string, status string, errMsg *string) error
|
||||
UpdateDocumentText(ctx context.Context, id string, text string, chunkCount int) error
|
||||
UpdateDocumentStorageKey(ctx context.Context, id string, storageKey string) error
|
||||
DeleteDocument(ctx context.Context, id string) (*models.KBDocument, error) // returns for storage cleanup
|
||||
|
||||
// Chunks
|
||||
InsertChunks(ctx context.Context, chunks []models.KBChunk) error
|
||||
DeleteChunksForDocument(ctx context.Context, documentID string) error
|
||||
SimilaritySearch(ctx context.Context, kbIDs []string, queryVec []float64,
|
||||
threshold float64, limit int) ([]models.KBSearchResult, error)
|
||||
|
||||
// Channel links
|
||||
SetChannelKBs(ctx context.Context, channelID string, kbIDs []string) error
|
||||
GetChannelKBs(ctx context.Context, channelID string) ([]models.ChannelKB, error)
|
||||
GetActiveKBIDs(ctx context.Context, channelID string, userID string,
|
||||
teamIDs []string) ([]string, error) // enabled + user has access
|
||||
GetActiveKBIDsWithPersona(ctx context.Context, channelID string, userID string,
|
||||
teamIDs []string, personaID string) ([]string, error) // includes persona-bound KBs
|
||||
ListDiscoverable(ctx context.Context, userID string, teamIDs []string) ([]models.KnowledgeBase, error)
|
||||
|
||||
// Stats — recount document_count/chunk_count/total_bytes from child tables
|
||||
UpdateStats(ctx context.Context, kbID string) error
|
||||
|
||||
// Discoverable management
|
||||
SetDiscoverable(ctx context.Context, kbID string, discoverable bool) error
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// GROUP STORE (v0.16.0)
|
||||
// =========================================
|
||||
|
||||
type GroupStore interface {
|
||||
Create(ctx context.Context, g *models.Group) error
|
||||
GetByID(ctx context.Context, id string) (*models.Group, error)
|
||||
Update(ctx context.Context, id string, name, description *string) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
|
||||
// Scoped listing
|
||||
ListAll(ctx context.Context) ([]models.Group, error) // admin
|
||||
ListForTeam(ctx context.Context, teamID string) ([]models.Group, error) // team admin
|
||||
ListForUser(ctx context.Context, userID string) ([]models.Group, error) // groups I belong to
|
||||
|
||||
// Members
|
||||
AddMember(ctx context.Context, groupID, userID, addedBy string) error
|
||||
RemoveMember(ctx context.Context, groupID, userID string) error
|
||||
ListMembers(ctx context.Context, groupID string) ([]models.GroupMember, error)
|
||||
IsMember(ctx context.Context, groupID, userID string) (bool, error)
|
||||
|
||||
// For access resolution: returns group IDs a user belongs to
|
||||
GetUserGroupIDs(ctx context.Context, userID string) ([]string, error)
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// RESOURCE GRANT STORE (v0.16.0)
|
||||
// =========================================
|
||||
|
||||
type ResourceGrantStore interface {
|
||||
Set(ctx context.Context, grant *models.ResourceGrant) error
|
||||
Get(ctx context.Context, resourceType, resourceID string) (*models.ResourceGrant, error)
|
||||
Delete(ctx context.Context, resourceType, resourceID string) error
|
||||
|
||||
// Access check: does userID have group-based access to this resource?
|
||||
UserHasGroupAccess(ctx context.Context, userID, resourceType, resourceID string) (bool, error)
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// NOTIFICATION STORE (v0.20.0)
|
||||
// =========================================
|
||||
|
||||
type NotificationStore interface {
|
||||
Create(ctx context.Context, n *models.Notification) error
|
||||
ListByUser(ctx context.Context, userID string, limit, offset int, unreadOnly bool) ([]models.Notification, int, error)
|
||||
MarkRead(ctx context.Context, id, userID string) error
|
||||
MarkAllRead(ctx context.Context, userID string) error
|
||||
Delete(ctx context.Context, id, userID string) error
|
||||
UnreadCount(ctx context.Context, userID string) (int, error)
|
||||
DeleteOlderThan(ctx context.Context, before time.Time) (int64, error)
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// NOTIFICATION PREFERENCES STORE (v0.20.0)
|
||||
// =========================================
|
||||
|
||||
type NotificationPreferenceStore interface {
|
||||
// Get returns the preference for a specific user + type. Returns nil if not set.
|
||||
Get(ctx context.Context, userID, notifType string) (*models.NotificationPreference, error)
|
||||
// ListForUser returns all preferences set by a user.
|
||||
ListForUser(ctx context.Context, userID string) ([]models.NotificationPreference, error)
|
||||
// Upsert creates or updates a preference row.
|
||||
Upsert(ctx context.Context, pref *models.NotificationPreference) error
|
||||
// Delete removes a preference (falls back to default).
|
||||
Delete(ctx context.Context, userID, notifType string) error
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// WORKSPACE STORE (v0.21.0)
|
||||
// =========================================
|
||||
|
||||
type WorkspaceStore interface {
|
||||
// CRUD
|
||||
Create(ctx context.Context, w *models.Workspace) error
|
||||
GetByID(ctx context.Context, id string) (*models.Workspace, error)
|
||||
Update(ctx context.Context, id string, patch models.WorkspacePatch) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
|
||||
// Ownership lookup
|
||||
GetByOwner(ctx context.Context, ownerType, ownerID string) (*models.Workspace, error)
|
||||
ListByOwner(ctx context.Context, ownerType, ownerID string) ([]models.Workspace, error)
|
||||
|
||||
// File index
|
||||
UpsertFile(ctx context.Context, f *models.WorkspaceFile) error
|
||||
DeleteFile(ctx context.Context, workspaceID, path string) error
|
||||
DeleteFilesByPrefix(ctx context.Context, workspaceID, prefix string) error
|
||||
GetFile(ctx context.Context, workspaceID, path string) (*models.WorkspaceFile, error)
|
||||
ListFiles(ctx context.Context, workspaceID, prefix string, recursive bool) ([]models.WorkspaceFile, error)
|
||||
DeleteAllFiles(ctx context.Context, workspaceID string) error
|
||||
|
||||
// Stats
|
||||
GetStats(ctx context.Context, workspaceID string) (*models.WorkspaceStats, error)
|
||||
|
||||
// Chunks (v0.21.2 — workspace indexing)
|
||||
InsertChunks(ctx context.Context, chunks []models.WorkspaceChunk) error
|
||||
DeleteChunksByFile(ctx context.Context, fileID string) error
|
||||
SimilaritySearch(ctx context.Context, workspaceID string, queryVec []float64, threshold float64, limit int) ([]models.WorkspaceChunkResult, error)
|
||||
UpdateFileIndexStatus(ctx context.Context, fileID, status string, chunkCount int) error
|
||||
|
||||
// Git (v0.21.4)
|
||||
SetGitLastSync(ctx context.Context, workspaceID string, t time.Time) error
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// GIT CREDENTIAL STORE (v0.21.4)
|
||||
// =========================================
|
||||
|
||||
type GitCredentialStore interface {
|
||||
Create(ctx context.Context, cred *models.GitCredential) error
|
||||
GetByID(ctx context.Context, id string) (*models.GitCredential, error)
|
||||
ListByUser(ctx context.Context, userID string) ([]models.GitCredential, error)
|
||||
Delete(ctx context.Context, id, userID string) error
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// CAPABILITY OVERRIDES (v0.22.0)
|
||||
// =========================================
|
||||
|
||||
type CapabilityOverrideStore interface {
|
||||
// Set creates or updates an override for (provider, model, field).
|
||||
Set(ctx context.Context, o *models.CapabilityOverride) error
|
||||
|
||||
// Delete removes a specific override.
|
||||
Delete(ctx context.Context, id string) error
|
||||
|
||||
// ListForModel returns all overrides for a model ID (across all providers + global).
|
||||
ListForModel(ctx context.Context, modelID string) ([]models.CapabilityOverride, error)
|
||||
|
||||
// ListForProviderModel returns overrides for a specific provider+model combination.
|
||||
ListForProviderModel(ctx context.Context, providerConfigID, modelID string) ([]models.CapabilityOverride, error)
|
||||
|
||||
// ListAll returns every override (admin view).
|
||||
ListAll(ctx context.Context) ([]models.CapabilityOverride, error)
|
||||
|
||||
// DeleteForProvider removes all overrides for a provider (cascade cleanup).
|
||||
DeleteForProvider(ctx context.Context, providerConfigID string) error
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// ROUTING POLICY STORE (v0.22.2)
|
||||
// =========================================
|
||||
|
||||
type RoutingPolicyStore interface {
|
||||
// Create adds a new routing policy.
|
||||
Create(ctx context.Context, p *models.RoutingPolicy) error
|
||||
|
||||
// Update modifies an existing routing policy.
|
||||
Update(ctx context.Context, p *models.RoutingPolicy) error
|
||||
|
||||
// Delete removes a routing policy by ID.
|
||||
Delete(ctx context.Context, id string) error
|
||||
|
||||
// GetByID returns a single policy.
|
||||
GetByID(ctx context.Context, id string) (*models.RoutingPolicy, error)
|
||||
|
||||
// ListActive returns all active policies, ordered by priority ASC.
|
||||
ListActive(ctx context.Context) ([]models.RoutingPolicy, error)
|
||||
|
||||
// ListAll returns all policies (including inactive), for admin listing.
|
||||
ListAll(ctx context.Context) ([]models.RoutingPolicy, error)
|
||||
|
||||
// ListForTeam returns active policies applicable to a team (team-scoped + global).
|
||||
ListForTeam(ctx context.Context, teamID string) ([]models.RoutingPolicy, error)
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// SHARED TYPES
|
||||
// =========================================
|
||||
|
||||
// ListOptions provides standard pagination/sort for list queries.
|
||||
type ListOptions struct {
|
||||
Limit int
|
||||
Offset int
|
||||
Sort string // column name
|
||||
Order string // "asc" or "desc"
|
||||
}
|
||||
|
||||
// DefaultListOptions returns sensible defaults.
|
||||
func DefaultListOptions() ListOptions {
|
||||
return ListOptions{
|
||||
Limit: 50,
|
||||
Order: "desc",
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user