Documentation
¶
Index ¶
- Constants
- Variables
- func HasDangerousPermissions(permissions []string) bool
- func IsValidEventType(eventType string) bool
- func ValidatePermission(name string) bool
- func ValidatePermissions(names []string) (invalid []string)
- type BackendConfig
- type CreateRegistryRequest
- type DatabaseConfig
- type EnablePluginRequest
- type Event
- func NewContactEvent(eventType string, tenantID uuid.UUID, contactData interface{}) Event
- func NewGenericEvent(eventType string, tenantID uuid.UUID, data interface{}) Event
- func NewInvoiceEvent(eventType string, tenantID uuid.UUID, invoiceData interface{}) Event
- func NewPaymentEvent(eventType string, tenantID uuid.UUID, paymentData interface{}) Event
- type FrontendConfig
- type GORMRepository
- func (r *GORMRepository) CountEnabledTenantsForPlugin(ctx context.Context, pluginID uuid.UUID) (int, error)
- func (r *GORMRepository) CreatePlugin(ctx context.Context, p *Plugin) error
- func (r *GORMRepository) CreateRegistry(ctx context.Context, name, url, description string) (*Registry, error)
- func (r *GORMRepository) CreateTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID, settings json.RawMessage) error
- func (r *GORMRepository) DeletePlugin(ctx context.Context, id uuid.UUID) (int64, error)
- func (r *GORMRepository) DeleteRegistry(ctx context.Context, id uuid.UUID) (int64, error)
- func (r *GORMRepository) DeleteTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID) error
- func (r *GORMRepository) DisableAllTenantsForPlugin(ctx context.Context, pluginID uuid.UUID) error
- func (r *GORMRepository) DisableTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID) (int64, error)
- func (r *GORMRepository) EnableTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID, settings json.RawMessage) error
- func (r *GORMRepository) GetPlugin(ctx context.Context, id uuid.UUID) (*Plugin, error)
- func (r *GORMRepository) GetPluginByName(ctx context.Context, name string) (*Plugin, error)
- func (r *GORMRepository) GetRegistry(ctx context.Context, id uuid.UUID) (*Registry, error)
- func (r *GORMRepository) GetTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID) (*TenantPlugin, error)
- func (r *GORMRepository) GetTenantPluginSettings(ctx context.Context, tenantID, pluginID uuid.UUID) (json.RawMessage, error)
- func (r *GORMRepository) GetTenantPluginsWithAll(ctx context.Context, tenantID uuid.UUID) ([]TenantPlugin, error)
- func (r *GORMRepository) InsertPluginReturning(ctx context.Context, manifest *Manifest, repoURL string, ...) (*Plugin, error)
- func (r *GORMRepository) IsPluginEnabledForTenant(ctx context.Context, tenantID, pluginID uuid.UUID) (bool, error)
- func (r *GORMRepository) ListEnabledPlugins(ctx context.Context) ([]Plugin, error)
- func (r *GORMRepository) ListPlugins(ctx context.Context) ([]Plugin, error)
- func (r *GORMRepository) ListRegistries(ctx context.Context) ([]Registry, error)
- func (r *GORMRepository) ListTenantPlugins(ctx context.Context, tenantID uuid.UUID) ([]TenantPlugin, error)
- func (r *GORMRepository) UpdatePlugin(ctx context.Context, p *Plugin) error
- func (r *GORMRepository) UpdatePluginState(ctx context.Context, pluginID uuid.UUID, state PluginState, ...) error
- func (r *GORMRepository) UpdateRegistryLastSynced(ctx context.Context, id uuid.UUID) error
- func (r *GORMRepository) UpdateTenantPluginSettings(ctx context.Context, tenantID, pluginID uuid.UUID, settings json.RawMessage) error
- type HookConfig
- type HookHandler
- type HookRegistry
- func (r *HookRegistry) Emit(ctx context.Context, event Event) error
- func (r *HookRegistry) EmitAsync(event Event)
- func (r *HookRegistry) GetEventTypes() []string
- func (r *HookRegistry) GetHandlerCount(eventType string) int
- func (r *HookRegistry) HasHandlers(eventType string) bool
- func (r *HookRegistry) Register(eventType string, handler HookHandler)
- type InstallPluginRequest
- type LoadedPlugin
- type Manifest
- func (m *Manifest) GetBackendPath(pluginDir string) string
- func (m *Manifest) GetFrontendPath(pluginDir string) string
- func (m *Manifest) GetMigrationPath(pluginDir string) string
- func (m *Manifest) RequiredPermissions() []string
- func (m *Manifest) ToJSON() (json.RawMessage, error)
- func (m *Manifest) Validate() error
- type NavigationItem
- type Permission
- type PermissionCategory
- type PermissionRisk
- type PermissionSummary
- type Plugin
- type PluginInfo
- type PluginMigration
- type PluginRuntimeStatus
- type PluginSearchResult
- type PluginState
- type Registry
- type RegistryIndex
- type Repository
- type RepositoryType
- type RouteConfig
- type RuntimeHealthState
- type RuntimeLifecycleState
- type RuntimeRouteResponse
- type Service
- func (s *Service) AddRegistry(ctx context.Context, req CreateRegistryRequest) (*Registry, error)
- func (s *Service) DisableForTenant(ctx context.Context, tenantID, pluginID uuid.UUID) error
- func (s *Service) DisablePlugin(ctx context.Context, id uuid.UUID) error
- func (s *Service) EnableForTenant(ctx context.Context, tenantID, pluginID uuid.UUID, settings json.RawMessage) error
- func (s *Service) EnablePlugin(ctx context.Context, id uuid.UUID, permissions []string) error
- func (s *Service) FetchRegistryIndex(ctx context.Context, registryURL string) (*RegistryIndex, error)
- func (s *Service) GetHookRegistry() *HookRegistry
- func (s *Service) GetLoadedPlugin(name string) (*LoadedPlugin, bool)
- func (s *Service) GetPlugin(ctx context.Context, id uuid.UUID) (*Plugin, error)
- func (s *Service) GetPluginByName(ctx context.Context, name string) (*Plugin, error)
- func (s *Service) GetPluginRuntimeStatus(ctx context.Context, pluginID uuid.UUID) (*PluginRuntimeStatus, error)
- func (s *Service) GetRegistry(ctx context.Context, id uuid.UUID) (*Registry, error)
- func (s *Service) GetTenantPluginSettings(ctx context.Context, tenantID, pluginID uuid.UUID) (json.RawMessage, error)
- func (s *Service) GetTenantPlugins(ctx context.Context, tenantID uuid.UUID) ([]TenantPlugin, error)
- func (s *Service) InstallPlugin(ctx context.Context, repoURL string) (*Plugin, error)
- func (s *Service) InvokeTenantPluginRoute(ctx context.Context, tenantID uuid.UUID, pluginID uuid.UUID, method string, ...) (*RuntimeRouteResponse, error)
- func (s *Service) IsPluginEnabledForTenant(ctx context.Context, tenantID, pluginID uuid.UUID) (bool, error)
- func (s *Service) ListPlugins(ctx context.Context) ([]Plugin, error)
- func (s *Service) ListRegistries(ctx context.Context) ([]Registry, error)
- func (s *Service) LoadEnabledPlugins(ctx context.Context) error
- func (s *Service) RemoveRegistry(ctx context.Context, id uuid.UUID) error
- func (s *Service) RestartPluginRuntime(ctx context.Context, pluginID uuid.UUID) (*PluginRuntimeStatus, error)
- func (s *Service) SearchPlugins(ctx context.Context, query string) ([]PluginSearchResult, error)
- func (s *Service) SyncRegistry(ctx context.Context, registryID uuid.UUID) error
- func (s *Service) UninstallPlugin(ctx context.Context, id uuid.UUID) error
- func (s *Service) UpdateRegistryLastSynced(ctx context.Context, id uuid.UUID) error
- func (s *Service) UpdateTenantPluginSettings(ctx context.Context, tenantID, pluginID uuid.UUID, settings json.RawMessage) error
- type SettingProperty
- type SettingsSchema
- type SlotConfig
- type TenantPlugin
- type TenantPluginSettingsRequest
Constants ¶
const ( // Invoice events EventInvoiceCreated = "invoice.created" EventInvoiceSent = "invoice.sent" EventInvoicePaid = "invoice.paid" EventInvoiceVoided = "invoice.voided" // Payment events EventPaymentReceived = "payment.received" EventPaymentAllocated = "payment.allocated" // Contact events EventContactCreated = "contact.created" EventContactUpdated = "contact.updated" EventContactDeleted = "contact.deleted" // Journal entry events EventJournalEntryCreated = "journal_entry.created" EventJournalEntryPosted = "journal_entry.posted" EventJournalEntryVoided = "journal_entry.voided" // Expense events EventExpenseCreated = "expense.created" EventExpenseSubmitted = "expense.submitted" EventExpenseApproved = "expense.approved" EventExpenseRejected = "expense.rejected" EventExpensePosted = "expense.posted" // Recurring invoice events EventRecurringCreated = "recurring.created" EventRecurringGenerated = "recurring.generated" EventRecurringStopped = "recurring.stopped" // Banking events EventBankTransactionImported = "bank_transaction.imported" EventBankTransactionMatched = "bank_transaction.matched" EventReconciliationCompleted = "reconciliation.completed" // Payroll events EventPayrollCalculated = "payroll.calculated" EventPayrollApproved = "payroll.approved" EventEmployeeCreated = "employee.created" // Tenant events EventTenantCreated = "tenant.created" EventTenantUpdated = "tenant.updated" // Email events EventEmailSent = "email.sent" EventEmailFailed = "email.failed" // Webhook events EventWebhookTest = "webhook.test" )
Event types for the hook system
const (
BackendRuntimeHTTP = "http"
)
const BackendRuntimePackage = "package"
const ( // DemoInstallFixtureRepositoryURL is an exact demo-mode fixture URL used by // local and CI E2E tests to exercise plugin installation without network IO. DemoInstallFixtureRepositoryURL = "https://github.com/HMB-research/open-accounting-demo-admin-plugin" )
Variables ¶
var ( ErrPluginRuntimeUnsupported = errors.New("plugin backend runtime is unsupported") ErrPluginRouteNotFound = errors.New("plugin route is not registered") ErrPluginNotEnabled = errors.New("plugin is not enabled") )
var AllEventTypes = []string{ EventInvoiceCreated, EventInvoiceSent, EventInvoicePaid, EventInvoiceVoided, EventPaymentReceived, EventPaymentAllocated, EventContactCreated, EventContactUpdated, EventContactDeleted, EventJournalEntryCreated, EventJournalEntryPosted, EventJournalEntryVoided, EventExpenseCreated, EventExpenseSubmitted, EventExpenseApproved, EventExpenseRejected, EventExpensePosted, EventRecurringCreated, EventRecurringGenerated, EventRecurringStopped, EventBankTransactionImported, EventBankTransactionMatched, EventReconciliationCompleted, EventPayrollCalculated, EventPayrollApproved, EventEmployeeCreated, EventTenantCreated, EventTenantUpdated, EventEmailSent, EventEmailFailed, EventWebhookTest, }
AllEventTypes returns all available event types
var AllPermissions = map[string]Permission{ "contacts:read": { Name: "contacts:read", Category: CategoryDataAccess, Risk: RiskLow, Description: "Read contact information", }, "contacts:write": { Name: "contacts:write", Category: CategoryDataAccess, Risk: RiskLow, Description: "Create and modify contacts", }, "invoices:read": { Name: "invoices:read", Category: CategoryDataAccess, Risk: RiskLow, Description: "Read invoices", }, "invoices:write": { Name: "invoices:write", Category: CategoryDataAccess, Risk: RiskMedium, Description: "Create and modify invoices", }, "payments:read": { Name: "payments:read", Category: CategoryDataAccess, Risk: RiskLow, Description: "Read payment records", }, "payments:write": { Name: "payments:write", Category: CategoryDataAccess, Risk: RiskMedium, Description: "Record payments", }, "accounts:read": { Name: "accounts:read", Category: CategoryDataAccess, Risk: RiskLow, Description: "Read chart of accounts", }, "accounts:write": { Name: "accounts:write", Category: CategoryDataAccess, Risk: RiskMedium, Description: "Modify chart of accounts", }, "employees:read": { Name: "employees:read", Category: CategoryDataAccess, Risk: RiskLow, Description: "Read employee information", }, "employees:write": { Name: "employees:write", Category: CategoryDataAccess, Risk: RiskMedium, Description: "Manage employees", }, "payroll:read": { Name: "payroll:read", Category: CategoryDataAccess, Risk: RiskMedium, Description: "Read payroll data", }, "payroll:write": { Name: "payroll:write", Category: CategoryDataAccess, Risk: RiskHigh, Description: "Manage payroll", }, "banking:read": { Name: "banking:read", Category: CategoryDataAccess, Risk: RiskMedium, Description: "Read bank account data", }, "banking:write": { Name: "banking:write", Category: CategoryDataAccess, Risk: RiskHigh, Description: "Manage bank transactions", }, "email:send": { Name: "email:send", Category: CategorySystem, Risk: RiskMedium, Description: "Send emails on behalf of tenant", }, "storage:read": { Name: "storage:read", Category: CategorySystem, Risk: RiskLow, Description: "Read stored files", }, "storage:write": { Name: "storage:write", Category: CategorySystem, Risk: RiskMedium, Description: "Upload and store files", }, "pdf:generate": { Name: "pdf:generate", Category: CategorySystem, Risk: RiskLow, Description: "Generate PDF documents", }, "settings:read": { Name: "settings:read", Category: CategorySystem, Risk: RiskLow, Description: "Read tenant settings", }, "settings:write": { Name: "settings:write", Category: CategorySystem, Risk: RiskMedium, Description: "Modify tenant settings", }, "database:migrate": { Name: "database:migrate", Category: CategoryDatabase, Risk: RiskHigh, Description: "Run database migrations in tenant schema", }, "database:query": { Name: "database:query", Category: CategoryDatabase, Risk: RiskHigh, Description: "Execute SQL queries in tenant schema", }, "hooks:register": { Name: "hooks:register", Category: CategoryDangerous, Risk: RiskCritical, Description: "Listen to system events", }, "routes:register": { Name: "routes:register", Category: CategoryDangerous, Risk: RiskCritical, Description: "Add custom API endpoints", }, "admin:access": { Name: "admin:access", Category: CategoryDangerous, Risk: RiskCritical, Description: "Access admin functions", }, }
AllPermissions is the registry of all available permissions
ErrPluginRuntimeUnavailable is returned when a plugin hook is invoked without a backend runtime capable of executing plugin code.
Functions ¶
func HasDangerousPermissions ¶
HasDangerousPermissions checks if any permissions are in the dangerous category
func IsValidEventType ¶
IsValidEventType checks if an event type is valid
func ValidatePermission ¶
ValidatePermission checks if a permission name is valid
func ValidatePermissions ¶
ValidatePermissions checks if all permission names are valid
Types ¶
type BackendConfig ¶
type BackendConfig struct {
Package string `yaml:"package" json:"package"`
Entry string `yaml:"entry" json:"entry"`
Runtime string `yaml:"runtime,omitempty" json:"runtime,omitempty"`
BaseURL string `yaml:"base_url,omitempty" json:"base_url,omitempty"`
Executable string `yaml:"executable,omitempty" json:"executable,omitempty"`
Hooks []HookConfig `yaml:"hooks,omitempty" json:"hooks,omitempty"`
Routes []RouteConfig `yaml:"routes,omitempty" json:"routes,omitempty"`
}
BackendConfig represents the backend section of the manifest
type CreateRegistryRequest ¶
type CreateRegistryRequest struct {
Name string `json:"name" validate:"required,min=1,max=255"`
URL string `json:"url" validate:"required,url"`
Description string `json:"description,omitempty"`
}
CreateRegistryRequest represents a request to add a new registry
type DatabaseConfig ¶
type DatabaseConfig struct {
Migrations string `yaml:"migrations" json:"migrations"`
}
DatabaseConfig represents the database section of the manifest
type EnablePluginRequest ¶
type EnablePluginRequest struct {
GrantedPermissions []string `json:"granted_permissions"`
}
EnablePluginRequest represents a request to enable a plugin with permissions
type Event ¶
type Event struct {
Type string `json:"type"`
TenantID uuid.UUID `json:"tenant_id"`
Data json.RawMessage `json:"data"`
Time time.Time `json:"time"`
}
Event represents an event emitted by the system
func NewContactEvent ¶
NewContactEvent creates a contact-related event
func NewGenericEvent ¶
NewGenericEvent creates a generic event
func NewInvoiceEvent ¶
NewInvoiceEvent creates an invoice-related event
type FrontendConfig ¶
type FrontendConfig struct {
Components string `yaml:"components" json:"components"`
Slots []SlotConfig `yaml:"slots,omitempty" json:"slots,omitempty"`
}
FrontendConfig represents the frontend section of the manifest
type GORMRepository ¶
type GORMRepository struct {
// contains filtered or unexported fields
}
GORMRepository implements Repository using GORM
func NewGORMRepository ¶
func NewGORMRepository(db *gorm.DB) *GORMRepository
NewGORMRepository creates a new GORM plugin repository
func (*GORMRepository) CountEnabledTenantsForPlugin ¶
func (r *GORMRepository) CountEnabledTenantsForPlugin(ctx context.Context, pluginID uuid.UUID) (int, error)
CountEnabledTenantsForPlugin counts tenants that have the plugin enabled
func (*GORMRepository) CreatePlugin ¶
func (r *GORMRepository) CreatePlugin(ctx context.Context, p *Plugin) error
CreatePlugin creates a new plugin
func (*GORMRepository) CreateRegistry ¶
func (r *GORMRepository) CreateRegistry(ctx context.Context, name, url, description string) (*Registry, error)
CreateRegistry creates a new registry
func (*GORMRepository) CreateTenantPlugin ¶
func (r *GORMRepository) CreateTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID, settings json.RawMessage) error
CreateTenantPlugin enables a plugin for a tenant
func (*GORMRepository) DeletePlugin ¶
DeletePlugin deletes a plugin
func (*GORMRepository) DeleteRegistry ¶
DeleteRegistry deletes a non-official registry
func (*GORMRepository) DeleteTenantPlugin ¶
func (r *GORMRepository) DeleteTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID) error
DeleteTenantPlugin removes a plugin from a tenant
func (*GORMRepository) DisableAllTenantsForPlugin ¶
DisableAllTenantsForPlugin disables the plugin for all tenants
func (*GORMRepository) DisableTenantPlugin ¶
func (r *GORMRepository) DisableTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID) (int64, error)
DisableTenantPlugin disables a plugin for a tenant
func (*GORMRepository) EnableTenantPlugin ¶
func (r *GORMRepository) EnableTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID, settings json.RawMessage) error
EnableTenantPlugin enables a plugin for a tenant (upsert)
func (*GORMRepository) GetPluginByName ¶
GetPluginByName returns a plugin by name
func (*GORMRepository) GetRegistry ¶
GetRegistry returns a registry by ID
func (*GORMRepository) GetTenantPlugin ¶
func (r *GORMRepository) GetTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID) (*TenantPlugin, error)
GetTenantPlugin returns a tenant plugin
func (*GORMRepository) GetTenantPluginSettings ¶
func (r *GORMRepository) GetTenantPluginSettings(ctx context.Context, tenantID, pluginID uuid.UUID) (json.RawMessage, error)
GetTenantPluginSettings returns the settings for a tenant plugin
func (*GORMRepository) GetTenantPluginsWithAll ¶
func (r *GORMRepository) GetTenantPluginsWithAll(ctx context.Context, tenantID uuid.UUID) ([]TenantPlugin, error)
GetTenantPluginsWithAll returns all plugins available to a tenant (enabled or not)
func (*GORMRepository) InsertPluginReturning ¶
func (r *GORMRepository) InsertPluginReturning(ctx context.Context, manifest *Manifest, repoURL string, repoType RepositoryType, manifestJSON []byte) (*Plugin, error)
InsertPluginReturning inserts a plugin and returns the created record
func (*GORMRepository) IsPluginEnabledForTenant ¶
func (r *GORMRepository) IsPluginEnabledForTenant(ctx context.Context, tenantID, pluginID uuid.UUID) (bool, error)
IsPluginEnabledForTenant checks if a plugin is enabled for a tenant
func (*GORMRepository) ListEnabledPlugins ¶
func (r *GORMRepository) ListEnabledPlugins(ctx context.Context) ([]Plugin, error)
ListEnabledPlugins returns all enabled plugins
func (*GORMRepository) ListPlugins ¶
func (r *GORMRepository) ListPlugins(ctx context.Context) ([]Plugin, error)
ListPlugins returns all plugins
func (*GORMRepository) ListRegistries ¶
func (r *GORMRepository) ListRegistries(ctx context.Context) ([]Registry, error)
ListRegistries returns all plugin registries
func (*GORMRepository) ListTenantPlugins ¶
func (r *GORMRepository) ListTenantPlugins(ctx context.Context, tenantID uuid.UUID) ([]TenantPlugin, error)
ListTenantPlugins returns all plugins enabled for a tenant
func (*GORMRepository) UpdatePlugin ¶
func (r *GORMRepository) UpdatePlugin(ctx context.Context, p *Plugin) error
UpdatePlugin updates a plugin
func (*GORMRepository) UpdatePluginState ¶
func (r *GORMRepository) UpdatePluginState(ctx context.Context, pluginID uuid.UUID, state PluginState, permissions []string) error
UpdatePluginState updates a plugin's state and permissions
func (*GORMRepository) UpdateRegistryLastSynced ¶
UpdateRegistryLastSynced updates the last synced timestamp
func (*GORMRepository) UpdateTenantPluginSettings ¶
func (r *GORMRepository) UpdateTenantPluginSettings(ctx context.Context, tenantID, pluginID uuid.UUID, settings json.RawMessage) error
UpdateTenantPluginSettings updates tenant plugin settings
type HookConfig ¶
type HookConfig struct {
Event string `yaml:"event" json:"event"`
Handler string `yaml:"handler" json:"handler"`
}
HookConfig represents an event hook subscription
type HookHandler ¶
HookHandler is a function that handles an event
type HookRegistry ¶
type HookRegistry struct {
// contains filtered or unexported fields
}
HookRegistry manages event subscriptions
func NewHookRegistry ¶
func NewHookRegistry() *HookRegistry
NewHookRegistry creates a new hook registry
func (*HookRegistry) Emit ¶
func (r *HookRegistry) Emit(ctx context.Context, event Event) error
Emit fires an event to all registered handlers
func (*HookRegistry) EmitAsync ¶
func (r *HookRegistry) EmitAsync(event Event)
EmitAsync fires an event asynchronously (fire-and-forget)
func (*HookRegistry) GetEventTypes ¶
func (r *HookRegistry) GetEventTypes() []string
GetEventTypes returns all registered event types
func (*HookRegistry) GetHandlerCount ¶
func (r *HookRegistry) GetHandlerCount(eventType string) int
GetHandlerCount returns the number of handlers for an event type
func (*HookRegistry) HasHandlers ¶
func (r *HookRegistry) HasHandlers(eventType string) bool
HasHandlers checks if there are any handlers for an event type
func (*HookRegistry) Register ¶
func (r *HookRegistry) Register(eventType string, handler HookHandler)
Register registers a handler for an event type
type InstallPluginRequest ¶
type InstallPluginRequest struct {
RepositoryURL string `json:"repository_url" validate:"required,url"`
}
InstallPluginRequest represents a request to install a plugin
type LoadedPlugin ¶
LoadedPlugin represents a plugin loaded into memory
type Manifest ¶
type Manifest struct {
// Plugin Metadata
Name string `yaml:"name" json:"name"`
DisplayName string `yaml:"display_name" json:"display_name"`
Version string `yaml:"version" json:"version"`
Description string `yaml:"description,omitempty" json:"description,omitempty"`
Author string `yaml:"author,omitempty" json:"author,omitempty"`
License string `yaml:"license,omitempty" json:"license,omitempty"`
Homepage string `yaml:"homepage,omitempty" json:"homepage,omitempty"`
MinAppVersion string `yaml:"min_app_version,omitempty" json:"min_app_version,omitempty"`
// Permissions
Permissions []string `yaml:"permissions,omitempty" json:"permissions,omitempty"`
// Backend Configuration
Backend *BackendConfig `yaml:"backend,omitempty" json:"backend,omitempty"`
// Frontend Configuration
Frontend *FrontendConfig `yaml:"frontend,omitempty" json:"frontend,omitempty"`
// Database Configuration
Database *DatabaseConfig `yaml:"database,omitempty" json:"database,omitempty"`
// Dependencies
Dependencies []string `yaml:"dependencies,omitempty" json:"dependencies,omitempty"`
// Settings Schema (JSON Schema)
Settings *SettingsSchema `yaml:"settings,omitempty" json:"settings,omitempty"`
}
Manifest represents the plugin.yaml configuration file
func LoadManifest ¶
LoadManifest loads a plugin manifest from a file path
func ParseManifest ¶
ParseManifest parses manifest data from bytes
func (*Manifest) GetBackendPath ¶
GetBackendPath returns the full path to the backend package directory
func (*Manifest) GetFrontendPath ¶
GetFrontendPath returns the full path to the frontend components directory
func (*Manifest) GetMigrationPath ¶
GetMigrationPath returns the full path to the migrations directory
func (*Manifest) RequiredPermissions ¶
RequiredPermissions returns a list of permissions that would be required based on the manifest configuration
type NavigationItem ¶
type NavigationItem struct {
}
NavigationItem represents a navigation menu item
type Permission ¶
type Permission struct {
Name string `json:"name"`
Category PermissionCategory `json:"category"`
Risk PermissionRisk `json:"risk"`
Description string `json:"description"`
}
Permission defines a plugin permission
func GetPermission ¶
func GetPermission(name string) (Permission, bool)
GetPermission returns a permission by name
func GetPermissionsByCategory ¶
func GetPermissionsByCategory(category PermissionCategory) []Permission
GetPermissionsByCategory returns all permissions in a category
func GetPermissionsByRisk ¶
func GetPermissionsByRisk(minRisk PermissionRisk) []Permission
GetPermissionsByRisk returns all permissions at or above a risk level
type PermissionCategory ¶
type PermissionCategory string
PermissionCategory represents a category of permissions
const ( CategoryDataAccess PermissionCategory = "data" CategorySystem PermissionCategory = "system" CategoryDatabase PermissionCategory = "database" CategoryDangerous PermissionCategory = "dangerous" )
type PermissionRisk ¶
type PermissionRisk string
PermissionRisk represents the risk level of a permission
const ( RiskLow PermissionRisk = "low" RiskMedium PermissionRisk = "medium" RiskHigh PermissionRisk = "high" RiskCritical PermissionRisk = "critical" )
func GetHighestRiskLevel ¶
func GetHighestRiskLevel(permissions []string) PermissionRisk
GetHighestRiskLevel returns the highest risk level among the given permissions
type PermissionSummary ¶
type PermissionSummary struct {
Total int `json:"total"`
ByCategory map[string]int `json:"by_category"`
ByRisk map[string]int `json:"by_risk"`
HighestRisk PermissionRisk `json:"highest_risk"`
HasDangerous bool `json:"has_dangerous"`
InvalidCount int `json:"invalid_count"`
InvalidNames []string `json:"invalid_names,omitempty"`
}
PermissionSummary provides a summary of requested permissions
func SummarizePermissions ¶
func SummarizePermissions(permissions []string) PermissionSummary
SummarizePermissions provides a summary of the given permissions
type Plugin ¶
type Plugin struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
DisplayName string `json:"display_name"`
Description string `json:"description,omitempty"`
Version string `json:"version"`
RepositoryURL string `json:"repository_url"`
RepositoryType RepositoryType `json:"repository_type"`
Author string `json:"author,omitempty"`
License string `json:"license,omitempty"`
HomepageURL string `json:"homepage_url,omitempty"`
State PluginState `json:"state"`
GrantedPermissions []string `json:"granted_permissions"`
Manifest json.RawMessage `json:"manifest"`
InstalledAt time.Time `json:"installed_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Plugin represents an installed plugin
type PluginInfo ¶
type PluginInfo struct {
Name string `yaml:"name" json:"name"`
DisplayName string `yaml:"display_name" json:"display_name"`
Description string `yaml:"description,omitempty" json:"description,omitempty"`
Repository string `yaml:"repository" json:"repository"`
Version string `yaml:"version" json:"version"`
Author string `yaml:"author,omitempty" json:"author,omitempty"`
License string `yaml:"license,omitempty" json:"license,omitempty"`
Tags []string `yaml:"tags,omitempty" json:"tags,omitempty"`
Downloads int `yaml:"downloads,omitempty" json:"downloads,omitempty"`
Stars int `yaml:"stars,omitempty" json:"stars,omitempty"`
}
PluginInfo represents plugin information from a registry
type PluginMigration ¶
type PluginMigration struct {
ID uuid.UUID `json:"id"`
PluginID uuid.UUID `json:"plugin_id"`
Version string `json:"version"`
Filename string `json:"filename"`
AppliedAt time.Time `json:"applied_at"`
Checksum string `json:"checksum,omitempty"`
}
PluginMigration tracks applied migrations for a plugin
type PluginRuntimeStatus ¶
type PluginRuntimeStatus struct {
PluginID uuid.UUID `json:"plugin_id"`
PluginName string `json:"plugin_name"`
DisplayName string `json:"display_name,omitempty"`
Runtime string `json:"runtime"`
State RuntimeLifecycleState `json:"state"`
Health RuntimeHealthState `json:"health"`
Message string `json:"message,omitempty"`
BaseURL string `json:"base_url,omitempty"`
PID *int `json:"pid,omitempty"`
StartedAt *time.Time `json:"started_at,omitempty"`
ReadyAt *time.Time `json:"ready_at,omitempty"`
ExitedAt *time.Time `json:"exited_at,omitempty"`
LastHealthCheckAt *time.Time `json:"last_health_check_at,omitempty"`
BackoffUntil *time.Time `json:"backoff_until,omitempty"`
ExitCode *int `json:"exit_code,omitempty"`
RestartCount int `json:"restart_count"`
CrashCount int `json:"crash_count"`
HookCount int `json:"hook_count"`
RouteCount int `json:"route_count"`
LastExitError string `json:"last_exit_error,omitempty"`
LastHealthError string `json:"last_health_error,omitempty"`
LastError string `json:"last_error,omitempty"`
LastOutput string `json:"last_output,omitempty"`
}
PluginRuntimeStatus is the operator-facing status snapshot for a plugin backend runtime.
type PluginSearchResult ¶
type PluginSearchResult struct {
Plugin PluginInfo `json:"plugin"`
Registry string `json:"registry"`
}
PluginSearchResult represents search results from registries
type PluginState ¶
type PluginState string
PluginState represents the lifecycle state of a plugin
const ( StateInstalled PluginState = "installed" StateEnabled PluginState = "enabled" StateDisabled PluginState = "disabled" StateFailed PluginState = "failed" )
type Registry ¶
type Registry struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
URL string `json:"url"`
Description string `json:"description,omitempty"`
IsOfficial bool `json:"is_official"`
IsActive bool `json:"is_active"`
LastSyncedAt *time.Time `json:"last_synced_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Registry represents a plugin marketplace source
type RegistryIndex ¶
type RegistryIndex struct {
Version int `yaml:"version" json:"version"`
Plugins []PluginInfo `yaml:"plugins" json:"plugins"`
}
RegistryIndex represents the structure of a registry's plugins.yaml
type Repository ¶
type Repository interface {
// Registry operations
ListRegistries(ctx context.Context) ([]Registry, error)
GetRegistry(ctx context.Context, id uuid.UUID) (*Registry, error)
CreateRegistry(ctx context.Context, name, url, description string) (*Registry, error)
DeleteRegistry(ctx context.Context, id uuid.UUID) (int64, error)
UpdateRegistryLastSynced(ctx context.Context, id uuid.UUID) error
// Plugin operations
ListPlugins(ctx context.Context) ([]Plugin, error)
GetPlugin(ctx context.Context, id uuid.UUID) (*Plugin, error)
GetPluginByName(ctx context.Context, name string) (*Plugin, error)
CreatePlugin(ctx context.Context, p *Plugin) error
UpdatePlugin(ctx context.Context, p *Plugin) error
DeletePlugin(ctx context.Context, id uuid.UUID) (int64, error)
// Tenant plugin operations
ListTenantPlugins(ctx context.Context, tenantID uuid.UUID) ([]TenantPlugin, error)
GetTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID) (*TenantPlugin, error)
CreateTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID, settings json.RawMessage) error
EnableTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID, settings json.RawMessage) error
DisableTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID) (int64, error)
GetTenantPluginSettings(ctx context.Context, tenantID, pluginID uuid.UUID) (json.RawMessage, error)
UpdateTenantPluginSettings(ctx context.Context, tenantID, pluginID uuid.UUID, settings json.RawMessage) error
DeleteTenantPlugin(ctx context.Context, tenantID, pluginID uuid.UUID) error
IsPluginEnabledForTenant(ctx context.Context, tenantID, pluginID uuid.UUID) (bool, error)
// Enabled plugins query
ListEnabledPlugins(ctx context.Context) ([]Plugin, error)
// Additional operations for service refactoring
InsertPluginReturning(ctx context.Context, manifest *Manifest, repoURL string, repoType RepositoryType, manifestJSON []byte) (*Plugin, error)
CountEnabledTenantsForPlugin(ctx context.Context, pluginID uuid.UUID) (int, error)
UpdatePluginState(ctx context.Context, pluginID uuid.UUID, state PluginState, permissions []string) error
DisableAllTenantsForPlugin(ctx context.Context, pluginID uuid.UUID) error
GetTenantPluginsWithAll(ctx context.Context, tenantID uuid.UUID) ([]TenantPlugin, error)
}
Repository defines the interface for plugin data access
type RepositoryType ¶
type RepositoryType string
RepositoryType represents the source control type
const ( RepoGitHub RepositoryType = "github" RepoGitLab RepositoryType = "gitlab" )
type RouteConfig ¶
type RouteConfig struct {
Method string `yaml:"method" json:"method"`
Path string `yaml:"path" json:"path"`
Handler string `yaml:"handler" json:"handler"`
}
RouteConfig represents an API route to register
type RuntimeHealthState ¶
type RuntimeHealthState string
RuntimeHealthState describes the latest known runtime health signal.
const ( RuntimeHealthNotApplicable RuntimeHealthState = "not_applicable" RuntimeHealthUnknown RuntimeHealthState = "unknown" RuntimeHealthHealthy RuntimeHealthState = "healthy" RuntimeHealthUnhealthy RuntimeHealthState = "unhealthy" )
type RuntimeLifecycleState ¶
type RuntimeLifecycleState string
RuntimeLifecycleState describes the operator-visible lifecycle of a plugin backend runtime.
const ( RuntimeStateNotConfigured RuntimeLifecycleState = "not_configured" RuntimeStateExternal RuntimeLifecycleState = "external" RuntimeStateNotLoaded RuntimeLifecycleState = "not_loaded" RuntimeStateStarting RuntimeLifecycleState = "starting" RuntimeStateRunning RuntimeLifecycleState = "running" RuntimeStateStopped RuntimeLifecycleState = "stopped" RuntimeStateExited RuntimeLifecycleState = "exited" RuntimeStateBackoff RuntimeLifecycleState = "backoff" RuntimeStateFailed RuntimeLifecycleState = "failed" )
type RuntimeRouteResponse ¶
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service handles plugin lifecycle management
func NewService ¶
NewService creates a new plugin service with an ORM-backed repository.
func NewServiceWithRepository ¶
func NewServiceWithRepository(repo Repository, hooks *HookRegistry, pluginDir string) *Service
NewServiceWithRepository creates a new plugin service with a custom repository (for testing)
func (*Service) AddRegistry ¶
AddRegistry adds a new plugin registry
func (*Service) DisableForTenant ¶
DisableForTenant disables a plugin for a specific tenant
func (*Service) DisablePlugin ¶
DisablePlugin disables a plugin
func (*Service) EnableForTenant ¶
func (s *Service) EnableForTenant(ctx context.Context, tenantID, pluginID uuid.UUID, settings json.RawMessage) error
EnableForTenant enables a plugin for a specific tenant
func (*Service) EnablePlugin ¶
EnablePlugin enables a plugin with granted permissions
func (*Service) FetchRegistryIndex ¶
func (s *Service) FetchRegistryIndex(ctx context.Context, registryURL string) (*RegistryIndex, error)
FetchRegistryIndex fetches the plugins.yaml index from a registry
func (*Service) GetHookRegistry ¶
func (s *Service) GetHookRegistry() *HookRegistry
GetHookRegistry returns the hook registry for registering hooks
func (*Service) GetLoadedPlugin ¶
func (s *Service) GetLoadedPlugin(name string) (*LoadedPlugin, bool)
GetLoadedPlugin returns a loaded plugin by name
func (*Service) GetPluginByName ¶
GetPluginByName returns a plugin by name
func (*Service) GetPluginRuntimeStatus ¶
func (s *Service) GetPluginRuntimeStatus(ctx context.Context, pluginID uuid.UUID) (*PluginRuntimeStatus, error)
GetPluginRuntimeStatus returns the operator-visible backend runtime status for an installed plugin.
func (*Service) GetRegistry ¶
GetRegistry returns a registry by ID
func (*Service) GetTenantPluginSettings ¶
func (s *Service) GetTenantPluginSettings(ctx context.Context, tenantID, pluginID uuid.UUID) (json.RawMessage, error)
GetTenantPluginSettings returns the settings for a plugin for a tenant
func (*Service) GetTenantPlugins ¶
GetTenantPlugins returns all plugins available to a tenant
func (*Service) InstallPlugin ¶
InstallPlugin installs a plugin from a repository URL
func (*Service) InvokeTenantPluginRoute ¶
func (*Service) IsPluginEnabledForTenant ¶
func (s *Service) IsPluginEnabledForTenant(ctx context.Context, tenantID, pluginID uuid.UUID) (bool, error)
IsPluginEnabledForTenant checks if a plugin is enabled for a tenant
func (*Service) ListPlugins ¶
ListPlugins returns all installed plugins
func (*Service) ListRegistries ¶
ListRegistries returns all plugin registries
func (*Service) LoadEnabledPlugins ¶
LoadEnabledPlugins loads all enabled plugins into memory on startup
func (*Service) RemoveRegistry ¶
RemoveRegistry removes a plugin registry
func (*Service) RestartPluginRuntime ¶
func (s *Service) RestartPluginRuntime(ctx context.Context, pluginID uuid.UUID) (*PluginRuntimeStatus, error)
RestartPluginRuntime manually restarts a supervised package runtime.
func (*Service) SearchPlugins ¶
SearchPlugins searches for plugins across all active registries
func (*Service) SyncRegistry ¶
SyncRegistry fetches and caches the plugin list from a registry
func (*Service) UninstallPlugin ¶
UninstallPlugin removes a plugin
func (*Service) UpdateRegistryLastSynced ¶
UpdateRegistryLastSynced updates the last synced timestamp
func (*Service) UpdateTenantPluginSettings ¶
func (s *Service) UpdateTenantPluginSettings(ctx context.Context, tenantID, pluginID uuid.UUID, settings json.RawMessage) error
UpdateTenantPluginSettings updates the settings for a plugin for a tenant
type SettingProperty ¶
type SettingProperty struct {
Type string `yaml:"type" json:"type"`
Default interface{} `yaml:"default,omitempty" json:"default,omitempty"`
Description string `yaml:"description,omitempty" json:"description,omitempty"`
Minimum *float64 `yaml:"minimum,omitempty" json:"minimum,omitempty"`
Maximum *float64 `yaml:"maximum,omitempty" json:"maximum,omitempty"`
MinLength *int `yaml:"minLength,omitempty" json:"minLength,omitempty"`
MaxLength *int `yaml:"maxLength,omitempty" json:"maxLength,omitempty"`
Enum []string `yaml:"enum,omitempty" json:"enum,omitempty"`
}
SettingProperty represents a single setting property
type SettingsSchema ¶
type SettingsSchema struct {
Type string `yaml:"type" json:"type"`
Properties map[string]SettingProperty `yaml:"properties,omitempty" json:"properties,omitempty"`
Required []string `yaml:"required,omitempty" json:"required,omitempty"`
}
SettingsSchema represents a JSON Schema for plugin settings
type SlotConfig ¶
type SlotConfig struct {
Name string `yaml:"name" json:"name"`
Component string `yaml:"component" json:"component"`
Label string `yaml:"label,omitempty" json:"label,omitempty"`
Description string `yaml:"description,omitempty" json:"description,omitempty"`
Path string `yaml:"path,omitempty" json:"path,omitempty"`
Kind string `yaml:"kind,omitempty" json:"kind,omitempty"`
Badge string `yaml:"badge,omitempty" json:"badge,omitempty"`
Order *int `yaml:"order,omitempty" json:"order,omitempty"`
}
SlotConfig represents a UI slot injection
type TenantPlugin ¶
type TenantPlugin struct {
ID uuid.UUID `json:"id"`
TenantID uuid.UUID `json:"tenant_id"`
PluginID uuid.UUID `json:"plugin_id"`
IsEnabled bool `json:"is_enabled"`
Settings json.RawMessage `json:"settings,omitempty"`
EnabledAt *time.Time `json:"enabled_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// Joined fields
Plugin *Plugin `json:"plugin,omitempty"`
}
TenantPlugin represents a plugin enabled for a specific tenant
type TenantPluginSettingsRequest ¶
type TenantPluginSettingsRequest struct {
Settings json.RawMessage `json:"settings"`
}
TenantPluginSettingsRequest represents a request to update tenant plugin settings