feat: plugin discovery, capability/contribution/permission registries, Plugin Manager UI
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
// Package permissions provides a registry for plugin permissions.
|
||||
package permissions
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Entry describes a known permission.
|
||||
type Entry struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Dangerous bool `json:"dangerous"`
|
||||
}
|
||||
|
||||
// Registry tracks known permissions and their safety levels.
|
||||
type Registry struct {
|
||||
mu sync.RWMutex
|
||||
permissions map[string]Entry
|
||||
}
|
||||
|
||||
// NewRegistry creates a new permissions registry.
|
||||
func NewRegistry() *Registry {
|
||||
r := &Registry{
|
||||
permissions: make(map[string]Entry),
|
||||
}
|
||||
r.registerDefaults()
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Registry) registerDefaults() {
|
||||
defaults := []Entry{
|
||||
{Name: "vault.read", Description: "Read vault files and metadata", Dangerous: false},
|
||||
{Name: "vault.write", Description: "Write vault files and metadata", Dangerous: true},
|
||||
{Name: "vault.watch", Description: "Watch vault file changes", Dangerous: false},
|
||||
{Name: "storage.namespace", Description: "Read/write plugin's own storage namespace", Dangerous: false},
|
||||
{Name: "storage.migrations", Description: "Run database migrations in plugin namespace", Dangerous: false},
|
||||
{Name: "events.publish", Description: "Publish events to the event bus", Dangerous: false},
|
||||
{Name: "events.subscribe", Description: "Subscribe to events on the event bus", Dangerous: false},
|
||||
{Name: "ui.register", Description: "Register UI components and contributions", Dangerous: false},
|
||||
{Name: "commands.register", Description: "Register command palette commands", Dangerous: false},
|
||||
{Name: "network.local", Description: "Connect to localhost network services", Dangerous: false},
|
||||
{Name: "network.remote", Description: "Connect to remote network services", Dangerous: true},
|
||||
{Name: "process.spawn", Description: "Spawn external processes", Dangerous: true},
|
||||
{Name: "secrets.read", Description: "Read secrets from the secret store", Dangerous: true},
|
||||
{Name: "secrets.write", Description: "Write secrets to the secret store", Dangerous: true},
|
||||
{Name: "sync.participate", Description: "Participate in vault sync", Dangerous: true},
|
||||
}
|
||||
for _, e := range defaults {
|
||||
r.permissions[e.Name] = e
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns permission info by name.
|
||||
func (r *Registry) Get(name string) (Entry, bool) {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
e, ok := r.permissions[name]
|
||||
return e, ok
|
||||
}
|
||||
|
||||
// IsDangerous checks if a permission is marked dangerous.
|
||||
func (r *Registry) IsDangerous(name string) bool {
|
||||
e, ok := r.Get(name)
|
||||
return ok && e.Dangerous
|
||||
}
|
||||
|
||||
// List returns all known permissions, sorted by name.
|
||||
func (r *Registry) List() []Entry {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
|
||||
entries := make([]Entry, 0, len(r.permissions))
|
||||
for _, e := range r.permissions {
|
||||
entries = append(entries, e)
|
||||
}
|
||||
sort.Slice(entries, func(i, j int) bool {
|
||||
return entries[i].Name < entries[j].Name
|
||||
})
|
||||
return entries
|
||||
}
|
||||
Reference in New Issue
Block a user